latest omni changes

This commit is contained in:
Stoyan Zlatev
2023-11-14 08:16:53 +01:00
parent aafa3828f8
commit 0fc0466e6b
17 changed files with 748 additions and 275 deletions
@@ -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; }
}
+9
View File
@@ -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);
}
}
}
+59 -3
View File
@@ -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);
}
}
}
+6 -2
View File
@@ -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" />
+32 -13
View File
@@ -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);
}
+115 -93
View File
@@ -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);
+2 -1
View File
@@ -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";
}
+74 -41
View File
@@ -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);
}
}
}
+132 -85
View File
@@ -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)
);
+105
View File
@@ -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();
}
}
}
+43 -15
View File
@@ -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;
}
}
}
+26
View File
@@ -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;
}
}
}
}
+22 -5
View File
@@ -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;
}
}
}
+7 -2
View File
@@ -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();