302 lines
9.5 KiB
C#
302 lines
9.5 KiB
C#
namespace Xylem.Common.Ui.GenesisToolBox.Infrastructure
|
|
{
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Globalization;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Runtime.InteropServices;
|
|
using System.Timers;
|
|
|
|
using SystemThreadingThread = System.Threading.Thread;
|
|
|
|
internal interface ITempMeterForm
|
|
{
|
|
void AddMessage(string message);
|
|
|
|
double AvgTOF();
|
|
|
|
IAsyncResult BeginInvoke(Delegate @delegate);
|
|
|
|
void StartRecording();
|
|
}
|
|
|
|
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 DateTime? Timestamp { get; set; }
|
|
}
|
|
|
|
public class RefTempRange
|
|
{
|
|
public Double Min { get; set; }
|
|
|
|
public Double Max { get; set; }
|
|
}
|
|
|
|
public class TemperatureSource : IDisposable
|
|
{
|
|
[DllImport("GMH3x32E.dll")]
|
|
public static extern Int16 UniversalOpenCom(Int16 ini16COMPortNumber, UInt32 inui32BaudRate, Int16 inui16ConverterType, Int16 ini16Parity, Int16 ini16StoppBits);
|
|
|
|
[DllImport("GMH3x32E.dll")]
|
|
public static extern Int16 GMH_CloseCom();
|
|
|
|
[DllImport("GMH3x32E.dll")]
|
|
unsafe public static extern Int16 GMH_Transmit(Int16 ini16DeviceAddress, Int16 ini16TransmitCode, Int16* refi16ptrPriority, double* refdblptrFloatValue, Int32* refi32ptrIntegerValue);
|
|
|
|
public TemperatureSource() => UniversalOpenCom(Appsettings.GMHPort, 4800, 8, 0, 0);
|
|
|
|
public double GetTemperature()
|
|
{
|
|
var result = default(short);
|
|
var priority = default(short);
|
|
var temperature = default(double);
|
|
var value = default(int);
|
|
|
|
unsafe
|
|
{
|
|
result = GMH_Transmit(1, 0, &priority, &temperature, &value);
|
|
}
|
|
|
|
return temperature;
|
|
}
|
|
|
|
public void Dispose() => GMH_CloseCom();
|
|
}
|
|
|
|
partial class AutomaticTemperatureCalibration
|
|
{
|
|
private const string WORKING_DIR = @".\temperature_calibrations";
|
|
private const string MESSUREMENTS_FILE = @"_messurements.txt";
|
|
private const string AGGREGATIONS_FILE = @"_aggregations.txt";
|
|
private const NumberStyles ANY = NumberStyles.Any;
|
|
|
|
private readonly string pcbId;
|
|
private readonly string messurementsFile;
|
|
private readonly string aggregationsFile;
|
|
private readonly ITempMeterForm tempMeterForm;
|
|
private readonly CultureInfo en;
|
|
private readonly CultureInfo de;
|
|
|
|
private TemperatureSource temperatureSource;
|
|
private Timer longTimer;
|
|
private Timer shortTimer;
|
|
private bool messuring;
|
|
|
|
public AutomaticTemperatureCalibration(string pcbId, ITempMeterForm genesisMeter)
|
|
{
|
|
this.pcbId = pcbId;
|
|
this.tempMeterForm = genesisMeter;
|
|
this.messurementsFile = this.GetOrCreateMessurementsFile(this.pcbId);
|
|
this.aggregationsFile = this.GetOrCreateAggregationsFile(this.pcbId);
|
|
this.temperatureSource = new TemperatureSource();
|
|
this.en = new CultureInfo("en-US");
|
|
this.de = new CultureInfo("de-DE");
|
|
}
|
|
|
|
public void StartMessuring()
|
|
{
|
|
this.messuring = false;
|
|
this.temperatureSource = new TemperatureSource();
|
|
|
|
this.shortTimer = new Timer(Appsettings.MessurementStep)
|
|
{
|
|
Enabled = true,
|
|
AutoReset = true
|
|
};
|
|
this.shortTimer.Elapsed += this.ShortTimerElapsed;
|
|
this.shortTimer.Stop();
|
|
|
|
this.longTimer = new Timer(Appsettings.MessurementDauer)
|
|
{
|
|
Enabled = true,
|
|
AutoReset = true
|
|
};
|
|
this.longTimer.Elapsed += this.LongTimerElapsed;
|
|
this.LongTimerElapsed(null, null);
|
|
this.longTimer.Start();
|
|
|
|
File.AppendAllText(this.aggregationsFile, Environment.NewLine);
|
|
}
|
|
|
|
public void StopMessuring()
|
|
{
|
|
this.shortTimer?.Stop();
|
|
this.shortTimer?.Dispose();
|
|
this.shortTimer = null;
|
|
|
|
this.longTimer?.Stop();
|
|
this.longTimer?.Dispose();
|
|
this.longTimer = null;
|
|
|
|
this.temperatureSource?.Dispose();
|
|
this.temperatureSource = null;
|
|
}
|
|
|
|
private void LongTimerElapsed(Object sender, ElapsedEventArgs _)
|
|
{
|
|
this.messuring = !this.messuring;
|
|
|
|
SystemThreadingThread.Sleep(1_000);
|
|
|
|
if (this.messuring)
|
|
{
|
|
this.tempMeterForm.StartRecording();
|
|
this.shortTimer.Start();
|
|
}
|
|
else
|
|
{
|
|
this.shortTimer.Stop();
|
|
this.ParseMessurements();
|
|
}
|
|
}
|
|
|
|
private void ShortTimerElapsed(Object sender, ElapsedEventArgs args)
|
|
{
|
|
lock (this.shortTimer)
|
|
{
|
|
this.tempMeterForm.BeginInvoke(new Action(() =>
|
|
{
|
|
var currentTOF = this.tempMeterForm.AvgTOF();
|
|
var currentT = this.temperatureSource.GetTemperature();
|
|
var messurement = $"[{args.SignalTime:yyyy-MM-dd hh:mm:ss}]\t{this.pcbId,9}\t{currentT,5:00.00}\t{currentTOF,14:0.000000000000}";
|
|
|
|
if (this.messuring)
|
|
{
|
|
this.tempMeterForm.AddMessage(messurement);
|
|
File.AppendAllLines(this.messurementsFile, new[] { messurement });
|
|
}
|
|
}));
|
|
}
|
|
}
|
|
|
|
private String GetOrCreateMessurementsFile(string pcbId)
|
|
{
|
|
Directory.CreateDirectory(WORKING_DIR);
|
|
|
|
var filePath = $@"{WORKING_DIR}\{this.pcbId}{MESSUREMENTS_FILE}";
|
|
|
|
File.AppendAllText(filePath, Environment.NewLine);
|
|
|
|
return filePath;
|
|
}
|
|
|
|
private String GetOrCreateAggregationsFile(string pcbId)
|
|
{
|
|
Directory.CreateDirectory(WORKING_DIR);
|
|
|
|
var filePath = $@"{WORKING_DIR}\{this.pcbId}{AGGREGATIONS_FILE}";
|
|
|
|
if (!File.Exists(filePath))
|
|
{
|
|
File.WriteAllLines(filePath, new[] { Messurements.Header });
|
|
}
|
|
|
|
return filePath;
|
|
}
|
|
|
|
private void ParseMessurements()
|
|
{
|
|
var messurementLines = File.ReadAllLines(this.messurementsFile);
|
|
var messurements = new Messurements(this.pcbId);
|
|
|
|
File.WriteAllText(this.messurementsFile, string.Empty);
|
|
|
|
foreach (var messurementLine in messurementLines)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(messurementLine))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
var tokens = messurementLine
|
|
.Split(new[] { '\t' }, StringSplitOptions.RemoveEmptyEntries);
|
|
|
|
if (tokens.Length != 4)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
var dateString = tokens[0];
|
|
var pcbString = tokens[1];
|
|
var tString = tokens[2];
|
|
var tofString = tokens[3];
|
|
|
|
var currentT = default(double);
|
|
var currentTOF = default(double);
|
|
|
|
try
|
|
{
|
|
var tParsed = double.TryParse(tString, ANY, this.en, out currentT) || double.TryParse(tString, ANY, this.de, out currentT);
|
|
var tofParsed = double.TryParse(tofString, ANY, this.en, out currentTOF) || double.TryParse(tofString, ANY, this.de, out currentTOF);
|
|
}
|
|
catch
|
|
{
|
|
continue;
|
|
}
|
|
|
|
messurements.Add(currentT, currentTOF);
|
|
}
|
|
|
|
File.AppendAllLines(this.aggregationsFile, new[] { messurements.ToString() });
|
|
}
|
|
}
|
|
|
|
class Messurements
|
|
{
|
|
private readonly string pcbId;
|
|
|
|
// _______________________________ t _____ tof _________________
|
|
private readonly ICollection<Tuple<double, double>> messurements
|
|
= new List<Tuple<double, double>>();
|
|
|
|
public Messurements(string pcbId)
|
|
=> this.pcbId = pcbId;
|
|
|
|
public double MinT => this.messurements.Min(x => x.Item1);
|
|
|
|
public double MinTOF => this.messurements.Min(x => x.Item2);
|
|
|
|
public double AvgT => this.messurements.Average(x => x.Item1);
|
|
|
|
public double AvgTOF => this.messurements.Average(x => x.Item2);
|
|
|
|
public double MaxT => this.messurements.Max(x => x.Item1);
|
|
|
|
public double MaxTOF => this.messurements.Max(x => x.Item2);
|
|
|
|
public double DifT => Math.Abs(this.MinT - this.MaxT);
|
|
|
|
public double DifTOF => Math.Abs(this.MinTOF - this.MaxTOF);
|
|
|
|
public int Count => this.messurements.Count;
|
|
|
|
public override String ToString()
|
|
=> $"{this.pcbId}"
|
|
+ $"\t{this.MinT:0.00}"
|
|
+ $"\t{this.MinTOF:0.0000000000}"
|
|
+ $"\t{this.AvgT:0.00}"
|
|
+ $"\t{this.AvgTOF:0.0000000000}"
|
|
+ $"\t{this.MaxT:0.00}"
|
|
+ $"\t{this.MaxTOF:0.0000000000}"
|
|
+ $"\t{this.DifT:0.00}"
|
|
+ $"\t{this.DifTOF:0.0000000000}"
|
|
+ $"\t{this.Count}";
|
|
|
|
public void Add(double t, double tof)
|
|
=> this.messurements.Add(new Tuple<double, double>(t, tof));
|
|
|
|
public static string Header
|
|
=> $"Pcb Id\tMin °C\tMin TOF\tAvg °C\tAvg TOF\tMax °C\tMax TOF\tDif °C\tDif TOF\tCount";
|
|
}
|
|
} |