omni changes

This commit is contained in:
Stoyan Zlatev
2023-10-24 08:43:18 +02:00
parent 35ba0a62ea
commit ad62140430
18 changed files with 266 additions and 95 deletions
+13 -13
View File
@@ -2,18 +2,18 @@
{
public enum BaudRate
{
X300 = 300,
X600 = 600,
X1200 = 1200,
X2400 = 2400,
X4800 = 4800,
X9600 = 9600,
X19200 = 19200,
X38400 = 38400,
X57600 = 57600,
X115200 = 115200,
X230400 = 230400,
X460800 = 460800,
X921600 = 921600
BaudRate300 = 300,
BaudRate600 = 600,
BaudRate1200 = 1200,
BaudRate2400 = 2400,
BaudRate4800 = 4800,
BaudRate9600 = 9600,
BaudRate19200 = 19200,
BaudRate38400 = 38400,
BaudRate57600 = 57600,
BaudRate115200 = 115200,
BaudRate230400 = 230400,
BaudRate460800 = 460800,
BaudRate921600 = 921600
}
}
+4 -4
View File
@@ -2,9 +2,9 @@
{
public enum DataBits
{
X5 = 5,
X6 = 6,
X7 = 7,
X8 = 8
DataBits5 = 5,
DataBits6 = 6,
DataBits7 = 7,
DataBits8 = 8
}
}
@@ -25,7 +25,7 @@ namespace OmniPlus.Connection
public event SerialPortStateChangedEventHandler StateChanged;
protected bool open => this.state == SerialPortState.Open;
protected bool connected => this.state == SerialPortState.Open;
public void Close()
{
@@ -56,6 +56,9 @@ namespace OmniPlus.Connection
try
{
var fileInfo = new FileInfo(this.options.LogFile);
fileInfo.Directory.Create();
File.AppendAllText(this.options.LogFile, string.Empty);
this.Log += this.SerialPortConnection_Log;
@@ -93,7 +96,11 @@ namespace OmniPlus.Connection
this.Read += this.SerialPortConnection_Read;
this.StateChanged?.Invoke(this.state, $"{this.options.PortName} opened.");
this.StateChanged?.Invoke(this.state, $"{this.options.PortName} opened"
+ $", {this.options.BaudRate}"
+ $", {this.options.DataBits}"
+ $", {this.options.Parity}"
+ $", {this.options.StopBits}");
}
catch (Exception e)
{
@@ -107,12 +114,22 @@ namespace OmniPlus.Connection
public virtual void Write(SerialPortMessage message)
{
if (this.open && message.Length > 0)
if (this.connected && message.Length > 0)
{
this.serialPort.Write(message, 0, message.Length);
}
this.Log?.Invoke($"RX: {BitConverter.ToString(message)}");
this.Log?.Invoke($"TX: {BitConverter.ToString(message)}");
}
public virtual void Write(params byte[] message)
{
if (this.connected && message.Length > 0)
{
this.serialPort.Write(message, 0, message.Length);
}
this.Log?.Invoke($"TX: {BitConverter.ToString(message)}");
}
protected abstract void SerialPortConnection_Read();
@@ -146,7 +163,7 @@ namespace OmniPlus.Connection
private void Port_DataReceived(object sender, SerialDataReceivedEventArgs args)
{
if (this.open && sender is System.IO.Ports.SerialPort port && port.BytesToRead > 0)
if (this.connected && sender is System.IO.Ports.SerialPort port && port.BytesToRead > 0)
{
var bytes = new byte[port.BytesToRead];
var lock_object = new object();
@@ -163,7 +180,7 @@ namespace OmniPlus.Connection
this.Read?.Invoke();
}
this.Log?.Invoke($"TX: {BitConverter.ToString(bytes)}");
this.Log?.Invoke($"RX: {BitConverter.ToString(bytes)}");
}
}
@@ -8,26 +8,26 @@ namespace OmniPlus.Connection
{
public SerialPortOptions()
{
foreach (var portName in System.IO.Ports.SerialPort.GetPortNames())
foreach (var portName in SerialPort.GetPortNames())
{
this.PortName = portName;
break;
}
this.BaudRate = BaudRate.X4800;
this.DataBits = DataBits.X8;
this.BaudRate = BaudRate.BaudRate4800;
this.DataBits = DataBits.DataBits8;
this.Parity = Parity.None;
this.StopBits = StopBits.One;
}
public string PortName { get; set; }
public BaudRate BaudRate { get; set; } = BaudRate.X4800;
public BaudRate BaudRate { get; set; } = BaudRate.BaudRate4800;
public Parity Parity { get; set; } = Parity.None;
public DataBits DataBits { get; set; } = DataBits.X8;
public DataBits DataBits { get; set; } = DataBits.DataBits8;
public StopBits StopBits { get; set; } = StopBits.One;
+22 -3
View File
@@ -52,14 +52,33 @@ namespace OmniPlus.Connection
return;
}
Array.Copy(this.buffer, sourceIndex, destinationArray, destinationIndex, length);
}
public void Flush(int length)
{
var lock_object = new object();
lock (lock_object)
{
this.dataLength = this.buffer.Length - requiredBufferLength;
if (length <= 0 || this.dataLength - length <= 0)
{
this.buffer = new byte[this.minBufferLength];
}
else
{
var dataLength = this.dataLength - length;
var newBufferLength = this.minBufferLength;
Array.Copy(this.buffer, sourceIndex, destinationArray, destinationIndex, length);
Array.Copy(this.buffer, requiredBufferLength, this.buffer, 0, this.dataLength);
while (newBufferLength <= dataLength)
{
newBufferLength *= 2;
}
var newBuffer = new byte[newBufferLength];
Array.Copy(this.buffer, dataLength, newBuffer, 0, dataLength);
}
}
}
}
+1 -1
View File
@@ -73,7 +73,7 @@ namespace OmniPlus.Connections
public static byte[] CalculateCheckSum16(this byte[] bytes, int length)
{
short checksum = 0;
ushort checksum = 0;
for (int i = 0; i < length; i++)
{
+18 -18
View File
@@ -16,14 +16,14 @@
private event Action<IrdaMessage> messageReceived;
public IrdaConnection(string portName)
public IrdaConnection(string portName, string logFile = null)
{
this.options.PortName = portName;
this.options.BaudRate = BaudRate.X4800;
this.options.DataBits = DataBits.X8;
this.options.BaudRate = BaudRate.BaudRate115200;
this.options.DataBits = DataBits.DataBits8;
this.options.Parity = Parity.None;
this.options.StopBits = StopBits.One;
this.options.RtsEnabled = true;
this.options.LogFile = logFile ?? ".\\IrdaConnection.txt";
}
public byte[] Write(byte[] command, int timeout, int delay)
@@ -31,6 +31,7 @@
var ui1236Request = new UI1236Message(command);
var irdaRequest = new IrdaMessage(ui1236Request);
var responseBytes = Array.Empty<byte>();
var retriesCount = 3;
var received = false;
this.messageReceived += irdaResponse =>
@@ -40,22 +41,21 @@
received = true;
};
this.Write(irdaRequest);
#region Temporary
// TODO: remove for real connections
this.stream = new SerialPortStream();
this.stream.Append(new byte[] { 0xFF, 0x01, 0x25, 0x00, 0x80, 0x9B, 0x33, 0x04, 0x0D, 0x05, 0x08, 0x0C, 0xFF, 0x01, 0x25, 0x00, 0x80, 0x88 });
this.SerialPortConnection_Read();
#endregion
Thread.Sleep(1);
while (!received && timeout >= 0)
while (!received && retriesCount-- > 0)
{
timeout -= delay;
this.Write(0x01, 0x01, 0x01, 0x01);
Thread.Sleep(1);
this.Write(irdaRequest);
// this.Write(0x9B, 0x33, 0x04, 0x0D, 0x05, 0x08, 0xFD, 0xC6, 0x01, 0xDD, 0x00, 0x3B, 0x1B);
Thread.Sleep(delay);
var sleep = timeout;
while (!received && sleep >= 0)
{
sleep -= delay;
Thread.Sleep(delay);
}
}
return responseBytes;
@@ -1,6 +1,8 @@
using OmniPlus.Connection;
using System;
using System.Linq;
using Xylem.Common.Utils.Crc16Ccitt;
namespace OmniPlus.Connections.Messages
{
@@ -31,27 +33,13 @@ namespace OmniPlus.Connections.Messages
set => this.bytes[2] = value;
}
public void CopyCRC16(byte[] bytes, int sourceIndex)
{
var crcPosition = this.bytes.Length - CRC_LENGTH;
Array.Copy(bytes, sourceIndex, this.bytes, crcPosition, CRC_LENGTH);
var crc16 = this.bytes.CalculateCRC(0, crcPosition);
if (crc16[0] == this.bytes[crcPosition] && crc16[0] == this.bytes[crcPosition + 1])
{
// TODO: message validated.
}
}
protected override byte[] CreateMessage(byte[] payload)
{
var messageLength = payload.Length;
messageLength += messageLength % 2;
var index = 0;
var message = new byte[messageLength + 5];
var message = new byte[messageLength + MIN_LENGTH];
message[index++] = IrdaConnection.MSG_START;
message[index++] = IrdaConnection.MSG_PC2OMNI;
message[index++] = (byte)(messageLength / 2);
@@ -60,7 +48,7 @@ namespace OmniPlus.Connections.Messages
messageLength = message.Length;
var crc16 = message.CalculateCRC(0, messageLength - CRC_LENGTH);
var crc16 = BitConverter.GetBytes(Crc16Ccitt.CalculateReversedLsb8408(message.Skip(1).Take(message.Length - 3).ToArray()));
message[messageLength - 2] = crc16[1];
message[messageLength - 1] = crc16[0];
@@ -10,6 +10,7 @@ namespace OmniPlus.Connections.Messages
{
public const byte START_BYTE = 0x0D;
public const byte MIN_LENGTH = 0x05;
public const byte HEADER_BYTES = 0x03;
public UI1236Message(byte[] bytes, bool response = false) : base(bytes, response)
{
@@ -29,14 +30,11 @@ namespace OmniPlus.Connections.Messages
protected override byte[] CreateMessage(byte[] payload)
{
var messageLength = payload.Length + MIN_LENGTH;
var even = messageLength % 2;
messageLength += even;
var message = new byte[messageLength];
var index = 0;
message[index++] = START_BYTE;
message[index++] = (byte)payload.Length;
message[index++] = (byte)(payload.Length + HEADER_BYTES);
Control control = 0;
control.ReturnResponse = true;
@@ -44,9 +42,9 @@ namespace OmniPlus.Connections.Messages
payload.CopyTo(message, index);
var checksum = message.CalculateCheckSum16(messageLength);
message[messageLength - even - 2] = checksum[1];
message[messageLength - even - 1] = checksum[0];
var checksum = message.CalculateCheckSum16(messageLength - 2);
message[messageLength - 2] = checksum[1];
message[messageLength - 1] = checksum[0];
return message;
}
@@ -10,8 +10,8 @@ namespace OmniPlus.Connections
public UniProConnection(string portName)
{
this.options.PortName = portName;
this.options.BaudRate = BaudRate.X2400;
this.options.DataBits = DataBits.X8;
this.options.BaudRate = BaudRate.BaudRate2400;
this.options.DataBits = DataBits.DataBits8;
this.options.Parity = Parity.None;
this.options.StopBits = StopBits.One;
this.options.RtsEnabled = true;
@@ -0,0 +1,47 @@
using OmniPlus.Features.Enums;
using System;
namespace OmniPlus.Features.DeviceSpecific
{
public struct CalibrationResults
{
private const byte FAILED = 0x01;
private const byte COMPLETED = 0x02;
private CalibrationResults(byte[] bytes)
{
this.Status = Status.UnknownCommand;
this.Completed = default(bool);
this.Rotations = default(ushort);
this.Dauer = default(uint);
if (bytes?.Length == 8)
{
this.Status = (Status)bytes[0];
this.Completed = bytes[1] == COMPLETED;
this.Rotations = BitConverter.ToUInt16(bytes, 2);
this.Dauer = BitConverter.ToUInt16(bytes, 4);
}
}
public Status Status { get; }
public bool Completed { get; }
public ushort Rotations { get; }
public uint Dauer { get; }
public static byte[] RequestResults => new byte[]
{
FactoryMeterChamberCalibrationTest.BASE,
FactoryMeterChamberCalibrationTest.SET,
FactoryMeterChamberCalibrationTest.VIEW,
};
public static implicit operator CalibrationResults(byte[] bytes)
=> new CalibrationResults(bytes);
}
}
@@ -0,0 +1,27 @@
using OmniPlus.Features.UI1236;
namespace OmniPlus.Features.DeviceSpecific
{
public struct ConfigurationParameters
{
public const byte BASE = 0xFD;
public const byte GET = 0xC7;
public const byte ALL = 0x01;
public ProgrammableID ProgrammableId { get; }
public FactoryID FactoryId { get; }
public NumberOfReadingDigits ReadingDigits { get; }
public Reading Reading { get; }
public OptionalUniDirectionalFields OptionalUniDirectionalFields { get; }
public AlarmPersistencePeriod AlarmPersistensePeriaod { get; }
public DataLogInterval DataLogInterval { get; }
public RegisterDeviceIDString DeviceIDString { get; }
}
}
@@ -1,8 +1,54 @@
namespace OmniPlus.Features.DeviceSpecific
using OmniPlus.Features.Enums;
using System;
namespace OmniPlus.Features.DeviceSpecific
{
public struct FactoryMeterChamberCalibrationTest
{
public const byte BASE = 0xFD;
public const byte SET = 0x67;
public const byte VIEW = 0x01;
private FactoryMeterChamberCalibrationTest(byte[] bytes) : this()
{
this.Status = Status.UnknownCommand;
this.CalibrationState = default(CalibrationState);
this.Rotations = default(ushort);
this.Dauer = default(ushort);
if (bytes?.Length == 6)
{
this.Status = (Status)bytes[0];
this.CalibrationState = (CalibrationState)bytes[1];
this.Rotations = BitConverter.ToUInt16(bytes, 2);
this.Dauer = BitConverter.ToUInt16(bytes, 4);
}
}
public Status Status { get; set; }
public CalibrationState CalibrationState { get; set; }
public ushort Rotations { get; set; }
public ushort Dauer { get; set; }
public static implicit operator FactoryMeterChamberCalibrationTest(byte[] bytes)
=> new FactoryMeterChamberCalibrationTest(bytes);
public static implicit operator byte[] (FactoryMeterChamberCalibrationTest calibration)
{
var bytes = new byte[7];
bytes[0] = BASE;
bytes[1] = SET;
bytes[2] = (byte)(calibration.CalibrationState);
BitConverter.GetBytes(calibration.Rotations).CopyTo(bytes, 3);
BitConverter.GetBytes(calibration.Dauer).CopyTo(bytes, 5);
return bytes;
}
}
}
@@ -39,8 +39,7 @@ namespace OmniPlus.Features.DeviceSpecific
public MeterRange MeterRange { get; set; }
public static byte[] GetCommand
=> new byte[] { BASE, GET };
public static byte[] GetCommand => new byte[] { BASE, GET };
public static implicit operator InputVolume(byte[] bytes)
=> new InputVolume(bytes);
@@ -0,0 +1,9 @@
namespace OmniPlus.Features.Enums
{
public enum CalibrationState : byte
{
OK = 0x00,
Failed = 0x01,
Completed = 0x02
}
}
+9 -1
View File
@@ -57,6 +57,8 @@
<Compile Include="Connection\SerialPortStream.cs" />
<Compile Include="Features\DeviceSpecific\BatteryVoltage.cs" />
<Compile Include="Features\DeviceSpecific\BatteryVoltageMeasurementCalibrationFactors.cs" />
<Compile Include="Features\DeviceSpecific\CalibrationResults.cs" />
<Compile Include="Features\DeviceSpecific\ConfigurationParameters.cs" />
<Compile Include="Features\DeviceSpecific\DataLogData.cs" />
<Compile Include="Features\DeviceSpecific\DataLogInterval.cs" />
<Compile Include="Features\DeviceSpecific\DisplayMode.cs" />
@@ -91,6 +93,7 @@
<Compile Include="Features\DeviceSpecific\TimeofFactorySeal.cs" />
<Compile Include="Features\DeviceSpecific\TimeofInstallation.cs" />
<Compile Include="Features\DeviceSpecific\TriggerWatchdogReset.cs" />
<Compile Include="Features\Enums\CalibrationState.cs" />
<Compile Include="Features\Enums\DeviceCommands.cs" />
<Compile Include="Features\Enums\MeterRanges.cs" />
<Compile Include="Features\Enums\MeterSizes.cs" />
@@ -134,6 +137,11 @@
<ItemGroup>
<None Include="App.config" />
</ItemGroup>
<ItemGroup />
<ItemGroup>
<ProjectReference Include="..\Utils\Crc16Ccitt\Crc16Ccitt.csproj">
<Project>{91DEF0C0-AA4F-40AE-8F18-CB717FDE7E7F}</Project>
<Name>Crc16Ccitt</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>
+8 -4
View File
@@ -25,8 +25,6 @@ namespace OmniPlus
this.uniProConnection?.Close();
this.irdaConnection?.Open();
this.messageHandler = this.irdaConnection.Write;
var bytes = this.GetSystemParameters();
}
public void ActivateUniPro()
@@ -36,15 +34,21 @@ namespace OmniPlus
this.messageHandler = this.uniProConnection.Write;
}
internal SystemParameters GetSystemParameters()
public SystemParameters GetSystemParameters()
=> this.messageHandler?.Invoke(SystemParameters.GetCommand, 3000, 300);
internal bool SetInputVolume(InputVolume inputVolume)
public bool SetInputVolume(InputVolume inputVolume)
{
inputVolume = this.messageHandler?.Invoke(inputVolume, 3000, 300);
return inputVolume.Status == Status.Completed;
}
public FactoryMeterChamberCalibrationTest StartCalibration(FactoryMeterChamberCalibrationTest calibrationOptions)
=> this.messageHandler?.Invoke(calibrationOptions, 3000, 300);
public CalibrationResults GetCalibrationResults()
=> this.messageHandler?.Invoke(CalibrationResults.RequestResults, 3000, 300);
}
}
+21 -12
View File
@@ -1,21 +1,30 @@
using OmniPlus.Features.DeviceSpecific;
using OmniPlus.Features.Enums;
namespace OmniPlus
namespace OmniPlus
{
class Program
{
static void Main(string[] args)
{
var omniRegister = new OmniRegister("COM1");
var omniRegister = new OmniRegister("COM4");
omniRegister.ActivateIrda();
var x = omniRegister.SetInputVolume(new InputVolume
{
MilliliterPerPulse = 1500,
FractionalPart = 500,
MeterSize = MeterSizes.OneHalfIn,
MeterRange = MeterRanges.From1To2,
});
var systemParameters = omniRegister.GetSystemParameters();
//var inputVolumeSetted = omniRegister.SetInputVolume(new InputVolume
//{
// MilliliterPerPulse = 1500,
// FractionalPart = 500,
// MeterSize = MeterSizes.OneHalfIn,
// MeterRange = MeterRanges.From1To2,
//});
//var calibrationStart = omniRegister.StartCalibration(new FactoryMeterChamberCalibrationTest
//{
// CalibrationState = CalibrationState.OK,
// Rotations = 1000,
// Dauer = 10000
//});
//var calibration = omniRegister.GetCalibrationResults();
}
}
}