FM2014: - message handling improved

This commit is contained in:
Thomas Wiedebusch 2026-02-14 06:21:03 +01:00
parent 20ab81eba7
commit 8998f9058f
3 changed files with 175 additions and 199 deletions

View File

@ -433,12 +433,17 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core.Co
/// <summary>
/// Hexadecimal integer
/// </summary>
INT_HEX,
UINT_HEX,
/// <summary>
/// Hexadecimal byte plus additional sign
/// </summary>
BYTE_HEX_PLUS_SIGN,
/// <summary>
/// Decimal integer
/// </summary>
INT_DEZ,
UINT_DEZ,
/// <summary>
/// Individual formatting required
@ -565,46 +570,46 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core.Co
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_BAUDRATE_PC, "=BP", CmdType.INDIVIDUAL, ParaFormat.UINT_DEZ, Resources.StrCmdMsgBaudrateAll),
new Cmd(CmdName.CMD_GET_VIRTUAL_ADDRESS, " ", CmdType.INDIVIDUAL, ParaFormat.UINT_HEX, Resources.StrCmdMsgGetVirtualAddress),
new Cmd(CmdName.CMD_SERIAL, "#", CmdType.INDIVIDUAL, ParaFormat.UINT_DEZ, Resources.StrCmdMsgSerial),
new Cmd(CmdName.CMD_GET_STATUS, UNICODE_ACK, CmdType.INDIVIDUAL, ParaFormat.UINT_HEX, Resources.StrCmdMsgGetStatus),
new Cmd(CmdName.CMD_SET_VIRTUAL_ADDRESS, "N", CmdType.INDIVIDUAL, ParaFormat.UINT_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, ParaFormat.PARAMETERLESS, Resources.StrCmdMsgRstMeas),
// Double impulse detection settings
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_DPLS_LOCK_TMR, "S", CmdType.BROADCAST, ParaFormat.UINT_DEZ, Resources.StrCmdMsgDplsLockTmr),
new Cmd(CmdName.CMD_SET_DPLS_LOCK_MULT, "s", CmdType.BROADCAST, ParaFormat.UINT_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, 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),
new Cmd(CmdName.CMD_DUT_SET_PLS, "H", CmdType.BROADCAST, ParaFormat.UINT_HEX, Resources.StrCmdMsgDutSetPls),
new Cmd(CmdName.CMD_REF_SET_PLS, "M", CmdType.BROADCAST, ParaFormat.UINT_HEX, Resources.StrCmdMsgRefSetPls),
new Cmd(CmdName.CMD_DUT_GET_PLS_RMN, "I", CmdType.INDIVIDUAL, ParaFormat.UINT_HEX, Resources.StrCmdMsgDutGetPlsRmn),
new Cmd(CmdName.CMD_REF_GET_PLS_RMN, "J", CmdType.INDIVIDUAL, ParaFormat.UINT_HEX, Resources.StrCmdMsgRefGetPlsRmn),
// Pulse counters start, readout and backup
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_GET_PLS_CTR, "L", CmdType.INDIVIDUAL, ParaFormat.UINT_HEX, Resources.StrCmdMsgRefGetPlsCtr),
new Cmd(CmdName.CMD_DUT_GET_PLS_CTR, "U", CmdType.INDIVIDUAL, ParaFormat.UINT_HEX, Resources.StrCmdMsgDutGetPlsCtr),
new Cmd(CmdName.CMD_REF_GET_PLS_CTR_BU, "l", CmdType.INDIVIDUAL, ParaFormat.UINT_HEX, Resources.StrCmdMsgRefGetPlsCtrBu),
new Cmd(CmdName.CMD_DUT_GET_PLS_CTR_BU, "u", CmdType.INDIVIDUAL, ParaFormat.UINT_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, 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),
new Cmd(CmdName.CMD_DUT_LPP_SCALE, "V", CmdType.INDIVIDUAL_UNRESPONSIVE, ParaFormat.UINT_DEZ, Resources.StrCmdMsgDutLppScale),
new Cmd(CmdName.CMD_REF_LPP_SCALE, "W", CmdType.INDIVIDUAL_UNRESPONSIVE, ParaFormat.UINT_DEZ, Resources.StrCmdMsgRefLppScale),
new Cmd(CmdName.CMD_MEAS_SET_ATTN, "T", CmdType.BROADCAST, ParaFormat.UINT_DEZ, Resources.StrCmdMsgMeasSetAttn),
// Measurement result request
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_DUT_GET_TMR, "X", CmdType.INDIVIDUAL, ParaFormat.UINT_HEX, Resources.StrCmdMsgDutGetTmr),
new Cmd(CmdName.CMD_REF_GET_TMR, "Y", CmdType.INDIVIDUAL, ParaFormat.UINT_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_GET_UDTLC, "Z", CmdType.INDIVIDUAL, ParaFormat.BYTE_HEX_PLUS_SIGN, Resources.StrCmdMsgGetUdtlc),
new Cmd(CmdName.CMD_GET_DTLC, "z", CmdType.INDIVIDUAL, ParaFormat.BYTE_HEX_PLUS_SIGN, Resources.StrCmdMsgGetDtlc),
new Cmd(CmdName.CMD_GET_REF_PERIOD, UNICODE_DLE, CmdType.INDIVIDUAL, ParaFormat.UINT_HEX, Resources.StrCmdMsgGetRefPeriod),
new Cmd(CmdName.CMD_GET_DUT_PERIOD, UNICODE_DC1, CmdType.INDIVIDUAL,ParaFormat.UINT_HEX, Resources.StrCmdMsgGetDutPeriod),
new Cmd(CmdName.CMD_GET_REF_FREQU, UNICODE_DC2, CmdType.INDIVIDUAL, ParaFormat.UINT_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),
@ -614,7 +619,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core.Co
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)
new Cmd(CmdName.CMD_ADDR_PC, "A", CmdType.INDIVIDUAL, ParaFormat.UINT_DEZ, Resources.StrCmdMsgAddrPc)
};
/// <summary>
@ -675,7 +680,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core.Co
/// <summary>
/// Optional integer value
/// </summary>
public Int32? IntValue { get; private set; }
public UInt32? IntValue { get; private set; }
/// <summary>
/// Optional double value
@ -695,7 +700,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core.Co
/// <param name="intValue"></param>
/// <param name="doubleValue"></param>
/// <param name="unit"></param>
public CmdResponse(CmdName cmdName, String answerStr, Int32? intValue = null, Double? doubleValue = null,
public CmdResponse(CmdName cmdName, String answerStr, UInt32? intValue = null, Double? doubleValue = null,
String unit = "")
{
CmdName = cmdName;

View File

@ -386,17 +386,18 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core
/// </summary>
public Boolean UseDampedTolerance { get; set; }
private UInt16 _refPulsesRequired;
private UInt32 _refPulsesRequired;
/// <summary>
/// Required REF pulses for time measurement.
/// </summary>
public UInt16 RefPulsesRequired
public UInt32 RefPulsesRequired
{
get => _refPulsesRequired;
private set
{
// Check limits and equality
if (value < PULSES_TIME_MEASUREMENT_INPUT_MIN ||
value > PULSES_TIME_MEASUREMENT_INPUT_MAX ||
value == _refPulsesRequired)
return;
@ -404,17 +405,18 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core
}
}
private UInt16 _dutPulsesRequired;
private UInt32 _dutPulsesRequired;
/// <summary>
/// Required DUT pulses for time measurement.
/// </summary>
public UInt16 DutPulsesRequired
public UInt32 DutPulsesRequired
{
get => _dutPulsesRequired;
private set
{
// Check limits and equality
if (value < PULSES_TIME_MEASUREMENT_INPUT_MIN ||
value > PULSES_TIME_MEASUREMENT_INPUT_MAX ||
value == _dutPulsesRequired)
return;
@ -738,7 +740,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core
do
{
// Change the SI unit to ms instead of seconds
var response = new CmdResponse(CmdName.CMD_RST_MEAS, infoStr, resetDelayCtr_ms,
var response = new CmdResponse(CmdName.CMD_RST_MEAS, infoStr, (UInt32)resetDelayCtr_ms,
unit: "m" + Units.GetInfo(Units.Name.TIME_s));
PublishResponse(firstActiveFm2014, new ProcessExecEventArgs("",
actualProcessMessage: infoStr,
@ -836,12 +838,12 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core
/// <remarks date="2026-Feb-13" author="Thomas Wiedebusch">
/// - Initial.
/// </remarks>
private static void ResponseEvent(FM2014 fm2014, CmdResponse cmdResponse,
private static void ResponseEvent(FM2014 fm2014, CmdResponse cmdResponse,
StatusReturn statusReturn = StatusReturn.Unknown)
{
var processExecEventArgs = new ProcessExecEventArgs("",
actualProcessMessage: MeasurementInfo,
actualProcessPercent: ActualProcessProgress,
actualProcessPercent: ActualProcessProgress_percent,
statusReturn: statusReturn,
specificInfoObj: cmdResponse);
fm2014?.OnRawRecordReceived?.Invoke(fm2014, processExecEventArgs);
@ -886,7 +888,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core
/// <returns>true if initialization successfully executed or
/// <see cref="SharedCyclicMeasSequ"/> marks the already started cyclic requests
/// for all registered FM2014s</returns>
/// <remarks date="2026-Jan-10..Feb-11" author="Thomas Wiedebusch">
/// <remarks date="2026-Jan-10..Feb-14" author="Thomas Wiedebusch">
/// - Initial.
/// </remarks>
public static Boolean PulseCounterMeasurement(Boolean refPulseCtrOn, Boolean dutPulseCtrOn)
@ -1002,7 +1004,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core
if (fm2014.RefPulseCtrOn && Write(cmdNameRef, fm2014))
{
if (Read(cmdNameRef, fm2014, out _, out var intValue))
if (Read(cmdNameRef, fm2014, out _, out var intValue, out _))
{
var response = new CmdResponse(cmdNameRef, infoRef, intValue);
ResponseEvent(fm2014, response);
@ -1011,7 +1013,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core
if (fm2014.DutPulseCtrOn && Write(cmdNameDut, fm2014))
{
if (Read(cmdNameDut, fm2014, out _, out var intValue))
if (Read(cmdNameDut, fm2014, out _, out var intValue, out _))
{
var response = new CmdResponse(cmdNameDut, infoDut, intValue);
ResponseEvent(fm2014, response);
@ -1068,7 +1070,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core
/// <param name="doublePulseDeadtime_ms"></param>
/// <param name="currentOutputAttenuation"></param>
/// <returns></returns>
/// <remarks date="2026-Jan-14..Feb-11" author="Thomas Wiedebusch">
/// <remarks date="2026-Jan-14..Feb-14" author="Thomas Wiedebusch">
/// - Initial.
/// </remarks>
public static Boolean RegulationMeasurement(UInt32 refPulses_per_cm, UInt16 dutPulses_per_cm,
@ -1156,38 +1158,26 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core
{
// Read out the damped/undamped tolerance and convert the raw value (0, +/-1..255 digits) to the
// tolerance in percent depending on the setup to 3 % (3.3) of 5 % (5.5)
String responseStr;
StatusReturn statusReturn;
cmdName = fm2014.UseDampedTolerance ? CmdName.CMD_GET_DTLC : CmdName.CMD_GET_UDTLC;
var info = GetCmdInfo(cmdName);
if (SharedCyclicMeasSequ != CyclicMeasSequ.IDLE && Write(cmdName, fm2014))
{
if (Read(cmdName, fm2014, out responseStr, out _))
if (Read(cmdName, fm2014, out _, out _, out var doubleValue))
{
// The response contains a sign!
var signMultiplier = responseStr.Contains("+") ? 1.0f : -1.0f;
var cleanedStr = responseStr.Replace("+", "").Replace("-", "");
if (int.TryParse(cleanedStr, NumberStyles.HexNumber,
new CultureInfo("en"), out var measTolerance))
{
fm2014.DutToRefToleranceMeasured_percent =
measTolerance * fm2014.CurrentOutputToleranceNominalToRealScale * signMultiplier;
var response = new CmdResponse(cmdName, info,
doubleValue: fm2014.DutToRefToleranceMeasured_percent,
unit: Units.GetInfo(Units.Name.PERCENT));
fm2014.DutToRefToleranceMeasured_percent = doubleValue *
fm2014.CurrentOutputToleranceNominalToRealScale;
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) >
fm2014.CurrentOutputToleranceNominalInt_percent)
statusReturn = StatusReturn.MeasurementOutOfRange;
else statusReturn = StatusReturn.Okay;
// Check the threshold for OOR
if (Math.Abs((Double)fm2014.DutToRefToleranceMeasured_percent) >
fm2014.CurrentOutputToleranceNominalInt_percent)
statusReturn = StatusReturn.MeasurementOutOfRange;
else statusReturn = StatusReturn.Okay;
PublishResponse(fm2014,
new ProcessExecEventArgs("",
actualProcessMessage: MeasurementInfo,
statusReturn: statusReturn,
specificInfoObj: response));
}
ResponseEvent(fm2014, response, statusReturn);
}
}
@ -1197,16 +1187,13 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core
if (fm2014.RequestDebugInformation && SharedCyclicMeasSequ != CyclicMeasSequ.IDLE &&
Write(cmdName, fm2014))
{
if (Read(cmdName, fm2014, out responseStr, out _) &&
int.TryParse(responseStr, NumberStyles.HexNumber, new CultureInfo("en"), out var period))
if (Read(cmdName, fm2014, out _, out var period, out _))
{
// Publish the period [ms]
var response = new CmdResponse(cmdName, info,
doubleValue: TMR_RESOLUTION_s * 1000.0 * period,
unit: "m" + Units.GetInfo(Units.Name.TIME_s));
PublishResponse(fm2014,
new ProcessExecEventArgs("", actualProcessMessage: MeasurementInfo,
specificInfoObj: response));
ResponseEvent(fm2014, response);
// Publish the frequency in [Hz]
cmdName = CmdName.CMD_CAL_FREQU_REF_PERIOD;
@ -1214,20 +1201,16 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core
response = new CmdResponse(cmdName, info,
doubleValue: 1.0 / (TMR_RESOLUTION_s * period),
unit: Units.GetInfo(Units.Name.FREQUENCY_Hz));
PublishResponse(fm2014,
new ProcessExecEventArgs("", actualProcessMessage: MeasurementInfo,
specificInfoObj: response));
ResponseEvent(fm2014, response);
// Convert to m³/h (3600 s/h) based on REF pulse rate
fm2014.RefFlowRate_cm_per_h = 3600.0 / (period * TMR_RESOLUTION_s) / fm2014.RefPulses_per_cm;
fm2014.RefFlowRate_cm_per_h = 3600.0 / ((Double)period * TMR_RESOLUTION_s) / fm2014.RefPulses_per_cm;
// Publish the calculated flow rate [m³/h]
cmdName = CmdName.CMD_CAL_FLOW_REF_PERIOD;
info = GetCmdInfo(cmdName);
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,
specificInfoObj: response));
ResponseEvent(fm2014, response);
}
}
@ -1239,16 +1222,13 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core
SharedCyclicMeasSequ != CyclicMeasSequ.IDLE &&
Write(cmdName, fm2014))
{
if (Read(cmdName, fm2014, out responseStr, out _) &&
int.TryParse(responseStr, NumberStyles.HexNumber, new CultureInfo("en"), out var period))
if (Read(cmdName, fm2014, out _, out var period, out _))
{
// Publish the period [ms]
var response = new CmdResponse(cmdName, info,
doubleValue: TMR_RESOLUTION_s * 1000.0 * period,
unit: "m" + Units.GetInfo(Units.Name.TIME_s));
PublishResponse(fm2014,
new ProcessExecEventArgs("", actualProcessMessage: MeasurementInfo,
specificInfoObj: response));
ResponseEvent(fm2014, response);
// Publish the frequency in [Hz]
cmdName = CmdName.CMD_CAL_FREQU_DUT_PERIOD;
@ -1256,32 +1236,25 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core
response = new CmdResponse(cmdName, info,
doubleValue: 1.0 / (TMR_RESOLUTION_s * period),
unit: Units.GetInfo(Units.Name.FREQUENCY_Hz));
PublishResponse(fm2014,
new ProcessExecEventArgs("", actualProcessMessage: MeasurementInfo,
specificInfoObj: response));
ResponseEvent(fm2014, response);
// Convert to m³/h (3600 s/h) based on DUT pulse rate
fm2014.DutFlowRate_cm_per_h = 3600.0 / (period * TMR_RESOLUTION_s) / fm2014.DutPulses_per_cm;
fm2014.DutFlowRate_cm_per_h = 3600.0 / ((Double)period * TMR_RESOLUTION_s) / fm2014.DutPulses_per_cm;
// Publish the calculated flow rate [m³/h]
cmdName = CmdName.CMD_CAL_FLOW_DUT_PERIOD;
info = GetCmdInfo(cmdName);
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,
specificInfoObj: response));
ResponseEvent(fm2014, response);
}
}
// Read the REF frequency [Hz] directly and calculate the flow rate [m³/h] based on this frequency
cmdName = CmdName.CMD_GET_REF_FREQU;
info = GetCmdInfo(cmdName);
if (SharedCyclicMeasSequ != CyclicMeasSequ.IDLE && Write(cmdName, fm2014))
{
if (Read(cmdName, fm2014, out responseStr, out _) &&
int.TryParse(responseStr, NumberStyles.HexNumber, new CultureInfo("en"),
out var refFrequency))
if (Read(cmdName, fm2014, out _, out var refFrequency, out _))
{
// Check the threshold for OOR
if (refFrequency < REF_FREQU_MIN || refFrequency > REF_FREQU_MAX)
@ -1289,25 +1262,18 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core
else statusReturn = StatusReturn.Okay;
// Publish the frequency in [Hz]
var response = new CmdResponse(cmdName, info, refFrequency,
var response = new CmdResponse(cmdName, info, (UInt32)refFrequency,
unit: Units.GetInfo(Units.Name.FREQUENCY_Hz));
PublishResponse(fm2014, new ProcessExecEventArgs("",
actualProcessMessage: MeasurementInfo,
statusReturn: statusReturn,
specificInfoObj: response));
ResponseEvent(fm2014, response, statusReturn);
// Convert to m³/h (3600 s/h) and save the value
fm2014.RefFlowRate_cm_per_h = 3600.0 * refFrequency / fm2014.RefPulses_per_cm;
fm2014.RefFlowRate_cm_per_h = 3600.0 * (Double)refFrequency / fm2014.RefPulses_per_cm;
// Publish the calculated flow rate [m³/h]
cmdName = CmdName.CMD_CAL_FLOW_REF_FREQU;
info = GetCmdInfo(cmdName);
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,
statusReturn: statusReturn,
specificInfoObj: response));
ResponseEvent(fm2014, response, statusReturn);
}
}
}
@ -1356,7 +1322,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core
/// <param name="doublePulseDeadtime_ms">0 if double impulse deadtime detection is off</param>
/// </summary>
/// <returns></returns>
/// <remarks date="2026-Jan-14..Feb-13" author="Thomas Wiedebusch">
/// <remarks date="2026-Jan-14..Feb-14" author="Thomas Wiedebusch">
/// - Initial.
/// </remarks>
public static Boolean PulseTimeMeasurement(UInt16? refPulsesRequired = null, UInt16? dutPulsesRequired = null,
@ -1463,9 +1429,9 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core
// Set up the progress maximal counter value base on required pulses for REF or DUT
InitActualProcessProgress(
firstActiveFm2014.RefPulsesRequired != 0
? firstActiveFm2014.RefPulsesRequired
: firstActiveFm2014.DutPulsesRequired, disableWriteReadIncrease: true);
(Int32)firstActiveFm2014.RefPulsesRequired != 0
? (Int32)firstActiveFm2014.RefPulsesRequired
: (Int32)firstActiveFm2014.DutPulsesRequired, disableWriteReadIncrease: true);
do
{
@ -1473,24 +1439,19 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core
{
try
{
String info;
String responseStr;
StatusReturn statusReturn;
// Read the device status to check for timeout between pulses
cmdName = CmdName.CMD_GET_STATUS;
info = GetCmdInfo(cmdName);
var info = GetCmdInfo(cmdName);
if (SharedCyclicMeasSequ != CyclicMeasSequ.IDLE && Write(cmdName, fm2014))
{
if (Read(cmdName, fm2014, out responseStr, out _) &&
int.TryParse(responseStr, NumberStyles.HexNumber, new CultureInfo("en"),
out var status))
if (Read(cmdName, fm2014, out responseStr, out var status, out _))
{
info += $": {responseStr}";
var response = new CmdResponse(cmdName, info, status);
PublishResponse(fm2014, new ProcessExecEventArgs("",
actualProcessPercent: ActualProcessProgress_percent,
actualProcessMessage: MeasurementInfo, specificInfoObj: response));
ResponseEvent(fm2014, response);
}
}
@ -1498,17 +1459,15 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core
if (fm2014.RefPulsesRequired != 0)
{
// Feed the progress counter
ActualProcessProgress = firstActiveFm2014.RefPulsesRequired -
ActualProcessProgress = (Int32)firstActiveFm2014.RefPulsesRequired -
firstActiveFm2014.RefPulsesRemaining;
cmdName = CmdName.CMD_REF_GET_PLS_RMN;
info = GetCmdInfo(cmdName);
if (SharedCyclicMeasSequ != CyclicMeasSequ.IDLE && Write(cmdName, fm2014))
{
if (Read(cmdName, fm2014, out responseStr, out _) &&
ushort.TryParse(responseStr, NumberStyles.HexNumber, new CultureInfo("en"),
out var pulses))
if (Read(cmdName, fm2014, out responseStr, out var pulses, out _))
{
fm2014.RefPulsesRemaining = pulses;
fm2014.RefPulsesRemaining = (UInt16)pulses;
// Check if remaining pulses are going to count down based on required pulses
if (RegisteredFm2014s.Any(fm => fm.RefPulsesRemaining * 1.1 < fm.RefPulsesRequired) &&
@ -1523,10 +1482,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core
}
var response = new CmdResponse(cmdName, info, pulses);
PublishResponse(fm2014, new ProcessExecEventArgs("",
actualProcessPercent: ActualProcessProgress_percent,
statusReturn: statusReturn,
actualProcessMessage: MeasurementInfo, specificInfoObj: response));
ResponseEvent(fm2014, response, statusReturn);
}
}
}
@ -1536,17 +1492,15 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core
{
// Feed the progress counter but only if not done for REF pulses
if (firstActiveFm2014.RefPulsesRequired == 0)
ActualProcessProgress = firstActiveFm2014.DutPulsesRequired -
ActualProcessProgress = (Int32)firstActiveFm2014.DutPulsesRequired -
firstActiveFm2014.DutPulsesRemaining;
cmdName = CmdName.CMD_DUT_GET_PLS_RMN;
info = GetCmdInfo(cmdName);
if (SharedCyclicMeasSequ != CyclicMeasSequ.IDLE && Write(cmdName, fm2014))
{
if (Read(cmdName, fm2014, out responseStr, out _) &&
ushort.TryParse(responseStr, NumberStyles.HexNumber, new CultureInfo("en"),
out var pulses))
if (Read(cmdName, fm2014, out responseStr, out var pulses, out _))
{
fm2014.DutPulsesRemaining = pulses;
fm2014.DutPulsesRemaining = (UInt16)pulses;
// Check if remaining pulses are going to count down based on required pulses
if (RegisteredFm2014s.Any(fm => fm.DutPulsesRemaining * 1.1 < fm.DutPulsesRequired) &&
@ -1561,10 +1515,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core
}
var response = new CmdResponse(cmdName, info, pulses);
PublishResponse(fm2014, new ProcessExecEventArgs("",
actualProcessMessage: MeasurementInfo,
statusReturn: statusReturn,
specificInfoObj: response));
ResponseEvent(fm2014, response, statusReturn);
}
}
}
@ -1582,27 +1533,19 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core
info = GetCmdInfo(cmdName);
if (SharedCyclicMeasSequ != CyclicMeasSequ.IDLE && Write(cmdName, fm2014))
{
if (Read(cmdName, fm2014, out responseStr, out _) &&
uint.TryParse(responseStr, NumberStyles.HexNumber, new CultureInfo("en"),
out var timerTicks))
if (Read(cmdName, fm2014, out responseStr, out var timerTicks, out _))
{
// Is converting to a real time in seconds
fm2014.RefTimerTicksMeasured = timerTicks;
fm2014.RefTimerTicksMeasured = (UInt16)timerTicks;
var response = new CmdResponse(cmdName, info, doubleValue: fm2014.RefTimeMeasured_s,
unit: Units.GetInfo(Units.Name.TIME_s));
PublishResponse(fm2014, new ProcessExecEventArgs("",
actualProcessMessage: MeasurementInfo,
specificInfoObj: response));
ResponseEvent(fm2014, response);
}
else
{
retVal = false;
}
}
else
{
retVal = false;
}
}
// Read the DUT timer ticks for the counted pulses
@ -1612,27 +1555,19 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core
info = GetCmdInfo(cmdName);
if (SharedCyclicMeasSequ != CyclicMeasSequ.IDLE && Write(cmdName, fm2014))
{
if (Read(cmdName, fm2014, out responseStr, out _) &&
uint.TryParse(responseStr, NumberStyles.HexNumber, new CultureInfo("en"),
out var timerTicks))
if (Read(cmdName, fm2014, out responseStr, out var timerTicks, out _))
{
// Is converting to a real time in seconds
fm2014.DutTimerTicksMeasured = timerTicks;
fm2014.DutTimerTicksMeasured = (UInt16)timerTicks;
var response = new CmdResponse(cmdName, info, doubleValue: fm2014.DutTimeMeasured_s,
unit: Units.GetInfo(Units.Name.TIME_s));
PublishResponse(fm2014, new ProcessExecEventArgs("",
actualProcessMessage: MeasurementInfo,
specificInfoObj: response));
ResponseEvent(fm2014, response);
}
else
{
retVal = false;
}
}
else
{
retVal = false;
}
}
// Calculate the DUT to REF tolerance if both timer had been active
@ -1657,10 +1592,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core
var response = new CmdResponse(cmdName, info,
doubleValue: fm2014.DutToRefToleranceMeasured_percent,
unit: Units.GetInfo(Units.Name.PERCENT));
PublishResponse(fm2014, new ProcessExecEventArgs("",
actualProcessMessage: MeasurementInfo,
statusReturn: statusReturn,
specificInfoObj: response));
ResponseEvent(fm2014, response, statusReturn);
}
}
@ -1692,6 +1624,55 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core
return true;
}
/// <summary>
/// Common routine to parse the response from the FM2014
/// </summary>
/// <param name="cmdName"></param>
/// <param name="responseStr"></param>
/// <param name="intValue"></param>
/// <param name="doubleValue"></param>
/// <returns></returns>
/// <remarks date="2026-Feb-14" author="Thomas Wiedebusch">
/// - Initial.
/// </remarks>
private static StatusReturn ParseResponse(CmdName cmdName, String responseStr, out UInt32? intValue,
out Double? doubleValue)
{
intValue = null;
doubleValue = null;
var statusReturn = StatusReturn.Unknown;
var numberStyle = NumberStyles.None;
var paraFormat = GetParaFormat(cmdName);
if (paraFormat == ParaFormat.UINT_HEX || paraFormat == ParaFormat.BYTE_HEX_PLUS_SIGN)
{
numberStyle = NumberStyles.HexNumber;
}
switch (paraFormat)
{
case ParaFormat.BYTE_HEX_PLUS_SIGN:
// The response contains a sign!
var signMultiplier = responseStr.Contains("+") ? 1.0 : -1.0;
var cleanedStr = responseStr.Replace("+", "").Replace("-", "");
if (uint.TryParse(cleanedStr, numberStyle, new CultureInfo("en"), out var intValueParsed))
{
doubleValue = intValueParsed * signMultiplier;
}
break;
case ParaFormat.UINT_HEX:
case ParaFormat.UINT_DEZ:
if (uint.TryParse(responseStr, numberStyle, new CultureInfo("en"), out intValueParsed))
{
intValue = intValueParsed;
statusReturn = StatusReturn.Okay;
}
break;
}
return statusReturn;
}
/// <summary>
/// Read FM2014:
/// - Accesses directly to the 'SerialPort.ReadTo',
@ -1701,14 +1682,17 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core
/// <param name="fm2014"></param>
/// <param name="responseStr">output of pure pure raw data response from FM2014</param>
/// <param name="intValue">output of parsed response to integer value</param>
/// <param name="doubleValue"></param>
/// <returns></returns>
/// <remarks date="2026-Jan-23..Feb-13" author="Thomas Wiedebusch">
/// <remarks date="2026-Jan-23..Feb-14" author="Thomas Wiedebusch">
/// - Initial.
/// </remarks>
private static Boolean Read(CmdName cmdName, FM2014 fm2014, out String responseStr, out Int32? intValue)
private static Boolean Read(CmdName cmdName, FM2014 fm2014, out String responseStr, out UInt32? intValue,
out Double? doubleValue)
{
responseStr = "";
intValue = null;
doubleValue = null;
var info = $"{Resources.StrCommResponse}: {GetCmdInfo(cmdName)}";
var statusReturn = StatusReturn.Failed;
if (!DisableWriteReadActualProcessIncreasing)
@ -1738,19 +1722,11 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core
var isErrorStr = StatusReturn.Failed == statusReturn ? Resources.StrError + ": " : "";
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;
}
// Publish the raw response for logging
ResponseEvent(fm2014, response, statusReturn);
// Parse the raw value to get a useful result
statusReturn = ParseResponse(cmdName, responseStr, out intValue, out doubleValue);
return StatusReturn.Failed != statusReturn;
}
@ -1768,7 +1744,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core
/// <param name="fm2014"></param>
/// <param name="dataObj"></param>
/// <returns></returns>
/// <remarks date="2026-Jan-12..Feb-13" author="Thomas Wiedebusch">
/// <remarks date="2026-Jan-12..Feb-14" author="Thomas Wiedebusch">
/// - Initial.
/// </remarks>
private static Boolean Write(CmdName cmdName, FM2014 fm2014, Object dataObj = null)
@ -1814,7 +1790,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;
var isHexFormat = GetParaFormat(cmdName) == ParaFormat.UINT_HEX;
CmdResponse response;
// Without data the command alone needs to be sent
if (dataObj == null)
@ -1835,7 +1811,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core
}
// The data contains the preceding setup, the command code and string delimiter will be added here
else if (dataObj is UInt16 || dataObj is Byte)
else if (dataObj is UInt16 || dataObj is UInt32 || dataObj is Byte)
{
var valueStr = isHexFormat ? $"{dataObj:X}{cmdCodeStr}" : $"{dataObj}{cmdCodeStr}";
SharedSerialPort.Write($"{valueStr}{END_OF_STR}");
@ -1853,7 +1829,8 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core
}
var statusReturn = retVal ? StatusReturn.Okay : StatusReturn.Failed;
PublishResponse(fm2014, new ProcessExecEventArgs("", specificInfoObj: response, statusReturn: statusReturn));
ResponseEvent(fm2014, response, statusReturn);
return retVal;
}
@ -2095,7 +2072,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core
}
try
{
var measurementInfoStr = Resources.StrMeasMsgStanaloneRegulation;
MeasurementInfo = Resources.StrMeasMsgStanaloneRegulation;
var responseStrs = new List<String>();
if (Write(cmdName, this))
{
@ -2105,7 +2082,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core
var loopCtr = 4;
do
{
if (Read(cmdName, this, out var responseStr, out _))
if (Read(cmdName, this, out var responseStr, out _, out _))
responseStrs.Add(responseStr);
} while (loopCtr-- > 0);
}
@ -2115,7 +2092,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core
var loopCtr = 5;
do
{
if (Read(cmdName, this, out var responseStr, out _))
if (Read(cmdName, this, out var responseStr, out _, out _))
responseStrs.Add(responseStr);
} while (loopCtr-- > 0);
}
@ -2126,14 +2103,14 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core
{
var strCleaned = Regex.Replace(str, "[^0-9]", string.Empty);
if (byte.TryParse(strCleaned, out var attenuation) &&
attenuation > 0 && attenuation <= 9)
attenuation >= CURRENT_OUTPUT_ATTENUATION_MIN &&
attenuation <= CURRENT_OUTPUT_ATTENUATION_MAX)
{
cmdName = CmdName.CMD_MEAS_SET_ATTN;
var info = GetCmdInfo(cmdName);
CurrentOutputAttenuation = attenuation;
var response = new CmdResponse(cmdName, info, CurrentOutputAttenuation);
PublishResponse(this, new ProcessExecEventArgs("",
actualProcessMessage: measurementInfoStr, specificInfoObj: response));
ResponseEvent(this, response);
}
}
if (str.Contains(StandAlonePartSearchScaleStr))
@ -2146,9 +2123,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);
PublishResponse(this,
new ProcessExecEventArgs("", actualProcessMessage: measurementInfoStr,
specificInfoObj: response));
ResponseEvent(this, response);
}
}
@ -2161,18 +2136,14 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core
var info = GetCmdInfo(cmdName);
DutPulses_per_cm = value;
var response = new CmdResponse(cmdName, info, DutPulses_per_cm);
PublishResponse(this,
new ProcessExecEventArgs("", actualProcessMessage: measurementInfoStr,
specificInfoObj: response));
ResponseEvent(this, response);
// Added 2026-Jan-01 to overcome limitation of max 9999 Impulses per volume
cmdName = CmdName.CMD_REF_LPP_SCALE;
info = GetCmdInfo(cmdName);
// Calculate REF pulses per cubic meter
RefPulses_per_cm = (UInt32)Math.Round(DutPulses_per_cm * RefToDutScale_norm, 1);
response = new CmdResponse(cmdName, info, (Int32)RefPulses_per_cm);
PublishResponse(this,
new ProcessExecEventArgs("", actualProcessMessage: measurementInfoStr,
specificInfoObj: response));
response = new CmdResponse(cmdName, info, RefPulses_per_cm);
ResponseEvent(this, response);
}
}
}
@ -2294,7 +2265,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core
IsLoggedOn = true;
if (Read(cmdName, this, out var responseStr, out _))
if (Read(cmdName, this, out var responseStr, out _, out _))
SerialNumber = responseStr;
if (!string.IsNullOrEmpty(SerialNumber))
@ -2309,7 +2280,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core
return false;
}
if (Read(cmdName, this, out responseStr, out _))
if (Read(cmdName, this, out responseStr, out _, out _))
{
var cleanedResponse = Regex.Replace(responseStr, "[^0-9]", string.Empty);
if (int.TryParse(cleanedResponse, out var intValue))

View File

@ -655,8 +655,8 @@ namespace Sensus.Ui.FM2014TestBench
if (null == firstFm2014)
return;
_fm2014Config.RefPulsesRequired = firstFm2014.RefPulsesRequired;
_fm2014Config.DutPulsesRequired = firstFm2014.DutPulsesRequired;
_fm2014Config.RefPulsesRequired = (UInt16)firstFm2014.RefPulsesRequired;
_fm2014Config.DutPulsesRequired = (UInt16)firstFm2014.DutPulsesRequired;
_fm2014Config.DoublePulseDeadtime = firstFm2014.DoublePulseDeadtime_ms;
_fm2014Config.DutToRefToleranceMax = firstFm2014.DutToRefCalibrationToleranceMax_percent;
_fm2014Config.DutToRefToleranceMin = firstFm2014.DutToRefCalibrationToleranceMin_percent;
@ -1100,7 +1100,7 @@ namespace Sensus.Ui.FM2014TestBench
UpdateContentControl(lblActualProcessText, e.ActualProcessMessage);
}
if (e.ActualProcessPercent != null)
if (e.ActualProcessPercent != null && !_autoProgressBar)
{
UpdateProgressBar(pbActualProgress, (Double)e.ActualProcessPercent);
}