diff --git a/Common/Hardware/WaterMeter/MechanicalMeter/FM2014/FM2014Core/FM2014.cs b/Common/Hardware/WaterMeter/MechanicalMeter/FM2014/FM2014Core/FM2014.cs index 414187a8..4adc6d71 100644 --- a/Common/Hardware/WaterMeter/MechanicalMeter/FM2014/FM2014Core/FM2014.cs +++ b/Common/Hardware/WaterMeter/MechanicalMeter/FM2014/FM2014Core/FM2014.cs @@ -172,6 +172,11 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core /// public String SerialNumber { get; private set; } + /// + /// Lifetime of the FM2014 in hours + /// + public Int32 Lifetime_h { get; private set; } + /// /// FM2014 identification string e.g. FM2014.112.1 /// @@ -411,6 +416,20 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core return false; } + /// + /// Common handler to publish the response. + /// + /// + /// + /// + /// + /// - Initial. + /// + private static void PublishResponse(FM2014 fm2014, ProcessExecEventArgs processExecEventArgs) + { + fm2014?.OnRawRecordReceived?.Invoke(fm2014, processExecEventArgs); + } + /// /// Read FM2014: /// - Accesses directly to the 'SerialPort.ReadTo', @@ -423,7 +442,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core /// /// - Initial. /// - /// + /// /// - Support for multiple FM2014s. /// private static Boolean Read(CmdName cmdName, FM2014 fm2014, out String responseStr) @@ -456,8 +475,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core var isErrorStr = StatusReturn.Failed == statusReturn ? Resources.StrError + ": " : ""; var response = new CmdResponse(cmdName, $"{isErrorStr}{info} {responseStr}"); - fm2014?.OnRawRecordReceived?.Invoke(fm2014, new ProcessExecEventArgs("", specificInfoObj: response, - statusReturn: statusReturn)); + PublishResponse(fm2014, new ProcessExecEventArgs("", specificInfoObj: response, statusReturn: statusReturn)); return StatusReturn.Failed != statusReturn; } @@ -479,7 +497,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core /// /// - Initial. /// - /// + /// /// - Support for multiple FM2014s. /// private static Boolean Write(CmdName cmdName, FM2014 fm2014, Object dataObj = null) @@ -560,8 +578,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core } var statusReturn = retVal ? StatusReturn.Okay : StatusReturn.Failed; - fm2014.OnRawRecordReceived?.Invoke(fm2014, new ProcessExecEventArgs("", specificInfoObj: response, - statusReturn: statusReturn)); + PublishResponse(fm2014, new ProcessExecEventArgs("", specificInfoObj: response, statusReturn: statusReturn)); return retVal; } @@ -592,7 +609,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core { var response = new CmdResponse(CmdName.CMD_ADDR_PC, $"{Resources.StrCmdRespErrorBroadcast}"); - fm2014.OnRawRecordReceived?.Invoke(fm2014, new ProcessExecEventArgs(Resources.StrError, + PublishResponse(fm2014, new ProcessExecEventArgs(Resources.StrError, specificInfoObj: response, statusReturn: StatusReturn.Failed)); SharedCmdTypeReminderLastCmd = CmdType.NOT_INITIALIZED; @@ -614,7 +631,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core var cmdName = CmdName.CMD_CONNECT; var info = GetCmdInfo(cmdName) + ": " + BROADCAST_ADDRESS; var response = new CmdResponse(cmdName, info); - fm2014.OnRawRecordReceived?.Invoke(fm2014, new ProcessExecEventArgs("", specificInfoObj: response)); + PublishResponse(fm2014, new ProcessExecEventArgs("", specificInfoObj: response)); SharedCmdTypeReminderLastCmd = CmdType.BROADCAST; return true; } @@ -622,7 +639,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core { var response = new CmdResponse(CmdName.CMD_ADDR_PC, $"{Resources.StrCmdRespErrorBroadcast} - {e.Message}"); - fm2014.OnRawRecordReceived?.Invoke(fm2014, new ProcessExecEventArgs(Resources.StrError, + PublishResponse(fm2014, new ProcessExecEventArgs(Resources.StrError, specificInfoObj: response, statusReturn: StatusReturn.Failed)); SharedCmdTypeReminderLastCmd = CmdType.NOT_INITIALIZED; return false; @@ -655,7 +672,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core if (!SharedSerialPort.IsOpen) { response = new CmdResponse(CmdName.CMD_ADDR_PC, $"{Resources.StrCmdRespErrorIndividual}"); - fm2014.OnRawRecordReceived?.Invoke(fm2014, new ProcessExecEventArgs(Resources.StrError, + PublishResponse(fm2014, new ProcessExecEventArgs(Resources.StrError, specificInfoObj: response, statusReturn: StatusReturn.Failed)); SharedCmdTypeReminderLastCmd = CmdType.NOT_INITIALIZED; @@ -677,7 +694,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core var cmdName = CmdName.CMD_CONNECT; var info = GetCmdInfo(cmdName) + ": " + fm2014.AddressStr; response = new CmdResponse(cmdName, info); - fm2014.OnRawRecordReceived?.Invoke(fm2014, new ProcessExecEventArgs("", specificInfoObj: response)); + PublishResponse(fm2014, new ProcessExecEventArgs("", specificInfoObj: response)); fm2014.ConnectResponse = fm2014.ConnectResponse.Replace(ADDR_RECORD_STR, ""); var fields = fm2014.ConnectResponse.Split('.'); fm2014.FwVersion = fields[1]; @@ -689,7 +706,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core { response = new CmdResponse(CmdName.CMD_CONNECT, $"{Resources.StrCmdRespErrorIndividual}" + $": {fm2014.AddressStr}" + $" - {e.Message}"); - fm2014.OnRawRecordReceived?.Invoke(fm2014, new ProcessExecEventArgs(Resources.StrError, + PublishResponse(fm2014, new ProcessExecEventArgs(Resources.StrError, specificInfoObj: response, statusReturn: StatusReturn.Failed)); SharedCmdTypeReminderLastCmd = CmdType.NOT_INITIALIZED; fm2014.IsLoggedOn = false; @@ -697,7 +714,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core } response = new CmdResponse(CmdName.CMD_CONNECT, $"{Resources.StrCmdRespErrorIndividual}"); - fm2014.OnRawRecordReceived?.Invoke(fm2014, new ProcessExecEventArgs(Resources.StrError, + PublishResponse(fm2014, new ProcessExecEventArgs(Resources.StrError, specificInfoObj: response, statusReturn: StatusReturn.Failed)); SharedCmdTypeReminderLastCmd = CmdType.NOT_INITIALIZED; return false; @@ -789,7 +806,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core catch (Exception e) { var response = new CmdResponse(cmdName, e.Message); - OnRawRecordReceived?.Invoke(this, new ProcessExecEventArgs(Resources.StrError, specificInfoObj: response, + PublishResponse(this, new ProcessExecEventArgs(Resources.StrError, specificInfoObj: response, statusReturn: StatusReturn.Failed)); return false; } @@ -841,7 +858,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core out var intValue)) { var response = new CmdResponse(cmdNameRef, infoRef, intValue); - fm2014.OnRawRecordReceived?.Invoke(fm2014, + PublishResponse(fm2014, new ProcessExecEventArgs("", actualProcessMessage: measurementInfoStr, specificInfoObj: response)); } @@ -854,7 +871,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core out var intValue)) { var response = new CmdResponse(cmdNameDut, infoDut, intValue); - fm2014.OnRawRecordReceived?.Invoke(fm2014, + PublishResponse(fm2014, new ProcessExecEventArgs("", actualProcessMessage: measurementInfoStr, specificInfoObj: response)); } @@ -864,7 +881,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core catch (Exception e) { var response = new CmdResponse(cmdName, e.Message); - fm2014?.OnRawRecordReceived?.Invoke(fm2014, new ProcessExecEventArgs(Resources.StrError, + PublishResponse(fm2014, new ProcessExecEventArgs(Resources.StrError, specificInfoObj: response, statusReturn: StatusReturn.Failed)); } } @@ -957,7 +974,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core catch (Exception e) { var response = new CmdResponse(cmdName, e.Message); - OnRawRecordReceived?.Invoke(this, new ProcessExecEventArgs(Resources.StrError, specificInfoObj: response, + PublishResponse(this, new ProcessExecEventArgs(Resources.StrError, specificInfoObj: response, statusReturn: StatusReturn.Failed)); return false; } @@ -992,7 +1009,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core var response = new CmdResponse(cmdName, info, doubleValue: measTolerance * _toleranceRawToPercentScale * signMultiplier, siUnit: SiUnits.GetInfo(SiUnits.SiUnitName.PERCENTAGE_NON_SI)); - fm2014?.OnRawRecordReceived?.Invoke(fm2014, + PublishResponse(fm2014, new ProcessExecEventArgs("", actualProcessMessage: measurementInfo, specificInfoObj: response)); } @@ -1012,7 +1029,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core var response = new CmdResponse(cmdName, info, doubleValue: TMR_RESOLUTION_s * 1000.0 * period, siUnit: "m" + SiUnits.GetInfo(SiUnits.SiUnitName.TIME)); - fm2014?.OnRawRecordReceived?.Invoke(fm2014, + PublishResponse(fm2014, new ProcessExecEventArgs("", actualProcessMessage: measurementInfo, specificInfoObj: response)); @@ -1022,7 +1039,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core response = new CmdResponse(cmdName, info, doubleValue: 1.0 / (TMR_RESOLUTION_s * period), siUnit: SiUnits.GetInfo(SiUnits.SiUnitName.FREQUENCY)); - fm2014?.OnRawRecordReceived?.Invoke(fm2014, + PublishResponse(fm2014, new ProcessExecEventArgs("", actualProcessMessage: measurementInfo, specificInfoObj: response)); @@ -1033,7 +1050,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core info = GetCmdInfo(cmdName); response = new CmdResponse(cmdName, info, doubleValue: flowRate_cm_per_h, siUnit: SiUnits.GetInfo(SiUnits.SiUnitName.FLOW_RATE_NON_SI)); - fm2014?.OnRawRecordReceived?.Invoke(fm2014, + PublishResponse(fm2014, new ProcessExecEventArgs("", actualProcessMessage: measurementInfo, specificInfoObj: response)); } @@ -1054,7 +1071,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core var response = new CmdResponse(cmdName, info, doubleValue: TMR_RESOLUTION_s * 1000.0 * period, siUnit: "m" + SiUnits.GetInfo(SiUnits.SiUnitName.TIME)); - fm2014?.OnRawRecordReceived?.Invoke(fm2014, + PublishResponse(fm2014, new ProcessExecEventArgs("", actualProcessMessage: measurementInfo, specificInfoObj: response)); @@ -1064,7 +1081,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core response = new CmdResponse(cmdName, info, doubleValue: 1.0 / (TMR_RESOLUTION_s * period), siUnit: SiUnits.GetInfo(SiUnits.SiUnitName.FREQUENCY)); - fm2014?.OnRawRecordReceived?.Invoke(fm2014, + PublishResponse(fm2014, new ProcessExecEventArgs("", actualProcessMessage: measurementInfo, specificInfoObj: response)); @@ -1075,7 +1092,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core info = GetCmdInfo(cmdName); response = new CmdResponse(cmdName, info, doubleValue: flowRate_cm_per_h, siUnit: SiUnits.GetInfo(SiUnits.SiUnitName.FLOW_RATE_NON_SI)); - fm2014?.OnRawRecordReceived?.Invoke(fm2014, + PublishResponse(fm2014, new ProcessExecEventArgs("", actualProcessMessage: measurementInfo, specificInfoObj: response)); } @@ -1094,7 +1111,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core // Publish the frequency in [Hz] var response = new CmdResponse(cmdName, info, refFrequency, siUnit: SiUnits.GetInfo(SiUnits.SiUnitName.FREQUENCY)); - fm2014?.OnRawRecordReceived?.Invoke(fm2014, new ProcessExecEventArgs("", + PublishResponse(fm2014, new ProcessExecEventArgs("", actualProcessMessage: measurementInfo, specificInfoObj: response)); @@ -1105,7 +1122,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core info = GetCmdInfo(cmdName); response = new CmdResponse(cmdName, info, doubleValue: RefFlowRate_cm_per_h, siUnit: SiUnits.GetInfo(SiUnits.SiUnitName.FLOW_RATE_NON_SI)); - fm2014?.OnRawRecordReceived?.Invoke(fm2014, + PublishResponse(fm2014, new ProcessExecEventArgs("", actualProcessMessage: measurementInfo, specificInfoObj: response)); } @@ -1114,7 +1131,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core catch (Exception e) { var response = new CmdResponse(cmdName, e.Message); - fm2014?.OnRawRecordReceived?.Invoke(fm2014, new ProcessExecEventArgs(Resources.StrError, + PublishResponse(fm2014, new ProcessExecEventArgs(Resources.StrError, specificInfoObj: response, statusReturn: StatusReturn.Failed)); } } @@ -1182,7 +1199,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core catch (Exception e) { var response = new CmdResponse(cmdName, e.Message); - OnRawRecordReceived?.Invoke(this, new ProcessExecEventArgs(Resources.StrError, specificInfoObj: response, + PublishResponse(this, new ProcessExecEventArgs(Resources.StrError, specificInfoObj: response, statusReturn: StatusReturn.Failed)); } return false; @@ -1206,7 +1223,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core /// /// - Support for multiple FM2014s. /// - private Boolean ReadAloneMeasurementControl(CmdName cmdName) + private Boolean ReadStandAloneMeasurement(CmdName cmdName) { // If the cyclic task has already been started everything is fine if (SharedCyclicMeasSequ != CyclicMeasSequ.IDLE || !IsLoggedOn) @@ -1257,9 +1274,8 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core var info = GetCmdInfo(cmdName); Attenuation = attenuation; var response = new CmdResponse(cmdName, info, Attenuation); - OnRawRecordReceived?.Invoke(this, - new ProcessExecEventArgs("", actualProcessMessage: measurementInfoStr, - specificInfoObj: response)); + PublishResponse(this, new ProcessExecEventArgs("", + actualProcessMessage: measurementInfoStr, specificInfoObj: response)); } } if (str.Contains(StandAlonePartSearchScaleStr)) @@ -1272,7 +1288,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core var info = GetCmdInfo(cmdName); RefToDutScale_norm = value; var response = new CmdResponse(cmdName, info, doubleValue: RefToDutScale_norm); - OnRawRecordReceived?.Invoke(this, + PublishResponse(this, new ProcessExecEventArgs("", actualProcessMessage: measurementInfoStr, specificInfoObj: response)); } @@ -1287,7 +1303,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core var info = GetCmdInfo(cmdName); Dut_pulse_per_cm = value; var response = new CmdResponse(cmdName, info, (Int32)Dut_pulse_per_cm); - OnRawRecordReceived?.Invoke(this, + PublishResponse(this, new ProcessExecEventArgs("", actualProcessMessage: measurementInfoStr, specificInfoObj: response)); // Added 2026-Jan-01 to overcome limitation of max 9999 Impulses per volume @@ -1296,7 +1312,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core // Calculate REF pulses per cubic meter Ref_pulse_per_cm = (UInt32)Math.Round(Dut_pulse_per_cm * RefToDutScale_norm, 1); response = new CmdResponse(cmdName, info, (Int32)Ref_pulse_per_cm); - OnRawRecordReceived?.Invoke(this, + PublishResponse(this, new ProcessExecEventArgs("", actualProcessMessage: measurementInfoStr, specificInfoObj: response)); } @@ -1307,7 +1323,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core catch (Exception e) { var response = new CmdResponse(cmdName, e.Message); - OnRawRecordReceived?.Invoke(this, new ProcessExecEventArgs(Resources.StrError, specificInfoObj: response, + PublishResponse(this, new ProcessExecEventArgs(Resources.StrError, specificInfoObj: response, statusReturn: StatusReturn.Failed)); return false; } @@ -1333,34 +1349,46 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core if (SharedCyclicMeasSequ != CyclicMeasSequ.IDLE) return false; - var cmdCode = GetCmdStr(CmdName.CMD_SERIAL); - const CmdName cmdName = CmdName.CMD_SERIAL; + var cmdName = CmdName.CMD_SERIAL; try { + var cmdCode = GetCmdStr(cmdName); // Read out the serial number of this FM2014 if (!Write(cmdName, this)) { return false; } + IsLoggedOn = true; + if (Read(cmdName, this, out var responseStr)) SerialNumber = responseStr; if (!string.IsNullOrEmpty(SerialNumber)) { SerialNumber = SerialNumber.Replace(cmdCode, ""); - IsLoggedOn = true; } - if (IsLoggedOn) + cmdName = CmdName.CMD_PRINT_STATISTICS; + // Read out the lifetime of this FM2014 + if (!Write(cmdName, this)) { - IsLoggedOn = ReadAloneMeasurementControl(CmdName.CMD_READ_EEP_MEAS_SETUP); + return false; } + + if (Read(cmdName, this, out responseStr)) + { + var cleanedResponse = Regex.Replace(responseStr, "[^0-9]", string.Empty); + if (int.TryParse(cleanedResponse, /*NumberStyles.HexNumber, new CultureInfo("en"),*/ out var intValue)) + Lifetime_h = intValue; + } + + IsLoggedOn = ReadStandAloneMeasurement(CmdName.CMD_READ_EEP_MEAS_SETUP); } catch (Exception e) { var response = new CmdResponse(cmdName, e.Message); - OnRawRecordReceived?.Invoke(this, new ProcessExecEventArgs(Resources.StrError, specificInfoObj: response, + PublishResponse(this, new ProcessExecEventArgs(Resources.StrError, specificInfoObj: response, statusReturn: StatusReturn.Failed)); return false; } @@ -1409,7 +1437,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core // Change the SI unit to ms instead of seconds var response = new CmdResponse(CmdName.CMD_RST_MEAS, infoStr, resetDelayCtr_ms, siUnit: "m" + SiUnits.GetInfo(SiUnits.SiUnitName.TIME)); - OnRawRecordReceived?.Invoke(this, new ProcessExecEventArgs(infoStr, + PublishResponse(this, new ProcessExecEventArgs(infoStr, actualProcessMessage: infoStr, actualProcessPercent: _actualProcessProgress_percent, specificInfoObj: response));