MagFlux: - api 1.2.0.42

This commit is contained in:
Thomas Wiedebusch 2024-08-20 13:17:23 +02:00
parent f4b4765ea4
commit 499248c6ce
9 changed files with 916 additions and 0 deletions

View File

@ -152,6 +152,7 @@ EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "MjkControlledCodeRef", "MjkControlledCodeRef", "{B4F8545B-F379-42A5-BDE9-763FD7B79598}"
ProjectSection(SolutionItems) = preProject
MagFluxApi\magflux_api.dll = MagFluxApi\magflux_api.dll
MagFluxApi\shared_code.dll = MagFluxApi\shared_code.dll
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MagFluxToolBox", "Ui\MagFluxToolBox\MagFluxToolBox.csproj", "{A5E7CE52-3101-4E9B-B896-C2C0FADE4812}"
@ -232,6 +233,16 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Common.UI.WPFConnector", "U
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Common.UI.WPF", "Ui\Common.UI.WPF\Common.UI.WPF.csproj", "{F7316525-FF8E-4651-BA67-3C9B948D1E91}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "API_Docu", "API_Docu", "{9158A215-69E2-4D4C-B1DA-DDED9C3460AB}"
ProjectSection(SolutionItems) = preProject
MagFluxApi\api_doc\CalibrationPoint.cs = MagFluxApi\api_doc\CalibrationPoint.cs
MagFluxApi\api_doc\CalibrationPoints.cs = MagFluxApi\api_doc\CalibrationPoints.cs
MagFluxApi\api_doc\IMagFlux.cs = MagFluxApi\api_doc\IMagFlux.cs
MagFluxApi\api_doc\IMagFluxAPI.cs = MagFluxApi\api_doc\IMagFluxAPI.cs
MagFluxApi\api_doc\IMagFluxRequestProtocol.cs = MagFluxApi\api_doc\IMagFluxRequestProtocol.cs
MagFluxApi\api_doc\SensorInfo.cs = MagFluxApi\api_doc\SensorInfo.cs
EndProjectSection
EndProject
Global
GlobalSection(SharedMSBuildProjectFiles) = preSolution
Utils\DateTimeServerShared\DateTimeServerShared.projitems*{4806d89a-fbfb-41bc-aaa7-2242444bf55a}*SharedItemsImports = 4
@ -5682,6 +5693,7 @@ Global
{05F0CCAF-9F2B-45F9-A7F8-12F29AD182F3} = {7A0EE7B8-6B7E-41E9-B679-319C8CA48CF1}
{37E4BF89-44AE-4133-BE0B-8355F791A79D} = {03D4F23E-7E4A-4091-BC96-036C996D351A}
{F7316525-FF8E-4651-BA67-3C9B948D1E91} = {03D4F23E-7E4A-4091-BC96-036C996D351A}
{9158A215-69E2-4D4C-B1DA-DDED9C3460AB} = {B4F8545B-F379-42A5-BDE9-763FD7B79598}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {4BCB7B69-696C-436A-86F7-C91EA5588164}

View File

