609 lines
18 KiB
C#
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");
|
|
}
|
|
}
|
|
}
|