From 20ab81eba7b03ae56082b8ef4825a2b64563cf4e Mon Sep 17 00:00:00 2001 From: Thomas Wiedebusch Date: Fri, 13 Feb 2026 19:26:06 +0100 Subject: [PATCH] FM2014: - optimization --- .../FM2014/FM2014Core/Consts/FM2014CmdDef.cs | 165 +++++++++----- .../FM2014/FM2014Core/FM2014.cs | 201 ++++++++++-------- 2 files changed, 226 insertions(+), 140 deletions(-) diff --git a/Common/Hardware/WaterMeter/MechanicalMeter/FM2014/FM2014Core/Consts/FM2014CmdDef.cs b/Common/Hardware/WaterMeter/MechanicalMeter/FM2014/FM2014Core/Consts/FM2014CmdDef.cs index d12bda30..fc7ecae5 100644 --- a/Common/Hardware/WaterMeter/MechanicalMeter/FM2014/FM2014Core/Consts/FM2014CmdDef.cs +++ b/Common/Hardware/WaterMeter/MechanicalMeter/FM2014/FM2014Core/Consts/FM2014CmdDef.cs @@ -415,6 +415,42 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core.Co } + /// + /// Parameter format to convert the response or the request + /// + public enum ParaFormat + { + /// + /// String taken directly to send or as received + /// + STRING, + + /// + /// Double format + /// + DOUBLE, + + /// + /// Hexadecimal integer + /// + INT_HEX, + + /// + /// Decimal integer + /// + INT_DEZ, + + /// + /// Individual formatting required + /// + INDIVIDUAL, + + /// + /// Parameterless means the command will be sent without any parameter + /// + PARAMETERLESS + } + /// /// Assembly of command information and functional code /// @@ -435,6 +471,11 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core.Co /// public readonly CmdType CmdType; + /// + /// Command parameter style for raw data conversion from response string or for transmission + /// + public readonly ParaFormat ParamFormat; + /// /// Multilingual command information string /// @@ -446,12 +487,15 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core.Co /// Enumerator of command name acronym /// Code being sent to FM2014 as string /// Command type regarding the address (broadcast or individual) and answer + /// parameter format for conversion /// Multilingual command information string - public Cmd(CmdName cmdName, String cmdCodeStr, CmdType cmdType, String cmdInfoStr) + public Cmd(CmdName cmdName, String cmdCodeStr, CmdType cmdType, ParaFormat paraFormat, + String cmdInfoStr) { CmdName = cmdName; CmdCodeStr = cmdCodeStr; CmdType = cmdType; + ParamFormat = paraFormat; CmdInfoStr = cmdInfoStr; } } @@ -512,65 +556,65 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core.Co public static readonly List CmdTbl = new List { // FM2014 control and information - new Cmd(CmdName.CMD_CONNECT, "", CmdType.INDIVIDUAL, Resources.StrCmdMsgConnect), - new Cmd(CmdName.CMD_UNLOCK_SETUP, "&U@", CmdType.INDIVIDUAL, Resources.StrCmdMsgUnlock), - new Cmd(CmdName.CMD_ERASE_SETUP, "&E@", CmdType.INDIVIDUAL, Resources.StrCmdMsgErase), - new Cmd(CmdName.CMD_READ_EEP_MEAS_SETUP, "%D@", CmdType.INDIVIDUAL, Resources.StrCmdMsgReadDefMeasSetup), - new Cmd(CmdName.CMD_READ_RAM_MEAS_SETUP, "%A@", CmdType.INDIVIDUAL, Resources.StrCmdMsgActualDefMeasSetup), - new Cmd(CmdName.CMD_SAVE_RAM_TO_EEP_MEAS_SETUP, "%S@", CmdType.INDIVIDUAL, Resources.StrCmdMsgStoreDefMeasSetup), - new Cmd(CmdName.CMD_BOOT_MODE, "$B@", CmdType.INDIVIDUAL, Resources.StrCmdMsgBootMode), - new Cmd(CmdName.CMD_PRINT_APP_INFO, "?A", CmdType.INDIVIDUAL, Resources.StrCmdMsgPrintAppInfo), - new Cmd(CmdName.CMD_PRINT_BOOT_INFO, "?B", CmdType.INDIVIDUAL, Resources.StrCmdMsgPrintBootInfo), - new Cmd(CmdName.CMD_BAUDRATE_PC, "=BP", CmdType.INDIVIDUAL, Resources.StrCmdMsgBaudrateAll), - new Cmd(CmdName.CMD_GET_VIRTUAL_ADDRESS, " ", CmdType.INDIVIDUAL, Resources.StrCmdMsgGetVirtualAddress), - new Cmd(CmdName.CMD_SERIAL, "#", CmdType.INDIVIDUAL, Resources.StrCmdMsgSerial), - new Cmd(CmdName.CMD_GET_STATUS, UNICODE_ACK, CmdType.INDIVIDUAL, Resources.StrCmdMsgGetStatus), - new Cmd(CmdName.CMD_SET_VIRTUAL_ADDRESS, "N", CmdType.INDIVIDUAL, Resources.StrCmdMsgSetVirtualAddress), - new Cmd(CmdName.CMD_PRINT_STATISTICS, "!", CmdType.INDIVIDUAL, Resources.StrCmdMsgPrintStatistics), + new Cmd(CmdName.CMD_CONNECT, "", CmdType.INDIVIDUAL, ParaFormat.PARAMETERLESS, Resources.StrCmdMsgConnect), + new Cmd(CmdName.CMD_UNLOCK_SETUP, "&U@", CmdType.INDIVIDUAL, ParaFormat.PARAMETERLESS, Resources.StrCmdMsgUnlock), + new Cmd(CmdName.CMD_ERASE_SETUP, "&E@", CmdType.INDIVIDUAL, ParaFormat.PARAMETERLESS, Resources.StrCmdMsgErase), + new Cmd(CmdName.CMD_READ_EEP_MEAS_SETUP, "%D@", CmdType.INDIVIDUAL, ParaFormat.PARAMETERLESS, Resources.StrCmdMsgReadDefMeasSetup), + new Cmd(CmdName.CMD_READ_RAM_MEAS_SETUP, "%A@", CmdType.INDIVIDUAL, ParaFormat.PARAMETERLESS, Resources.StrCmdMsgActualDefMeasSetup), + new Cmd(CmdName.CMD_SAVE_RAM_TO_EEP_MEAS_SETUP, "%S@", CmdType.INDIVIDUAL, ParaFormat.PARAMETERLESS, Resources.StrCmdMsgStoreDefMeasSetup), + new Cmd(CmdName.CMD_BOOT_MODE, "$B@", CmdType.INDIVIDUAL, ParaFormat.PARAMETERLESS, Resources.StrCmdMsgBootMode), + new Cmd(CmdName.CMD_PRINT_APP_INFO, "?A", CmdType.INDIVIDUAL, ParaFormat.PARAMETERLESS, Resources.StrCmdMsgPrintAppInfo), + new Cmd(CmdName.CMD_PRINT_BOOT_INFO, "?B", CmdType.INDIVIDUAL, ParaFormat.PARAMETERLESS, Resources.StrCmdMsgPrintBootInfo), + new Cmd(CmdName.CMD_BAUDRATE_PC, "=BP", CmdType.INDIVIDUAL, ParaFormat.INT_DEZ, Resources.StrCmdMsgBaudrateAll), + new Cmd(CmdName.CMD_GET_VIRTUAL_ADDRESS, " ", CmdType.INDIVIDUAL, ParaFormat.INT_HEX, Resources.StrCmdMsgGetVirtualAddress), + new Cmd(CmdName.CMD_SERIAL, "#", CmdType.INDIVIDUAL, ParaFormat.INT_DEZ, Resources.StrCmdMsgSerial), + new Cmd(CmdName.CMD_GET_STATUS, UNICODE_ACK, CmdType.INDIVIDUAL, ParaFormat.INT_HEX, Resources.StrCmdMsgGetStatus), + new Cmd(CmdName.CMD_SET_VIRTUAL_ADDRESS, "N", CmdType.INDIVIDUAL, ParaFormat.INT_HEX, Resources.StrCmdMsgSetVirtualAddress), + new Cmd(CmdName.CMD_PRINT_STATISTICS, "!", CmdType.INDIVIDUAL, ParaFormat.STRING, Resources.StrCmdMsgPrintStatistics), //measurement reset - new Cmd(CmdName.CMD_RST_MEAS, "R", CmdType.BROADCAST, Resources.StrCmdMsgRstMeas), + new Cmd(CmdName.CMD_RST_MEAS, "R", CmdType.BROADCAST, ParaFormat.PARAMETERLESS, Resources.StrCmdMsgRstMeas), // Double impulse detection settings - new Cmd(CmdName.CMD_SET_DPLS_LOCK_TMR, "S", CmdType.BROADCAST, Resources.StrCmdMsgDplsLockTmr), - new Cmd(CmdName.CMD_SET_DPLS_LOCK_MULT, "s", CmdType.BROADCAST, Resources.StrCmdMsgDplsLockMult), - new Cmd(CmdName.CMD_SET_DBPL_UNLOCK, "G", CmdType.BROADCAST, Resources.StrCmdMsgSetDbplUnlock), + new Cmd(CmdName.CMD_SET_DPLS_LOCK_TMR, "S", CmdType.BROADCAST, ParaFormat.INT_DEZ, Resources.StrCmdMsgDplsLockTmr), + new Cmd(CmdName.CMD_SET_DPLS_LOCK_MULT, "s", CmdType.BROADCAST, ParaFormat.INT_DEZ, Resources.StrCmdMsgDplsLockMult), + new Cmd(CmdName.CMD_SET_DBPL_UNLOCK, "G", CmdType.BROADCAST, ParaFormat.PARAMETERLESS, Resources.StrCmdMsgSetDbplUnlock), // Main measurement pulse settings and readout - new Cmd(CmdName.CMD_DUT_SET_PLS, "H", CmdType.BROADCAST, Resources.StrCmdMsgDutSetPls), - new Cmd(CmdName.CMD_REF_SET_PLS, "M", CmdType.BROADCAST, Resources.StrCmdMsgRefSetPls), - new Cmd(CmdName.CMD_DUT_GET_PLS_RMN, "I", CmdType.INDIVIDUAL, Resources.StrCmdMsgDutGetPlsRmn), - new Cmd(CmdName.CMD_REF_GET_PLS_RMN, "J", CmdType.INDIVIDUAL, Resources.StrCmdMsgRefGetPlsRmn), + new Cmd(CmdName.CMD_DUT_SET_PLS, "H", CmdType.BROADCAST, ParaFormat.INT_HEX, Resources.StrCmdMsgDutSetPls), + new Cmd(CmdName.CMD_REF_SET_PLS, "M", CmdType.BROADCAST, ParaFormat.INT_HEX, Resources.StrCmdMsgRefSetPls), + new Cmd(CmdName.CMD_DUT_GET_PLS_RMN, "I", CmdType.INDIVIDUAL, ParaFormat.INT_HEX, Resources.StrCmdMsgDutGetPlsRmn), + new Cmd(CmdName.CMD_REF_GET_PLS_RMN, "J", CmdType.INDIVIDUAL, ParaFormat.INT_HEX, Resources.StrCmdMsgRefGetPlsRmn), // Pulse counters start, readout and backup - new Cmd(CmdName.CMD_REF_STR_PLS_CTR, "O", CmdType.BROADCAST, Resources.StrCmdMsgRefStrPlsCtr), - new Cmd(CmdName.CMD_DUT_STR_PLS_CTR, "Q", CmdType.BROADCAST, Resources.StrCmdMsgDutStrPlsCtr), - new Cmd(CmdName.CMD_REF_GET_PLS_CTR, "L", CmdType.INDIVIDUAL, Resources.StrCmdMsgRefGetPlsCtr), - new Cmd(CmdName.CMD_DUT_GET_PLS_CTR, "U", CmdType.INDIVIDUAL, Resources.StrCmdMsgDutGetPlsCtr), - new Cmd(CmdName.CMD_REF_GET_PLS_CTR_BU, "l", CmdType.INDIVIDUAL, Resources.StrCmdMsgRefGetPlsCtrBu), - new Cmd(CmdName.CMD_DUT_GET_PLS_CTR_BU, "u", CmdType.INDIVIDUAL, Resources.StrCmdMsgDutGetPlsCtrBu), - new Cmd(CmdName.CMD_REF_DUT_STR_PLS_CTR, "o", CmdType.BROADCAST, Resources.StrCmdMsgRefDutStrPlsCtr), - new Cmd(CmdName.CMD_REF_DUT_BU_PLS_CTR, "q", CmdType.BROADCAST, Resources.StrCmdMsgRefDutBuPlsCtr), + new Cmd(CmdName.CMD_REF_STR_PLS_CTR, "O", CmdType.BROADCAST, ParaFormat.PARAMETERLESS, Resources.StrCmdMsgRefStrPlsCtr), + new Cmd(CmdName.CMD_DUT_STR_PLS_CTR, "Q", CmdType.BROADCAST, ParaFormat.PARAMETERLESS, Resources.StrCmdMsgDutStrPlsCtr), + new Cmd(CmdName.CMD_REF_GET_PLS_CTR, "L", CmdType.INDIVIDUAL, ParaFormat.INT_HEX, Resources.StrCmdMsgRefGetPlsCtr), + new Cmd(CmdName.CMD_DUT_GET_PLS_CTR, "U", CmdType.INDIVIDUAL, ParaFormat.INT_HEX, Resources.StrCmdMsgDutGetPlsCtr), + new Cmd(CmdName.CMD_REF_GET_PLS_CTR_BU, "l", CmdType.INDIVIDUAL, ParaFormat.INT_HEX, Resources.StrCmdMsgRefGetPlsCtrBu), + new Cmd(CmdName.CMD_DUT_GET_PLS_CTR_BU, "u", CmdType.INDIVIDUAL, ParaFormat.INT_HEX, Resources.StrCmdMsgDutGetPlsCtrBu), + new Cmd(CmdName.CMD_REF_DUT_STR_PLS_CTR, "o", CmdType.BROADCAST, ParaFormat.PARAMETERLESS, Resources.StrCmdMsgRefDutStrPlsCtr), + new Cmd(CmdName.CMD_REF_DUT_BU_PLS_CTR, "q", CmdType.BROADCAST, ParaFormat.PARAMETERLESS, Resources.StrCmdMsgRefDutBuPlsCtr), // General measurement setup - new Cmd(CmdName.CMD_REF_SET_SCALE, "K", CmdType.BROADCAST, Resources.StrCmdMsgRefSetScale), - new Cmd(CmdName.CMD_DUT_LPP_SCALE, "V", CmdType.INDIVIDUAL_UNRESPONSIVE, Resources.StrCmdMsgDutLppScale), - new Cmd(CmdName.CMD_REF_LPP_SCALE, "W", CmdType.INDIVIDUAL_UNRESPONSIVE, Resources.StrCmdMsgRefLppScale), - new Cmd(CmdName.CMD_MEAS_SET_ATTN, "T", CmdType.BROADCAST, Resources.StrCmdMsgMeasSetAttn), + new Cmd(CmdName.CMD_REF_SET_SCALE, "K", CmdType.BROADCAST, ParaFormat.INDIVIDUAL, Resources.StrCmdMsgRefSetScale), + new Cmd(CmdName.CMD_DUT_LPP_SCALE, "V", CmdType.INDIVIDUAL_UNRESPONSIVE, ParaFormat.INT_DEZ, Resources.StrCmdMsgDutLppScale), + new Cmd(CmdName.CMD_REF_LPP_SCALE, "W", CmdType.INDIVIDUAL_UNRESPONSIVE, ParaFormat.INT_DEZ, Resources.StrCmdMsgRefLppScale), + new Cmd(CmdName.CMD_MEAS_SET_ATTN, "T", CmdType.BROADCAST, ParaFormat.INT_DEZ, Resources.StrCmdMsgMeasSetAttn), // Measurement result request - new Cmd(CmdName.CMD_DUT_GET_TMR, "X", CmdType.INDIVIDUAL, Resources.StrCmdMsgDutGetTmr), - new Cmd(CmdName.CMD_REF_GET_TMR, "Y", CmdType.INDIVIDUAL, Resources.StrCmdMsgRefGetTmr), - new Cmd(CmdName.CMD_CAL_DUT_TO_REF_TOL, "", CmdType.INDIVIDUAL, Resources.StrCalDutToRefTol), - new Cmd(CmdName.CMD_GET_UDTLC, "Z", CmdType.INDIVIDUAL, Resources.StrCmdMsgGetUdtlc), - new Cmd(CmdName.CMD_GET_DTLC, "z", CmdType.INDIVIDUAL, Resources.StrCmdMsgGetDtlc), - new Cmd(CmdName.CMD_GET_REF_PERIOD, UNICODE_DLE, CmdType.INDIVIDUAL, Resources.StrCmdMsgGetRefPeriod), - new Cmd(CmdName.CMD_GET_DUT_PERIOD, UNICODE_DC1, CmdType.INDIVIDUAL, Resources.StrCmdMsgGetDutPeriod), - new Cmd(CmdName.CMD_GET_REF_FREQU, UNICODE_DC2, CmdType.INDIVIDUAL, Resources.StrCmdMsgGetRefFrequ), - new Cmd(CmdName.CMD_CAL_FREQU_REF_PERIOD, "", CmdType.INDIVIDUAL, Resources.StrCalRefFrequFromRefPeriod), - new Cmd(CmdName.CMD_CAL_FREQU_DUT_PERIOD, "", CmdType.INDIVIDUAL, Resources.StrCalDutFrequFromDutPeriod), - new Cmd(CmdName.CMD_CAL_FLOW_REF_FREQU, "", CmdType.INDIVIDUAL, Resources.StrCalRefFlowRateFromRefFrequ), - new Cmd(CmdName.CMD_CAL_FLOW_REF_PERIOD, "", CmdType.INDIVIDUAL, Resources.StrCalRefFlowRateFromRefPeriod), - new Cmd(CmdName.CMD_CAL_FLOW_DUT_PERIOD, "", CmdType.INDIVIDUAL, Resources.StrCalDutFlowRateFromDutPeriod), + new Cmd(CmdName.CMD_DUT_GET_TMR, "X", CmdType.INDIVIDUAL, ParaFormat.INT_HEX, Resources.StrCmdMsgDutGetTmr), + new Cmd(CmdName.CMD_REF_GET_TMR, "Y", CmdType.INDIVIDUAL, ParaFormat.INT_HEX, Resources.StrCmdMsgRefGetTmr), + new Cmd(CmdName.CMD_CAL_DUT_TO_REF_TOL, "", CmdType.INDIVIDUAL, ParaFormat.DOUBLE, Resources.StrCalDutToRefTol), + new Cmd(CmdName.CMD_GET_UDTLC, "Z", CmdType.INDIVIDUAL, ParaFormat.INDIVIDUAL, Resources.StrCmdMsgGetUdtlc), + new Cmd(CmdName.CMD_GET_DTLC, "z", CmdType.INDIVIDUAL, ParaFormat.INDIVIDUAL, Resources.StrCmdMsgGetDtlc), + new Cmd(CmdName.CMD_GET_REF_PERIOD, UNICODE_DLE, CmdType.INDIVIDUAL, ParaFormat.INT_HEX, Resources.StrCmdMsgGetRefPeriod), + new Cmd(CmdName.CMD_GET_DUT_PERIOD, UNICODE_DC1, CmdType.INDIVIDUAL,ParaFormat.INT_HEX, Resources.StrCmdMsgGetDutPeriod), + new Cmd(CmdName.CMD_GET_REF_FREQU, UNICODE_DC2, CmdType.INDIVIDUAL, ParaFormat.INT_HEX, Resources.StrCmdMsgGetRefFrequ), + new Cmd(CmdName.CMD_CAL_FREQU_REF_PERIOD, "", CmdType.INDIVIDUAL, ParaFormat.DOUBLE, Resources.StrCalRefFrequFromRefPeriod), + new Cmd(CmdName.CMD_CAL_FREQU_DUT_PERIOD, "", CmdType.INDIVIDUAL, ParaFormat.DOUBLE, Resources.StrCalDutFrequFromDutPeriod), + new Cmd(CmdName.CMD_CAL_FLOW_REF_FREQU, "", CmdType.INDIVIDUAL, ParaFormat.DOUBLE, Resources.StrCalRefFlowRateFromRefFrequ), + new Cmd(CmdName.CMD_CAL_FLOW_REF_PERIOD, "", CmdType.INDIVIDUAL, ParaFormat.DOUBLE, Resources.StrCalRefFlowRateFromRefPeriod), + new Cmd(CmdName.CMD_CAL_FLOW_DUT_PERIOD, "", CmdType.INDIVIDUAL, ParaFormat.DOUBLE, Resources.StrCalDutFlowRateFromDutPeriod), // Adjustment, place here Ids which may represent digital numbers from A to F - new Cmd(CmdName.CMD_COR_CURRENT, "C", CmdType.BROADCAST, Resources.StrCmdMsgCorCurrent), - new Cmd(CmdName.CMD_SET_XTR_MAX, "+", CmdType.BROADCAST, Resources.StrCmdMsgSetXtrMax), - new Cmd(CmdName.CMD_SET_XTR_MIN, "-", CmdType.BROADCAST, Resources.StrCmdMsgSetXtrMin), - new Cmd(CmdName.CMD_ADDR_PC, "A", CmdType.INDIVIDUAL, Resources.StrCmdMsgAddrPc) + new Cmd(CmdName.CMD_COR_CURRENT, "C", CmdType.BROADCAST, ParaFormat.PARAMETERLESS, Resources.StrCmdMsgCorCurrent), + new Cmd(CmdName.CMD_SET_XTR_MAX, "+", CmdType.BROADCAST, ParaFormat.PARAMETERLESS, Resources.StrCmdMsgSetXtrMax), + new Cmd(CmdName.CMD_SET_XTR_MIN, "-", CmdType.BROADCAST, ParaFormat.PARAMETERLESS, Resources.StrCmdMsgSetXtrMin), + new Cmd(CmdName.CMD_ADDR_PC, "A", CmdType.INDIVIDUAL, ParaFormat.INT_DEZ, Resources.StrCmdMsgAddrPc) }; /// @@ -721,5 +765,20 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core.Co where ct.CmdName == cmdName select ct.CmdType).FirstOrDefault(); } + + /// + /// Get the parameter format + /// + /// + /// Command type + /// + /// - Initial. + /// + public static ParaFormat GetParaFormat(CmdName cmdName) + { + return (from ct in CmdTbl + where ct.CmdName == cmdName + select ct.ParamFormat).FirstOrDefault(); + } } } diff --git a/Common/Hardware/WaterMeter/MechanicalMeter/FM2014/FM2014Core/FM2014.cs b/Common/Hardware/WaterMeter/MechanicalMeter/FM2014/FM2014Core/FM2014.cs index 9fead8d5..260ae508 100644 --- a/Common/Hardware/WaterMeter/MechanicalMeter/FM2014/FM2014Core/FM2014.cs +++ b/Common/Hardware/WaterMeter/MechanicalMeter/FM2014/FM2014Core/FM2014.cs @@ -197,17 +197,23 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core /// private const Int32 PROCESSES_SAVE_STAND_ALONE_MEASUREMENT = 5; #endregion ---------------------------------------- constants ------------------------------------------------- - #region ------------------------------------------- events ---------------------------------------------------- /// /// Received data feedback /// public event EventHandler OnRawRecordReceived; #endregion ---------------------------------------- events ---------------------------------------------------- - #region ------------------------------------------- static properties ----------------------------------------- + /// + /// Reminder of actual ongoing measurement information + /// + private static String MeasurementInfo { get; set; } + + /// + /// + /// + private static Boolean DisableWriteReadActualProcessIncreasing { get; set; } - private static Boolean _disableWriteReadActualProcessIncreasing; /// /// Shared cancellation token /// @@ -803,7 +809,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core private static void InitActualProcessProgress(Int32? maxInitProcesses = null, Boolean broadcast = false, Boolean disableWriteReadIncrease = false) { - _disableWriteReadActualProcessIncreasing = disableWriteReadIncrease; + DisableWriteReadActualProcessIncreasing = disableWriteReadIncrease; MaxActualProcessProgress = 1; ActualProcessProgress = 0; @@ -820,6 +826,27 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core } } + /// + /// Common handler to publish the response. + /// + /// + /// + /// + /// + /// + /// - Initial. + /// + private static void ResponseEvent(FM2014 fm2014, CmdResponse cmdResponse, + StatusReturn statusReturn = StatusReturn.Unknown) + { + var processExecEventArgs = new ProcessExecEventArgs("", + actualProcessMessage: MeasurementInfo, + actualProcessPercent: ActualProcessProgress, + statusReturn: statusReturn, + specificInfoObj: cmdResponse); + fm2014?.OnRawRecordReceived?.Invoke(fm2014, processExecEventArgs); + } + /// /// Common handler to publish the response. /// @@ -895,7 +922,6 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core } var cmdName = CmdName.CMD_NA; - String measurementInfoStr; // Prepare REF and/or DUT pulse counter measurement, the first call activates if one or both are started! try @@ -904,15 +930,15 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core { case true when firstActiveFm2014.DutPulseCtrOn: cmdName = CmdName.CMD_REF_DUT_STR_PLS_CTR; - measurementInfoStr = Resources.StrMeasMsgPulseCtrRefDut; + MeasurementInfo = Resources.StrMeasMsgPulseCtrRefDut; break; case true: cmdName = CmdName.CMD_REF_STR_PLS_CTR; - measurementInfoStr = Resources.StrMeasMsgPulseCtrRef; + MeasurementInfo = Resources.StrMeasMsgPulseCtrRef; break; default: cmdName = CmdName.CMD_DUT_STR_PLS_CTR; - measurementInfoStr = Resources.StrMeasMsgPulseCtrDut; + MeasurementInfo = Resources.StrMeasMsgPulseCtrDut; break; } @@ -972,32 +998,23 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core { try { - if (SharedCyclicMeasSequ != CyclicMeasSequ.IDLE) - { - if (fm2014.RefPulseCtrOn && Write(cmdNameRef, fm2014)) - { - if (Read(cmdNameRef, fm2014, out var responseStr) && - int.TryParse(responseStr, NumberStyles.HexNumber, new CultureInfo("en"), - out var intValue)) - { - var response = new CmdResponse(cmdNameRef, infoRef, intValue); - PublishResponse(fm2014, - new ProcessExecEventArgs("", actualProcessMessage: measurementInfoStr, - specificInfoObj: response)); - } - } + if (SharedCyclicMeasSequ == CyclicMeasSequ.IDLE) continue; - if (fm2014.DutPulseCtrOn && Write(cmdNameDut, fm2014)) + if (fm2014.RefPulseCtrOn && Write(cmdNameRef, fm2014)) + { + if (Read(cmdNameRef, fm2014, out _, out var intValue)) { - if (Read(cmdNameDut, fm2014, out var responseStr) && - int.TryParse(responseStr, NumberStyles.HexNumber, new CultureInfo("en"), - out var intValue)) - { - var response = new CmdResponse(cmdNameDut, infoDut, intValue); - PublishResponse(fm2014, - new ProcessExecEventArgs("", actualProcessMessage: measurementInfoStr, - specificInfoObj: response)); - } + var response = new CmdResponse(cmdNameRef, infoRef, intValue); + ResponseEvent(fm2014, response); + } + } + + if (fm2014.DutPulseCtrOn && Write(cmdNameDut, fm2014)) + { + if (Read(cmdNameDut, fm2014, out _, out var intValue)) + { + var response = new CmdResponse(cmdNameDut, infoDut, intValue); + ResponseEvent(fm2014, response); } } } @@ -1096,7 +1113,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core } var cmdName = CmdName.CMD_NA; - var measurementInfo = Resources.StrMeasMsgRegulation; + MeasurementInfo = Resources.StrMeasMsgRegulation; // Prepare regulation measurement try { @@ -1145,12 +1162,12 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core var info = GetCmdInfo(cmdName); if (SharedCyclicMeasSequ != CyclicMeasSequ.IDLE && Write(cmdName, fm2014)) { - if (Read(cmdName, fm2014, out responseStr)) + if (Read(cmdName, fm2014, out responseStr, out _)) { // The response contains a sign! var signMultiplier = responseStr.Contains("+") ? 1.0f : -1.0f; var cleanedStr = responseStr.Replace("+", "").Replace("-", ""); - if (int.TryParse(cleanedStr, NumberStyles.HexNumber, + if (int.TryParse(cleanedStr, NumberStyles.HexNumber, new CultureInfo("en"), out var measTolerance)) { fm2014.DutToRefToleranceMeasured_percent = @@ -1158,16 +1175,16 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core var response = new CmdResponse(cmdName, info, doubleValue: fm2014.DutToRefToleranceMeasured_percent, unit: Units.GetInfo(Units.Name.PERCENT)); - + // Check the threshold for OOR - if (Math.Abs((Double)fm2014.DutToRefToleranceMeasured_percent) > + if (Math.Abs((Double)fm2014.DutToRefToleranceMeasured_percent) > fm2014.CurrentOutputToleranceNominalInt_percent) statusReturn = StatusReturn.MeasurementOutOfRange; else statusReturn = StatusReturn.Okay; PublishResponse(fm2014, - new ProcessExecEventArgs("", - actualProcessMessage: measurementInfo, + new ProcessExecEventArgs("", + actualProcessMessage: MeasurementInfo, statusReturn: statusReturn, specificInfoObj: response)); } @@ -1180,7 +1197,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core if (fm2014.RequestDebugInformation && SharedCyclicMeasSequ != CyclicMeasSequ.IDLE && Write(cmdName, fm2014)) { - if (Read(cmdName, fm2014, out responseStr) && + if (Read(cmdName, fm2014, out responseStr, out _) && int.TryParse(responseStr, NumberStyles.HexNumber, new CultureInfo("en"), out var period)) { // Publish the period [ms] @@ -1188,7 +1205,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core doubleValue: TMR_RESOLUTION_s * 1000.0 * period, unit: "m" + Units.GetInfo(Units.Name.TIME_s)); PublishResponse(fm2014, - new ProcessExecEventArgs("", actualProcessMessage: measurementInfo, + new ProcessExecEventArgs("", actualProcessMessage: MeasurementInfo, specificInfoObj: response)); // Publish the frequency in [Hz] @@ -1198,7 +1215,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core doubleValue: 1.0 / (TMR_RESOLUTION_s * period), unit: Units.GetInfo(Units.Name.FREQUENCY_Hz)); PublishResponse(fm2014, - new ProcessExecEventArgs("", actualProcessMessage: measurementInfo, + new ProcessExecEventArgs("", actualProcessMessage: MeasurementInfo, specificInfoObj: response)); // Convert to m³/h (3600 s/h) based on REF pulse rate @@ -1209,7 +1226,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core response = new CmdResponse(cmdName, info, doubleValue: fm2014.RefFlowRate_cm_per_h, unit: Units.GetInfo(Units.Name.FLOW_RATE_cm_per_h)); PublishResponse(fm2014, - new ProcessExecEventArgs("", actualProcessMessage: measurementInfo, + new ProcessExecEventArgs("", actualProcessMessage: MeasurementInfo, specificInfoObj: response)); } } @@ -1222,7 +1239,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core SharedCyclicMeasSequ != CyclicMeasSequ.IDLE && Write(cmdName, fm2014)) { - if (Read(cmdName, fm2014, out responseStr) && + if (Read(cmdName, fm2014, out responseStr, out _) && int.TryParse(responseStr, NumberStyles.HexNumber, new CultureInfo("en"), out var period)) { // Publish the period [ms] @@ -1230,7 +1247,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core doubleValue: TMR_RESOLUTION_s * 1000.0 * period, unit: "m" + Units.GetInfo(Units.Name.TIME_s)); PublishResponse(fm2014, - new ProcessExecEventArgs("", actualProcessMessage: measurementInfo, + new ProcessExecEventArgs("", actualProcessMessage: MeasurementInfo, specificInfoObj: response)); // Publish the frequency in [Hz] @@ -1240,7 +1257,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core doubleValue: 1.0 / (TMR_RESOLUTION_s * period), unit: Units.GetInfo(Units.Name.FREQUENCY_Hz)); PublishResponse(fm2014, - new ProcessExecEventArgs("", actualProcessMessage: measurementInfo, + new ProcessExecEventArgs("", actualProcessMessage: MeasurementInfo, specificInfoObj: response)); // Convert to m³/h (3600 s/h) based on DUT pulse rate @@ -1251,7 +1268,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core response = new CmdResponse(cmdName, info, doubleValue: fm2014.DutFlowRate_cm_per_h, unit: Units.GetInfo(Units.Name.FLOW_RATE_cm_per_h)); PublishResponse(fm2014, - new ProcessExecEventArgs("", actualProcessMessage: measurementInfo, + new ProcessExecEventArgs("", actualProcessMessage: MeasurementInfo, specificInfoObj: response)); } } @@ -1262,7 +1279,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core info = GetCmdInfo(cmdName); if (SharedCyclicMeasSequ != CyclicMeasSequ.IDLE && Write(cmdName, fm2014)) { - if (Read(cmdName, fm2014, out responseStr) && + if (Read(cmdName, fm2014, out responseStr, out _) && int.TryParse(responseStr, NumberStyles.HexNumber, new CultureInfo("en"), out var refFrequency)) { @@ -1270,12 +1287,12 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core if (refFrequency < REF_FREQU_MIN || refFrequency > REF_FREQU_MAX) statusReturn = StatusReturn.MeasurementOutOfRange; else statusReturn = StatusReturn.Okay; - + // Publish the frequency in [Hz] var response = new CmdResponse(cmdName, info, refFrequency, unit: Units.GetInfo(Units.Name.FREQUENCY_Hz)); PublishResponse(fm2014, new ProcessExecEventArgs("", - actualProcessMessage: measurementInfo, + actualProcessMessage: MeasurementInfo, statusReturn: statusReturn, specificInfoObj: response)); @@ -1288,7 +1305,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core unit: Units.GetInfo(Units.Name.FLOW_RATE_cm_per_h)); PublishResponse(fm2014, new ProcessExecEventArgs("", - actualProcessMessage: measurementInfo, + actualProcessMessage: MeasurementInfo, statusReturn: statusReturn, specificInfoObj: response)); } @@ -1381,9 +1398,9 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core } var cmdName = CmdName.CMD_NA; - var measurementInfo = Resources.StrMeasMsgCalibration; + MeasurementInfo = Resources.StrMeasMsgCalibration; - // Prepare pulse time measurement + // Prepare pulse time measurement with all broadcast command - avoid read try { // Check if double pulse deadtime has been set or si switched off @@ -1415,7 +1432,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core if (firstActiveFm2014.RefPulsesRequired != 0) { cmdName = CmdName.CMD_REF_SET_PLS; - if (!Write(cmdName, firstActiveFm2014, firstActiveFm2014.RefPulsesRequired, true)) + if (!Write(cmdName, firstActiveFm2014, firstActiveFm2014.RefPulsesRequired)) { return false; } @@ -1424,7 +1441,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core if (firstActiveFm2014.DutPulsesRequired != 0) { cmdName = CmdName.CMD_DUT_SET_PLS; - if (!Write(cmdName, firstActiveFm2014, firstActiveFm2014.DutPulsesRequired, true)) + if (!Write(cmdName, firstActiveFm2014, firstActiveFm2014.DutPulsesRequired)) { return false; } @@ -1459,21 +1476,21 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core String info; String responseStr; StatusReturn statusReturn; - + // Read the device status to check for timeout between pulses cmdName = CmdName.CMD_GET_STATUS; info = GetCmdInfo(cmdName); if (SharedCyclicMeasSequ != CyclicMeasSequ.IDLE && Write(cmdName, fm2014)) { - if (Read(cmdName, fm2014, out responseStr) && + if (Read(cmdName, fm2014, out responseStr, out _) && int.TryParse(responseStr, NumberStyles.HexNumber, new CultureInfo("en"), out var status)) { info += $": {responseStr}"; - var response = new CmdResponse(cmdName, info); + var response = new CmdResponse(cmdName, info, status); PublishResponse(fm2014, new ProcessExecEventArgs("", actualProcessPercent: ActualProcessProgress_percent, - actualProcessMessage: measurementInfo, specificInfoObj: response)); + actualProcessMessage: MeasurementInfo, specificInfoObj: response)); } } @@ -1487,7 +1504,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core info = GetCmdInfo(cmdName); if (SharedCyclicMeasSequ != CyclicMeasSequ.IDLE && Write(cmdName, fm2014)) { - if (Read(cmdName, fm2014, out responseStr) && + if (Read(cmdName, fm2014, out responseStr, out _) && ushort.TryParse(responseStr, NumberStyles.HexNumber, new CultureInfo("en"), out var pulses)) { @@ -1509,7 +1526,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core PublishResponse(fm2014, new ProcessExecEventArgs("", actualProcessPercent: ActualProcessProgress_percent, statusReturn: statusReturn, - actualProcessMessage: measurementInfo, specificInfoObj: response)); + actualProcessMessage: MeasurementInfo, specificInfoObj: response)); } } } @@ -1525,7 +1542,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core info = GetCmdInfo(cmdName); if (SharedCyclicMeasSequ != CyclicMeasSequ.IDLE && Write(cmdName, fm2014)) { - if (Read(cmdName, fm2014, out responseStr) && + if (Read(cmdName, fm2014, out responseStr, out _) && ushort.TryParse(responseStr, NumberStyles.HexNumber, new CultureInfo("en"), out var pulses)) { @@ -1545,7 +1562,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core var response = new CmdResponse(cmdName, info, pulses); PublishResponse(fm2014, new ProcessExecEventArgs("", - actualProcessMessage: measurementInfo, + actualProcessMessage: MeasurementInfo, statusReturn: statusReturn, specificInfoObj: response)); } @@ -1565,7 +1582,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core info = GetCmdInfo(cmdName); if (SharedCyclicMeasSequ != CyclicMeasSequ.IDLE && Write(cmdName, fm2014)) { - if (Read(cmdName, fm2014, out responseStr) && + if (Read(cmdName, fm2014, out responseStr, out _) && uint.TryParse(responseStr, NumberStyles.HexNumber, new CultureInfo("en"), out var timerTicks)) { @@ -1574,7 +1591,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core var response = new CmdResponse(cmdName, info, doubleValue: fm2014.RefTimeMeasured_s, unit: Units.GetInfo(Units.Name.TIME_s)); PublishResponse(fm2014, new ProcessExecEventArgs("", - actualProcessMessage: measurementInfo, + actualProcessMessage: MeasurementInfo, specificInfoObj: response)); } else @@ -1595,7 +1612,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core info = GetCmdInfo(cmdName); if (SharedCyclicMeasSequ != CyclicMeasSequ.IDLE && Write(cmdName, fm2014)) { - if (Read(cmdName, fm2014, out responseStr) && + if (Read(cmdName, fm2014, out responseStr, out _) && uint.TryParse(responseStr, NumberStyles.HexNumber, new CultureInfo("en"), out var timerTicks)) { @@ -1604,7 +1621,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core var response = new CmdResponse(cmdName, info, doubleValue: fm2014.DutTimeMeasured_s, unit: Units.GetInfo(Units.Name.TIME_s)); PublishResponse(fm2014, new ProcessExecEventArgs("", - actualProcessMessage: measurementInfo, + actualProcessMessage: MeasurementInfo, specificInfoObj: response)); } else @@ -1630,18 +1647,18 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core (1.0 - fm2014.DutTimeMeasured_s / fm2014.RefTimeMeasured_s) * 100.0; // Check the threshold for OOR - if (fm2014.DutToRefToleranceMeasured_percent > + if (fm2014.DutToRefToleranceMeasured_percent > fm2014.DutToRefCalibrationToleranceMax_percent || - fm2014.DutToRefToleranceMeasured_percent < + fm2014.DutToRefToleranceMeasured_percent < fm2014.DutToRefCalibrationToleranceMin_percent) statusReturn = StatusReturn.MeasurementOutOfRange; else statusReturn = StatusReturn.Okay; - + var response = new CmdResponse(cmdName, info, doubleValue: fm2014.DutToRefToleranceMeasured_percent, unit: Units.GetInfo(Units.Name.PERCENT)); PublishResponse(fm2014, new ProcessExecEventArgs("", - actualProcessMessage: measurementInfo, + actualProcessMessage: MeasurementInfo, statusReturn: statusReturn, specificInfoObj: response)); } @@ -1661,7 +1678,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core // Check all remaining DUT and REF pulses are counted on all connected devices and finalize process by // reading out all results - if (RegisteredFm2014s.All(fm2014 => fm2014.MeasurementIsReady || fm2014.ErrorIsDetected || + if (RegisteredFm2014s.All(fm2014 => fm2014.MeasurementIsReady || fm2014.ErrorIsDetected || !fm2014.IsLoggedOn)) { ResetHardwareAllDevices(); @@ -1682,20 +1699,19 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core /// /// /// - /// + /// output of pure pure raw data response from FM2014 + /// output of parsed response to integer value /// - /// + /// /// - Initial. /// - /// - /// - Support for multiple FM2014s. - /// - private static Boolean Read(CmdName cmdName, FM2014 fm2014, out String responseStr) + private static Boolean Read(CmdName cmdName, FM2014 fm2014, out String responseStr, out Int32? intValue) { responseStr = ""; + intValue = null; var info = $"{Resources.StrCommResponse}: {GetCmdInfo(cmdName)}"; var statusReturn = StatusReturn.Failed; - if (!_disableWriteReadActualProcessIncreasing) + if (!DisableWriteReadActualProcessIncreasing) ActualProcessProgress++; // Check for individual command without response @@ -1724,6 +1740,17 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core var response = new CmdResponse(cmdName, $"{isErrorStr}{info} {responseStr}"); PublishResponse(fm2014, new ProcessExecEventArgs("", specificInfoObj: response, statusReturn: statusReturn)); + var numberStyle = NumberStyles.None; + if (GetParaFormat(cmdName) == ParaFormat.INT_HEX) + { + numberStyle = NumberStyles.HexNumber; + } + + if (int.TryParse(responseStr, numberStyle, new CultureInfo("en"), out var intParsedResponse)) + { + intValue = intParsedResponse; + } + return StatusReturn.Failed != statusReturn; } @@ -1740,12 +1767,11 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core /// /// /// - /// /// - /// + /// /// - Initial. /// - private static Boolean Write(CmdName cmdName, FM2014 fm2014, Object dataObj = null, Boolean isHexFormat = false) + private static Boolean Write(CmdName cmdName, FM2014 fm2014, Object dataObj = null) { if (fm2014 == null) return false; @@ -1757,7 +1783,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core SharedCyclicMeasSequ = CyclicMeasSequ.IDLE; return false; } - if (!_disableWriteReadActualProcessIncreasing) + if (!DisableWriteReadActualProcessIncreasing) ActualProcessProgress++; // Initiate communication using the individual or broadcast address @@ -1788,6 +1814,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core var cmdCodeStr = GetCmdStr(cmdName); var info = GetCmdInfo(cmdName) + $": {cmdCodeStr}"; + var isHexFormat = GetParaFormat(cmdName) == ParaFormat.INT_HEX; CmdResponse response; // Without data the command alone needs to be sent if (dataObj == null) @@ -2078,7 +2105,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core var loopCtr = 4; do { - if (Read(cmdName, this, out var responseStr)) + if (Read(cmdName, this, out var responseStr, out _)) responseStrs.Add(responseStr); } while (loopCtr-- > 0); } @@ -2088,7 +2115,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core var loopCtr = 5; do { - if (Read(cmdName, this, out var responseStr)) + if (Read(cmdName, this, out var responseStr, out _)) responseStrs.Add(responseStr); } while (loopCtr-- > 0); } @@ -2267,7 +2294,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core IsLoggedOn = true; - if (Read(cmdName, this, out var responseStr)) + if (Read(cmdName, this, out var responseStr, out _)) SerialNumber = responseStr; if (!string.IsNullOrEmpty(SerialNumber)) @@ -2282,7 +2309,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core return false; } - if (Read(cmdName, this, out responseStr)) + if (Read(cmdName, this, out responseStr, out _)) { var cleanedResponse = Regex.Replace(responseStr, "[^0-9]", string.Empty); if (int.TryParse(cleanedResponse, out var intValue))