using ByteArrayStyle; using Newtonsoft.Json; using NLog; using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Diagnostics; using System.Drawing; using System.Globalization; using System.Linq; using System.Reflection; using System.Runtime.InteropServices; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; using Xylem.Common.CommonCore.Configuration; using Xylem.Common.Hardware.WaterMeter.eRegister.eRegisterCore; using Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore; using Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore.Consts; using Xylem.Common.Hardware.WaterMeter.Genesis.Registers; using Xylem.Common.Hardware.WaterMeter.MagFlux.MagFluxCore; using Xylem.Common.Hardware.WaterMeter.WaterMeterCore; using Xylem.Common.Hardware.WaterMeter.WaterMeterCore.Consts; using Xylem.Common.Logic.SoftwareAccessHelper; using Xylem.Common.Metrology.Measurements; using Xylem.Common.Metrology.Measurements.Consts; using Xylem.Common.Utils.Logging; using XylemCommonUiLegacyGenCtl.DataPackage; using XylemCommonUiLegacyGenCtl.Enums; namespace XylemCommonUiLegacyGenCtl { [Guid("034A00BD-AAAA-4DF7-97F3-43D0CBF8A805"), ComVisible(true), ClassInterface(ClassInterfaceType.None), ComSourceInterfaces(typeof(ICtlBatch))] public partial class ctlBatch : UserControl, ICtlBatch { #region Const Layout private const Int32 LblPositionLeft = 5; private const Int32 LblPositionTop = 20; private const Int32 LblPositionSize = 70; private const Int32 LblPositionHeight = 70; private const Int32 LblPositionSpace = 15; private const Int32 SizeOfMeter = 140; #endregion #region Prop private enum Mode { AutoRefresh, View, } /// /// State for state machine /// private enum BatchState { Idle, Init, Error, PrepareGui, PrepareMeasurement, MeasurementActive, MeasurementCompleted, TestContainerIsReady, BatchIsReady, AddMeters, PrepareMeters, MetersPrepared, ReadyForMesuremnt, StartMesurement, StopMesurement, } private BatchState _currentState; private BatchState _backupState; private Mode currentMode = Mode.View; private ILogger _logger; private Dictionary CalibrationIsDone = new Dictionary(); public MeterBatch batch; //private System.Windows.Forms.Timer RefreshTimer = new System.Windows.Forms.Timer(); //private System.Windows.Forms.Timer RefreshTimerWatch = new System.Windows.Forms.Timer(); private Alarm TestBenchRelatedAlarms = Alarm.EMPTY_PIPE & Alarm.REBOOT & Alarm.HIGH_PRESSURE & Alarm.HIGH_TEMPERATURE & Alarm.LOW_PRESSURE & Alarm.LOW_TEMPERATURE; private ConcurrentDictionary WarningMetersAlarms = new ConcurrentDictionary(); private ConcurrentDictionary ErrorMetersAlarms = new ConcurrentDictionary(); public String MeterDn = "-"; public Double RefPulseValence; public Double PredictedQFlow; public Double PredictedTs; public Double RefError; public Int32 CurrentPulse; public Double CurrentRefVolume; public Int32 RemainingPulse; public String Period = "-"; public Double RefFlowrate; public Double RefTestTime; public Double RefFlowUncorrected; public Double MeterDefaultCorrection; private TestSetupContainer TestSetupContainer; private DataTable dtBatch; #region busy public Boolean IsBusy { get; private set; } private Int32? ProgressTotal; private Int32? ProgressCurrent; private Dictionary slotErrorFrameDic = new Dictionary(); private Dictionary slotLut = new Dictionary(); private Dictionary slotPreadjustment = new Dictionary(); private Dictionary> labelValueCollection; public Boolean IsFlyingStartStop { get; private set; } private Double StoreRefVolume, StoreTestTimeRef; private Stopwatch stopWatch = new Stopwatch(); private Dictionary rowIndex = new Dictionary(); #endregion #endregion #region ctor public ctlBatch() { _logger = NLogHelper.CreateOrGetMultiLogger("ctlBatch", "", "Batch", "", ""); _logger.Info("start construct ctlBatch"); //RefreshTimerWatch.Enabled = true; //RefreshTimerWatch.Interval = 5000; //RefreshTimerWatch.Tick += RefreshTimerWatch_Tick; InitializeComponent(); labelValueCollection = new Dictionary>(); InitLabelValueCollection(); grbInfo.SuspendLayout(); SuspendLayout(); Disposed += CtlBatch_Disposed; //kick off the state machine _currentState = BatchState.Init; _backupState = BatchState.Idle; _logger.Info("construct ctlBatch end"); } private void CtlBatch_Disposed(Object sender, EventArgs e) { try { base.Dispose(); Close(); } catch (Exception ex) { _logger.Error(ex, "error at CtlBatch_Disposed"); } } #endregion #region StateMachine /// /// State machine for control batch /// /// /// - Initial. /// private void CtlBatchStateMachine() { if (_currentState == _backupState) { Thread.Sleep(1); } else { // this loop calls the function and assigns the return states on success and error // remind backup state to avoid repeated execution and side effects _logger.Info($"StateMachine has change from {_backupState} to {_currentState}"); _backupState = _currentState; switch (_currentState) { case BatchState.Idle: break; case BatchState.Init: break; case BatchState.Error: break; case BatchState.PrepareGui: break; case BatchState.PrepareMeasurement: break; case BatchState.TestContainerIsReady: break; case BatchState.BatchIsReady: break; case BatchState.AddMeters: var tAddMeters = Task.Factory.StartNew(() => { return AddAllMeters_Internal(); }); tAddMeters.ContinueWith(r => { _currentState = r.Result ? BatchState.PrepareMeters : BatchState.Error; }); break; case BatchState.PrepareMeters: var tPrepareMeters = Task.Factory.StartNew(() => { return PrepareMeters_Internal(); }); tPrepareMeters.ContinueWith(r => { _currentState = r.Result ? BatchState.MetersPrepared : BatchState.Error; }); break; case BatchState.MetersPrepared: //Wait For Caller when every thing is setup break; case BatchState.ReadyForMesuremnt: //Wait for caller to start Measurement break; case BatchState.StartMesurement: var tStartMesurement = Task.Factory.StartNew(() => { return StartMeasurement_Internal(); }); tStartMesurement.ContinueWith(r => { _currentState = r.Result ? BatchState.MeasurementActive : BatchState.Error; }); break; case BatchState.MeasurementActive: // wait for signal that the measurement can be stopped break; case BatchState.StopMesurement: var tStopMesurement = Task.Factory.StartNew(() => { return StopMeasurement_Internal(); }); tStopMesurement.ContinueWith(r => { _currentState = r.Result ? BatchState.MeasurementCompleted : BatchState.Error; }); break; case BatchState.MeasurementCompleted: //Measurement waiting for caller to grab all the results break; }// lock repeated execution of identical state } } #endregion #region busy private void setBusy(Boolean val, String action = "", Boolean hideToExternal = false) { try { if (!hideToExternal) { IsBusy = val; } if (val) { TryInvoke(new Action(() => { pnlBussy.Visible = true; timProgress.Enabled = true; lblAction.Text = action; pnlBussy.Size = Size; pnlBussy.Location = new Point(0, 0); lblAction.Left = (ClientSize.Width - lblAction.Width) / 2; lblAction.Top = ((ClientSize.Height - lblAction.Height) / 2) - (lblBussyHealine.Height * 4); lblBussyHealine.Left = (ClientSize.Width - lblBussyHealine.Width) / 2; lblBussyHealine.Top = (ClientSize.Height - lblBussyHealine.Height) / 2 - (lblBussyHealine.Height * 2); })); } else { ProgressTotal = null; ProgressCurrent = null; TryInvoke(new Action(() => { pnlBussy.Visible = false; timProgress.Enabled = false; lblAction.Text = action; lblProgress.Text = ""; })); } } catch (Exception ex) { _logger.Error(ex, $"error at setBusy(val={val},action={action}"); } } private void setProgress(String text, Int32 total = 0, Int32 current = 0) { try { ProgressTotal = total; ProgressCurrent = current; TryInvoke(new Action(() => { lblProgress.Text = $@"{text} ({current}/{total})"; })); } catch (Exception ex) { _logger.Error(ex, $"error at setProgress(text={text},total={total},current={current}"); } } private Boolean AvoidDisposedTimer(Object sender) { if (Disposing || Disposing) { if (sender is System.Windows.Forms.Timer) { ((System.Windows.Forms.Timer)(sender)).Enabled = false; ((System.Windows.Forms.Timer)(sender)).Dispose(); } return true; } return false; } private void timProgress_Tick(Object sender, EventArgs e) { try { CtlBatchStateMachine(); if (AvoidDisposedTimer(sender)) { return; } if (IsBusy) { if (ProgressTotal.HasValue && ProgressCurrent.HasValue && !ProgressTotal.Value.Equals(0) && !ProgressCurrent.Value.Equals(0)) { try { TryInvoke(new Action(() => { probarBusy.Value = (Int32)Math.Round(ProgressCurrent.Value / (Double)ProgressTotal.Value * 100, 0); })); } catch (Exception exception) { _logger.Error(exception, @"Timer routine progress"); } } else { var current = probarBusy.Value; if (current + 1 > 100) { current = 0; } TryInvoke(new Action(() => { probarBusy.Value = current + 1; })); } } } catch (Exception ex) { _logger.Error(ex, "timProgress_Tick"); } } #endregion #region refresh private void RefreshTimerWatch_Tick(Object sender, EventArgs e) { try { if (AvoidDisposedTimer(sender)) { return; } if (currentMode == Mode.AutoRefresh) { TryInvoke(new Action(() => { pgbUpdate.Visible = true; })); if (stopWatch != null && stopWatch.IsRunning) { var progress = (Int32)(stopWatch.ElapsedMilliseconds); progress = progress > pgbUpdate.Maximum ? pgbUpdate.Maximum : progress; TryInvoke(new Action(() => { pgbUpdate.Value = progress; })); } } else { TryInvoke(new Action(() => { pgbUpdate.Visible = false; })); } } catch (Exception ex) { _logger.Error(ex, "error at RefreshTimerWatch_Tick()"); } } private void RefreshTimer_Tick(Object sender, EventArgs e) { //try //{ // if (this.AvoidDisposedTimer(sender)) // return; // this.UpdateBatch(); //} //catch (Exception ex) //{ // _logger.Error(ex, $"error at RefreshTimer_Tick()"); //} } private void updateTotalProgress(Double refTestTime) { try { if (PredictedTs > 0 && refTestTime > 0) { var timeLeft = PredictedTs - refTestTime; TryInvoke(new Action(() => { lblEndTime.Text = DateTime.Now.AddSeconds(timeLeft).ToString("HH:mm:ss"); pgbEndTime.Value = (Int32)refTestTime >= pgbEndTime.Maximum ? pgbEndTime.Maximum : (Int32)refTestTime; pnlEndTime.Visible = true; })); } } catch (Exception ex) { _logger.Error(ex, $"error at updateTotalProgress(refTestTime={refTestTime}"); } } #endregion #region infoLables private void InitLabelValueCollection() { AddInfoLabels("MeterDn", "MID", 0, MeterDn); AddInfoLabels("PulseValence", "Impulswertigkeit", 1, doubleToStringFormat(RefPulseValence)); AddInfoLabels("PredictedQFlow", "Q soll[m³/ h]", 2, doubleToStringFormat(PredictedQFlow, 6)); AddInfoLabels("PredictedTs", "T soll[s]", 3, doubleToStringFormat(PredictedTs, 1)); AddInfoLabels("RefError", "RZ Fehler[%]", 4, doubleToStringFormat(RefError, 3)); AddInfoLabels("CurrentPulse", "Impulse", 6, CurrentPulse.ToString()); AddInfoLabels("CurrentRefVolume", "RZ Volumen m³", 7, doubleToStringFormat(CurrentRefVolume, 6)); AddInfoLabels("RemainingPulse", "Verbleib.Imp", 8, RemainingPulse.ToString()); AddInfoLabels("Period", "Periodendauer", 9, Period); AddInfoLabels("RefFlow", "Ref Q", 11, doubleToStringFormat(RefFlowrate, 6)); AddInfoLabels("RefFlowUncorrected", "unkor. Ref Q", 12, doubleToStringFormat(RefFlowUncorrected, 6)); } private void AddInfoLabels(String name, String text, Int32 index, String value) { var tmpLblText = new Label(); var tmpLblValue = new Label(); grbInfo.Controls.Add(tmpLblText); grbInfo.Controls.Add(tmpLblValue); tmpLblText.AutoSize = true; tmpLblText.Location = new Point(LblPositionLeft, LblPositionTop * (index + 1)); tmpLblText.Name = $"lblInfo{name}text"; tmpLblText.Size = new Size(LblPositionSize, LblPositionHeight); tmpLblText.TabIndex = index; tmpLblText.Text = text; tmpLblValue.AutoSize = true; tmpLblValue.Location = new Point(LblPositionLeft + LblPositionSize + LblPositionSpace, LblPositionTop * (index + 1)); tmpLblValue.Name = $"lblInfo{name}value"; tmpLblValue.Size = new Size(LblPositionSize, LblPositionHeight); tmpLblValue.TabIndex = index + 1; tmpLblValue.Text = value; labelValueCollection.Add(name, new Tuple(tmpLblValue, value)); } public void updateLabelCollection() { labelValueCollection["MeterDn"] = new Tuple(labelValueCollection["MeterDn"].Item1, MeterDn); labelValueCollection["PulseValence"] = new Tuple(labelValueCollection["PulseValence"].Item1, doubleToStringFormat(RefPulseValence)); labelValueCollection["PredictedQFlow"] = new Tuple(labelValueCollection["PredictedQFlow"].Item1, doubleToStringFormat(PredictedQFlow, 6)); labelValueCollection["PredictedTs"] = new Tuple(labelValueCollection["PredictedTs"].Item1, doubleToStringFormat(PredictedTs, 1)); labelValueCollection["RefError"] = new Tuple(labelValueCollection["RefError"].Item1, doubleToStringFormat(RefError, 3)); labelValueCollection["CurrentPulse"] = new Tuple(labelValueCollection["CurrentPulse"].Item1, CurrentPulse.ToString()); labelValueCollection["CurrentRefVolume"] = new Tuple(labelValueCollection["CurrentRefVolume"].Item1, doubleToStringFormat(CurrentRefVolume, 6)); labelValueCollection["RemainingPulse"] = new Tuple(labelValueCollection["RemainingPulse"].Item1, RemainingPulse.ToString()); labelValueCollection["Period"] = new Tuple(labelValueCollection["Period"].Item1, Period); labelValueCollection["RefFlow"] = new Tuple(labelValueCollection["RefFlow"].Item1, doubleToStringFormat(RefFlowrate, 6)); labelValueCollection["RefFlowUncorrected"] = new Tuple(labelValueCollection["RefFlowUncorrected"].Item1, doubleToStringFormat(RefFlowUncorrected, 6)); TryInvoke(new Action(() => { foreach (var item in labelValueCollection) { item.Value.Item1.Text = item.Value.Item2; } })); } #endregion #region dataGridview private Color? getErrorColor(Double meterError, Int32 slot) { Color? ret = Color.Green; var errorFrame = slotErrorFrameDic.FirstOrDefault(e => e.Key.Equals(slot)).Value; if (errorFrame <= Math.Abs(meterError)) { ret = Color.LightYellow; } if (double.IsNaN(meterError) || double.IsNaN(errorFrame)) { ret = Color.Yellow; } return ret; } private void updateRowVisible(String Row, Boolean Value) { TryInvoke(new Action(() => { dgvBatch.Rows[rowIndex.First(k => k.Value == Row).Key].Visible = Value; })); } private void updateCellToInput(String Row, Int32 Slot, Boolean Value) { if (dgvBatch != null && dgvBatch.Rows.Count > rowIndex.First(k => k.Value == Row).Key && dgvBatch.Rows[rowIndex.First(k => k.Value == Row).Key].Cells.Count > Slot) { TryInvoke(new Action(() => { dgvBatch.Rows[rowIndex.First(k => k.Value == Row).Key].Cells[Slot].ReadOnly = Value; })); } } private T getCellValue(String Row, Int32 Slot) { if (dgvBatch != null && dgvBatch.Rows.Count > rowIndex.First(k => k.Value == Row).Key && dgvBatch.Rows[rowIndex.First(k => k.Value == Row).Key].Cells.Count > Slot) { var currentRowIndex = rowIndex.First(k => k.Value == Row).Key; var value = dtBatch.Rows[currentRowIndex][Slot].ToString(); var converter = TypeDescriptor.GetConverter(typeof(T)); return (T)converter.ConvertFrom(value); } return default(T); } private void setColor(String Row, Int32 Slot, Color c) { if (dgvBatch != null && dgvBatch.Rows.Count > rowIndex.First(k => k.Value == Row).Key && dgvBatch.Rows[rowIndex.First(k => k.Value == Row).Key].Cells.Count > Slot) { TryInvoke(new Action(() => { var currentRowIndex = rowIndex.First(k => k.Value == Row).Key; var currentCell = dgvBatch.Rows[currentRowIndex].Cells[Slot]; if (dgvBatch.InvokeRequired) { setColor(Row, Slot, c); } else { currentCell.Style.BackColor = c; } })); } } private void updateCell(String Row, Int32 Slot, Double Value, Int32 digits = 2, Color? c = null) { updateCell(Row, Slot, doubleToStringFormat(Value, digits), c); } private void updateCell(String Row, Int32 Slot, String Value, Color? c = null) { if (dgvBatch != null && dgvBatch.Rows.Count > rowIndex.First(k => k.Value == Row).Key && dgvBatch.Rows[rowIndex.First(k => k.Value == Row).Key].Cells.Count > Slot) { TryInvoke(new Action(() => { var currentRowIndex = rowIndex.First(k => k.Value == Row).Key; dtBatch.Rows[currentRowIndex][Slot] = Value; if (c.HasValue) { dgvBatch.Rows[currentRowIndex].Cells[Slot].Style.BackColor = c.Value; } else { dgvBatch.Rows[currentRowIndex].Cells[Slot].Style.BackColor = Color.Empty; } })); } } private void initDt() { rowIndex = new Dictionary(); rowIndex.Add(rowIndex.Count, "Einbauplatz"); rowIndex.Add(rowIndex.Count, "Seriennummer"); rowIndex.Add(rowIndex.Count, "PcbId"); rowIndex.Add(rowIndex.Count, "Status"); rowIndex.Add(rowIndex.Count, "Fehler [%]"); rowIndex.Add(rowIndex.Count, "Druchfluss [m³/h]"); rowIndex.Add(rowIndex.Count, "Volumen [m³]"); rowIndex.Add(rowIndex.Count, "Zeit [S]"); rowIndex.Add(rowIndex.Count, "Fehlergrenze [%]"); rowIndex.Add(rowIndex.Count, "Zielwert Justage [%]"); rowIndex.Add(rowIndex.Count, "Pfad 1 Fehler [%]"); rowIndex.Add(rowIndex.Count, "Pfad 1 Druchfluss [m³/h]"); rowIndex.Add(rowIndex.Count, "Pfad 1 Volumen [m³]"); rowIndex.Add(rowIndex.Count, "Pfad 1 Zeit [S]"); rowIndex.Add(rowIndex.Count, "Pfad 2 Fehler [%]"); rowIndex.Add(rowIndex.Count, "Pfad 2 Druchfluss [m³/h]"); rowIndex.Add(rowIndex.Count, "Pfad 2 Volumen [m³]"); rowIndex.Add(rowIndex.Count, "Pfad 2 Zeit [S]"); rowIndex.Add(rowIndex.Count, "Pfad 3 Fehler [%]"); rowIndex.Add(rowIndex.Count, "Pfad 3 Druchfluss [m³/h]"); rowIndex.Add(rowIndex.Count, "Pfad 3 Volumen [m³]"); rowIndex.Add(rowIndex.Count, "Pfad 3 Zeit [S]"); dtBatch = new DataTable(); dtBatch.Columns.Add("RowHeader"); dtBatch.Columns.Add("1"); dtBatch.Columns.Add("2"); dtBatch.Columns.Add("3"); dtBatch.Columns.Add("4"); dtBatch.Columns.Add("5"); dtBatch.Columns.Add("6"); dtBatch.Columns.Add("7"); dtBatch.Columns.Add("8"); dtBatch.Columns.Add("9"); dtBatch.Columns.Add("10"); foreach (var item in rowIndex) { dtBatch.Rows.Add(); dtBatch.Rows[dtBatch.Rows.Count - 1][0] = item.Value; } dgvBatch.DataSource = dtBatch; foreach (var item in dgvBatch.Columns) { if (item is DataGridViewColumn) { var dt = (DataGridViewColumn)item; dt.ReadOnly = true; if (dt.Name != "RowHeader") { dt.Visible = false; } } } } private void ExpertMode(Boolean visible) { updateRowVisible("Pfad 1 Fehler [%]", visible); updateRowVisible("Pfad 1 Druchfluss [m³/h]", visible); updateRowVisible("Pfad 1 Volumen [m³]", visible); updateRowVisible("Pfad 1 Zeit [S]", visible); updateRowVisible("Pfad 2 Fehler [%]", visible); updateRowVisible("Pfad 2 Druchfluss [m³/h]", visible); updateRowVisible("Pfad 2 Volumen [m³]", visible); updateRowVisible("Pfad 2 Zeit [S]", visible); updateRowVisible("Pfad 3 Fehler [%]", visible); updateRowVisible("Pfad 3 Druchfluss [m³/h]", visible); updateRowVisible("Pfad 3 Volumen [m³]", visible); updateRowVisible("Pfad 3 Zeit [S]", visible); } #endregion #region ictlBatch & Mainwork private Boolean _useRequest; private Boolean _rawLogging = true; private Boolean IsAdjustment; private Boolean _checkAllChannels = true; /// /// /// /// public void PrepareBatch(String ControlSrt = "JustToCheckUpdate") { try { _logger.Trace($"PrepareBatch ControlSrt : {ControlSrt} "); batch = new MeterBatch(); _useRequest = true; _rawLogging = true; _checkAllChannels = TestSetupContainer.AllChanelsRequired; _currentState = BatchState.BatchIsReady; } catch (Exception ex) { _logger.Error(ex, $"error at ControlSrt : {ControlSrt}"); _currentState = BatchState.Error; } } public Boolean AddAllMeters_Internal() { try { if (TestSetupContainer == null) { _logger.Error("Test setup container missing"); return false; } var listOfTasks = new List(); foreach (var item in TestSetupContainer.meterTestSettings) { if (item != null && (item.FlowAdjustment || item.FlowTesting)) { listOfTasks.Add(new Task(() => { if (batch.ListOfMeters.All(f => f.Slot != item.Slot)) { try { IMeter meter; switch (item.meterType) { case MeterTypes.Cordonel: meter = new GenesisMeter(); break; case MeterTypes.MagFlux: meter = new MagFluxMeter(); break; case MeterTypes.eRegister: meter = new eRegisterMeter(); _rawLogging = true; break; default: meter = new GenesisMeter(); break; } meter.SerialNumber = item.SerialNr; meter.CurrentActionText = "FlowTest"; meter.SetupFromConfigFile(item.Slot, false, _useRequest, true); meter.LogRawData(_rawLogging); meter.SkipPreparationForTestBench = false; //if (TestSetupContainer.ProductionMode) //{ // meter.SkipPreparationForTestBench = true; //} batch.AddMeter(meter); var uniMeter = batch.GetMeter(item.Slot); if (!uniMeter.Login()) { if (!uniMeter.Login()) { return; } } //; uniMeter.WriteLog("Add from AddAllMeters"); } catch (Exception ex) { _logger.Warn(ex.Message); } } })); } } listOfTasks.ForEach(t => t.Start()); Task.WaitAll(listOfTasks.ToArray()); setBusy(false); return true; } catch (Exception ex) { setBusy(false); _logger.Error(ex, "Add all meters failed"); return false; } } public void AddAllMeters(String meterDn = "-", Double refPulseValence = 0.0, Double predictedQFlow = 0.0, Double predictedTs = 0.0, Double refError = 0.0, Boolean isAdjustment = false, Boolean isFlyingStartStop = true, int testRunNr = 0) { try { setBusy(true, "alle Zähler hinzufügen"); IsFlyingStartStop = isFlyingStartStop; _logger.Trace($"Start PrepareMeters(meterDn={meterDn},refPulseValence={refPulseValence}," + $"predictedQFlow ={predictedQFlow},predictedTs={predictedTs},refError={refError}," + $"isAdjustment={isAdjustment},IsFlyingStartStop={IsFlyingStartStop}"); WarningMetersAlarms = new ConcurrentDictionary(); ErrorMetersAlarms = new ConcurrentDictionary(); initAction(meterDn, refPulseValence, predictedQFlow, predictedTs, refError, isFlyingStartStop); IsAdjustment = isAdjustment; _currentState = BatchState.AddMeters; } catch (Exception ex) { _logger.Error(ex, $"error at PrepareMeters(meterDn={meterDn},refPulseValence={refPulseValence}," + $"predictedQFlow ={predictedQFlow},predictedTs={predictedTs},refError={refError}," + $"isAdjustment={isAdjustment},IsFlyingStartStop={IsFlyingStartStop}"); } } public void AddMeter(String serialNumber, Int32 slot, Boolean SkipPrepearation) { try { setBusy(true, $"Füge {serialNumber} hinzu"); Task.Factory.StartNew(() => { if (batch.ListOfMeters.Any(f => f.Slot == slot)) { batch.RemoveMeter(batch.ListOfMeters.First(f => f.Slot == slot)); } var meter = new GenesisMeter(); meter.SerialNumber = serialNumber; meter.CurrentActionText = "FlowTest"; meter.SetupFromConfigFile(slot, false, _useRequest, true); meter.LogRawData(_rawLogging); meter.EnableAutoLogon(); batch.AddMeter(meter); }).ContinueWith(delegate { setBusy(false); }); } catch (Exception ex) { _logger.Error(ex, $"error at AddMeter(serialNumber={serialNumber},slot={slot}"); } } public void AddMeter(String serialNumber, Int32 slot) { if (TestSetupContainer == null) { TestSetupContainer = new TestSetupContainer(); TestSetupContainer.AllChanelsRequired = true; TestSetupContainer.meterTestSettings = new MeterTestSettings[10]; TestSetupContainer.meterTestResults = new MeterTestResults[10]; } if (!TestSetupContainer.meterTestSettings.Any(f => f != null && f.Slot == slot)) { TestSetupContainer.meterTestSettings[slot - 1] = new MeterTestSettings() { SerialNr = serialNumber, Slot = slot, FlowAdjustment = true, FlowTesting = true }; TestSetupContainer.meterTestResults[slot - 1] = new MeterTestResults() { SerialNr = serialNumber, Slot = slot, meterType = MeterTypes.MagFlux, Results = new List() }; } AddMeter(serialNumber, slot, true); } public void RemoveMeter(Int32 slot) { try { setBusy(true, $"Entferne EP. {slot}"); Task.Factory.StartNew(() => { var meterToRemove = batch.ListOfMeters.First(a => a.Slot == slot); batch.RemoveMeter(meterToRemove); }).ContinueWith(delegate { setBusy(false); }); } catch (Exception ex) { _logger.Error(ex, $"error at RemoveMeter(slot={slot}"); } } public String LutCrc(Int32 slot) { if (!slotLut.ContainsKey(slot)) { return ""; } return slotLut[slot]; } public Boolean MeterHasPreadjustment(Int32 slot) { if (!slotPreadjustment.ContainsKey(slot)) { return false; } return slotPreadjustment[slot]; } public void MeterDoneWithDetails(Int32 slot, Boolean Succeed) { var meter = batch.ListOfMeters.First(f => f.Slot == slot); if (meter is MagFluxMeter mag) { MeterDone(slot, Succeed); } else { if (!slotLut.ContainsKey(slot)) { slotLut.Add(slot, ""); } else { slotLut[slot] = ""; } if (!slotPreadjustment.ContainsKey(slot)) { slotPreadjustment.Add(slot, false); } else { slotPreadjustment[slot] = false; } MeterDone(slot, Succeed); if (meter is GenesisMeter gen) { slotLut[slot] = gen.LutCrc; try { var responseJson = LocalWebRequest.GetRequest($"{ServiceUrls.MeterInfoForTestBench()}{gen.PcbId}"); var a = JsonConvert.DeserializeObject(responseJson); var SerialNumber = a[0]; if (!string.IsNullOrEmpty(SerialNumber)) { slotPreadjustment[slot] = int.TryParse(a[4], out _); } } catch (Exception ex) { _logger.Error(ex, $"error at meter done web request (PcbId={gen.PcbId}"); throw; } } } } public void MeterDone(Int32 slot, Boolean Succeed) { try { setBusy(true, $"Set {slot} LCD"); Task.Factory.StartNew(() => { //FF-55-00-00 var meter = batch.ListOfMeters.First(f => f.Slot == slot); var state = DisplayCodes.FlowTested; if (meter is MagFluxMeter mag) { try { var sb = new StringBuilder(); if (TestSetupContainer.meterTestSettings.Any(s => s != null && s.Slot == slot && s.PreAdjustment)) { //essageBox.Show($"has meter with Zeroflow {slot}"); var result = TestSetupContainer.meterTestResults.First(s => s != null && s.Slot == slot); sb.AppendLine($"Results: {result.SerialNr} on ep. {result.Slot}"); foreach (var flowDeviations in result.Results) { //MessageBox.Show($"RefFlow {flowDeviations.MeasuredRefFlowQmPerH} (for {flowDeviations.RefTimeS} Seconds) vs DutFlow {flowDeviations.MeasuredDutFlowQmPerH} (for {flowDeviations.DutTimeS} Seconds)"); sb.AppendLine($"RefFlow {flowDeviations.MeasuredRefFlowQmPerH} (for {flowDeviations.RefTimeS} Seconds) vs DutFlow {flowDeviations.MeasuredDutFlowQmPerH} (for {flowDeviations.DutTimeS} Seconds)"); } //MessageBox.Show(sb.ToString()); mag.WriteLog(sb.ToString()); mag.WriteCalibrationTestBench(result.Results); } } catch (Exception ex) { MessageBox.Show(ex.Message); } return; } if (!Succeed) { if (meter is GenesisMeter gen) { if (gen.IsLoggedOn) { var displayState = gen.ReadRegister(Register.Genesisflow.TriggerIdle); var displayStateString = ByteStyler.ToString(displayState); if (displayStateString.Substring(0, 2) != "FF") { state = DisplayCodes.FlowTestFailed; } else { gen.WriteLog($"meter not active because display code has an error on code:{displayStateString}"); //skip set return; } } } } if (meter is GenesisMeter genMeter) { try { if (!genMeter.IsLoggedOn) { genMeter.Login(); } meter.SetProcessState(state); genMeter.WriteRegister(Register.Genesisflow.SampleRate, 2); genMeter.WriteRegister(Register.Genesisflow.LedMode, 0); meter.WriteLog($"MeterIsDone {state} {genMeter.LutCrc }"); } catch (Exception ex) { meter.WriteLog($"MeterIsDone {state} with ex {ex.Message}"); } } else { meter.WriteLog($"MeterIsDone {state} "); } }).ContinueWith(delegate { setBusy(false); }); } catch (Exception ex) { _logger.Error(ex, $"error at MeterDone(slot={slot},Succeed={Succeed})"); } } public void SetErrorFrame(Int32 slot, Double errorFrame = 0.0) { try { setBusy(true, "Setze Fehlergrenze"); updateCell("Fehlergrenze [%]", slot, errorFrame); if (slotErrorFrameDic.ContainsKey(slot)) { slotErrorFrameDic.Remove(slot); } slotErrorFrameDic.Add(slot, errorFrame); setBusy(false); } catch (Exception ex) { _logger.Error(ex, $"error at SetErrorFrame(slot={slot},errorFrame={errorFrame}"); } } public void LogMeter(Int32 slot, String message) { try { Task.Factory.StartNew(() => { var meter = batch.ListOfMeters.First(f => f.Slot == slot); meter.WriteLog(message); }); } catch (Exception ex) { _logger.Error(ex, $"error at LogMeter(slot={slot},message={message}"); } } private Boolean PrepareMeters_Internal() { try { setBusy(true, "Bereite Zähler vor"); if (IsAdjustment) { CalibrationIsDone = new Dictionary(); } var listOfTasks = new List(); foreach (var meter in batch.ListOfMeters) { _logger.Debug($"Add Meter To Grid {meter.Slot}"); if ((meter is GenesisMeter genesisMeter)) { AddMeterToGrid(meter.Slot, meter.SerialNumber, genesisMeter.PcbId, IsFlyingStartStop); } else if ((meter is MagFluxMeter fluxMeter)) { AddMeterToGrid(meter.Slot, meter.SerialNumber, fluxMeter.PcbId, IsFlyingStartStop); } else { AddMeterToGrid(meter.Slot, meter.SerialNumber, "-", IsFlyingStartStop); } //todo : roland check SkipPrepearationForTestBench //((GenesisMeter)meter).SkipPrepearationForTestBench = true; if (IsAdjustment) { CalibrationIsDone.Add(meter.Slot, LegacyCalibrationResult.Pending); } if (_useRequest) { listOfTasks.Add(new Task(() => { if ((meter is GenesisMeter gMeter)) { ((GenesisMeter)meter).ReLogin(); } meter.WriteLog("Prepare meter for Measurement/Adjustment "); _logger.Debug("Prepare Meters for Measurement/Adjustment"); if (IsAdjustment) { meter.InitCalibration(); } else { meter.InitMeasurement(); } })); //// Reboot, HighPressure ////ReadOut Alarms, Show and reset //_logger.Debug($"Start CheckMetersAreReadyForTest"); } } listOfTasks.ForEach(t => t.Start()); Task.WaitAll(listOfTasks.ToArray()); TryInvoke(new Action(UpdateBatch)); //When testing with scale we dont have a flow right now if (!IsFlyingStartStop) { CheckMetersAreReadyForTest(); } setBusy(false); return true; } catch (Exception ex) { _logger.Error(ex, $"error at PrepareMeters(meterDn={MeterDn},refPulseValence={RefPulseValence}," + $"predictedQFlow ={PredictedQFlow},predictedTs={PredictedTs},refError={RefError}," + $"isAdjustment={IsAdjustment},IsFlyingStartStop={IsFlyingStartStop}"); return false; } } private void CheckMetersAreReadyForTest() { _logger.Trace("CheckMetersAreReadyForTest"); try { TryInvoke(new Action(() => { lblAction.Text = @"Warte auf Zählerstand wechsel von allen Zählern"; })); var listOfTasks = new List(); listOfTasks.Add(new Task(() => { var SlotsWithoutProgress = new List(); var TotalTimeForCheck = 65; var sleepTimeS = 5; foreach (var meter in batch.ListOfMeters) { if (!(meter is GenesisMeter)) { continue; } _logger.Debug($" Meter {meter.Slot} CheckMetersAreReadyForTest loops {TotalTimeForCheck};delay {sleepTimeS}S"); ((GenesisMeter)meter).StartMeasurement(); SlotsWithoutProgress.Add(((GenesisMeter)meter).Slot); } Thread.Sleep(sleepTimeS * 1000); //Run as long the Checktime is not zero or we dont have a meter left without progress while (TotalTimeForCheck >= 0 && SlotsWithoutProgress.Any()) { Thread.Sleep(sleepTimeS * 1000); TotalTimeForCheck -= sleepTimeS; foreach (var meter in batch.ListOfMeters) { try { if (SlotsWithoutProgress.Contains(meter.Slot)) { try { var r = ((GenesisMeter)meter).GetMainMeasurementResult(null, null, true); //when Start and Stop Record have different Volumes the meter is ready for test, //if a measurement hasn't finished, the StopRecord is an intermediate record, as //this will be used for intermediate tolerance calculation. //ReSharper disable once CompareOfFloatsByEqualityOperator as the rounding will take place in the //Cordonel and only an unequally value needs to be detected //when Start and Stop Record have diffrent Volumes the meter is ready for test if (r.DutStartRecord.GetVolumeCm() != r.DutStopRecord.GetVolumeCm()) { _logger.Info($" Meter {meter.Slot} Meter has progress {r.DutVolumeCm}"); ((GenesisMeter)meter).StopMeasurement(); SlotsWithoutProgress.Remove(meter.Slot); } _logger.Info($" Meter {meter.Slot} display frozen {r.DutVolumeCm} ccm; loops left {TotalTimeForCheck} s"); } catch (Exception ex) { if (ex is ApplicationException aex && aex.Message.Contains("Measurement records missing")) { _logger.Info($" Meter {meter.Slot} display frozen record is missing; loops left {TotalTimeForCheck} s"); } else { _logger.Info($" Meter {meter.Slot} display frozen record is missing; loops left {TotalTimeForCheck} s"); _logger.Error(ex); } } } } catch (Exception ex) { _logger.Error(ex, $" Meter {meter.Slot} Meter has progress error"); } } } if (SlotsWithoutProgress.Any()) { foreach (var item in SlotsWithoutProgress) { _logger.Warn($"Slot {item} has no progress"); } } else { _logger.Debug($"All Meters have progress"); } })); listOfTasks.ForEach(t => t.Start()); Task.WaitAll(listOfTasks.ToArray()); } catch (Exception ex) { _logger.Error(ex); //in case something went wrong this check can be skip } } public Boolean StartMeasurement_Internal() { try { _logger.Debug($"StartMesurment from state machien"); var listOfTasks = new List(); foreach (var item in batch.ListOfMeters) { listOfTasks.Add(new Task(() => { var settings = TestSetupContainer.meterTestSettings.First(f => f != null && f.Slot == item.Slot); if (IsAdjustment && settings.FlowAdjustment) { item.StartCalibration(); } if (!IsAdjustment && settings.FlowTesting) { item.StartMeasurement(); } })); } listOfTasks.ForEach(t => t.Start()); Task.WaitAll(listOfTasks.ToArray()); currentMode = Mode.AutoRefresh; return true; } catch (Exception ex) { _logger.Error(ex, "StartMeasurement"); } return false; } public void StartMeasurement() { _logger.Info("Caller start Measurement"); _currentState = BatchState.StartMesurement; } public void SetLoggerActionText(String ActionText) { foreach (var item in batch.ListOfMeters) { if (item is GenesisMeter gm) { gm.CurrentActionText = $"{ActionText}"; } } } public void StopMeasurement() { _logger.Info("Caller stop Measurement"); _currentState = BatchState.StopMesurement; } public Boolean StopMeasurement_Internal() { try { var nrOfRetrys = 40; _logger.Info("SM Call StopMeasurement_Internal"); foreach (var item in batch.ListOfMeters) { var settings = TestSetupContainer.meterTestSettings.First(f => f != null && f.Slot == item.Slot); if (IsAdjustment && !settings.FlowAdjustment) { continue; } if (!IsAdjustment && !settings.FlowTesting) { continue; } if (IsAdjustment) { item.StopCalibration(); } else { item.StopMeasurement(); } } _logger.Info("All Meters Stopped"); var listOfTasks = new List(); foreach (var item in batch.ListOfMeters) { var settings = TestSetupContainer.meterTestSettings.First(f => f != null && f.Slot == item.Slot); if (IsAdjustment && !settings.FlowAdjustment) { continue; } if (!IsAdjustment && !settings.FlowTesting) { continue; } listOfTasks.Add(new Task(() => { if (IsAdjustment) { Int32 retrys = 0; while (item.GetCalibrationState() != MeasurementStates.IsCompleted && retrys < nrOfRetrys) { if (retrys == (nrOfRetrys / 2)) { item.StopCalibration(); } Thread.Sleep(100); retrys = retrys + 1; } } else { Int32 retrys = 0; //remove channel filter 0 var onlyChnl = _checkAllChannels ? null : (Int32?)0; while (item.GetMeasurementState(onlyChnl) != MeasurementStates.IsCompleted && retrys < nrOfRetrys) { if (retrys == (nrOfRetrys / 2)) { item.StopMeasurement(); } Thread.Sleep(100); retrys = retrys + 1; } } })); } listOfTasks.ForEach(t => t.Start()); Task.WaitAll(listOfTasks.ToArray()); foreach (var item in batch.ListOfMeters) { if (!IsAdjustment && item is GenesisMeter gm) { gm.CurrentActionText = "FlowTest"; } } return true; } catch (Exception ex) { _logger.Error(ex, "StopMeasurement"); } return false; } Boolean ICtlBatch.IsBusy() { return IsBusy; } private MeasurementResults? GetMeasurementResult(Int32 Slot, Int32 Chnnl, Double refVolQm, Double refTimeS, MeasurementDirection dir = MeasurementDirection.TakeBoth) { try { var meter = batch.ListOfMeters.First(f => f.Slot == Slot); MeasurementResults result; if (meter is GenesisMeter genesisMeter) { if (Chnnl != 0) { result = genesisMeter.GetAllMeasurementResults(refVolQm, refTimeS) .FirstOrDefault(f => f.Channel == Chnnl); return result; } if (((GenesisMeter)meter).AllChannelsRequired) { if (meter.GetMeasurementState() != MeasurementStates.IsCompleted) { return null; } } } result = refTimeS == 0.0 ? meter.GetMainMeasurementResult(refVolQm, null, dir: dir) : meter.GetMainMeasurementResult(refVolQm, refTimeS, dir: dir); return result; } catch (Exception ex) { _logger.Error(ex, $"error on GetResults Slot={Slot},Chnnl={Chnnl},refVolQm={refVolQm},refTimeS={refTimeS}"); return null; } } public Results GetResults(Int32 Slot, Int32 Chnnl, Double refVolQm, Double refTimeS) { try { //todo remove MeasurementResults? result; var t = MeasurementDirection.TakeBoth; try { if (TestSetupContainer != null && TestSetupContainer.meterTestSettings != null && TestSetupContainer.meterTestSettings.Any(ts => ts != null && ts.Slot == Slot)) { var testset = TestSetupContainer.meterTestSettings.First(ts => ts != null && ts.Slot == Slot); if (testset.FlowTestingOnlyRevers) { t = MeasurementDirection.TakeOnlyBackward; } else if (testset.FlowTestingOnlyForward) { t = MeasurementDirection.TakeOnlyForward; } if (testset.meterType == MeterTypes.eRegister) { t = MeasurementDirection.TakeBoth; } if (testset.meterType == MeterTypes.MagFlux) { if (testset.FlowTestingOnlyRevers) { t = MeasurementDirection.TakeOnlyBackward; }else if (testset.FlowAdjustment) { t = MeasurementDirection.TakeBoth; } else { t = MeasurementDirection.TakeOnlyForward; } } } else { _logger.Warn($"No TestSetupContainer found ({TestSetupContainer != null}) or no MeterTestsetting found ({TestSetupContainer.meterTestSettings != null}) or no Testsettings for Slot {Slot} found ({TestSetupContainer.meterTestSettings.Any(ts => ts != null && ts.Slot == Slot)}) "); } } catch (Exception ex) { _logger.Error(ex, $"error on GetResults find Testcontainer Slot={Slot},Chnnl={Chnnl},refVolQm={refVolQm},refTimeS={refTimeS}"); throw; } result = GetMeasurementResult(Slot, Chnnl, refVolQm, refTimeS, t); if (!result.HasValue) { _logger.Warn($"No Result found for GetResults(Slot={Slot},Chnnl={Chnnl},refVolQm={refVolQm},refTimeS={refTimeS})"); return new Results(); } _logger.Debug($"Result request by caller for Slot={Slot} and Channel={Chnnl} with refVolQm={refVolQm} and refTimeS={refTimeS} are:"); _logger.Debug($"AccuDutOverflowTimeS = {result.Value.AccuDutOverflowTimeS}"); _logger.Debug($"AccuDutOverflowVolumeCm = {result.Value.AccuDutOverflowVolumeCm}"); _logger.Debug($"DeviationDutToRefPer = {result.Value.DeviationDutToRefPer}"); _logger.Debug($"DeviationDutToRefRel = {result.Value.DeviationDutToRefRel}"); _logger.Debug($"DutFlowRateCmPh = {result.Value.DutFlowRateCmPh}"); _logger.Debug($"DutTimeS = {result.Value.DutTimeS}"); _logger.Debug($"DutVolumeCm = {result.Value.DutVolumeCm}"); _logger.Debug($"RefTimeS = {result.Value.RefTimeS}"); _logger.Debug($"RefVolumeCm = {result.Value.RefVolumeCm}"); _logger.Debug($"ScaleFactorRefToDut = {result.Value.ScaleFactorRefToDut}"); _logger.Debug($"Start Record: TimeS={result.Value.DutStartRecord.GetTimeS()}, VolumeCm={result.Value.DutStartRecord.GetVolumeCm()}"); _logger.Debug($"End Record: TimeS={result.Value.DutStopRecord.GetTimeS()}, VolumeCm={result.Value.DutStopRecord.GetVolumeCm()}"); //try //{ // var meter = batch.ListOfMeters.First(f => f.Slot == Slot); // if (meter is GenesisMeter genesisMeter) // { // foreach (var item in genesisMeter.ErrorCurrent) // { // _logger.Debug($"Error Cound:CHNL {item.Key} : Total count {item.Value.Item1} ; last error {item.Value.Item2}"); // } // } //} //catch (Exception) //{ //} var sbError = string.Empty; if (ErrorMetersAlarms.ContainsKey(Slot) && ErrorMetersAlarms[Slot].HasFlag(TestBenchRelatedAlarms)) { var MeterAlarms = ErrorMetersAlarms[Slot].GetHashCode(); sbError = $"ErrorCode{MeterAlarms}"; } if (Chnnl == 0) { try { if (TestSetupContainer != null) { if (TestSetupContainer.meterTestResults == null) { TestSetupContainer.meterTestResults = new MeterTestResults[10]; } if (!TestSetupContainer.meterTestResults.Any(f => f != null && f.Slot == Slot)) { TestSetupContainer.meterTestResults[Slot - 1] = new MeterTestResults(); TestSetupContainer.meterTestResults[Slot - 1].Slot = Slot; TestSetupContainer.meterTestResults[Slot - 1].Results = new List(); } var results = TestSetupContainer.meterTestResults[Slot - 1].Results; if (!results.Any(f => f.MeasuredRefFlowQmPerH == result.Value.RefFlowRateCmPh)) { results.Add(new Xylem.Common.Hardware.WaterMeter.DataPackages.MeasurementRecords.FlowDeviations() { MeasuredRefFlowQmPerH = result.Value.RefFlowRateCmPh ?? 0, RefTimeS = result.Value.RefTimeS ?? 0, RequierdFlowQmPerH = result.Value.RefFlowRateCmPh ?? 0, RequierdTimeS = result.Value.RefTimeS ?? 0, MeasuredDutFlowQmPerH = result.Value.DutFlowRateCmPh ?? 0, DutTimeS = result.Value.DutTimeS, }); } } else { _logger.Error($"error no TestSetupcontainer on GetResults add testresult Slot={Slot},Chnnl={Chnnl},refVolQm={refVolQm},refTimeS={refTimeS}"); } } catch (Exception ex) { _logger.Error(ex, $"error on GetResults add testresult Slot={Slot},Chnnl={Chnnl},refVolQm={refVolQm},refTimeS={refTimeS}"); } } return new Results(result.Value, sbError); } catch (Exception ex) { _logger.Error(ex, $"error on GetResults Slot={Slot},Chnnl={Chnnl},refVolQm={refVolQm},refTimeS={refTimeS}"); return new Results(); } } public LegacyCalibrationResult GetCalibrationResult(Int32 slot) { try { if (CalibrationIsDone == null || !CalibrationIsDone.Any()) { throw new ApplicationException("No Calibration is running"); } if (!CalibrationIsDone.ContainsKey(slot)) { throw new ApplicationException($"No Calibration is running on slot {slot}"); } return CalibrationIsDone[slot]; } catch (Exception ex) { _logger.Error(ex, "error on GetCalibrationIsDone"); return LegacyCalibrationResult.CheckAllMeters; } } public LegacyCalibrationResult GetCalibrationIsDone() { try { if (CalibrationIsDone.Any(any => any.Value == LegacyCalibrationResult.Pending)) { return LegacyCalibrationResult.Pending; } if (CalibrationIsDone.All(all => all.Value == LegacyCalibrationResult.Good)) { return LegacyCalibrationResult.Good; } if (CalibrationIsDone.Any(any => any.Value == LegacyCalibrationResult.BadAbort)) { return LegacyCalibrationResult.BadAbort; } return LegacyCalibrationResult.CheckAllMeters; } catch (Exception ex) { _logger.Error(ex, "error on GetCalibrationIsDone"); return LegacyCalibrationResult.CheckAllMeters; } } public void StartStoreCalibrationAuto(Double refVolume, Double testTimeRef, Double AdjustmentPerc = 0) { MeterDefaultCorrection = AdjustmentPerc; StartStoreCalibration(refVolume, testTimeRef); btnOk_Click(null, EventArgs.Empty); } public void StartStoreCalibration(Double refVolume, Double testTimeRef) { try { pnlEndTime.Visible = false; StoreRefVolume = refVolume; StoreTestTimeRef = testTimeRef; UpdateBatch(); pnlCalibration.Visible = true; foreach (var baseMeter in batch.ListOfMeters) { var settings = TestSetupContainer.meterTestSettings.First(f => f != null && f.Slot == baseMeter.Slot); if (settings.FlowAdjustment) { updateCellToInput("Zielwert Justage [%]", baseMeter.Slot, false); updateCell("Zielwert Justage [%]", baseMeter.Slot, (Double)settings.FlowAdjustmentTarget, 2, Color.Beige); } } } catch (Exception ex) { _logger.Error(ex, $"error on StartStoreCalibration refVolume={refVolume},testTimeRef={testTimeRef}"); } } public void AddMeterToGrid(Int32 Slot, String SerialNumber, String PcbId, Boolean isFlyingStartStop) { try { IsFlyingStartStop = isFlyingStartStop; //var totalWidth = dgvBatch.Columns.GetColumnsWidth(DataGridViewElementStates.None) + 40; //dgvBatch.Size = new Size(totalWidth, dgvBatch.Size.Height); updateCell("Einbauplatz", Slot, Slot.ToString()); updateCell("Seriennummer", Slot, SerialNumber); updateCell("PcbId", Slot, PcbId); TryInvoke(new Action(() => { dgvBatch.Columns[Slot].Visible = true; })); } catch (Exception ex) { _logger.Error(ex, $"error on AddMeterToGrid Slot={Slot},SerialNumber={SerialNumber}," + $"IsFlyingStartStop={IsFlyingStartStop}"); } } public void ShowTest() { setBusy(false); ManualUpdate(); TryInvoke(new Action(() => { pnlEndTime.Visible = true; })); } //private void TimerSetting() //{ // switch (currentMode) // { // case Mode.AutoRefresh: // RefeshTimer = new System.Windows.Forms.Timer(); // RefeshTimer.Interval = 10000; // RefeshTimer.Tick += RefreshTimer_Tick; // RefeshTimer.Enabled = true; // break; // case Mode.View: // RefeshTimer.Enabled = false; // break; // } //} private void initAction(String meterDn = "-", Double refPulseValence = 0, Double predictedQFlow = 0, Double predictedTs = 0, Double refError = 0, Boolean isFlyingStartStop = true) { TryInvoke(new Action(() => { initDt(); pnlEndTime.Visible = false; pnlCalibration.Visible = false; IsFlyingStartStop = isFlyingStartStop; Clear(); InitLabelValueCollection(); MeterDn = meterDn; RefPulseValence = refPulseValence; PredictedTs = predictedTs; RefError = refError; currentMode = Mode.AutoRefresh; //this.RefreshTimer.Interval = 10000; //this.RefreshTimer.Tick += new EventHandler(this.RefreshTimer_Tick); //this.RefreshTimer.Enabled = true; pgbUpdate.Maximum = 10000; updateLabelCollection(); ExpertMode(cbxExpert.Checked); // dgvBatch.Size = new Size(SizeOfMeter, dgvBatch.Size.Height); pgbEndTime.Maximum = (Int32)predictedTs; })); } public void Init(String meterDn = "-", Double refPulseValence = 0, Double predictedQFlow = 0, Double predictedTs = 0, Double refError = 0, Boolean isFlyingStartStop = true) { try { IsFlyingStartStop = isFlyingStartStop; setBusy(true, "lade Prüfpunkt"); initAction(meterDn, refPulseValence, predictedQFlow, predictedTs, refError, IsFlyingStartStop); setBusy(false); } catch (Exception ex) { _logger.Error(ex, $"error on Init meterDn={meterDn},refPulseValence={refPulseValence}," + $"predictedQFlow={predictedQFlow},predictedTs={predictedTs}," + $"refError={refError},IsFlyingStartStop={IsFlyingStartStop}"); } } public void SetBatchInfos(Double refFlowrate = 0, Double refTestTime = 0, Double refFlowUncorrected = 0, Int32 currentPulse = 0, Double currentRefVolume = 0, Int32 remainingPulse = 0, String period = "-", Boolean forceMeterUpdate = false) { try { CurrentPulse = currentPulse; CurrentRefVolume = currentRefVolume; if (refTestTime > 9 && currentRefVolume == 0 && refFlowrate != 0) { CurrentRefVolume = (refTestTime / 3600) * refFlowrate; } RemainingPulse = remainingPulse; Period = period; RefFlowrate = refFlowrate; RefTestTime = refTestTime; RefFlowUncorrected = refFlowUncorrected; updateLabelCollection(); updateTotalProgress(refTestTime); // if (forceMeterUpdate) // { UpdateBatch(); // } } catch (Exception ex) { _logger.Error(ex, $"error on SetBatchInfos refFlowrate={refFlowrate}," + $"refTestTime={refTestTime},refFlowUncorrected={refFlowUncorrected}," + $"currentPulse={currentPulse},currentRefVolume={currentRefVolume}," + $"remainingPulse={remainingPulse},period={period}"); } } private void UpdateBatch() { try { stopWatch.Reset(); var listOfStates = new List(); foreach (var item in batch.ListOfMeters) { try { //if (item is GenesisMeter) //{ var settings = TestSetupContainer.meterTestSettings.First(f => f != null && f.Slot == item.Slot); if ((IsAdjustment && !settings.FlowAdjustment) || (!IsAdjustment && !settings.FlowTesting)) { updateCell("Status", item.Slot, "-", Color.Gray); continue; } var _meter = item; var onlyChnl = _checkAllChannels ? null : (Int32?)0; var ProcessStatus = item.GetMeasurementState(onlyChnl); listOfStates.Add(ProcessStatus); String textState; var statusColor = Color.Empty; switch (ProcessStatus) { case MeasurementStates.IsCompleted: textState = "Messung beendet"; statusColor = Color.Green; break; case MeasurementStates.IsRunning: case MeasurementStates.IsWaitingForIntermediateData: textState = "Messung läuft"; break; case MeasurementStates.NotStarted: default: textState = "nicht gestartet"; break; case MeasurementStates.IsWaitingForStartData: case MeasurementStates.IsWaitingForEndData: textState = "warte auf Daten"; statusColor = Color.Yellow; break; } updateCell("Status", _meter.Slot, textState, statusColor); Double? testTime = null; if (IsFlyingStartStop) { testTime = RefTestTime; } if (ProcessStatus != MeasurementStates.NotStarted) { var interResult = new List(); if (ProcessStatus == MeasurementStates.IsRunning || ProcessStatus == MeasurementStates.IsWaitingForIntermediateData) { if (_checkAllChannels) { interResult = _meter.GetAllMeasurementResults(CurrentRefVolume, testTime, true); } else { interResult.Add(_meter.GetMainMeasurementResult(CurrentRefVolume, testTime, true)); } } else if (ProcessStatus == MeasurementStates.IsCompleted) { if (_checkAllChannels) { interResult = _meter.GetAllMeasurementResults(CurrentRefVolume, testTime); } else { interResult.Add(_meter.GetMainMeasurementResult(CurrentRefVolume, testTime)); } } if (interResult != null && interResult.Any()) { foreach (var channelResult in interResult) { var prefix = ""; if (channelResult.Channel > 0) { prefix = $"Pfad {channelResult.Channel} "; } updateCell($"{prefix}Druchfluss [m³/h]", _meter.Slot, channelResult.DutFlowRateCmPh ?? 0, 4); updateCell($"{prefix}Volumen [m³]", _meter.Slot, Math.Abs(channelResult.DutVolumeCm), 4); updateCell($"{prefix}Zeit [S]", _meter.Slot, channelResult.DutTimeS); if (channelResult.DeviationDutToRefPer.HasValue) { updateCell($"{prefix}Fehler [%]", _meter.Slot, channelResult.DeviationDutToRefPer.Value, 2, getErrorColor(channelResult.DeviationDutToRefPer.Value, _meter.Slot)); if (channelResult.Channel == 0) { _logger.Info($"CurrentDeviation on {_meter.Slot} = {channelResult.DeviationDutToRefPer.Value}% (DutFlow:{channelResult.DutFlowRateCmPh}, CurrentRefVolume: {CurrentRefVolume}, testTime: {testTime})"); } } else { updateCell($"{prefix}Fehler [%]", _meter.Slot, "NaN", getErrorColor(100, _meter.Slot)); } } } } //} } catch (Exception e) { _logger.Error(e, $"error on UpdateBatch for meter {e.Message} "); } } if (listOfStates.All(a => a.Equals(MeasurementStates.IsCompleted))) { currentMode = Mode.View; TryInvoke(new Action(() => { //this.RefreshTimer.Enabled = false; //this.pnlEndTime.Visible = false; })); } else { currentMode = Mode.AutoRefresh; } TryInvoke(new Action(() => { //this.RefreshTimer.Enabled = true; })); stopWatch.Start(); } catch (Exception ex) { _logger.Error(ex, $"error on UpdateBatch {ex.Message} "); } } public void Clear() { try { grbInfo.Controls.Clear(); labelValueCollection.Clear(); MeterDn = string.Empty; RefPulseValence = 0.0; PredictedTs = 0.0; RefError = 0.0; //RefeshTimer = new System.Windows.Forms.Timer(); //RefeshTimer.Interval = 50000; //RefeshTimer.Enabled = false; currentMode = Mode.View; } catch (Exception ex) { _logger.Error(ex, "error on Clear()"); } } private void ManualUpdate() { try { setBusy(true, "Update"); Task.Factory.StartNew(() => { foreach (var item in batch.ListOfMeters) { if (item is GenesisMeter) { // ((GenesisMeter)item).(); } } Thread.Sleep(1000); UpdateBatch(); }).ContinueWith(delegate { setBusy(false); }); } catch (Exception ex) { _logger.Error(ex, "error on ManuleUpdate()"); } } #endregion #region GUI private void btnPlus1_Click(Object sender, EventArgs e) { nudFactor.Value = nudFactor.Value + 1; } private void btnPlus01_Click(Object sender, EventArgs e) { nudFactor.Value = nudFactor.Value + (Decimal)0.1; } private void btnMinus01_Click(Object sender, EventArgs e) { nudFactor.Value = nudFactor.Value - (Decimal)0.1; } private void btnMinus1_Click(Object sender, EventArgs e) { nudFactor.Value = nudFactor.Value - 1; } private void btnOk_Click(Object sender, EventArgs e) { try { var taskList = new List>>(); TryInvoke(new Action(() => { pnlCalibration.Visible = false; })); foreach (var baseMeter in batch.ListOfMeters) { var settings = TestSetupContainer.meterTestSettings.First(f => f != null && f.Slot == baseMeter.Slot); if (!settings.FlowAdjustment) { continue; } var calFactor = getCellValue("Zielwert Justage [%]", baseMeter.Slot); if (baseMeter is GenesisMeter) { var calibrationTask = new Task>(() => { try { var genesis = (GenesisMeter)baseMeter; genesis.ReLogin(); genesis.BuildAndCheckCalibFactorsAllChannels(StoreRefVolume, StoreTestTimeRef, calFactor, 0,null); //genesis.SetCalibFactorsAllChannels(true); genesis.SetCalibFactorsAllChannels(); return new Tuple(true, baseMeter.Slot); } catch (Exception ex) { _logger.Error(ex, "Calibration went wrong"); return new Tuple(false, baseMeter.Slot); } }); taskList.Add(calibrationTask); } } setBusy(true, "Speicher Zielwert Justage"); taskList.ForEach(ct => ct.Start()); var t = new Task(() => { // ReSharper disable once CoVariantArrayConversion Task.WaitAll(taskList.ToArray()); Boolean overallResult = true; foreach (var item in taskList) { if (item.Result.Item1) { setColor("Zielwert Justage [%]", item.Result.Item2, Color.Green); setColor("Seriennummer", item.Result.Item2, Color.Green); CalibrationIsDone[item.Result.Item2] = LegacyCalibrationResult.Good; } else { setColor("Zielwert Justage [%]", item.Result.Item2, Color.LightYellow); setColor("Seriennummer", item.Result.Item2, Color.LightYellow); CalibrationIsDone[item.Result.Item2] = LegacyCalibrationResult.BadRetry; overallResult = false; } } setBusy(false); if (overallResult == false) { var r = MessageBox.Show(@"Calibration went wrong", @"Retry", MessageBoxButtons.AbortRetryIgnore); foreach (var changeState in CalibrationIsDone.ToList()) { if (changeState.Value != LegacyCalibrationResult.Good) { switch (r) { case DialogResult.Abort: CalibrationIsDone[changeState.Key] = LegacyCalibrationResult.BadAbort; break; case DialogResult.Ignore: CalibrationIsDone[changeState.Key] = LegacyCalibrationResult.BadIgnor; break; } } } } } ); t.Start(); } catch (Exception ex) { _logger.Error(ex, "error on btnOk_Click()"); } } private void btnUpdate_Click(Object sender, EventArgs e) { ManualUpdate(); //if (RefreshTimer.Enabled) //{ // RefreshTimer.Stop(); // RefreshTimer.Start(); //} } private void cbxExpert_CheckedChanged(Object sender, EventArgs e) { dgvBatch.ClearSelection(); ExpertMode(cbxExpert.Checked); } private void nudFactor_ValueChanged(Object sender, EventArgs e) { foreach (var basemeter in batch.ListOfMeters) { updateCell(@"Zielwert Justage [%]", basemeter.Slot, nudFactor.Value.ToString(CultureInfo.InvariantCulture), Color.Beige); } } private void ctlBatch_ControlRemoved(Object sender, ControlEventArgs e) { Close(); } private void Close() { if (stopWatch != null) { stopWatch.Stop(); stopWatch = null; } //if (RefeshTimer != null) //{ // RefeshTimer.Enabled = false; // RefeshTimer = null; //} //if (RefreshTimerWatch != null) //{ // RefreshTimerWatch.Enabled = false; // RefreshTimerWatch = null; //} } #endregion #region helper private String doubleToStringFormat(Double Value, Int32 digits = 2) { var text = "-"; if (!double.IsNaN(Value)) { // ReSharper disable once FormatStringProblem text = string.Format("{0:N" + digits + // ReSharper disable once FormatStringProblem "}", Value); } return text; } public void TryInvoke(Delegate d) { if (IsHandleCreated) { Invoke(d); } } void ICtlBatch.Dispose(Boolean fromCode) { Dispose(fromCode); } private void ctlBatch_Resize(Object sender, EventArgs e) { //181 dgvBatch.Width = Width - 181; } #endregion /// /// Clean up any resources being used. /// /// true if managed resources should be disposed; otherwise, false. protected override void Dispose(Boolean disposing) { if (batch != null) { batch.DisposeTestBench(); batch.RemoveAllMeters(); batch.Dispose(); } if (disposing && (components != null)) { components.Dispose(); } base.Dispose(disposing); } public String GetVersion() { var taskList = new List>(); foreach (var baseMeter in batch.ListOfMeters) { if (baseMeter is GenesisMeter) { var calibrationTask = new Task(() => { try { var genesis = (GenesisMeter)baseMeter; genesis.PushProgress("LegacyGenCtl", Assembly.GetExecutingAssembly().GetName().Version.ToString()); return true; } catch (Exception ex) { _logger.Error(ex, "PushProgress went wrong"); return false; } }); taskList.Add(calibrationTask); } } taskList.ForEach(ct => ct.Start()); if (taskList.Count > 0) { // ReSharper disable once CoVariantArrayConversion Task.WaitAll(taskList.ToArray()); } return Assembly.GetExecutingAssembly().GetName().Version.ToString(); } public void SetTestSetupContainer(dynamic vbContainer) { vbContainer = vbContainer.ToString(); if (vbContainer is String strContainer) { StringBuilder sb = new StringBuilder(); vbContainer = JsonConvert.DeserializeObject(strContainer); } if (vbContainer is TestSetupContainer container) { _logger.Info($"SetTestSetupContainer ({vbContainer.ToString()}) "); TestSetupContainer = vbContainer; _currentState = BatchState.TestContainerIsReady; return; } else { _logger.Error("Test container unkown"); _logger.Error($"Test container type {vbContainer.GetType()}"); _logger.Error($"Test container cast {vbContainer}"); } _logger.Error("Test container setup failed"); _currentState = BatchState.Error; } public dynamic GetTestSetupContainer() { if (TestSetupContainer == null) { return new TestSetupContainer(); } return TestSetupContainer; } private void timStateMachine_Tick(Object sender, EventArgs e) { CtlBatchStateMachine(); } public void SetReadyForMesuremnt() { _logger.Debug($"Caller set batch state to state ReadyForMesuremnt"); _currentState = BatchState.ReadyForMesuremnt; } public Boolean MeasurementIsActive() { _logger.Debug($"Caller MeasurementIsActive state is{_currentState}"); return _currentState == BatchState.MeasurementActive; } public Boolean MeasurementIsCompleted() { _logger.Debug($"Caller MeasurementIsCompleted state is{_currentState}"); return _currentState == BatchState.MeasurementCompleted; } public Boolean MetersArePrepared() { _logger.Debug($"Caller MetersArePrepared state is{_currentState}"); return _currentState == BatchState.MetersPrepared; } public Boolean IsReadyForMesuremnt() { _logger.Debug($"Caller IsReadyForMesuremnt state is{_currentState}"); return _currentState == BatchState.ReadyForMesuremnt; } } }