@ -0,0 +1,136 @@
// Ignore Spelling: lps
using System;
using XYLEM.Base;
namespace XYLEM
{
/// <summary>
/// A single calibration point
/// </summary>
[Serializable]
public class CalibrationPoint : IComparable<CalibrationPoint>, IEquatable<CalibrationPoint>
{
/// <summary>
/// Reference flow in liter / second
/// https://xyleminc.atlassian.net/wiki/spaces/MJKMF/pages/6661802342
/// </summary>
public Single ReferenceFlowRate_lps { get; set; }
/// <summary>
/// DUT Reported flow in liter / second
/// https://xyleminc.atlassian.net/wiki/spaces/MJKMF/pages/6661802342
/// </summary>
public Single ReportedFlowRate_lps { get; set; }
public CalibrationPoint()
{
ReferenceFlowRate_lps = ReportedFlowRate_lps = 0;
}
/// <summary>
/// Ctor
/// </summary>
/// <param name="referenceFlowRate_lps">reference flow rate [l/s] given by the flow-test-bench</param>
/// <param name="reportedFlowRate_lps">reported flow rate [l/s] by the DUT</param>
public CalibrationPoint(Single referenceFlowRate_lps, Single reportedFlowRate_lps)
{
ReferenceFlowRate_lps = referenceFlowRate_lps;
ReportedFlowRate_lps = reportedFlowRate_lps;
}
public override string ToString()
{
const int w1 = 11;
return $"Ref={ReferenceFlowRate_lps*3.6,w1:F6} m3/h DUT={ReportedFlowRate_lps*3.6,w1:F6} m3/h " +
$"(Ref={ReferenceFlowRate_lps,w1:F6} l/s DUT={ReportedFlowRate_lps,w1:F6} l/s)";
}
public int CompareTo(CalibrationPoint other)
{
// If null, it can't be the same
if (System.Object.ReferenceEquals(other, null))
{
return -1;
}
// Any of them is not okay
if ((this.ReferenceFlowRate_lps!= other.ReferenceFlowRate_lps) || (this.ReportedFlowRate_lps!= other.ReportedFlowRate_lps))
{
return -1; // Not the same
}
return 0; // is the same
}
public bool Equals(CalibrationPoint other)
{
return this.CompareTo(other) == 0;
}
public override bool Equals(object obj)
{
if (!(obj is CalibrationPoint)) return false;
CalibrationPoint p = (CalibrationPoint)obj;
return this == p;
}
public override int GetHashCode()
{
return HashTools.ShiftAndWrap(ReferenceFlowRate_lps.GetHashCode(), 2) ^ ReportedFlowRate_lps.GetHashCode();
}
#region Operator == > < ! ..
public static bool operator ==(CalibrationPoint a, CalibrationPoint b)
{
// If both are null, or both are same instance, return true.
if (System.Object.ReferenceEquals(a, b))
{
return true;
}
// If one is null, but not both, return false.
// from https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/statements-expressions-operators/how-to-define-value-equality-for-a-type?redirectedfrom=MSDN
if (a is null)
{
// null == null = true.
if (b is null)
{
return true;
}
// Only the left side is null.
return false;
}
// Return true if the fields match:
return (a.Equals(b));
}
public static bool operator !=(CalibrationPoint a, CalibrationPoint b)
{
return !(a == b);
}
public static bool operator <(CalibrationPoint a, CalibrationPoint b)
{
return a.CompareTo(b) < 0;
}
public static bool operator >(CalibrationPoint a, CalibrationPoint b)
{
return a.CompareTo(b) > 0;
}
public static bool operator >=(CalibrationPoint a, CalibrationPoint b)
{
return a.CompareTo(b) >= 0;
}
public static bool operator <=(CalibrationPoint a, CalibrationPoint b)
{
return a.CompareTo(b) <= 0;
}
#endregion
}
}

View File

