common/Ui/LegacyGenesisControl/ctlBatch.cs
2026-04-23 17:50:07 +02:00

2513 lines
94 KiB
C#

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,
}
/// <summary>
/// State for state machine
/// </summary>
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<Int32, LegacyCalibrationResult> CalibrationIsDone = new Dictionary<Int32, LegacyCalibrationResult>();
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<Int32, Alarm> WarningMetersAlarms = new ConcurrentDictionary<Int32, Alarm>();
private ConcurrentDictionary<Int32, Alarm> ErrorMetersAlarms = new ConcurrentDictionary<Int32, Alarm>();
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<Int32, Double> slotErrorFrameDic = new Dictionary<Int32, Double>();
private Dictionary<Int32, String> slotLut = new Dictionary<Int32, String>();
private Dictionary<Int32, Boolean> slotPreadjustment = new Dictionary<Int32, Boolean>();
private Dictionary<String, Tuple<Label, String>> labelValueCollection;
public Boolean IsFlyingStartStop
{
get; private set;
}
private Double StoreRefVolume, StoreTestTimeRef;
private Stopwatch stopWatch = new Stopwatch();
private Dictionary<Int32, String> rowIndex = new Dictionary<Int32, String>();
#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<String, Tuple<Label, String>>();
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
/// <summary>
/// State machine for control batch
/// </summary>
/// <remarks date="2021-Feb-16" author="Thomas Wiedebusch">
/// - Initial.
/// </remarks>
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<Boolean>.Factory.StartNew(() => { return AddAllMeters_Internal(); });
tAddMeters.ContinueWith(r => { _currentState = r.Result ? BatchState.PrepareMeters : BatchState.Error; });
break;
case BatchState.PrepareMeters:
var tPrepareMeters = Task<Boolean>.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<Boolean>.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<Boolean>.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<Label, String>(tmpLblValue, value));
}
public void updateLabelCollection()
{
labelValueCollection["MeterDn"] = new Tuple<Label, String>(labelValueCollection["MeterDn"].Item1, MeterDn);
labelValueCollection["PulseValence"] =
new Tuple<Label, String>(labelValueCollection["PulseValence"].Item1, doubleToStringFormat(RefPulseValence));
labelValueCollection["PredictedQFlow"] =
new Tuple<Label, String>(labelValueCollection["PredictedQFlow"].Item1, doubleToStringFormat(PredictedQFlow, 6));
labelValueCollection["PredictedTs"] =
new Tuple<Label, String>(labelValueCollection["PredictedTs"].Item1, doubleToStringFormat(PredictedTs, 1));
labelValueCollection["RefError"] =
new Tuple<Label, String>(labelValueCollection["RefError"].Item1, doubleToStringFormat(RefError, 3));
labelValueCollection["CurrentPulse"] =
new Tuple<Label, String>(labelValueCollection["CurrentPulse"].Item1, CurrentPulse.ToString());
labelValueCollection["CurrentRefVolume"] =
new Tuple<Label, String>(labelValueCollection["CurrentRefVolume"].Item1, doubleToStringFormat(CurrentRefVolume, 6));
labelValueCollection["RemainingPulse"] =
new Tuple<Label, String>(labelValueCollection["RemainingPulse"].Item1, RemainingPulse.ToString());
labelValueCollection["Period"] = new Tuple<Label, String>(labelValueCollection["Period"].Item1, Period);
labelValueCollection["RefFlow"] = new Tuple<Label, String>(labelValueCollection["RefFlow"].Item1, doubleToStringFormat(RefFlowrate, 6));
labelValueCollection["RefFlowUncorrected"] =
new Tuple<Label, String>(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<T>(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<Int32, String>();
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;
/// <summary>
///
/// </summary>
/// <param name="ControlSrt"></param>
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<Task>();
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<Int32, Alarm>();
ErrorMetersAlarms = new ConcurrentDictionary<Int32, Alarm>();
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<Xylem.Common.Hardware.WaterMeter.DataPackages.MeasurementRecords.FlowDeviations>() };
}
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<String[]>(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<Int32, LegacyCalibrationResult>();
}
var listOfTasks = new List<Task>();
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<Task>();
listOfTasks.Add(new Task(() =>
{
var SlotsWithoutProgress = new List<int>();
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<Task>();
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<Task>();
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<Xylem.Common.Hardware.WaterMeter.DataPackages.MeasurementRecords.FlowDeviations>();
}
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<MeasurementStates>();
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<MeasurementResults>();
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<Task<Tuple<Boolean, Int32>>>();
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<Double>("Zielwert Justage [%]", baseMeter.Slot);
if (baseMeter is GenesisMeter)
{
var calibrationTask = new Task<Tuple<Boolean, Int32>>(() =>
{
try
{
var genesis = (GenesisMeter)baseMeter;
genesis.ReLogin();
genesis.BuildAndCheckCalibFactorsAllChannels(StoreRefVolume, StoreTestTimeRef, calFactor, 0,null);
//genesis.SetCalibFactorsAllChannels(true);
genesis.SetCalibFactorsAllChannels();
return new Tuple<Boolean, Int32>(true, baseMeter.Slot);
}
catch (Exception ex)
{
_logger.Error(ex, "Calibration went wrong");
return new Tuple<Boolean, Int32>(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
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
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<Task<Boolean>>();
foreach (var baseMeter in batch.ListOfMeters)
{
if (baseMeter is GenesisMeter)
{
var calibrationTask = new Task<Boolean>(() =>
{
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<TestSetupContainer>(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;
}
}
}