diff --git a/Common/.vs/config/applicationhost.config b/Common/.vs/config/applicationhost.config index 883679a3..de10b180 100644 --- a/Common/.vs/config/applicationhost.config +++ b/Common/.vs/config/applicationhost.config @@ -155,7 +155,7 @@ - + diff --git a/Common/CordoPlot/MainWindow.xaml b/Common/CordoPlot/MainWindow.xaml index 7f488107..52a7862a 100644 --- a/Common/CordoPlot/MainWindow.xaml +++ b/Common/CordoPlot/MainWindow.xaml @@ -10,13 +10,15 @@ - + + - + + - + + + + diff --git a/Common/CordoPlot/MainWindow.xaml.cs b/Common/CordoPlot/MainWindow.xaml.cs index 64f3a28f..b4f9c5aa 100644 --- a/Common/CordoPlot/MainWindow.xaml.cs +++ b/Common/CordoPlot/MainWindow.xaml.cs @@ -1,4 +1,5 @@ using Newtonsoft.Json; +using ScottPlot.WPF; using System; using System.Collections.Generic; using System.IO; @@ -11,6 +12,7 @@ using Xylem.Common.Logic.ProductionOrderCore.TestResults; using Xylem.Common.Logic.SoftwareAccessHelper; using Xylem.Common.Metrology.Measurements; + namespace CordoPlot { /// @@ -149,44 +151,44 @@ namespace CordoPlot Lines.Add(new List()); - List> Errors = new List>(); - Errors.Add(new List()); - Errors.Add(new List()); - Errors.Add(new List()); - Errors.Add(new List()); + //List> Errors = new List>(); + //Errors.Add(new List()); + //Errors.Add(new List()); + //Errors.Add(new List()); + //Errors.Add(new List()); - List Syncmarks = new List(); + //List Syncmarks = new List(); - List Linescale = new List(); - foreach (var dataItem in listOfData) - { - foreach (var item in dataItem) - { - if (item is FlowTestRecord flow) - { - Lines.First().Add(flow.GetVolumeCm()); - Errors.First().Add(0); - Linescale.Add(flow.GetTimeS()); - if (item.GetDataSyncMark() == SyncMarkRecord.SyncStart || item.GetDataSyncMark() == SyncMarkRecord.SyncEnd) - { - Syncmarks.Add(flow.GetTimeS()); - } - } - if (item is CalibrationRecord cal) - { - if (Linescale.Any()) - { - Lines[cal.Channel].Add(cal.GetVolumeCm()); - Errors[cal.Channel].Add(cal.Validation); - if (item.GetDataSyncMark() == SyncMarkRecord.SyncStart || item.GetDataSyncMark() == SyncMarkRecord.SyncEnd) - { - Syncmarks.Add(cal.GetTimeS()); - } - } - } - } - } + //List Linescale = new List(); + //foreach (var dataItem in listOfData) + //{ + // foreach (var item in dataItem) + // { + // if (item is FlowTestRecord flow) + // { + // Lines.First().Add(flow.GetVolumeCm()); + // Errors.First().Add(0); + // Linescale.Add(flow.GetTimeS()); + // if (item.GetDataSyncMark() == SyncMarkRecord.SyncStart || item.GetDataSyncMark() == SyncMarkRecord.SyncEnd) + // { + // Syncmarks.Add(flow.GetTimeS()); + // } + // } + // if (item is CalibrationRecord cal) + // { + // if (Linescale.Any()) + // { + // Lines[cal.Channel].Add(cal.GetVolumeCm()); + // Errors[cal.Channel].Add(cal.Validation); + // if (item.GetDataSyncMark() == SyncMarkRecord.SyncStart || item.GetDataSyncMark() == SyncMarkRecord.SyncEnd) + // { + // Syncmarks.Add(cal.GetTimeS()); + // } + // } + // } + // } + //} List> colors = new List>(); colors.Add(new Tuple(ScottPlot.Colors.Blue, ScottPlot.Colors.DarkBlue)); @@ -200,100 +202,60 @@ namespace CordoPlot FinLines.Add(new List()); FinLines.Add(new List()); - var linecounter = 0; - var counter = 0; - var intiVol = 0.0; - foreach (var lines in Lines) + + + var ChnlHelper = new List>(); + ChnlHelper.Add(new Tuple(0, WpfPlot1)); + ChnlHelper.Add(new Tuple(1, WpfPlot2)); + ChnlHelper.Add(new Tuple(2, WpfPlot3)); + ChnlHelper.Add(new Tuple(3, WpfPlot4)); + + + var Plotresults = new List(); + foreach (var item in ChnlHelper) { - counter = 0; - foreach (var line in lines) + var volLines = testBenchresults.Plot( item.Item1, null); + volLines.Color = colors[item.Item1].Item1; + Plotresults.Add(volLines); + + //foreach (var item in Errors[i]) + //{ + + // if (item != 0) + // { + // WpfPlot1.Plot.Add.Marker(Linescale[cordHelp], FinLines[i][cordHelp], ScottPlot.MarkerShape.Cross, 10, colors[1].Item2); + // } + // cordHelp = cordHelp + 1; + //} + + } + var maxScale = Plotresults.Max(p => p.ScaleLine.Count); + var AddScale = Plotresults.First(p => p.ScaleLine.Count == maxScale); + var srtExport = new System.Text.StringBuilder(); + + foreach (var item in ChnlHelper) + { + Plotresults[item.Item1].ScaleUp(AddScale.ScaleLine); + item.Item2.Plot.Add.Scatter(Plotresults[item.Item1].ScaleLine.ToArray(), Plotresults[item.Item1].VolumeLine.ToArray(), Plotresults[item.Item1].Color); + var exprLine = 0; + srtExport.AppendLine($"Chnl {item.Item1} ;Scale; Vol;"); + foreach (var exprHelpLine in Plotresults[item.Item1].ScaleLine) { - if (!FinLines[linecounter].Any()) - { - FinLines[linecounter].Add(0); - intiVol = Lines[linecounter][counter]; - } - else - { - var addVol = line - intiVol; - var dutOverflowVolumeCm = listOfData[linecounter].First().GetOverflowVolumeCm(); - //an overflow is detected when absolute volume difference is higher than 1/2 of the OverflowVolumeCm - if (Math.Abs(addVol - FinLines[linecounter].Last()) > (0.5 * dutOverflowVolumeCm)) - { - //if the overflow has been detected the end volume is higher than the start volume - //indicates the negative flow direction - if (addVol > FinLines[linecounter].Last()) - { - //negative overflow - intiVol -= dutOverflowVolumeCm; - //LoggerMeasurement.Info($"Slot:{Slot}, Channel: {IntermediateRecord.GetChannel()} - has negative overflow. currentVolumeQm ({currentVolumeQm}) - lastVolumeQm ({lastVolumeQm}). current accuOverflowVolume is {_accuDutOverflowVolumeCm}"); - } - else - { - //positive overflow - intiVol += dutOverflowVolumeCm; - //LoggerMeasurement.Info($"Slot:{Slot}, Channel: {IntermediateRecord.GetChannel()} - has positive overflow. currentVolumeQm ({currentVolumeQm}) - lastVolumeQm ({lastVolumeQm}). current accuOverflowVolume is {_accuDutOverflowVolumeCm}"); - } - } - addVol = line - intiVol; - - FinLines[linecounter].Add(addVol); - - - } - - - - counter = counter + 1; - - + srtExport.AppendLine($"{exprHelpLine};{Plotresults[item.Item1].VolumeLine[exprLine]};"); + exprLine = exprLine + 1; } - linecounter = 1 + linecounter; + item.Item2.Plot.Axes.AutoScale(); + item.Item2.Refresh(); } - for (int i = 0; i <= 3; i++) - { - for (int add = FinLines[i].Count; add < Linescale.Count; add++) - { - FinLines[i].Add(0); - } + //foreach (var syncm in Syncmarks) + //{ + // WpfPlot1.Plot.Add.VerticalLine(syncm, 2, ScottPlot.Colors.DarkGray); + //} - for (int add = Errors[i].Count; add < Linescale.Count; add++) - { - Errors[i].Add(0); - } - } - - - WpfPlot1.Plot.Add.Scatter(Linescale.ToArray(), FinLines[0].ToArray(), colors[0].Item1); - WpfPlot1.Plot.Add.Scatter(Linescale.ToArray(), FinLines[1].ToArray(), colors[1].Item1); - WpfPlot1.Plot.Add.Scatter(Linescale.ToArray(), FinLines[2].ToArray(), colors[2].Item1); - WpfPlot1.Plot.Add.Scatter(Linescale.ToArray(), FinLines[3].ToArray(), colors[3].Item1); - - for (int i = 0; i <= 3; i++) - { - var cordHelp = 0; - foreach (var item in Errors[i]) - { - - if (item != 0) - { - WpfPlot1.Plot.Add.Marker(Linescale[cordHelp], FinLines[i][cordHelp], ScottPlot.MarkerShape.Cross, 10, colors[1].Item2); - } - cordHelp = cordHelp + 1; - } - - } - - - foreach (var syncm in Syncmarks) - { - WpfPlot1.Plot.Add.VerticalLine(syncm, 2, ScottPlot.Colors.DarkGray); - } - - WpfPlot1.Plot.Axes.AutoScale(); + //WpfPlot1.Plot.Axes.AutoScale(); //for (int i = 0; i <= 3; i++) //{ @@ -307,7 +269,7 @@ namespace CordoPlot - WpfPlot1.Refresh(); + //WpfPlot1.Refresh(); } } diff --git a/Common/CordoPlot/PlotableTestResults.cs b/Common/CordoPlot/PlotableTestResults.cs index 24da7031..3cb6239b 100644 --- a/Common/CordoPlot/PlotableTestResults.cs +++ b/Common/CordoPlot/PlotableTestResults.cs @@ -1,10 +1,35 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Linq; +using ScottPlot; +using Xylem.Common.Hardware.WaterMeter.Genesis.DataPackages.MeasurementRecords; using Xylem.Common.Logic.ProductionOrderCore.TestResults; using Xylem.Common.Metrology.Measurements; namespace CordoPlot { + public class PlotResult + { + public List VolumeLine = new List(); + public List ScaleLine = new List(); + public List GP30Erros = new List(); + public List TestMarks = new List(); + + public Color Color { get; internal set; } + + public void ScaleUp(List MaxSacle) + { + if (VolumeLine.Count < MaxSacle.Count) + { + for (int i = VolumeLine.Count; i < MaxSacle.Count; i++) + { + VolumeLine.Add(double.NaN); + ScaleLine.Add(MaxSacle[i]); + } + + } + } + } public class TestPointResult { public int? Chnl { get; internal set; } = null; @@ -34,11 +59,12 @@ namespace CordoPlot foreach (var allChnlItems in this.ListOfRecords) { var intiVol = 0.0; - CurrentChnl = CurrentChnl + 1; + CurrentChnl = CurrentChnl + 1;//29586 + CurrentTestPoint = 0; foreach (var item in allChnlItems) { - + if (!testPointLocked && item.GetDataSyncMark() == Xylem.Common.CommonCore.Consts.SyncMarkRecord.SyncStart) { @@ -61,40 +87,60 @@ namespace CordoPlot } } - + } return true; } - - public double[] Plot(int? Chnl = null, int? TestNr = null) + + public PlotResult Plot(int Chnl, int? TestNr = null) { // + var results = testPointResults.Where(t => t.Chnl == Chnl && (!TestNr.HasValue || t.TestNr == TestNr.Value)); - + List VolumeLine = new List(); + List ScaleLine = new List(); + List GP30Erros = new List(); + List TestMarks = new List(); var linecounter = 0; var counter = 0; - - foreach (var lines in Lines) + var intiVol = 0.0; + var currentTestNr = -1; + foreach (var lines in results) { counter = 0; - foreach (var line in lines) + foreach (var line in lines.measurementRecords) { - if (!FinLines[linecounter].Any()) + if (lines.TestNr != currentTestNr) { - FinLines[linecounter].Add(0); - intiVol = Lines[linecounter][counter]; + TestMarks.Add(line.GetTimeS()); + currentTestNr = lines.TestNr; + } + + ScaleLine.Add(line.GetTimeS() + (100000 * currentTestNr)); + if (line is CalibrationRecord cal) + { + GP30Erros.Add(cal.Validation); } else { - var addVol = line - intiVol; - var dutOverflowVolumeCm = listOfData[linecounter].First().GetOverflowVolumeCm(); + GP30Erros.Add(0); + } + if (!VolumeLine.Any()) + { + VolumeLine.Add(0); + intiVol = line.GetVolumeCm(); + } + else + { + var addVol = line.GetVolumeCm() - intiVol; + var dutOverflowVolumeCm = line.GetOverflowVolumeCm(); //an overflow is detected when absolute volume difference is higher than 1/2 of the OverflowVolumeCm - if (Math.Abs(addVol - FinLines[linecounter].Last()) > (0.5 * dutOverflowVolumeCm)) + if (Math.Abs(addVol - VolumeLine.Last()) > (0.5 * dutOverflowVolumeCm)) { //if the overflow has been detected the end volume is higher than the start volume //indicates the negative flow direction - if (addVol > FinLines[linecounter].Last()) + if (addVol > VolumeLine.Last()) { //negative overflow intiVol -= dutOverflowVolumeCm; @@ -107,9 +153,9 @@ namespace CordoPlot //LoggerMeasurement.Info($"Slot:{Slot}, Channel: {IntermediateRecord.GetChannel()} - has positive overflow. currentVolumeQm ({currentVolumeQm}) - lastVolumeQm ({lastVolumeQm}). current accuOverflowVolume is {_accuDutOverflowVolumeCm}"); } } - addVol = line - intiVol; + addVol = line.GetVolumeCm() - intiVol; - FinLines[linecounter].Add(addVol); + VolumeLine.Add(addVol); } @@ -123,6 +169,8 @@ namespace CordoPlot linecounter = 1 + linecounter; } + return new PlotResult() { VolumeLine = VolumeLine, ScaleLine = ScaleLine, GP30Erros = GP30Erros, TestMarks = TestMarks }; + } } diff --git a/Common/CordonelPreadjustmentUi/CordonelPreadjustmentUi.csproj b/Common/CordonelPreadjustmentUi/CordonelPreadjustmentUi.csproj index eb7cf2a9..820f7296 100644 --- a/Common/CordonelPreadjustmentUi/CordonelPreadjustmentUi.csproj +++ b/Common/CordonelPreadjustmentUi/CordonelPreadjustmentUi.csproj @@ -175,6 +175,11 @@ PreAdjustmentControl.cs + + + + + @@ -196,6 +201,7 @@ + MainForm.cs diff --git a/Common/CordonelPreadjustmentUi/PreAdjustmentControl.cs b/Common/CordonelPreadjustmentUi/PreAdjustmentControl.cs index b1aaedd6..53823e0c 100644 --- a/Common/CordonelPreadjustmentUi/PreAdjustmentControl.cs +++ b/Common/CordonelPreadjustmentUi/PreAdjustmentControl.cs @@ -1,7 +1,6 @@ using CordonelPreadjustmentUi.Processes; using CordonelPreadjustmentUi.Processes.Actions; using CordonelPreadjustmentUi.Processes.Itinerary; -using Logic.ProductionToProductMapper.Cordonel; using System; using System.Collections.Generic; using System.Drawing; @@ -11,7 +10,6 @@ using System.Text; using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; -using Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore.Consts; using Xylem.Common.Hardware.WaterMeter.WaterMeterCore; using Xylem.Common.Hardware.WaterMeter.WaterMeterCore.Consts; using Xylem.Common.Logic.ProductionOrderCore.OrderData; @@ -158,7 +156,7 @@ namespace CordonelPreadjustmentUi meterStateCtl.StartTempWatch(meterStateCtl.MeterTempMode); } - + } @@ -1694,7 +1692,7 @@ namespace CordonelPreadjustmentUi List listOfProgrammParts = new List(); - + listOfProgrammParts.Add(new PrepareTestProcess("PrepareTest", StatusPanelItems.Detect, string.Empty, string.Empty, 1 * 60)); @@ -1704,26 +1702,59 @@ namespace CordonelPreadjustmentUi //listOfProgrammParts.Add(new PressureTestProcess("PreussureTest", StatusPanelItems.Prepare, PredefinedMessages.WaitUntilPreparationFinished(pp.Setting.Culture), PredefinedMessages.PreparationFailed(pp.Setting.Culture), 1 * 60)); + if (pp.Setting.NumberOfPaths == 1) + { + listOfProgrammParts.Add(new SPPreparationProcess("Preparation Single", StatusPanelItems.Prepare, PredefinedMessages.WaitUntilPreparationFinished(pp.Setting.Culture), PredefinedMessages.PreparationFailed(pp.Setting.Culture), 1 * 60)); + + } + else + { + listOfProgrammParts.Add(new PreparationProcess("Preparation", 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)); + if (pp.Setting.NumberOfPaths == 1) + { + listOfProgrammParts.Add(new SPAmplitudeTestProcess("Amplitude Test Single", StatusPanelItems.Amplitude, PredefinedMessages.WaitUntilAmplitudeTestFinished(pp.Setting.Culture), PredefinedMessages.AmplitudeFailed(pp.Setting.Culture), 4 * 60)); + } + else + { + listOfProgrammParts.Add(new AmplitudeTestProcess("Amplitude Test", StatusPanelItems.Amplitude, PredefinedMessages.WaitUntilAmplitudeTestFinished(pp.Setting.Culture), PredefinedMessages.AmplitudeFailed(pp.Setting.Culture), 4 * 60)); + } + listOfProgrammParts.Add(new FlushProcess("Second Flush", StatusPanelItems.Amplitude, PredefinedMessages.WaitUntilFlushFinished(pp.Setting.Culture), string.Empty, 2 * 60)); } - listOfProgrammParts.Add(new TemperatureCalibrationProcess("Temperature Calibration", StatusPanelItems.TempCal, PredefinedMessages.WaitUntilTemperatureCalibrationFinished(pp.Setting.Culture), PredefinedMessages.TempCalFailed(pp.Setting.Culture), 2 * 60)); - - - if (!pp.Setting.TempOnly) + if (pp.Setting.NumberOfPaths == 1) { - listOfProgrammParts.Add(new OffsetTestProcess("Offset Test", StatusPanelItems.Offset, PredefinedMessages.WaitUntilZeroflowOffsetTestFinished(pp.Setting.Culture), PredefinedMessages.ZeroflowOffsetTestFailed(pp.Setting.Culture), 18 * 60)); - } - listOfProgrammParts.Add(new CompletionProcess("Completion", StatusPanelItems.Completion, PredefinedMessages.WaitUntilCompletionFinished(pp.Setting.Culture), PredefinedMessages.CompletionFailed(pp.Setting.Culture), 1 * 60)); + listOfProgrammParts.Add(new SPTemperatureCalibrationProcess("Temperature Calibration Single", StatusPanelItems.TempCal, PredefinedMessages.WaitUntilTemperatureCalibrationFinished(pp.Setting.Culture), PredefinedMessages.TempCalFailed(pp.Setting.Culture), 2 * 60)); + if (!pp.Setting.TempOnly) + { + listOfProgrammParts.Add(new SPOffsetTestProcess("Offset Test Single", StatusPanelItems.Offset, PredefinedMessages.WaitUntilZeroflowOffsetTestFinished(pp.Setting.Culture), PredefinedMessages.ZeroflowOffsetTestFailed(pp.Setting.Culture), 18 * 60)); + } + listOfProgrammParts.Add(new SPCompletionProcess("Completion Single", StatusPanelItems.Completion, PredefinedMessages.WaitUntilCompletionFinished(pp.Setting.Culture), PredefinedMessages.CompletionFailed(pp.Setting.Culture), 1 * 60)); + + } + else + { + listOfProgrammParts.Add(new TemperatureCalibrationProcess("Temperature Calibration", StatusPanelItems.TempCal, PredefinedMessages.WaitUntilTemperatureCalibrationFinished(pp.Setting.Culture), PredefinedMessages.TempCalFailed(pp.Setting.Culture), 2 * 60)); + + if (!pp.Setting.TempOnly) + { + listOfProgrammParts.Add(new OffsetTestProcess("Offset Test", StatusPanelItems.Offset, PredefinedMessages.WaitUntilZeroflowOffsetTestFinished(pp.Setting.Culture), PredefinedMessages.ZeroflowOffsetTestFailed(pp.Setting.Culture), 18 * 60)); + } + listOfProgrammParts.Add(new CompletionProcess("Completion", StatusPanelItems.Completion, PredefinedMessages.WaitUntilCompletionFinished(pp.Setting.Culture), PredefinedMessages.CompletionFailed(pp.Setting.Culture), 1 * 60)); + + } + + + var t = new Task(() => { try diff --git a/Common/CordonelPreadjustmentUi/Processes/ActionsSinglePath/DemoProcess.cs b/Common/CordonelPreadjustmentUi/Processes/ActionsSinglePath/DemoProcess.cs new file mode 100644 index 00000000..c8df0cc4 --- /dev/null +++ b/Common/CordonelPreadjustmentUi/Processes/ActionsSinglePath/DemoProcess.cs @@ -0,0 +1,85 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.Eventing.Reader; +using System.Linq; +using System.Text; +using CordonelPreadjustmentUi.Processes.Itinerary; +using System.Threading; +using static CordonelPreadjustmentUi.PreAdjustmentControl; +using System.Threading.Tasks; + +namespace CordonelPreadjustmentUi.Processes.Actions +{ + public class DemoProcess : BaseProcess + { + public DemoProcess(string processName, StatusPanelItems panelState, string performMessage, string failedMessage ) : base(processName, panelState, performMessage, failedMessage ) + { + } + + public override List StartWork() + { + return doWorkProcess(base.CurrentProcessProgress); + } + + private List doWorkProcess(ProcessProgress pp) + { + var MetersToProcess = MeterStateCtls.Where(e => e.IsEnabled).ToList(); + + var listOfProcessTask = new List(); + + foreach (var meterctl in MetersToProcess) + { + listOfProcessTask.Add(new Task(() => + { + var Result = false; + for (int i = 0; i < 3; i++) + { + pp.DebugMessage = $"\tCOMMAND CHANNEL: \t Performing {ProcessName} procedure\n"; + + try + { + Result = string.IsNullOrEmpty(meterctl.OverridePassword) + ? meterctl.Meter.Login() + : meterctl.Meter.Login(meterctl.OverridePassword); + + if (Result) + { + break; + } + Thread.Sleep(100); + } + catch (Exception e) + { + pp.DebugMessage = $"\tCOMMAND CHANNEL: \t Error on {ProcessName} procedure\n"; + } + + } + + var meterIndex = (meterctl.Slot).ToString(pp.Setting.Culture); + meterctl.Failed = !Result; + if (!Result) + { + pp.DebugMessage = $"\tCOMMAND CHANNEL: \t {ProcessName} procedure failed at METER{meterIndex}\n"; + } + else + { + pp.DebugMessage = $"\tCOMMAND CHANNEL: \t {ProcessName} procedure successful at METER{meterIndex}\n"; + pp.GenerateReturnNote($"{meterctl.Slot}", meterctl.Meter.PcbId, PredefinedMessages.LoginFailed(pp.Setting.Culture)); + } + + return Result; + + })); + + } + + + return listOfProcessTask; + + } + + } + + + +} diff --git a/Common/CordonelPreadjustmentUi/Processes/ActionsSinglePath/SPAmplitudeTestProcess.cs b/Common/CordonelPreadjustmentUi/Processes/ActionsSinglePath/SPAmplitudeTestProcess.cs new file mode 100644 index 00000000..5e1f7ffb --- /dev/null +++ b/Common/CordonelPreadjustmentUi/Processes/ActionsSinglePath/SPAmplitudeTestProcess.cs @@ -0,0 +1,527 @@ +using CordonelPreadjustmentUi.Const; +using CordonelPreadjustmentUi.Helper; +using CordonelPreadjustmentUi.Helper.Extensions; +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.Registers; +using static CordonelPreadjustmentUi.PreAdjustmentControl; + +namespace CordonelPreadjustmentUi.Processes.Actions +{ + public class SPAmplitudeTestProcess : BaseProcess + { + public SPAmplitudeTestProcess(string processName, StatusPanelItems panelState, string performMessage, string failedMessage, int? expectedTimeS) : base(processName, panelState, performMessage, failedMessage, expectedTimeS) + { + } + + public override List StartWork() + { + return doWorkProcess(base.CurrentProcessProgress); + } + + private List doWorkProcess(ProcessProgress pp) + { + var MetersToProcess = MeterStateCtls.Where(e => e.IsEnabled).ToList(); + + var listOfProcessTask = new List(); + + foreach (var meterctl in MetersToProcess) + { + listOfProcessTask.Add(new Task(() => + { + + pp.DebugMessage($"Performing {ProcessName} procedure", null, "CC"); + + #region Definitions and initializations + const Int32 FirstHitShiftValue = 4; + const Int32 FirstHitShiftValueEnd = 4; + const Int32 FirstHitUpdatePeriodeValue = 1; + const Int32 FirstHitUpdatePeriodeValueEnd = 10; + const Int32 WaitBeforeLogging = 5; + String DebugMessage = String.Empty; + + var TofAvgMean = new MultiPathDataLogContainer(pp.Setting.NumberOfPaths); + var OptimalPoint = new MultiPathDataLogContainer(pp.Setting.NumberOfPaths); + var TofAvgMeanTotal = new MultiPathDataLogContainer>(pp.Setting.NumberOfPaths); + TofAvgMeanTotal.Update(null, new List()); + + Boolean Ok = false; + #endregion + #region StartLogging + if (pp.Setting.AmpTestGenerateLogfiles) + { + String time = System.DateTime.Now.ToString(Formats.LogFileDateTimeString); + String Header = $"Genesis ZeroFlowOffsetCalibration {meterctl.Meter.Slot}; PCB ID = {meterctl.Meter.PcbId}; Date = {time}; Operator = {Environment.UserName}\n"; + meterctl.Meter.DataLog(Header); + //GenesisZeroFlow._GenesisZeroFlow.SetLoggingPathAmplitudeTest(this.MeterNumber, $"{DataLogging.DefaultPath}AmplitudeTest_RawData_{TempPcbID}_{time}.txt"); + meterctl.Meter.logAmpTest = true; + pp.DebugMessage($" Start logging", meterctl.Meter.Slot, "DC", meterctl.Meter.PcbId); + } + #endregion + + + Ok = false; + + Ok = WriteRegisterSafe(meterctl.Meter, "First hit update period", Register.Genesisflow.FirstHitUpdatePeriod, FirstHitUpdatePeriodeValue); + if (CheckAbort(Ok, meterctl)) { return Ok; } + + pp.StatusLabel = (PredefinedMessages.WaitUntilRegisterWriteFinished(pp.Setting.Culture)); + Ok = false; + Ok = WriteRegisterSafe(meterctl.Meter, "WorkAround TriggerIdle", Register.Genesisflow.TriggerIdle, 1, false); + Thread.Sleep(150); + + pp.StatusLabel = (PredefinedMessages.WaitUntilRegisterWriteFinished(pp.Setting.Culture)); + Ok = false; + Ok = WriteRegisterSafe(meterctl.Meter, "first hit shift", Register.Genesisflow.FirstHitShift, FirstHitShiftValueEnd); + + Thread.Sleep(150); + pp.StatusLabel = (PredefinedMessages.WaitUntilRegisterWriteFinished(pp.Setting.Culture)); + Ok = false; + Ok = WriteRegisterSafe(meterctl.Meter, "WorkAround TriggerActive", Register.Genesisflow.TriggerActive, 1, false); + Thread.Sleep(150); + + #region Set first hit level percentage from 5 to 35 + pp.DebugMessage($"Start first hit level percentage sweep ", meterctl.Meter.Slot, "DC", meterctl.Meter.PcbId); + for (Int32 FirstHitLevelPercentage = pp.Setting.AmpTestPercentageStart; FirstHitLevelPercentage <= pp.Setting.AmpTestPercentageStop; FirstHitLevelPercentage++) + { + if (CheckAbort(Ok, meterctl)) { return Ok; } + + pp.StatusLabel = $"{PredefinedMessages.WaitUntilPercentageSweepFinished(pp.Setting.Culture)} {FirstHitLevelPercentage.ToString(pp.Setting.Culture)}/{pp.Setting.AmpTestPercentageStop.ToString(pp.Setting.Culture)}"; + #region Write to percentage register PATH0 + + Ok = false; + + Ok = WriteRegisterSafe(meterctl.Meter, "Percentage", Register.Genesisflow.FirstHitPercent2, FirstHitLevelPercentage); + if (CheckAbort(Ok, meterctl)) { return Ok; } + #endregion + + #region Wait for 1 second + for (Int32 i = 0; i < WaitBeforeLogging; i++) + { + Thread.Sleep(200); + } + #endregion + #region Record TOF + + + Ok = RecordData(pp, meterctl, Ok, FirstHitLevelPercentage); + + bool retryRecord = false; + if (true) + { + if (!meterctl.Meter.listOfTotalTimeOfFlightSPerPath.Get(1).Any()) + { + pp.StatusLabel = $"No Data for Path {1}. Start one recollect"; + + retryRecord = true; + } + } + else + { + //for (UInt16 Path = 0; Path < meterctl.Meter.listOfTotalTimeOfFlightSPerPath.GetPathCount(); Path++) + //{ + // if (!meterctl.Meter.listOfTotalTimeOfFlightSPerPath.Get(Path).Any()) + // { + // pp.StatusLabel = $"No Data for Path {Path}. Start one recollect"; + + // retryRecord = true; + // } + + //} + } + + if (retryRecord) + { + Ok = RecordData(pp, meterctl, Ok, FirstHitLevelPercentage); + } + + + pp.StatusLabel = $"{PredefinedMessages.WaitUntilPercentageSweepFinished(pp.Setting.Culture)} {FirstHitLevelPercentage.ToString(pp.Setting.Culture)}/{ pp.Setting.AmpTestPercentageStop.ToString(pp.Setting.Culture)}; 0s"; + Ok = true; + #endregion + #region Calculate mean value + UInt16 Path = 1; + + var meanVal = meterctl.Meter.listOfTotalTimeOfFlightSPerPath.Get(Path).ToList().Mean(); + pp.DebugMessage($"Calculate mean value {meanVal} at {meterctl.Meter.Slot}; PATH{(Path + 1).ToString(pp.Setting.Culture)}", meterctl.Meter.Slot, "DC", meterctl.Meter.PcbId); + //earlier TofAvgMeanTotal + //TofAvgMean.Update(Path, meanVal); + + if (meanVal == 0) + { + pp.DebugMessage($"Mean value is zero at {meterctl.Meter.Slot}; PATH{(Path + 1).ToString(pp.Setting.Culture)}; Value = {Math.Round(meanVal, 4).ToString("000.0000", pp.Setting.Culture)}", meterctl.Meter.Slot, "DC", meterctl.Meter.PcbId); + meterctl.Meter.calibrationResult.AddAdditionalLog($"" + + $"PATH {Path + 1}", Math.Round(meanVal, 4).ToString("000.0000", pp.Setting.Culture)); + + if (CheckAbort(false, meterctl)) { return false; } + } + + pp.DebugMessage($"Mean value at {meterctl.Meter.Slot}; PATH{(Path + 1).ToString(pp.Setting.Culture)}; Value = {Math.Round(meanVal, 4).ToString("000.0000", pp.Setting.Culture)}", meterctl.Meter.Slot, "DC", meterctl.Meter.PcbId); + + meterctl.Meter.calibrationResult.AddAdditionalLog($"Amp. Test Mean value PATH {Path + 1}", $"at {FirstHitLevelPercentage}={Math.Round(meanVal, 4).ToString("000.0000", pp.Setting.Culture)}"); + var cTofAvgMeanTotal = TofAvgMeanTotal.Get(0).ToList(); + + cTofAvgMeanTotal.Add(meanVal); + TofAvgMeanTotal.Update(0, cTofAvgMeanTotal); + //meterctl.Meter.listOfTotalTimeOfFlightSPerPath.Update(Path,new List()); + + + #endregion + } + #endregion + #region Write raw data to files + //if (this.GenerateLogFiles) + //{ + // GenesisZeroFlow._GenesisZeroFlow.SetLoggingIndicatorAmpTest(this.MeterNumber, false); + // String temp = GenesisZeroFlow._GenesisZeroFlow.GetDataToLog()[this.MeterNumber]; + // pp.DebugMessage =$"{meterctl.Meter.PcbId}\tAPPLICATION:\t\t Write data to files at {meterctl.Meter.Slot}\n"; + // Logging.WriteToFile(temp, GenesisZeroFlow._GenesisZeroFlow.GetLoggingPathAmplitudeTest()[this.MeterNumber]); + //} + #endregion + #region Write mean values to file + //String DateTime = System.DateTime.Now.ToString(Formats.LogFileDateTimeString; + //if (this.GenerateMeanFiles) + //{ + // for (UInt16 Path = Constants.PATH0; Path < Constants.NumberOfPaths; Path++) + // Logging.WriteToFile(GenesisZeroFlow._GenesisZeroFlow.GetAmpValuesToLog()[this.MeterNumber][Constants.PATH0], $@"..\ZeroflowCalibrationTool_MeanAmplitude_{meterctl.Meter.Slot}_PATH{Path + 1}_{TempPcbID}_{DateTime}.csv"); + //} + + + //this.ClearData(); + //#endregion + #region Calculate optimal point + + var DistanceLeft = new MultiPathDataLogContainer(pp.Setting.NumberOfPaths); + var DistanceRight = new MultiPathDataLogContainer(pp.Setting.NumberOfPaths); + + var CalculationFailed = new MultiPathDataLogContainer(pp.Setting.NumberOfPaths); + + pp.DebugMessage($"Start calculating optimal points", meterctl.Meter.Slot, "DC", meterctl.Meter.PcbId); + + for (UInt16 Path = 0; Path < TofAvgMeanTotal.GetPathCount(); Path++) + { + var tmpOptimalPoint = 0; + var tmpDistanceLeft = 0.0; + var tmpDistanceRight = 0.0; + + var r = CalculateOptimalPoint(pp, meterctl.Meter.Slot, TofAvgMeanTotal.Get(Path).ToList(), out tmpDistanceLeft, out tmpDistanceRight, out tmpOptimalPoint); + OptimalPoint.Update(Path, tmpOptimalPoint); + DistanceLeft.Update(Path, tmpDistanceLeft); + DistanceRight.Update(Path, tmpDistanceRight); + + CalculationFailed.Update(Path, r); + + if (!r) + { + meterctl.Meter.calibrationResult.AddAdditionalLog($"Amp. Test OptimalPoint PATH {Path + 1}", OptimalPoint.Get(Path).ToString(pp.Setting.Culture)); + pp.DebugMessage($"Optimal point calculation successful PATH{Path + 1}; Value = {OptimalPoint.Get(Path).ToString(pp.Setting.Culture)}", meterctl.Meter.Slot, "DC", meterctl.Meter.PcbId); + } + else + { + meterctl.Meter.calibrationResult.AddAdditionalLog($"Amp. Test OptimalPoint PATH {Path + 1}", "NaN"); + pp.DebugMessage($"Optimal point calculation failed, PATH{Path + 1}", meterctl.Meter.Slot, "DC", meterctl.Meter.PcbId); + if (CheckAbort(!r, meterctl)) { return !r; } + } + + } + #endregion + #region Check value + pp.DebugMessage($"Start optimal point values check", meterctl.Meter.Slot, "DC", meterctl.Meter.PcbId); + + Boolean OptimalPointOK = true; + for (UInt16 Path = 0; Path < OptimalPoint.GetPathCount(); Path++) + { + if (!this.CheckOptimalPoint(pp, OptimalPoint.Get(Path), out DebugMessage, meterctl.Meter.Slot)) + { + OptimalPointOK = false; + } + + pp.DebugMessage($"{DebugMessage}, PATH{Path + 1}", meterctl.Meter.Slot, "DC", meterctl.Meter.PcbId); + } + + if (CheckAbort(OptimalPointOK, meterctl)) { return OptimalPointOK; } + #endregion + #region Check distance + Boolean CheckDistOK = true; + for (UInt16 Path = 0; Path < DistanceLeft.GetPathCount(); Path++) + { + if (!this.CheckDistance(pp, DistanceLeft.Get(Path), DistanceRight.Get(Path), out DebugMessage, meterctl.Meter.Slot)) + { + CheckDistOK = false; + } + + pp.DebugMessage($"{DebugMessage}, PATH{Path + 1}", meterctl.Meter.Slot, "DC", meterctl.Meter.PcbId); + } + if (CheckAbort(CheckDistOK, meterctl)) { return CheckDistOK; } + + #endregion + #region Set first hit level percentage registers + pp.DebugMessage($"Start writing to percentage registers", meterctl.Meter.Slot, "CC", meterctl.Meter.PcbId); + + pp.StatusLabel = ($"{PredefinedMessages.WaitUntilRegisterWriteFinished(pp.Setting.Culture)}"); + Ok = false; + String RegValue = Register.Genesisflow.FirstHitPercent2; + + + Ok = WriteRegisterSafe(meterctl.Meter, "Percentage", RegValue, OptimalPoint.Get(0)); + if (CheckAbort(Ok, meterctl)) { return Ok; } + + #endregion + + //here + + #region Set first hit update period to 10 + pp.StatusLabel = (PredefinedMessages.WaitUntilRegisterWriteFinished(pp.Setting.Culture)); + Ok = false; + Ok = WriteRegisterSafe(meterctl.Meter, "first hit update period", Register.Genesisflow.FirstHitUpdatePeriod, FirstHitUpdatePeriodeValueEnd); + if (CheckAbort(Ok, meterctl)) { return Ok; } + #endregion + + #region Wait for 1 second + for (Int32 i = 0; i < WaitBeforeLogging; i++) + { + Thread.Sleep(300); + } + #endregion + + + + #region Set first hit shift to 4 + //Frost, Alex Do 02.07.2020 17:12 + //RE: Writing 4 to 'First hit shift'-register failed + //I think a workaround would be to go into idle mode before changing this register then back to active mode after.I haven’t tried this out yet + pp.StatusLabel = (PredefinedMessages.WaitUntilRegisterWriteFinished(pp.Setting.Culture)); + Ok = false; + Ok = WriteRegisterSafe(meterctl.Meter, "WorkAround TriggerIdle", Register.Genesisflow.TriggerIdle, 1, false); + Thread.Sleep(150); + pp.StatusLabel = (PredefinedMessages.WaitUntilRegisterWriteFinished(pp.Setting.Culture)); + Ok = false; + Ok = WriteRegisterSafe(meterctl.Meter, "first hit shift", Register.Genesisflow.FirstHitShift, FirstHitShiftValueEnd); + Thread.Sleep(150); + pp.StatusLabel = (PredefinedMessages.WaitUntilRegisterWriteFinished(pp.Setting.Culture)); + Ok = false; + Ok = WriteRegisterSafe(meterctl.Meter, "WorkAround TriggerActive", Register.Genesisflow.TriggerActive, 1, false); + Thread.Sleep(150); + + if (CheckAbort(Ok, meterctl)) { return Ok; } + #endregion + #endregion + return Ok; + })); + + } + + + return listOfProcessTask; + + } + + private bool RecordData(ProcessProgress pp, MeterStateControl meterctl, bool Ok, int FirstHitLevelPercentage) + { + meterctl.Meter.listOfTotalTimeOfFlightSPerPath.Update(null, new List()); + meterctl.Meter.logAmpTest = true; + + pp.DebugMessage($"Start collecting data", meterctl.Meter.Slot, "DC", meterctl.Meter.PcbId); + var LinecounterFollowing = new MultiPathDataLogContainer(pp.Setting.NumberOfPaths); + + + for (Int32 Seconds = 0; Seconds < pp.Setting.AmpTestTofRecordingTime; Seconds++) // eight seconds remove /2 + { + if (Int32.Equals((Seconds % pp.Setting.AmpTestActivityCheckInverval), 0)) + { + pp.StatusLabel = $"{PredefinedMessages.WaitUntilPercentageSweepFinished(pp.Setting.Culture)} {FirstHitLevelPercentage.ToString(pp.Setting.Culture)}/{ pp.Setting.AmpTestPercentageStop.ToString(pp.Setting.Culture)}; {(pp.Setting.AmpTestTofRecordingTime - Seconds).ToString(pp.Setting.Culture)}s"; + + Thread.Sleep(1000); + Ok = ActivityCheck(pp, meterctl.Meter.listOfTotalTimeOfFlightSPerPath, pp.Setting.AmpTestTofRecordingTime); + if (!Ok) + { + pp.DebugMessage($"Activity check failed", meterctl.Meter.Slot, "DC", meterctl.Meter.PcbId); + // if (CheckAbort(Ok, meterctl)) { return Ok; } + } + + } + + } + + return Ok; + } + + private Boolean CalculateOptimalPoint(ProcessProgress pp, int Slot, List TofAvg, out Double left, out Double right, out Int32 xAtOptimalPoint) + { + + List ValuesLeft = new List(); + List ValuesRight = new List(); + List MinDistance = new List(); + xAtOptimalPoint = 0; + Boolean SubError = true; + left = 0; + right = 0; + + ValuesLeft = this.CalculateNearestDistanceLeft(pp, TofAvg, out left); + ValuesRight = this.CalculateNearestDistanceRight(pp, TofAvg, out right); + + for (UInt16 i = 0; i < ValuesLeft.Count(); i++) + { + Double temp1 = ValuesLeft.ElementAt(i); + Double temp2 = ValuesRight.ElementAt(i); + Thread.Sleep(10); + MinDistance.Add(Math.Min(temp1, temp2)); + } + + //String mindistance = $"mindistance: PATH{path.ToString(GlobalCulture)}\n"; + //for (Int16 i = 0; i < MinDistance.Count(); i++) + //{ + // Double temp = MinDistance.ElementAt(i); + // Misc.WaitNMilliseconds(10); + // mindistance = $"{mindistance}{temp.ToString(GlobalCulture)}\n"; + //} + //Logging.WriteToFile(mindistance, @"..\mindistance_PATH"+ path.ToString() + ".txt"); + + Double Maximum = 0; + + for (Int16 i = 0; i < MinDistance.Count(); i++) + { + if ((!Int16.Equals(i, 0)) && (!Int16.Equals(i, (Int16)(TofAvg.Count() - 1)))) + { + if (MinDistance.ElementAt(i) > Maximum) + { + Maximum = MinDistance.ElementAt(i); + xAtOptimalPoint = (Int32)i + pp.Setting.AmpTestPercentageStart; + ; + SubError = false; + } + } + } + + return SubError; + } + private List CalculateNearestDistanceLeft(ProcessProgress pp, List TofAvg, out Double left) + { + List Distance = new List(); + Double NearestDistance = 0; + Boolean Detected = false; + left = 0; + + for (Int32 Percentage = pp.Setting.AmpTestFirstHitLevelPropMin; Percentage <= pp.Setting.AmpTestFirstHitLevelPropMax; Percentage++) + { + Detected = false; + for (Int32 PercentageFollowing = Percentage; PercentageFollowing <= pp.Setting.AmpTestFirstHitLevelPropMax; PercentageFollowing++) + { + if ((TofAvg.ElementAt(PercentageFollowing - pp.Setting.AmpTestFirstHitLevelPropMin) - TofAvg.ElementAt(Percentage - pp.Setting.AmpTestFirstHitLevelPropMin)) > pp.Setting.AmpTestTriggerValue) + { + NearestDistance = PercentageFollowing - Percentage; + Detected = true; + break; + } + } + if (!Detected) + { + NearestDistance = pp.Setting.AmpTestFirstHitLevelPropMax - Percentage; + } + + Distance.Add(NearestDistance); + } + + for (Int16 i = 0; i < (Int16)Distance.Count(); i++) + { + if (Distance.ElementAt(i) >= left) + { + left = Distance.ElementAt(i); + } + } + return Distance; + } + private List CalculateNearestDistanceRight(ProcessProgress pp, List TofAvg, out Double right) + { + List Distance = new List(); + Double NearestDistance = 0; + Boolean Detected = false; + right = 0; + + for (Int32 Percentage = pp.Setting.AmpTestFirstHitLevelPropMax; Percentage >= (pp.Setting.AmpTestFirstHitLevelPropMin); Percentage--) + { + Detected = false; + + for (Int32 ProportionFollowing = Percentage; ProportionFollowing >= pp.Setting.AmpTestFirstHitLevelPropMin; ProportionFollowing--) + { + if ((TofAvg.ElementAt(ProportionFollowing - pp.Setting.AmpTestFirstHitLevelPropMin)) - (TofAvg.ElementAt(Percentage - pp.Setting.AmpTestFirstHitLevelPropMin)) < -pp.Setting.AmpTestTriggerValue) + { + NearestDistance = Percentage - ProportionFollowing; + Detected = true; + break; + } + } + + if (!Detected) + { + NearestDistance = Percentage - pp.Setting.AmpTestFirstHitLevelPropMin; + } + + Distance.Add(NearestDistance); + } + + + Distance.Reverse(); + + for (Int16 i = 0; i < Distance.Count(); i++) + { + if (Distance.ElementAt(i) >= right) + { + right = Distance.ElementAt(i); + } + } + return Distance; + } + private Boolean CheckOptimalPoint(ProcessProgress pp, Int32 optimalPoint, out String debugMessage, int Slot) + { + Boolean Ok = true; + debugMessage = $"Optimal point check successful at {Slot}"; + // ampTestLowerLimit, ampTestUpperLimit, ampTestDistance + if (optimalPoint > pp.Setting.AmpTestFirstHitLevelPropMax) + { + debugMessage = $"Optimal point maximum check failed at {Slot}"; + Ok = false; + return Ok; + } + + if (optimalPoint < pp.Setting.AmpTestFirstHitLevelPropMin) + { + debugMessage = $"Optimal point minimum check failed at {Slot}"; + Ok = false; + return Ok; + } + + return Ok; + } + private Boolean CheckDistance(ProcessProgress pp, Double left, Double right, out String debugMessage, int Slot) + { + Boolean Ok = true; + debugMessage = $"Distance check successful at {Slot}"; + + if (left < pp.Setting.AmpTestFirstHitLevelPropMin) + { + Ok = false; + debugMessage = $"Distance check failed at {Slot}"; + return Ok; + } + + if (right < pp.Setting.AmpTestFirstHitLevelPropMin) + { + Ok = false; + debugMessage = $"Distance check failed at {Slot}"; + return Ok; + } + + return Ok; + } + + + } + + + +} \ No newline at end of file diff --git a/Common/CordonelPreadjustmentUi/Processes/ActionsSinglePath/SPCompletionProcess.cs b/Common/CordonelPreadjustmentUi/Processes/ActionsSinglePath/SPCompletionProcess.cs new file mode 100644 index 00000000..4a013b26 --- /dev/null +++ b/Common/CordonelPreadjustmentUi/Processes/ActionsSinglePath/SPCompletionProcess.cs @@ -0,0 +1,189 @@ +using CordonelPreadjustmentUi.Processes.Itinerary; +using Logic.ProductionToProductMapper.Cordonel; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Threading.Tasks; +using Xylem.Common.CommonCore.Configuration; +using Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore.Consts; +using Xylem.Common.Hardware.WaterMeter.Genesis.Registers; +using Xylem.Common.Hardware.WaterMeter.WaterMeterCore.Consts; +using Xylem.Common.Logic.SoftwareAccessHelper; +using static CordonelPreadjustmentUi.PreAdjustmentControl; + +namespace CordonelPreadjustmentUi.Processes.Actions +{ + public class SPCompletionProcess : BaseProcess + { + + public SPCompletionProcess(string processName, StatusPanelItems panelState, string performMessage, string failedMessage, int? expectedTimeS) : base(processName, panelState, performMessage, failedMessage, expectedTimeS) + { + } + + public override List StartWork() + { + return doWorkProcess(base.CurrentProcessProgress); + } + + private List doWorkProcess(ProcessProgress pp) + { + var MetersToProcess = MeterStateCtls.Where(e => e.IsEnabled).ToList(); + + var listOfProcessTask = new List(); + + foreach (var meterctl in MetersToProcess) + { + listOfProcessTask.Add(new Task(() => + { + var Result = true; + pp.DebugMessage($"Performing {ProcessName} procedure", null, "APP"); + + try + { + + var Ok = false; + Ok = WriteRegisterSafe(meterctl.Meter, $"Samplerate", Register.Genesisflow.SampleRate, 10); + if (CheckAbort(Ok, meterctl)) { return Ok; } + Ok = WriteRegisterSafe(meterctl.Meter, $"LED mode", Register.Genesisflow.LedMode, (Byte)6); + if (CheckAbort(Ok, meterctl)) { return Ok; } + Ok = WriteRegisterSafe(meterctl.Meter, $"Store calibration", Register.Genesisflow.StoreCalibration, 1, false); + if (CheckAbort(Ok, meterctl)) { return Ok; } + pp.DebugMessage($"Read out", meterctl.Slot, "CC"); + + + + + var readsOk = new List(); + byte[] retByte; + readsOk.Add(ReadRegister(meterctl.Meter, "MeterSize", Register.Genesisflow.MeterSize, out retByte)); + meterctl.Meter.calibrationResult.MeterSize = RegisterConverter.ByteArrayToValue(retByte); + readsOk.Add(ReadRegister(meterctl.Meter, "CalFactor1", Register.Genesisflow.CalFactor1, out retByte)); + meterctl.Meter.calibrationResult.CalFactor1 = RegisterConverter.ByteArrayToValue(retByte); + readsOk.Add(ReadRegister(meterctl.Meter, "CalFactor2", Register.Genesisflow.CalFactor2, out retByte)); + meterctl.Meter.calibrationResult.CalFactor2 = RegisterConverter.ByteArrayToValue(retByte); + readsOk.Add(ReadRegister(meterctl.Meter, "CalFactor3", Register.Genesisflow.CalFactor3, out retByte)); + meterctl.Meter.calibrationResult.CalFactor3 = RegisterConverter.ByteArrayToValue(retByte); + readsOk.Add(ReadRegister(meterctl.Meter, "ZeroOffset1", Register.Genesisflow.ZeroOffset1, out retByte)); + meterctl.Meter.calibrationResult.ZeroOffset1 = RegisterConverter.ByteArrayToValue(retByte); + readsOk.Add(ReadRegister(meterctl.Meter, "ZeroOffset2", Register.Genesisflow.ZeroOffset2, out retByte)); + meterctl.Meter.calibrationResult.ZeroOffset2 = RegisterConverter.ByteArrayToValue(retByte); + readsOk.Add(ReadRegister(meterctl.Meter, "ZeroOffset3", Register.Genesisflow.ZeroOffset3, out retByte)); + meterctl.Meter.calibrationResult.ZeroOffset3 = RegisterConverter.ByteArrayToValue(retByte); + readsOk.Add(ReadRegister(meterctl.Meter, "FirstHitUpdatePeriod", Register.Genesisflow.FirstHitUpdatePeriod, out retByte)); + meterctl.Meter.calibrationResult.FirstHitUpdatePeriod = RegisterConverter.ByteArrayToValue(retByte); + readsOk.Add(ReadRegister(meterctl.Meter, "FirstHitShift", Register.Genesisflow.FirstHitShift, out retByte)); + meterctl.Meter.calibrationResult.FirstHitShift = RegisterConverter.ByteArrayToValue(retByte); + readsOk.Add(ReadRegister(meterctl.Meter, "FirstHitPercent1", Register.Genesisflow.FirstHitPercent1, out retByte)); + meterctl.Meter.calibrationResult.FirstHitPercent1 = RegisterConverter.ByteArrayToValue(retByte); + readsOk.Add(ReadRegister(meterctl.Meter, "FirstHitPercent2", Register.Genesisflow.FirstHitPercent2, out retByte)); + meterctl.Meter.calibrationResult.FirstHitPercent2 = RegisterConverter.ByteArrayToValue(retByte); + readsOk.Add(ReadRegister(meterctl.Meter, "FirstHitPercent3", Register.Genesisflow.FirstHitPercent3, out retByte)); + meterctl.Meter.calibrationResult.FirstHitPercent3 = RegisterConverter.ByteArrayToValue(retByte); + readsOk.Add(ReadRegister(meterctl.Meter, "ToFTempOffset1", Register.Genesisflow.ToFTempOffset1, out retByte)); + meterctl.Meter.calibrationResult.ToFTempOffset1 = RegisterConverter.ByteArrayToValue(retByte); + readsOk.Add(ReadRegister(meterctl.Meter, "ToFTempOffset2", Register.Genesisflow.ToFTempOffset2, out retByte)); + meterctl.Meter.calibrationResult.ToFTempOffset2 = RegisterConverter.ByteArrayToValue(retByte); + readsOk.Add(ReadRegister(meterctl.Meter, "ToFTempOffset3", Register.Genesisflow.ToFTempOffset3, out retByte)); + meterctl.Meter.calibrationResult.ToFTempOffset3 = RegisterConverter.ByteArrayToValue(retByte); + + if (readsOk.Any(a => !a)) + { + Ok = false; + } + if (CheckAbort(Ok, meterctl)) { return Ok; } + + Exception exPost = new Exception(); + int code = 0; + var tempP = ""; + + if (meterctl.Meter.calibrationResult.AdditionalLogInfos.TryGetValue("Amp. Test Mean value PATH 1", out tempP)) + { + tempP = tempP.Replace(" at ", "").Replace("at ", ""); + tempP = tempP.Replace(System.Environment.NewLine, ";"); + + meterctl.Meter.calibrationResult.AdditionalLogInfos["Amp. Test Mean value PATH 1"] = tempP; + } + + if (meterctl.Meter.calibrationResult.AdditionalLogInfos.TryGetValue("Amp. Test Mean value PATH 2", out tempP)) + { + tempP = tempP.Replace(" at ", "").Replace("at ", ""); ; + tempP = tempP.Replace(System.Environment.NewLine, ";"); + + meterctl.Meter.calibrationResult.AdditionalLogInfos["Amp. Test Mean value PATH 2"] = tempP; + } + + if (meterctl.Meter.calibrationResult.AdditionalLogInfos.TryGetValue("Amp. Test Mean value PATH 3", out tempP)) + { + tempP = tempP.Replace(" at ", "").Replace("at ", ""); ; + tempP = tempP.Replace(System.Environment.NewLine, ";"); + + meterctl.Meter.calibrationResult.AdditionalLogInfos["Amp. Test Mean value PATH 3"] = tempP.Trim(); + } + + + var r = LocalWebRequest.PostRequestAsync($"{ServiceUrls.PostGenesisCalibrationResultUrl()}?PcbId={meterctl.Meter.PcbId}", ref code, ref exPost, 8000, meterctl.Meter.calibrationResult); + if (!r) + { + meterctl.Meter.WriteLog($"Could not store CalibrationResults on server CODE {code}EX:{exPost} "); + + foreach (var item in meterctl.Meter.calibrationResult.AdditionalLogInfos) + { + meterctl.Meter.WriteLog($"AdditionalLogInfos {item.Key} -> {item.Value} "); + } + + throw new Exception("Could not store CalibrationResults on server"); + } + if (pp.IsAutomaticMode) + { + // meterctl.Meter.SetProcessState(Xylem.Common.Hardware.WaterMeter.WaterMeterCore.Consts.DisplayCodes.ZeroFlow); + + } + + } + catch (Exception e) + { + pp.DebugMessage($"Error on {ProcessName} procedure", null, "APP"); + pp.DebugMessage($"{e.Message}", null, "APP"); + } + + var meterIndex = (meterctl.Slot).ToString(pp.Setting.Culture); + meterctl.Failed = !Result; + if (!Result) + { + if (pp.IsAutomaticMode) + { + meterctl.Meter.SetProcessState(DisplayCodes.ZeroFlowFailed); + } + pp.DebugMessage($"{ProcessName} procedure failed", meterctl.Slot, "APP", meterctl.Meter.PcbId); + pp.GenerateReturnNote(PredefinedMessages.CompletionFailed(pp.Setting.Culture), meterctl); + + } + else + { + + pp.DebugMessage($"{ProcessName} procedure successful", meterctl.Slot, "APP", meterctl.Meter.PcbId); + if (pp.IsAutomaticMode) + { + //meterctl.Meter.SetProcessState(Xylem.Common.Hardware.WaterMeter.WaterMeterCore.Consts.DisplayCodes.ZeroFlow); + } + + } + meterctl.Meter.PushProgress("CordonelPreadjustmentUi", Assembly.GetExecutingAssembly().GetName().Version.ToString()); + + return Result; + + })); + + } + + + return listOfProcessTask; + + } + + } + + + +} diff --git a/Common/CordonelPreadjustmentUi/Processes/ActionsSinglePath/SPOffsetTestProcess.cs b/Common/CordonelPreadjustmentUi/Processes/ActionsSinglePath/SPOffsetTestProcess.cs new file mode 100644 index 00000000..931db2ea --- /dev/null +++ b/Common/CordonelPreadjustmentUi/Processes/ActionsSinglePath/SPOffsetTestProcess.cs @@ -0,0 +1,290 @@ +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 SPOffsetTestProcess : BaseProcess + { + public SPOffsetTestProcess(string processName, StatusPanelItems panelState, string performMessage, string failedMessage, int? expectedTimeS) : base(processName, panelState, performMessage, failedMessage, expectedTimeS) + { + } + + public override List StartWork() + { + return doWorkProcess(base.CurrentProcessProgress); + } + + private List doWorkProcess(ProcessProgress pp) + { + var MetersToProcess = MeterStateCtls.Where(e => e.IsEnabled).ToList(); + + var listOfProcessTask = new List(); + + + listOfProcessTask.Add(new Task(() => + { + + #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(); + + foreach (var meterctl in MetersToProcess) + { + meterctl.Meter.CurrentRecords.Clear(); + + listOfSubTask.Add(new Task(() => + { + 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(pp.Setting.NumberOfPaths); + var MaxTimeoutWarnings = 300; + pataDataActivitCheck.Update(null, -1); + Thread.Sleep(1800); + var Path = 1; + while (PerformCheck) + { + var offsetRecords = new List(); + 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);// + var PathSum = 1; + var currentCount = offsetRecords.Count(c => c.Channel == PathSum + 1);// immer 2 + var oldCound = pataDataActivitCheck.Get(0);// immer 0 + 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(0, 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; + + 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>(pp.Setting.NumberOfPaths); + var PathDataContainer = new MultiPathDataLogContainer>(pp.Setting.NumberOfPaths); + + + var offsetRecordsB = meterctl.Meter.CurrentRecords.ToList().Where(c => (c.Channel == (Path + 1)) && c.IsValid).ToList(); + PathDataContainer.Update(Path, offsetRecordsB); + + offsetRecordsB = meterctl.Meter.CurrentRecords.ToList().Where(c => (c.Channel == (Path + 1)) && !c.IsValid).ToList(); + PathDataContainerBaddata.Update(Path, offsetRecordsB); + + + + #region Calculating mean values + + pp.DebugMessage($"Calculating mean values", meterctl.Meter.Slot, "APP", meterctl.Meter.PcbId); + + var amplitudeValuesMeanUp = new MultiPathDataLogContainer(pp.Setting.NumberOfPaths); + var amplitudeValuesMeanDown = new MultiPathDataLogContainer(pp.Setting.NumberOfPaths); + var DeltaTimeOfFlightAverage = new MultiPathDataLogContainer(pp.Setting.NumberOfPaths); + + + 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; + + + 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 ((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; } + + + + + 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: + RegValue = Register.Genesisflow.ZeroOffset1; + 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; + + } + + } + +} diff --git a/Common/CordonelPreadjustmentUi/Processes/ActionsSinglePath/SPPreparationProcess.cs b/Common/CordonelPreadjustmentUi/Processes/ActionsSinglePath/SPPreparationProcess.cs new file mode 100644 index 00000000..eb60fffc --- /dev/null +++ b/Common/CordonelPreadjustmentUi/Processes/ActionsSinglePath/SPPreparationProcess.cs @@ -0,0 +1,149 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.Eventing.Reader; +using System.Linq; +using System.Text; +using CordonelPreadjustmentUi.Processes.Itinerary; +using System.Threading; +using static CordonelPreadjustmentUi.PreAdjustmentControl; +using System.Threading.Tasks; +using Xylem.Common.Hardware.WaterMeter.Genesis.Registers; +using Xylem.Common.Logic.SoftwareAccessHelper; +using Xylem.Common.CommonCore.Configuration; +using Newtonsoft.Json; + +namespace CordonelPreadjustmentUi.Processes.Actions +{ + public class SPPreparationProcess : BaseProcess + { + public SPPreparationProcess(string processName, StatusPanelItems panelState, string performMessage, string failedMessage, int? expectedTimeS) : base(processName, panelState, performMessage, failedMessage, expectedTimeS) + { + } + + public override List StartWork() + { + return doWorkProcess(base.CurrentProcessProgress); + } + + private List doWorkProcess(ProcessProgress pp) + { + var MetersToProcess = MeterStateCtls.Where(e => e.IsEnabled).ToList(); + + //MetersToProcess.AddRange(TempMeterStateCtls.Where(e => e.IsEnabled)); + + var listOfProcessTask = new List(); + + foreach (var item in TempMeterStateCtls.Where(e => e.IsEnabled)) + { + listOfProcessTask.Add(new Task(() => + { + item.Meter.StartRecordData(); + return true; + })); + } + foreach (var meterctl in MetersToProcess) + { + listOfProcessTask.Add(new Task(() => + { + + + meterctl.Id = string.IsNullOrEmpty(meterctl.Meter.PcbId) ? "Unknown" : $"Pcb:{meterctl.Meter.PcbId}"; + meterctl.Meter.StartRecordData(); + + + + Boolean Ok = false; + + + if (pp.Setting.NumberOfPaths > 0) + { + Ok = WriteRegisterSafe(meterctl.Meter, "Calibration factor1", Register.Genesisflow.CalFactor1, pp.Setting.CalFactor1); + if (CheckAbort(Ok, meterctl)) { return Ok; } + } + if (pp.Setting.NumberOfPaths > 1) + { + Ok = WriteRegisterSafe(meterctl.Meter, "Calibration factor2", Register.Genesisflow.CalFactor2, pp.Setting.CalFactor2); + if (CheckAbort(Ok, meterctl)) { return Ok; } + } + if (pp.Setting.NumberOfPaths > 2) + { + Ok = WriteRegisterSafe(meterctl.Meter, "Calibration factor3", Register.Genesisflow.CalFactor3, pp.Setting.CalFactor3); + if (CheckAbort(Ok, meterctl)) { return Ok; } + } + + + if (pp.Setting.doOffsetTest) + { + if (pp.Setting.NumberOfPaths > 0) + { + Ok = WriteRegisterSafe(meterctl.Meter, "Zeroflow offset1", Register.Genesisflow.ZeroOffset1, pp.Setting.ZeroOffset1); + if (CheckAbort(Ok, meterctl)) { return Ok; } + } + if (pp.Setting.NumberOfPaths > 1) + { + Ok = WriteRegisterSafe(meterctl.Meter, "Zeroflow offset2", Register.Genesisflow.ZeroOffset2, pp.Setting.ZeroOffset2); + if (CheckAbort(Ok, meterctl)) { return Ok; } + } + if (pp.Setting.NumberOfPaths > 2) + { + Ok = WriteRegisterSafe(meterctl.Meter, "Zeroflow offset3", Register.Genesisflow.ZeroOffset3, pp.Setting.ZeroOffset3); + if (CheckAbort(Ok, meterctl)) { return Ok; } + } + + } + meterctl.Meter.calibrationResult.AddAdditionalLog($"OffsetTestNumberOfLines", pp.Setting.OffsetTestNumberOfLines.ToString()); + meterctl.Meter.calibrationResult.AddAdditionalLog($"Samplerate", pp.Setting.Samplerate.ToString()); + + + Ok = WriteRegisterSafe(meterctl.Meter, "Samplerate", Register.Genesisflow.SampleRate, pp.Setting.Samplerate); + if (CheckAbort(Ok, meterctl)) { return Ok; } + if (pp.Setting.Production) + { + Ok = WriteRegisterSafe(meterctl.Meter, "Metersize", Register.Genesisflow.MeterSize, pp.Setting.MeterSize.GetHashCode(), false); + if (CheckAbort(Ok, meterctl)) { return Ok; } + } + else + { + WriteRegisterSafe(meterctl.Meter, "Metersize", Register.Genesisflow.MeterSize, pp.Setting.MeterSize.GetHashCode(), false); + if (CheckAbort(Ok, meterctl)) { return Ok; } + } + + + Ok = WriteRegisterSafe(meterctl.Meter, "LED mode", Register.Genesisflow.LedMode, pp.Setting.LedMode.GetHashCode()); + if (CheckAbort(Ok, meterctl)) { return Ok; } + + Ok = WriteRegisterSafe(meterctl.Meter, "TriggerActive", Register.Genesisflow.TriggerActive, 1, false); + if (CheckAbort(Ok, meterctl)) { return Ok; } + + + + if (CheckAbort(Ok, meterctl)) { return Ok; } + + var r = LocalWebRequest.GetRequest($"{ ServiceUrls.GenesisFinalCheckServiceUrl()}GetMetersizeProgrammingData?MeterSize={pp.Setting.MeterSize.GetHashCode()}", 2000); + var dt = JsonConvert.DeserializeObject>(r); + + foreach (var item in dt) + { + Ok = meterctl.Meter.WriteRegisterUnsafe(item.Key, item.Value); + if (CheckAbort(Ok, meterctl)) { return Ok; } + } + + + return Ok; + })); + + } + return listOfProcessTask; + + } + private static byte[] ReservandFill(byte[] b) + { + return b.Reverse().ToArray(); + + } + + } + + + +} diff --git a/Common/CordonelPreadjustmentUi/Processes/ActionsSinglePath/SPTemperatureCalibrationProcess.cs b/Common/CordonelPreadjustmentUi/Processes/ActionsSinglePath/SPTemperatureCalibrationProcess.cs new file mode 100644 index 00000000..a66f662b --- /dev/null +++ b/Common/CordonelPreadjustmentUi/Processes/ActionsSinglePath/SPTemperatureCalibrationProcess.cs @@ -0,0 +1,290 @@ +using CordonelPreadjustmentUi.Processes.Itinerary; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using Xylem.Common.Hardware.WaterMeter.Genesis.Registers; +using Xylem.Common.Ui.CordonelPreadjustmentUi.Helper.Extensions; + +using static CordonelPreadjustmentUi.PreAdjustmentControl; + +namespace CordonelPreadjustmentUi.Processes.Actions +{ + public class SPTemperatureCalibrationProcess : BaseProcess + { + public SPTemperatureCalibrationProcess(string processName, StatusPanelItems panelState, string performMessage, string failedMessage, int? expectedTimeS) : base(processName, panelState, performMessage, failedMessage, expectedTimeS) + { + } + + public override List StartWork() + { + return doWorkProcess(base.CurrentProcessProgress); + } + + private List doWorkProcess(ProcessProgress pp) + { + #region Wait for settling time (60s) + for (Int32 Time = pp.Setting.OffsetTestSettlingTime; Time >= 0; Time--) + { + + pp.StatusLabel = $"{PredefinedMessages.ZeroflowOffsetWaitForSettling(pp.Setting.Culture)}{Time.ToString(pp.Setting.Culture)}"; + Thread.Sleep(1000); + } + #endregion + + var MetersToProcess = MeterStateCtls.Where(e => e.IsEnabled).ToList(); + + var listOfProcessTask = new List(); + + + pp.StatusLabel = (PredefinedMessages.WaitUntilTemperatureAcquisitionFinished(pp.Setting.Culture)); + bool skipMan = false; + if (pp.Setting.GetTempUseTempFlansh() || TempMeterStateCtls.Any(a => a.IsEnabled)) + { + skipMan = false; + //aoutmatic + decimal avgTemp = 0; + int TempFlanshCount = 0; + var listOFEnabledTempMeters = TempMeterStateCtls.Where(a => a.IsEnabled).ToList(); + foreach (var avgTempCtls in listOFEnabledTempMeters) + { + var check = avgTempCtls.GetTemperature(); + if (check > 5 && (double)check != 25.0d ) + { + avgTemp = avgTemp + avgTempCtls.GetTemperature(); + TempFlanshCount = TempFlanshCount + 1; + skipMan = true; + } + + } + if (TempFlanshCount == 0) + { + System.Windows.Forms.MessageBox.Show("Fehler beim auslesen der TemperaturFlansche. Bitte per Hand eingeben"); + skipMan = false; + + pp.RequestTempretureSelection(); + + } + else + { + avgTemp = avgTemp / TempFlanshCount; + + foreach (var meterctl in MetersToProcess) + { + meterctl.SetTemperature(avgTemp); + } + } + + } + + if (!skipMan) + { + //manual input + foreach (var meterctl in MetersToProcess) + { + meterctl.SetTemperature((decimal)0); + } + pp.RequestTemperatur(); + foreach (var meterctl in TempMeterStateCtls) + { + meterctl.SetTemperature((decimal)0); + meterctl.OnTempretureChangedHandler += delegate (Object sender, EventArgsDecimal d) + { + decimal avgTemp = 0; + foreach (var tempMeter in TempMeterStateCtls) + { + avgTemp = avgTemp + tempMeter.GetTemperature(); + } + + avgTemp = avgTemp / TempMeterStateCtls.Count; + + foreach (var updateMeter in MetersToProcess) + { + updateMeter.SetTemperature(avgTemp); + } + + }; + + + } + } + + + + pp.DebugMessage($"Performing {ProcessName} procedure"); + + listOfProcessTask.Add(new Task(() => + { + + pp.RequestTempretureSelection(); + while (!pp.TempretureSelected) + { + + Thread.Sleep(100); + } + if (pp.Setting.GetTempUsePtOverSps() && pp.PushedTestBenchTemp.HasValue) + { + foreach (var updateMeter in MetersToProcess) + { + updateMeter.SetTemperature(Convert.ToDecimal(pp.PushedTestBenchTemp.Value)); + } + } + var listOfSubTasks = new List>(); + foreach (var disableTempInputMeter in MetersToProcess) + { + disableTempInputMeter.DisableTemperatureinput(true); + } + foreach (var disableTempInputMeter in TempMeterStateCtls) + { + disableTempInputMeter.DisableTemperatureinput(true); + } + + + foreach (var putTempIntoMeter in MetersToProcess) + { + listOfSubTasks.Add(new Task(() => + { + + var originTemp = putTempIntoMeter.GetTemperature(); + if (originTemp == (decimal)25.0 || originTemp == (decimal)1 || originTemp == (decimal)0) + { + pp.DebugMessage($"Temperature check failed - default", putTempIntoMeter.Meter.Slot, "APP", putTempIntoMeter.Meter.PcbId); + return false; + } + UInt32 TempToRegister = (UInt32)(originTemp * 4096); + + #region Set temperature calibration register + var Ok = false; + pp.StatusLabel = PredefinedMessages.WaitUntilRegisterWriteFinished(pp.Setting.Culture); + Ok = WriteRegisterSafe(putTempIntoMeter.Meter, "Temperature calibration", Register.Genesisflow.ToFTempCalibrate, TempToRegister, false); + if (CheckAbort(Ok, putTempIntoMeter)) { return Ok; } + putTempIntoMeter.Meter.calibrationResult.AddAdditionalLog($"Temperature calibration Register", TempToRegister.ToString()); + putTempIntoMeter.Meter.calibrationResult.AddAdditionalLog($"Temperature calibration Origin", originTemp.ToString()); + + #endregion + #region Wait for some seconds + const UInt16 WaitingTime = 10; + + + putTempIntoMeter.Meter.listOfTotalTimeOfFlightSPerPath.Update(null, new List()); + putTempIntoMeter.Meter.CurrentRecords.Clear(); + putTempIntoMeter.Meter.logAmpTest = true; + + + for (Int32 Seconds = 0; Seconds < WaitingTime; Seconds++) // eight seconds remove /2 + { + Ok = ActivityCheck(pp, putTempIntoMeter.Meter.listOfTotalTimeOfFlightSPerPath, Seconds); + if (CheckAbort(Ok, putTempIntoMeter)) + { + + pp.DebugMessage($"Activity check failed", putTempIntoMeter.Meter.Slot, "DC", putTempIntoMeter.Meter.PcbId); + return Ok; + } + pp.StatusLabel = $"{PredefinedMessages.WaitSeconds(Seconds, pp.Setting.Culture)}"; + Thread.Sleep(1000); + } + #endregion + #region Check temperature + putTempIntoMeter.Meter.CurrentRecords.Clear(); + putTempIntoMeter.Meter.logAmpTest = true; + Thread.Sleep(1000); + var tmpTempCheckRecords = putTempIntoMeter.Meter.CurrentRecords.ToList(); + if (tmpTempCheckRecords.Any()) + { + + + var checkTempMeter = (decimal)tmpTempCheckRecords.Average(a => a.TemperatureDegC); + + var sbTemp = new StringBuilder(); + + sbTemp.AppendLine( + $"Ref. temp = {Math.Round(originTemp, 2).ToString("00.00", pp.Setting.Culture)}°C vs. Meter temp = {checkTempMeter}°C at {putTempIntoMeter.Meter.Slot}"); + + if (Math.Abs(originTemp - checkTempMeter) > (decimal)pp.Setting.TempDeviationLimit) + { + pp.DebugMessage($"Temperature check failed", putTempIntoMeter.Meter.Slot, "APP", putTempIntoMeter.Meter.PcbId); + Ok = false; + } + if (CheckAbort(Ok, putTempIntoMeter)) { return Ok; } + + pp.DebugMessage($"Temperature check OK", putTempIntoMeter.Meter.Slot, "APP", putTempIntoMeter.Meter.PcbId); + + #endregion + + + #region Get 'TOF offset' registers + if (pp.Setting.NumberOfPaths > 0) + { + byte[] rawResult; + Ok = ReadRegister(putTempIntoMeter.Meter, "TOF offset1", Register.Genesisflow.ToFTempOffset1, out rawResult); + if (CheckAbort(Ok, putTempIntoMeter)) { return Ok; } + if (rawResult != null) + { + var tmp = BitConverter.ToInt32(rawResult, 0); + } + + } + if (pp.Setting.NumberOfPaths > 1) + { + byte[] rawResult; + Ok = ReadRegister(putTempIntoMeter.Meter, "TOF offset2", Register.Genesisflow.ToFTempOffset2, out rawResult); + if (CheckAbort(Ok, putTempIntoMeter)) { return Ok; } + if (rawResult != null) + { + var tmp = BitConverter.ToInt32(rawResult, 0); + } + + } + + if (pp.Setting.NumberOfPaths > 2) + { + byte[] rawResult; + Ok = ReadRegister(putTempIntoMeter.Meter, "TOF offset3", Register.Genesisflow.ToFTempOffset3, out rawResult); + if (CheckAbort(Ok, putTempIntoMeter)) { return Ok; } + if (rawResult != null) + { + var tmp = BitConverter.ToInt32(rawResult, 0); + } + } + #endregion + + + + putTempIntoMeter.SetWatcher((decimal)pp.Setting.LowerTempLimit, (decimal)pp.Setting.UpperTempLimit, (decimal)pp.Setting.TempDeviationLimit); + putTempIntoMeter.StartTempWatch(); + + return true; + } + else + { + pp.DebugMessage($"Temperature check failed - No Records", putTempIntoMeter.Meter.Slot, "APP", putTempIntoMeter.Meter.PcbId); + return false; + } + + })); + } + + listOfSubTasks.ForEach(t => t.Start()); + while (!listOfSubTasks.All(t => t.IsCompleted)) + { + Thread.Sleep(5); + } + + return true; + + })); + + + + + return listOfProcessTask; + + } + + } + + + +} diff --git a/Common/CordonelPreadjustmentUi/ZeroFlowGenesisMeter.cs b/Common/CordonelPreadjustmentUi/ZeroFlowGenesisMeter.cs index 1813db04..c95568f5 100644 --- a/Common/CordonelPreadjustmentUi/ZeroFlowGenesisMeter.cs +++ b/Common/CordonelPreadjustmentUi/ZeroFlowGenesisMeter.cs @@ -211,7 +211,7 @@ namespace CordonelPreadjustmentUi { if (e is CalibDataEventArgs) { - + var decodedDate = (CalibDataEventArgs)e; var data = decodedDate.CalibChl; if (Slot == 10 && data.Channel == 2) diff --git a/Common/CordonelPreadjustmentUi/ZeroFlowSinglePathMeter.cs b/Common/CordonelPreadjustmentUi/ZeroFlowSinglePathMeter.cs new file mode 100644 index 00000000..c623c37c --- /dev/null +++ b/Common/CordonelPreadjustmentUi/ZeroFlowSinglePathMeter.cs @@ -0,0 +1,44 @@ +//using CordonelPreadjustmentUi.Const; +//using CordonelPreadjustmentUi.Helper; +//using Logic.ProductionToProductMapper.Cordonel; +//using System; +//using System.Collections.Concurrent; +//using System.Collections.Generic; +//using System.Globalization; +//using System.Linq; +//using System.Threading; +//using Logic.ProductionToProductMapper.Cordonel; +//using Xylem.Common.CommonCore.Consts; +//using Xylem.Common.Hardware.Interfaces.Ports.PortCore; +//using Xylem.Common.Hardware.Interfaces.Protocols.ProtocolCore.EventArguments; +//using Xylem.Common.Hardware.WaterMeter.Genesis.DataPackages.EventArguments; +//using Xylem.Common.Hardware.WaterMeter.Genesis.DataPackages.MeasurementRecords; +//using Xylem.Common.Hardware.WaterMeter.Genesis.GenesisConfig; +//using Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore; +//using Xylem.Common.Ui.CordonelPreadjustmentUi.Helper.Extensions; + +//namespace CordonelPreadjustmentUi +//{ +// public class ZeroFlowSinglePathMeter : ZeroFlowGenesisMeter +// { + + +// public ZeroFlowSinglePathMeter(int Slot, int PathsCount = 3, bool ignorCurruptdata = true) : base() +// { + +// //base.SetupFromConfigFile(Slot, ignorCurruptdata); + + +// ////base.EnableAutoLogon(); +// //base.Setup(PathsCount); + +// ////on zeroflow every param has to be stored +// //Configuration.UseRegisterWatchService = true; +// //Configuration.RegisterWatchServiceUrl = Xylem.Common.CommonCore.Configuration.ServiceUrls.RegisterWatchServiceUrl(); + +// } + + + +// } +//} diff --git a/Common/Logic/ProductionOrderCore/OrderData/ScanToSerialNr.cs b/Common/Logic/ProductionOrderCore/OrderData/ScanToSerialNr.cs index cae19d67..f546f683 100644 --- a/Common/Logic/ProductionOrderCore/OrderData/ScanToSerialNr.cs +++ b/Common/Logic/ProductionOrderCore/OrderData/ScanToSerialNr.cs @@ -21,6 +21,7 @@ namespace Xylem.Common.Logic.ProductionOrderCore.OrderData { customerSr = scan.Substring(0, scan.IndexOf(",", StringComparison.Ordinal)); } + if (scan.StartsWith(prefix)) { @@ -71,6 +72,11 @@ namespace Xylem.Common.Logic.ProductionOrderCore.OrderData internalSerialNr = retCustom; return true; } + + if (scan.Replace(" ", "").Length == 12) + { + customerSr = scan.Replace(" ", ""); + } throw new ApplicationException("Could not parse serial number"); }