257 lines
13 KiB
C#
257 lines
13 KiB
C#
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.ByteArrayToValue<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.ByteArrayToValue<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.ByteArrayToValue<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; }
|
|
}
|
|
}
|