From 71ea89e0e71845760b0531932bdd1f4d63015ebb Mon Sep 17 00:00:00 2001 From: Thomas Wiedebusch Date: Tue, 20 Jan 2026 19:30:55 +0100 Subject: [PATCH] MiniPrf: - extended input validation --- .../FM2014/FM2014Core/FM2014.cs | 69 ++++++++--- MiniPrf/Ui/FrmMainMiniPrf.cs | 112 +++++++++++++----- MiniPrf/Ui/MiniPrf.csproj | 4 + 3 files changed, 141 insertions(+), 44 deletions(-) diff --git a/Common/Hardware/WaterMeter/MechanicalMeter/FM2014/FM2014Core/FM2014.cs b/Common/Hardware/WaterMeter/MechanicalMeter/FM2014/FM2014Core/FM2014.cs index 997cc144..c2b7cb67 100644 --- a/Common/Hardware/WaterMeter/MechanicalMeter/FM2014/FM2014Core/FM2014.cs +++ b/Common/Hardware/WaterMeter/MechanicalMeter/FM2014/FM2014Core/FM2014.cs @@ -165,6 +165,25 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core set; } + /// + /// Publish the FM2014 minimum pulses for REF and DUT time measurement. + /// + public const UInt16 TimeMeasurementPulsesSetupMin = 1; + /// + /// Publish the FM2014 maximum pulses for REF and DUT time measurement. + /// + public const UInt16 TimeMeasurementPulsesSetupMax = 0xFFFF; + + + /// + /// Publish the FM2014 minimum pulses for REF and DUT regulation measurement. + /// + public const UInt16 PulsesPerCmRegulationSetupMin = 1; + /// + /// Publish the FM2014 maximum pulses for REF and DUT regulation measurement. + /// + public const UInt16 PulsesPerCmRegulationSetupMax = 9999; + private UInt16 _ref_pulse_per_cm = 1000; /// public UInt16 Ref_pulse_per_cm @@ -173,7 +192,9 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core set { // Check limits and equality - if (value < 1 || value > 9999 || _ref_pulse_per_cm == value) + if (value < PulsesPerCmRegulationSetupMin || + value > PulsesPerCmRegulationSetupMax || + value == _ref_pulse_per_cm) return; _ref_pulse_per_cm = value; @@ -190,7 +211,9 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core set { // Check limits and equality - if (value < 1 || value > 9999 || _dut_pulse_per_cm == value) + if (value < PulsesPerCmRegulationSetupMin || + value > PulsesPerCmRegulationSetupMax || + value == _dut_pulse_per_cm) return; _dut_pulse_per_cm = value; @@ -199,16 +222,31 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core } } + /// + /// Publish the FM2014 minimum REF to DUT scale for error display. + /// + public const Single RefToDutScaleMin = 0.0001f; + /// + /// Publish the FM2014 maximum REF to DUT scale for error display. + /// + public const Single RefToDutScaleMax = 999.9f; + /// /// As the scale needed to be sent to the FM2014 doesn't follow the standardized nomenclature /// for floating point values it has to be converted to the FM2014 requirement. - /// 1.0e+1f is "1000K+2" - /// 1.0e+2f is "1000K+3" - /// Max value is "9999K+3" = 999.9f; - /// Min value is "1000K-3" = 0.0001f + /// + /// Translation table examples + /// Min value is "1000K-3" = 0.0001 + /// "1000K-2" = 0.001 + /// "1000K-1" = 0.01 + /// "1000K0" = 0.1 + /// "1000K1" = 1.0 + /// "1000K2" = 10.0 + /// "1000K3" = 100.0 + /// Max value is "9999K3" = 999.9 /// public String RefToDutScaleStr = "1000K+2"; - private Single _refToDutScale_norm = 1.0e+1f; + private Single _refToDutScale_norm = 10.0f; /// public Single RefToDutScale_norm @@ -216,16 +254,15 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core get => _refToDutScale_norm; private set { - // Max value is "9999K+3" = 999.9f; Min value is "1000K-3" = 0.0001f - if (value > 999.9f || value < 0.0001f) + if (value > RefToDutScaleMax || value < RefToDutScaleMin) return; _refToDutScale_norm = value; var exponent = 4; var number = _refToDutScale_norm; - while (number * 10.0f < 10000.0f) + while (number < RefToDutScaleMax + 0.1f ) { - number *= 10.0f + 0.0001f; + number *= 10.0f; exponent--; } @@ -337,6 +374,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core SerialPort.Parity = Parity.Odd; SerialPort.PortName = comPort; SerialPort.ReadTimeout = 1000; + SerialPort.WriteTimeout = 1000; return true; } @@ -961,7 +999,7 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core /// Initiate communication to individual node /// /// - /// + /// /// - Initial. /// private Boolean InitiateIndividualComm() @@ -1012,14 +1050,13 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core } catch (Exception e) { - response = new CmdResponse(CmdName.CMD_ADDR_PC, - $"{Resources.StrCmdRespErrorIndividual} - {e.Message}"); + response = new CmdResponse(CmdName.CMD_CONNECT, $"{Resources.StrCmdRespErrorIndividual} - {e.Message}"); OnRawRecordReceived?.Invoke(this, new ProcessExecEventArgs(Resources.StrError, specificInfoObj: response, statusReturn: StatusReturn.Failed)); + return false; } - response = new CmdResponse(CmdName.CMD_ADDR_PC, - $"{Resources.StrCmdRespErrorIndividual}"); + response = new CmdResponse(CmdName.CMD_CONNECT, $"{Resources.StrCmdRespErrorIndividual}"); OnRawRecordReceived?.Invoke(this, new ProcessExecEventArgs(Resources.StrError, specificInfoObj: response, statusReturn: StatusReturn.Failed)); return false; diff --git a/MiniPrf/Ui/FrmMainMiniPrf.cs b/MiniPrf/Ui/FrmMainMiniPrf.cs index db57f105..89537f9f 100644 --- a/MiniPrf/Ui/FrmMainMiniPrf.cs +++ b/MiniPrf/Ui/FrmMainMiniPrf.cs @@ -45,6 +45,7 @@ using System.Reflection; using System.Threading.Tasks; using System.Windows.Forms; using Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core.Consts; +using Xylem.Common.CommonCore.Consts; using Xylem.Common.Utils.ProcessExec.EventArguments; namespace Sensus.MiniPrf.Ui @@ -164,8 +165,7 @@ namespace Sensus.MiniPrf.Ui { cbxFM2014ComPort.Items.Add(comPort); } - //_comPortIdx = 0; - //cbxFM2014ComPort.Text = cbxFM2014ComPort.Items[0].ToString(); + cbxFM2014ComPort.Text = cbxFM2014ComPort.Items[_comPortIdx].ToString(); var itemContent = _fm2014Config?.Address ?? 1; for (var idx = 0; idx < cbxFM2014Address.MaxDropDownItems; idx++) @@ -236,10 +236,7 @@ namespace Sensus.MiniPrf.Ui lblWaitingForMeterResponse.Text = Resources.StrLblWaitingForMeterResponse; lblWaitingForMeterResponse.Visible = false; - SetFM2014AccessLocked(); - btnFM2014Connect.Enabled = true; - cbxFM2014Address.Enabled = true; - cbxFM2014ComPort.Enabled = true; + CheckUpdateEnabled(); } @@ -385,6 +382,8 @@ namespace Sensus.MiniPrf.Ui { SetFM2014AccessLocked(); btnFM2014Connect.Enabled = true; + cbxFM2014Address.Enabled = true; + cbxFM2014ComPort.Enabled = true; return; } SetFM2014AccessEnabled(); @@ -464,6 +463,7 @@ namespace Sensus.MiniPrf.Ui LogErrorText(Resources.StrErrorMsgFM2014AccessDenied); Fm2014.Logout(); ActionControl(false); + return; } @@ -556,7 +556,7 @@ namespace Sensus.MiniPrf.Ui barSingleProgressUpdate.Update(); Update(); } - + /// /// Common method to prepare for changed setup. /// @@ -564,10 +564,43 @@ namespace Sensus.MiniPrf.Ui { _regulationSetupHasChanged = true; btnSaveRegulationSetup.Enabled = true; - tbxActualFlowRateCmPerHour.Text = ""; - tbxActualMeasuredToleranceDutToRef.Text = ""; + tbxRefFrequencyHz.Text = ""; + tbxRefFrequencyHz.BackColor = gbxDutToRefRegulation.BackColor; + tbxActualFlowRateCmPerHour.Text = ""; + tbxActualFlowRateCmPerHour.BackColor = gbxDutToRefRegulation.BackColor; + tbxActualMeasuredToleranceDutToRef.Text = ""; + tbxActualMeasuredToleranceDutToRef.BackColor = gbxDutToRefRegulation.BackColor; + + tbxRefPulsePerCm.BackColor = Color.White; + tbxDutPulsePerCm.BackColor = Color.White; + tbxScaleRefToDut.BackColor = lblRefPulsePerVolume.BackColor; + tbxManualInputVolumeLiters.BackColor = Color.White; + tbxRefCalibrationResultPulsePerCm.BackColor = lblRefPulsePerVolume.BackColor; + + } + + /// + /// Common routine for REF to DUT scale check and update + /// + /// + private Boolean UpdateRefToDutScale() + { + tbxScaleRefToDut.Text = $@"{Fm2014.RefToDutScale_norm:F4}"; + + // Display error if scale doesn't fit + if (Math.Abs(Fm2014.RefToDutScale_norm - + (Single)Fm2014.Ref_pulse_per_cm / Fm2014.Dut_pulse_per_cm) > FM2014.RefToDutScaleMin || + Fm2014.RefToDutScale_norm < FM2014.RefToDutScaleMin || + Fm2014.RefToDutScale_norm > FM2014.RefToDutScaleMax ) + { + tbxScaleRefToDut.BackColor = Color.Red; + tbxScaleRefToDut.Text = Resources.StrError; + btnSaveRegulationSetup.Enabled = false; + return false; + } + return true; } #endregion ProcessControls @@ -844,30 +877,33 @@ namespace Sensus.MiniPrf.Ui /// /// /// - /// + /// /// - Initial. /// private void tbxRefPulsesPerCm_Leave(Object sender, EventArgs e) { // Setup FM2014 - if (Fm2014 != null && ushort.TryParse(tbxRefPulsePerCm.Text, out var pulses_per_cm)) + if (Fm2014 != null && int.TryParse(tbxRefPulsePerCm.Text, out var pulses_per_cm)) { //Backup the actual setting to detect changes var backupPulses_per_cm = Fm2014.Ref_pulse_per_cm; - Fm2014.Ref_pulse_per_cm = pulses_per_cm; + Fm2014.Ref_pulse_per_cm = (UInt16)pulses_per_cm; // Output the Fm2014 setting to avoid wrong display of invalid ranges as this will be // limited during the setup of the FM2014 property! tbxRefPulsePerCm.Text = $@"{Fm2014.Ref_pulse_per_cm:D}"; // During setup of the 'Ref_pulse_per_cm' the 'RefToDutScaleStr' will be generated - tbxScaleRefToDut.Text = $@"{Fm2014.RefToDutScale_norm:F3}"; + if (!UpdateRefToDutScale()) + { + tbxRefPulsePerCm.BackColor = Color.Red; + return; + } // Check if values have changed and need to be updated in the standalone setup if (backupPulses_per_cm != Fm2014.Ref_pulse_per_cm) { SetupHasChanged(); } - // SPECIAL BACKUP AND RESTORE FOR REF CALIBRATION // If the REF pulses per cubic meter have been changed manually, the 'Manual REF Calibration' @@ -911,23 +947,28 @@ namespace Sensus.MiniPrf.Ui /// /// /// - /// + /// /// - Initial. /// private void tbxDutPulsesPerCm_Leave(Object sender, EventArgs e) { // Setup FM2014 - if (Fm2014 != null && ushort.TryParse(tbxDutPulsePerCm.Text, out var pulses_per_cm)) + if (Fm2014 != null && int.TryParse(tbxDutPulsePerCm.Text, out var pulses_per_cm)) { //Backup the actual setting to detect changes var backupPulses_per_cm = Fm2014.Dut_pulse_per_cm; // Try to set the new calculated REF pulses limited by the property setter - Fm2014.Dut_pulse_per_cm = pulses_per_cm; + Fm2014.Dut_pulse_per_cm = (UInt16)pulses_per_cm; // Output the Fm2014 setting to avoid wrong display of invalid ranges as this will be // limited during the setup of the FM2014 property! tbxDutPulsePerCm.Text = $@"{Fm2014.Dut_pulse_per_cm:D}"; // During setup of the 'Dut_pulse_per_cm' the 'RefToDutScaleStr' will be generated - tbxScaleRefToDut.Text = $@"{Fm2014.RefToDutScale_norm:F3}"; + if (!UpdateRefToDutScale()) + { + tbxDutPulsePerCm.BackColor = Color.Red; + return; + } + // Check if values have changed and need to be updated in the standalone setup if (backupPulses_per_cm != Fm2014.Dut_pulse_per_cm) { @@ -958,14 +999,14 @@ namespace Sensus.MiniPrf.Ui /// /// /// - /// + /// /// - Initial. /// private void tbxManualInputVolumeLiters_Leave(Object sender, EventArgs e) { // Calculate REF pulses per cubic meter - if (ushort.TryParse(tbxMeasuredRefPulses.Text, out var pulses) && pulses > 0 && - ushort.TryParse(tbxManualInputVolumeLiters.Text, out var liters) && liters > 0) + if (int.TryParse(tbxMeasuredRefPulses.Text, out var pulses) && pulses > 0 && + int.TryParse(tbxManualInputVolumeLiters.Text, out var liters) && liters > 0) { //Backup the actual setting to detect changes var backupPulses_per_cm = Fm2014.Ref_pulse_per_cm; @@ -981,7 +1022,14 @@ namespace Sensus.MiniPrf.Ui { tbxRefCalibrationResultPulsePerCm.Text = $@"{Fm2014.Ref_pulse_per_cm:D}"; tbxRefPulsePerCm.Text = $@"{Fm2014.Ref_pulse_per_cm:D}"; - tbxScaleRefToDut.Text = $@"{Fm2014.RefToDutScale_norm:F3}"; + tbxManualInputVolumeLiters.BackColor = Color.White; + tbxRefCalibrationResultPulsePerCm.BackColor = lblRefPulsePerVolume.BackColor; + + if (!UpdateRefToDutScale()) + { + tbxManualInputVolumeLiters.BackColor = Color.Red; + return; + } // Check if values have changed and need to be updated in the standalone setup if (backupPulses_per_cm != Fm2014.Ref_pulse_per_cm) @@ -991,6 +1039,8 @@ namespace Sensus.MiniPrf.Ui } else { + tbxManualInputVolumeLiters.BackColor = Color.Red; + tbxRefCalibrationResultPulsePerCm.BackColor = Color.Red; tbxRefCalibrationResultPulsePerCm.Text = Resources.StrError; } } @@ -1037,11 +1087,18 @@ namespace Sensus.MiniPrf.Ui // Data dispatcher var resp = (FM2014CmdDef.CmdResponse)e.SpecificInfoObj; - if (resp.IntValue == null && resp.DoubleValue == null) + + if (e.StatusReturn == StatusReturn.Failed) + { + LogErrorText(resp.AnswerStr); + //ErrorHandler(resp.CmdName); + } + + else if (resp.IntValue == null && resp.DoubleValue == null) { LogText(resp.AnswerStr); } - if (resp.IntValue != null) + else if (resp.IntValue != null) { LogText($"{resp.AnswerStr}: {resp.IntValue:D} {resp.SiUnit}"); switch (resp.CmdName) @@ -1061,7 +1118,6 @@ namespace Sensus.MiniPrf.Ui break; case FM2014CmdDef.CmdName.CMD_GET_REF_FREQU: tbxRefFrequencyHz.Text = $@"{resp.IntValue:D}"; - // DEBUG tbxRefFrequencyDirectHz.Text = $@"{resp.IntValue:D}"; if (resp.IntValue < 1 || resp.IntValue > 254) { @@ -1076,7 +1132,7 @@ namespace Sensus.MiniPrf.Ui break; } } - if (resp.DoubleValue != null) + else if (resp.DoubleValue != null) { LogText($"{resp.AnswerStr}: {resp.DoubleValue:F2} {resp.SiUnit}"); switch (resp.CmdName) @@ -1093,9 +1149,9 @@ namespace Sensus.MiniPrf.Ui { tbxActualMeasuredToleranceDutToRef.BackColor = gbxDutToRefRegulation.BackColor; } - break; + break; case FM2014CmdDef.CmdName.CMD_REF_SET_SCALE: - tbxScaleRefToDut.Text = $@"{resp.DoubleValue:F2}"; + tbxScaleRefToDut.Text = $@"{resp.DoubleValue:F4}" ; break; // DEBUG case FM2014CmdDef.CmdName.CMD_GET_REF_PERIOD: diff --git a/MiniPrf/Ui/MiniPrf.csproj b/MiniPrf/Ui/MiniPrf.csproj index ffa027b3..c659d301 100644 --- a/MiniPrf/Ui/MiniPrf.csproj +++ b/MiniPrf/Ui/MiniPrf.csproj @@ -113,6 +113,10 @@ + + {1B02C79E-0B19-43E2-8F6B-71EF0C786C97} + CommonCore + {2e139f63-b6fe-4ea9-a098-85364fe9b26c} PortCore