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; } } }