OMNI+ project created
This commit is contained in:
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<configuration>
|
||||
<startup>
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8.1" />
|
||||
</startup>
|
||||
</configuration>
|
||||
@@ -0,0 +1,20 @@
|
||||
namespace OmniPlus.Connection
|
||||
{
|
||||
public enum BaudRate : int
|
||||
{
|
||||
Bps110 = 110,
|
||||
Bps300 = 300,
|
||||
Bps600 = 600,
|
||||
Bps1200 = 1200,
|
||||
Bps2400 = 2400,
|
||||
Bps4800 = 4800,
|
||||
Bps9600 = 9600,
|
||||
Bps14400 = 14400,
|
||||
Bps19200 = 19200,
|
||||
Bps38400 = 38400,
|
||||
Bps57600 = 57600,
|
||||
Bps115200 = 115200,
|
||||
Bps128000 = 128000,
|
||||
Bps256000 = 256000
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
using System;
|
||||
|
||||
namespace OmniPlus.Connection.Contracts
|
||||
{
|
||||
internal interface IConnection : IDisposable
|
||||
{
|
||||
event ReadEventHandler DataReceived;
|
||||
event StateEventHandler StateChanged;
|
||||
|
||||
void OpenConnection();
|
||||
|
||||
void Write(byte[] data);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
namespace OmniPlus.Connection.Contracts
|
||||
{
|
||||
internal interface IData
|
||||
{
|
||||
byte[] Data { get; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
namespace OmniPlus.Connection.Contracts
|
||||
{
|
||||
internal interface IDataSettings : IData
|
||||
{
|
||||
bool ReadByte(byte data);
|
||||
|
||||
void StartReading();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
using System.IO.Ports;
|
||||
|
||||
namespace OmniPlus.Connection.Contracts
|
||||
{
|
||||
internal interface IPortSettings
|
||||
{
|
||||
BaudRate BaudRate { get; }
|
||||
|
||||
Parity Parity { get; }
|
||||
|
||||
DataBits DataBits { get; }
|
||||
|
||||
StopBits StopBits { get; }
|
||||
|
||||
bool RtsEnbaled { get; }
|
||||
|
||||
bool DtrEnabled { get; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
namespace OmniPlus.Connection
|
||||
{
|
||||
public enum DataBits : int
|
||||
{
|
||||
B8 = 8,
|
||||
B7 = 7,
|
||||
B6 = 6,
|
||||
B5 = 5
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
using OmniPlus.Connection.Contracts;
|
||||
|
||||
namespace OmniPlus.Connection
|
||||
{
|
||||
internal delegate void ReadEventHandler(IData data);
|
||||
}
|
||||
@@ -0,0 +1,182 @@
|
||||
using OmniPlus.Connection.Contracts;
|
||||
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.IO.Ports;
|
||||
|
||||
namespace OmniPlus.Connection
|
||||
{
|
||||
internal class SPConnection : IConnection
|
||||
{
|
||||
private readonly string portName;
|
||||
private readonly IPortSettings portSettings;
|
||||
private readonly IDataSettings dataSettings;
|
||||
|
||||
private event Action bytesReceived;
|
||||
private ConcurrentQueue<byte> data;
|
||||
private SerialPort serialPort;
|
||||
private bool parsingData;
|
||||
|
||||
public SPConnection(string portName, IPortSettings portSettings, IDataSettings dataSettings)
|
||||
{
|
||||
this.portName = portName;
|
||||
this.portSettings = portSettings;
|
||||
this.dataSettings = dataSettings;
|
||||
this.bytesReceived += SPConnection_BytesReceived;
|
||||
}
|
||||
|
||||
public event ReadEventHandler DataReceived;
|
||||
public event StateEventHandler StateChanged;
|
||||
|
||||
public virtual void Dispose()
|
||||
{
|
||||
if (this.DataReceived != null)
|
||||
{
|
||||
foreach (var callback in this.DataReceived.GetInvocationList())
|
||||
{
|
||||
if (callback is ReadEventHandler responseReceivedCallback)
|
||||
{
|
||||
this.DataReceived -= responseReceivedCallback;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.CloseConnection();
|
||||
}
|
||||
|
||||
public void Write(byte[] data)
|
||||
{
|
||||
if (data?.Length > 0 && this.serialPort.IsOpen)
|
||||
{
|
||||
lock (this.serialPort)
|
||||
{
|
||||
this.serialPort.Write(data, 0, data.Length);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void OpenConnection()
|
||||
{
|
||||
this.CloseConnection();
|
||||
|
||||
try
|
||||
{
|
||||
this.serialPort = new SerialPort
|
||||
{
|
||||
PortName = this.portName,
|
||||
BaudRate = (int)this.portSettings.BaudRate,
|
||||
Parity = this.portSettings.Parity,
|
||||
DataBits = (int)this.portSettings.DataBits,
|
||||
StopBits = this.portSettings.StopBits,
|
||||
RtsEnable = this.portSettings.RtsEnbaled,
|
||||
DtrEnable = this.portSettings.DtrEnabled
|
||||
};
|
||||
|
||||
this.serialPort.DataReceived += this.SerialPort_DataReceived;
|
||||
this.serialPort.Disposed += this.SerialPort_Disposed;
|
||||
this.serialPort.ErrorReceived += this.SerialPort_ErrorReceived;
|
||||
this.serialPort.PinChanged += this.SerialPort_PinChanged;
|
||||
|
||||
this.serialPort.Open();
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
this.StateChanged?.Invoke(SPState.Error, exception.ToString());
|
||||
|
||||
this.CloseConnection();
|
||||
}
|
||||
|
||||
if (this.serialPort?.IsOpen == true)
|
||||
{
|
||||
this.data = new ConcurrentQueue<byte>();
|
||||
|
||||
this.StateChanged?.Invoke(SPState.Opened, "Connected - "
|
||||
+ $", {this.serialPort.PortName}"
|
||||
+ $", {this.serialPort.BaudRate}"
|
||||
+ $", {this.serialPort.Parity}"
|
||||
+ $", {this.serialPort.DataBits}"
|
||||
+ $", {this.serialPort.StopBits}"
|
||||
+ $", RTS: {this.serialPort.RtsEnable}"
|
||||
+ $", DTR: {this.serialPort.DtrEnable}");
|
||||
}
|
||||
}
|
||||
|
||||
private void CloseConnection()
|
||||
{
|
||||
if (this.serialPort != null)
|
||||
{
|
||||
this.serialPort.DataReceived -= this.SerialPort_DataReceived;
|
||||
this.serialPort.Disposed -= this.SerialPort_Disposed;
|
||||
this.serialPort.ErrorReceived -= this.SerialPort_ErrorReceived;
|
||||
this.serialPort.PinChanged -= this.SerialPort_PinChanged;
|
||||
|
||||
this.serialPort.Dispose();
|
||||
|
||||
this.serialPort = null;
|
||||
this.data = null;
|
||||
|
||||
this.StateChanged?.Invoke(SPState.Closed, "Connection was closed.");
|
||||
}
|
||||
}
|
||||
|
||||
private void SPConnection_BytesReceived()
|
||||
{
|
||||
this.parsingData = true;
|
||||
|
||||
this.dataSettings.StartReading();
|
||||
|
||||
while (this.parsingData)
|
||||
{
|
||||
this.parsingData = this.data.TryDequeue(out byte current) && this.dataSettings.ReadByte(current);
|
||||
}
|
||||
|
||||
this.DataReceived?.Invoke(this.dataSettings);
|
||||
}
|
||||
|
||||
private void SerialPort_DataReceived(Object sender, SerialDataReceivedEventArgs args)
|
||||
{
|
||||
if (sender is SerialPort serialPort && serialPort.BytesToRead > 0)
|
||||
{
|
||||
var bytes = new byte[serialPort.BytesToRead];
|
||||
|
||||
lock (serialPort)
|
||||
{
|
||||
serialPort.Read(bytes, 0, bytes.Length);
|
||||
}
|
||||
|
||||
foreach (var x in bytes)
|
||||
{
|
||||
this.data.Enqueue(x);
|
||||
}
|
||||
|
||||
if (!this.parsingData)
|
||||
{
|
||||
this.bytesReceived?.Invoke();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void SerialPort_Disposed(Object sender, EventArgs args)
|
||||
{
|
||||
this.Dispose();
|
||||
|
||||
this.StateChanged?.Invoke(SPState.Disposed, $"Connection was disposed!");
|
||||
}
|
||||
|
||||
private void SerialPort_ErrorReceived(Object sender, SerialErrorReceivedEventArgs args)
|
||||
{
|
||||
this.Dispose();
|
||||
|
||||
this.StateChanged?.Invoke(SPState.Error, $"Error received - {nameof(args.EventType)}: {args.EventType}");
|
||||
}
|
||||
|
||||
private void SerialPort_PinChanged(Object sender, SerialPinChangedEventArgs args)
|
||||
{
|
||||
this.Dispose();
|
||||
|
||||
this.StateChanged?.Invoke(SPState.PinChanged, $"Pin changed - {nameof(args.EventType)}: {args.EventType}");
|
||||
}
|
||||
|
||||
~SPConnection() => this.Dispose();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
namespace OmniPlus.Connection
|
||||
{
|
||||
internal enum SPState
|
||||
{
|
||||
Closed,
|
||||
Disposed,
|
||||
Error,
|
||||
PinChanged,
|
||||
Opened
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
namespace OmniPlus.Connection
|
||||
{
|
||||
internal delegate void StateEventHandler(SPState state, string message);
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
using OmniPlus.Connection;
|
||||
|
||||
using System;
|
||||
|
||||
namespace OmniPlus.Contracts
|
||||
{
|
||||
internal interface IOmniConnection : IDisposable
|
||||
{
|
||||
event StateEventHandler StateChanged;
|
||||
|
||||
void CloseConnection();
|
||||
|
||||
void OpenConnection();
|
||||
|
||||
byte[] Send(byte[] request);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
namespace OmniPlus.Commands
|
||||
{
|
||||
using OmniPlus.Types;
|
||||
|
||||
using System;
|
||||
|
||||
public class AggregateSystemParameters
|
||||
{
|
||||
private readonly ASCIIString factoryBuild;
|
||||
private readonly Seconds manifacturingTime;
|
||||
private readonly Seconds systemTime;
|
||||
private readonly ASCIIString firmware;
|
||||
private readonly Battery battery;
|
||||
private readonly byte rebootCount;
|
||||
private readonly byte sealStatus;
|
||||
|
||||
private AggregateSystemParameters(byte[] data)
|
||||
{
|
||||
this.rebootCount = default(byte);
|
||||
this.sealStatus = default(byte);
|
||||
this.factoryBuild = new byte[16];
|
||||
this.manifacturingTime = new byte[4];
|
||||
this.systemTime = new byte[4];
|
||||
this.firmware = new byte[27];
|
||||
this.battery = new byte[6];
|
||||
|
||||
if (data?.Length > 0)
|
||||
{
|
||||
var exactData = new byte[59];
|
||||
|
||||
data.CopyTo(exactData, 0);
|
||||
|
||||
this.rebootCount = data[24];
|
||||
this.sealStatus = data[58];
|
||||
|
||||
Array.Copy(exactData, 0, this.factoryBuild, 0, 16);
|
||||
Array.Copy(exactData, 16, this.manifacturingTime, 0, 4);
|
||||
Array.Copy(exactData, 20, this.systemTime, 0, 4);
|
||||
Array.Copy(exactData, 25, this.firmware, 0, 27);
|
||||
Array.Copy(exactData, 52, this.battery, 0, 6);
|
||||
}
|
||||
}
|
||||
|
||||
public bool VerifyBatteryVoltage(double minV = 3.19, double maxV = 3.75)
|
||||
=> minV <= this.battery.Volts && this.battery.Volts <= maxV;
|
||||
|
||||
public bool VerifySystemTimeDrift(uint max = 700)
|
||||
{
|
||||
var baseTimeUTC = new DateTime(2000, 1, 1, 0, 0, 0, DateTimeKind.Utc);
|
||||
var presentUTC = DateTime.UtcNow - baseTimeUTC;
|
||||
var totalSeconds = Math.Abs(presentUTC.TotalSeconds - this.systemTime);
|
||||
|
||||
return 0 <= totalSeconds && totalSeconds <= max;
|
||||
}
|
||||
|
||||
public bool VerifyRegisterAge(uint max = 365)
|
||||
{
|
||||
var manifacturingTimeUTC = new DateTime(this.manifacturingTime.Ticks, DateTimeKind.Utc);
|
||||
var totalManifacturingDays = new TimeSpan(manifacturingTimeUTC.Ticks).TotalDays;
|
||||
|
||||
return 0 <= totalManifacturingDays && totalManifacturingDays <= max;
|
||||
}
|
||||
|
||||
public static implicit operator AggregateSystemParameters(byte[] data)
|
||||
=> new AggregateSystemParameters(data);
|
||||
|
||||
public static implicit operator byte[] (AggregateSystemParameters _)
|
||||
=> new byte[] { 0xFD, 0xC6 };
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
namespace OmniPlus.Messages
|
||||
{
|
||||
public class FixedMessages
|
||||
{
|
||||
/// <summary>
|
||||
/// Each bytes array describes following state:
|
||||
/// 0: pulse, 1: direction, 2-3: fractional portion ml/Pulse, 4: meter size, 5 meter range
|
||||
/// </summary>
|
||||
private static readonly byte[][] flowCalibrationSetup = new byte[][]
|
||||
{
|
||||
new byte[] { 0x00, 0x00, 0xE1, 0x84, 0x05, 0x00 }, // 0: Meters of size 1 1/2"
|
||||
new byte[] { 0x00, 0x00, 0xE1, 0x84, 0x05, 0x00 }, // 1: Meters of size 1 1/2"
|
||||
new byte[] { 0x00, 0x00, 0xE1, 0x84, 0x05, 0x00 }, // 2: Meters of size 1 1/2"
|
||||
new byte[] { 0x00, 0x00, 0xE1, 0x84, 0x05, 0x00 }, // 3: Meters of size 1 1/2"
|
||||
new byte[] { 0x00, 0x00, 0xE1, 0x84, 0x05, 0x00 }, // 4: Meters of size 1 1/2"
|
||||
new byte[] { 0x00, 0x00, 0xE1, 0x84, 0x05, 0x00 }, // 5: Meters of size 1 1/2"
|
||||
new byte[] { 0x00, 0x00, 0xE1, 0x84, 0x06, 0x00 }, // 6: Meters of size 2"
|
||||
new byte[] { 0x01, 0x00, 0x8B, 0xC6, 0x07, 0x01 }, // 7: Meters of size 3"
|
||||
new byte[] { 0x01, 0x00, 0x8B, 0xC6, 0x08, 0x01 }, // 8: Meters of size 4"
|
||||
new byte[] { 0x06, 0x00, 0x72, 0x41, 0x09, 0x02 }, // 9: Meters of size 6"
|
||||
new byte[] { 0x01, 0x80, 0xCE, 0x8F, 0x0A, 0x03 }, // 10: Meters of size 8"
|
||||
new byte[] { 0x02, 0x80, 0xA3, 0x54, 0x0B, 0x04 }, // 11: Meters of size 10"
|
||||
};
|
||||
|
||||
|
||||
public static byte[] FlowCalibrationSetup(byte meterSize)
|
||||
=> flowCalibrationSetup[meterSize % flowCalibrationSetup.Length - 1];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
using OmniPlus.Types;
|
||||
|
||||
namespace OmniPlus.Messages
|
||||
{
|
||||
public class SetInputVolume : Bytes
|
||||
{
|
||||
/// <summary>
|
||||
/// 0: pulse, 1: direction, 2-3: fractional portion ml/Pulse, 4: meter size, 5 meter range
|
||||
/// </summary>
|
||||
private static readonly byte[][] defaults = new byte[][]
|
||||
{
|
||||
new byte[] { 0x00, 0x00, 0xE1, 0x84, 0x05, 0x00 }, // 0: Meters of size 1 1/2"
|
||||
new byte[] { 0x00, 0x00, 0xE1, 0x84, 0x05, 0x00 }, // 1: Meters of size 1 1/2"
|
||||
new byte[] { 0x00, 0x00, 0xE1, 0x84, 0x05, 0x00 }, // 2: Meters of size 1 1/2"
|
||||
new byte[] { 0x00, 0x00, 0xE1, 0x84, 0x05, 0x00 }, // 3: Meters of size 1 1/2"
|
||||
new byte[] { 0x00, 0x00, 0xE1, 0x84, 0x05, 0x00 }, // 4: Meters of size 1 1/2"
|
||||
new byte[] { 0x00, 0x00, 0xE1, 0x84, 0x05, 0x00 }, // 5: Meters of size 1 1/2"
|
||||
new byte[] { 0x00, 0x00, 0xE1, 0x84, 0x06, 0x00 }, // 6: Meters of size 2"
|
||||
new byte[] { 0x01, 0x00, 0x8B, 0xC6, 0x07, 0x01 }, // 7: Meters of size 3"
|
||||
new byte[] { 0x01, 0x00, 0x8B, 0xC6, 0x08, 0x01 }, // 8: Meters of size 4"
|
||||
new byte[] { 0x06, 0x00, 0x72, 0x41, 0x09, 0x02 }, // 9: Meters of size 6"
|
||||
new byte[] { 0x01, 0x80, 0xCE, 0x8F, 0x0A, 0x03 }, // 10: Meters of size 8"
|
||||
new byte[] { 0x02, 0x80, 0xA3, 0x54, 0x0B, 0x04 }, // 11: Meters of size 10"
|
||||
};
|
||||
|
||||
public SetInputVolume(byte[] data) : base(data)
|
||||
{
|
||||
}
|
||||
|
||||
public static implicit operator SetInputVolume(byte size)
|
||||
=> defaults[size % (defaults.Length - 1)];
|
||||
|
||||
public static implicit operator SetInputVolume(byte[] bytes)
|
||||
=> new SetInputVolume(bytes);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
using OmniPlus.Connection;
|
||||
using OmniPlus.Connection.Contracts;
|
||||
using OmniPlus.Contracts;
|
||||
|
||||
using System;
|
||||
using System.Threading;
|
||||
|
||||
namespace OmniPlus
|
||||
{
|
||||
internal class OmniConnection : IOmniConnection
|
||||
{
|
||||
private readonly IConnection connection;
|
||||
private readonly int timeoutSeconds;
|
||||
private readonly int sleeMilliseconds;
|
||||
|
||||
private byte[] data;
|
||||
private bool waiting;
|
||||
|
||||
public OmniConnection(string portName, int timeoutSeconds = 3000, int sleeMilliseconds = 300)
|
||||
{
|
||||
this.connection = new SPConnection(
|
||||
portName: portName,
|
||||
portSettings: new OmniPortSettings(),
|
||||
dataSettings: new OmniDataSettings(new byte[][]
|
||||
{
|
||||
// length, length index
|
||||
new byte[] { 1, 0 }, // Start byte
|
||||
new byte[] { 3, 0 }, // Control bytes
|
||||
new byte[] { 1, 0 }, // Data length byte
|
||||
new byte[] { 0, 4 }, // Data bytes
|
||||
new byte[] { 1, 0 }, // Alignment byte
|
||||
new byte[] { 2, 0 } // CRC 16 bytes
|
||||
}));
|
||||
this.timeoutSeconds = timeoutSeconds;
|
||||
this.sleeMilliseconds = sleeMilliseconds;
|
||||
}
|
||||
|
||||
public event StateEventHandler StateChanged
|
||||
{
|
||||
add => this.connection.StateChanged += value;
|
||||
remove => this.connection.StateChanged -= value;
|
||||
}
|
||||
|
||||
public void CloseConnection()
|
||||
=> this.connection.Dispose();
|
||||
|
||||
public void Dispose()
|
||||
=> this.connection.Dispose();
|
||||
|
||||
public void OpenConnection()
|
||||
=> this.connection.OpenConnection();
|
||||
|
||||
public byte[] Send(byte[] request)
|
||||
{
|
||||
this.waiting = true;
|
||||
|
||||
this.connection.DataReceived += this.Connection_DataReceived;
|
||||
|
||||
this.connection.Write(request);
|
||||
|
||||
var timeoutSeconds = this.timeoutSeconds;
|
||||
|
||||
while (this.waiting && timeoutSeconds > 0)
|
||||
{
|
||||
timeoutSeconds -= this.sleeMilliseconds;
|
||||
|
||||
Thread.Sleep(this.sleeMilliseconds);
|
||||
}
|
||||
|
||||
this.connection.DataReceived -= this.Connection_DataReceived;
|
||||
|
||||
return this.data ?? Array.Empty<byte>();
|
||||
}
|
||||
|
||||
private void Connection_DataReceived(IData data)
|
||||
{
|
||||
this.waiting = false;
|
||||
this.data = data.Data;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
using OmniPlus.Connection.Contracts;
|
||||
|
||||
namespace OmniPlus
|
||||
{
|
||||
class OmniDataSettings : IDataSettings
|
||||
{
|
||||
private readonly byte[][] template;
|
||||
private byte[][] messageTemplate;
|
||||
private byte[] messageContent;
|
||||
private int rowLength;
|
||||
private int row;
|
||||
private int col;
|
||||
private bool ok;
|
||||
private bool reading;
|
||||
|
||||
public OmniDataSettings(byte[][] template)
|
||||
=> this.template = template;
|
||||
|
||||
public byte[] Data => this.messageContent;
|
||||
|
||||
public bool ReadByte(byte data)
|
||||
{
|
||||
if (!this.reading)
|
||||
{
|
||||
this.reading = this.template[0][1] == data;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.ok = this.PrepareReading();
|
||||
|
||||
if (this.ok)
|
||||
{
|
||||
this.messageContent[this.col] = data;
|
||||
}
|
||||
}
|
||||
|
||||
return this.ok;
|
||||
}
|
||||
|
||||
public void StartReading()
|
||||
{
|
||||
this.template.CopyTo(this.messageTemplate, 0);
|
||||
|
||||
this.messageContent = new byte[8];
|
||||
this.row = 0;
|
||||
this.rowLength = this.messageTemplate[this.row][0];
|
||||
this.col = -1;
|
||||
this.reading = false;
|
||||
this.ok = this.rowLength > 0 && this.col < this.messageContent.Length;
|
||||
}
|
||||
|
||||
private bool PrepareReading()
|
||||
{
|
||||
this.col++;
|
||||
|
||||
if (this.rowLength - this.col > 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
this.row++;
|
||||
|
||||
if (this.row >= this.messageTemplate.Length)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var nextLength = this.messageTemplate[this.row][0];
|
||||
|
||||
if (nextLength == 0)
|
||||
{
|
||||
nextLength = this.messageTemplate[this.row][1];
|
||||
|
||||
for (int i = this.row + 1; i < this.messageTemplate.Length; i++)
|
||||
{
|
||||
this.messageTemplate[i][1] += nextLength;
|
||||
}
|
||||
|
||||
var messageContent = new byte[this.messageContent.Length + nextLength];
|
||||
|
||||
this.messageContent.CopyTo(messageContent, 0);
|
||||
|
||||
this.messageContent = messageContent;
|
||||
}
|
||||
|
||||
this.rowLength += nextLength;
|
||||
|
||||
return this.row < this.messageTemplate.Length && this.col < this.messageContent.Length;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{920435CC-ABDF-497A-9C34-1A8511F0CB56}</ProjectGuid>
|
||||
<OutputType>Exe</OutputType>
|
||||
<RootNamespace>OmniPlus</RootNamespace>
|
||||
<AssemblyName>OmniPlus</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.8.1</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||
<Deterministic>true</Deterministic>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Connection\Contracts\IConnection.cs" />
|
||||
<Compile Include="Connection\Contracts\IData.cs" />
|
||||
<Compile Include="Connection\Contracts\IDataSettings.cs" />
|
||||
<Compile Include="Connection\Contracts\IPortSettings.cs" />
|
||||
<Compile Include="Connection\ReadEventHandler.cs" />
|
||||
<Compile Include="Connection\SPConnection.cs" />
|
||||
<Compile Include="Connection\BaudRate.cs" />
|
||||
<Compile Include="Contracts\IOmniConnection.cs" />
|
||||
<Compile Include="Connection\DataBits.cs" />
|
||||
<Compile Include="Connection\StateEventHandler.cs" />
|
||||
<Compile Include="OmniDataSettings.cs" />
|
||||
<Compile Include="Messages\AggregateSystemParameters.cs" />
|
||||
<Compile Include="Messages\FixedMessages.cs" />
|
||||
<Compile Include="Messages\SetInputVolume.cs" />
|
||||
<Compile Include="OmniConnection.cs" />
|
||||
<Compile Include="OmniPortSettings.cs" />
|
||||
<Compile Include="OmniRegister.cs" />
|
||||
<Compile Include="Program.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Connection\SPState.cs" />
|
||||
<Compile Include="Types\ASCIIString.cs" />
|
||||
<Compile Include="Types\Battery.cs" />
|
||||
<Compile Include="Types\Bytes.cs" />
|
||||
<Compile Include="Types\Seconds.cs" />
|
||||
<Compile Include="Types\TypesExtensions.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="App.config" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
</Project>
|
||||
@@ -0,0 +1,22 @@
|
||||
using OmniPlus.Connection;
|
||||
using OmniPlus.Connection.Contracts;
|
||||
|
||||
using System.IO.Ports;
|
||||
|
||||
namespace OmniPlus
|
||||
{
|
||||
public class OmniPortSettings : IPortSettings
|
||||
{
|
||||
public BaudRate BaudRate => BaudRate.Bps4800;
|
||||
|
||||
public Parity Parity => Parity.None;
|
||||
|
||||
public DataBits DataBits => DataBits.B8;
|
||||
|
||||
public StopBits StopBits => StopBits.One;
|
||||
|
||||
public System.Boolean RtsEnbaled => true;
|
||||
|
||||
public System.Boolean DtrEnabled => false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
using OmniPlus.Connection;
|
||||
using OmniPlus.Contracts;
|
||||
|
||||
using System;
|
||||
|
||||
namespace OmniPlus
|
||||
{
|
||||
public class OmniRegister
|
||||
{
|
||||
private readonly IOmniConnection omniConnection;
|
||||
|
||||
private bool connectionAvailable;
|
||||
|
||||
public OmniRegister(string portName)
|
||||
{
|
||||
this.omniConnection = new OmniConnection(portName);
|
||||
this.omniConnection.StateChanged += OmniConnection_StateChanged;
|
||||
this.omniConnection.OpenConnection();
|
||||
}
|
||||
|
||||
public bool EnsureRegisterInitialized()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool EnsureRegisterSealed()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
private void OmniConnection_StateChanged(SPState state, string message)
|
||||
{
|
||||
// TODO: handle, log - changes
|
||||
|
||||
Console.WriteLine($"[{state}] {message}");
|
||||
|
||||
this.connectionAvailable = state == SPState.Opened;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
using OmniPlus.Connection;
|
||||
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Text;
|
||||
|
||||
namespace OmniPlus
|
||||
{
|
||||
class Program
|
||||
{
|
||||
static void Main(string[] args)
|
||||
{
|
||||
//var queue = new ConcurrentQueue<byte>();
|
||||
//var dataSettings = new OmniIrdaSettings();
|
||||
//var parsingData = true;
|
||||
|
||||
//dataSettings.StartReading();
|
||||
|
||||
//for (byte i = (byte)'a'; i < (byte)'a' + 26; i++)
|
||||
//{
|
||||
// queue.Enqueue(i);
|
||||
//}
|
||||
|
||||
//while (parsingData)
|
||||
//{
|
||||
// parsingData = queue.TryDequeue(out byte current) && dataSettings.ReadByte(current);
|
||||
//}
|
||||
|
||||
//parsingData = false;
|
||||
|
||||
//Console.WriteLine(Encoding.ASCII.GetString(dataSettings.Data));
|
||||
|
||||
//var test = new SPConnection(null, null, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("OmniPlus")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("OmniPlus")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2023")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("920435cc-abdf-497a-9c34-1a8511f0cb56")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
@@ -0,0 +1,19 @@
|
||||
namespace OmniPlus.Types
|
||||
{
|
||||
using System;
|
||||
using System.Text;
|
||||
|
||||
public class ASCIIString : Bytes
|
||||
{
|
||||
private readonly string value;
|
||||
|
||||
public ASCIIString(byte[] data) : base(data)
|
||||
=> this.value = Encoding.ASCII.GetString(this.data);
|
||||
|
||||
public override string ToString()
|
||||
=> this.value;
|
||||
|
||||
public static implicit operator ASCIIString(byte[] data)
|
||||
=> new ASCIIString(data ?? Array.Empty<byte>());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
namespace OmniPlus.Types
|
||||
{
|
||||
using System;
|
||||
|
||||
public class Battery : Bytes
|
||||
{
|
||||
private readonly ushort volts;
|
||||
private readonly uint rawADC;
|
||||
|
||||
public Battery(byte[] data) : base(data)
|
||||
{
|
||||
this.volts = BitConverter.ToUInt16(this.data, 0);
|
||||
this.rawADC = BitConverter.ToUInt32(this.data, 2);
|
||||
}
|
||||
|
||||
public double Volts => this.volts / 1000.0;
|
||||
|
||||
public override string ToString()
|
||||
=> $"{this.volts}mV, {this.rawADC} ADC";
|
||||
|
||||
public static implicit operator Battery(byte[] data)
|
||||
=> new Battery(data ?? Array.Empty<byte>());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
namespace OmniPlus.Types
|
||||
{
|
||||
using System;
|
||||
|
||||
public class Bytes
|
||||
{
|
||||
protected readonly byte[] data;
|
||||
|
||||
public Bytes(byte[] data)
|
||||
=> this.data = data;
|
||||
|
||||
public string ToHexString()
|
||||
=> BitConverter.ToString(this.data);
|
||||
|
||||
public static implicit operator byte[] (Bytes bytes)
|
||||
=> bytes.data ?? Array.Empty<byte>();
|
||||
|
||||
public static implicit operator Bytes (byte[] bytes)
|
||||
=> new Bytes(bytes ?? Array.Empty<byte>());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
namespace OmniPlus.Types
|
||||
{
|
||||
using System;
|
||||
|
||||
public class Seconds : Bytes
|
||||
{
|
||||
private readonly uint seconds;
|
||||
|
||||
public Seconds(byte[] data) : base(data)
|
||||
=> this.seconds = BitConverter.ToUInt32(data, 0);
|
||||
|
||||
public long Ticks => this.seconds * 10_000_000;
|
||||
|
||||
public override string ToString()
|
||||
=> this.seconds.ToString();
|
||||
|
||||
public static implicit operator Seconds(byte[] data)
|
||||
=> new Seconds(data ?? Array.Empty<byte>());
|
||||
|
||||
public static implicit operator uint(Seconds seconds)
|
||||
=> seconds?.seconds ?? default(uint);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
namespace OmniPlus.Types
|
||||
{
|
||||
public static class TypesExtensions
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user