299 lines
16 KiB
C#
299 lines
16 KiB
C#
using CordonelPreadjustmentUi.Helper;
|
|
using CordonelPreadjustmentUi.Processes.Itinerary;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
using Xylem.Common.Hardware.WaterMeter.Genesis.DataPackages.MeasurementRecords;
|
|
using Xylem.Common.Hardware.WaterMeter.Genesis.Registers;
|
|
using Xylem.Common.Ui.CordonelPreadjustmentUi.Helper.Extensions;
|
|
using static CordonelPreadjustmentUi.PreAdjustmentControl;
|
|
|
|
namespace CordonelPreadjustmentUi.Processes.Actions
|
|
{
|
|
public class OffsetTestProcess : BaseProcess
|
|
{
|
|
public OffsetTestProcess(string processName, StatusPanelItems panelState, string performMessage, string failedMessage, int? expectedTimeS) : base(processName, panelState, performMessage, failedMessage, expectedTimeS)
|
|
{
|
|
}
|
|
|
|
public override List<Task> StartWork()
|
|
{
|
|
return doWorkProcess(base.CurrentProcessProgress);
|
|
}
|
|
|
|
private List<Task> doWorkProcess(ProcessProgress pp)
|
|
{
|
|
var MetersToProcess = MeterStateCtls.Where(e => e.IsEnabled).ToList();
|
|
|
|
var listOfProcessTask = new List<Task>();
|
|
|
|
|
|
listOfProcessTask.Add(new Task<bool>(() =>
|
|
{
|
|
|
|
#region Wait for settling time (60s)
|
|
for (Int32 Time = pp.Setting.OffsetTestSettlingTime; Time >= 0; Time--)
|
|
{
|
|
if (CheckAbort(true)) { return false; }
|
|
|
|
pp.StatusLabel = $"{PredefinedMessages.ZeroflowOffsetWaitForSettling(pp.Setting.Culture)}{Time.ToString(pp.Setting.Culture)}";
|
|
Thread.Sleep(1000);
|
|
}
|
|
#endregion
|
|
|
|
var listOfSubTask = new List<Task>();
|
|
|
|
foreach (var meterctl in MetersToProcess)
|
|
{
|
|
meterctl.Meter.CurrentRecords.Clear();
|
|
|
|
listOfSubTask.Add(new Task<bool>(() =>
|
|
{
|
|
var Ok = true;
|
|
Boolean PerformCheck = true;
|
|
|
|
//Timeout calculation for offset test
|
|
//(pp.Setting.OffsetTestNumberOfLines * number of path) / 1000
|
|
//((9000 * 3) / 1000 ) = 27 min
|
|
|
|
|
|
var pataDataActivitCheck = new MultiPathDataLogContainer<int>(pp.Setting.NumberOfPaths);
|
|
var MaxTimeoutWarnings = 300;
|
|
pataDataActivitCheck.Update(null, -1);
|
|
Thread.Sleep(1800);
|
|
while (PerformCheck)
|
|
{
|
|
var offsetRecords = new List<CalibrationRecord>();
|
|
try
|
|
{
|
|
offsetRecords = meterctl.Meter.CurrentRecords.ToList();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
try
|
|
{
|
|
offsetRecords = meterctl.Meter.CurrentRecords.ToList();
|
|
}
|
|
catch (Exception)
|
|
{
|
|
Ok = false;
|
|
PerformCheck = false;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pp.StatusLabel = ($"{PredefinedMessages.ZeroflowOffsetAqqFinished(pp.Setting.Culture)} {offsetRecords.Count}/{(pp.Setting.OffsetTestNumberOfLines * 3)}"); // "Wait until data aquisition has finished:"
|
|
Thread.Sleep(1800);
|
|
for (UInt16 PathSum = 0; PathSum < pp.Setting.NumberOfPaths; PathSum++)
|
|
{
|
|
var currentCount = offsetRecords.Count(c => c.Channel == PathSum + 1);
|
|
var oldCound = pataDataActivitCheck.Get(PathSum);
|
|
if (currentCount <= oldCound + 1)
|
|
{
|
|
pp.DebugMessage($"Warn! Receive no new lines on path {PathSum}", meterctl.Slot, "DC", meterctl.Meter.PcbId);
|
|
MaxTimeoutWarnings = MaxTimeoutWarnings - 1;
|
|
|
|
}
|
|
pataDataActivitCheck.Update(PathSum, currentCount);
|
|
}
|
|
|
|
//todo:enable timeout and canneclation token
|
|
if (MaxTimeoutWarnings <= 0)
|
|
{
|
|
pp.DebugMessage($"Fatal timeout while collecting data. Please check LED singnal. Has {offsetRecords.Count} from {pp.Setting.OffsetTestNumberOfLines * 3}", meterctl.Slot, "DC", meterctl.Meter.PcbId);
|
|
// Ok = false;
|
|
}
|
|
if (CheckAbort(Ok, meterctl)) { return Ok; }
|
|
|
|
bool testDone = true;
|
|
for (UInt16 Path = 0; Path < pp.Setting.NumberOfPaths; Path++)
|
|
{
|
|
var lstPathRecords = offsetRecords.Where(c => c.Channel == Path + 1).ToList();
|
|
if (lstPathRecords.Count(v => !v.IsValid) > pp.Setting.OffsetTestNumberOfLines * 0.1)
|
|
{
|
|
pp.DebugMessage($" To many bad data Packages {meterctl.Meter.Slot}; PATH {Path + 1}; Linecounter = {lstPathRecords.Count}", null, "DC");
|
|
|
|
Ok = false;
|
|
break;
|
|
}
|
|
if (lstPathRecords.Count < pp.Setting.OffsetTestNumberOfLines)
|
|
{
|
|
testDone = false;
|
|
}
|
|
}
|
|
|
|
if (testDone)
|
|
{
|
|
Ok = true;
|
|
PerformCheck = false;
|
|
}
|
|
if (CheckAbort(Ok, meterctl)) { return Ok; }
|
|
}
|
|
|
|
var PathDataContainerBaddata = new MultiPathDataLogContainer<List<CalibrationRecord>>(pp.Setting.NumberOfPaths);
|
|
var PathDataContainer = new MultiPathDataLogContainer<List<CalibrationRecord>>(pp.Setting.NumberOfPaths);
|
|
|
|
for (UInt16 Path = 0; Path < PathDataContainer.GetPathCount(); Path++)
|
|
{
|
|
var offsetRecords = meterctl.Meter.CurrentRecords.ToList().Where(c => (c.Channel == (Path + 1)) && c.IsValid).ToList();
|
|
PathDataContainer.Update(Path, offsetRecords);
|
|
|
|
offsetRecords = meterctl.Meter.CurrentRecords.ToList().Where(c => (c.Channel == (Path + 1)) && !c.IsValid).ToList();
|
|
PathDataContainerBaddata.Update(Path, offsetRecords);
|
|
}
|
|
|
|
|
|
#region Calculating mean values
|
|
|
|
pp.DebugMessage($"Calculating mean values", meterctl.Meter.Slot, "APP", meterctl.Meter.PcbId);
|
|
|
|
var amplitudeValuesMeanUp = new MultiPathDataLogContainer<double>(pp.Setting.NumberOfPaths);
|
|
var amplitudeValuesMeanDown = new MultiPathDataLogContainer<double>(pp.Setting.NumberOfPaths);
|
|
var DeltaTimeOfFlightAverage = new MultiPathDataLogContainer<double>(pp.Setting.NumberOfPaths);
|
|
|
|
for (UInt16 Path = 0; Path < PathDataContainer.GetPathCount(); Path++)
|
|
{
|
|
var meanAmplitudeUpV = PathDataContainer.Get(Path).Sum(ad => ad.AmplitudeUpV) / PathDataContainer.Get(Path).Count;
|
|
var meanAmplitudeDownV = PathDataContainer.Get(Path).Sum(ad => ad.AmplitudeDownV) / PathDataContainer.Get(Path).Count;
|
|
var avgDeltaTimeOfFlight = PathDataContainer.Get(Path).Sum(ad => ad.DeltaTimeOfFlightS) / PathDataContainer.Get(Path).Count;
|
|
|
|
if (meanAmplitudeUpV == 0 || meanAmplitudeDownV == 0 || avgDeltaTimeOfFlight == 0)
|
|
{
|
|
pp.DebugMessage($"Mean value is zero at {meterctl.Meter.Slot}; PATH{Path + 1}", meterctl.Meter.Slot, "DC", meterctl.Meter.PcbId);
|
|
if (pp.Setting.NumberOfPaths != 1)
|
|
{
|
|
Ok = false;
|
|
}
|
|
|
|
}
|
|
|
|
if (CheckAbort(Ok, meterctl)) { return Ok; }
|
|
|
|
amplitudeValuesMeanUp.Update(Path, meanAmplitudeUpV);
|
|
amplitudeValuesMeanDown.Update(Path, meanAmplitudeDownV);
|
|
DeltaTimeOfFlightAverage.Update(Path, avgDeltaTimeOfFlight);
|
|
|
|
}
|
|
#endregion
|
|
|
|
var BadDataCheckOK = true;
|
|
var AmplitudeCheckOK = true;
|
|
var OffsetCheckOK = true;
|
|
|
|
for (UInt16 Path = 0; Path < PathDataContainer.GetPathCount(); Path++)
|
|
{
|
|
pp.DebugMessage($"Bad data at PATH{Path + 1}:{PathDataContainerBaddata.Get(Path).Count()}", meterctl.Meter.Slot, "DC", meterctl.Meter.PcbId);
|
|
|
|
|
|
if (PathDataContainerBaddata.Get(Path).Count() > pp.Setting.OffsetTestBadDataLimit)
|
|
{
|
|
BadDataCheckOK = false;
|
|
pp.DebugMessage($"Bad datacheck failed!", meterctl.Meter.Slot, "DC", meterctl.Meter.PcbId);
|
|
}
|
|
|
|
pp.DebugMessage($"Average positive amplitude, PATH{(Path + 1)}: {Math.Round(amplitudeValuesMeanUp.Get(Path), 2).ToString("000.00")}mV", meterctl.Meter.Slot, "DC", meterctl.Meter.PcbId);
|
|
pp.DebugMessage($"Average negative amplitude, PATH{(Path + 1)}: {Math.Round(amplitudeValuesMeanDown.Get(Path), 2).ToString("000.00")}mV", meterctl.Meter.Slot, "DC", meterctl.Meter.PcbId);
|
|
meterctl.Meter.calibrationResult.AddAdditionalLog($"Offset Average positive amplitude PATH {(Path + 1)}", $"{Math.Round(amplitudeValuesMeanUp.Get(Path), 2).ToString("000.00")}mV");
|
|
meterctl.Meter.calibrationResult.AddAdditionalLog($"Offset Average negative amplitude PATH {(Path + 1)}", $"{Math.Round(amplitudeValuesMeanDown.Get(Path), 2).ToString("000.00")}mV");
|
|
if (pp.Setting.MeterSize == Xylem.Common.Logic.ProductionOrderCore.OrderData.MeterSize.DN200 || pp.Setting.MeterSize == Xylem.Common.Logic.ProductionOrderCore.OrderData.MeterSize.US8)
|
|
{
|
|
pp.Setting.OffsetTestLowerVoltageLimitMV = 180;
|
|
}
|
|
if ((amplitudeValuesMeanUp.Get(Path) > pp.Setting.OffsetTestUpperVoltageLimitMV) ||
|
|
(amplitudeValuesMeanUp.Get(Path) < pp.Setting.OffsetTestLowerVoltageLimitMV) ||
|
|
(amplitudeValuesMeanDown.Get(Path) < pp.Setting.OffsetTestLowerVoltageLimitMV) ||
|
|
(amplitudeValuesMeanDown.Get(Path) > pp.Setting.OffsetTestUpperVoltageLimitMV))
|
|
{
|
|
AmplitudeCheckOK = false;
|
|
pp.DebugMessage($"Amplitude check failed!", meterctl.Meter.Slot, "APP", meterctl.Meter.PcbId);
|
|
}
|
|
|
|
pp.DebugMessage($"Average delta time of flight valuePATH{(Path + 1)}: Raw{DeltaTimeOfFlightAverage.Get(Path)} -> in picoseconds= {Math.Round((DeltaTimeOfFlightAverage.Get(Path) / (Math.Pow(2, 38) * Math.Pow(10, 12))), 2).ToString("000.00")}", meterctl.Meter.Slot, "APP", meterctl.Meter.PcbId);
|
|
meterctl.Meter.calibrationResult.AddAdditionalLog($"Offset Average delta time of flight value PATH {(Path + 1)} RAW ", $"{DeltaTimeOfFlightAverage.Get(Path)}");
|
|
meterctl.Meter.calibrationResult.AddAdditionalLog($"Offset Average delta time of flight value PATH {(Path + 1)} picoseconds ", $"{Math.Round((DeltaTimeOfFlightAverage.Get(Path) / (Math.Pow(2, 38) * Math.Pow(10, 12))), 2).ToString("000.00")}");
|
|
|
|
if ((DeltaTimeOfFlightAverage.Get(Path) > pp.Setting.OffsetTestOffsetLimitPS) ||
|
|
(DeltaTimeOfFlightAverage.Get(Path) < -pp.Setting.OffsetTestOffsetLimitPS))
|
|
{
|
|
pp.DebugMessage($"Delta time of flight check failed", meterctl.Meter.Slot, "APP", meterctl.Meter.PcbId);
|
|
|
|
OffsetCheckOK = false;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
if (!BadDataCheckOK
|
|
|| !AmplitudeCheckOK
|
|
|| !OffsetCheckOK)
|
|
{
|
|
pp.DebugMessage($"Skip offset test at least one test is failed", meterctl.Meter.Slot, "APP", meterctl.Meter.PcbId);
|
|
if (pp.Setting.NumberOfPaths != 1)
|
|
{
|
|
if (CheckAbort(false, meterctl)) { return false; }
|
|
}
|
|
|
|
}
|
|
|
|
Ok = meterctl.Meter.ReLogin();
|
|
if (CheckAbort(Ok, meterctl)) { return Ok; }
|
|
|
|
|
|
for (UInt16 Path = 0; Path < DeltaTimeOfFlightAverage.GetPathCount(); Path++)
|
|
{
|
|
var OffsetValue = (Int32)((DeltaTimeOfFlightAverage.Get(Path) * Math.Pow(2, 40)));
|
|
pp.StatusLabel = ($"{PredefinedMessages.WaitUntilRegisterWriteFinished(pp.Setting.Culture)}");
|
|
String RegValue = String.Empty;
|
|
switch (Path)
|
|
{
|
|
case 0:
|
|
RegValue = Register.Genesisflow.ZeroOffset1;
|
|
break;
|
|
case 1:
|
|
RegValue = Register.Genesisflow.ZeroOffset2;
|
|
break;
|
|
case 2:
|
|
RegValue = Register.Genesisflow.ZeroOffset3;
|
|
break;
|
|
default:
|
|
System.Windows.Forms.MessageBox.Show($"Path number incorrect {Path}");
|
|
break;
|
|
};
|
|
if (pp.Setting.NumberOfPaths != 1)
|
|
{
|
|
Ok = WriteRegisterSafe(meterctl.Meter, $"Zero flow offset Path {Path + 1}", RegValue, OffsetValue);
|
|
if (CheckAbort(Ok, meterctl)) { return Ok; }
|
|
}
|
|
else
|
|
{
|
|
Ok = WriteRegisterSafe(meterctl.Meter, $"Zero flow offset Path {Path + 1}", RegValue, OffsetValue);
|
|
Ok = true;
|
|
}
|
|
|
|
}
|
|
return Ok;
|
|
}));
|
|
}
|
|
|
|
listOfSubTask.ForEach(t => t.Start());
|
|
|
|
while (listOfSubTask.Any(t => !t.IsCompleted))
|
|
{
|
|
Thread.Sleep(1000);
|
|
}
|
|
|
|
return true;
|
|
}));
|
|
|
|
return listOfProcessTask;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|