@ -0,0 +1,221 @@
using System;
using System.Collections.Generic;
using System.Linq;
using XYLEM.Base;
using XYLEM.Base.XML;
namespace XYLEM
{
[Serializable]
public class CalibrationPoints : IComparable<CalibrationPoints>, IEquatable<CalibrationPoints>
{
/// <summary>
/// calibrations to or from DUT
/// </summary>
public List<CalibrationPoint> calibrations { get; private set; }
public void SaveToFile(string filePath)
{
XMLWriteFuncClass.WriteToXmlFile(filePath, calibrations, false);
}
/// <summary>
///
/// </summary>
/// <param name="filePath"></param>
/// <returns>Is a valid calibration for DUT</returns>
public bool LoadFromFile(string filePath)
{
var pointsSaved = XMLWriteFuncClass.ReadFromXmlFile<List<CalibrationPoint>>(filePath);
calibrations = pointsSaved;
return IsOkay();
}
/// <summary>
/// Constructor for A empty list of calibrations, to use for loading calibrations from file
/// </summary>
public CalibrationPoints()
{
calibrations = new List<CalibrationPoint>();
}
/// <summary>
///
/// </summary>
/// <param name="cal_points"></param>
/// <param name="maxTotalPoints">Maximum numbers of calibration able to write to device</param>
public CalibrationPoints(List<CalibrationPoint> cal_points, int maxTotalPoints)
{
if (cal_points == null)
{
throw new ArgumentNullException("Calibrations points can't be zero");
}
if (cal_points.Count > maxTotalPoints)
{
throw new Exception($"Has {cal_points.Count} calibrations points and only support {maxTotalPoints}");
}
// Pad with zero if not the full size. Done to make a working writing and comparing two calibrations.
if (cal_points.Count < maxTotalPoints)
{
var missing = maxTotalPoints-cal_points.Count;
cal_points.AddRange(Enumerable.Range(0, missing).Select(_ => new CalibrationPoint(0, 0)));
}
calibrations = cal_points;
}
/// <summary>
/// Is a valid calibration to or from DUT
/// </summary>
/// <returns></returns>
public Boolean IsOkay()
{
if ((null == calibrations) || (0 > calibrations.Count))
{
return false; // Not okay
}
return true; // Is okay
}
/// <summary>
/// Number of calibrations to or from DUT
/// </summary>
/// <returns> is 0 or more if okay and -1 on error / not okay</returns>
public int Get_number_of_calibrations()
{
if (!IsOkay())
{
return -1;
}
return calibrations.Count;
}
public override string ToString()
{
if (!IsOkay())
{
return "No valide calibration to print out";
}
var ret_txt = "";
var idx = 0;
foreach (var cal in calibrations)
{
ret_txt += $"{idx++}: {cal}\n";
}
return ret_txt;
}
public int CompareTo(CalibrationPoints other)
{
// If null, it can't be the same
if (System.Object.ReferenceEquals(other, null))
{
return -1;
}
// Any of them is not okay
if (!this.IsOkay() || !other.IsOkay())
{
return -1; // Not the same
}
// if number of items is not the same
if (this.Get_number_of_calibrations() != other.Get_number_of_calibrations())
{
return -1; // Not the same
}
var num_of_cals = this.calibrations.Count;
var my_cals = this.calibrations;
var others_cals = other.calibrations;
for (int i = 0; i < num_of_cals; i++)
{
if (my_cals[i] != others_cals[i])
{
return -1; // Not the same
}
}
return 0; // is the same
}
public bool Equals(CalibrationPoints other)
{
return this.CompareTo(other) == 0;
}
public override bool Equals(object obj)
{
if (!(obj is CalibrationPoints)) return false;
CalibrationPoints p = (CalibrationPoints)obj;
return this == p;
}
public override int GetHashCode()
{
if (calibrations == null)
{
return base.GetHashCode();
}
else
{
int hash = 0;
foreach (var calibration in calibrations)
{
hash = HashTools.ShiftAndWrap(hash.GetHashCode(), 2) ^ calibration.GetHashCode();
}
return hash;
}
}
#region Operator == > < ! ..
public static bool operator ==(CalibrationPoints a, CalibrationPoints b)
{
// If both are null, or both are same instance, return true.
if (System.Object.ReferenceEquals(a, b))
{
return true;
}
// If one is null, but not both, return false.
// from https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/statements-expressions-operators/how-to-define-value-equality-for-a-type?redirectedfrom=MSDN
if (a is null)
{
// null == null = true.
if (b is null)
{
return true;
}
// Only the left side is null.
return false;
}
// Return true if the fields match:
return (a.Equals(b));
}
public static bool operator !=(CalibrationPoints a, CalibrationPoints b)
{
return !(a == b);
}
public static bool operator <(CalibrationPoints a, CalibrationPoints b)
{
return a.CompareTo(b) < 0;
}
public static bool operator >(CalibrationPoints a, CalibrationPoints b)
{
return a.CompareTo(b) > 0;
}
public static bool operator >=(CalibrationPoints a, CalibrationPoints b)
{
return a.CompareTo(b) >= 0;
}
public static bool operator <=(CalibrationPoints a, CalibrationPoints b)
{
return a.CompareTo(b) <= 0;
}
#endregion
}
}

View File

