Base comunication for OMNI+ register

This commit is contained in:
Stoyan Zlatev
2023-10-17 15:01:33 +02:00
parent f88124096b
commit 70bf9bbb5f
37 changed files with 694 additions and 641 deletions
@@ -1,16 +0,0 @@
using OmniPlus.Connection.EventHandlers;
using System;
namespace OmniPlus.Connection.Contracts
{
internal interface IConnection : IDisposable
{
event ReadEventHandler DataReceived;
event StateEventHandler StateChanged;
void OpenConnection();
void Send(IRequest request);
}
}
@@ -1,21 +0,0 @@
using OmniPlus.Connection.Enums;
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; }
}
}
@@ -1,7 +0,0 @@
namespace OmniPlus.Connection.Contracts
{
internal interface IRequest
{
byte[] ToByteArray();
}
}
@@ -1,11 +0,0 @@
namespace OmniPlus.Connection.Contracts
{
internal interface IResponse
{
byte[] Bytes { get; }
bool ReadByte(byte data);
void StartReading();
}
}
@@ -0,0 +1,15 @@
using OmniPlus.Connection.Events;
namespace OmniPlus.Connection.Contracts
{
public interface ISerialPortConnection
{
event SerialPortStateChangedEventHandler StateChanged;
void Write(SerialPortMessage message);
void Close();
void Open();
}
}
@@ -0,0 +1,7 @@
namespace OmniPlus.Connection.Contracts
{
public interface ISerialPortReader
{
void Read(byte b);
}
}
+14 -15
View File
@@ -1,20 +1,19 @@
namespace OmniPlus.Connection.Enums
{
public enum BaudRate : int
public enum BaudRate
{
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
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
}
}
+5 -5
View File
@@ -1,10 +1,10 @@
namespace OmniPlus.Connection.Enums
{
public enum DataBits : int
public enum DataBits
{
B8 = 8,
B7 = 7,
B6 = 6,
B5 = 5
X5 = 5,
X6 = 6,
X7 = 7,
X8 = 8
}
}
@@ -1,11 +1,11 @@
namespace OmniPlus.Connection.Enums
{
internal enum SPState
public enum SerialPortState
{
Closed,
Disposed,
Error,
PinChanged,
Opened
ErrorReceived,
Open
}
}
@@ -1,6 +0,0 @@
using OmniPlus.Connection.Contracts;
namespace OmniPlus.Connection.EventHandlers
{
internal delegate void ReadEventHandler(IResponse data);
}
@@ -1,6 +0,0 @@
using OmniPlus.Connection.Enums;
namespace OmniPlus.Connection.EventHandlers
{
internal delegate void StateEventHandler(SPState state, string message);
}
@@ -0,0 +1,6 @@
using OmniPlus.Connection.Enums;
namespace OmniPlus.Connection.Events
{
public delegate void SerialPortStateChangedEventHandler(SerialPortState state, string message);
}
-186
View File
@@ -1,186 +0,0 @@
using OmniPlus.Connection.Contracts;
using OmniPlus.Connection.Enums;
using OmniPlus.Connection.EventHandlers;
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 IResponse response;
private event Action bytesReceived;
private ConcurrentQueue<byte> data;
private SerialPort serialPort;
private bool parsingData;
public SPConnection(string portName, IPortSettings portSettings, IResponse dataSettings)
{
this.portName = portName;
this.portSettings = portSettings;
this.response = 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 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}");
}
}
public void Send(IRequest request)
{
var data = request.ToByteArray();
if (data?.Length > 0 && this.serialPort.IsOpen)
{
lock (this.serialPort)
{
this.serialPort.Write(data, 0, data.Length);
}
}
}
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.response.StartReading();
while (this.parsingData)
{
this.parsingData = this.data.TryDequeue(out byte current) && this.response.ReadByte(current);
}
this.DataReceived?.Invoke(this.response);
}
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();
}
}
-9
View File
@@ -1,9 +0,0 @@
using OmniPlus.Connection.Contracts;
namespace OmniPlus.Connection
{
internal abstract class SPRequest : IRequest
{
public abstract byte[] ToByteArray();
}
}
-94
View File
@@ -1,94 +0,0 @@
using OmniPlus.Connection.Contracts;
namespace OmniPlus.Connection
{
internal abstract class SPResponse : IResponse
{
private readonly byte[][] template;
private readonly byte[][] messageTemplate;
private int rowLength;
private int row;
private int col;
private bool ok;
private bool reading;
public SPResponse(byte[][] template)
{
this.template = template;
this.messageTemplate = template;
}
public byte[] Bytes { get; private set; }
public bool ReadByte(byte data)
{
if (!this.reading)
{
this.reading = this.template[0][1] == data;
}
else
{
this.ok = this.PrepareReading();
if (this.ok)
{
this.Bytes[this.col] = data;
}
}
return this.ok;
}
public void StartReading()
{
this.template.CopyTo(this.messageTemplate, 0);
this.Bytes = 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.Bytes.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 bytesLength = this.Bytes.Length;
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[bytesLength + nextLength];
this.Bytes.CopyTo(messageContent, 0);
this.Bytes = messageContent;
}
this.rowLength += nextLength;
return this.row < this.messageTemplate.Length && this.col < bytesLength;
}
}
}
@@ -0,0 +1,181 @@
using OmniPlus.Connection.Contracts;
using OmniPlus.Connection.Enums;
using OmniPlus.Connection.Events;
using System;
using System.Collections.Concurrent;
using System.IO;
using System.IO.Ports;
namespace OmniPlus.Connection
{
public abstract class SerialPortConnection : ISerialPortConnection
{
private event Action Read;
private event Action<string> Log;
private SerialPort serialPort;
private SerialPortState state;
protected bool reading;
protected SerialPortOptions options;
protected ConcurrentQueue<byte> stream;
protected SerialPortConnection()
=> this.options = new SerialPortOptions();
public event SerialPortStateChangedEventHandler StateChanged;
protected bool open => this.state == SerialPortState.Open;
public void Close()
{
if (this.serialPort != null)
{
this.serialPort.DataReceived -= this.Port_DataReceived;
this.serialPort.Disposed -= this.Port_Disposed;
this.serialPort.ErrorReceived -= this.Port_ErrorReceived;
this.serialPort.PinChanged -= this.Port_PinChanged;
}
this.serialPort?.Close();
this.stream = null;
this.serialPort = null;
this.state = SerialPortState.Closed;
this.StateChanged?.Invoke(this.state, $"{this.options.PortName} closed.");
this.Read -= this.SerialPortConnection_Read;
this.Log -= this.SerialPortConnection_Log;
this.StateChanged -= this.SerialPortConnection_StateChanged;
}
public void Open()
{
this.Close();
try
{
File.AppendAllText(this.options.LogFile, string.Empty);
this.Log += this.SerialPortConnection_Log;
this.StateChanged += this.SerialPortConnection_StateChanged;
}
catch (Exception e)
{
this.state = SerialPortState.ErrorReceived;
Console.WriteLine($"[{this.state}] {this.options.PortName}: {e}");
}
try
{
this.stream = new ConcurrentQueue<byte>();
this.serialPort = new System.IO.Ports.SerialPort
{
PortName = options.PortName,
BaudRate = (int)options.BaudRate,
DataBits = (int)options.DataBits,
Parity = options.Parity,
StopBits = options.StopBits,
RtsEnable = options.RtsEnabled,
DtrEnable = options.DtrEnabled
};
this.serialPort.DataReceived += this.Port_DataReceived;
this.serialPort.Disposed += this.Port_Disposed;
this.serialPort.ErrorReceived += this.Port_ErrorReceived;
this.serialPort.PinChanged += this.Port_PinChanged;
this.serialPort.Open();
this.state = SerialPortState.Open;
this.Read += this.SerialPortConnection_Read;
this.StateChanged?.Invoke(this.state, $"{this.options.PortName} opened.");
}
catch (Exception e)
{
this.state = SerialPortState.ErrorReceived;
this.StateChanged?.Invoke(this.state, $"{this.options.PortName}: {e}");
this.Close();
}
}
public virtual void Write(SerialPortMessage message)
{
if (this.open && message.Length > 0)
{
this.serialPort.Write(message, 0, message.Length);
}
this.Log?.Invoke($"RX: {BitConverter.ToString(message)}");
}
protected abstract void SerialPortConnection_Read();
private void Port_PinChanged(object sender, SerialPinChangedEventArgs args)
{
this.state = SerialPortState.PinChanged;
this.StateChanged?.Invoke(SerialPortState.PinChanged, $"{this.options.PortName} {args.EventType}.");
this.Close();
}
private void Port_ErrorReceived(object sender, SerialErrorReceivedEventArgs args)
{
this.state = SerialPortState.ErrorReceived;
this.StateChanged?.Invoke(SerialPortState.ErrorReceived, $"{this.options.PortName} {args.EventType}.");
this.Close();
}
private void Port_Disposed(object sender, EventArgs args)
{
this.state = SerialPortState.Disposed;
this.StateChanged?.Invoke(SerialPortState.Disposed, $"{this.options.PortName} disposed.");
this.Close();
}
private void Port_DataReceived(object sender, SerialDataReceivedEventArgs args)
{
if (this.open && sender is System.IO.Ports.SerialPort port && port.BytesToRead > 0)
{
var bytesLength = port.BytesToRead;
var bytes = new byte[bytesLength];
var lock_object = new object();
lock (lock_object)
{
port.Read(bytes, 0, bytesLength);
}
foreach (var item in bytes)
{
this.stream.Enqueue(item);
}
if (!this.reading)
{
this.Read?.Invoke();
}
this.Log?.Invoke($"TX: {BitConverter.ToString(bytes)}");
}
}
private void SerialPortConnection_Log(string message)
=> File.AppendAllText(this.options.LogFile, $"{message}{Environment.NewLine}");
private void SerialPortConnection_StateChanged(SerialPortState state, string message)
=> File.AppendAllText(this.options.LogFile, $"[{state}] {message}{Environment.NewLine}");
}
}
@@ -0,0 +1,35 @@
using System;
namespace OmniPlus.Connection
{
public abstract class SerialPortMessage
{
protected readonly byte[] bytes;
protected readonly byte[] payload;
protected SerialPortMessage(byte[] bytes, bool full)
{
if (full)
{
this.bytes = bytes;
this.payload = this.ParseMessage(bytes);
}
else
{
this.payload = bytes;
this.bytes = this.CreateMessage(bytes);
}
}
public int Length => this.bytes?.Length ?? 0;
public byte[] Payload => this.payload;
protected abstract byte[] CreateMessage(byte[] payload);
protected abstract byte[] ParseMessage(byte[] message);
public static implicit operator byte[](SerialPortMessage message)
=> message?.bytes ?? Array.Empty<byte>();
}
}
@@ -0,0 +1,40 @@
using OmniPlus.Connection.Enums;
using System.IO.Ports;
namespace OmniPlus.Connection
{
public class SerialPortOptions
{
public SerialPortOptions()
{
foreach (var portName in System.IO.Ports.SerialPort.GetPortNames())
{
this.PortName = portName;
break;
}
this.BaudRate = BaudRate.X4800;
this.DataBits = DataBits.X8;
this.Parity = Parity.None;
this.StopBits = StopBits.One;
}
public string PortName { get; set; }
public BaudRate BaudRate { get; set; } = BaudRate.X4800;
public Parity Parity { get; set; } = Parity.None;
public DataBits DataBits { get; set; } = DataBits.X8;
public StopBits StopBits { get; set; } = StopBits.One;
public bool RtsEnabled { get; set; }
public bool DtrEnabled { get; set; }
public string LogFile { get; set; }
}
}
+61
View File
@@ -0,0 +1,61 @@
using System;
namespace OmniPlus.Connections
{
public static class Extensions
{
/// <summary>
/// TODO: Test calculated crc
/// </summary>
/// <param name="message">The message for CRC16.</param>
/// <param name="start">The start index.</param>
/// <param name="length">The length from the start index.</param>
/// <returns>Two bytes array from the calculated CRC16 in LSB0.</returns>
public static byte[] CalculateCRC(this byte[] message, int start, int length)
{
var test = default(byte);
var zeichen = default(byte);
var crcSum = ushort.MaxValue;
var messageLength = length - start;
while (start < messageLength)
{
zeichen = message[start];
start++;
for (byte h = 0; h < 8; h++)
{
test = 0;
if ((crcSum & 0x8000) != 0)
{
test = 0x80;
}
crcSum <<= 1;
if (((zeichen & 0x80) ^ test) != 0)
{
crcSum ^= 0x1021;
}
zeichen <<= 1;
}
}
return BitConverter.GetBytes(crcSum);
}
public static byte[] CalculateCheckSum16(this byte[] bytes, int length)
{
short checksum = 0;
for (int i = 0; i < length; i++)
{
checksum += bytes[i];
}
return BitConverter.GetBytes(checksum);
}
}
}
@@ -0,0 +1,121 @@
namespace OmniPlus.Connections
{
using OmniPlus.Connection;
using OmniPlus.Connection.Enums;
using OmniPlus.Connections.Messages;
using System;
using System.IO.Ports;
using System.Threading;
public class IrdaConnection : SerialPortConnection
{
internal const byte MSG_START = 0x9B;
internal const byte MSG_OMNI2PC = 0x43;
internal const byte MSG_PC2OMNI = 0x33;
private event Action<IrdaMessage> messageReceived;
public IrdaConnection(string portName)
{
this.options.PortName = portName;
this.options.BaudRate = BaudRate.X4800;
this.options.DataBits = DataBits.X8;
this.options.Parity = Parity.None;
this.options.StopBits = StopBits.One;
this.options.RtsEnabled = true;
}
public byte[] Write(byte[] command, int timeout, int delay)
{
var ui1236Request = new UI1236Message(command);
var irdaRequest = new IrdaMessage(ui1236Request);
var responseBytes = Array.Empty<byte>();
var received = false;
this.messageReceived += irdaResponse =>
{
var ui1236Response = new UI1236Message(irdaResponse.Payload, true);
responseBytes = ui1236Response.Payload;
received = true;
};
this.Write(irdaRequest);
#region Temporary
this.stream = new System.Collections.Concurrent.ConcurrentQueue<byte>(
new byte[] { 0xFF, 0x01, 0x25, 0x00, 0x80, 0x9B, 0x33, 0x04, 0x0D, 0x05, 0x08, 0x0C, 0xFF, 0x01, 0x25, 0x00, 0x80, 0x88 });
this.SerialPortConnection_Read();
#endregion
while (!received && timeout >= 0)
{
timeout -= delay;
Thread.Sleep(delay);
}
return responseBytes;
}
protected override void SerialPortConnection_Read()
{
this.reading = true;
var message = default(IrdaMessage);
while (this.reading)
{
if (!this.stream.TryDequeue(out byte start))
{
break;
}
if (start != MSG_START)
{
continue;
}
_ = this.stream.TryDequeue(out byte type);
_ = this.stream.TryDequeue(out byte length);
var payloadLength = length * 2;
var payload = new byte[payloadLength];
for (int i = 0; i < payloadLength; i++)
{
if (this.stream.TryDequeue(out byte paybyte))
{
payload[i] = paybyte;
}
else break;
}
message = new IrdaMessage(payload);
message.Start = start;
message.Type = type;
message.DataLength = length;
var crc16 = new byte[2];
for (int i = 0; i < IrdaMessage.CRC_LENGTH; i++)
{
if (this.stream.TryDequeue(out byte crcbyte))
{
crc16[i] = crcbyte;
}
else break;
}
message.CopyCRC16(crc16, 0);
break;
}
this.reading = false;
this.messageReceived?.Invoke(message);
}
}
}
@@ -0,0 +1,80 @@
using OmniPlus.Connection;
using System;
namespace OmniPlus.Connections.Messages
{
public class IrdaMessage : SerialPortMessage
{
public const int MIN_LENGTH = 5;
public const int CRC_LENGTH = 2;
public IrdaMessage(byte[] bytes, bool full = false) : base(bytes, full)
{
}
public byte Start
{
get => this.bytes[0];
set => this.bytes[0] = value;
}
public byte Type
{
get => this.bytes[1];
set => this.bytes[1] = value;
}
public byte DataLength
{
get => this.bytes[2];
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];
message[index++] = IrdaConnection.MSG_START;
message[index++] = IrdaConnection.MSG_PC2OMNI;
message[index++] = (byte)(messageLength / 2);
payload.CopyTo(message, index);
messageLength = message.Length;
var crc16 = message.CalculateCRC(0, messageLength - CRC_LENGTH);
message[messageLength - 2] = crc16[1];
message[messageLength - 1] = crc16[0];
return message;
}
protected override byte[] ParseMessage(byte[] message)
{
var payloadLength = message.Length - MIN_LENGTH;
var payload = new byte[payloadLength];
Array.Copy(message, 3, payload, 0, payloadLength);
return payload;
}
}
}
@@ -0,0 +1,4 @@
namespace OmniPlus.Connections.Messages
{
public delegate byte[] MessageHandler(byte[] command, int timeout, int delay);
}
@@ -0,0 +1,47 @@
using OmniPlus.Connection;
using System;
namespace OmniPlus.Connections.Messages
{
public class UI1236Message : SerialPortMessage
{
public const int MIN_LENGTH = 5;
public const byte START_BYTE = 0x0D;
public UI1236Message(byte[] bytes, bool full = false) : base(bytes, full)
{
}
protected override byte[] CreateMessage(byte[] payload)
{
var length = payload.Length + MIN_LENGTH;
var evenOffset = length % 2;
length += evenOffset;
var index = 0;
var message = new byte[length];
message[index++] = START_BYTE;
message[index++] = (byte)(length - 3);
message[index++] = 0x08; // TODO: control byte
payload.CopyTo(message, index);
var checksum = message.CalculateCheckSum16(length);
message[length - evenOffset - 2] = checksum[1];
message[length - evenOffset - 1] = checksum[0];
return message;
}
protected override byte[] ParseMessage(byte[] message)
{
var payloadLength = message[1] - (message.Length - message[1]);
var payload = new byte[payloadLength];
Array.Copy(message, 3, payload, 0, payloadLength);
return payload;
}
}
}
@@ -0,0 +1,30 @@
using OmniPlus.Connection;
using OmniPlus.Connection.Enums;
using System.IO.Ports;
namespace OmniPlus.Connections
{
public class UniProConnection : SerialPortConnection
{
public UniProConnection(string portName)
{
this.options.PortName = portName;
this.options.BaudRate = BaudRate.X2400;
this.options.DataBits = DataBits.X8;
this.options.Parity = Parity.None;
this.options.StopBits = StopBits.One;
this.options.RtsEnabled = true;
}
public byte[] Write(byte[] command, int timeout, int delay)
{
throw new System.NotImplementedException();
}
protected override void SerialPortConnection_Read()
{
throw new System.NotImplementedException();
}
}
}
@@ -1,18 +0,0 @@
using OmniPlus.Connection.Contracts;
using OmniPlus.Connection.EventHandlers;
using System;
namespace OmniPlus.Contracts
{
internal interface IOmniConnection : IDisposable
{
event StateEventHandler StateChanged;
void CloseConnection();
void OpenConnection();
IResponse Send(IRequest request);
}
}
@@ -1,9 +0,0 @@
using System;
namespace OmniPlus.Contracts
{
public interface IOmniRegister : IDisposable
{
}
}
@@ -1,8 +0,0 @@
using OmniPlus.Connection.Contracts;
namespace OmniPlus.Contracts
{
internal interface IOmniRequest : IRequest
{
}
}
@@ -1,8 +0,0 @@
using OmniPlus.Connection.Contracts;
namespace OmniPlus.Contracts
{
internal interface IOmniResponse : IResponse
{
}
}
@@ -4,7 +4,7 @@
using System;
public class AggregateSystemParameters
public class SystemParameters
{
private readonly ASCIIString factoryBuild;
private readonly Seconds manifacturingTime;
@@ -14,7 +14,7 @@
private readonly byte rebootCount;
private readonly byte sealStatus;
private AggregateSystemParameters(byte[] data)
private SystemParameters(byte[] data)
{
this.rebootCount = default(byte);
this.sealStatus = default(byte);
@@ -61,10 +61,10 @@
return 0 <= totalManifacturingDays && totalManifacturingDays <= max;
}
public static implicit operator AggregateSystemParameters(byte[] data)
=> new AggregateSystemParameters(data);
public static implicit operator SystemParameters(byte[] data)
=> new SystemParameters(data);
public static implicit operator byte[] (AggregateSystemParameters _)
public static implicit operator byte[] (SystemParameters _)
=> new byte[] { 0xFD, 0xC6 };
}
}
-72
View File
@@ -1,72 +0,0 @@
using OmniPlus.Connection;
using OmniPlus.Connection.Contracts;
using OmniPlus.Connection.EventHandlers;
using OmniPlus.Contracts;
using System.Threading;
namespace OmniPlus
{
internal class OmniConnection : IOmniConnection
{
private readonly IConnection connection;
private readonly int timeoutSeconds;
private readonly int sleeMilliseconds;
private IResponse response;
private bool waiting;
public OmniConnection(string portName, int timeoutSeconds = 3000, int sleeMilliseconds = 300)
{
this.connection = new SPConnection(
portName: portName,
portSettings: new OmniPortSettings(),
dataSettings: new OmniResponse());
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 IResponse Send(IRequest request)
{
this.waiting = true;
this.connection.DataReceived += this.Connection_DataReceived;
this.connection.Send(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.response ?? default(IResponse);
}
private void Connection_DataReceived(IResponse response)
{
this.response = response;
this.waiting = false;
}
}
}
+15 -20
View File
@@ -43,33 +43,27 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Connection\Contracts\IConnection.cs" />
<Compile Include="Connection\Contracts\IRequest.cs" />
<Compile Include="Connection\Contracts\IResponse.cs" />
<Compile Include="Connection\Contracts\IPortSettings.cs" />
<Compile Include="Connection\EventHandlers\ReadEventHandler.cs" />
<Compile Include="Connection\SPConnection.cs" />
<Compile Include="Connections\Messages\MessageHandler.cs" />
<Compile Include="Connections\UniProConnection.cs" />
<Compile Include="Connection\Contracts\ISerialPortConnection.cs" />
<Compile Include="Connection\Contracts\ISerialPortReader.cs" />
<Compile Include="Connection\Enums\BaudRate.cs" />
<Compile Include="Connection\SPRequest.cs" />
<Compile Include="Connection\SPResponse.cs" />
<Compile Include="Contracts\IOmniConnection.cs" />
<Compile Include="Connection\Enums\SerialPortState.cs" />
<Compile Include="Connection\Events\SerialPortStateChangedEventHandler.cs" />
<Compile Include="Connection\SerialPortConnection.cs" />
<Compile Include="Connection\SerialPortMessage.cs" />
<Compile Include="Connection\SerialPortOptions.cs" />
<Compile Include="Connection\Enums\DataBits.cs" />
<Compile Include="Connection\EventHandlers\StateEventHandler.cs" />
<Compile Include="Contracts\IOmniRegister.cs" />
<Compile Include="Contracts\IOmniRequest.cs" />
<Compile Include="Contracts\IOmniResponse.cs" />
<Compile Include="OmniRequest.cs" />
<Compile Include="OmniResponse.cs" />
<Compile Include="Messages\AggregateSystemParameters.cs" />
<Compile Include="Messages\SystemParameters.cs" />
<Compile Include="Messages\FixedMessages.cs" />
<Compile Include="Messages\SetInputVolume.cs" />
<Compile Include="OmniConnection.cs" />
<Compile Include="OmniPortSettings.cs" />
<Compile Include="Connections\Messages\UI1236Message.cs" />
<Compile Include="Connections\IrdaConnection.cs" />
<Compile Include="Connections\Messages\IrdaMessage.cs" />
<Compile Include="Connections\Extensions.cs" />
<Compile Include="OmniRegister.cs" />
<Compile Include="OmniTemplates.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Connection\Enums\SPState.cs" />
<Compile Include="Types\ASCIIString.cs" />
<Compile Include="Types\Battery.cs" />
<Compile Include="Types\Bytes.cs" />
@@ -79,5 +73,6 @@
<ItemGroup>
<None Include="App.config" />
</ItemGroup>
<ItemGroup />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>
-22
View File
@@ -1,22 +0,0 @@
using OmniPlus.Connection.Contracts;
using OmniPlus.Connection.Enums;
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;
}
}
+21 -37
View File
@@ -1,55 +1,39 @@
using OmniPlus.Connection.Contracts;
using OmniPlus.Connection.Enums;
using OmniPlus.Contracts;
using System;
using System.Collections.Generic;
using System.IO;
using OmniPlus.Commands;
using OmniPlus.Connections;
using OmniPlus.Connections.Messages;
namespace OmniPlus
{
public class OmniRegister : IOmniRegister
public class OmniRegister
{
private readonly string loggingFile;
private readonly IOmniConnection omniConnection;
private readonly ICollection<IRequest> requests;
private readonly string portName;
private readonly IrdaConnection irdaConnection;
private readonly UniProConnection uniProConnection;
private bool connectionAvailable;
private MessageHandler messageHandler;
public OmniRegister(string portName)
{
this.loggingFile = this.GetOrCreateLoggingFile(portName);
this.requests = new List<IRequest>();
this.omniConnection = new OmniConnection(portName);
this.omniConnection.StateChanged += this.OmniConnection_StateChanged;
this.portName = portName;
this.irdaConnection = new IrdaConnection(portName);
this.uniProConnection = new UniProConnection(portName);
}
public void Dispose()
public void ActivateIrda()
{
this.omniConnection.StateChanged -= this.OmniConnection_StateChanged;
this.omniConnection.Dispose();
this.uniProConnection?.Close();
this.irdaConnection?.Open();
this.messageHandler = this.irdaConnection.Write;
}
private string GetOrCreateLoggingFile(string portName)
public void ActivateUniPro()
{
var directory = Directory.CreateDirectory(portName);
var fileName = $"{DateTime.Now:yyyy_MM_dd}.log";
var loggingFile = Path.Combine(directory.FullName, fileName);
if (!File.Exists(loggingFile))
{
File.WriteAllText(loggingFile, string.Empty);
}
return loggingFile;
this.irdaConnection?.Close();
this.uniProConnection?.Open();
this.messageHandler = this.uniProConnection.Write;
}
private void OmniConnection_StateChanged(SPState state, string message)
{
File.AppendAllText(this.loggingFile, $"[{DateTime.Now:hh:mm:ss}][{state}] {message}{Environment.NewLine}");
this.connectionAvailable = state == SPState.Opened;
}
internal SystemParameters GetSystemParameters()
=> this.messageHandler?.Invoke(new byte[] { 0xFD, 0xC6 }, 3000, 300);
}
}
-13
View File
@@ -1,13 +0,0 @@
using OmniPlus.Connection;
using OmniPlus.Contracts;
namespace OmniPlus
{
internal class OmniRequest : SPRequest, IOmniRequest
{
public override System.Byte[] ToByteArray()
{
throw new System.NotImplementedException();
}
}
}
-12
View File
@@ -1,12 +0,0 @@
using OmniPlus.Connection;
using OmniPlus.Contracts;
namespace OmniPlus
{
internal class OmniResponse : SPResponse, IOmniResponse
{
public OmniResponse() : base(OmniTemplates.IrdaResponse)
{
}
}
}
-15
View File
@@ -1,15 +0,0 @@
namespace OmniPlus
{
internal class OmniTemplates
{
public static byte[][] IrdaResponse => new byte[][]
{
new byte[] { 1, 0x9B }, // Start byte
new byte[] { 3, 0x00 }, // Control bytes
new byte[] { 1, 0x00 }, // Data length byte
new byte[] { 0, 0x04 }, // Data bytes
new byte[] { 1, 0x00 }, // Alignment byte
new byte[] { 2, 0x00 } // CRC 16 bytes
};
}
}
+4 -23
View File
@@ -1,32 +1,13 @@
using OmniPlus.Contracts;
using System;
using System.Collections.Generic;
namespace OmniPlus
namespace OmniPlus
{
class Program
{
static IOmniRegister omniRegister = new OmniRegister("COM1");
static void Main(string[] args)
{
var omniRegister = new OmniRegister("COM1");
omniRegister.ActivateIrda();
var systemParameters = omniRegister.GetSystemParameters();
}
}
public class Command
{
public Command(int index, int delay, params byte[] bytes)
{
this.Order = index;
this.Delay = delay;
this.Bytes = bytes;
}
public int Order { get; }
public int Delay { get; }
public byte[] Bytes { get; }
}
}