current working solution
This commit is contained in:
@@ -559,7 +559,7 @@
|
||||
var orderedResults = this.results
|
||||
.OrderBy(x => x.Key.GPM);
|
||||
var accuracies = orderedResults
|
||||
.Select(x => x.Value.DifferencePercentage())
|
||||
.Select(x => x.Value.AccuracyPercentage())
|
||||
.ToArray();
|
||||
|
||||
var correction = accuracies.GetCorrectionFactor();
|
||||
|
||||
@@ -88,7 +88,7 @@
|
||||
this.AddResult("Test result:", $"{test.Rotations:0}/{test.Duration:0.0000}");
|
||||
this.AddResult("Meter flow", $"{test.MeterFlowM3S:0.00000000} m³/h");
|
||||
this.AddResult("Reference flow", $"{test.ReferenceFlowM3S:0.00000000} m³/h");
|
||||
this.AddResult("Accuracy", $"{test.DifferencePercentage():0.00}%");
|
||||
this.AddResult("Accuracy", $"{test.AccuracyPercentage():0.00}%");
|
||||
}
|
||||
|
||||
internal void Add(ConfigurationParameters response)
|
||||
|
||||
@@ -14,10 +14,12 @@
|
||||
public override byte[] Send(params byte[] message)
|
||||
{
|
||||
var response = new byte[0];
|
||||
var received = false;
|
||||
|
||||
void DataReceived(byte[] data)
|
||||
{
|
||||
response = data;
|
||||
received = true;
|
||||
|
||||
this.waitHandle.Set();
|
||||
}
|
||||
@@ -26,27 +28,17 @@
|
||||
|
||||
this.StartListening();
|
||||
|
||||
for (int i = 0; i < 3; i++)
|
||||
for (int i = 0; i < 3 && !received; i++)
|
||||
{
|
||||
if (response != null && response.Length > 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
this.WritePlain(1, 1, 1, 1);
|
||||
|
||||
this.waitHandle.Wait(1);
|
||||
this.waitHandle.Reset();
|
||||
this.waitHandle.Wait(1);
|
||||
|
||||
this.WriteEncoded(message);
|
||||
|
||||
this.waitHandle.Wait(3000);
|
||||
this.waitHandle.Reset();
|
||||
|
||||
if (response != null && response.Length > 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
this.waitHandle.Wait(3000);
|
||||
}
|
||||
|
||||
this.StopListening();
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
this.NotifyStateChanged($"--- {e}");
|
||||
this.NotifyStateChanged($"[{DateTime.Now}] --- {e}");
|
||||
}
|
||||
|
||||
base.Close();
|
||||
@@ -51,7 +51,7 @@
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
this.NotifyStateChanged($"--- {e}");
|
||||
this.NotifyStateChanged($"[{DateTime.Now}] --- {e}");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,7 +64,7 @@
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
this.NotifyStateChanged($"--- {e}");
|
||||
this.NotifyStateChanged($"[{DateTime.Now}] --- {e}");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,7 +77,7 @@
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
this.NotifyStateChanged($"--- {e}");
|
||||
this.NotifyStateChanged($"[{DateTime.Now}] --- {e}");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -87,14 +87,14 @@
|
||||
{
|
||||
if (this.encoder.TryEncode(bytes, out byte[] message))
|
||||
{
|
||||
this.Write(message, 0, message.Length);
|
||||
}
|
||||
var timestamp = this.Write(message, 0, message.Length);
|
||||
|
||||
this.NotifyStateChanged($">>> {BitConverter.ToString(bytes)}");
|
||||
this.NotifyStateChanged($"[{timestamp}] >>> {BitConverter.ToString(bytes)}");
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
this.NotifyStateChanged($"--- {e}");
|
||||
this.NotifyStateChanged($"[{DateTime.Now}] --- {e}");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -102,41 +102,39 @@
|
||||
{
|
||||
try
|
||||
{
|
||||
this.Write(bytes, 0, bytes.Length);
|
||||
var timestamp = this.Write(bytes, 0, bytes.Length);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
this.NotifyStateChanged($"--- {e}");
|
||||
this.NotifyStateChanged($"[{DateTime.Now}] --- {e}");
|
||||
}
|
||||
}
|
||||
|
||||
private void ReadingTaskHandler()
|
||||
private void ReadingTaskHandler(object state)
|
||||
{
|
||||
while (this.IsOpen)
|
||||
if (state is SerialDataStream serialDataStream)
|
||||
{
|
||||
this.waitHandle.Wait();
|
||||
|
||||
var length = this.BytesToRead;
|
||||
|
||||
if (length > 0)
|
||||
while (serialDataStream.IsOpen)
|
||||
{
|
||||
var buffer = new byte[length];
|
||||
serialDataStream.waitHandle.Wait();
|
||||
|
||||
this.Read(buffer, 0, length);
|
||||
this.buffer.AddRange(buffer);
|
||||
var length = serialDataStream.BytesToRead;
|
||||
|
||||
var data = this.buffer.ToArray();
|
||||
|
||||
if (this.encoder.TryDecode(data, out byte[] message, out int start, out int _))
|
||||
if (length > 0)
|
||||
{
|
||||
this.DataReceived?.Invoke(message);
|
||||
var buffer = new byte[length];
|
||||
|
||||
this.NotifyStateChanged($"<<< {BitConverter.ToString(message)}");
|
||||
}
|
||||
var timestamp = serialDataStream.Read(buffer, 0, length);
|
||||
serialDataStream.buffer.AddRange(buffer);
|
||||
|
||||
if (start < 0)
|
||||
{
|
||||
this.buffer.Clear();
|
||||
var data = serialDataStream.buffer.ToArray();
|
||||
|
||||
if (serialDataStream.encoder.TryDecode(data, out byte[] message, out int start, out int _))
|
||||
{
|
||||
serialDataStream.DataReceived?.Invoke(message);
|
||||
|
||||
serialDataStream.NotifyStateChanged($"[{timestamp}] <<< {BitConverter.ToString(message)}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -146,12 +144,12 @@
|
||||
{
|
||||
this.cancellationTokenSource = new CancellationTokenSource();
|
||||
this.cancellationToken = this.cancellationTokenSource.Token;
|
||||
this.readingTask = Task.Factory.StartNew(this.ReadingTaskHandler, this.cancellationToken);
|
||||
this.readingTask = Task.Factory.StartNew(this.ReadingTaskHandler, this, this.cancellationToken);
|
||||
this.readingTask.ContinueWith(task =>
|
||||
{
|
||||
if (task.Exception != null)
|
||||
{
|
||||
this.NotifyStateChanged($"--- {task.Exception}");
|
||||
this.NotifyStateChanged($"[{DateTime.Now}] --- {task.Exception}");
|
||||
}
|
||||
|
||||
this.StartReading();
|
||||
|
||||
@@ -59,12 +59,12 @@
|
||||
this.serialPort.Dispose();
|
||||
this.serialPort = null;
|
||||
|
||||
this.NotifyStateChanged($"--- Disconnected: {this}");
|
||||
this.NotifyStateChanged($"[{DateTime.Now}] --- Disconnected: {this}");
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
this.NotifyStateChanged($"--- {e}");
|
||||
this.NotifyStateChanged($"[{DateTime.Now}] --- {e}");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -84,11 +84,11 @@
|
||||
|
||||
this.serialPort.Open();
|
||||
|
||||
this.NotifyStateChanged($"--- Connected: {this}");
|
||||
this.NotifyStateChanged($"[{DateTime.Now}] --- Connected: {this}");
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
this.NotifyStateChanged($"--- {e}");
|
||||
this.NotifyStateChanged($"[{DateTime.Now}] --- {e}");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -119,19 +119,23 @@
|
||||
this.StateChanged?.Invoke(state);
|
||||
}
|
||||
|
||||
protected void Read(byte[] bytes, int start, int length)
|
||||
protected DateTime Read(byte[] bytes, int start, int length)
|
||||
{
|
||||
this.serialPort.Read(bytes, start, length);
|
||||
|
||||
return DateTime.Now;
|
||||
}
|
||||
|
||||
protected void Write(byte[] bytes, int start, int length)
|
||||
protected DateTime Write(byte[] bytes, int start, int length)
|
||||
{
|
||||
var _lock = new object();
|
||||
var lock_object = new object();
|
||||
|
||||
lock (_lock)
|
||||
lock (lock_object)
|
||||
{
|
||||
this.serialPort.Write(bytes, 0, length);
|
||||
}
|
||||
|
||||
return DateTime.Now;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,6 +14,11 @@
|
||||
var mlPulse = intPart + fractionPart;
|
||||
var mlr = mlPulse * PULSES_PER_ROTATION;
|
||||
|
||||
if (double.IsNaN(mlr) || double.IsInfinity(mlr))
|
||||
{
|
||||
return default(double);
|
||||
}
|
||||
|
||||
return mlr;
|
||||
}
|
||||
|
||||
@@ -31,6 +36,11 @@
|
||||
var m3_min = l_min / 1000;
|
||||
var m3_h = m3_min * 60;
|
||||
|
||||
if (double.IsNaN(m3_h) || double.IsInfinity(m3_h))
|
||||
{
|
||||
return default(double);
|
||||
}
|
||||
|
||||
return m3_h;
|
||||
}
|
||||
|
||||
@@ -41,6 +51,11 @@
|
||||
var s_r = mlr / ml_s * 100;
|
||||
var duration = s_r * rotations;
|
||||
|
||||
if (double.IsNaN(duration) || double.IsInfinity(duration))
|
||||
{
|
||||
duration = -1;
|
||||
}
|
||||
|
||||
return (ushort)(Math.Truncate(duration) + 1);
|
||||
}
|
||||
|
||||
@@ -51,24 +66,61 @@
|
||||
var s_r = mlr / ml_s * 100;
|
||||
var duration = s_r * rotations;
|
||||
|
||||
if (double.IsNaN(duration) || double.IsInfinity(duration))
|
||||
{
|
||||
duration = -1;
|
||||
}
|
||||
|
||||
return (ushort)(Math.Truncate(duration) + 1);
|
||||
}
|
||||
|
||||
public static double DifferencePercentage(this OmniPlusTest test)
|
||||
public static double AccuracyPercentage(double meterFlow, double referenceFlow)
|
||||
{
|
||||
try
|
||||
{
|
||||
return 100 + (test.MeterFlowM3S - test.ReferenceFlowM3S) / test.ReferenceFlowM3S * 100;
|
||||
var result = 100 + (meterFlow - referenceFlow) / referenceFlow * 100;
|
||||
|
||||
if (double.IsNaN(result) || double.IsInfinity(result))
|
||||
{
|
||||
return default(double);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return -1;
|
||||
return default(double);
|
||||
}
|
||||
}
|
||||
|
||||
public static double AccuracyPercentage(this OmniPlusTest test)
|
||||
{
|
||||
try
|
||||
{
|
||||
var result = 100 + (test.MeterFlowM3S - test.ReferenceFlowM3S) / test.ReferenceFlowM3S * 100;
|
||||
|
||||
if (double.IsNaN(result) || double.IsInfinity(result))
|
||||
{
|
||||
return default(double);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return default(double);
|
||||
}
|
||||
}
|
||||
|
||||
public static double MeterFlowM3S(double rotations, double mlr, double duration)
|
||||
{
|
||||
var seconds = duration * (1D / (short.MaxValue + 1));
|
||||
var m3s = rotations * mlr / seconds / 1000D / 1000D * 100;
|
||||
|
||||
if (double.IsNaN(m3s) || double.IsInfinity(m3s))
|
||||
{
|
||||
return default(double);
|
||||
}
|
||||
|
||||
return rotations * mlr / seconds / 1000D / 1000D * 100;
|
||||
}
|
||||
@@ -78,16 +130,19 @@
|
||||
return MeterFlowM3S(test.Rotations, point.MLR, test.Duration);
|
||||
}
|
||||
|
||||
public static double GetCorrectionFactor(this double[] points)
|
||||
public static double GetCorrectionFactor(this double[] points, out bool succeeded)
|
||||
{
|
||||
succeeded = false;
|
||||
|
||||
if (points is null || points.Length != 3)
|
||||
{
|
||||
return -1;
|
||||
return default(double);
|
||||
}
|
||||
|
||||
var min = points[0];
|
||||
var mid = points[1];
|
||||
var max = points[2];
|
||||
var crrf = default(double);
|
||||
|
||||
if (Math.Abs(mid - max) <= 3 && Math.Max(mid, max) - min <= 6.5)
|
||||
{
|
||||
@@ -95,15 +150,40 @@
|
||||
|
||||
if (100 - avgMidMax + min < 95)
|
||||
{
|
||||
return 95 - min;
|
||||
crrf = 95 - min;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 100 - avgMidMax;
|
||||
crrf = 100 - avgMidMax;
|
||||
}
|
||||
|
||||
if (double.IsNaN(crrf) || double.IsInfinity(crrf))
|
||||
{
|
||||
crrf = default(double);
|
||||
}
|
||||
|
||||
succeeded = crrf != 0D;
|
||||
}
|
||||
else
|
||||
{
|
||||
var avgMidMax = (mid + max) / 2;
|
||||
|
||||
if (100 - avgMidMax + min < 95)
|
||||
{
|
||||
crrf = 95 - min;
|
||||
}
|
||||
else
|
||||
{
|
||||
crrf = 100 - avgMidMax;
|
||||
}
|
||||
|
||||
if (double.IsNaN(crrf) || double.IsInfinity(crrf))
|
||||
{
|
||||
crrf = default(double);
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
return crrf;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,9 @@
|
||||
|
||||
public abstract class OmniConnection
|
||||
{
|
||||
public abstract bool IsOpen { get; }
|
||||
public abstract bool IsOpen { get; }
|
||||
|
||||
public event StateChanged StateChenged;
|
||||
|
||||
protected MessageHandler MessageHandler { get; set; }
|
||||
|
||||
@@ -83,6 +85,21 @@
|
||||
return new ReadingResolution(response);
|
||||
}
|
||||
|
||||
public double? ViewFactoryCorrection()
|
||||
{
|
||||
var response = this.MessageHandler.Invoke(DEVICE_SPECIFIC, 0x08);
|
||||
var bytes = new byte[2];
|
||||
|
||||
if (response is null || response.Length <= 1)
|
||||
{
|
||||
return default(double);
|
||||
}
|
||||
|
||||
Buffer.BlockCopy(response, 1, bytes, 0, Math.Min(response.Length - 1, 2));
|
||||
|
||||
return BitConverter.ToInt16(bytes, 0) / 10D;
|
||||
}
|
||||
|
||||
public RateResolution ViewRateResolution()
|
||||
{
|
||||
var response = this.MessageHandler.Invoke(VIEW_RATE_RESOLUTION);
|
||||
@@ -97,6 +114,16 @@
|
||||
return new Readings(response);
|
||||
}
|
||||
|
||||
internal void SetFactoryCorrection(params byte[] crrf)
|
||||
{
|
||||
if (crrf is null || crrf.Length != 2)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var response = this.MessageHandler.Invoke(DEVICE_SPECIFIC, 0x09, crrf[0], crrf[1]);
|
||||
}
|
||||
|
||||
public ReadingMode ViewReadingMode()
|
||||
{
|
||||
var response = this.MessageHandler.Invoke(VIEW_READING_MODE);
|
||||
@@ -463,5 +490,10 @@
|
||||
|
||||
return new FactorySeal(response);
|
||||
}
|
||||
|
||||
protected void OnStateChanged(object state)
|
||||
{
|
||||
this.StateChenged?.Invoke(state);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
namespace OmniPlus
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
|
||||
public class OmniContext
|
||||
{
|
||||
private readonly ConcurrentDictionary<int, OmniMeter> meters;
|
||||
private readonly OmniDatabase database;
|
||||
|
||||
private int runId;
|
||||
|
||||
private OmniContext(string connectionString)
|
||||
{
|
||||
this.database = new OmniDatabase(connectionString);
|
||||
@@ -31,11 +33,13 @@
|
||||
public void LoadAuftrag(string suchnr)
|
||||
{
|
||||
this.Auftrag = this.database.LoadAuftrag(suchnr);
|
||||
this.runId = this.database.GetNextRunId();
|
||||
}
|
||||
|
||||
public void LoadAuftrag(byte size, string type)
|
||||
{
|
||||
this.Auftrag = this.database.LoadAuftrag(size, type);
|
||||
this.runId = this.database.GetNextRunId();
|
||||
}
|
||||
|
||||
public OmniMeter LoadMeter(int nr, string portName)
|
||||
@@ -45,14 +49,24 @@
|
||||
return this.meters.AddOrUpdate(nr, meter, (_, _1) => meter);
|
||||
}
|
||||
|
||||
internal bool Exists(string meterNr)
|
||||
public bool Exists(string meterNr)
|
||||
{
|
||||
return this.database.OmniPlus_Exists(meterNr);
|
||||
}
|
||||
|
||||
internal void Add(string meterNr, string meterState)
|
||||
public void Add(string meterNr, string meterState)
|
||||
{
|
||||
this.database.OmniPlus_Insert(meterNr, meterState);
|
||||
_ = this.database.OmniPlus_Insert(meterNr, meterState);
|
||||
}
|
||||
|
||||
public OmniPruefgang AddTestRun(int slotnr, string meterNr)
|
||||
{
|
||||
return this.database.AddTestRun(this.runId, slotnr, meterNr);
|
||||
}
|
||||
|
||||
internal int UpdateTestRun(IDictionary<string, object> parameters, int id, byte slotNr)
|
||||
{
|
||||
return this.database.UpdateTestRun(parameters, id, slotNr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,15 +5,27 @@
|
||||
|
||||
using OmniPlus.Inspection;
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
public class OmniDatabase
|
||||
{
|
||||
private readonly ISQLConnection sqlConnection;
|
||||
private readonly string logFile;
|
||||
|
||||
public OmniDatabase(string connectionString)
|
||||
{
|
||||
this.sqlConnection = SQLConnection.CreateSQLConnection(connectionString);
|
||||
this.logFile = Path.Combine(Directory.GetCurrentDirectory(), "sql_logger.txt");
|
||||
this.sqlConnection = SQLConnection.CreateSQLConnection(connectionString, this.ErrorLogger);
|
||||
}
|
||||
|
||||
internal int GetNextRunId()
|
||||
{
|
||||
return this.sqlConnection
|
||||
.CreateCommand("SELECT MAX([Id]) FROM [OmniTestRuns]")
|
||||
.ExecuteScalar(reader => reader.GetInt()) + 1;
|
||||
}
|
||||
|
||||
public OmniAuftrag LoadAuftrag(string suchNr)
|
||||
@@ -111,6 +123,8 @@
|
||||
});
|
||||
});
|
||||
|
||||
auftrag.GiveAllTestPointsNr();
|
||||
|
||||
return auftrag ?? new OmniAuftrag
|
||||
{
|
||||
TypParameter = new OmniParameter(),
|
||||
@@ -194,6 +208,8 @@
|
||||
});
|
||||
});
|
||||
|
||||
auftrag.GiveAllTestPointsNr();
|
||||
|
||||
return auftrag ?? new OmniAuftrag
|
||||
{
|
||||
TypParameter = new OmniParameter(),
|
||||
@@ -201,6 +217,46 @@
|
||||
};
|
||||
}
|
||||
|
||||
public OmniPruefgang AddTestRun(int id, int slotnr, string meterNr)
|
||||
{
|
||||
return this.sqlConnection
|
||||
.CreateCommand($@"
|
||||
INSERT
|
||||
INTO [OmniTestRuns] ([Id], [SlotNr], [MeterNr])
|
||||
OUTPUT [inserted].[Id]
|
||||
, [inserted].[SlotNr]
|
||||
, [inserted].[MeterNr]
|
||||
, [inserted].[AddDate]
|
||||
VALUES (@{nameof(id)}, @{nameof(slotnr)}, @{nameof(meterNr)})")
|
||||
.SetParameter(nameof(id), id)
|
||||
.SetParameter(nameof(slotnr), slotnr)
|
||||
.SetParameter(nameof(meterNr), meterNr)
|
||||
.FirstOrDefault(reader => new OmniPruefgang
|
||||
{
|
||||
Id = reader.GetInt(),
|
||||
SlotNr = reader.GetTinyint(),
|
||||
MeterNr = reader.GetString(),
|
||||
AddDate = reader.GetDate()
|
||||
});
|
||||
}
|
||||
|
||||
public int UpdateTestRun(IDictionary<string, object> parameters, int id, byte slotNr)
|
||||
{
|
||||
var setters = parameters.Select(x => $"[{x.Key}] = @{x.Key}");
|
||||
var query = string.Join($", {Environment.NewLine}", setters);
|
||||
|
||||
return this.sqlConnection
|
||||
.CreateCommand($@"
|
||||
UPDATE [OmniTestRuns]
|
||||
SET {query}
|
||||
WHERE [Id] = @{nameof(id)}
|
||||
AND [SlotNr] = @{nameof(slotNr)}")
|
||||
.SetParameter(nameof(id), id)
|
||||
.SetParameter(nameof(slotNr), slotNr)
|
||||
.SetParameters(parameters)
|
||||
.ExecuteNonQuery();
|
||||
}
|
||||
|
||||
public bool OmniPlus_Exists(string meterNr)
|
||||
{
|
||||
return this.sqlConnection
|
||||
@@ -212,11 +268,16 @@
|
||||
public int OmniPlus_Insert(string meterNr, string meterState)
|
||||
{
|
||||
return this.sqlConnection
|
||||
.CreateCommand($@"INSERT INTO [OmniPlus] VALUES (@{nameof(meterNr)}, @{nameof(meterState)})")
|
||||
.CreateCommand($@"INSERT INTO [OmniPlus] ([MeterNr], [MeterState]) VALUES (@{nameof(meterNr)}, @{nameof(meterState)})")
|
||||
.SetParameter(nameof(meterNr), meterNr)
|
||||
.SetParameter(nameof(meterState), meterState)
|
||||
.ExecuteNonQuery();
|
||||
}
|
||||
|
||||
private void ErrorLogger(string error)
|
||||
{
|
||||
File.AppendAllText(this.logFile, $"{error}{Environment.NewLine}");
|
||||
}
|
||||
}
|
||||
|
||||
public class OmniAuftrag
|
||||
@@ -248,6 +309,16 @@
|
||||
public OmniParameter TypParameter { get; internal set; }
|
||||
|
||||
public ICollection<OmniPruefpunkt> Pruefpunkte { get; internal set; }
|
||||
|
||||
internal void GiveAllTestPointsNr()
|
||||
{
|
||||
var count = this.Pruefpunkte.Count;
|
||||
|
||||
foreach (var pp in this.Pruefpunkte)
|
||||
{
|
||||
pp.PPNR = count--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class OmniParameter
|
||||
@@ -273,6 +344,8 @@
|
||||
|
||||
public class OmniPruefpunkt
|
||||
{
|
||||
public int PPNR { get; internal set; }
|
||||
|
||||
public short TestPointId { get; internal set; }
|
||||
|
||||
public byte OmniTypeId { get; internal set; }
|
||||
@@ -291,4 +364,120 @@
|
||||
|
||||
public double FlowM3H => this.GalPerMin.GPM2M3H();
|
||||
}
|
||||
|
||||
public class OmniPruefgang : Dictionary<string, object>
|
||||
{
|
||||
public int Id { get; set; }
|
||||
|
||||
public byte SlotNr { get; set; }
|
||||
|
||||
public string MeterNr { get; set; }
|
||||
|
||||
public DateTime AddDate { get; set; }
|
||||
|
||||
public string BuildInfo { get; set; }
|
||||
|
||||
public string VersionAndType { get; set; }
|
||||
|
||||
public DateTime? ManifacturedDate { get; set; }
|
||||
|
||||
public double? BatteryVoltage { get; set; }
|
||||
|
||||
public bool? IsValid { get; set; }
|
||||
|
||||
public double? CrrfBefore { get; set; }
|
||||
|
||||
public double? CrrfAfter{ get; set; }
|
||||
|
||||
public bool? Succeeded { get; set; }
|
||||
|
||||
public DateTime? EndDate { get; set; }
|
||||
|
||||
public ICollection<OmniPruefpunktResult> TestPoints { get; }
|
||||
= new List<OmniPruefpunktResult>();
|
||||
|
||||
internal void AddTestPoint(int ppnr, short testPointId, double gpm, int rotations, double duration, double m3s, double refm3s, double acc)
|
||||
{
|
||||
var tp = new OmniPruefpunktResult
|
||||
{
|
||||
Nr = (byte)ppnr,
|
||||
TpId = testPointId,
|
||||
Rotations = rotations,
|
||||
Duration = duration,
|
||||
MeterM3S = m3s,
|
||||
RefM3S = refm3s,
|
||||
Accuracy = acc,
|
||||
GPM = gpm
|
||||
};
|
||||
|
||||
this.TestPoints.Add(tp);
|
||||
|
||||
OmniContext.Current.UpdateTestRun(tp.ToDictionary(), this.Id, this.SlotNr);
|
||||
}
|
||||
|
||||
internal void SaveChanges()
|
||||
{
|
||||
OmniContext.Current.UpdateTestRun(new Dictionary<string, object>
|
||||
{
|
||||
{ nameof(BuildInfo), this.BuildInfo },
|
||||
{ nameof(VersionAndType), this.VersionAndType },
|
||||
{ nameof(ManifacturedDate), this.ManifacturedDate },
|
||||
{ nameof(BatteryVoltage), this.BatteryVoltage },
|
||||
{ nameof(IsValid), this.IsValid },
|
||||
{ nameof(CrrfBefore), this.CrrfBefore },
|
||||
}, this.Id, this.SlotNr);
|
||||
}
|
||||
|
||||
internal double[] GetAccuracies()
|
||||
{
|
||||
return this.TestPoints
|
||||
.OrderBy(x => x.GPM)
|
||||
.Select(x => x.Accuracy ?? default(double))
|
||||
.ToArray();
|
||||
}
|
||||
|
||||
internal void CloseTestRun()
|
||||
{
|
||||
this.EndDate = DateTime.Now;
|
||||
|
||||
OmniContext.Current.UpdateTestRun(new Dictionary<string, object>
|
||||
{
|
||||
{ nameof(CrrfAfter), this.CrrfAfter },
|
||||
{ nameof(Succeeded), this.Succeeded },
|
||||
{ nameof(EndDate), this.EndDate },
|
||||
}, this.Id, this.SlotNr);
|
||||
}
|
||||
}
|
||||
|
||||
public class OmniPruefpunktResult
|
||||
{
|
||||
public byte? Nr { get; set; }
|
||||
|
||||
public short? TpId { get; set; }
|
||||
|
||||
public int? Rotations { get; set; }
|
||||
|
||||
public double? Duration { get; set; }
|
||||
|
||||
public double? MeterM3S { get; set; }
|
||||
|
||||
public double? RefM3S { get; set; }
|
||||
|
||||
public double? Accuracy { get; set; }
|
||||
|
||||
public double? GPM { get; set; }
|
||||
|
||||
public IDictionary<string, object> ToDictionary()
|
||||
{
|
||||
return new Dictionary<string, object>
|
||||
{
|
||||
{ $"Q{this.Nr}_{nameof(TpId)}", this.TpId },
|
||||
{ $"Q{this.Nr}_{nameof(Rotations)}", this.Rotations },
|
||||
{ $"Q{this.Nr}_{nameof(Duration)}", this.Duration },
|
||||
{ $"Q{this.Nr}_{nameof(MeterM3S)}", this.MeterM3S },
|
||||
{ $"Q{this.Nr}_{nameof(RefM3S)}", this.RefM3S },
|
||||
{ $"Q{this.Nr}_{nameof(Accuracy)}", this.Accuracy },
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,18 +2,14 @@
|
||||
{
|
||||
using OmniPlus.Connections;
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.IO.Ports;
|
||||
|
||||
public sealed class OmniIrdaConnection : OmniConnection
|
||||
{
|
||||
private readonly OmniIrdaStream stream;
|
||||
private readonly string stateFile;
|
||||
|
||||
public OmniIrdaConnection(string portName)
|
||||
{
|
||||
this.stateFile = this.GetOrCreateStateFile(portName);
|
||||
this.stream = new OmniIrdaStream(
|
||||
encoder: new OmniIrdaEncoder(),
|
||||
settings: new SerialPortSettings
|
||||
@@ -42,35 +38,5 @@
|
||||
{
|
||||
this.stream.Open();
|
||||
}
|
||||
|
||||
private void OnStateChanged(object state)
|
||||
{
|
||||
try
|
||||
{
|
||||
File.AppendAllText(this.stateFile, $"[{DateTime.Now:yyyy-MM-dd HH:mm:ss.fffffff}] {state}{Environment.NewLine}");
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
try
|
||||
{
|
||||
File.AppendAllText(this.stateFile, $"[{DateTime.Now:yyyy-MM-dd HH:mm:ss.fffffff}] {e}");
|
||||
}
|
||||
catch (Exception _)
|
||||
{
|
||||
// TODO: throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private string GetOrCreateStateFile(string portName)
|
||||
{
|
||||
var stateFile = $"{portName}_{DateTime.Now:yyyy_MM_dd}.txt";
|
||||
var directory = Directory.CreateDirectory(".\\OmniIrda");
|
||||
stateFile = Path.Combine(directory.FullName, stateFile);
|
||||
|
||||
File.AppendAllText(stateFile, string.Empty);
|
||||
|
||||
return stateFile;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +1,23 @@
|
||||
namespace OmniPlus
|
||||
{
|
||||
using OmniPlus.Features;
|
||||
using OmniPlus.Features.Enums;
|
||||
using OmniPlus.Inspection;
|
||||
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
public class OmniMeter
|
||||
{
|
||||
const string NA = "n/a";
|
||||
|
||||
private readonly ConcurrentQueue<object> states = new ConcurrentQueue<object>();
|
||||
private readonly string stateFile;
|
||||
|
||||
private readonly int slotnr;
|
||||
private readonly string portName;
|
||||
private OmniConnection connection;
|
||||
@@ -18,17 +26,21 @@
|
||||
{
|
||||
this.slotnr = nr;
|
||||
this.portName = portName;
|
||||
this.stateFile = this.GetOrCreateStateFile(nr, portName);
|
||||
}
|
||||
|
||||
public string MeterNr { get; private set; }
|
||||
|
||||
public int? SerialNr { get; private set; }
|
||||
|
||||
public OmniPruefgang TestRun { get; private set; }
|
||||
|
||||
public void ConnectIrda()
|
||||
{
|
||||
if (this.connection is null)
|
||||
{
|
||||
this.connection = new OmniIrdaConnection(this.portName);
|
||||
this.connection.StateChenged += this.NotifyStateChanged;
|
||||
}
|
||||
|
||||
if (!this.connection.IsOpen)
|
||||
@@ -38,37 +50,97 @@
|
||||
}
|
||||
}
|
||||
|
||||
public void IdentitfyMeter()
|
||||
{
|
||||
var buildInfo = this.connection.ViewBuildInformation();
|
||||
|
||||
if (buildInfo.Status == Status.Completed)
|
||||
{
|
||||
this.MeterNr = buildInfo.Value;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.MeterNr = NA;
|
||||
}
|
||||
|
||||
// TODO: Change identNr to real serialNr
|
||||
// this.SerialNr = OmniContext.Current.Auftrag.IdentNr;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (this.connection != null)
|
||||
{
|
||||
this.connection.Close();
|
||||
|
||||
this.connection.StateChenged -= this.NotifyStateChanged;
|
||||
}
|
||||
|
||||
this.connection = null;
|
||||
|
||||
File.AppendAllLines(this.stateFile, this.states.Select(x => $"{x}"));
|
||||
}
|
||||
|
||||
public void Initialize()
|
||||
public void InitializeForInspection(bool preserveState = false)
|
||||
{
|
||||
this.ConnectIrda();
|
||||
var systemParameters = this.connection.ViewSystemParameters();
|
||||
var buildInfo = default(string);
|
||||
var versionAndType = default(string);
|
||||
var manifactured = default(DateTime?);
|
||||
var battery = default(double?);
|
||||
var isvalid = default(bool?);
|
||||
|
||||
this.MeterNr = NA;
|
||||
this.SerialNr = default(int?);
|
||||
var buildInfo = this.connection.ViewBuildInformation();
|
||||
if (systemParameters.Status == Status.Completed)
|
||||
{
|
||||
buildInfo = systemParameters.BuildInfo.Value;
|
||||
versionAndType = systemParameters.VersionAndType.Value;
|
||||
manifactured = systemParameters.ManifacturingTime.DateTime;
|
||||
battery = systemParameters.BatteryVoltage.Volts / 1000D;
|
||||
isvalid = systemParameters.IsValid;
|
||||
}
|
||||
|
||||
if (buildInfo.Status != Status.Completed)
|
||||
this.TestRun.SlotNr = (byte)this.slotnr;
|
||||
this.TestRun.BuildInfo = buildInfo;
|
||||
this.TestRun.VersionAndType = versionAndType;
|
||||
this.TestRun.ManifacturedDate = manifactured;
|
||||
this.TestRun.BatteryVoltage = battery;
|
||||
this.TestRun.IsValid = isvalid;
|
||||
|
||||
if (!preserveState)
|
||||
{
|
||||
var defaultCrrf = (sbyte)(3.3 * 10D);
|
||||
var crrfBytes = BitConverter.GetBytes(defaultCrrf);
|
||||
this.connection.SetFactoryCorrection(crrfBytes);
|
||||
}
|
||||
|
||||
this.TestRun.CrrfBefore = this.connection.ViewFactoryCorrection();
|
||||
|
||||
this.TestRun.SaveChanges();
|
||||
|
||||
var defaults = OmniContext.Current.Auftrag.TypParameter;
|
||||
var inputVolumeResult = this.connection.Set(new InputVolume
|
||||
{
|
||||
Direction = defaults.Direction,
|
||||
Fraction = (ushort)defaults.Fraction,
|
||||
IntPart = defaults.IntPart,
|
||||
Range = defaults.Range,
|
||||
Size = defaults.Size
|
||||
});
|
||||
}
|
||||
|
||||
public void LoadTestRun()
|
||||
{
|
||||
this.TestRun = OmniContext.Current.AddTestRun(this.slotnr, this.MeterNr);
|
||||
}
|
||||
|
||||
public void SaveMeterState()
|
||||
{
|
||||
if (this.MeterNr == NA)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this.MeterNr = buildInfo.Value;
|
||||
this.SerialNr = OmniContext.Current.Auftrag.IdentNr;
|
||||
|
||||
if (string.IsNullOrWhiteSpace(this.MeterNr))
|
||||
{
|
||||
return;
|
||||
}
|
||||
else if (OmniContext.Current.Exists(this.MeterNr))
|
||||
if (OmniContext.Current.Exists(this.MeterNr))
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -138,5 +210,82 @@
|
||||
|
||||
OmniContext.Current.Add(this.MeterNr, meterState.ToString());
|
||||
}
|
||||
|
||||
public void StartCalibration(ushort rotations, ushort duration)
|
||||
{
|
||||
var response = connection.StartChamberCalibration(rotations, duration);
|
||||
}
|
||||
|
||||
public Tuple<double, string, double> StopCalibration(OmniPruefpunkt pp, double refm3s)
|
||||
{
|
||||
var response = this.connection.ViewChamberCalibration();
|
||||
var rotations = response.Rotations;
|
||||
var duration = response.DurationSec;
|
||||
var rs = $"{rotations}/{duration:0.0}";
|
||||
var defaults = OmniContext.Current.Auftrag.TypParameter;
|
||||
var mlr = OmniPlusFormulas.MilliliterPerRotation(defaults.IntPart, (ushort)defaults.Fraction, defaults.Factor);
|
||||
var m3s = OmniPlusFormulas.MeterFlowM3S(rotations, mlr, response.Duration);
|
||||
var acc = OmniPlusFormulas.AccuracyPercentage(m3s, refm3s);
|
||||
|
||||
this.TestRun.AddTestPoint(pp.PPNR, pp.TestPointId, pp.GalPerMin, rotations, duration, m3s, refm3s, acc);
|
||||
|
||||
return new Tuple<double, string, double>(m3s, rs, acc);
|
||||
}
|
||||
|
||||
public void FinishInspection(bool preserveState = false)
|
||||
{
|
||||
var crrf = this.TestRun
|
||||
.GetAccuracies()
|
||||
.GetCorrectionFactor(out bool succeeded);
|
||||
var defaults = OmniContext.Current.Auftrag.TypParameter;
|
||||
|
||||
if (!preserveState)
|
||||
{
|
||||
var response = this.connection.Set(new RegisterSettings
|
||||
{
|
||||
IntPart = defaults.IntPart,
|
||||
Fraction = (ushort)defaults.Fraction,
|
||||
Size = defaults.Size,
|
||||
Range = defaults.Range,
|
||||
VolumePerPulseUnit = 0x00,
|
||||
MeterUnits = (byte)MessurementUnits.CubicMeters,
|
||||
FlowUnits = (byte)MessurementUnits.CubicMeters,
|
||||
FlowRate = (byte)TimeUnits.Hours,
|
||||
FactoryCorrection = (sbyte)(crrf * 10),
|
||||
FieldCorrection = 0x00,
|
||||
PulseWeight = 0,
|
||||
PulseWidth = 7,
|
||||
PulseUpdate = 0,
|
||||
});
|
||||
}
|
||||
|
||||
this.TestRun.Succeeded = succeeded;
|
||||
this.TestRun.CrrfAfter = crrf;
|
||||
this.TestRun.CloseTestRun();
|
||||
}
|
||||
|
||||
public void NotifyStateChanged(object state)
|
||||
{
|
||||
this.states.Enqueue(state);
|
||||
}
|
||||
|
||||
private string GetOrCreateStateFile(int slotNr, string portName)
|
||||
{
|
||||
var directory = Directory.GetCurrentDirectory();
|
||||
var stateDirectory = Path.Combine(directory, "Debug", $"{slotNr}_{portName}");
|
||||
var stateFile = Path.Combine(stateDirectory, $"{DateTime.Now:yyyy-MM-dd}.txt");
|
||||
|
||||
try
|
||||
{
|
||||
Directory.CreateDirectory(stateDirectory);
|
||||
File.AppendAllText(stateFile, $"{nameof(OmniMeter)}.{nameof(GetOrCreateStateFile)}({nameof(slotNr)}:{slotNr}, {nameof(portName)}:{portName});{Environment.NewLine}");
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
this.states.Enqueue(e);
|
||||
}
|
||||
|
||||
return stateFile;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
USE [AuftragKopie];
|
||||
USE [Auftrag];
|
||||
|
||||
IF OBJECT_ID(N'OmniTestRuns') IS NOT NULL DROP TABLE [OmniTestRuns];
|
||||
IF OBJECT_ID(N'OmniTestPoints') IS NOT NULL DROP TABLE [OmniTestPoints];
|
||||
IF OBJECT_ID(N'OmniTypes') IS NOT NULL DROP TABLE [OmniTypes];
|
||||
IF OBJECT_ID(N'OmniPlus') IS NOT NULL DROP TABLE [OmniPlus];
|
||||
@@ -65,7 +66,43 @@ VALUES ( 1, 'C2', 160.00, 700, 35, 98.5,
|
||||
|
||||
CREATE TABLE [OmniPlus] (
|
||||
[MeterNr] VARCHAR(32) NOT NULL PRIMARY KEY,
|
||||
[MeterState] VARCHAR(MAX) NOT NULL
|
||||
[MeterState] VARCHAR(MAX) NOT NULL,
|
||||
[ReadyState] VARCHAR(MAX) NULL
|
||||
);
|
||||
|
||||
CREATE TABLE [OmniTestRuns] (
|
||||
[Id] INT NOT NULL PRIMARY KEY IDENTITY(1, 1),
|
||||
[SlotNr] TINYINT NOT NULL,
|
||||
[MeterNr] VARCHAR(32) NOT NULL,
|
||||
[AddDate] DATETIME NOT NULL DEFAULT(GETDATE()),
|
||||
|
||||
[BuildInfo] VARCHAR(15) NULL,
|
||||
[VersionAndType] VARCHAR(30) NULL,
|
||||
[ManifacturedDate] DATETIME NULL,
|
||||
[BatteryVoltage] FLOAT NULL,
|
||||
[IsValid] BIT NULL,
|
||||
[CrrfBefore] FLOAT NULL,
|
||||
|
||||
[Q1_TpId] SMALLINT NULL,
|
||||
[Q1_Rotations] INT NULL,
|
||||
[Q1_Duration] FLOAT NULL,
|
||||
[Q1_FlowM3S] FLOAT NULL,
|
||||
[Q1_Accuracy] FLOAT NULL,
|
||||
|
||||
[Q2_TpId] SMALLINT NULL,
|
||||
[Q2_Rotations] INT NULL,
|
||||
[Q2_Duration] FLOAT NULL,
|
||||
[Q2_FlowM3S] FLOAT NULL,
|
||||
[Q2_Accuracy] FLOAT NULL,
|
||||
|
||||
[Q3_TpId] SMALLINT NULL,
|
||||
[Q3_Rotations] INT NULL,
|
||||
[Q3_Duration] FLOAT NULL,
|
||||
[Q3_FlowM3S] FLOAT NULL,
|
||||
[Q3_Accuracy] FLOAT NULL,
|
||||
|
||||
[CrrfAfter] FLOAT NULL,
|
||||
[EndDate] DATETIME NULL,
|
||||
);
|
||||
|
||||
|
||||
|
||||
@@ -1,19 +1,15 @@
|
||||
namespace OmniPlus
|
||||
{
|
||||
using OmniPlus.Connections;
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
using System.IO.Ports;
|
||||
|
||||
public class OmniUniProConnection : OmniConnection
|
||||
{
|
||||
private readonly OmniUniProStream stream;
|
||||
private readonly string stateFile;
|
||||
|
||||
public OmniUniProConnection(string portName)
|
||||
{
|
||||
this.stateFile = this.GetOrCreateStateFile(portName);
|
||||
this.stream = new OmniUniProStream(
|
||||
encoder: new OmniUniProEncoder(),
|
||||
settings: new SerialPortSettings
|
||||
@@ -42,29 +38,5 @@
|
||||
{
|
||||
this.stream.Open();
|
||||
}
|
||||
|
||||
private void OnStateChanged(object state)
|
||||
{
|
||||
try
|
||||
{
|
||||
File.AppendAllText(this.stateFile, $"[{DateTime.Now:yyyy-MM-dd HH:mm:ss.fff}] {state}{Environment.NewLine}");
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
|
||||
// TODO: throw;
|
||||
}
|
||||
}
|
||||
|
||||
private string GetOrCreateStateFile(string portName)
|
||||
{
|
||||
var stateFile = $"{portName}_{DateTime.Now:yyyy_MM_dd}.txt";
|
||||
var directory = Directory.CreateDirectory(".\\OmniUniPro");
|
||||
stateFile = Path.Combine(directory.FullName, stateFile);
|
||||
|
||||
File.AppendAllText(stateFile, string.Empty);
|
||||
|
||||
return stateFile;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user