@ -0,0 +1,67 @@
using System;
using System.IO.Ports;
using XYLEM.Base.Config;
using XYLEM.Communication;
namespace XYLEM
{
/// <summary>
/// Command interface for MagFlux 6200
/// https://xyleminc.atlassian.net/wiki/spaces/MJKMF/pages/7112855120/Command+Interface+Draft
/// </summary>
internal interface IMagFlux : IMagFluxRequestProtocol
{
#region When sharing same serial port
/// <summary>
/// Connect when using same serial port
/// </summary>
/// <param name="id"></param>
/// <param name="md_com"></param>
/// <returns></returns>
Boolean Connect(UInt16 id, ModbusCom md_com);
/// <summary>
/// Get current device com settings
/// </summary>
/// <returns></returns>
SerialPortSettingClass GetComSetting();
/// <summary>
/// Current modbus device device ID / address
/// </summary>
UInt16 Device_ID { get; }
#endregion
#region For stand alone use without sharing same serial port
#endregion
/// <summary>
/// Make communication connection to Meter
/// !!NOTE!! Only one meter is supported for each com port
/// </summary>
/// <param name="comport">Like "COM1"</param>
/// <param name="id">>Device modbus address / ID 1..247 (default 1) Warning!! use 247 with single device connected, most MJK devices replay no matter it's id setting</param>
/// <returns>true on okay or false on error</returns>
Boolean Connect(string comport, UInt16 id = 1);
/// <summary>
/// Make communication connection to Meter with a specific communication setup
/// !!NOTE!! Only one meter is supported for each com port
/// </summary>
/// <param name="comport">>Like "COM1"</param>
/// <param name="id">>Device modbus address / ID 1..247 (default 1) Warning!! use 247 with single device connected, most MJK devices replay no matter it's id setting</param>
/// <param name="baudRate">Like 9600 (default on RS485)</param>
/// <param name="parity">Like Parity.Even (default on RS485)</param>
/// <returns></returns>
Boolean Connect(string comport, UInt16 id, UInt32 baudRate, Parity parity);
/// <summary>
/// Close communication connection to Meter
/// </summary>
/// <returns>true on okay or false on error</returns>
Boolean CloseConnection();
}
}

View File

@ -0,0 +1,40 @@
using System.IO.Ports;
using XYLEM.Device;
namespace XYLEM
{
public interface IMagFluxAPI
{
/// <summary>
/// Make communication connection to Meter
///
/// Imported note: Devices placed on same serial connection, must have same communication settings.
/// Ex. All devices on same serial connection must be configured to same baudrate, parity
///
/// </summary>
/// <param name="comport">Like "COM1"</param>
/// <param name="id">Device modbus address / ID 1..247 (default 1) Warning!! use 247 with single device connected, most MJK devices replay no matter it's id setting</param>
/// <param name="log_path">folder path for where to log file should be saved</param>
/// <param name="runAs">RUN_TYPE.Normal with connection to serial port, if not set</param>
/// <returns>Return a MagFlux device or "null" if failing connect</returns>
IMagFluxRequestProtocol Connect(string comport, ushort id = 1, string log_path = null, RUN_TYPE runAs = RUN_TYPE.Normal);
/// <summary>
/// Make communication connection to Meter with a specific communication setup
///
/// Imported note: Devices placed on same serial connection, must have same communication settings.
/// Ex. All devices on serial connection must be configured to same baudrate, parity
///
/// </summary>
/// <param name="comport">>Like "COM1"</param>
/// <param name="id">Device modbus address / ID 1..247 (default 1) Warning!! use 247 with single device connected, most MJK devices replay no matter it's id setting</param>
/// <param name="baudRate">Like 9600 (default on RS485)</param>
/// <param name="parity">Like Parity.Even (default on RS485)</param>
/// <param name="log_path">folder path for where to log file should be saved</param>
/// <param name="runAs">RUN_TYPE.Normal with connection to serial port, if not set</param>
/// <returns>Return a MagFlux device or "null" if failing connect</returns>
/// <exception cref="InvalidDataException"> if the configuration is not valid</exception>
IMagFluxRequestProtocol Connect(string comport, ushort id, uint baudRate, Parity parity, string log_path = null, RUN_TYPE runAs = RUN_TYPE.Normal);
}
}

View File

