using ByteArrayStyle;
using Newtonsoft.Json;
using NLog;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using Xylem.Common.CommonCore.Configuration;
using Xylem.Common.Hardware.WaterMeter.eRegister.eRegisterCore;
using Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore;
using Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore.Consts;
using Xylem.Common.Hardware.WaterMeter.Genesis.Registers;
using Xylem.Common.Hardware.WaterMeter.MagFlux.MagFluxCore;
using Xylem.Common.Hardware.WaterMeter.WaterMeterCore;
using Xylem.Common.Hardware.WaterMeter.WaterMeterCore.Consts;
using Xylem.Common.Logic.SoftwareAccessHelper;
using Xylem.Common.Metrology.Measurements;
using Xylem.Common.Metrology.Measurements.Consts;
using Xylem.Common.Utils.Logging;
using XylemCommonUiLegacyGenCtl.DataPackage;
using XylemCommonUiLegacyGenCtl.Enums;
namespace XylemCommonUiLegacyGenCtl
{
[Guid("034A00BD-AAAA-4DF7-97F3-43D0CBF8A805"),
ComVisible(true),
ClassInterface(ClassInterfaceType.None),
ComSourceInterfaces(typeof(ICtlBatch))]
public partial class ctlBatch : UserControl, ICtlBatch
{
#region Const Layout
private const Int32 LblPositionLeft = 5;
private const Int32 LblPositionTop = 20;
private const Int32 LblPositionSize = 70;
private const Int32 LblPositionHeight = 70;
private const Int32 LblPositionSpace = 15;
private const Int32 SizeOfMeter = 140;
#endregion
#region Prop
private enum Mode
{
AutoRefresh,
View,
}
///
/// State for state machine
///
private enum BatchState
{
Idle,
Init,
Error,
PrepareGui,
PrepareMeasurement,
MeasurementActive,
MeasurementCompleted,
TestContainerIsReady,
BatchIsReady,
AddMeters,
PrepareMeters,
MetersPrepared,
ReadyForMesuremnt,
StartMesurement,
StopMesurement,
}
private BatchState _currentState;
private BatchState _backupState;
private Mode currentMode = Mode.View;
private ILogger _logger;
private Dictionary CalibrationIsDone = new Dictionary();
public MeterBatch batch;
//private System.Windows.Forms.Timer RefreshTimer = new System.Windows.Forms.Timer();
//private System.Windows.Forms.Timer RefreshTimerWatch = new System.Windows.Forms.Timer();
private Alarm TestBenchRelatedAlarms = Alarm.EMPTY_PIPE &
Alarm.REBOOT &
Alarm.HIGH_PRESSURE &
Alarm.HIGH_TEMPERATURE &
Alarm.LOW_PRESSURE &
Alarm.LOW_TEMPERATURE;
private ConcurrentDictionary WarningMetersAlarms = new ConcurrentDictionary();
private ConcurrentDictionary ErrorMetersAlarms = new ConcurrentDictionary();
public String MeterDn = "-";
public Double RefPulseValence;
public Double PredictedQFlow;
public Double PredictedTs;
public Double RefError;
public Int32 CurrentPulse;
public Double CurrentRefVolume;
public Int32 RemainingPulse;
public String Period = "-";
public Double RefFlowrate;
public Double RefTestTime;
public Double RefFlowUncorrected;
public Double MeterDefaultCorrection;
private TestSetupContainer TestSetupContainer;
private DataTable dtBatch;
#region busy
public Boolean IsBusy
{
get; private set;
}
private Int32? ProgressTotal;
private Int32? ProgressCurrent;
private Dictionary slotErrorFrameDic = new Dictionary();
private Dictionary slotLut = new Dictionary();
private Dictionary slotPreadjustment = new Dictionary();
private Dictionary> labelValueCollection;
public Boolean IsFlyingStartStop
{
get; private set;
}
private Double StoreRefVolume, StoreTestTimeRef;
private Stopwatch stopWatch = new Stopwatch();
private Dictionary rowIndex = new Dictionary();
#endregion
#endregion
#region ctor
public ctlBatch()
{
_logger = NLogHelper.CreateOrGetMultiLogger("ctlBatch", "", "Batch", "", "");
_logger.Info("start construct ctlBatch");
//RefreshTimerWatch.Enabled = true;
//RefreshTimerWatch.Interval = 5000;
//RefreshTimerWatch.Tick += RefreshTimerWatch_Tick;
InitializeComponent();
labelValueCollection = new Dictionary>();
InitLabelValueCollection();
grbInfo.SuspendLayout();
SuspendLayout();
Disposed += CtlBatch_Disposed;
//kick off the state machine
_currentState = BatchState.Init;
_backupState = BatchState.Idle;
_logger.Info("construct ctlBatch end");
}
private void CtlBatch_Disposed(Object sender, EventArgs e)
{
try
{
base.Dispose();
Close();
}
catch (Exception ex)
{
_logger.Error(ex, "error at CtlBatch_Disposed");
}
}
#endregion
#region StateMachine
///
/// State machine for control batch
///
///
/// - Initial.
///
private void CtlBatchStateMachine()
{
if (_currentState == _backupState)
{
Thread.Sleep(1);
}
else
{
// this loop calls the function and assigns the return states on success and error
// remind backup state to avoid repeated execution and side effects
_logger.Info($"StateMachine has change from {_backupState} to {_currentState}");
_backupState = _currentState;
switch (_currentState)
{
case BatchState.Idle:
break;
case BatchState.Init:
break;
case BatchState.Error:
break;
case BatchState.PrepareGui:
break;
case BatchState.PrepareMeasurement:
break;
case BatchState.TestContainerIsReady:
break;
case BatchState.BatchIsReady:
break;
case BatchState.AddMeters:
var tAddMeters = Task.Factory.StartNew(() => { return AddAllMeters_Internal(); });
tAddMeters.ContinueWith(r => { _currentState = r.Result ? BatchState.PrepareMeters : BatchState.Error; });
break;
case BatchState.PrepareMeters:
var tPrepareMeters = Task.Factory.StartNew(() => { return PrepareMeters_Internal(); });
tPrepareMeters.ContinueWith(r => { _currentState = r.Result ? BatchState.MetersPrepared : BatchState.Error; });
break;
case BatchState.MetersPrepared:
//Wait For Caller when every thing is setup
break;
case BatchState.ReadyForMesuremnt:
//Wait for caller to start Measurement
break;
case BatchState.StartMesurement:
var tStartMesurement = Task.Factory.StartNew(() => { return StartMeasurement_Internal(); });
tStartMesurement.ContinueWith(r => { _currentState = r.Result ? BatchState.MeasurementActive : BatchState.Error; });
break;
case BatchState.MeasurementActive:
// wait for signal that the measurement can be stopped
break;
case BatchState.StopMesurement:
var tStopMesurement = Task.Factory.StartNew(() => { return StopMeasurement_Internal(); });
tStopMesurement.ContinueWith(r => { _currentState = r.Result ? BatchState.MeasurementCompleted : BatchState.Error; });
break;
case BatchState.MeasurementCompleted:
//Measurement waiting for caller to grab all the results
break;
}// lock repeated execution of identical state
}
}
#endregion
#region busy
private void setBusy(Boolean val, String action = "", Boolean hideToExternal = false)
{
try
{
if (!hideToExternal)
{
IsBusy = val;
}
if (val)
{
TryInvoke(new Action(() =>
{
pnlBussy.Visible = true;
timProgress.Enabled = true;
lblAction.Text = action;
pnlBussy.Size = Size;
pnlBussy.Location = new Point(0, 0);
lblAction.Left = (ClientSize.Width - lblAction.Width) / 2;
lblAction.Top = ((ClientSize.Height - lblAction.Height) / 2) - (lblBussyHealine.Height * 4);
lblBussyHealine.Left = (ClientSize.Width - lblBussyHealine.Width) / 2;
lblBussyHealine.Top = (ClientSize.Height - lblBussyHealine.Height) / 2 - (lblBussyHealine.Height * 2);
}));
}
else
{
ProgressTotal = null;
ProgressCurrent = null;
TryInvoke(new Action(() => { pnlBussy.Visible = false; timProgress.Enabled = false; lblAction.Text = action; lblProgress.Text = ""; }));
}
}
catch (Exception ex)
{
_logger.Error(ex, $"error at setBusy(val={val},action={action}");
}
}
private void setProgress(String text, Int32 total = 0, Int32 current = 0)
{
try
{
ProgressTotal = total;
ProgressCurrent = current;
TryInvoke(new Action(() => { lblProgress.Text = $@"{text} ({current}/{total})"; }));
}
catch (Exception ex)
{
_logger.Error(ex, $"error at setProgress(text={text},total={total},current={current}");
}
}
private Boolean AvoidDisposedTimer(Object sender)
{
if (Disposing || Disposing)
{
if (sender is System.Windows.Forms.Timer)
{
((System.Windows.Forms.Timer)(sender)).Enabled = false;
((System.Windows.Forms.Timer)(sender)).Dispose();
}
return true;
}
return false;
}
private void timProgress_Tick(Object sender, EventArgs e)
{
try
{
CtlBatchStateMachine();
if (AvoidDisposedTimer(sender))
{
return;
}
if (IsBusy)
{
if (ProgressTotal.HasValue && ProgressCurrent.HasValue && !ProgressTotal.Value.Equals(0) && !ProgressCurrent.Value.Equals(0))
{
try
{
TryInvoke(new Action(() =>
{
probarBusy.Value = (Int32)Math.Round(ProgressCurrent.Value /
(Double)ProgressTotal.Value * 100, 0);
}));
}
catch (Exception exception)
{
_logger.Error(exception, @"Timer routine progress");
}
}
else
{
var current = probarBusy.Value;
if (current + 1 > 100)
{
current = 0;
}
TryInvoke(new Action(() => { probarBusy.Value = current + 1; }));
}
}
}
catch (Exception ex)
{
_logger.Error(ex, "timProgress_Tick");
}
}
#endregion
#region refresh
private void RefreshTimerWatch_Tick(Object sender, EventArgs e)
{
try
{
if (AvoidDisposedTimer(sender))
{
return;
}
if (currentMode == Mode.AutoRefresh)
{
TryInvoke(new Action(() => { pgbUpdate.Visible = true; }));
if (stopWatch != null && stopWatch.IsRunning)
{
var progress = (Int32)(stopWatch.ElapsedMilliseconds);
progress = progress > pgbUpdate.Maximum ? pgbUpdate.Maximum : progress;
TryInvoke(new Action(() => { pgbUpdate.Value = progress; }));
}
}
else
{
TryInvoke(new Action(() => { pgbUpdate.Visible = false; }));
}
}
catch (Exception ex)
{
_logger.Error(ex, "error at RefreshTimerWatch_Tick()");
}
}
private void RefreshTimer_Tick(Object sender, EventArgs e)
{
//try
//{
// if (this.AvoidDisposedTimer(sender))
// return;
// this.UpdateBatch();
//}
//catch (Exception ex)
//{
// _logger.Error(ex, $"error at RefreshTimer_Tick()");
//}
}
private void updateTotalProgress(Double refTestTime)
{
try
{
if (PredictedTs > 0 && refTestTime > 0)
{
var timeLeft = PredictedTs - refTestTime;
TryInvoke(new Action(() =>
{
lblEndTime.Text = DateTime.Now.AddSeconds(timeLeft).ToString("HH:mm:ss");
pgbEndTime.Value = (Int32)refTestTime >= pgbEndTime.Maximum ? pgbEndTime.Maximum : (Int32)refTestTime;
pnlEndTime.Visible = true;
}));
}
}
catch (Exception ex)
{
_logger.Error(ex, $"error at updateTotalProgress(refTestTime={refTestTime}");
}
}
#endregion
#region infoLables
private void InitLabelValueCollection()
{
AddInfoLabels("MeterDn", "MID", 0, MeterDn);
AddInfoLabels("PulseValence", "Impulswertigkeit", 1, doubleToStringFormat(RefPulseValence));
AddInfoLabels("PredictedQFlow", "Q soll[m³/ h]", 2, doubleToStringFormat(PredictedQFlow, 6));
AddInfoLabels("PredictedTs", "T soll[s]", 3, doubleToStringFormat(PredictedTs, 1));
AddInfoLabels("RefError", "RZ Fehler[%]", 4, doubleToStringFormat(RefError, 3));
AddInfoLabels("CurrentPulse", "Impulse", 6, CurrentPulse.ToString());
AddInfoLabels("CurrentRefVolume", "RZ Volumen m³", 7, doubleToStringFormat(CurrentRefVolume, 6));
AddInfoLabels("RemainingPulse", "Verbleib.Imp", 8, RemainingPulse.ToString());
AddInfoLabels("Period", "Periodendauer", 9, Period);
AddInfoLabels("RefFlow", "Ref Q", 11, doubleToStringFormat(RefFlowrate, 6));
AddInfoLabels("RefFlowUncorrected", "unkor. Ref Q", 12, doubleToStringFormat(RefFlowUncorrected, 6));
}
private void AddInfoLabels(String name, String text, Int32 index, String value)
{
var tmpLblText = new Label();
var tmpLblValue = new Label();
grbInfo.Controls.Add(tmpLblText);
grbInfo.Controls.Add(tmpLblValue);
tmpLblText.AutoSize = true;
tmpLblText.Location = new Point(LblPositionLeft, LblPositionTop * (index + 1));
tmpLblText.Name = $"lblInfo{name}text";
tmpLblText.Size = new Size(LblPositionSize, LblPositionHeight);
tmpLblText.TabIndex = index;
tmpLblText.Text = text;
tmpLblValue.AutoSize = true;
tmpLblValue.Location = new Point(LblPositionLeft + LblPositionSize + LblPositionSpace,
LblPositionTop * (index + 1));
tmpLblValue.Name = $"lblInfo{name}value";
tmpLblValue.Size = new Size(LblPositionSize, LblPositionHeight);
tmpLblValue.TabIndex = index + 1;
tmpLblValue.Text = value;
labelValueCollection.Add(name, new Tuple