Pressure measurement process done.
This commit is contained in:
@@ -5,7 +5,7 @@
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{D0C8D887-ED52-40AB-A069-90BCE0E801E2}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>Xylem.Common.Ui.CordonelPreadjustmentUi</RootNamespace>
|
||||
<AssemblyName>Xylem.Common.Ui.CordonelPreadjustmentUi</AssemblyName>
|
||||
@@ -103,6 +103,9 @@
|
||||
<PropertyGroup />
|
||||
<PropertyGroup />
|
||||
<PropertyGroup />
|
||||
<PropertyGroup>
|
||||
<NoWin32Manifest>true</NoWin32Manifest>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Newtonsoft.Json, Version=12.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Newtonsoft.Json.12.0.3\lib\net40\Newtonsoft.Json.dll</HintPath>
|
||||
@@ -116,6 +119,9 @@
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Drawing" />
|
||||
<Reference Include="System.Net.Http">
|
||||
<HintPath>..\..\..\..\..\..\..\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.8\System.Net.Http.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Windows.Forms" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
@@ -153,6 +159,7 @@
|
||||
<DependentUpon>PreAdjustmentControl.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="PreAdjustmentSettingsContainer.cs" />
|
||||
<Compile Include="Processes\Actions\PressureTestProcess.cs" />
|
||||
<Compile Include="Processes\Actions\FlushProcess.cs" />
|
||||
<Compile Include="Processes\Actions\PrepareTestProcess.cs" />
|
||||
<Compile Include="Processes\Actions\AmplitudeTestProcess.cs" />
|
||||
|
||||
@@ -393,6 +393,7 @@ namespace CordonelPreadjustmentUi
|
||||
{
|
||||
this.l_ZeroFlowCal_TempCal.ForeColor = color;
|
||||
}
|
||||
|
||||
public enum StatusPanelItems
|
||||
{
|
||||
None = 0,
|
||||
@@ -1681,9 +1682,13 @@ namespace CordonelPreadjustmentUi
|
||||
|
||||
listOfProgrammParts.Add(new FlushProcess("First Flush", StatusPanelItems.Detect, PredefinedMessages.WaitUntilFlushFinished(pp.Setting.Culture), string.Empty, 2 * 60));
|
||||
|
||||
listOfProgrammParts.Add(new PressureTestProcess("PreussureTest", StatusPanelItems.Prepare, PredefinedMessages.WaitUntilPreparationFinished(pp.Setting.Culture), PredefinedMessages.PreparationFailed(pp.Setting.Culture), 1 * 60));
|
||||
|
||||
|
||||
listOfProgrammParts.Add(new PreparationProcess("Preparation", StatusPanelItems.Prepare, PredefinedMessages.WaitUntilPreparationFinished(pp.Setting.Culture), PredefinedMessages.PreparationFailed(pp.Setting.Culture), 1 * 60));
|
||||
|
||||
|
||||
|
||||
if (!pp.Setting.TempOnly)
|
||||
{
|
||||
listOfProgrammParts.Add(new AmplitudeTestProcess("Amplitude Test", StatusPanelItems.Amplitude, PredefinedMessages.WaitUntilAmplitudeTestFinished(pp.Setting.Culture), PredefinedMessages.AmplitudeFailed(pp.Setting.Culture), 4 * 60));
|
||||
|
||||
@@ -16,8 +16,6 @@ namespace CordonelPreadjustmentUi.Processes.Actions
|
||||
{
|
||||
public class PreparationProcess : BaseProcess
|
||||
{
|
||||
|
||||
|
||||
public PreparationProcess(string processName, StatusPanelItems panelState, string performMessage, string failedMessage, int? expectedTimeS) : base(processName, panelState, performMessage, failedMessage, expectedTimeS)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -0,0 +1,256 @@
|
||||
namespace CordonelPreadjustmentUi.Processes.Actions
|
||||
{
|
||||
using Newtonsoft.Json;
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Xylem.Common.CommonCore.Configuration;
|
||||
using Xylem.Common.Hardware.WaterMeter.Genesis.Registers;
|
||||
using Xylem.Common.Logic.SoftwareAccessHelper;
|
||||
|
||||
using static CordonelPreadjustmentUi.PreAdjustmentControl;
|
||||
|
||||
/// <summary>
|
||||
/// Process for cordonel water meters with pressure sensor.
|
||||
/// </summary>
|
||||
/// <remarks date="2023-05-23" author="Stoyan Zlatev">
|
||||
/// Just started implementing pressure test for water meters with pressure sensor.
|
||||
/// </remarks>
|
||||
public class PressureTestProcess : BaseProcess
|
||||
{
|
||||
/// <summary>
|
||||
/// Read / Write is pressure present for the water meter.
|
||||
/// </summary>
|
||||
/// <remarks date="2023-05-23" author="Stoyan Zlatev">
|
||||
/// Just started implementing pressure test for water meters with pressure sensor.
|
||||
/// </remarks>
|
||||
private const string PRESSURE_PRESENT = "METROLOGYASST_PressurePresent";
|
||||
/// <summary>
|
||||
/// Read / Write pressure measurements for the water meter.
|
||||
/// </summary>
|
||||
/// <remarks date="2023-05-23" author="Stoyan Zlatev">
|
||||
/// Just started implementing pressure test for water meters with pressure sensor.
|
||||
/// </remarks>
|
||||
private const string PRESSURE_MEASURE = "METROLOGYASST_PressureMeasure";
|
||||
|
||||
/// <summary>
|
||||
/// Constructor for passing parameters to the base constructor of the derived class.
|
||||
/// </summary>
|
||||
/// <param name="processName">The name used to show into the GUI.</param>
|
||||
/// <param name="panelState">TODO: Get the right description. Probably the state for the box into the GUI. ???</param>
|
||||
/// <param name="performMessage">TODO: Get the right description. Probably the success message to show into the GUI. ???</param>
|
||||
/// <param name="failedMessage">TODO: Get the right description. Probably the error message to show into the GUI. ???</param>
|
||||
/// <param name="expectedTimeS">TODO: Get the right description. Probably the expected time for process the pressure tests. ???</param>
|
||||
/// <remarks date="2023-05-23" author="Stoyan Zlatev">
|
||||
/// Just started implementing pressure test for water meters with pressure sensor.
|
||||
/// </remarks>
|
||||
public PressureTestProcess(string processName, StatusPanelItems panelState, string performMessage, string failedMessage, int? expectedTimeS)
|
||||
: base(processName, panelState, performMessage, failedMessage, expectedTimeS)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determinates and initializes a list of pressure measure tests processes on the logedin cordonels with pressure sensor.
|
||||
/// Programm workflow for Cordonels with pressure sensor.
|
||||
/// When any of the water meters has presure sensor - load the test specification.
|
||||
/// Acording to the test specification process all meters, also the referenz on workplaces 11 and 12.
|
||||
/// <list type="number">
|
||||
/// <listheader>Measurement as follow.</listheader>
|
||||
/// <item>Measure starts with <see cref="PRESSURE_MEASURE"/> = 1</item>
|
||||
/// <item>Then registry is readeded and comaired to the referenz meters acording to the specification.</item>
|
||||
/// </list>
|
||||
/// </summary>
|
||||
/// <returns>Returns a <see cref="List{Task}"/> for processing the pressure tests on the goggedin cordonels.</returns>
|
||||
/// <remarks date="2023-05-23" author="Stoyan Zlatev">
|
||||
/// Just started implementing pressure test for water meters with pressure sensor.
|
||||
/// </remarks>
|
||||
public override List<Task> StartWork()
|
||||
{
|
||||
/// List of the processes to start.
|
||||
var listOfPresureTestTasks = new List<Task>();
|
||||
var pressureTestSpecification = default(PressureTestSpecification);
|
||||
var pressureTestSpecificationLoaded = false;
|
||||
/// Just to not lose from focus the process progrss object.
|
||||
var processProgress = base.CurrentProcessProgress;
|
||||
var minPressureReferenzValue = default(int?);
|
||||
var maxPressureReferenzValue = default(int?);
|
||||
|
||||
/// Looping trough all <see cref="MeterStateControl"/>s to determinate whitch are with pressure sensor.
|
||||
foreach (var meterStateControl in base.MeterStateCtls)
|
||||
{
|
||||
/// If the meter is enabled and pressure sensor is present a new pressure mesure task should be initialized and added to the processes list.
|
||||
if (meterStateControl.IsEnabled)
|
||||
{
|
||||
/// Getting the meter object from the state control.
|
||||
var meter = meterStateControl.Meter;
|
||||
/// Reads the buffer for determinating if the pressure sensor is present.
|
||||
var isPressurePresentBuffer = meter.ReadRegister(PRESSURE_PRESENT);
|
||||
/// Converted value for determinating if the pressure sensor is present.
|
||||
var isPressurePresent = RegisterConverter.ConvertTo<bool>(isPressurePresentBuffer);
|
||||
|
||||
if (!isPressurePresent)
|
||||
{
|
||||
processProgress.DebugMessage($"Watermeter has no pressure sensor!", meterStateControl.Slot, "DC", meter.PcbId);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
/// Loads the pressure test specification from the defined web service if not yet loaded.
|
||||
if (pressureTestSpecification is null && !pressureTestSpecificationLoaded)
|
||||
{
|
||||
pressureTestSpecificationLoaded = true;
|
||||
pressureTestSpecification = this.LoadPressureTestSpecification();
|
||||
|
||||
/// if loading fails
|
||||
if (pressureTestSpecification is null)
|
||||
{
|
||||
processProgress.DebugMessage($"Test specification could not be loaded properly!", meterStateControl.Slot, "DC", meter.PcbId);
|
||||
|
||||
// TODO: Handle possible exceptions by making http request.
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/// Initialize min and max referenz values ones for all meters
|
||||
if (minPressureReferenzValue is null)
|
||||
{
|
||||
/// setting the min and max values on their oposit values.
|
||||
/// checking the equality later will set up a value by 1 or more referenz meters.
|
||||
minPressureReferenzValue = int.MaxValue;
|
||||
maxPressureReferenzValue = int.MinValue;
|
||||
|
||||
if (processProgress.Setting.GetTempUseTempFlansh() || TempMeterStateCtls.Any(a => a.IsEnabled))
|
||||
{
|
||||
/// Determinates the min and max values aus temperatur meters list.
|
||||
foreach (var referenzMeterState in base.TempMeterStateCtls)
|
||||
{
|
||||
if (referenzMeterState.IsEnabled)
|
||||
{
|
||||
var referenzMeter = referenzMeterState.Meter;
|
||||
/// Reset meter pressure
|
||||
referenzMeter.WriteRegister(PRESSURE_MEASURE, 1);
|
||||
|
||||
if (!referenzMeter.IsLoggedOn)
|
||||
{
|
||||
referenzMeter.Login();
|
||||
}
|
||||
|
||||
var referenzPressureBuffer = referenzMeter.ReadRegister(PRESSURE_MEASURE);
|
||||
var referenzPressure = RegisterConverter.ConvertTo<int>(referenzPressureBuffer);
|
||||
|
||||
if (referenzPressure < minPressureReferenzValue)
|
||||
{
|
||||
minPressureReferenzValue = referenzPressure;
|
||||
}
|
||||
|
||||
if (referenzPressure > maxPressureReferenzValue)
|
||||
{
|
||||
maxPressureReferenzValue = referenzPressure;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Continue if min pressure value is still its oposit for the type. There was no referenz zehler found.
|
||||
if (minPressureReferenzValue == int.MaxValue)
|
||||
{
|
||||
processProgress.DebugMessage($"No referenz watermeter found!", meterStateControl.Slot, "DC", meter.PcbId);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
listOfPresureTestTasks.Add(new Task<bool>(() =>
|
||||
{
|
||||
var measuredTestValues = new int[pressureTestSpecification.NumberOfMeasurements];
|
||||
var measurementDelyInS = pressureTestSpecification.TimeMeasurementsInS * 1000;
|
||||
var numberOfMeasurements = pressureTestSpecification.NumberOfMeasurements;
|
||||
var testDate = DateTime.Now;
|
||||
|
||||
for (int measurement = 0; measurement < numberOfMeasurements; measurement++)
|
||||
{
|
||||
/// Reset meter pressure
|
||||
meter.WriteRegister(PRESSURE_MEASURE, 1);
|
||||
|
||||
/// Read the new meter pressure
|
||||
var pressureMeasureBuffer = meter.ReadRegister(PRESSURE_MEASURE);
|
||||
var pressureInPascals = RegisterConverter.ConvertTo<int>(pressureMeasureBuffer);
|
||||
|
||||
measuredTestValues[measurement] = pressureInPascals;
|
||||
processProgress.DebugMessage($"Measure {measurement + 1}: {pressureInPascals}Pa", meterStateControl.Slot, "DC", meter.PcbId);
|
||||
|
||||
/// Dely only for first n - 1 measurements
|
||||
if (measurement < numberOfMeasurements - 1)
|
||||
{
|
||||
Thread.Sleep(measurementDelyInS);
|
||||
}
|
||||
}
|
||||
|
||||
var avgPressure = (int)measuredTestValues.Average();
|
||||
var testPassed = minPressureReferenzValue <= avgPressure && avgPressure <= maxPressureReferenzValue;
|
||||
var avgPressureInBars = avgPressure / 100_000F;
|
||||
|
||||
processProgress.DebugMessage($"Average pressure: {avgPressure}Pa", meterStateControl.Slot, "DC", meter.PcbId);
|
||||
processProgress.DebugMessage($"Average pressure: {avgPressureInBars}Bar", meterStateControl.Slot, "DC", meter.PcbId);
|
||||
|
||||
if (!this.PostPressureTestResult(meter.PcbId, avgPressureInBars, testPassed, testDate))
|
||||
{
|
||||
processProgress.DebugMessage($"Test result was not posted!", meterStateControl.Slot, "DC", meter.PcbId);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return testPassed;
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return listOfPresureTestTasks;
|
||||
}
|
||||
|
||||
private PressureTestSpecification LoadPressureTestSpecification()
|
||||
{
|
||||
try
|
||||
{
|
||||
var responseContent = LocalWebRequest.GetRequest(ServiceUrls.GetPressureSensorSpecificationURL);
|
||||
|
||||
return JsonConvert.DeserializeObject<PressureTestSpecification>(responseContent);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private bool PostPressureTestResult(string pcbIdText, float avgPressure, bool passed, DateTime testDate)
|
||||
{
|
||||
try
|
||||
{
|
||||
return LocalWebRequest.PostRequestAsync(ServiceUrls.PostPressureSensorResultURL, json: new
|
||||
{
|
||||
PcbId = int.TryParse(pcbIdText, out int pcbId) ? pcbId : default(int?),
|
||||
AvgPressureInBar = avgPressure,
|
||||
TestPassed = passed,
|
||||
TestDate = testDate,
|
||||
});
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal class PressureTestSpecification
|
||||
{
|
||||
public int NumberOfMeasurements { get; set; }
|
||||
|
||||
public int TimeMeasurementsInS { get; set; }
|
||||
|
||||
public float MaxDeviationInBar { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -20,6 +20,7 @@ namespace CordonelPreadjustmentUi.Processes
|
||||
public readonly string PerformMessage;
|
||||
public readonly int ExpectedTimeS;
|
||||
public DateTimeOffset StartTime;
|
||||
|
||||
public BaseProcess(string processName, StatusPanelItems panelState, string performMessage, string failedMessage, int? expectedTimeS = null)
|
||||
{
|
||||
ProcessName = processName;
|
||||
@@ -30,6 +31,7 @@ namespace CordonelPreadjustmentUi.Processes
|
||||
|
||||
ExpectedTimeS = expectedTimeS.HasValue ? expectedTimeS.Value : 0;
|
||||
}
|
||||
|
||||
internal List<MeterStateControl> AllMeterStateCtrls()
|
||||
{
|
||||
var r = new List<MeterStateControl>();
|
||||
@@ -75,29 +77,29 @@ namespace CordonelPreadjustmentUi.Processes
|
||||
|
||||
|
||||
var completTasks = new Task(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
while (!listOfProcessTasks.All(t => t.IsCompleted))
|
||||
{
|
||||
try
|
||||
if (pp.CancellationSource != null && pp.CancellationSource.IsCancellationRequested)
|
||||
{
|
||||
while (!listOfProcessTasks.All(t => t.IsCompleted))
|
||||
{
|
||||
if (pp.CancellationSource != null && pp.CancellationSource.IsCancellationRequested)
|
||||
{
|
||||
return;
|
||||
}
|
||||
Thread.Sleep(5);
|
||||
}
|
||||
|
||||
GetSequenceResult($"{ProcessName} sequence");
|
||||
pp.IsBusy = false;
|
||||
return;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Thread.Sleep(5);
|
||||
}
|
||||
|
||||
throw new ApplicationException("Error on waiting for completition", ex);
|
||||
}
|
||||
GetSequenceResult($"{ProcessName} sequence");
|
||||
pp.IsBusy = false;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
throw new ApplicationException("Error on waiting for completition", ex);
|
||||
}
|
||||
|
||||
|
||||
});
|
||||
});
|
||||
completTasks.Start();
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<appSettings>
|
||||
<add key="GetPressureSensorSpecificationURL" value="http://sla12iis01.emea.sensus.net/MeterProcessState/api/CordonelPressureSensorTest/GetTestSpec"/>
|
||||
<add key="PostPressureSensorResultURL" value="http://sla12iis01.emea.sensus.net/MeterProcessState/api/CordonelPressureSensorTest/PostTestResults"/>
|
||||
<add key="PressureSensorResultsURL" value="http://sla12iis01.emea.sensus.net/MeterProcessState/api/CordonelPressureSensorTest/GetTestResults/{0}"/>
|
||||
</appSettings>
|
||||
<runtime>
|
||||
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||
<dependentAssembly>
|
||||
|
||||
Reference in New Issue
Block a user