diff --git a/Common/CommonCore/Consts/StatusReturn.cs b/Common/CommonCore/Consts/StatusReturn.cs
index 04722a29..702d4c77 100644
--- a/Common/CommonCore/Consts/StatusReturn.cs
+++ b/Common/CommonCore/Consts/StatusReturn.cs
@@ -28,6 +28,11 @@
///
/// inspection needed as warning returns
///
- Warning
+ Warning,
+
+ ///
+ /// the measurement is out of range
+ ///
+ MeasurementOutOfRange
}
}
\ No newline at end of file
diff --git a/Common/Hardware/WaterMeter/MechanicalMeter/FM2014/FM2014Core/Consts/FM2014CmdDef.cs b/Common/Hardware/WaterMeter/MechanicalMeter/FM2014/FM2014Core/Consts/FM2014CmdDef.cs
index e74d910a..d12bda30 100644
--- a/Common/Hardware/WaterMeter/MechanicalMeter/FM2014/FM2014Core/Consts/FM2014CmdDef.cs
+++ b/Common/Hardware/WaterMeter/MechanicalMeter/FM2014/FM2014Core/Consts/FM2014CmdDef.cs
@@ -507,9 +507,9 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core.Co
private const String UNICODE_DC2 = "\u0013";
///
- /// Complete command table
+ /// Command table for communication with FM2014 combines the name with the command code and additional info.
///
- public static List CmdTbl = new List
+ public static readonly List CmdTbl = new List
{
// FM2014 control and information
new Cmd(CmdName.CMD_CONNECT, "", CmdType.INDIVIDUAL, Resources.StrCmdMsgConnect),
diff --git a/Common/Hardware/WaterMeter/MechanicalMeter/FM2014/FM2014Core/FM2014.cs b/Common/Hardware/WaterMeter/MechanicalMeter/FM2014/FM2014Core/FM2014.cs
index 0e9be667..0021f414 100644
--- a/Common/Hardware/WaterMeter/MechanicalMeter/FM2014/FM2014Core/FM2014.cs
+++ b/Common/Hardware/WaterMeter/MechanicalMeter/FM2014/FM2014Core/FM2014.cs
@@ -299,12 +299,12 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core
///
/// REF pulse counter is switched active
///
- public Boolean RefPulseCtrOn { set; get; }
+ private Boolean RefPulseCtrOn { set; get; }
///
/// DUT pulse counter is switched active
///
- public Boolean DutPulseCtrOn { set; get; }
+ private Boolean DutPulseCtrOn { set; get; }
///
/// Serial number of the FM2014
@@ -580,7 +580,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core
get => _currentOutputAttenuation;
private set
{
- if (value < CURRENT_OUTPUT_ATTENUATION_MIN ||
+ if (value < CURRENT_OUTPUT_ATTENUATION_MIN ||
value > CURRENT_OUTPUT_ATTENUATION_MAX)
return;
@@ -1054,7 +1054,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core
///
/// - Initial.
///
- public static Boolean RegulationMeasurement(UInt32 refPulses_per_cm, UInt16 dutPulses_per_cm,
+ public static Boolean RegulationMeasurement(UInt32 refPulses_per_cm, UInt16 dutPulses_per_cm,
UInt16 doublePulseDeadtime_ms, Byte currentOutputAttenuation)
{
// If the cyclic task has already been started everything is fine
@@ -1140,6 +1140,7 @@ 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))
@@ -1152,11 +1153,21 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core
if (int.TryParse(cleanedStr, NumberStyles.HexNumber, new CultureInfo("en"),
out var measTolerance))
{
+ fm2014.DutToRefToleranceMeasured_percent =
+ measTolerance * fm2014.ToleranceRawToPercentScale * signMultiplier;
var response = new CmdResponse(cmdName, info,
- doubleValue: measTolerance * fm2014.ToleranceRawToPercentScale * signMultiplier,
+ doubleValue: fm2014.DutToRefToleranceMeasured_percent,
unit: Units.GetInfo(Units.Name.PERCENT));
+
+ // Check the threshold for OOR
+ if (Math.Abs(fm2014.DutToRefToleranceMeasured_percent) > fm2014.Tolerance_percent)
+ statusReturn = StatusReturn.MeasurementOutOfRange;
+ else statusReturn = StatusReturn.Okay;
+
PublishResponse(fm2014,
- new ProcessExecEventArgs("", actualProcessMessage: measurementInfo,
+ new ProcessExecEventArgs("",
+ actualProcessMessage: measurementInfo,
+ statusReturn: statusReturn,
specificInfoObj: response));
}
}
@@ -1254,11 +1265,17 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core
int.TryParse(responseStr, NumberStyles.HexNumber, new CultureInfo("en"),
out var refFrequency))
{
+ // Check the threshold for OOR
+ 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,
+ statusReturn: statusReturn,
specificInfoObj: response));
// Convert to m³/h (3600 s/h) and save the value
@@ -1269,7 +1286,9 @@ 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,
+ statusReturn: statusReturn,
specificInfoObj: response));
}
}
@@ -1438,7 +1457,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core
{
String info;
String responseStr;
-
+ StatusReturn statusReturn;
// Read the remaining REF pulses if required
if (firstActiveFm2014.RefPulsesRequired != 0)
{
@@ -1491,7 +1510,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core
if (fm2014.RefPulsesRemaining == 0 && fm2014.DutPulsesRemaining == 0)
{
var retVal = true;
-
+
// Read the REF timer ticks for the counted pulses
if (firstActiveFm2014.RefPulsesRequired != 0)
{
@@ -1562,11 +1581,21 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core
{
fm2014.DutToRefToleranceMeasured_percent =
(1.0 - fm2014.DutTimeMeasured_s / fm2014.RefTimeMeasured_s) * 100.0;
+
+ // Check the threshold for OOR
+ if (fm2014.DutToRefToleranceMeasured_percent >
+ fm2014.DutToRefCalibrationToleranceMax_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,
+ statusReturn: statusReturn,
specificInfoObj: response));
}
}
diff --git a/FM2014TestApp/Ui/Fm2014sTest/FM2014TestBenchWindow.xaml.cs b/FM2014TestApp/Ui/Fm2014sTest/FM2014TestBenchWindow.xaml.cs
index 5c38ef4a..94b7c718 100644
--- a/FM2014TestApp/Ui/Fm2014sTest/FM2014TestBenchWindow.xaml.cs
+++ b/FM2014TestApp/Ui/Fm2014sTest/FM2014TestBenchWindow.xaml.cs
@@ -1076,7 +1076,7 @@ namespace Sensus.Ui.FM2014TestBench
///
/// Feedback from FM2014being parsed to GUI
///
- ///
+ ///
/// - Initial.
///
private void DataReceived_Handler(Object sender, ProcessExecEventArgs e)
@@ -1112,6 +1112,8 @@ namespace Sensus.Ui.FM2014TestBench
// Data dispatcher
var resp = (CmdResponse)e.SpecificInfoObj;
String valueStr;
+ // Used as marker for error, null means measurement is in range or status or health is good
+ Brush statusColor = null;
if (e.StatusReturn == StatusReturn.Failed)
{
@@ -1124,42 +1126,41 @@ namespace Sensus.Ui.FM2014TestBench
}
else if (resp.IntValue != null)
{
+ if (e.StatusReturn == StatusReturn.MeasurementOutOfRange)
+ statusColor = ColorProcessFailed;
LogText($"{resp.AnswerStr}: {resp.IntValue:D} {resp.Unit}");
switch (resp.CmdName)
{
case CmdName.CMD_REF_GET_PLS_RMN:
- ucFm2014.SetValue(CAL_LBL_IDX_REF_RMN_PLS, $"{resp.IntValue:D}");
+ ucFm2014.SetValue(CAL_LBL_IDX_REF_RMN_PLS, $"{resp.IntValue:D}", statusColor);
break;
case CmdName.CMD_DUT_GET_PLS_RMN:
- ucFm2014.SetValue(CAL_LBL_IDX_DUT_RMN_PLS, $"{resp.IntValue:D}");
+ ucFm2014.SetValue(CAL_LBL_IDX_DUT_RMN_PLS, $"{resp.IntValue:D}", statusColor);
break;
case CmdName.CMD_REF_GET_PLS_CTR:
case CmdName.CMD_REF_GET_PLS_CTR_BU:
if (firstFm2014 != null && firstFm2014.Address == fm2014.Address)
- UpdateTextBox(tbxRefPulsesMeasured, $"{resp.IntValue:D}");
- ucFm2014.SetValue(CTR_LBL_IDX_REF_PLS, $"{resp.IntValue:D}");
+ UpdateTextBox(tbxRefPulsesMeasured, $"{resp.IntValue:D}", statusColor);
+ ucFm2014.SetValue(CTR_LBL_IDX_REF_PLS, $"{resp.IntValue:D}", statusColor);
break;
case CmdName.CMD_DUT_GET_PLS_CTR:
case CmdName.CMD_DUT_GET_PLS_CTR_BU:
if (firstFm2014 != null && firstFm2014.Address == fm2014.Address)
- UpdateTextBox(tbxDutPulsesMeasured, $"{resp.IntValue:D}");
- ucFm2014.SetValue(CTR_LBL_IDX_DUT_PLS, $"{resp.IntValue:D}");
+ UpdateTextBox(tbxDutPulsesMeasured, $"{resp.IntValue:D}", statusColor);
+ ucFm2014.SetValue(CTR_LBL_IDX_DUT_PLS, $"{resp.IntValue:D}", statusColor);
break;
case CmdName.CMD_REF_LPP_SCALE:
- UpdateTextBox(tbxRefPulsesPerCm, $"{resp.IntValue:D}");
+ UpdateTextBox(tbxRefPulsesPerCm, $"{resp.IntValue:D}", statusColor);
break;
case CmdName.CMD_DUT_LPP_SCALE:
- UpdateTextBox(tbxDutPulsesPerCm, $"{resp.IntValue:D}");
+ UpdateTextBox(tbxDutPulsesPerCm, $"{resp.IntValue:D}", statusColor);
break;
case CmdName.CMD_MEAS_SET_ATTN:
Dispatcher.Invoke(() => cbxDisplayAttenuation.SelectedItem = $"{resp.IntValue}");
break;
case CmdName.CMD_GET_REF_FREQU:
valueStr = $"{resp.IntValue:D}";
- if (resp.IntValue < FM2014.REF_FREQU_MIN || resp.IntValue > FM2014.REF_FREQU_MAX)
- ucFm2014.SetValue(REG_LBL_IDX_REF_FREQU, valueStr, ColorProcessFailed);
- else
- ucFm2014.SetValue(REG_LBL_IDX_REF_FREQU, valueStr);
+ ucFm2014.SetValue(REG_LBL_IDX_REF_FREQU, valueStr, statusColor);
break;
case CmdName.CMD_RST_MEAS:
// Immediately lock all buttons and input fields until reset is finished
@@ -1172,35 +1173,30 @@ namespace Sensus.Ui.FM2014TestBench
}
else if (resp.DoubleValue != null)
{
+ if (e.StatusReturn == StatusReturn.MeasurementOutOfRange)
+ statusColor = ColorProcessFailed;
LogText($"{resp.AnswerStr}: {resp.DoubleValue:F2} {resp.Unit}");
switch (resp.CmdName)
{
case CmdName.CMD_REF_GET_TMR:
valueStr = $"{resp.DoubleValue:F3}";
- ucFm2014.SetValue(CAL_LBL_IDX_REF_MEAS_TMR, valueStr);
+ ucFm2014.SetValue(CAL_LBL_IDX_REF_MEAS_TMR, valueStr, statusColor);
break;
case CmdName.CMD_DUT_GET_TMR:
valueStr = $"{resp.DoubleValue:F3}";
- ucFm2014.SetValue(CAL_LBL_IDX_DUT_MEAS_TMR, valueStr);
+ ucFm2014.SetValue(CAL_LBL_IDX_DUT_MEAS_TMR, valueStr, statusColor);
break;
case CmdName.CMD_CAL_DUT_TO_REF_TOL:
valueStr = $"{resp.DoubleValue:F3}";
- if ((Double)resp.DoubleValue <= fm2014.DutToRefCalibrationToleranceMax_percent &&
- (Double)resp.DoubleValue >= fm2014.DutToRefCalibrationToleranceMin_percent)
- ucFm2014.SetValue(CAL_LBL_IDX_DUT_TO_REF_TOL, valueStr, ColorSuccess);
- else
- ucFm2014.SetValue(CAL_LBL_IDX_DUT_TO_REF_TOL, valueStr, ColorProcessFailed);
+ ucFm2014.SetValue(CAL_LBL_IDX_DUT_TO_REF_TOL, valueStr, statusColor);
break;
case CmdName.CMD_GET_UDTLC:
case CmdName.CMD_GET_DTLC:
valueStr = $"{resp.DoubleValue:F2}";
- if (Math.Abs((Double)resp.DoubleValue) > fm2014.Tolerance_percent)
- ucFm2014.SetValue(REG_LBL_IDX_DUT_TO_REF_TOL, valueStr, ColorProcessFailed);
- else
- ucFm2014.SetValue(REG_LBL_IDX_DUT_TO_REF_TOL, valueStr);
+ ucFm2014.SetValue(REG_LBL_IDX_DUT_TO_REF_TOL, valueStr, statusColor);
break;
case CmdName.CMD_REF_SET_SCALE:
- UpdateTextBox(tbxScaleRefToDut, $"{resp.DoubleValue:F4}");
+ UpdateTextBox(tbxScaleRefToDut, $"{resp.DoubleValue:F4}", statusColor);
break;
// // DEBUG
// case FM2014CmdDef.CmdName.CMD_GET_REF_PERIOD:
@@ -1217,7 +1213,7 @@ namespace Sensus.Ui.FM2014TestBench
// break;
case CmdName.CMD_CAL_FLOW_REF_FREQU:
valueStr = $"{resp.DoubleValue:F3}";
- ucFm2014.SetValue(REG_LBL_IDX_FLOW_RATE, valueStr);
+ ucFm2014.SetValue(REG_LBL_IDX_FLOW_RATE, valueStr, statusColor);
//UpdateTextBox(tbxRefFlowRateFromRefFrequencyCmPerH, valueStr);
// TODO THW Check if the actual flow shall be taken based on 'REF Frequency'
//UpdateTextBox(tbxActualFlowRateCmPerHour, valueStr);