Files
laatzen/Common/Ui/GenesisToolBox/FrmTempMeter.cs
T

882 lines
29 KiB
C#

namespace Xylem.Common.Ui.GenesisToolBox
{
using global::CordonelPreadjustmentUi;
using Newtonsoft.Json;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.IO.Pipes;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using TempFlansh;
using Xylem.Common.Hardware.WaterMeter.Genesis.DataPackages;
using Xylem.Common.Hardware.WaterMeter.Genesis.DataPackages.MeasurementRecords;
using Xylem.Common.Hardware.WaterMeter.Genesis.Registers;
using Xylem.Common.Hardware.WaterMeter.WaterMeterCore;
using Xylem.Common.Logic.SoftwareAccessHelper;
using Xylem.Common.Ui.GenesisToolBox.Infrastructure;
public partial class FrmTempMeter : Form, ITempMeterForm
{
private ToolStripLabel slotsLabel;
private ToolStripComboBox slotsList;
private ToolStripLabel pcbidLabel;
private ToolStripTextBox pcbidTextBox;
private ToolStripButton connectBtn;
private ToolStripButton disconnectBtn;
private ToolStripButton testBtn;
private ProgrammState programmState;
private ZeroFlowGenesisMeter currentGenesis;
private MeterBatch meterBatch;
private Boolean lutIsMissing;
private List<RefTempRange> reftempRangeReq;
private List<CordonelTempLut> cordonelTempLut;
public FrmTempMeter()
{
this.InitializeComponent();
this.InitializeContent();
this.reftempRangeReq = new List<RefTempRange>()
{
new RefTempRange() { Min = 7, Max= 9 },
new RefTempRange() { Min = 13,Max = 15 },
new RefTempRange() { Min = 16,Max = 18 },
new RefTempRange() { Min = 19,Max = 20 },
new RefTempRange() { Min = 20,Max = 22 },
new RefTempRange() { Min = 23,Max = 25 },
new RefTempRange() { Min = 26,Max = 28 },
new RefTempRange() { Min = 28,Max = 30 },
new RefTempRange() { Min = 33,Max = 36 },
};
}
private void BtnConnect_Click(Object sender, EventArgs e)
{
this.Connect();
}
private void Connect()
{
try
{
if (!int.TryParse($"{this.slotsList.SelectedItem}", out var slotNr))
{
return;
}
//var drive = 1;
currentGenesis?.DisposeMeter();
//dispose old meter
meterBatch = new MeterBatch();
currentGenesis = null;
Thread.Sleep(200);
//assign new meter and assign meter to FW update file if this exists
currentGenesis = new ZeroFlowGenesisMeter(slotNr, 3, false);
//_currentGenesis.SetupFromConfigFile(slotNr);
meterBatch.AddMeter(currentGenesis);
Task.Factory.StartNew(() =>
{
meterBatch.MetersLogin();
if (!currentGenesis.IsLoggedOn)
{
Thread.Sleep(2000);
meterBatch.MetersLogin();
}
if (!currentGenesis.IsLoggedOn)
{
SetEnabled(ProgrammState.Start);
return;
}
var a = GetLutsText(currentGenesis.PcbId);
currentGenesis.InitMeasurement();
Invoke(new Action(() =>
{
txtLuts.Text = a;
if (lutIsMissing)
{
txtLuts.BackColor = Color.IndianRed;
}
else
{
txtLuts.BackColor = Color.LightGreen;
}
this.pcbidTextBox.Text = currentGenesis.PcbId;
this.SetEnabled(ProgrammState.Connected);
}));
});
}
catch (Exception ex)
{
txtLuts.Text = "-";
MessageBox.Show(ex.Message);
SetEnabled(ProgrammState.Start);
}
}
private void btnRefreshLut_Click(Object sender, EventArgs e)
{
if (!string.IsNullOrEmpty(currentGenesis?.PcbId))
{
Task.Factory.StartNew(() =>
{
var a = GetLutsText(currentGenesis.PcbId);
Invoke(new Action(() =>
{
txtLuts.Text = a;
if (lutIsMissing)
{
txtLuts.BackColor = Color.IndianRed;
}
else
{
txtLuts.BackColor = Color.LightGreen;
}
}));
});
}
else
{
txtLuts.Text = "-";
}
}
private String GetLutsText(String PcbId)
{
var ret = new StringBuilder();
var resp = LocalWebRequest.GetRequest($"http://10.49.40.25/MeterProcessState/api/TempFlange/GetLut?PcbId={PcbId}");
ret.AppendLine($"Ref Temp C°\t|\t AvgTof");
var CurrentReqRequierd = new List<RefTempRange>();
CurrentReqRequierd.AddRange(reftempRangeReq);
try
{
cordonelTempLut = JsonConvert.DeserializeObject<List<CordonelTempLut>>(resp);
foreach (var item in cordonelTempLut.OrderBy(a => a.RefTempC))
{
CurrentReqRequierd.RemoveAll(rem => item.RefTempC >= rem.Min && item.RefTempC <= rem.Max);
ret.AppendLine($"{item.RefTempC.ToString("n8")}\t|\t{item.AvgTof}");
}
}
catch (Exception)
{
ret.AppendLine($"No entrys");
}
lutIsMissing = false;
foreach (var item in CurrentReqRequierd)
{
lutIsMissing = true;
ret.AppendLine($"{item.Min}-{item.Max}\t|\t Missing");
}
return ret.ToString();
}
private DateTimeOffset start;
private void BtnStartRecord_Click(Object sender, EventArgs e)
{
automatic = false;
start = DateTimeOffset.Now;
currentGenesis.StartRecordData();
currentGenesis.WriteRegister<Byte>(Register.Genesisflow.SampleRate, 16, checkRegister: true);
SetEnabled(ProgrammState.RecordRuning);
timer2.Enabled = true;
}
private void BtnStopRecord_Click(Object sender, EventArgs e)
{
timer2.Enabled = false;
OutputAvgTof(true);
currentGenesis.WriteRegister<Byte>(Register.Genesisflow.SampleRate, 0, checkRegister: true);
SetEnabled(ProgrammState.RecordStoped);
}
private void btnAddLut_Click(Object sender, EventArgs e)
{
var req = LocalWebRequest.PostRequestAsync($"http://10.49.40.25/MeterProcessState/api/TempFlange/AddLut?PcbId={currentGenesis.PcbId}&RefTempC={nudRef.Value.ToString().Replace(",", ".")}&AvgTof={lblAvgDutTof.Text.Replace(",", ".")}");
SetEnabled(ProgrammState.Connected);
}
TempHelper helper;
private void btnCheck_Click(Object sender, EventArgs e)
{
if (btnCheck.Text == "Start Check")
{
short port = 0;
if (short.TryParse(txtComport.Text, out port))
{
helper = new TempHelper();
TempHelper.UniversalOpenCom((port), 4800, 8, 0, 0);
}
currentGenesis.StartRecordData();
timer1.Enabled = true;
btnCheck.Text = "Stop Check";
}
else
{
currentGenesis.StopRecordData();
timer1.Enabled = false;
btnCheck.Text = "Start Check";
}
}
private static Decimal interPol(List<CordonelTempLut> points, Double x)
{
var x1 = 0.000;
var y1 = 0.000;
var x2 = 0.000;
var y2 = 0.000;
Decimal checkTempMeter;
if ((x <= points[0].AvgTof) && (x >= points.Last().AvgTof))
{
var i = 0;
foreach (var val in points)
{
if (points[i].AvgTof <= x)
{
x1 = points[i - 1].AvgTof;
y1 = points[i - 1].RefTempC;
x2 = points[i].AvgTof;
y2 = points[i].RefTempC;
break;
}
i = i + 1;
}
checkTempMeter = (Decimal)((y2 - y1) / (x2 - x1) * (x - x1) + y1);
}
else
{
checkTempMeter = 1;
}
return checkTempMeter;
}
private void timer1_Tick(Object sender, EventArgs e)
{
try
{
var cRecords = currentGenesis.CurrentRecords.ToList();
if (cRecords != null && cRecords.Any())
{
Decimal checkTempMeter = 0;
var sumTof = 0.0;
var countTof = 0;
foreach (var tofItem in cRecords.Where(c => c.Channel == 2))
{
if (tofItem.Channel == 2)
{
sumTof = tofItem.TotalTimeOfFlightS * 1000 + sumTof;
countTof = countTof + 1;
}
}
var x = sumTof / countTof / 1000;
checkTempMeter = interPol(cordonelTempLut, x);
var a = new CalibrationRecord();
while (currentGenesis.CurrentRecords.TryDequeue(out a))
{
// do nothing
}
var refTemp = helper.ReadCurrentDisplayValue().ToString();
File.AppendAllLines("Check.txt", new List<string> { $"{currentGenesis.PcbId },{checkTempMeter.ToString()},{refTemp.ToString()} " });
lblCheck.Text = "DUT:" + checkTempMeter.ToString() + "vs Ref:" + refTemp.ToString();
//
}
else
{
lblCheck.Text = $"temp NA";
}
}
catch (Exception ex)
{
lblCheck.Text = $"temp NA - {ex.Message}";
}
}
private void timer2_Tick(Object sender, EventArgs e)
{
if (programmState == ProgrammState.RecordRuning)
{
if (automatic)
{
}
else
{
OutputAvgTof();
}
}
}
private double OutputAvgTof(Boolean stop = false)
{
// TODO: Prüfung der TOF signal ???
var avgToF = default(double);
try
{
StringBuilder cTofs = new StringBuilder();
var listOfRec = currentGenesis.CurrentRecords.Where(s => s.Channel == 2).ToList();
if (stop)
{
currentGenesis.StopRecordData();
}
var list = listOfRec.Select(s => new { ToF = s.TotalTimeOfFlightS * 1000, s.Channel });
foreach (var item in list.OrderBy(o => o.Channel))
{
cTofs.Append(item.Channel);
cTofs.Append(":");
cTofs.AppendLine((item.ToF / 1000).ToString());
}
avgToF = list.Average(s => s.ToF) / 1000;
lblAvgDutTof.Text = avgToF.ToString();
txtCurrentTofs.Text = cTofs.ToString();
lblLines.Text = list.Count().ToString();
lblDuration.Text = $"{(DateTimeOffset.Now - start).TotalSeconds}S";
}
catch (Exception ex)
{
txtCurrentTofs.Text = ex.Message;
}
return avgToF;
}
private class TempTime
{
public TempTime(Double temp)
{
date = DateTime.UtcNow;
Temp = temp;
}
public TempTime(String temp)
{
Double tmp = double.MinValue;
if (double.TryParse(temp, out tmp))
{
date = DateTime.UtcNow;
Temp = tmp;
}
}
public DateTime date;
public Double Temp;
}
private class ToFTime
{
public ToFTime(Double temp, DateTimeOffset date)
{
Date = date.ToUniversalTime().DateTime;
Tof = temp;
}
public DateTime Date;
public Double Tof;
}
private ConcurrentQueue<TempTofCalc> listTempTime = new ConcurrentQueue<TempTofCalc>();
private void RunTemConnection()
{
using (var pipeClient = new NamedPipeClientStream(".", "TempPipe", PipeDirection.In))
{
// Connect to the pipe or wait until the pipe is available.
//Console.Write("Attempting to connect to pipe...");
pipeClient.Connect();
//Console.WriteLine("Connected to pipe.");
//Console.WriteLine("There are currently {0} pipe server instances open.",
// pipeClient.NumberOfServerInstances);
using (var sr = new StreamReader(pipeClient))
{
string temp;
while ((temp = sr.ReadLine()) != null)
{
CalibrationRecord record;
Double avgTof = 0;
Double reftemp = 0;
if (double.TryParse(temp, out reftemp))
{
avgTof = 0;
var i = 0;
while (currentGenesis.CurrentRecords.TryDequeue(out record))
{
if (record.Channel == 2)
{
avgTof = avgTof + record.TotalTimeOfFlightS;
i = 1 + i;
}
}
if (i > 0)
{
avgTof = avgTof / i;
if (!double.IsNaN(avgTof))
{
listTempTime.Enqueue(new TempTofCalc() { RefDate = DateTime.Now, RefTemp = reftemp, Tof = avgTof });
if (avgTof.ToString().Contains("a"))
{
}
}
}
}
}
}
}
}
private List<ToFTime> toFTimes = new List<ToFTime>();
private void MergeToAutoFile()
{
List<TempTofCalc> itimestowri = new List<TempTofCalc>();
TempTofCalc lItem;
while (listTempTime.TryDequeue(out lItem))
{
itimestowri.Add(lItem);
}
var fiName = $"{currentGenesis.PcbId}_{start.ToString("yyyy_MM_dd_HH-mm-ss")}.TempTof";
String jsonData = JsonConvert.SerializeObject(itimestowri.ToList());
jsonData = jsonData.TrimStart('[').TrimEnd(']');
if (File.Exists(fiName))
{
jsonData = $",{jsonData}";
}
File.AppendAllText(fiName, jsonData);
}
//private Int32 PlateauMinLengt = 15;
//private Double TempConstMarker = 0.01;
private List<TempTofCalc> toGrid = new List<TempTofCalc>();
private void timer3_Tick(Object sender, EventArgs e)
{
MergeToAutoFile();
}
private Double generateTof(Random r, Double temp)
{
var tmp = r.Next(1, 5);
var retrn = temp / 9000 - Math.Pow(temp, 1.6) / 100_000;
return retrn - (retrn * tmp / 100 + Math.Pow(tmp, 1.6) / 100_000);
}
private void TestBtn_Click(Object sender, EventArgs e)
{
List<TempTofCalc> refTempss = new List<TempTofCalc>();
var sDate = DateTime.UtcNow;
Double refTemp = 5.0;
for (Int32 i = 0; i <= 5; i++)
{
var needUp = 2.5;
var rramp = new Random();
var rtof = new Random();
//plateau
while (needUp >= 0)
{
var temp = rramp.NextDouble() / (needUp * 100); // +0
needUp = needUp - temp;
refTemp = refTemp + temp;
refTempss.Add(new TempTofCalc() { RefDate = sDate.AddSeconds(refTempss.Count), RefTemp = refTemp, Tof = generateTof(rtof, refTemp) });
}
var ra = new Random();
var tillI = ra.Next(150, 4000); // +0
var r = new Random(tillI);
for (Int32 platI = 0; platI < tillI; platI++)
{
var temp = r.NextDouble() / 5;
refTempss.Add(new TempTofCalc() { RefDate = sDate.AddSeconds(refTempss.Count), RefTemp = refTemp + temp, Tof = generateTof(rtof, refTemp) });
}
}
var jsonData = JsonConvert.SerializeObject(refTempss);
File.AppendAllText($"124563_{start.ToString("yyyy_MM_dd_HH-mm-ss")}.TempTof", jsonData);
}
private void InitializeContent()
{
this.mainMenuStrip.Padding = new Padding(5);
var menuFont = this.mainMenuStrip.Font;
var fontBold = new Font(menuFont.FontFamily, menuFont.Size, FontStyle.Bold);
this.slotsLabel = new ToolStripLabel
{
Text = "Slot: ",
AutoSize = true,
Font = fontBold,
ForeColor = Color.Gray
};
this.slotsList = new ToolStripComboBox
{
Items = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 },
SelectedIndex = 0,
AutoSize = true,
FlatStyle = FlatStyle.System,
DropDownStyle = ComboBoxStyle.DropDownList,
};
this.pcbidLabel = new ToolStripLabel
{
Text = "Pcb Id: ",
AutoSize = true,
TextAlign = ContentAlignment.MiddleRight,
Font = fontBold,
Margin = new Padding(10, 0, 0, 0),
ForeColor = Color.Gray
};
this.pcbidTextBox = new ToolStripTextBox
{
Text = "n/a",
AutoSize = true,
TextAlign = ContentAlignment.MiddleRight,
BorderStyle = BorderStyle.None,
ReadOnly = true,
BackColor = this.slotsList.BackColor
};
this.connectBtn = new ToolStripButton
{
Text = "Connect",
AutoSize = true,
Font = fontBold,
TextAlign = ContentAlignment.MiddleCenter,
Margin = new Padding(10, 0, 0, 0),
Padding = new Padding(10, 0, 10, 0),
BackColor = Color.LightGray
};
this.connectBtn.Click += this.BtnConnect_Click;
this.disconnectBtn = new ToolStripButton
{
Text = "Disconnect",
AutoSize = true,
Font = fontBold,
TextAlign = ContentAlignment.MiddleCenter,
Margin = new Padding(10, 0, 0, 0),
Padding = new Padding(10, 0, 10, 0),
BackColor = Color.LightGray
};
this.disconnectBtn.Click += this.BtnDisconnect_Click;
this.testBtn = new ToolStripButton
{
Text = "Test",
AutoSize = true,
Font = fontBold,
TextAlign = ContentAlignment.MiddleCenter,
Margin = new Padding(5, 0, 0, 0),
Padding = new Padding(10, 0, 10, 0),
BackColor = Color.LightGray
};
this.connectBtn.Click += this.TestBtn_Click;
this.mainMenuStrip.Items.Add(this.slotsLabel);
this.mainMenuStrip.Items.Add(this.slotsList);
this.mainMenuStrip.Items.Add(this.pcbidLabel);
this.mainMenuStrip.Items.Add(this.pcbidTextBox);
this.mainMenuStrip.Items.Add(this.connectBtn);
this.mainMenuStrip.Items.Add(this.disconnectBtn);
this.mainMenuStrip.Items.Add(this.testBtn);
this.automaticCalibrationTabControl.GotFocus += (Object sender, EventArgs e) =>
{
this.GMHPort.Text = Appsettings.GMHPort.ToString();
this.messurementStepMS.Text = Appsettings.MessurementStep.ToString();
this.messurementDauerMS.Text = Appsettings.MessurementDauer.ToString();
};
this.SetEnabled(ProgrammState.Start);
}
private void BtnDisconnect_Click(Object sender, EventArgs args)
{
try
{
this.currentGenesis.DisposeMeter();
}
catch (Exception e)
{
Console.WriteLine(e);
}
finally
{
this.currentGenesis = null;
}
this.Invoke(new Action(() =>
{
this.txtLuts.Text = string.Empty;
this.txtLuts.BackColor = Color.White;
this.pcbidTextBox.Text = "not connected";
this.SetEnabled(ProgrammState.Start);
}));
}
private void SetEnabled(ProgrammState state)
{
this.programmState = state;
switch (programmState)
{
case ProgrammState.Start:
this.btnStartRecord.Enabled = false;
this.btnStopRecord.Enabled = false;
this.btnAddLut.Enabled = false;
this.nudRef.Visible = false;
this.btnRefreshLut.Enabled = false;
this.disconnectBtn.Visible = false;
this.connectBtn.Visible = true;
break;
case ProgrammState.Connected:
this.btnStartRecord.Enabled = true;
this.btnStopRecord.Enabled = false;
this.btnAddLut.Enabled = false;
this.nudRef.Visible = false;
this.btnRefreshLut.Enabled = true;
this.disconnectBtn.Visible = true;
this.connectBtn.Visible = false;
break;
case ProgrammState.RecordRuning:
this.btnStartRecord.Enabled = false;
this.btnStopRecord.Enabled = true;
this.btnAddLut.Enabled = false;
this.nudRef.Visible = false;
this.btnRefreshLut.Enabled = true;
break;
case ProgrammState.RecordStoped:
this.btnStartRecord.Enabled = true;
this.btnStopRecord.Enabled = false;
this.btnAddLut.Enabled = true;
this.nudRef.Visible = true;
this.btnRefreshLut.Enabled = true;
break;
default:
break;
}
this.startAutomaticBtn.Enabled = true;
this.stopAutomaticBtn.Enabled = false;
}
private bool automatic = false;
private AutomaticTemperatureCalibration automaticCalibration;
private void StartAutomaticBtn_Clicked(object sender, EventArgs args)
{
if (this.currentGenesis is null)
{
MessageBox.Show(this, "Water meter not connected!", "Start aborted", MessageBoxButtons.OK);
return;
}
this.currentGenesis?.WriteRegister(Register.Genesisflow.SampleRate, (byte)16, checkRegister: true);
this.currentGenesis?.WriteRegister("GENESISFLOW_MaxValidDeltaToF", 4294967295, checkRegister: true);
this.currentGenesis?.WriteRegister("GENESISFLOW_MaxValidToF", 4294967295, checkRegister: true);
this.currentGenesis?.WriteRegister("GENESISFLOW_MinValidToF", (uint)0, checkRegister: true);
this.automatic = true;
this.start = DateTimeOffset.Now;
var pcbid = this.currentGenesis?.PcbId ?? "*********";
this.automaticCalibration = new AutomaticTemperatureCalibration(pcbid, this);
this.automaticCalibration.StartMessuring();
this.SetEnabled(ProgrammState.RecordRuning);
this.startAutomaticBtn.Enabled = false;
this.stopAutomaticBtn.Enabled = true;
}
private void StopAutomaticBtn_Clicked(object sender, EventArgs args)
{
this.automatic = false;
this.automaticCalibration.StopMessuring();
this.MergeToAutoFile();
this.SetEnabled(ProgrammState.RecordStoped);
this.startAutomaticBtn.Enabled = true;
this.stopAutomaticBtn.Enabled = false;
}
private const int TAKE_LINES = 50;
public void AddMessage(string message)
{
this.BeginInvoke(new Action(() =>
{
this.automaticContentBox.AppendText($"{message}{Environment.NewLine}");
var skipLines = this.automaticContentBox.Lines.Length - TAKE_LINES;
if (skipLines > 0)
{
this.automaticContentBox.Lines = this.automaticContentBox
.Lines
.Skip(skipLines)
.Take(TAKE_LINES)
.ToArray();
}
}));
}
private void SaveMessurement(double currentT, double meterTOF, DateTime timestamp)
{
// var pcbid = this.currentGenesis?.PcbId ?? "000000000";
// var temperature = currentT.ToString().Substring(0, 2);
// TODO: LocalWebRequest.PostRequestAsync(
// $"http://10.49.40.25/MeterProcessState/api/TempFlange/AddLut?PcbId={pcbid}&RefTempC={temperature}&AvgTof={meterTOF}&dt={timestamp}");
// File.AppendAllLines("_temp_luts.txt", new[] { $"{pcbid}\t{temperature:F2}\t{meterTOF}\t{timestamp}" });
// File.AppendAllText($"./messuremensts/{pcbid}.txt", $"{pcbid}\t{currentT:F2}\t{meterTOF:F16}\t{timestamp}{Environment.NewLine}");
}
protected override void OnClosed(EventArgs e)
{
base.OnClosed(e);
this.automatic = false;
if (this.automaticCalibration != null)
{
this.automaticCalibration.StopMessuring();
}
try
{
this.MergeToAutoFile();
}
catch (Exception)
{
// TODO:
}
}
public void StartRecording()
=> this.currentGenesis
?.StartRecordData();
public Double AvgTOF()
{
if (this.currentGenesis is null)
{
this.automaticCalibration.StopMessuring();
return double.MinValue;
}
return this.currentGenesis
.CurrentRecords
.Where(s => s.Channel == 2)
.Average(x => x.TotalTimeOfFlightS);
}
protected override void OnFormClosed(FormClosedEventArgs e)
=> this.BtnDisconnect_Click(default(object), EventArgs.Empty);
private void SaveSettingsBtn_Click(Object sender, EventArgs e)
{
if (short.TryParse($"{this.GMHPort.Text}", out short gmhPort))
{
Appsettings.GMHPort = gmhPort;
}
if (int.TryParse($"{this.messurementStepMS.Text}", out int msStep))
{
Appsettings.MessurementStep = msStep;
}
if (int.TryParse($"{this.messurementDauerMS.Text}", out int msDauer))
{
Appsettings.MessurementDauer = msDauer;
}
Appsettings.SaveSettings();
}
}
}