laatzen/Common/CordonelPreadjustmentUi/MeterStateControl.cs
2025-04-11 08:44:21 +02:00

609 lines
18 KiB
C#

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using CordonelPreadjustmentUi;
using CordonelPreadjustmentUi.Processes.Itinerary;
using Newtonsoft.Json;
using Xylem.Common.Hardware.WaterMeter.Genesis.Registers;
using Xylem.Common.Logic.SoftwareAccessHelper;
using Xylem.Common.Ui.CordonelPreadjustmentUi.Helper.Extensions;
namespace Xylem.Common.Ui.CordonelPreadjustmentUi
{
public partial class MeterStateControl : UserControl
{
public EventHandler OnRequestDetails;
public EventHandler<EventArgsDecimal> OnTempretureChangedHandler;
public EventHandler OnWatcherFailed;
private Int32 WatcherInvervalS = 2;
private decimal? minTemp;
private decimal? maxTemp;
private decimal? currentTemp;
private bool watcherFailed = false;
private decimal? watcherMinTemp;
private decimal? watcherMaxTemp;
private decimal? watcherMaxDeviation;
public void SetWatcher(decimal? MinTemp, decimal? MaxTemp, decimal? MaxDeviation)
{
watcherMinTemp = MinTemp;
watcherMaxTemp = MaxTemp;
watcherMaxDeviation = MaxDeviation;
}
public MeterStateControl(string Text)
{
InitializeComponent();
IsEnabled = cB_ZeroFlowCal_EnableMeter.Checked;
Failed = false;
setImage(Xylem.Common.Ui.CordonelPreadjustmentUi.Properties.Resources.NormalImage);
Slot = -1;
setSerialNumbersVisible(false);
setTempinputVisible(false);
nUD_TempField_Celsius.ValueChanged += delegate (Object sender, EventArgs args)
{
if (sender is NumericUpDown)
{
changedTempreture(((NumericUpDown)sender).Value);
}
};
l_ZeroFlowCal_Meter.Text = Text;
}
public MeterStateControl(int slot)
{
InitializeComponent();
IsEnabled = cB_ZeroFlowCal_EnableMeter.Checked;
Failed = false;
setImage(Xylem.Common.Ui.CordonelPreadjustmentUi.Properties.Resources.NormalImage);
Slot = slot;
setSerialNumbersVisible(false);
setTempinputVisible(false);
nUD_TempField_Celsius.ValueChanged += delegate (Object sender, EventArgs args)
{
if (sender is NumericUpDown)
{
changedTempreture(((NumericUpDown)sender).Value);
}
};
l_ZeroFlowCal_Meter.Text = $"METER {slot}";
}
private void watcherIsFailed()
{
OnWatcherFailed?.Invoke(this, EventArgs.Empty);
watcherFailed = true;
Failed = true;
}
private void RunWatchActions()
{
try
{
var cRecords = Meter.CurrentRecords.ToList();
Log($"cRecords.Count={cRecords.Count}");
if (cRecords != null && cRecords.Any())
{
decimal checkTempMeter = 0;
if (MeterTempMode == TempMode.CalcTof)
{
//
var sumTof = 0.0;
var countTof = 0;
foreach (var tofItem in cRecords.Where(c => c.Channel == 2))
{
if (tofItem.Channel == 2)
{
Log($"TotalTimeOfFlightS;{(tofItem.TotalTimeOfFlightS * 1000).ToString()}");
Log($"RAWTEMP;{interPol(TempFromTofLUT, (tofItem.TotalTimeOfFlightS * 1000))}");
sumTof = (tofItem.TotalTimeOfFlightS * 1000) + sumTof;
countTof = countTof + 1;
}
}
var x = (sumTof / countTof) / 1000;
Log($"avgTof;{x}({sumTof}/{countTof})");
checkTempMeter = interPol(TempFromTofLUT, x);
Meter.CurrentRecords.Clear();
}
else
{
checkTempMeter = (decimal)cRecords.Last().TemperatureDegC;
}
currentTemp = checkTempMeter;
Log($"{DateTime.UtcNow};currentTemp;{currentTemp};°C");
if (!minTemp.HasValue || currentTemp < minTemp.Value)
{
minTemp = currentTemp;
}
if (!maxTemp.HasValue || currentTemp > maxTemp.Value)
{
maxTemp = currentTemp;
}
SetTemperature(currentTemp.Value, false);
if (watcherMinTemp.HasValue && minTemp < watcherMinTemp.Value)
{
watcherIsFailed();
}
if (watcherMaxTemp.HasValue && maxTemp > watcherMaxTemp.Value)
{
watcherIsFailed();
}
if (watcherMaxDeviation.HasValue && Math.Abs(maxTemp.Value - minTemp.Value) > watcherMaxDeviation.Value)
{
watcherIsFailed();
}
}
else
{
Log($"temp NA");
}
}
catch (Exception ex)
{
Log($"temp NA - {ex.Message}");
}
}
private static decimal interPol(List<Tuple<double, double>> points, double x)
{
var x1 = 0.000;
var y1 = 0.000;
var x2 = 0.000;
var y2 = 0.000;
decimal checkTempMeter;
try
{
if ((x <= points[0].Item1) && (x >= points.Last().Item1))
{
var i = 0;
foreach (var val in points)
{
if (points[i].Item1 <= x)
{
x1 = points[i - 1].Item1;
y1 = points[i - 1].Item2;
x2 = points[i].Item1;
y2 = points[i].Item2;
break;
}
i = i + 1;
}
checkTempMeter = (decimal)((y2 - y1) / (x2 - x1) * (x - x1) + y1);
}
else
{
checkTempMeter = 1;
}
return checkTempMeter;
}
catch (Exception ex)
{
return 2;
}
}
public void setImage(Bitmap img)
{
pB_Meter.Image = img;
}
private StringBuilder logSb = new StringBuilder();
public bool EnableOpening { get; internal set; }
public bool IsEnabled { get; internal set; }
public bool IsDisabeldForRetry { get; private set; }
public bool Ok { get; internal set; }
public bool SetToUnknownStatus { get; internal set; }
public int Slot { get; internal set; }
public ZeroFlowGenesisMeter Meter { get; internal set; }
public bool LoginFailed { get; internal set; }
public string OverridePassword { get; internal set; }
internal decimal GetTemperature()
{
return nUD_TempField_Celsius.Value;
}
public bool Failed { get; internal set; }
private string idText = "";
public string Id
{
get { return idText; }
internal set
{
idText = value;
UpdateLbl(l_PcbId, idText);
setSerialNumbersVisible(!string.IsNullOrEmpty(idText));
}
}
private string srn = "";
public string Srn
{
get { return srn; }
internal set
{
srn = value;
UpdateLbl(L_Srnr, srn);
setSerialNumbersVisible(!string.IsNullOrEmpty(Srn));
}
}
public String OverridePcbId { get; internal set; }
private void setSerialNumbersVisible(bool vis)
{
if (vis && !IsEnabled)
{
vis = false;
}
UpdateVisControl(l_PcbId, vis);
UpdateVisControl(L_Srnr, vis);
}
private void setTempinputVisible(bool vis)
{
UpdateVisControl(l_TempField_Celsius, vis);
UpdateVisControl(nUD_TempField_Celsius, vis);
UpdateEnableControl(nUD_TempField_Celsius, vis);
}
internal void StopTempWatch()
{
watchActiv = false;
}
public class CordonelTempLut
{
public int Id { get; set; }
public int PcbId { get; set; }
public double RefTempC { get; set; }
public double AvgTof { get; set; }
public bool Active { get; set; }
}
public TempMode MeterTempMode;
private List<Tuple<double, double>> TempFromTofLUT;
internal void StartTempWatch(TempMode tempMode = TempMode.Hand)
{
try
{
Meter.WriteLog($"StartTempWatch with {tempMode}");
Meter.logAmpTest = true;
if (tempMode == TempMode.CalcTof)
{
TempFromTofLUT = new List<Tuple<double, double>>();
var pcbid = "";
if (OverridePcbId != null)
{
pcbid = OverridePcbId;
}
else
{
pcbid = Meter.GetPcbId();
}
try
{
//if (Meter.Slot == 11)
//{
// pcbid = "193400024";
// OverridePassword = "10C16DF46E6C";
// Meter.WriteLog($"Fake pcbid {pcbid}");
//}
//else if (Meter.Slot == 12)
//{
// pcbid = "193400261";
// OverridePassword = "BF8AC70AB27E";
// Meter.WriteLog($"Fake pcbid {pcbid}");
//}
Meter.Login();
Meter.WriteRegister(Register.Genesisflow.TriggerIdle, 0);
Meter.WriteRegister(Register.Genesisflow.LedMode, 6);
Meter.WriteRegister(Register.Genesisflow.SampleRate, 10);
var resp = LocalWebRequest.GetRequest($"http://10.49.40.25/MeterProcessState/api/TempFlange/GetLut?PcbId={pcbid}", 50000);
var cordonelTempLut = JsonConvert.DeserializeObject<List<CordonelTempLut>>(resp);
TempFromTofLUT = new List<Tuple<double, double>>();
foreach (var item in cordonelTempLut.OrderBy(a => a.RefTempC))
{
TempFromTofLUT.Add(new Tuple<double, double>(item.AvgTof, item.RefTempC));
}
var sb = new StringBuilder();
foreach (var t in TempFromTofLUT)
{
sb.Append("Tof:");
sb.Append(t.Item1);
sb.Append("=Temp:");
sb.Append(t.Item2);
sb.Append(",");
}
Meter.WriteLog($"Load LUT { sb.ToString() } for meter {pcbid}");
}
catch (Exception ex)
{
Meter.WriteLog($"StartTempWatch with LUT faild for meter {pcbid} with ex{ex.Message}");
}
}
watchActiv = true;
MeterTempMode = tempMode;
}
catch (Exception ex)
{
Log("StartTempWatch" + ex.Message);
}
}
public enum TempMode
{
Hand,
Meter,
CalcTof
}
private void WatchTmrOnTick(Object sender, EventArgs e)
{
//var t = new Task(() => { RunWatchActions(); });
//t.Start();
}
internal void DisableTemperatureinput(bool v)
{
UpdateEnableControl(nUD_TempField_Celsius, !v);
}
public void SetTemperature(decimal temp, bool setControls = true)
{
if (nUD_TempField_Celsius.InvokeRequired)
{
Invoke((Action<decimal, bool>)SetTemperature, temp, setControls);
return;
}
if (setControls)
{
if (!nUD_TempField_Celsius.Visible)
{
setTempinputVisible(true);
}
}
nUD_TempField_Celsius.Value = temp;
}
public void changedTempreture(decimal newValue)
{
OnTempretureChangedHandler?.Invoke(this, new EventArgsDecimal(newValue));
}
private void UpdateLbl(Label lbl, string text)
{
if (lbl.InvokeRequired)
{
Invoke((Action<Label, string>)UpdateLbl, lbl, text);
return;
}
lbl.Text = text;
}
private void UpdateVisControl(Control lbl, bool vis)
{
if (lbl.InvokeRequired)
{
Invoke((Action<Control, bool>)UpdateVisControl, lbl, vis);
return;
}
lbl.Visible = vis;
}
private void UpdateEnableControl(Control ctl, bool enab)
{
if (ctl.InvokeRequired)
{
Invoke((Action<Control, bool>)UpdateEnableControl, ctl, enab);
return;
}
if (ctl is NumericUpDown)
{
((NumericUpDown)ctl).ReadOnly = !enab;
}
ctl.Enabled = enab;
}
internal void Log(string v)
{
logSb?.AppendLine(v);
Meter?.WriteLog(v);
}
public string GetLog()
{
if (logSb == null)
{
return "";
}
return logSb.ToString();
}
private void cB_ZeroFlowCal_EnableMeter_CheckedChanged(object sender, EventArgs e)
{
IsEnabled = ((CheckBox)sender).Checked;
}
internal void SetChecked(bool v)
{
if (cB_ZeroFlowCal_EnableMeter.InvokeRequired)
{
Invoke((Action<bool>)SetChecked, v);
return;
}
cB_ZeroFlowCal_EnableMeter.Checked = v;
}
internal void SetUi(bool v = false)
{
if (p_ZeroFlowCal_Meter.InvokeRequired)
{
Invoke((Action<bool>)SetUi, true);
return;
}
if (SetToUnknownStatus || (!IsEnabled && !Failed))
{
p_ZeroFlowCal_Meter.BackColor = Color.Cornsilk;
return;
}
if (Ok && !Failed)
{
p_ZeroFlowCal_Meter.BackColor = Color.LightGreen;
//pB_Meter.Image = GenesisZeroFlow._GenesisZeroFlow.pB_AvailableImages.ErrorImage;
}
else
{
p_ZeroFlowCal_Meter.BackColor = Color.LightPink;
}
}
private void numericUpDown1_EnabledChanged(object sender, EventArgs e)
{
}
private void timBlink_Tick(object sender, EventArgs e)
{
}
private bool watchActiv = false;
private Color failedBackgroundColor = Color.OrangeRed;
private void timWatch_Tick(object sender, EventArgs e)
{
try
{
if (IsEnabled && watchActiv)
{
var t = new Task(() => { RunWatchActions(); });
t.Start();
if (watcherFailed)
{
var tmp = p_ZeroFlowCal_Meter.BackColor;
p_ZeroFlowCal_Meter.BackColor = failedBackgroundColor;
failedBackgroundColor = tmp;
}
}
else
{
if (watchActiv)
{
Log("watcher activ but ctl is disabled!");
}
}
}
catch (Exception ex)
{
Log(ex.Message);
}
}
internal void SetDisableForRetry()
{
IsEnabled = false;
IsDisabeldForRetry = true;
}
internal void SetEnableAfterRetry()
{
if (IsDisabeldForRetry)
{
IsEnabled = true;
}
}
internal void EnabeldBoxEnabel(bool v)
{
UpdateEnableControl(cB_ZeroFlowCal_EnableMeter, v);
}
private void pB_Meter_Click(object sender, EventArgs e)
{
OnRequestDetails?.Invoke(this, e);
}
private void l_TempField_Celsius_Click(object sender, EventArgs e)
{
Log("Click");
}
}
}