MiniPrf: - extended input validation

This commit is contained in:
Thomas Wiedebusch 2026-01-20 19:30:55 +01:00
parent e98bd03b03
commit 71ea89e0e7
3 changed files with 141 additions and 44 deletions

View File

@ -165,6 +165,25 @@ namespace Sensus.Common.Hardware.WaterMeter.MechanicalMeter.FM2014.FM2014Core
set;
}
/// <summary>
/// Publish the FM2014 minimum pulses for REF and DUT time measurement.
/// </summary>
public const UInt16 TimeMeasurementPulsesSetupMin = 1;
/// <summary>
/// Publish the FM2014 maximum pulses for REF and DUT time measurement.
/// </summary>
public const UInt16 TimeMeasurementPulsesSetupMax = 0xFFFF;
/// <summary>
/// Publish the FM2014 minimum pulses for REF and DUT regulation measurement.
/// </summary>
public const UInt16 PulsesPerCmRegulationSetupMin = 1;
/// <summary>
/// Publish the FM2014 maximum pulses for REF and DUT regulation measurement.
/// </summary>
public const UInt16 PulsesPerCmRegulationSetupMax = 9999;
private UInt16 _ref_pulse_per_cm = 1000;
/// <inheritdoc/>
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
}
}
/// <summary>
/// Publish the FM2014 minimum REF to DUT scale for error display.
/// </summary>
public const Single RefToDutScaleMin = 0.0001f;
/// <summary>
/// Publish the FM2014 maximum REF to DUT scale for error display.
/// </summary>
public const Single RefToDutScaleMax = 999.9f;
/// <summary>
/// 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
/// </summary>
public String RefToDutScaleStr = "1000K+2";
private Single _refToDutScale_norm = 1.0e+1f;
private Single _refToDutScale_norm = 10.0f;
/// <inheritdoc/>
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
/// </summary>
/// <returns></returns>
/// <remarks date="2026-Jan-08..19" author="Thomas Wiedebusch">
/// <remarks date="2026-Jan-08..20" author="Thomas Wiedebusch">
/// - Initial.
/// </remarks>
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;

View File

@ -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();
}
/// <summary>
/// Common method to prepare for changed setup.
/// </summary>
@ -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;
}
/// <summary>
/// Common routine for REF to DUT scale check and update
/// </summary>
/// <returns></returns>
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
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
/// <remarks date="2023-Jan-14..18" author="Thomas Wiedebusch">
/// <remarks date="2023-Jan-14..20" author="Thomas Wiedebusch">
/// - Initial.
/// </remarks>
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
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
/// <remarks date="2023-Jan-14..19" author="Thomas Wiedebusch">
/// <remarks date="2023-Jan-14..20" author="Thomas Wiedebusch">
/// - Initial.
/// </remarks>
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
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
/// <remarks date="2023-Jan-15..19" author="Thomas Wiedebusch">
/// <remarks date="2023-Jan-15..20" author="Thomas Wiedebusch">
/// - Initial.
/// </remarks>
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:

View File

@ -113,6 +113,10 @@
<None Include="Resources\Sensus Logo.JPG" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\Common\CommonCore\CommonCore.csproj">
<Project>{1B02C79E-0B19-43E2-8F6B-71EF0C786C97}</Project>
<Name>CommonCore</Name>
</ProjectReference>
<ProjectReference Include="..\..\Common\Hardware\Interfaces\Ports\PortCore\PortCore.csproj">
<Project>{2e139f63-b6fe-4ea9-a098-85364fe9b26c}</Project>
<Name>PortCore</Name>