@ -0,0 +1,350 @@
using System;
using System.Collections.Generic;
using XYLEM.Base;
namespace XYLEM
{
/// <summary>
/// Command interface for MagFlux
/// https://xyleminc.atlassian.net/wiki/spaces/MJKMF/pages/7112855120/Command+Interface+Draft
/// </summary>
public interface IMagFluxRequestProtocol
{
/// <summary>
/// Is connected
/// </summary>
/// <returns>true if yes</returns>
Boolean IsConnected();
/// <summary>
/// Get current device Modbus ID / Device Address
/// </summary>
/// <param name="value_out">1-246</param>
/// <returns>true on okay or false on error</returns>
Boolean GetDeviceID(out int value_out);
/// <summary>
/// Simple Check if a device ID is Free or responding
/// Reads address 0 to check on any device response
/// Is used in SetDeviceID() before attempting change ID
/// </summary>
/// <param name="id_to_check"></param>
/// <returns>Return True if no device was responding on ID</returns>
Boolean IsDeviceID_Free(uint id_to_check);
/// <summary>
/// Set current device Modbus ID / Device Address
/// </summary>
/// <param name="value_out">1-246 (Don't use device ID 247, it is a MJK broad cast)</param>
/// <returns>true on okay or false on error</returns>
/// Notes:
/// There is a simple check on new device id is free (read address 0 check on)
/// Change of device ID is instantly and may loose any communication if not able to function on this ID.
/// Troubleshooting on failing:
/// * Power off and remove optional USBC cable on MagFlux.
/// * Remove all other devices on RS485 and retry connection.
/// * Check Device ID manually on LCD other program like 840126 with USBC connection.
Boolean SetDeviceID(UInt16 new_id);
/// <summary>
/// Get printout of communication counters
/// </summary>
/// <returns></returns>
string GetComCounters();
/// <summary>
/// Set location for where log data can saved.
/// </summary>
/// <param name="path">path for where to log file should be saved</param>
/// <param name="filename">set a custom log file name without extension (ex. "UserCustomLogFile") or null if use default</param>
/// <returns>true on okay or false on error</returns>
Boolean SetLogLocation(String path, string filename = null);
/// <summary>
/// Open saved log file
/// </summary>
void OpenLogFile();
/// <summary>
/// Get latest log added to log file while this program was running
/// </summary>
/// <param name="from">How long to go back after log messages, if Null then standard 1 minute</param>
/// <returns>"Lasted" Log messages Queue After last connection</returns>
List<LogMessage> GetLatestLogs(DateTime? from = null);
/// <summary>
/// Unique-ID for the MagFlux electronics
/// </summary>
/// <param name="value_out">a hex decimal string 0x1234ABCDEF or NULL at error</param>
/// <returns>true on okay or false on error</returns>
Boolean GetUniqueId(out string value_out);
/// <summary>
/// MagFlux metrology board serial number
/// More info on:
/// https://xyleminc.atlassian.net/wiki/spaces/MJKMF/pages/7648215086/Metrology+and+Application+serial+numbers
/// </summary>
/// <param name="value_out">a serial number ex. 510360.00000105W46Y23 or NULL at error</param>
/// <returns>true on okay or false on error</returns>
Boolean GetBoardSerialNo(out string value_out);
/// <summary>
/// MagFlux metrology board serial number
/// More info on:
/// https://xyleminc.atlassian.net/wiki/spaces/MJKMF/pages/7648215086/Metrology+and+Application+serial+numbers
/// </summary>
/// <param name="new_serial_number">a serial number ex. 510360.00000105W46Y23</param>
/// <returns>true on okay or false on error</returns>
Boolean SetBoardSerialNo(string new_serial_number);
/// <summary>
/// Get the firmware version
/// </summary>
/// <param name="value_out">like 1.2.4 (MAJOR.MINOR.REVISION)</param>
/// <returns>true on okay or false on error</returns>
Boolean GetFirmwareVersion(out string value_out);
/// <summary>
/// Get Current device register version
/// </summary>
/// <param name="value_out">like "51" or on connecting error "?", "0", "-1" </param>
/// <returns>true on okay or false on error</returns>
Boolean GetRegisterVersion(out string value_out);
/// <summary>
/// Get Current communication register version used by the interface
/// </summary>
/// <param name="value_out">like "51" or on error "?", "0", "-1" </param>
/// <returns>true on okay or false on error</returns>
Boolean GetAPIRegisterVersion(out string value_out);
/// <summary>
/// Get the firmware build date
/// </summary>
/// <param name="value_out">like 2022/12/24 13:00:00 or 2022-12-24 13:45:10</param>
/// <returns>true on okay or false on error</returns>
Boolean GetFwBuildDate(out string value_out);
/// <summary>
/// Git Hash to Unique identify firmware
/// </summary>
/// <param name="value_out">like 0xABCDE123</param>
/// <returns>true on okay or false on error</returns>
Boolean GetFwGitHash(out string value_out);
/// <summary>
/// Flow rate calibrated
/// </summary>
/// <param name="value_out"> Actual flow rate [l/s] </param>
/// <returns>true on okay or false on error</returns>
Boolean GetFlowRate_lps(out Single value_out);
/// <summary>
/// !!! Warning make sure to turn off simulation, when calibration off sensor is done !!!
/// ----
/// Set a fixed test flow to force MagFlux, for check of digital output pulse etc.
/// ----
/// Will also activate and start fixed simulated flow in device
/// Used for getting a fixed simulated flow before sensor calibration from MagFlux
/// Note on limitation:
/// The actual resulting flow is depended on sensor calibration and MagFlux conversion from m/s to flow.
/// Always check resulting flow with GetFlowRate_lps() to verify if the same as expected
/// With a calibration of all 0 (equal no calibration 1:1) normally produce same GetFlowRate_lps() down to 3 digit precision.
/// </summary>
/// <param name="value_lps">The fixed flow to force MagFlux to output [l/s] </param>
/// <returns>true on okay or false on error</returns>
Boolean SetSimulatedFlow_lps(double value_lps);
/// <summary>
/// Get the correction factor from board "1.0000" is default none calibration board
/// </summary>
/// <param name="value_out"></param>
/// <returns>true on okay or false on error</returns>
Boolean GetElectrodeBoardCorrectionFactor(out Single value_out);
/// <summary>
/// Get Empty pipe control bits
/// Bit0="EPD disabled", 1="Enabled w. Flags only", 2="EPD enabled full"
/// </summary>
/// <param name="epd_cntl_bits">empty pipe control bits</param>
/// <returns>true on okay or false on error</returns>
Boolean GetEmptyPipeControl(out Int32 epd_cntl_bits);
/// <summary>
/// !!! Warning don't use this feature on already correct calibrated and configured boards !!!
/// Can only be used for demo and not for real sensor customer calibration measurement
/// ----
/// Set a uncalibrated blank board to defaults, that allow using it for testing
/// ----
/// Note:
/// Limitations will take up to a minute to exit, if all configs needs to be set in a blank device
/// * If "1.00" and device Healthy not, then rewrite "ElectrodeBoardCorrectionFactor" as "1.00" to remove PDS Invalid system calibration error
/// * If Sensor serial number is "0", it will be changed to "2"
/// * If Flange type is "0", It will be changed to "1" equal "EN-1092-1"
/// * If board PCB SN is blank "", then to "Demo [Date on change]"
/// * if Empty Pipe Control bits is all "0", then turn on "Enable w. flags only"
/// * Prepare with a default calibration that is 1:1
/// </summary>
/// <returns>true on okay or false on error</returns>
Boolean SetPCBToDemoDefaults();
/// <summary>
/// Is the fixed test flow active
/// Used for getting a fixed simulated flow from MagFlux
/// </summary>
/// <returns>true if ON</returns>
Boolean IsSimulatedFlowActive();
/// <summary>
/// Turn on/off fixed test flow output from MagFlux
/// Used for getting a fixed simulated flow from MagFlux
/// </summary>
/// <param name="testFlowOn"></param>
/// <returns>true on okay or false on error</returns>
Boolean SetSimulatedFlowActive(Boolean testFlowOn);
/// <summary>
/// Total forward volume (Positive flow volume totalizator)
/// </summary>
/// <param name="value_out">volume in in liter [l]</param>
/// <returns>true on okay or false on error</returns>
Boolean GetForwardVolume_l(out Double value_out);
/// <summary>
/// Total backward volume (Reversed or negative flow volume totalizator)
/// </summary>
/// <param name="value_out"></param>
/// <returns>true on okay or false on error</returns>
Boolean GetBackwardVolume_l(out Double value_out);
/// <summary>
/// Get the general sensor information
/// </summary>
/// <param name="value_out">sensor information</param>
/// <returns>true on okay or false on error</returns>
Boolean GetSensorInfo(out SensorInfo value_out);
/// <summary>
/// MagFlux Sensor serial number
/// </summary>
/// <param name="value_out">a decimal serial number ex. 12345678 or NULL at error</param>
/// <returns>true on okay or false on error</returns>
Boolean GetSensorSerialNo(out string value_out);
/// <summary>
/// Set MagFlux Sensor serial number
/// </summary>
/// <param name="new_serial_number"></param>
/// <returns>true on okay or false on error</returns>
Boolean SetSensorSerialNo(UInt64 new_serial_number);
/// <summary>
/// MagFlux Sensor nominal DN size in millimeters
/// </summary>
/// <param name="dn_mm_out">DN size in [mm] is -1 on error</param>
/// <returns>true on okay or false on error</returns>
Boolean GetDn_mm(out Int32 dn_mm_out);
/// <summary>
/// Set Sensor nominal DN size in millimeters
/// </summary>
/// <param name="new_dn_mm">DN size in [mm] ex 50 is 50mm or DN50</param>
/// <returns>true on okay or false on error</returns>
Boolean SetDn_mm(UInt16 new_dn_mm);
/// <summary>
/// Get Sensor Flange Type
/// 0 = Unknown, 1="EN-1092-1", 2=AS 4087-2004 or AS 2129-2000", 3="ANSI or ASME B16.5", 4="AWWA C207"
/// </summary>
/// <param name="flangeType_out">Flange type number</param>
/// <returns>true on okay or false on error</returns>
Boolean GetFlangeType(out Int32 flangeType_out);
/// <summary>
/// Set Sensor Flange Type
/// 0 = Unknown, 1="EN-1092-1", 2=AS 4087-2004 or AS 2129-2000", 3="ANSI or ASME B16.5", 4="AWWA C207"
/// </summary>
/// <param name="new_flangeType">Flange type number</param>
/// <returns>true on okay or false on error</returns>
Boolean SetFlangeType(UInt16 new_flangeType);
/// <summary>
/// get what volume per pulse for both forward and reverse counter is
/// Note: will return only forward pulse volume if both settings is not the same.
/// </summary>
/// <param name="pls_vol_ml">A pulse volume in [ml] (milliliter)</param>
/// <returns>true on okay or false on error</returns>
Boolean GetVolumePerPulse_ml(out UInt32 pls_vol_ml);
/// <summary>
/// Set what volume per pulse for both forward and reverse counter is
/// </summary>
/// <param name="pls_vol_ml">A pulse volume in [ml] (milliliter)</param>
/// <returns>true on okay or false on error</returns>
Boolean SetVolumePerPulse_ml(UInt32 pls_vol_ml);
/// <summary>
/// Get what pulse turn on time for both forward and reverse counter is
/// Note: will return only forward turn on time if both settings is not the same.
/// </summary>
/// <param name="pls_Ton_ms">A pulse turn on time in ms (millisecond) Note setting to 0 will result in pulse time be as fast as device support</param>
/// <returns>true on okay or false on error</returns>
Boolean GetPulseOutput_Ton_ms(out UInt16 pls_Ton_ms);
/// <summary>
/// Set what pulse turn on time for both forward and reverse counter is
/// </summary>
/// <param name="pls_vol_ml">A pulse turn on time in ms (millisecond)</param>
/// <returns>true on okay or false on error</returns>
Boolean SetPulseOutput_Ton_ms(UInt16 pls_Ton_ms);
/// <summary>
/// Check if there is problem with the DUT
/// use <see cref="GetDeviceErrorMessages"/>" to get a list of error messages for debug problems
/// </summary>
/// <returns>>true if device operates correctly</returns>
Boolean GetDeviceHealthy();
/// <summary>
/// get a list of error messages for debug problem
/// </summary>
/// <param name="status_list_out">Will return a empty list if there is no messages to return</param>
/// <returns>true on okay or false on error</returns>
Boolean GetDeviceErrorMessages(out List<string> status_list_out);
/// <summary>
/// This function prepares the DUT for the calibration.
///
/// ATTENTION:
/// This function needs to be called before the calibration process starts any flow of water.
/// </summary>
/// <returns>true on okay or false on error</returns>
Boolean PrepareDeviceForCalibration();
/// <summary>
/// This function will abort started or failed calibration to bring DUT back to normal calibration state
/// </summary>
/// <returns>true on okay or false on error</returns>
Boolean AbortDeviceForCalibration();
/// <summary>
/// The maximum calibration points that is supported by the device
/// </summary>
int CalibrationPointsMax { get; }
/// <summary>
/// Get list of calibration points saved in DUT
/// </summary>
/// <param name="values_read">The calibrations points from device</param>
/// <returns>true on okay or false on error</returns>
Boolean GetCalibrationPoints(out CalibrationPoints values_read);
/// <summary>
/// set calibration in DUT.
/// Remember to run <see cref="PrepareDeviceForCalibration"/> before the calibration process is started.
/// </summary>
/// <param name="new_calibration_points">A list of calibration points to write to DUT</param>
/// <returns>true on okay or false on error</returns>
Boolean SetCalibrationPoints(CalibrationPoints new_calibration_points);
}
}

