latest omni changes
This commit is contained in:
@@ -0,0 +1,48 @@
|
||||
using System;
|
||||
|
||||
namespace OmniPlus.Features
|
||||
{
|
||||
public class ChamberCalibrationRequest : FeatureRequest
|
||||
{
|
||||
public const byte ACTIVATE_TEST = 0x00;
|
||||
public const byte REQUEST_RESULTS = 0x01;
|
||||
|
||||
const int LENGTH = 5;
|
||||
|
||||
public ChamberCalibrationRequest() : base(LENGTH)
|
||||
{
|
||||
}
|
||||
|
||||
public ChamberCalibrationRequest(byte[] response) : base(response, LENGTH)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 0 – Activate Factory Calibration Test
|
||||
/// 1 – Request Factory Calibration Test Results
|
||||
/// </summary>
|
||||
public byte Control
|
||||
{
|
||||
get => this.bytes[0];
|
||||
set => this.bytes[0] = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Request: Number of Rotations to collect. (not required if Requesting Calibration results) (Limited to 1 to 5000 rotations)
|
||||
/// </summary>
|
||||
public ushort Rotations
|
||||
{
|
||||
get => BitConverter.ToUInt16(this.bytes, 1);
|
||||
set => BitConverter.GetBytes(value).CopyTo(this.bytes, 1);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Request: Maximum Time command is supposed to take to execute - 1 to 3600 Seconds.
|
||||
/// </summary>
|
||||
public ushort Duration
|
||||
{
|
||||
get => BitConverter.ToUInt16(this.bytes, 3);
|
||||
set => BitConverter.GetBytes(value).CopyTo(this.bytes, 3);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
namespace OmniPlus.Features
|
||||
{
|
||||
using System;
|
||||
|
||||
public class ChamberCalibrationResponse : FeatureRequest
|
||||
{
|
||||
public const byte TEST_ACTIVATED = 0x00;
|
||||
public const byte TEST_FAILED = 0x01;
|
||||
public const byte TEST_COMPLETED = 0x02;
|
||||
|
||||
const int LENGTH = 7;
|
||||
|
||||
public ChamberCalibrationResponse() : base(LENGTH)
|
||||
{
|
||||
}
|
||||
|
||||
public ChamberCalibrationResponse(byte[] response) : base(response, LENGTH)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 0 Test Activation Successful
|
||||
/// 1 Test Failed (Timeout)
|
||||
/// 2 Test Successfully Completed
|
||||
/// </summary>
|
||||
public byte Control
|
||||
{
|
||||
get => this.bytes[0];
|
||||
set => this.bytes[0] = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Response: Number of rotations collected
|
||||
/// On Test Activation, this field echoes the number of rotations requested.
|
||||
/// On Test Failed and Test Successfully Completed, returns the number of rotations collected.
|
||||
/// </summary>
|
||||
public ushort Rotations
|
||||
{
|
||||
get => BitConverter.ToUInt16(this.bytes, 1);
|
||||
set => BitConverter.GetBytes(value).CopyTo(this.bytes, 1);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Response: Total Time it took to collect the indicated rotations. Each count is equal to 30.5176us.
|
||||
/// On Test Activation Successful, returns number of seconds test is allowed to take.
|
||||
/// On Test Failed, this field will show 0 indicating that the tested failed.
|
||||
/// </summary>
|
||||
public uint Duration
|
||||
{
|
||||
get => BitConverter.ToUInt16(this.bytes, 3);
|
||||
set => BitConverter.GetBytes(value).CopyTo(this.bytes, 3);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,12 @@
|
||||
|
||||
public ConfigurationParameters() : base(LENGTH)
|
||||
{
|
||||
this.ProgrammableID = new ProgrammableID();
|
||||
this.FactoryID = new FactoryID();
|
||||
this.ReadingDigits = new ReadingDigits();
|
||||
this.Readings = new Readings();
|
||||
this.OptionalUniDirFields = new OptionalUniDirFields();
|
||||
this.DeviceID = new DeviceID();
|
||||
}
|
||||
|
||||
public ConfigurationParameters(byte[] response) : base(response, LENGTH)
|
||||
@@ -31,14 +37,14 @@
|
||||
|
||||
this.OptionalUniDirFields = new OptionalUniDirFields();
|
||||
this.OptionalUniDirFields.Status = this.Status;
|
||||
this.OptionalUniDirFields.Past(this.bytes, 46);
|
||||
this.OptionalUniDirFields.Value = this.bytes.ToASCIIString(46, 49);
|
||||
|
||||
this.AlartPersistencePeriod = this.bytes[50];
|
||||
this.DataLogIntervalMinutes = BitConverter.ToUInt16(this.bytes, 51);
|
||||
this.AlartPersistenceDays = this.bytes[50];
|
||||
this.DataLogIntervalMins = BitConverter.ToUInt16(this.bytes, 51);
|
||||
|
||||
this.DeviceID = new DeviceID();
|
||||
this.Readings.Status = this.Status;
|
||||
this.Readings.Value = this.bytes.ToASCIIString(53, 61);
|
||||
this.DeviceID.Status = this.Status;
|
||||
this.DeviceID.Value = this.bytes.ToASCIIString(53, 61);
|
||||
}
|
||||
|
||||
public ProgrammableID ProgrammableID { get; set; }
|
||||
@@ -51,9 +57,9 @@
|
||||
|
||||
public OptionalUniDirFields OptionalUniDirFields { get; set; }
|
||||
|
||||
public byte AlartPersistencePeriod { get; set; }
|
||||
public byte AlartPersistenceDays { get; set; }
|
||||
|
||||
public ushort DataLogIntervalMinutes { get; set; }
|
||||
public ushort DataLogIntervalMins { get; set; }
|
||||
|
||||
public DeviceID DeviceID { get; set; }
|
||||
}
|
||||
|
||||
@@ -325,5 +325,14 @@
|
||||
/// the register will update system time to the time specified in this command in addition to setting manufacturing time.
|
||||
/// </summary>
|
||||
public const byte SET_MANIFACTURING_TIME = 0x3A;
|
||||
|
||||
/// <summary>
|
||||
/// The command is used to view the Register Configuration of the Meter
|
||||
/// </summary>
|
||||
public const byte VIEW_REGISTER_SETTINGS = 0x24;
|
||||
/// <summary>
|
||||
/// Command is used to modify majority of the Factory Settings at one time to speed up Factory initialization time.
|
||||
/// </summary>
|
||||
public const byte SET_REGISTER_SETTINGS = 0x25;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
/// <summary>
|
||||
/// TODO: Need more investigation of the purpose
|
||||
/// </summary>
|
||||
public class OptionalUniDirFields : FeatureRequest
|
||||
public class OptionalUniDirFields : ASCIIString
|
||||
{
|
||||
const int LENGTH = 4;
|
||||
|
||||
@@ -16,12 +16,5 @@
|
||||
public OptionalUniDirFields(byte[] response) : base(response, LENGTH)
|
||||
{
|
||||
}
|
||||
|
||||
public void Past(byte[] bytes, int start)
|
||||
{
|
||||
this.bytes.Clear();
|
||||
|
||||
Array.Copy(bytes, start, this.bytes, 0, 4);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
namespace OmniPlus.Features
|
||||
{
|
||||
using System;
|
||||
using System;
|
||||
|
||||
using static OmniPlus.OmniPlusExtensions;
|
||||
|
||||
namespace OmniPlus.Features
|
||||
{
|
||||
public class RegisterSettings : FeatureRequest
|
||||
{
|
||||
const int LENGTH = 13;
|
||||
@@ -37,5 +39,59 @@
|
||||
get => this.bytes[5];
|
||||
set => this.bytes[5] = value;
|
||||
}
|
||||
|
||||
public byte VolumePerPulseUnit
|
||||
{
|
||||
get => this.bytes[6];
|
||||
set => this.bytes[6] = value;
|
||||
}
|
||||
|
||||
public byte MeterUnits
|
||||
{
|
||||
get => this.bytes[7];
|
||||
set => this.bytes[7] = value;
|
||||
}
|
||||
|
||||
public byte FlowUnits
|
||||
{
|
||||
get => this.bytes[8].GetUint8(0, 4);
|
||||
set => this.bytes[8].SetUint8(0, 4, value);
|
||||
}
|
||||
|
||||
public byte FlowRate
|
||||
{
|
||||
get => this.bytes[8].GetUint8(4, 4);
|
||||
set => this.bytes[8].SetUint8(4, 4, value);
|
||||
}
|
||||
|
||||
public sbyte FactoryCorrection
|
||||
{
|
||||
get => (sbyte)this.bytes[9];
|
||||
set => this.bytes[9] = (byte)value;
|
||||
}
|
||||
|
||||
public sbyte FieldCorrection
|
||||
{
|
||||
get => (sbyte)this.bytes[10];
|
||||
set => this.bytes[10] = (byte)value;
|
||||
}
|
||||
|
||||
public byte PulseWeight
|
||||
{
|
||||
get => this.bytes[11];
|
||||
set => this.bytes[11] = value;
|
||||
}
|
||||
|
||||
public byte PulseWidth
|
||||
{
|
||||
get => this.bytes[12].GetUint8(0, 3);
|
||||
set => this.bytes[12].SetUint8(0, 3, value);
|
||||
}
|
||||
|
||||
public byte PulseUpdate
|
||||
{
|
||||
get => this.bytes[12].GetUint8(3, 3);
|
||||
set => this.bytes[12].SetUint8(3, 3, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>OmniPlus</RootNamespace>
|
||||
<AssemblyName>OmniPlus</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
|
||||
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<Deterministic>true</Deterministic>
|
||||
<TargetFrameworkProfile />
|
||||
@@ -22,6 +22,7 @@
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
@@ -30,6 +31,7 @@
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
@@ -50,7 +52,8 @@
|
||||
<Compile Include="Features\ASCIIString.cs" />
|
||||
<Compile Include="Features\BatteryVoltage.cs" />
|
||||
<Compile Include="Features\BuildInfo.cs" />
|
||||
<Compile Include="Features\ChamberCalibration.cs" />
|
||||
<Compile Include="Features\ChamberCalibrationRequest.cs" />
|
||||
<Compile Include="Features\ChamberCalibrationResponse.cs" />
|
||||
<Compile Include="Features\ConfigurationParameters.cs" />
|
||||
<Compile Include="Features\CustomerText.cs" />
|
||||
<Compile Include="Features\DeviceID.cs" />
|
||||
@@ -89,6 +92,7 @@
|
||||
<Compile Include="OmniPlusDatabase.cs" />
|
||||
<Compile Include="OmniPlusExtensions.cs" />
|
||||
<Compile Include="OmniPlusConstants.cs" />
|
||||
<Compile Include="OmniPlusTest.cs" />
|
||||
<Compile Include="OmniPlusTestPoint.cs" />
|
||||
<Compile Include="OmniPlusMeter.cs" />
|
||||
<Compile Include="OmniPlusStateChanged.cs" />
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
using OmniPlus.Features;
|
||||
using OmniPlus.Hanlers;
|
||||
|
||||
using System;
|
||||
|
||||
using static OmniPlus.Features.Features;
|
||||
|
||||
namespace OmniPlus.Connections
|
||||
@@ -242,23 +240,23 @@ namespace OmniPlus.Connections
|
||||
return new FeatureResponse(response);
|
||||
}
|
||||
|
||||
public ChamberCalibration StartChamberCalibration(ushort rotations, ushort duration)
|
||||
public ChamberCalibrationRequest StartChamberCalibration(ushort rotations, ushort duration)
|
||||
{
|
||||
var response = this.MessageHandler.Invoke(new ChamberCalibration
|
||||
var response = this.MessageHandler.Invoke(new ChamberCalibrationRequest
|
||||
{
|
||||
Rotations = rotations,
|
||||
Duration = duration,
|
||||
Control = ChamberCalibration.ACTIVATE_TEST
|
||||
Control = ChamberCalibrationRequest.ACTIVATE_TEST
|
||||
});
|
||||
|
||||
return new ChamberCalibration(response);
|
||||
return new ChamberCalibrationRequest(response);
|
||||
}
|
||||
|
||||
public ChamberCalibration ViewChamberCalibration()
|
||||
public ChamberCalibrationResponse ViewChamberCalibration()
|
||||
{
|
||||
var response = this.MessageHandler.Invoke(DEVICE_SPECIFIC, CHAMBER_CALIBRATION, ChamberCalibration.REQUEST_RESULTS);
|
||||
var response = this.MessageHandler.Invoke(DEVICE_SPECIFIC, CHAMBER_CALIBRATION, ChamberCalibrationRequest.REQUEST_RESULTS);
|
||||
|
||||
return new ChamberCalibration(response);
|
||||
return new ChamberCalibrationResponse(response);
|
||||
}
|
||||
|
||||
internal SystemTime ViewSystemTime()
|
||||
@@ -268,14 +266,35 @@ namespace OmniPlus.Connections
|
||||
return new SystemTime(response);
|
||||
}
|
||||
|
||||
internal FeatureResponse SetSystemTime(SystemTime systemTime = null)
|
||||
internal FeatureResponse SetSystemTime(SystemTime request = null)
|
||||
{
|
||||
if (systemTime is null)
|
||||
if (request is null)
|
||||
{
|
||||
systemTime = new SystemTime();
|
||||
request = new SystemTime();
|
||||
}
|
||||
|
||||
var response = this.MessageHandler.Invoke(systemTime[DEVICE_SPECIFIC, SET_SYSTEM_TIME]);
|
||||
var response = this.MessageHandler.Invoke(request[DEVICE_SPECIFIC, SET_SYSTEM_TIME]);
|
||||
|
||||
return new FeatureResponse(response);
|
||||
}
|
||||
|
||||
internal RegisterSettings ViewRegisterSettings()
|
||||
{
|
||||
var response = this.MessageHandler.Invoke(DEVICE_SPECIFIC, VIEW_REGISTER_SETTINGS);
|
||||
|
||||
return new RegisterSettings(response);
|
||||
}
|
||||
|
||||
internal FeatureResponse ViewRegisterSettings(FeatureRequest request)
|
||||
{
|
||||
var response = this.MessageHandler.Invoke(request[DEVICE_SPECIFIC, SET_REGISTER_SETTINGS]);
|
||||
|
||||
return new RegisterSettings(response);
|
||||
}
|
||||
|
||||
internal FeatureResponse SetRegisterSettings(RegisterSettings request)
|
||||
{
|
||||
var response = this.MessageHandler.Invoke(request[DEVICE_SPECIFIC, SET_REGISTER_SETTINGS]);
|
||||
|
||||
return new FeatureResponse(response);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using OmniPlus.Connections;
|
||||
using OmniPlus.Enums;
|
||||
using OmniPlus.Features;
|
||||
|
||||
using System;
|
||||
@@ -20,6 +21,7 @@ namespace OmniPlus
|
||||
private readonly OmniPlusType omniType;
|
||||
|
||||
private byte size;
|
||||
private string variant;
|
||||
|
||||
public OmniPlusConnectionsPool(string dbConnectionString)
|
||||
{
|
||||
@@ -27,7 +29,9 @@ namespace OmniPlus
|
||||
this.meters = new ConcurrentDictionary<int, OmniPlusMeter>();
|
||||
this.database = new OmniPlusDatabase(dbConnectionString);
|
||||
this.omniType = new OmniPlusType();
|
||||
|
||||
this.size = 5;
|
||||
this.variant = "C2";
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
@@ -63,18 +67,20 @@ namespace OmniPlus
|
||||
{
|
||||
OmniPlusConnection connection;
|
||||
OmniPlusMeter meter;
|
||||
var position = 1;
|
||||
var connected = true;
|
||||
int position = 1;
|
||||
bool connected;
|
||||
|
||||
foreach (var portName in portNames)
|
||||
{
|
||||
connection = new OmniPlusConnection(portName);
|
||||
connected = connection.ConnectIrda();
|
||||
meter = new OmniPlusMeter();
|
||||
|
||||
if (connected)
|
||||
{
|
||||
meter.Connected = true;
|
||||
meter = new OmniPlusMeter
|
||||
{
|
||||
Connected = connected
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -92,7 +98,7 @@ namespace OmniPlus
|
||||
position++;
|
||||
}
|
||||
|
||||
this.database.LoadOmniPlusType(this.size, this.omniType);
|
||||
this.database.LoadOmniPlusType(this.size, this.variant, this.omniType);
|
||||
}
|
||||
|
||||
public void StartInspection()
|
||||
@@ -105,53 +111,47 @@ namespace OmniPlus
|
||||
tasks[position - 1] = Task.Factory.StartNew(() => this.StartOmniInitialization(position));
|
||||
}
|
||||
|
||||
Task.Factory
|
||||
.ContinueWhenAll(tasks, _ => { })
|
||||
.Wait();
|
||||
tasks.ContinueWhenAll();
|
||||
|
||||
foreach (var point in this.omniType.TestPoints)
|
||||
{
|
||||
// TODO: Request and wait for volume.
|
||||
// TODO: Request and wait for flow.
|
||||
|
||||
tasks = new Task[connectionsCount];
|
||||
|
||||
foreach (var position in this.connections.Keys)
|
||||
{
|
||||
tasks[position - 1] = Task.Factory.StartNew(() => this.StartOmniCalibration(position, point));
|
||||
tasks[position - 1] = Task.Factory.StartNew(() => this.StartOmniInspection(position, point));
|
||||
}
|
||||
|
||||
Task.Factory
|
||||
.ContinueWhenAll(tasks, _ => { })
|
||||
.Wait();
|
||||
tasks.ContinueWhenAll();
|
||||
|
||||
// TODO: Request reference volume.
|
||||
var volume = 0D;
|
||||
// TODO: Request and wait for volume.
|
||||
var volumeMessured = 0.1D;
|
||||
|
||||
foreach (var meter in this.meters.Values)
|
||||
foreach (var position in this.connections.Keys)
|
||||
{
|
||||
// TODO: meter.AddInspectionVolume(point, volume);
|
||||
this.SetPointDifference(position, point, volumeMessured);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var position in this.connections.Keys)
|
||||
{
|
||||
this.GetCorrectionFactor(position);
|
||||
}
|
||||
|
||||
tasks = new Task[connectionsCount];
|
||||
|
||||
foreach (var position in this.connections.Keys)
|
||||
{
|
||||
tasks[position - 1] = Task.Factory.StartNew(() => this.CalibrateMeter(position));
|
||||
tasks[position - 1] = Task.Factory.StartNew(() => this.FinishOmniInspection(position));
|
||||
}
|
||||
|
||||
Task.Factory
|
||||
.ContinueWhenAll(tasks, _ => { })
|
||||
.Wait();
|
||||
|
||||
//this.FinishOmniInspection();
|
||||
tasks.ContinueWhenAll();
|
||||
}
|
||||
|
||||
private void StartOmniInitialization(int position)
|
||||
{
|
||||
this.StateChanged?.Invoke(position, null, FIRMWARE, null);
|
||||
this.StateChanged?.Invoke(position, null, BUILD_INFO, null);
|
||||
|
||||
if (this.TryGetOmni(position, out var connection, out var meter))
|
||||
{
|
||||
this.StateChanged?.Invoke(position, null, FIRMWARE, TBD);
|
||||
@@ -165,45 +165,34 @@ namespace OmniPlus
|
||||
this.database.AddOrUpdate(position, systemParameters);
|
||||
}
|
||||
|
||||
connection.SetInputVolume(this.omniType.InputVolume);
|
||||
meter.CanCalibrate = connection.SetInputVolume(this.omniType.InputVolume).Succeeded;
|
||||
|
||||
this.StateChanged?.Invoke(position, meter.FirmwareInRange, FIRMWARE, meter.Firmware);
|
||||
this.StateChanged?.Invoke(position, !string.IsNullOrWhiteSpace(meter.BuildInfo), BUILD_INFO, meter.BuildInfo);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.StateChanged?.Invoke(position, null, FIRMWARE, null);
|
||||
this.StateChanged?.Invoke(position, null, BUILD_INFO, null);
|
||||
}
|
||||
}
|
||||
|
||||
private void StartOmniCalibration(int position, OmniPlusTestPoint point)
|
||||
private void StartOmniInspection(int position, OmniPlusTestPoint point)
|
||||
{
|
||||
var header = $"{point.VolumeM3H:0.0000} m³/h";
|
||||
this.StateChanged?.Invoke(position, null, header, null);
|
||||
var header = $"{point.VolumeM3H:0.0000}m³/h";
|
||||
|
||||
if (this.TryGetOmni(position, out var connection, out var meter) && meter.Initialized)
|
||||
if (this.TryGetOmni(position, out var connection, out var meter) && meter.Initialized && meter.CanCalibrate)
|
||||
{
|
||||
this.StateChanged?.Invoke(position, null, header, TBD);
|
||||
|
||||
var activationResponse = connection.StartChamberCalibration(point.Rotations, point.Duration);
|
||||
var calibrationResult = default(ChamberCalibration);
|
||||
|
||||
if (activationResponse.Succeeded)
|
||||
{
|
||||
var progress = 0;
|
||||
this.NotifyTimeProgress(position, header, point.Duration);
|
||||
var calibrationResult = new ChamberCalibrationResponse();
|
||||
var duration = point.Duration + 3;
|
||||
|
||||
progress = 10;
|
||||
|
||||
this.StateChanged?.Invoke(position, true, header, $"{progress}%");
|
||||
|
||||
//0x00 indicates that the parameters are valid and test will start 3 seconds after the response.
|
||||
Thread.Sleep(3000);
|
||||
|
||||
progress += 10;
|
||||
this.StateChanged?.Invoke(position, true, header, $"{progress}%");
|
||||
|
||||
// waiting all the secconds to execute test
|
||||
Thread.Sleep(point.Duration * 1000);
|
||||
|
||||
progress += 70;
|
||||
this.StateChanged?.Invoke(position, true, header, $"{progress}%");
|
||||
|
||||
var delay = (int)(point.Duration * 0.1) * 1000;
|
||||
this.NotifyWhileThreadSleep(position, header, point.Duration + 3);
|
||||
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
@@ -214,71 +203,78 @@ namespace OmniPlus
|
||||
break;
|
||||
}
|
||||
|
||||
Thread.Sleep(delay);
|
||||
|
||||
progress += 3;
|
||||
this.StateChanged?.Invoke(position, true, header, $"{progress}%");
|
||||
Thread.Sleep(1000);
|
||||
}
|
||||
|
||||
if (calibrationResult?.Succeeded == true)
|
||||
if (!calibrationResult.Succeeded)
|
||||
{
|
||||
if (calibrationResult.Control == ChamberCalibration.TEST_COMPLETED)
|
||||
{
|
||||
this.StateChanged?.Invoke(position, true, header, $"100%");
|
||||
}
|
||||
else // calibration timeout or not ready but exceeds the 3s + seconds to run + 0.3%
|
||||
{
|
||||
this.StateChanged?.Invoke(position, false, header, X);
|
||||
}
|
||||
this.StateChanged?.Invoke(position, false, header, $"CC: {calibrationResult.Status}");
|
||||
}
|
||||
else // calibration failed
|
||||
else if (calibrationResult.Control != ChamberCalibrationResponse.TEST_COMPLETED)
|
||||
{
|
||||
this.StateChanged?.Invoke(position, false, header, "n/a");
|
||||
this.StateChanged?.Invoke(position, false, header, $"CC: {calibrationResult.Control}");
|
||||
}
|
||||
else // process calibration
|
||||
{
|
||||
var volume = meter.AddCalibrationResult(point, calibrationResult);
|
||||
|
||||
this.StateChanged?.Invoke(position, null, header, $"{volume:0.0000}m³");
|
||||
}
|
||||
}
|
||||
else // activation failed
|
||||
{
|
||||
this.StateChanged?.Invoke(position, false, header, "n/a");
|
||||
this.StateChanged?.Invoke(position, false, header, $"AC: {activationResponse.Status}");
|
||||
}
|
||||
|
||||
meter.AddCalibrationResult(point, calibrationResult);
|
||||
}
|
||||
else // not connected
|
||||
{
|
||||
this.StateChanged?.Invoke(position, null, header, null);
|
||||
}
|
||||
}
|
||||
|
||||
private void CalibrateMeter(int position)
|
||||
private void SetPointDifference(int position, OmniPlusTestPoint point, double volume)
|
||||
{
|
||||
if (this.TryGetOmni(position, out var connection, out var meter))
|
||||
{
|
||||
var correctionFactor = 0D;
|
||||
// TODO: var correctionFactor = meter.CalculateCorrectionFactor();
|
||||
var header = $"{point.VolumeM3H:0.0000}m³/h";
|
||||
|
||||
this.StateChanged?.Invoke(position, meter.Calibrated, CORRECTION, $"{correctionFactor:0.00}%");
|
||||
if (this.TryGetOmni(position, out var connection, out var meter) && meter.Initialized && meter.CanCalibrate)
|
||||
{
|
||||
var difference = meter.AddCalibrationVolume(point, volume);
|
||||
|
||||
this.StateChanged?.Invoke(position, null, header, $"{difference:0.00}%");
|
||||
}
|
||||
else // meter or connection not in use
|
||||
else // not connected
|
||||
{
|
||||
this.StateChanged?.Invoke(position, null, header, null);
|
||||
}
|
||||
}
|
||||
|
||||
private void GetCorrectionFactor(int position)
|
||||
{
|
||||
if (this.TryGetOmni(position, out var connection, out var meter) && meter.Initialized && meter.CanCalibrate)
|
||||
{
|
||||
var correctionFactor = meter.GetCorrectionFactor();
|
||||
|
||||
this.StateChanged?.Invoke(position, meter.CanCalibrate, CORRECTION, $"{correctionFactor:0.00}%");
|
||||
}
|
||||
else // not connected
|
||||
{
|
||||
this.StateChanged?.Invoke(position, null, CORRECTION, null);
|
||||
}
|
||||
}
|
||||
|
||||
private void FinishOmniInspection()
|
||||
{
|
||||
var tasks = new Task[this.connections.Count];
|
||||
|
||||
foreach (var position in this.connections.Keys)
|
||||
{
|
||||
tasks[position - 1] = Task.Factory.StartNew(() => this.FinishOmniInspection(position));
|
||||
}
|
||||
|
||||
Task.Factory.ContinueWhenAll(tasks, _ => { });
|
||||
}
|
||||
|
||||
private void FinishOmniInspection(int position)
|
||||
{
|
||||
if (this.TryGetOmni(position, out var connection, out var meter))
|
||||
if (this.TryGetOmni(position, out var connection, out var meter) && meter.Calibrated)
|
||||
{
|
||||
var configurationParameters = connection.ViewConfigurationParameters();
|
||||
var canContinue = configurationParameters.Succeeded;
|
||||
|
||||
if (canContinue)
|
||||
{
|
||||
meter.AddConfigurationParameters(configurationParameters);
|
||||
this.database.AddOrUpdate(position, configurationParameters);
|
||||
}
|
||||
|
||||
if (canContinue)
|
||||
{
|
||||
var systemTimeReset = connection.SetSystemTime();
|
||||
@@ -287,7 +283,29 @@ namespace OmniPlus
|
||||
|
||||
if (canContinue)
|
||||
{
|
||||
// TODO: var registerSettings = connection.ViewRegisterSettings();
|
||||
var registerSettings = connection.ViewRegisterSettings();
|
||||
|
||||
registerSettings.IntPart = this.omniType.IntPart;
|
||||
registerSettings.Fraction = this.omniType.Fraction;
|
||||
registerSettings.Size = this.omniType.Size;
|
||||
registerSettings.Range = this.omniType.Range;
|
||||
registerSettings.VolumePerPulseUnit = 0x00;
|
||||
registerSettings.MeterUnits = (byte)MessurementUnits.USGallons;
|
||||
registerSettings.FlowUnits = (byte)MessurementUnits.USGallons;
|
||||
registerSettings.FlowRate = (byte)TimeUnits.Minutes;
|
||||
registerSettings.FactoryCorrection = meter.FactoryCorrection;
|
||||
registerSettings.FieldCorrection = 0x00;
|
||||
registerSettings.PulseWeight = 0x01;
|
||||
registerSettings.PulseWidth = 0x02;
|
||||
registerSettings.PulseUpdate = 0x00;
|
||||
|
||||
var response = connection.SetRegisterSettings(registerSettings);
|
||||
canContinue = response.Succeeded;
|
||||
}
|
||||
|
||||
if (canContinue)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
else // meter or connection not in use
|
||||
@@ -315,15 +333,19 @@ namespace OmniPlus
|
||||
&& meter.Connected;
|
||||
}
|
||||
|
||||
private void NotifyTimeProgress(int position, string header, int duration)
|
||||
private void NotifyWhileThreadSleep(int position, string header, int duration)
|
||||
{
|
||||
var progress = 0;
|
||||
var seconds = 0;
|
||||
var timer = new System.Timers.Timer(1000)
|
||||
{
|
||||
Enabled = true,
|
||||
AutoReset = true,
|
||||
};
|
||||
timer.Elapsed += (_, _1) => this.StateChanged?.Invoke(position, null, header, $"{progress++}/{duration}");
|
||||
timer.Elapsed += (_, _1) =>
|
||||
{
|
||||
this.StateChanged?.Invoke(position, null, header, $"{seconds++}/{duration}");
|
||||
};
|
||||
|
||||
timer.Start();
|
||||
|
||||
Thread.Sleep(duration * 1000);
|
||||
|
||||
@@ -14,8 +14,9 @@
|
||||
public const string BUILD_INFO = "Build-Info";
|
||||
public const string ML_PER_ROTATION = "Ml/Rotation";
|
||||
public const string CORRECTION = "Korrekturfaktor";
|
||||
public const string DIFFERENCE = "Abweichung";
|
||||
|
||||
public const string TBD = "wird ermittelt";
|
||||
public const string TBD = "wird ermittelt ...";
|
||||
public const string OK = "OK";
|
||||
public const string X = "x";
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ namespace OmniPlus
|
||||
public OmniPlusDatabase(string omniDatabase)
|
||||
=> this.connectionString = omniDatabase;
|
||||
|
||||
internal void AddOrUpdate(int position, SystemParameters systemParameters)
|
||||
internal void AddOrUpdate(int position, SystemParameters parameters)
|
||||
{
|
||||
using (var sqlConnection = new SqlConnection(this.connectionString))
|
||||
{
|
||||
@@ -32,23 +32,70 @@ namespace OmniPlus
|
||||
{
|
||||
sqlCommand.CommandText = $@"
|
||||
UPDATE [OmniTestStates]
|
||||
SET [BuildInfo] = @{nameof(systemParameters.BuildInfo)}
|
||||
, [ManifacturingTime] = @{nameof(systemParameters.ManifacturingTime)}
|
||||
, [RebootsCount] = @{nameof(systemParameters.RebootsCount)}
|
||||
, [VersionAndType] = @{nameof(systemParameters.VersionAndType)}
|
||||
SET [BuildInfo] = @{nameof(parameters.BuildInfo)}
|
||||
, [ManifacturingTime] = @{nameof(parameters.ManifacturingTime)}
|
||||
, [RebootsCount] = @{nameof(parameters.RebootsCount)}
|
||||
, [VersionAndType] = @{nameof(parameters.VersionAndType)}
|
||||
WHERE [Position] = @{nameof(position)}";
|
||||
sqlCommand.Parameters.Add(new SqlParameter(nameof(position), position));
|
||||
sqlCommand.Parameters.Add(new SqlParameter(nameof(systemParameters.VersionAndType), systemParameters.VersionAndType.Value));
|
||||
sqlCommand.Parameters.Add(new SqlParameter(nameof(systemParameters.RebootsCount), systemParameters.RebootsCount));
|
||||
sqlCommand.Parameters.Add(new SqlParameter(nameof(systemParameters.ManifacturingTime), systemParameters.ManifacturingTime.DateTime));
|
||||
sqlCommand.Parameters.Add(new SqlParameter(nameof(systemParameters.BuildInfo), systemParameters.BuildInfo.Value));
|
||||
sqlCommand.Parameters.Add(new SqlParameter(nameof(parameters.VersionAndType), parameters.VersionAndType.Value));
|
||||
sqlCommand.Parameters.Add(new SqlParameter(nameof(parameters.RebootsCount), parameters.RebootsCount));
|
||||
sqlCommand.Parameters.Add(new SqlParameter(nameof(parameters.ManifacturingTime), parameters.ManifacturingTime.DateTime));
|
||||
sqlCommand.Parameters.Add(new SqlParameter(nameof(parameters.BuildInfo), parameters.BuildInfo.Value));
|
||||
sqlCommand.ExecuteNonQuery();
|
||||
sqlCommand.Parameters.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal void LoadOmniPlusType(byte size, OmniPlusType omniType)
|
||||
internal void AddOrUpdate(int position, ConfigurationParameters parameters)
|
||||
{
|
||||
using (var sqlConnection = new SqlConnection(this.connectionString))
|
||||
{
|
||||
sqlConnection.OpenConnection();
|
||||
|
||||
using (var sqlCommand = sqlConnection.CreateCommand())
|
||||
{
|
||||
sqlCommand.CommandText = $@"
|
||||
INSERT
|
||||
INTO [OmniTestStates] ([Position])
|
||||
VALUES (@{nameof(position)})";
|
||||
sqlCommand.Parameters.Add(new SqlParameter(nameof(position), position));
|
||||
sqlCommand.ExecuteNonQuery();
|
||||
sqlCommand.Parameters.Clear();
|
||||
}
|
||||
|
||||
using (var sqlCommand = sqlConnection.CreateCommand())
|
||||
{
|
||||
sqlCommand.CommandText = $@"
|
||||
UPDATE [OmniTestStates]
|
||||
SET [ProgrammableID] = @{nameof(parameters.ProgrammableID)}
|
||||
, [FactoryID] = @{nameof(parameters.FactoryID)}
|
||||
, [ReadingDigitsCount] = @{nameof(parameters.ReadingDigits.Count)}
|
||||
, [ReadingDigitsOffsest] = @{nameof(parameters.ReadingDigits.Offset)}
|
||||
, [Readings] = @{nameof(parameters.Readings)}
|
||||
, [OptionalUniDirFields] = @{nameof(parameters.OptionalUniDirFields)}
|
||||
, [AlarmPersitenceDays] = @{nameof(parameters.AlartPersistenceDays)}
|
||||
, [DataLogIntervalMins] = @{nameof(parameters.DataLogIntervalMins)}
|
||||
, [DeviceID] = @{nameof(parameters.DeviceID)}
|
||||
WHERE [Position] = @{nameof(position)}";
|
||||
sqlCommand.Parameters.Add(new SqlParameter(nameof(position), position));
|
||||
sqlCommand.Parameters.Add(new SqlParameter(nameof(parameters.ProgrammableID), parameters.ProgrammableID.Value));
|
||||
sqlCommand.Parameters.Add(new SqlParameter(nameof(parameters.FactoryID), parameters.FactoryID.Value));
|
||||
sqlCommand.Parameters.Add(new SqlParameter(nameof(parameters.ReadingDigits.Count), parameters.ReadingDigits.Count));
|
||||
sqlCommand.Parameters.Add(new SqlParameter(nameof(parameters.ReadingDigits.Offset), parameters.ReadingDigits.Offset));
|
||||
sqlCommand.Parameters.Add(new SqlParameter(nameof(parameters.Readings), parameters.Readings.Value));
|
||||
sqlCommand.Parameters.Add(new SqlParameter(nameof(parameters.OptionalUniDirFields), parameters.OptionalUniDirFields));
|
||||
sqlCommand.Parameters.Add(new SqlParameter(nameof(parameters.AlartPersistenceDays), parameters.AlartPersistenceDays));
|
||||
sqlCommand.Parameters.Add(new SqlParameter(nameof(parameters.DataLogIntervalMins), parameters.DataLogIntervalMins));
|
||||
sqlCommand.Parameters.Add(new SqlParameter(nameof(parameters.DeviceID), parameters.DeviceID.Value));
|
||||
sqlCommand.ExecuteNonQuery();
|
||||
sqlCommand.Parameters.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal void LoadOmniPlusType(byte size, string variant, OmniPlusType omniType)
|
||||
{
|
||||
using (var sqlConnection = new SqlConnection(this.connectionString))
|
||||
{
|
||||
@@ -65,7 +112,8 @@ namespace OmniPlus
|
||||
, [Direction]
|
||||
, [IntPart]
|
||||
, [Fraction]
|
||||
, [MlPerPulse] * [PulsePerRotation]
|
||||
, [PulsePerRotation]
|
||||
, [CorrectionFactor]
|
||||
FROM [OmniTestTypes]
|
||||
WHERE [Size] = @{nameof(size)}";
|
||||
sqlCommand.Parameters.Add(new SqlParameter(nameof(size), size));
|
||||
@@ -82,7 +130,8 @@ namespace OmniPlus
|
||||
omniType.Direction = sqlDataReader.GetValue<byte>(field++);
|
||||
omniType.IntPart = sqlDataReader.GetValue<byte>(field++);
|
||||
omniType.Fraction = (ushort)sqlDataReader.GetValue<int>(field++);
|
||||
omniType.MlPerRotation = sqlDataReader.GetValue<double>(field++);
|
||||
omniType.PulsePerRotation = sqlDataReader.GetValue<double>(field++);
|
||||
omniType.CorrectionFactor = sqlDataReader.GetValue<short>(field++);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -90,26 +139,35 @@ namespace OmniPlus
|
||||
using (var sqlCommand = sqlConnection.CreateCommand())
|
||||
{
|
||||
sqlCommand.CommandText = $@"
|
||||
SELECT [M3PerHour]
|
||||
SELECT [GalPerMin]
|
||||
, [Rotations]
|
||||
, [Duration]
|
||||
, [MinDiff]
|
||||
, [MaxDiff]
|
||||
FROM [OmniTestPoints]
|
||||
WHERE [OmniTypeId] = @{nameof(omniType.OmniId)}
|
||||
AND [Enabled] = 1
|
||||
WHERE [OmniTypeId] = @{nameof(omniType.OmniId)}
|
||||
AND [OmniVariant] = @{nameof(variant)}
|
||||
AND [MinDiff] IS NOT NULL
|
||||
ORDER BY [GalPerMin] ASC";
|
||||
sqlCommand.Parameters.Add(new SqlParameter(nameof(omniType.OmniId), omniType.OmniId));
|
||||
sqlCommand.Parameters.Add(new SqlParameter(nameof(variant), variant));
|
||||
|
||||
using (var sqlDataReader = sqlCommand.ExecuteReader())
|
||||
{
|
||||
var mlPerRotation = omniType.MlPerRotation;
|
||||
|
||||
while (sqlDataReader.Read())
|
||||
{
|
||||
field = 0;
|
||||
|
||||
omniType.TestPoints.Add(new OmniPlusTestPoint
|
||||
{
|
||||
VolumeM3H = sqlDataReader.GetValue<double>(field++),
|
||||
MlPerRotation = mlPerRotation,
|
||||
GalPerMin = sqlDataReader.GetValue<double>(field++),
|
||||
Rotations = (ushort)sqlDataReader.GetValue<short>(field++),
|
||||
Duration = (ushort)sqlDataReader.GetValue<short>(field++),
|
||||
MinDiff = (ushort)sqlDataReader.GetValue<double>(field++),
|
||||
MaxDiff = (ushort)sqlDataReader.GetValue<double>(field++),
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -117,29 +175,4 @@ namespace OmniPlus
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal static class OmniPlusDatabaseExtensions
|
||||
{
|
||||
public static void OpenConnection(this SqlConnection sqlConnection)
|
||||
{
|
||||
sqlConnection.FireInfoMessageEventOnUserErrors = true;
|
||||
sqlConnection.InfoMessage += SqlConnection_InfoMessage;
|
||||
sqlConnection.Open();
|
||||
}
|
||||
|
||||
private static void SqlConnection_InfoMessage(object _1, SqlInfoMessageEventArgs args)
|
||||
{
|
||||
System.Console.WriteLine(args.Message);
|
||||
}
|
||||
|
||||
public static T GetValue<T>(this SqlDataReader reader, int field)
|
||||
{
|
||||
if (!reader.IsDBNull(field) && reader.GetValue(field) is T value)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
return default(T);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,6 @@ CREATE TABLE [OmniTestTypes] (
|
||||
[Fraction] INT NOT NULL,
|
||||
[CorrectionFactor] SMALLINT NOT NULL,
|
||||
[PulsePerRotation] TINYINT NOT NULL,
|
||||
[MlPerPulse] FLOAT NULL
|
||||
CONSTRAINT [PK_OmniTestTypes_Id] PRIMARY KEY ([Id])
|
||||
);
|
||||
|
||||
@@ -28,16 +27,15 @@ VALUES ( '1½"', 0x05, 0x00, 0x00, 0x00, 34017,
|
||||
, ( '8"', 0x0A, 0x03, 0x80, 0x01, 36814, 1000, 8)
|
||||
, ( '10"', 0x0B, 0x04, 0x80, 0x02, 21667, 1000, 8);
|
||||
|
||||
UPDATE [OmniTestTypes] SET [MlPerPulse] = ([IntPart] + [Fraction] / 65535.0) * [CorrectionFactor];
|
||||
|
||||
CREATE TABLE [OmniTestPoints] (
|
||||
[Id] SMALLINT NOT NULL IDENTITY(1, 1),
|
||||
[OmniTypeId] TINYINT NOT NULL,
|
||||
[OmniVariant] CHAR(2) NULL,
|
||||
[GalPerMin] FLOAT NOT NULL,
|
||||
[M3PerHour] FLOAT NULL,
|
||||
[Rotations] SMALLINT NOT NULL,
|
||||
[Duration] SMALLINT NOT NULL,
|
||||
[Enabled] BIT NOT NULL DEFAULT(0)
|
||||
[MinDiff] FLOAT NULL,
|
||||
[MaxDiff] FLOAT NULL,
|
||||
CONSTRAINT [PK_OmniTestPoints_Id] PRIMARY KEY ([Id]),
|
||||
CONSTRAINT [FK_OmniTestPoints_OmniTypeId_OmniPlus_Id] FOREIGN KEY ([OmniTypeId]) REFERENCES [OmniTestTypes]([Id]),
|
||||
CONSTRAINT [CHK_OmniTestPoints_Rotations] CHECK ([Rotations] BETWEEN 1 AND 5000),
|
||||
@@ -45,88 +43,137 @@ CREATE TABLE [OmniTestPoints] (
|
||||
);
|
||||
|
||||
INSERT INTO [OmniTestPoints]
|
||||
([OmniTypeId], [GalPerMin], [Rotations], [Duration])
|
||||
------------------------------------------------------
|
||||
VALUES ( 1, 200.00, 900, 36)
|
||||
, ( 1, 160.00, 700, 35)
|
||||
, ( 1, 150.00, 600, 32)
|
||||
, ( 1, 2.50, 10, 32)
|
||||
, ( 1, 2.00, 8, 32)
|
||||
, ( 1, 1.50, 6, 32)
|
||||
, ( 1, 1.25, 6, 38)
|
||||
, ( 1, 1.00, 4, 32)
|
||||
, ( 1, 0.75, 4, 43)
|
||||
, ( 1, 0.25, 4, 127)
|
||||
------------------------------------------------------
|
||||
, ( 2, 200.00, 1000, 40)
|
||||
, ( 2, 160.00, 800, 40)
|
||||
, ( 2, 2.50, 10, 32)
|
||||
, ( 2, 1.50, 8, 43)
|
||||
, ( 2, 0.25, 4, 127)
|
||||
------------------------------------------------------
|
||||
, ( 3, 500.00, 700, 38)
|
||||
, ( 3, 400.00, 580, 40)
|
||||
, ( 3, 350.00, 450, 35)
|
||||
, ( 3, 20.00, 30, 41)
|
||||
, ( 3, 10.00, 16, 44)
|
||||
, ( 3, 2.50, 4, 44)
|
||||
, ( 3, 2.00, 4, 55)
|
||||
, ( 3, 1.50, 4, 73)
|
||||
, ( 3, 0.50, 4, 217)
|
||||
------------------------------------------------------
|
||||
, ( 4, 1000.00, 1200, 33)
|
||||
, ( 4, 800.00, 1100, 38)
|
||||
, ( 4, 30.00, 40, 37)
|
||||
, ( 4, 3.00, 4, 37)
|
||||
, ( 4, 2.00, 4, 55)
|
||||
, ( 4, 1.50, 4, 73)
|
||||
, ( 4, 0.75, 4, 145)
|
||||
------------------------------------------------------
|
||||
, ( 5, 2000.00, 800, 39)
|
||||
, ( 5, 1600.00, 660, 40)
|
||||
, ( 5, 50.00, 20, 39)
|
||||
, ( 5, 5.00, 4, 77)
|
||||
, ( 5, 4.00, 4, 96)
|
||||
, ( 5, 3.00, 4, 127)
|
||||
, ( 5, 2.50, 4, 153)
|
||||
, ( 5, 1.50, 4, 254)
|
||||
------------------------------------------------------
|
||||
, ( 6, 3500.00, 500, 34)
|
||||
, ( 6, 2700.00, 400, 36)
|
||||
, ( 6, 7.00, 4, 136)
|
||||
, ( 6, 5.00, 4, 191)
|
||||
, ( 6, 4.00, 4, 238)
|
||||
, ( 6, 3.00, 4, 317)
|
||||
, ( 6, 2.50, 4, 381)
|
||||
------------------------------------------------------
|
||||
, ( 7, 5500.00, 550, 36)
|
||||
, ( 7, 4000.00, 400, 36)
|
||||
, ( 7, 2500.00, 260, 37)
|
||||
, ( 7, 14.00, 4, 102)
|
||||
, ( 7, 5.00, 4, 284)
|
||||
, ( 7, 3.50, 4, 406);
|
||||
|
||||
UPDATE [OmniTestPoints]
|
||||
SET [Enabled] = 1
|
||||
--------------------------------ml. in Gal--------l-----m³---min. in hour
|
||||
, [M3PerHour] = ([GalPerMin] * 3785.411784) / 1000 / 1000 * 60 --------
|
||||
FROM [OmniTestPoints] AS [Current]
|
||||
JOIN (SELECT [OmniTypeId] AS [TypeId]
|
||||
, MIN([GalPerMin]) AS [Min]
|
||||
, MAX([GalPerMin]) AS [Max]
|
||||
FROM [OmniTestPoints]
|
||||
GROUP BY [OmniTypeId])
|
||||
AS [Aggregated]
|
||||
ON [Aggregated].[TypeId] = [Current].[OmniTypeId]
|
||||
AND ([Aggregated].[Min] = [Current].[GalPerMin]
|
||||
OR [Aggregated].[Max] = [Current].[GalPerMin]);
|
||||
([OmniTypeId], [OmniVariant], [GalPerMin], [Rotations], [Duration], [MinDiff], [MaxDiff])
|
||||
------------------------------------------------------------------------------------------
|
||||
VALUES ( 1, 'C2', 200.00, 900, 36, NULL, NULL)
|
||||
, ( 1, 'C2', 160.00, 700, 35, 98.5, 101.5)
|
||||
, ( 1, 'C2', 150.00, 600, 32, NULL, NULL)
|
||||
, ( 1, 'C2', 2.50, 10, 32, NULL, NULL)
|
||||
, ( 1, 'C2', 2.00, 8, 32, NULL, NULL)
|
||||
, ( 1, 'C2', 1.50, 6, 32, NULL, NULL)
|
||||
, ( 1, 'C2', 1.25, 6, 38, NULL, NULL)
|
||||
, ( 1, 'C2', 1.00, 4, 32, 98.5, 101.5)
|
||||
, ( 1, 'C2', 0.75, 4, 43, NULL, NULL)
|
||||
, ( 1, 'C2', 0.25, 4, 127, 95.0, 101.5)
|
||||
------------------------------------------------------------------------------------------
|
||||
, ( 1, 'F2', 200.00, 900, 36, NULL, NULL)
|
||||
, ( 1, 'F2', 160.00, 700, 35, 98.5, 101.5)
|
||||
, ( 1, 'F2', 150.00, 600, 32, NULL, NULL)
|
||||
, ( 1, 'F2', 2.50, 10, 32, NULL, NULL)
|
||||
, ( 1, 'F2', 2.00, 8, 32, NULL, NULL)
|
||||
, ( 1, 'F2', 1.50, 6, 32, NULL, NULL)
|
||||
, ( 1, 'F2', 1.25, 6, 38, NULL, NULL)
|
||||
, ( 1, 'F2', 1.00, 4, 32, 98.5, 101.5)
|
||||
, ( 1, 'F2', 0.75, 4, 43, NULL, NULL)
|
||||
, ( 1, 'F2', 0.25, 4, 127, 95.0, 101.5)
|
||||
------------------------------------------------------------------------------------------
|
||||
, ( 1, 'R2', 200.00, 900, 36, NULL, NULL)
|
||||
, ( 1, 'R2', 160.00, 700, 35, NULL, NULL)
|
||||
, ( 1, 'R2', 150.00, 600, 32, 98.5, 101.5)
|
||||
, ( 1, 'R2', 2.50, 10, 32, NULL, NULL)
|
||||
, ( 1, 'R2', 2.00, 8, 32, 98.5, 101.5)
|
||||
, ( 1, 'R2', 1.50, 6, 32, NULL, NULL)
|
||||
, ( 1, 'R2', 1.25, 6, 38, NULL, NULL)
|
||||
, ( 1, 'R2', 1.00, 4, 32, NULL, NULL)
|
||||
, ( 1, 'R2', 0.75, 4, 43, 95.0, 101.5)
|
||||
, ( 1, 'R2', 0.25, 4, 127, NULL, NULL)
|
||||
------------------------------------------------------------------------------------------
|
||||
, ( 1, 'T2', 200.00, 900, 36, NULL, NULL)
|
||||
, ( 1, 'T2', 160.00, 700, 35, 98.5, 101.5)
|
||||
, ( 1, 'T2', 150.00, 600, 32, NULL, NULL)
|
||||
, ( 1, 'T2', 2.50, 10, 32, NULL, NULL)
|
||||
, ( 1, 'T2', 2.00, 8, 32, NULL, NULL)
|
||||
, ( 1, 'T2', 1.50, 6, 32, NULL, NULL)
|
||||
, ( 1, 'T2', 1.25, 6, 38, 98.5, 101.5)
|
||||
, ( 1, 'T2', 1.00, 4, 32, NULL, NULL)
|
||||
, ( 1, 'T2', 0.75, 4, 43, 95.0, 101.5)
|
||||
, ( 1, 'T2', 0.25, 4, 127, NULL, NULL)
|
||||
------------------------------------------------------------------------------------------
|
||||
, ( 2, 'C2', 200.00, 1000, 40, NULL, NULL)
|
||||
, ( 2, 'C2', 160.00, 800, 40, 98.5, 101.5)
|
||||
, ( 2, 'C2', 2.50, 10, 32, NULL, NULL)
|
||||
, ( 2, 'C2', 1.50, 8, 43, NULL, NULL)
|
||||
, ( 2, 'C2', 1.00, 4, 32, 98.5, 101.5)
|
||||
, ( 2, 'C2', 0.25, 4, 127, 95.0, 101.5)
|
||||
------------------------------------------------------------------------------------------
|
||||
, ( 2, 'F2', 200.00, 1000, 40, NULL, NULL)
|
||||
, ( 2, 'F2', 160.00, 800, 40, 98.5, 101.5)
|
||||
, ( 2, 'F2', 2.50, 10, 32, NULL, NULL)
|
||||
, ( 2, 'F2', 1.50, 8, 43, NULL, NULL)
|
||||
, ( 2, 'F2', 1.00, 4, 32, 98.5, 101.5)
|
||||
, ( 2, 'F2', 0.25, 4, 127, 95.0, 101.5)
|
||||
------------------------------------------------------------------------------------------
|
||||
, ( 2, 'R2', 200.00, 1000, 40, 98.5, 101.5)
|
||||
, ( 2, 'R2', 160.00, 800, 40, NULL, NULL)
|
||||
, ( 2, 'R2', 2.50, 10, 32, 98.5, 101.5)
|
||||
, ( 2, 'R2', 1.50, 8, 43, NULL, NULL)
|
||||
, ( 2, 'R2', 1.00, 4, 32, 95.0, 101.5)
|
||||
, ( 2, 'R2', 0.25, 4, 127, NULL, NULL)
|
||||
------------------------------------------------------------------------------------------
|
||||
, ( 2, 'T2', 200.00, 1000, 40, 98.5, 101.5)
|
||||
, ( 2, 'T2', 160.00, 800, 40, NULL, NULL)
|
||||
, ( 2, 'T2', 2.50, 10, 32, NULL, NULL)
|
||||
, ( 2, 'T2', 1.50, 8, 43, 98.5, 101.5)
|
||||
, ( 2, 'T2', 1.00, 4, 32, 95.0, 101.5)
|
||||
, ( 2, 'T2', 0.25, 4, 127, NULL, NULL)
|
||||
------------------------------------------------------------------------------------------
|
||||
, ( 3, NULL, 500.00, 700, 38, NULL, NULL)
|
||||
, ( 3, NULL, 400.00, 580, 40, NULL, NULL)
|
||||
, ( 3, NULL, 350.00, 450, 35, NULL, NULL)
|
||||
, ( 3, NULL, 20.00, 30, 41, NULL, NULL)
|
||||
, ( 3, NULL, 10.00, 16, 44, NULL, NULL)
|
||||
, ( 3, NULL, 2.50, 4, 44, NULL, NULL)
|
||||
, ( 3, NULL, 2.00, 4, 55, NULL, NULL)
|
||||
, ( 3, NULL, 1.50, 4, 73, NULL, NULL)
|
||||
, ( 3, NULL, 0.50, 4, 217, NULL, NULL)
|
||||
------------------------------------------------------------------------------------------
|
||||
, ( 4, NULL, 1000.00, 1200, 33, NULL, NULL)
|
||||
, ( 4, NULL, 800.00, 1100, 38, NULL, NULL)
|
||||
, ( 4, NULL, 30.00, 40, 37, NULL, NULL)
|
||||
, ( 4, NULL, 3.00, 4, 37, NULL, NULL)
|
||||
, ( 4, NULL, 2.00, 4, 55, NULL, NULL)
|
||||
, ( 4, NULL, 1.50, 4, 73, NULL, NULL)
|
||||
, ( 4, NULL, 0.75, 4, 145, NULL, NULL)
|
||||
------------------------------------------------------------------------------------------
|
||||
, ( 5, NULL, 2000.00, 800, 39, NULL, NULL)
|
||||
, ( 5, NULL, 1600.00, 660, 40, NULL, NULL)
|
||||
, ( 5, NULL, 50.00, 20, 39, NULL, NULL)
|
||||
, ( 5, NULL, 5.00, 4, 77, NULL, NULL)
|
||||
, ( 5, NULL, 4.00, 4, 96, NULL, NULL)
|
||||
, ( 5, NULL, 3.00, 4, 127, NULL, NULL)
|
||||
, ( 5, NULL, 2.50, 4, 153, NULL, NULL)
|
||||
, ( 5, NULL, 1.50, 4, 254, NULL, NULL)
|
||||
------------------------------------------------------------------------------------------
|
||||
, ( 6, NULL, 3500.00, 500, 34, NULL, NULL)
|
||||
, ( 6, NULL, 2700.00, 400, 36, NULL, NULL)
|
||||
, ( 6, NULL, 7.00, 4, 136, NULL, NULL)
|
||||
, ( 6, NULL, 5.00, 4, 191, NULL, NULL)
|
||||
, ( 6, NULL, 4.00, 4, 238, NULL, NULL)
|
||||
, ( 6, NULL, 3.00, 4, 317, NULL, NULL)
|
||||
, ( 6, NULL, 2.50, 4, 381, NULL, NULL)
|
||||
------------------------------------------------------------------------------------------
|
||||
, ( 7, NULL, 5500.00, 550, 36, NULL, NULL)
|
||||
, ( 7, NULL, 4000.00, 400, 36, NULL, NULL)
|
||||
, ( 7, NULL, 2500.00, 260, 37, NULL, NULL)
|
||||
, ( 7, NULL, 14.00, 4, 102, NULL, NULL)
|
||||
, ( 7, NULL, 5.00, 4, 284, NULL, NULL)
|
||||
, ( 7, NULL, 3.50, 4, 406, NULL, NULL);
|
||||
|
||||
CREATE TABLE [OmniTestStates] (
|
||||
[Position] INT NOT NULL,
|
||||
[BuildInfo] VARCHAR(50) NULL,
|
||||
[ManifacturingTime] DATETIME NULL,
|
||||
[RebootsCount] TINYINT NULL,
|
||||
[VersionAndType] VARCHAR(50) NULL,
|
||||
[Position] INT NOT NULL,
|
||||
[BuildInfo] VARCHAR(50) NULL,
|
||||
[ManifacturingTime] DATETIME NULL,
|
||||
[RebootsCount] TINYINT NULL,
|
||||
[VersionAndType] VARCHAR(50) NULL,
|
||||
[ProgrammableID] VARCHAR(50) NULL,
|
||||
[FactoryID] VARCHAR(50) NULL,
|
||||
[ReadingDigitsCount] BINARY(1) NULL,
|
||||
[ReadingDigitsOffsest] BINARY(1) NULL,
|
||||
[Readings] VARCHAR(50) NULL,
|
||||
[OptionalUniDirFields] VARCHAR(50) NULL,
|
||||
[AlarmPersitenceDays] BINARY(1) NULL,
|
||||
[DataLogIntervalMins] BINARY(2) NULL,
|
||||
[DeviceID] VARCHAR(50) NULL,
|
||||
CONSTRAINT [PK_OmniTestStates_Position] PRIMARY KEY ([Position]),
|
||||
CONSTRAINT [CHK_OmniTestStates_Position] CHECK ([Position] BETWEEN 1 AND 10)
|
||||
);
|
||||
@@ -1,11 +1,16 @@
|
||||
using OmniPlus.Options;
|
||||
|
||||
using System;
|
||||
using System.Data.SqlClient;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace OmniPlus
|
||||
{
|
||||
internal static class OmniPlusExtensions
|
||||
{
|
||||
public const int BYTE_BITS = 8;
|
||||
|
||||
public const byte OxOO = 0x00;
|
||||
public const byte OxO1 = 0x01;
|
||||
public const byte OxO2 = 0x02;
|
||||
@@ -271,5 +276,105 @@ namespace OmniPlus
|
||||
|
||||
return asciiString.Trim();
|
||||
}
|
||||
|
||||
public static void ContinueWhenAll(this Task[] tasks)
|
||||
=> Task.Factory
|
||||
.ContinueWhenAll(tasks, _ => { })
|
||||
.Wait();
|
||||
|
||||
public static void OpenConnection(this SqlConnection sqlConnection)
|
||||
{
|
||||
sqlConnection.FireInfoMessageEventOnUserErrors = true;
|
||||
sqlConnection.InfoMessage += SqlConnection_InfoMessage;
|
||||
sqlConnection.Open();
|
||||
}
|
||||
|
||||
private static void SqlConnection_InfoMessage(object _, SqlInfoMessageEventArgs args)
|
||||
{
|
||||
Console.WriteLine(args.Message);
|
||||
}
|
||||
|
||||
public static T GetValue<T>(this SqlDataReader reader, int field)
|
||||
{
|
||||
if (!reader.IsDBNull(field) && reader.GetValue(field) is T value)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
return default(T);
|
||||
}
|
||||
|
||||
public static double MlPerRotation(byte intPart, ushort fraction, short correctionFactor)
|
||||
=> (intPart + (double)fraction / ushort.MaxValue) * correctionFactor;
|
||||
|
||||
public static double GPM2M3H(double value)
|
||||
=> value * 3785.411784 / 1000 / 1000 * 60;
|
||||
|
||||
public static double GetCorrectionFactor(this double[] points)
|
||||
{
|
||||
var min = points[0];
|
||||
var mid = points[1];
|
||||
var max = points[2];
|
||||
|
||||
if (Math.Abs(mid - max) <= 3 && Math.Max(mid, max) - min <= 6.5)
|
||||
{
|
||||
var avgMidMax = (mid + max) / 2;
|
||||
|
||||
if (100 - avgMidMax + min < 95)
|
||||
{
|
||||
return 95 - min;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 100 - avgMidMax;
|
||||
}
|
||||
}
|
||||
|
||||
return double.MaxValue;
|
||||
}
|
||||
|
||||
public static byte[] GetBits(this byte value)
|
||||
{
|
||||
var bits = new byte[BYTE_BITS];
|
||||
|
||||
for (byte i = 0; i < BYTE_BITS; i++)
|
||||
{
|
||||
bits[i] = (byte)(value >> i & 1);
|
||||
}
|
||||
|
||||
return bits;
|
||||
}
|
||||
|
||||
public static byte ToUint8(this byte[] bits)
|
||||
{
|
||||
var sum = default(byte);
|
||||
|
||||
for (byte i = 0; i < bits.Length; i++)
|
||||
{
|
||||
sum ^= (byte)(bits[i] << i);
|
||||
}
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
||||
public static byte GetUint8(this ref byte x, int start, int length)
|
||||
{
|
||||
var src = x.GetBits();
|
||||
var dst = new byte[8];
|
||||
|
||||
Array.Copy(src, start, dst, 0, length);
|
||||
|
||||
return dst.ToUint8();
|
||||
}
|
||||
|
||||
public static void SetUint8(this ref byte x, int start, int length, byte value)
|
||||
{
|
||||
var src = value.GetBits();
|
||||
var dst = x.GetBits();
|
||||
|
||||
Array.Copy(src, 0, dst, start, length);
|
||||
|
||||
x = dst.ToUint8();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,24 +2,21 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace OmniPlus
|
||||
{
|
||||
internal class OmniPlusMeter
|
||||
{
|
||||
private readonly IDictionary<OmniPlusTestPoint, double> inspectionPoints;
|
||||
private readonly IDictionary<OmniPlusTestPoint, ChamberCalibration> calibrationResults;
|
||||
private readonly IDictionary<OmniPlusTestPoint, OmniPlusTest> testPoints;
|
||||
|
||||
private InputVolume inputVolume;
|
||||
private SystemParameters systemParameters;
|
||||
|
||||
public OmniPlusMeter(bool connected = false)
|
||||
{
|
||||
this.Connected = connected;
|
||||
this.inputVolume = new InputVolume();
|
||||
this.systemParameters = new SystemParameters();
|
||||
this.inspectionPoints = new Dictionary<OmniPlusTestPoint, double>();
|
||||
this.calibrationResults = new Dictionary<OmniPlusTestPoint, ChamberCalibration>();
|
||||
this.testPoints = new Dictionary<OmniPlusTestPoint, OmniPlusTest>();
|
||||
}
|
||||
|
||||
public bool Connected { get; set; }
|
||||
@@ -82,12 +79,43 @@ namespace OmniPlus
|
||||
|
||||
public bool VoltsInRange => 3.19 <= this.Volts && this.Volts <= 3.75;
|
||||
|
||||
public double CorrectionFactor { get; private set; }
|
||||
|
||||
public sbyte FactoryCorrection
|
||||
{
|
||||
get => (sbyte)(this.CorrectionFactor * 10);
|
||||
}
|
||||
|
||||
public bool FactorySealed
|
||||
{
|
||||
get => this.systemParameters.FactorySealed;
|
||||
set => this.systemParameters.FactorySealed = value;
|
||||
}
|
||||
|
||||
internal double AddCalibrationResult(OmniPlusTestPoint point, ChamberCalibrationResponse result)
|
||||
{
|
||||
this.testPoints[point] = new OmniPlusTest
|
||||
{
|
||||
Rotations = result.Rotations,
|
||||
Duration = result.Duration,
|
||||
MeterVolume = point.VolumeM3(result.Rotations, result.Duration)
|
||||
};
|
||||
|
||||
return this.testPoints[point].MeterVolume;
|
||||
}
|
||||
|
||||
internal double AddCalibrationVolume(OmniPlusTestPoint point, double volumeMessured)
|
||||
{
|
||||
this.testPoints[point].VolumeMessured = volumeMessured;
|
||||
|
||||
return this.testPoints[point].DifferencePercentage;
|
||||
}
|
||||
|
||||
internal void AddConfigurationParameters(ConfigurationParameters configurationParameters)
|
||||
{
|
||||
// TODO: throw new NotImplementedException();
|
||||
}
|
||||
|
||||
internal void AddSystemParameters(SystemParameters systemParameters)
|
||||
{
|
||||
if (systemParameters != null)
|
||||
@@ -110,17 +138,17 @@ namespace OmniPlus
|
||||
}
|
||||
}
|
||||
|
||||
internal void AddCalibrationResult(OmniPlusTestPoint point, ChamberCalibration result)
|
||||
internal double GetCorrectionFactor()
|
||||
{
|
||||
this.calibrationResults[point] = result;
|
||||
this.CorrectionFactor = this.testPoints
|
||||
.OrderBy(x => x.Key.GalPerMin)
|
||||
.Select(x => x.Value.DifferencePercentage)
|
||||
.ToArray()
|
||||
.GetCorrectionFactor();
|
||||
|
||||
if (this.CanCalibrate)
|
||||
{
|
||||
this.CanCalibrate
|
||||
= result != null
|
||||
&& result.Succeeded
|
||||
&& result.Control == ChamberCalibration.TEST_COMPLETED;
|
||||
}
|
||||
this.CanCalibrate = this.CorrectionFactor != double.MaxValue;
|
||||
|
||||
return this.CorrectionFactor;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
namespace OmniPlus
|
||||
{
|
||||
internal class OmniPlusTest
|
||||
{
|
||||
public double Rotations { get; set; }
|
||||
|
||||
public double Duration { get; set; }
|
||||
|
||||
public double MeterVolume { get; set; }
|
||||
|
||||
public double VolumeMessured { get; set; }
|
||||
|
||||
public double DifferencePercentage
|
||||
{
|
||||
get
|
||||
{
|
||||
if (this.MeterVolume != 0 && this.VolumeMessured != 0)
|
||||
{
|
||||
return this.MeterVolume / this.VolumeMessured * 100;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,16 +1,33 @@
|
||||
namespace OmniPlus
|
||||
{
|
||||
using System;
|
||||
using System;
|
||||
|
||||
public struct OmniPlusTestPoint : IComparable<OmniPlusTestPoint>
|
||||
namespace OmniPlus
|
||||
{
|
||||
internal struct OmniPlusTestPoint : IComparable<OmniPlusTestPoint>
|
||||
{
|
||||
public double VolumeM3H { get; set; }
|
||||
public double GalPerMin { get; set; }
|
||||
|
||||
public ushort Rotations { get; set; }
|
||||
|
||||
public ushort Duration { get; set; }
|
||||
|
||||
public ushort MinDiff { get; set; }
|
||||
|
||||
public ushort MaxDiff { get; set; }
|
||||
|
||||
public double MlPerRotation { get; set; }
|
||||
|
||||
public double VolumeM3H
|
||||
=> OmniPlusExtensions.GPM2M3H(this.GalPerMin);
|
||||
|
||||
public int CompareTo(OmniPlusTestPoint other)
|
||||
=> this.Rotations.CompareTo(other.Rotations);
|
||||
|
||||
public double VolumeM3(double rotations, double duration)
|
||||
{
|
||||
var seconds = duration / 32768;
|
||||
var milliliter = rotations * this.MlPerRotation;
|
||||
|
||||
return seconds * milliliter / 1000 / 1000;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,7 @@ using System.Collections.Generic;
|
||||
|
||||
namespace OmniPlus
|
||||
{
|
||||
public class OmniPlusType
|
||||
internal class OmniPlusType
|
||||
{
|
||||
public byte OmniId { get; set; }
|
||||
|
||||
@@ -38,7 +38,12 @@ namespace OmniPlus
|
||||
set => this.InputVolume.Fraction = value;
|
||||
}
|
||||
|
||||
public double MlPerRotation { get; set; }
|
||||
public double PulsePerRotation { get; set; }
|
||||
|
||||
public short CorrectionFactor { get; set; }
|
||||
|
||||
public double MlPerRotation
|
||||
=> OmniPlusExtensions.MlPerRotation(this.IntPart, this.Fraction, this.CorrectionFactor);
|
||||
|
||||
public InputVolume InputVolume { get; }
|
||||
= new InputVolume();
|
||||
|
||||
Reference in New Issue
Block a user