2513 lines
94 KiB
C#
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;
|
|
}
|
|
}
|
|
}
|