View File

@ -0,0 +1,90 @@
using System;
namespace XYLEM
{
public class SensorInfo
{
/// <summary>
///Sensor serial number ex. 0x1234ABCDEF or 0 as unknown / not defined
/// </summary>
public UInt64 SerialNumber { get; private set; }
/// <summary>
/// MagFlux Sensor nominal DN size in millimeters
/// </summary>
public Int32 DN_mm { get; private set; }
/// <summary>
/// MagFlux Sensor Flange Type
/// 0 = Unknown, 1="EN-1092-1", 2=AS 4087-2004 or AS 2129-2000", 3="ANSI or ASME B16.5", 4="AWWA C207"
/// </summary>
public Int32 FlangeType { get; private set; }
/// <summary>
/// Calibration method was used. 0 is default, for calibration on flow rig for 5 min per point
/// </summary>
public Int32 CalibrationVersion { get; private set; }
/// <summary>
/// Sampling scheme code used by front end measurement. //NL// 0=32/40, 1=20/40
/// </summary>
public Int32 SamplingSchemeCode { get; private set; }
/// <summary>
/// Coil driver frequency, 0 = 0.625Hz, 1= 1.25Hz, 2 = 2.5Hz, 3 = 5Hz, 4 = 10Hz,
/// </summary>
public Int32 CoilDriverFrequencyConfig { get; private set; }
/// <summary>
/// Number of calibration points
/// The same as calling "Calibration.Get_number_of_calibrations()"
/// </summary>
public Int32 NumberOfCalibrations { get; private set; }
/// <summary>
/// List of calibration points saved in DUT
/// </summary>
public CalibrationPoints Calibration { get; private set; }
public SensorInfo(
UInt64 SerialNumber,
Int32 DN_mm,
Int32 FlangeType,
Int32 CalibrationVersion,
Int32 SamplingSchemeCode,
Int32 CoilDriverFrequencyConfig,
CalibrationPoints Calibration)
{
this.SerialNumber = SerialNumber;
this.DN_mm = DN_mm;
this.FlangeType = FlangeType;
this.CalibrationVersion = CalibrationVersion;
this.SamplingSchemeCode = SamplingSchemeCode;
this.CoilDriverFrequencyConfig = CoilDriverFrequencyConfig;
this.Calibration = Calibration;
if (null == this.Calibration)
{
this.NumberOfCalibrations = 0;
}
else
{
this.NumberOfCalibrations = this.Calibration.Get_number_of_calibrations();
}
}
public override String ToString()
{
String strReturn = "";
strReturn += $"SN: {SerialNumber}" + Environment.NewLine;
strReturn += $"DN{DN_mm} [mm]" + Environment.NewLine;
strReturn += $"Flange: {FlangeType}" + Environment.NewLine;
strReturn += $"Cal. Ver: {CalibrationVersion}" + Environment.NewLine;
strReturn += $"Sampling Scheme: {SamplingSchemeCode}" + Environment.NewLine;
strReturn += $"Coil Freq.: {CoilDriverFrequencyConfig}" + Environment.NewLine;
strReturn += $"Number of Cal.points: {NumberOfCalibrations}" + Environment.NewLine;
strReturn += $"Cal.points:" + Environment.NewLine + Calibration.ToString();
return strReturn;
}
}
}

Binary file not shown.

Binary file not shown.