using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using NLog;
using XYLEM;
using Xylem.Common.Hardware.Interfaces.Ports.PortCore.EventArguments;
using Xylem.Common.Hardware.Interfaces.Protocols.ProtocolCore;
using Xylem.Common.Hardware.Interfaces.Protocols.ProtocolCore.EventArguments;
using Xylem.Common.Hardware.WaterMeter.MagFlux.DataPackages.DataTypes;
using Xylem.Common.Utils.Logging;
namespace Xylem.Common.Hardware.WaterMeter.MagFlux.Protocols.RequestProtocol
{
///
/// Wrapper for MagFlux request protocol implemented in
///
public class RequestProtocol : BaseProtocol
{
private readonly String _ident;
private readonly ILogger _logger;
private IMagFluxRequestProtocol _magFluxRequestProtocol;
private IMagFluxAPI _magFluxApi;
// calibration point in cubic meters per hour
private List _calibPointsCmPerH;
// intermediate volumes in cubic-meters
private Double _forwardVolume_cm;
private Double _reverseVolume_cm;
///
///
/// - MagFluxApi
///
public RequestProtocol(String ident) : base(ident)
{
_ident = ident;
_magFluxApi = new MagFluxAPI();
_calibPointsCmPerH = new List();
_logger = NLogHelper.CreateOrGetMultiLogger(_ident, "", "RequestProtocol", "MeterBase",
"MeterBase");
}
/// >
///
/// - MagFluxApi
///
public override void Dispose()
{
_calibPointsCmPerH.Clear();
_calibPointsCmPerH = null;
CloseConnection();
_magFluxRequestProtocol = null;
_magFluxApi = null;
base.Dispose();
}
///
public override event EventHandler OnRecordReadyToSend;
///
public override event EventHandler OnRecordIsDecoded;
protected override void DecodeRecord(IPortDataEventArgs data)
{
throw new NotImplementedException();
}
///
/// Wrapper to connect MagFlux
///
///
///
///
/// - Initial
///
///
/// - MagFluxApi
///
///
/// - Avoid re-opening if connection is already done
///
public Boolean Connect(String portName)
{
if (_magFluxApi == null)
return false;
if (_magFluxRequestProtocol != null && _magFluxRequestProtocol.IsConnected())
{
_logger.Info($"{_ident} Connection already established to {portName}");
return true;
}
_magFluxRequestProtocol = _magFluxApi.Connect(portName);
if (_magFluxRequestProtocol == null)
{
_logger.Error($"{_ident} Connection to {portName} failed! Object reference returned null");
return false;
}
Thread.Sleep(100);
var retVal = _magFluxRequestProtocol.IsConnected();
if (retVal)
{
_logger.Info($"{_ident} New connection established to {portName}");
}
else
{
_logger.Error($"{_ident} Connection to {portName} failed!");
}
return retVal;
}
public String GetComCounters()
{
throw new NotImplementedException();
}
///
/// Wrapper to set the log location for MagFlux direct raw output
///
/// location of raw logging
/// file name based on the UniqueId
///
///
/// - Initial
///
public Boolean SetLogLocation(String path, String fileName)
{
if (_magFluxRequestProtocol == null)
return false;
var retVal = _magFluxRequestProtocol.SetLogLocation(path, fileName);
if (string.IsNullOrEmpty(fileName))
fileName = "?";
_logger.Debug(retVal ?
$"{_ident} Logging set to: {path}\\{fileName}" :
$"{_ident} Logging path setup failed!");
return retVal;
}
public void OpenLogFile()
{
throw new NotImplementedException();
}
///
/// Wrapper to set experimental boards to defaults regarding board serial number
/// and board calibration values
///
///
///
/// - Initial
///
public Boolean SetPCBToDemoDefaults()
{
if (_magFluxRequestProtocol == null)
return false;
var retVal = _magFluxRequestProtocol.SetPCBToDemoDefaults();
_logger.Debug(retVal ?
$"{_ident} Successfully set PCB settings and PCB calibrations to default" :
$"{_ident} PCB settings and PCB calibrations setup to default failed!");
return retVal;
}
///
/// Wrapper to get the calibration read only lock
///
///
///
/// - Initial
///
public Boolean IsMetrologyReadOnly()
{
if (_magFluxRequestProtocol == null)
return false;
var retVal = _magFluxRequestProtocol.IsMetrologyReadOnly();
_logger.Debug($"{_ident} Calibration read only read back returns: {retVal}");
return retVal;
}
///
/// Wrapper to get the simulated flow setting
///
///
///
/// - Initial
///
public Boolean IsSimulatedFlowActive()
{
if (_magFluxRequestProtocol == null)
return false;
var retVal = _magFluxRequestProtocol.IsSimulatedFlowActive();
_logger.Debug($"{_ident} Simulated flow active read back returns: {retVal}");
return retVal;
}
///
/// Wrapper to set the simulated flow setting
///
/// true to ignore state
///
///
/// - Initial
///
public Boolean SetSimulatedFlowActive(Boolean on)
{
if (_magFluxRequestProtocol == null)
return false;
var retVal = _magFluxRequestProtocol.SetSimulatedFlowActive(on);
_logger.Debug(retVal ?
$"{_ident} Simulated flow active set to: {on}" :
$"{_ident} Simulated flow active setup failed!");
return retVal;
}
///
/// Wrapper to get the ignore empty pipe mode status
///
///
///
/// - Initial
///
public Boolean GetIgnoreFailOnEmptyPipeOnHealthy()
{
if (_magFluxRequestProtocol == null)
return false;
var retVal = _magFluxRequestProtocol.GetIgnoreFailOnEmptyPipeOnHealthy();
_logger.Debug($"{_ident} Ignore empty pipe status read back returns: {retVal}");
return retVal;
}
///
/// Wrapper to set the ignore empty pipe mode
///
/// true to ignore state
///
///
/// - Initial
///
public Boolean SetIgnoreFailOnEmptyPipeOnHealthy(Boolean on)
{
if (_magFluxRequestProtocol == null)
return false;
_magFluxRequestProtocol.SetIgnoreFailOnEmptyPipeOnHealthy(on);
var retVal = _magFluxRequestProtocol.GetIgnoreFailOnEmptyPipeOnHealthy();
_logger.Debug(retVal == on ?
$"{_ident} Ignore empty pipe status adjusted to: {on}" :
$"{_ident} Ignore empty pipe status setup failed!");
return retVal == on;
}
///
/// Wrapper to set the empty pipe bits
///
///
///
///
/// - Initial
///
public Boolean SetEmptyPipeControl(Int32 epd_cntl_bits)
{
if (_magFluxRequestProtocol == null)
return false;
var retVal = _magFluxRequestProtocol.SetEmptyPipeControl(epd_cntl_bits);
_logger.Debug(retVal ?
$"{_ident} Empty pipe control bits set to: 0x{epd_cntl_bits:X4}" :
$"{_ident} Empty pipe control bits setup failed!");
return retVal;
}
///
/// Wrapper to get the empty pipe bits
///
///
///
///
/// - Initial
///
public Boolean GetEmptyPipeControl(out Int32 epd_cntl_bits)
{
epd_cntl_bits = 0;
if (_magFluxRequestProtocol == null)
return false;
var retVal = _magFluxRequestProtocol.GetEmptyPipeControl(out epd_cntl_bits);
_logger.Debug(retVal ?
$"{_ident} Empty pipe control bits readout: 0x{epd_cntl_bits:X4}" :
$"{_ident} Empty pipe control bits request failed!");
return retVal;
}
///
/// Wrapper to get the standard deviation value of the electrode in milli Volts
///
///
///
///
/// - Initial
///
public Boolean GetStdDev_Electrode_mV(out Single u_mV)
{
u_mV = 0;
if (_magFluxRequestProtocol == null)
return false;
var retVal = _magFluxRequestProtocol.GetStdDev_Electrode_mV(out u_mV);
_logger.Debug(retVal ?
$"{_ident} Standard deviation of electrode: {u_mV:F6} mV" :
$"{_ident} Standard deviation of electrode request failed!");
return retVal;
}
///
/// Wrapper to get the standard deviation value of the electrode in milli Volts
///
///
///
///
/// - Initial
///
public Boolean GetAverage_Electrode_mV(out Single u_mV)
{
u_mV = 0;
if (_magFluxRequestProtocol == null)
return false;
var retVal = _magFluxRequestProtocol.GetAverage_Electrode_mV(out u_mV);
_logger.Debug(retVal ?
$"{_ident} Average of electrode: {u_mV:F6} mV" :
$"{_ident} Average of electrode request failed!");
return retVal;
}
///
/// Wrapper to get the board calibration value
///
///
///
///
/// - Initial
///
public Boolean GetElectrodeBoardCorrectionFactor(out Single value_out)
{
value_out = 0f;
if (_magFluxRequestProtocol == null)
return false;
var retVal = _magFluxRequestProtocol.GetElectrodeBoardCorrectionFactor(out value_out);
_logger.Debug(retVal ?
$"{_ident} Board calibration: {value_out:F4}" :
$"{_ident} SensorSerialNo request failed!");
return retVal;
}
///
/// Wrapper to get the sensor serial number
///
///
///
///
/// - Initial
///
public Boolean GetSensorSerialNo(out String sensorSerialNo)
{
sensorSerialNo = "?";
if (_magFluxRequestProtocol == null)
return false;
var retVal = _magFluxRequestProtocol.GetSensorSerialNo(out sensorSerialNo);
_logger.Debug(retVal ?
$"{_ident} SensorSerialNo: {sensorSerialNo}" :
$"{_ident} SensorSerialNo request failed!");
return retVal;
}
///
/// Wrapper to get the PcbId
///
///
///
///
/// - Initial
///
public Boolean GetPcbId(out String pcbId)
{
pcbId = "?";
if (_magFluxRequestProtocol == null)
return false;
var retVal = _magFluxRequestProtocol.GetBoardSerialNo(out pcbId);
_logger.Debug(retVal ?
$"{_ident} PcbId: {pcbId}" :
$"{_ident} PcbId request failed!");
return retVal;
}
///
/// Wrapper to set the sensor serial number
///
///
///
///
/// - Initial
///
public Boolean SetSensorSerialNo(UInt32 sensorSerialNo)
{
if (_magFluxRequestProtocol == null)
return false;
var retVal = _magFluxRequestProtocol.SetSensorSerialNo(sensorSerialNo);
_logger.Debug(retVal ?
$"{_ident} Set SensorSerialNo: {sensorSerialNo}" :
$"{_ident} Set SensorSerialNo request failed!");
return retVal;
}
///
/// Wrapper to get unique id referenced as PCBID
///
///
///
///
/// - Initial
///
public Boolean GetUniqueId(out String pcbId)
{
pcbId = "?";
if (_magFluxRequestProtocol == null)
return false;
var retVal = _magFluxRequestProtocol.GetUniqueId(out pcbId);
_logger.Debug(retVal ?
$"{_ident} UniqueId: {pcbId}" :
$"{_ident} UniqueId request failed!");
return retVal;
}
///
/// Wrapper to get FW version of MagFlux
///
///
///
///
/// - Initial
///
public Boolean GetFirmwareVersion(out String fwVersion)
{
fwVersion = "?";
if (_magFluxRequestProtocol == null)
return false;
var retVal = _magFluxRequestProtocol.GetFirmwareVersion(out fwVersion);
_logger.Debug(retVal ?
$"{_ident} FW Version: {fwVersion}" :
$"{_ident} FW Version request failed!");
return retVal;
}
///
/// Wrapper to get FW Build Date
///
///
///
///
/// - Initial
///
public Boolean GetFwBuildDate(out String fwBuildDate)
{
fwBuildDate = "?";
if (_magFluxRequestProtocol == null)
return false;
var retVal = _magFluxRequestProtocol.GetFwBuildDate(out fwBuildDate);
_logger.Debug(retVal ?
$"{_ident} FW Build Date: {fwBuildDate}" :
$"{_ident} FW Build Date request failed!");
return retVal;
}
///
/// Wrapper to get FW GIT hash of MagFlux
///
///
///
///
/// - Initial
///
public Boolean GetFwGitHash(out String fwGitHash)
{
fwGitHash = "?";
if (_magFluxRequestProtocol == null)
return false;
var retVal = _magFluxRequestProtocol.GetFwGitHash(out fwGitHash);
_logger.Debug(retVal ?
$"{_ident} FW GIT Hash: {fwGitHash}" :
$"{_ident} FW GIT Hash request failed!");
return retVal;
}
///
/// Wrapper to get API register version of MagFlux
///
///
///
///
/// - Initial
///
public Boolean GetApiRegisterVersion(out String apiRegisterVersion)
{
apiRegisterVersion = "?";
if (_magFluxRequestProtocol == null)
return false;
var retVal = _magFluxRequestProtocol.GetAPIRegisterVersion(out apiRegisterVersion);
_logger.Debug(retVal ?
$"{_ident} MagFlux API Register Version: {apiRegisterVersion}" :
$"{_ident} MagFlux API Register Version request failed!");
return retVal;
}
public Boolean GetFlowRate_lps(out Single value_out)
{
throw new NotImplementedException();
}
///
/// Wrapper to get the forward volume in cm
///
///
///
///
/// - Initial
///
public Boolean GetForwardVolume_cm(out Double forwardVolume_cm)
{
forwardVolume_cm = 0;
if (_magFluxRequestProtocol == null)
return false;
var retVal = _magFluxRequestProtocol.GetForwardVolume_l(out var forwardVolume_l);
// convert the liters to cubic-meters
forwardVolume_cm = forwardVolume_l / 1000f;
_logger.Debug(retVal ?
$"{_ident} Forward Volume: {forwardVolume_cm:F3} m³" :
$"{_ident} Forward Volume request failed!");
_forwardVolume_cm = forwardVolume_cm;
return retVal;
}
///
/// Wrapper to get the backward volume in cm
///
///
///
///
/// - Initial
///
public Boolean GetReverseVolume_cm(out Double reverseVolume_cm)
{
reverseVolume_cm = 0;
if (_magFluxRequestProtocol == null)
return false;
var retVal = _magFluxRequestProtocol.GetBackwardVolume_l(out var backwardVolume_l);
// convert the liters to cubic-meters
reverseVolume_cm = backwardVolume_l / 1000f;
_logger.Debug(retVal ?
$"{_ident} Reverse Volume: {reverseVolume_cm:F3} m³" :
$"{_ident} Reverse Volume request failed!");
_reverseVolume_cm = reverseVolume_cm;
return retVal;
}
///
/// Get the volume in cm which is the forwardVolume_cm - backwardVolume_cm
///
///
///
///
/// - Initial
///
public Boolean GetVolume_cm(out Double volume_cm)
{
volume_cm = _forwardVolume_cm - _reverseVolume_cm;
if (_magFluxRequestProtocol == null)
return false;
_logger.Debug($"{_ident} Volume: {volume_cm:F3} m³");
return true;
}
///
/// Wrapper to get meter size in mm
///
///
///
///
/// - Initial
///
public Boolean GetMeterSizeMm(out Int32 meterSize)
{
meterSize = 0;
if (_magFluxRequestProtocol == null)
return false;
var retVal = _magFluxRequestProtocol.GetDn_mm(out meterSize);
_logger.Debug(retVal ?
$"{_ident} MeterSize DN: {meterSize}" :
$"{_ident} MeterSize request failed!");
return retVal;
}
///
/// Wrapper to set meter size in mm
///
///
///
///
/// - Initial
///
public Boolean SetMeterSizeMm(UInt16 meterSize)
{
if (_magFluxRequestProtocol == null)
return false;
var retVal = _magFluxRequestProtocol.SetDn_mm(meterSize);
_logger.Debug(retVal ?
$"{_ident} Set MeterSize DN: {meterSize}" :
$"{_ident} Set MeterSize failed!");
return retVal;
}
///
/// Wrapper to get info if device is healthy
///
///
///
/// - Initial
///
public Boolean GetDeviceHealthy()
{
if (_magFluxRequestProtocol == null)
return false;
var retVal = _magFluxRequestProtocol.GetDeviceHealthy();
_logger.Debug($"{_ident} Get device is healthy read back returns: {retVal}");
return retVal;
}
///
/// Wrapper to get the device error list
///
///
///
///
/// - Initial
///
public Boolean GetDeviceErrorMessages(out List status_list_out)
{
status_list_out = null;
if (_magFluxRequestProtocol == null)
return false;
var retVal = _magFluxRequestProtocol.GetDeviceErrorMessages(out status_list_out);
_logger.Debug(retVal ?
$"{_ident} Error messages: {status_list_out}" :
$"{_ident} Error messages request failed!");
return retVal;
}
///
/// Wrapper to get the device status
///
///
///
///
/// - Initial
///
public Boolean GetDeviceStatus(out String deviceStatusMsg)
{
deviceStatusMsg = null;
if (_magFluxRequestProtocol == null)
return false;
var retVal = _magFluxRequestProtocol.GetDeviceStatus(out var deviceStatus);
deviceStatusMsg = deviceStatus.ToString();
_logger.Debug(retVal ?
$"{_ident} Device status messages messages: {deviceStatusMsg}" :
$"{_ident} Device status messages request failed!");
return retVal;
}
public Boolean PrepareDeviceForCalibration()
{
if (_magFluxRequestProtocol == null)
return false;
var retVal = _magFluxRequestProtocol.PrepareDeviceForCalibration();
_logger.Debug(retVal ?
$"{_ident} MagFlux successfully prepared for calibration" :
$"{_ident} MagFlux preparation for calibration failed!");
return retVal;
}
public Boolean AbortDeviceForCalibration()
{
if (_magFluxRequestProtocol == null)
return false;
var retVal = _magFluxRequestProtocol.AbortDeviceForCalibration();
_logger.Debug(retVal ?
$"{_ident} MagFlux calibration successfully aborted" :
$"{_ident} MagFlux abortion of calibration failed!");
return retVal;
}
///
/// Wrapper to get the calibration points from MagFlux:
/// - Here the conversion from to to
/// will take place.
///
///
///
///
/// - Initial
///
///
/// - Output in cubic meters per hour.
///
public Boolean GetCalibrationPoints(out List calibPointsCmPerH)
{
calibPointsCmPerH = new List();
if (_magFluxRequestProtocol == null)
return false;
var retVal = _magFluxRequestProtocol.GetCalibrationPoints(out var calibrations);
_logger.Debug(retVal ?
$"{_ident} MagFlux calibration successfully read:\n{calibrations}" :
$"{_ident} MagFlux calibration read failed!");
if (!retVal)
return false;
// extract the single calibration points from container as ref and DUT in liters per second
var calibPoints = calibrations?.calibrations?.ToList();
if (calibPoints == null)
return false;
var calibConverter = new Calibration();
_calibPointsCmPerH?.Clear();
foreach (var cp in calibPoints)
{
// convert flow rate from liters per second to cubic meters per hour
calibConverter.refFlowRate = cp.ReferenceFlowRate_lps * 3.6f;
calibConverter.dutFlowRate = cp.ReportedFlowRate_lps * 3.6f;
_calibPointsCmPerH?.Add(calibConverter);
}
calibPointsCmPerH = _calibPointsCmPerH;
return true;
}
///
/// Wrapper to set the calibration points from MagFlux:
/// - Calibration points have to be sorted ascending by request from MJK
/// - Here the conversion from to
/// will take place.
///
///
///
///
/// - Initial
///
///
/// - Input in cubic meters per hour,
/// - Remove multiple 0;0 calibrations as these are unused points.
///
public Boolean SetCalibrationPoints(List calibPointsCmPerH)
{
if (_magFluxRequestProtocol == null || calibPointsCmPerH == null)
return false;
// remove zeros as this are possibly empty (unused) fields
var removedZeros = calibPointsCmPerH.Where(x => x.dutFlowRate != 0 || x.refFlowRate != 0);
var calibrations = new List();
calibrations.AddRange(removedZeros);
if (calibrations.All(x => x.refFlowRate != 0))
{
calibrations.Add(new Calibration { dutFlowRate = 0, refFlowRate = 0 });
}
// order calibrations ascending as required by MJK
var orderedCalibrations = calibrations.OrderBy(x => x.refFlowRate);
_calibPointsCmPerH.Clear();
_calibPointsCmPerH.AddRange(orderedCalibrations);
var calibPoints = new List();
foreach (var cp in _calibPointsCmPerH)
{
// convert flow rate to liters per second from cubic meters per hour
var calibConverter = new CalibrationPoint
{
ReferenceFlowRate_lps = cp.refFlowRate / 3.6f,
ReportedFlowRate_lps = cp.dutFlowRate / 3.6f
};
calibPoints.Add(calibConverter);
}
var cbs = new CalibrationPoints(calibPoints, calibPoints.Count);
var retVal = _magFluxRequestProtocol.SetCalibrationPoints(cbs);
_logger.Debug(retVal ?
$"{_ident} MagFlux calibration successfully set:\n{cbs}" :
$"{_ident} MagFlux calibration setup failed!");
return retVal;
}
///
/// Wrapper to close the connection to the MagFlux
///
///
///
/// - Initial
///
///
/// - Corrected logic, if !IsConnected = connection is closed
///
public Boolean CloseConnection()
{
if (_magFluxRequestProtocol == null)
return false;
MagFluxAPI.CloseAllConnections();
Thread.Sleep(100);
var retVal = _magFluxRequestProtocol.IsConnected();
_logger.Info(!retVal ?
$"{_ident} Connection is closed" :
$"{_ident} Close connection request failed!");
return retVal;
}
}
}