calculation of the correction factor
This commit is contained in:
@@ -1,14 +1,14 @@
|
||||
using OmniPlus.Enums;
|
||||
using OmniPlus.Hanlers;
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.IO.Ports;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace OmniPlus
|
||||
namespace OmniPlus.Connections
|
||||
{
|
||||
using OmniPlus.Enums;
|
||||
using OmniPlus.Hanlers;
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.IO.Ports;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
internal class IrdaConnection : SerialPortConnection
|
||||
{
|
||||
protected event DataReceivedHandler MessageReceived;
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
namespace OmniPlus.Connections
|
||||
{
|
||||
internal class IrdaEncoder : SerialDataEncoder
|
||||
{
|
||||
public byte Device2PC { get; } = SerialDataExtensions.IRDA_REG2PC;
|
||||
|
||||
public override bool TryDecode(byte[] encoded, out byte[] decoded)
|
||||
{
|
||||
decoded = encoded.FromIrdaMessage();
|
||||
|
||||
return decoded.Length > 0;
|
||||
}
|
||||
|
||||
public override bool TryEncode(byte[] decoded, out byte[] encoded)
|
||||
{
|
||||
encoded = decoded.ToIrdaMessage();
|
||||
|
||||
return encoded.Length > 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
namespace OmniPlus.Connections
|
||||
{
|
||||
using System;
|
||||
using System.Threading;
|
||||
|
||||
internal class IrdaStream : SerialDataReader
|
||||
{
|
||||
private readonly IrdaEncoder encoder;
|
||||
|
||||
public IrdaStream(SerialPortSettings settings) : base(settings)
|
||||
{
|
||||
this.encoder = new IrdaEncoder();
|
||||
}
|
||||
|
||||
public override void WriteBytes(params byte[] bytes)
|
||||
{
|
||||
if (this.encoder.TryEncode(bytes, out byte[] message))
|
||||
{
|
||||
base.WriteBytes(1, 1, 1, 1);
|
||||
|
||||
Thread.Sleep(1);
|
||||
|
||||
base.WriteBytes(message);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void BeginRead(byte[] buffer)
|
||||
{
|
||||
var start = Array.IndexOf(buffer, this.encoder.Device2PC);
|
||||
|
||||
if (start >= 0)
|
||||
{
|
||||
if (this.encoder.TryDecode(buffer, out byte[] message))
|
||||
{
|
||||
this.EnqueueMessage(message);
|
||||
this.RemoveRange(message.Length);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
this.RemoveRange(buffer.Length);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
namespace OmniPlus.Connections
|
||||
{
|
||||
using System;
|
||||
using System.IO.Ports;
|
||||
using System.Text;
|
||||
|
||||
internal class Program
|
||||
{
|
||||
static void Main(string[] args)
|
||||
{
|
||||
var number = "81623241198";
|
||||
var last = number.Length - 1;
|
||||
var line = string.Empty;
|
||||
|
||||
while (!string.IsNullOrEmpty(line = Console.ReadLine()))
|
||||
{
|
||||
Console.WriteLine();
|
||||
|
||||
var next = number + line[0];
|
||||
var request = new byte[] { };
|
||||
var response = new byte[] { };
|
||||
var settings = new SerialPortSettings
|
||||
{
|
||||
BaudRate = 115200,
|
||||
DataBits = 8,
|
||||
Parity = Parity.None,
|
||||
PortName = "COM1",
|
||||
StopBits = StopBits.One,
|
||||
};
|
||||
var foreground = Console.ForegroundColor;
|
||||
|
||||
using (var stream = new UI1236Stream(settings))
|
||||
{
|
||||
stream.Open();
|
||||
|
||||
request = new byte[] { 0x05 };
|
||||
Console.ForegroundColor = ConsoleColor.DarkYellow;
|
||||
Console.WriteLine($">>> {BitConverter.ToString(request)}");
|
||||
response = stream.Write(request);
|
||||
Console.ForegroundColor = ConsoleColor.DarkGreen;
|
||||
Console.WriteLine($"<<< {BitConverter.ToString(response)}");
|
||||
Console.ForegroundColor = ConsoleColor.DarkGray;
|
||||
Console.WriteLine($"... {Encoding.ASCII.GetString(response).Trim('\0', '\r', '\n')}");
|
||||
|
||||
request = new byte[] { 0x01 };
|
||||
Console.ForegroundColor = ConsoleColor.DarkYellow;
|
||||
Console.WriteLine($">>> {BitConverter.ToString(request)}");
|
||||
response = stream.Write(request);
|
||||
Console.ForegroundColor = ConsoleColor.DarkGreen;
|
||||
Console.WriteLine($"<<< {BitConverter.ToString(response)}");
|
||||
Console.ForegroundColor = ConsoleColor.DarkGray;
|
||||
Console.WriteLine($"... {Encoding.ASCII.GetString(response).Trim('\0', '\r', '\n')}");
|
||||
|
||||
request = new byte[14];
|
||||
request[0] = 0x02;
|
||||
Encoding.ASCII.GetBytes(next).CopyTo(request, 1);
|
||||
Console.ForegroundColor = ConsoleColor.DarkYellow;
|
||||
Console.WriteLine($">>> {BitConverter.ToString(request)}");
|
||||
response = stream.Write(request);
|
||||
Console.ForegroundColor = ConsoleColor.DarkGreen;
|
||||
Console.WriteLine($"<<< {BitConverter.ToString(response)}");
|
||||
Console.ForegroundColor = ConsoleColor.DarkGray;
|
||||
Console.WriteLine($"... {Encoding.ASCII.GetString(response).Trim('\0', '\r', '\n')}");
|
||||
|
||||
request = new byte[] { 0x01 };
|
||||
Console.ForegroundColor = ConsoleColor.DarkYellow;
|
||||
Console.WriteLine($">>> {BitConverter.ToString(request)}");
|
||||
response = stream.Write(request);
|
||||
Console.ForegroundColor = ConsoleColor.DarkGreen;
|
||||
Console.WriteLine($"<<< {BitConverter.ToString(response)}");
|
||||
Console.ForegroundColor = ConsoleColor.White;
|
||||
Console.WriteLine($"... {Encoding.ASCII.GetString(response).Trim('\0', '\r', '\n')}");
|
||||
|
||||
request = new byte[] { 0x03 };
|
||||
Console.ForegroundColor = ConsoleColor.DarkYellow;
|
||||
Console.WriteLine($">>> {BitConverter.ToString(request)}");
|
||||
response = stream.Write(request);
|
||||
Console.ForegroundColor = ConsoleColor.DarkGreen;
|
||||
Console.WriteLine($"<<< {BitConverter.ToString(response)}");
|
||||
Console.ForegroundColor = ConsoleColor.DarkGray;
|
||||
Console.WriteLine($"... {Encoding.ASCII.GetString(response).Trim('\0', '\r', '\n')}");
|
||||
|
||||
request = new byte[22];
|
||||
request[0] = 0x04;
|
||||
Encoding.ASCII.GetBytes($"SEN{next}").CopyTo(request, 1);
|
||||
Console.ForegroundColor = ConsoleColor.DarkYellow;
|
||||
Console.WriteLine($">>> {BitConverter.ToString(request)}");
|
||||
response = stream.Write(request);
|
||||
Console.ForegroundColor = ConsoleColor.DarkGreen;
|
||||
Console.WriteLine($"<<< {BitConverter.ToString(response)}");
|
||||
Console.ForegroundColor = ConsoleColor.DarkGray;
|
||||
Console.WriteLine($"... {Encoding.ASCII.GetString(response).Trim('\0', '\r', '\n')}");
|
||||
|
||||
request = new byte[] { 0x03 };
|
||||
Console.ForegroundColor = ConsoleColor.DarkYellow;
|
||||
Console.WriteLine($">>> {BitConverter.ToString(request)}");
|
||||
response = stream.Write(request);
|
||||
Console.ForegroundColor = ConsoleColor.DarkGreen;
|
||||
Console.WriteLine($"<<< {BitConverter.ToString(response)}");
|
||||
Console.ForegroundColor = ConsoleColor.White;
|
||||
Console.WriteLine($"... {Encoding.ASCII.GetString(response).Trim('\0', '\r', '\n')}");
|
||||
|
||||
Console.ForegroundColor = foreground;
|
||||
}
|
||||
|
||||
Console.WriteLine();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
namespace OmniPlus.Connections
|
||||
{
|
||||
internal abstract class SerialDataEncoder
|
||||
{
|
||||
public abstract bool TryDecode(byte[] encoded, out byte[] decoded);
|
||||
|
||||
public abstract bool TryEncode(byte[] decoded, out byte[] encoded);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,334 @@
|
||||
namespace OmniPlus.Connections
|
||||
{
|
||||
using System;
|
||||
|
||||
internal static class SerialDataExtensions
|
||||
{
|
||||
public const int BYTE_BITS = 8;
|
||||
|
||||
public const byte OxOO = 0x00;
|
||||
public const byte OxO1 = 0x01;
|
||||
public const byte OxO2 = 0x02;
|
||||
public const byte OxO3 = 0x03;
|
||||
|
||||
public const byte UNIPRO_START = 0x53;
|
||||
public const byte UNIPRO_PC2REG = 0x57;
|
||||
public const byte UNIPRO_REG2PC = 0x52;
|
||||
public const byte UNIPRO_STOP = 0x0D;
|
||||
public const byte UNIPRO_MIN_LENGTH = 4;
|
||||
|
||||
public const byte UI1236_START = 0x0D;
|
||||
public const byte UI1236_MIN_LENGTH = 5;
|
||||
public const byte UI1236_HED_LENGTH = 3;
|
||||
|
||||
public const byte IRDA_START = 0x9B;
|
||||
public const byte IRDA_PING = 0x82;
|
||||
public const byte IRDA_PC2REG = 0x33;
|
||||
public const byte IRDA_REG2PC = 0x43;
|
||||
public const byte IRDA_MIN_LENGTH = 5;
|
||||
public const byte IRDA_CRC_LENGTH = 2;
|
||||
|
||||
/// <summary>
|
||||
/// <para>UI1236 structure:</para>
|
||||
/// <para> 0. 0x0D - Start byte</para>
|
||||
/// <para> 1. .... - Length: max. 254</para>
|
||||
/// <para> 2. .... - Control byte</para>
|
||||
/// <para>3+n. .... - Payload</para>
|
||||
/// <para>n-2. .... - Checksum 0 </para>
|
||||
/// <para>n-1. .... - Checksum 1 </para>
|
||||
/// </summary>
|
||||
public static byte[] ToUI1236Message(this byte[] bytes)
|
||||
{
|
||||
var bytesLength = bytes.Length;
|
||||
var payloadLength = bytes.Length + UI1236_MIN_LENGTH;
|
||||
payloadLength += payloadLength % OxO2;
|
||||
|
||||
var index = OxOO;
|
||||
var message = new byte[payloadLength];
|
||||
message[index++] = UI1236_START;
|
||||
message[index++] = (byte)(bytesLength + UI1236_HED_LENGTH);
|
||||
|
||||
//OmniControlOptions control = OxOO;
|
||||
//control.ReturnResponse = true;
|
||||
//message[index++] = control;
|
||||
message[index++] = 0x08;
|
||||
|
||||
bytes.CopyTo(message, index);
|
||||
|
||||
var checksum = message.CalculateCheckSUM(message.Length - OxO2);
|
||||
var checksumIndex = bytesLength + UI1236_HED_LENGTH;
|
||||
message[checksumIndex++] = checksum[OxO1];
|
||||
message[checksumIndex++] = checksum[OxOO];
|
||||
|
||||
return message;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <para>UI1236 structure:</para>
|
||||
/// <para> 0. 0x0D - Start byte</para>
|
||||
/// <para> 1. .... - Length: max. 254</para>
|
||||
/// <para> 2. .... - Control byte</para>
|
||||
/// <para>3+n. .... - Payload</para>
|
||||
/// <para>n-2. .... - Checksum 0 </para>
|
||||
/// <para>n-1. .... - Checksum 1 </para>
|
||||
/// </summary>
|
||||
public static byte[] FromUI1236Message(this byte[] bytes)
|
||||
{
|
||||
var payload = new byte[OxOO];
|
||||
|
||||
if (bytes is null)
|
||||
{
|
||||
return payload;
|
||||
}
|
||||
|
||||
var payloadLength = bytes.Length - UI1236_MIN_LENGTH;
|
||||
|
||||
if (payloadLength <= OxOO)
|
||||
{
|
||||
return payload;
|
||||
}
|
||||
|
||||
payload = new byte[payloadLength];
|
||||
|
||||
Buffer.BlockCopy(bytes, OxO3, payload, OxOO, payloadLength);
|
||||
|
||||
return payload;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <para>UniPro structure:</para>
|
||||
/// <para> 0. .... - Start byte</para>
|
||||
/// <para> 1. .... - Direction</para>
|
||||
/// <para> 2. .... - Length</para>
|
||||
/// <para> .. .... - Payload</para>
|
||||
/// <para>n-1. .... - Stop byte</para>
|
||||
/// </summary>
|
||||
public static byte[] ToUniProMessage(this byte[] bytes)
|
||||
{
|
||||
var messageLength = (byte)(bytes.Length + UNIPRO_MIN_LENGTH);
|
||||
var message = new byte[messageLength];
|
||||
var index = OxOO;
|
||||
|
||||
message[index++] = UNIPRO_START;
|
||||
message[index++] = UNIPRO_PC2REG;
|
||||
message[index++] = messageLength;
|
||||
message[messageLength - OxO1] = UNIPRO_STOP;
|
||||
|
||||
bytes.CopyTo(message, index);
|
||||
|
||||
return message;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <para>UniPro structure:</para>
|
||||
/// <para> 0. .... - Start byte</para>
|
||||
/// <para> 1. .... - Direction</para>
|
||||
/// <para> 2. .... - Length</para>
|
||||
/// <para> .. .... - Payload</para>
|
||||
/// <para>n-1. .... - Stop byte</para>
|
||||
/// </summary>
|
||||
public static byte[] FromUniProMessage(this byte[] bytes)
|
||||
{
|
||||
var payload = new byte[OxOO];
|
||||
|
||||
if (bytes is null)
|
||||
{
|
||||
return payload;
|
||||
}
|
||||
|
||||
var payloadLength = bytes.Length - UNIPRO_MIN_LENGTH;
|
||||
|
||||
if (payloadLength <= OxOO)
|
||||
{
|
||||
return payload;
|
||||
}
|
||||
|
||||
payload = new byte[payloadLength];
|
||||
|
||||
Buffer.BlockCopy(bytes, OxO3, payload, OxOO, payloadLength);
|
||||
|
||||
return payload;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <para>Irda structure:</para>
|
||||
/// <para> 0. .... - Start byte</para>
|
||||
/// <para> 1. .... - Direction</para>
|
||||
/// <para> 2. .... - Length / 2</para>
|
||||
/// <para>3+n. .... - Payload</para>
|
||||
/// <para>n-3. .... - aligned byte</para>
|
||||
/// <para>n-2. .... - CRC16 0 </para>
|
||||
/// <para>n-1. .... - CRC16 1 </para>
|
||||
/// </summary>
|
||||
public static byte[] ToIrdaMessage(this byte[] bytes)
|
||||
{
|
||||
var payloadLength = bytes.Length;
|
||||
payloadLength += payloadLength % OxO2;
|
||||
|
||||
var index = OxOO;
|
||||
var message = new byte[payloadLength + IRDA_MIN_LENGTH];
|
||||
message[index++] = IRDA_START;
|
||||
message[index++] = IRDA_PC2REG;
|
||||
message[index++] = (byte)(payloadLength / OxO2);
|
||||
|
||||
bytes.CopyTo(message, index);
|
||||
|
||||
var messageLength = message.Length;
|
||||
var crc16 = message.CalculateCRC8408(1, messageLength - IRDA_CRC_LENGTH);
|
||||
message[messageLength - OxO2] = crc16[OxOO];
|
||||
message[messageLength - OxO1] = crc16[OxO1];
|
||||
|
||||
return message;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <para>Irda structure:</para>
|
||||
/// <para> 0. .... - Start byte</para>
|
||||
/// <para> 1. .... - Direction</para>
|
||||
/// <para> 2. .... - Length / 2</para>
|
||||
/// <para>3+n. .... - Payload</para>
|
||||
/// <para>n-3. .... - aligned byte</para>
|
||||
/// <para>n-2. .... - CRC16 0 </para>
|
||||
/// <para>n-1. .... - CRC16 1 </para>
|
||||
/// </summary>
|
||||
public static byte[] FromIrdaMessage(this byte[] bytes)
|
||||
{
|
||||
var payload = new byte[OxOO];
|
||||
|
||||
if (bytes is null)
|
||||
{
|
||||
return payload;
|
||||
}
|
||||
|
||||
var payloadLength = bytes.Length - IRDA_MIN_LENGTH;
|
||||
|
||||
if (payloadLength <= OxOO)
|
||||
{
|
||||
return payload;
|
||||
}
|
||||
|
||||
payload = new byte[payloadLength];
|
||||
|
||||
Buffer.BlockCopy(bytes, OxO3, payload, OxOO, payloadLength);
|
||||
|
||||
return payload;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <para>Irda structure:</para>
|
||||
/// <para> 0. .... - Start byte</para>
|
||||
/// <para> 1. .... - Direction</para>
|
||||
/// <para> 2. .... - Length / 2</para>
|
||||
/// <para>3+n. .... - Payload</para>
|
||||
/// <para>n-3. .... - aligned byte</para>
|
||||
/// <para>n-2. .... - CRC16 0 </para>
|
||||
/// <para>n-1. .... - CRC16 1 </para>
|
||||
/// </summary>
|
||||
public static byte[] FromIrdaMessage(this byte[] bytes, int start, out int length)
|
||||
{
|
||||
length = OxOO;
|
||||
|
||||
var payload = new byte[length];
|
||||
|
||||
if (bytes is null)
|
||||
{
|
||||
return payload;
|
||||
}
|
||||
|
||||
var bytesLength = bytes.Length;
|
||||
var payloadLengthIndex = start + 2;
|
||||
|
||||
if (bytesLength <= payloadLengthIndex)
|
||||
{
|
||||
return payload;
|
||||
}
|
||||
|
||||
var payloadLength = bytes[payloadLengthIndex] * 2;
|
||||
length = payloadLength + IRDA_MIN_LENGTH;
|
||||
|
||||
if (payloadLength <= OxOO)
|
||||
{
|
||||
return payload;
|
||||
}
|
||||
|
||||
payload = new byte[payloadLength];
|
||||
var payloadStart = payloadLengthIndex + 1;
|
||||
|
||||
Buffer.BlockCopy(bytes, payloadStart, payload, 0, payloadLength);
|
||||
|
||||
return payload;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <para>Irda structure:</para>
|
||||
/// <para> 0. .... - Start byte</para>
|
||||
/// <para> 1. .... - Direction</para>
|
||||
/// <para> 2. .... - Length / 2</para>
|
||||
/// <para>3+n. .... - Payload</para>
|
||||
/// <para>n-3. .... - aligned byte</para>
|
||||
/// <para>n-2. .... - CRC16 0 </para>
|
||||
/// <para>n-1. .... - CRC16 1 </para>
|
||||
/// </summary>
|
||||
public static byte[] FromIrdaMessage(this byte[] bytes, int start)
|
||||
{
|
||||
var bytesLength = bytes.Length;
|
||||
|
||||
if (bytes is null || bytesLength <= start)
|
||||
{
|
||||
return new byte[] { };
|
||||
}
|
||||
|
||||
var _length = bytes[start + 2] * 2;
|
||||
var _start = start + 3;
|
||||
|
||||
if (_start + _length >= bytesLength)
|
||||
{
|
||||
return new byte[] { };
|
||||
}
|
||||
|
||||
var data = new byte[_length];
|
||||
|
||||
Buffer.BlockCopy(bytes, _start, data, 0, _length);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
public static byte[] CalculateCRC8408(this byte[] message, int start, int length)
|
||||
{
|
||||
var crc = 0xFFFF;
|
||||
|
||||
for (int x = start; x < length; x++)
|
||||
{
|
||||
crc ^= 0x00FF & message[x];
|
||||
|
||||
for (int i = 8; i > OxOO; i--)
|
||||
{
|
||||
if ((crc & 0x0001) != OxOO)
|
||||
{
|
||||
crc = (crc >> OxO1) ^ 0x8408;
|
||||
}
|
||||
else
|
||||
{
|
||||
crc >>= OxO1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
crc = ~crc;
|
||||
|
||||
return BitConverter.GetBytes(crc);
|
||||
}
|
||||
|
||||
public static byte[] CalculateCheckSUM(this byte[] bytes, int length)
|
||||
{
|
||||
ushort checksum = OxOO;
|
||||
|
||||
for (int i = OxOO; i < length; i++)
|
||||
{
|
||||
checksum += bytes[i];
|
||||
}
|
||||
|
||||
return BitConverter.GetBytes(checksum);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,135 @@
|
||||
namespace OmniPlus.Connections
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
|
||||
internal abstract class SerialDataReader : SerialDataStream
|
||||
{
|
||||
private Thread thread;
|
||||
private List<byte> stream;
|
||||
private Queue<byte[]> messages;
|
||||
|
||||
protected SerialDataReader(SerialPortSettings settings) : base(settings)
|
||||
{
|
||||
}
|
||||
|
||||
public bool IsAlive
|
||||
{
|
||||
get
|
||||
{
|
||||
if (this.thread is null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return this.thread.IsAlive;
|
||||
}
|
||||
}
|
||||
|
||||
public override void Dispose()
|
||||
{
|
||||
this.StopListening();
|
||||
|
||||
base.Dispose();
|
||||
}
|
||||
|
||||
protected virtual void BeginRead(byte[] bytes)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
protected void ClearMessages()
|
||||
{
|
||||
if (this.messages != null)
|
||||
{
|
||||
this.messages.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
protected byte[] DequeueMessage()
|
||||
{
|
||||
if (this.messages != null && this.messages.Count > 0)
|
||||
{
|
||||
return this.messages.Dequeue();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
protected void EnqueueMessage(byte[] message)
|
||||
{
|
||||
if (this.messages != null)
|
||||
{
|
||||
this.messages.Enqueue(message);
|
||||
}
|
||||
}
|
||||
|
||||
protected void RemoveRange(int length)
|
||||
{
|
||||
if (this.stream != null)
|
||||
{
|
||||
this.stream.RemoveRange(0, length);
|
||||
}
|
||||
}
|
||||
|
||||
protected void StartListening()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (this.IsOpen)
|
||||
{
|
||||
this.stream = new List<byte>();
|
||||
this.messages = new Queue<byte[]>();
|
||||
this.thread = new Thread(this.BeginRead);
|
||||
this.thread.Start();
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
this.NotifyStateChanged(e);
|
||||
}
|
||||
}
|
||||
|
||||
protected void StopListening()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (this.IsAlive)
|
||||
{
|
||||
this.thread.Abort();
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
this.NotifyStateChanged(e);
|
||||
}
|
||||
|
||||
this.stream?.Clear();
|
||||
this.messages?.Clear();
|
||||
|
||||
this.messages = null;
|
||||
this.stream = null;
|
||||
this.thread = null;
|
||||
}
|
||||
|
||||
private void BeginRead()
|
||||
{
|
||||
this.NotifyStateChanged($"{nameof(IrdaStream)} - reading thread started.");
|
||||
|
||||
while (this.IsAlive)
|
||||
{
|
||||
var bytes = this.ReadBytes();
|
||||
|
||||
if (bytes.Length > 0)
|
||||
{
|
||||
this.stream.AddRange(bytes);
|
||||
}
|
||||
|
||||
this.BeginRead(this.stream.ToArray());
|
||||
}
|
||||
|
||||
this.NotifyStateChanged($"{nameof(IrdaStream)} - reading thread stoped.");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
namespace OmniPlus.Connections
|
||||
{
|
||||
using System;
|
||||
|
||||
internal class SerialDataStream : SerialPortStream
|
||||
{
|
||||
public SerialDataStream(SerialPortSettings settings) : base(settings)
|
||||
{
|
||||
}
|
||||
|
||||
public virtual byte[] ReadBytes()
|
||||
{
|
||||
var bytes = new byte[0];
|
||||
|
||||
try
|
||||
{
|
||||
if (this.IsOpen)
|
||||
{
|
||||
var length = this.serialPort.BytesToRead;
|
||||
|
||||
if (length > 1)
|
||||
{
|
||||
bytes = new byte[length];
|
||||
|
||||
this.serialPort.Read(bytes, 0, length);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
this.NotifyStateChanged(e);
|
||||
}
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
public virtual void WriteBytes(params byte[] bytes)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (this.IsOpen)
|
||||
{
|
||||
var _lock = new object();
|
||||
|
||||
lock (_lock)
|
||||
{
|
||||
this.serialPort.Write(bytes, 0, bytes.Length);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
this.NotifyStateChanged(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,14 +1,14 @@
|
||||
using OmniPlus.Enums;
|
||||
using OmniPlus.Hanlers;
|
||||
using OmniPlus.Options;
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.IO.Ports;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace OmniPlus
|
||||
namespace OmniPlus.Connections
|
||||
{
|
||||
using OmniPlus.Enums;
|
||||
using OmniPlus.Hanlers;
|
||||
using OmniPlus.Options;
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.IO.Ports;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
internal abstract class SerialPortConnection : IDisposable
|
||||
{
|
||||
protected event StateChangedEventHandler StateChanged;
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
namespace OmniPlus.Connections
|
||||
{
|
||||
using System.IO.Ports;
|
||||
|
||||
internal class SerialPortSettings
|
||||
{
|
||||
public int BaudRate { get; set; }
|
||||
|
||||
public int DataBits { get; set; }
|
||||
|
||||
public Parity Parity { get; set; }
|
||||
|
||||
public string PortName { get; set; }
|
||||
|
||||
public StopBits StopBits { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
namespace OmniPlus.Connections
|
||||
{
|
||||
using System;
|
||||
using System.IO.Ports;
|
||||
|
||||
internal abstract class SerialPortStream : IDisposable
|
||||
{
|
||||
protected SerialPort serialPort;
|
||||
|
||||
private readonly SerialPortSettings settings;
|
||||
|
||||
protected SerialPortStream(SerialPortSettings settings)
|
||||
{
|
||||
this.settings = settings;
|
||||
}
|
||||
|
||||
public event Action Connected;
|
||||
public event Action Disconnected;
|
||||
public event Action<object> StateChanged;
|
||||
|
||||
public bool IsOpen
|
||||
{
|
||||
get
|
||||
{
|
||||
if (this.serialPort is null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return this.serialPort.IsOpen;
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void Dispose()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (this.serialPort != null)
|
||||
{
|
||||
this.serialPort.Close();
|
||||
this.serialPort.Dispose();
|
||||
this.serialPort = null;
|
||||
|
||||
this.NotifyStateChanged($"{this} - disposed.");
|
||||
this.Disconnected?.Invoke();
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
this.NotifyStateChanged(e);
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void Open()
|
||||
{
|
||||
if (this.serialPort != null)
|
||||
{
|
||||
this.Dispose();
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
this.serialPort = new SerialPort
|
||||
{
|
||||
BaudRate = this.settings.BaudRate,
|
||||
DataBits = this.settings.DataBits,
|
||||
Parity = this.settings.Parity,
|
||||
PortName = this.settings.PortName,
|
||||
StopBits = this.settings.StopBits,
|
||||
};
|
||||
|
||||
this.serialPort.Open();
|
||||
|
||||
if (this.IsOpen)
|
||||
{
|
||||
this.NotifyStateChanged($"{this} - connected.");
|
||||
this.Connected?.Invoke();
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
this.NotifyStateChanged(e);
|
||||
}
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
if (this.serialPort is null)
|
||||
{
|
||||
return $"{this.settings.PortName}, " +
|
||||
$"{this.settings.BaudRate}, " +
|
||||
$"{this.settings.DataBits}, " +
|
||||
$"{this.settings.Parity}, " +
|
||||
$"{this.settings.StopBits}";
|
||||
}
|
||||
else
|
||||
{
|
||||
return $"{this.serialPort.PortName}, " +
|
||||
$"{this.serialPort.BaudRate}, " +
|
||||
$"{this.serialPort.DataBits}, " +
|
||||
$"{this.serialPort.Parity}, " +
|
||||
$"{this.serialPort.StopBits}";
|
||||
}
|
||||
}
|
||||
|
||||
protected void NotifyStateChanged(object state)
|
||||
{
|
||||
this.StateChanged?.Invoke(state);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
namespace OmniPlus.Connections
|
||||
{
|
||||
using System;
|
||||
|
||||
internal class SerialTextStream : SerialPortStream
|
||||
{
|
||||
public SerialTextStream(SerialPortSettings settings) : base(settings)
|
||||
{
|
||||
}
|
||||
|
||||
public string ReadLine()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (this.IsOpen)
|
||||
{
|
||||
return this.serialPort.ReadLine();
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
this.NotifyStateChanged(e);
|
||||
}
|
||||
|
||||
return default(string);
|
||||
}
|
||||
|
||||
public void WriteLine(string line)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (this.IsOpen)
|
||||
{
|
||||
var _lock = new object();
|
||||
|
||||
lock (_lock)
|
||||
{
|
||||
this.serialPort.WriteLine(line);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
this.NotifyStateChanged(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
namespace OmniPlus.Connections
|
||||
{
|
||||
internal class UI1236Encoder : SerialDataEncoder
|
||||
{
|
||||
public override bool TryDecode(byte[] encoded, out byte[] decoded)
|
||||
{
|
||||
decoded = encoded.FromUI1236Message();
|
||||
|
||||
return decoded.Length > 0;
|
||||
}
|
||||
|
||||
public override bool TryEncode(byte[] decoded, out byte[] encoded)
|
||||
{
|
||||
encoded = decoded.ToUI1236Message();
|
||||
|
||||
return encoded.Length > 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
namespace OmniPlus.Connections
|
||||
{
|
||||
using System.Threading;
|
||||
|
||||
internal class UI1236Stream : IrdaStream
|
||||
{
|
||||
private readonly UI1236Encoder encoder;
|
||||
|
||||
public UI1236Stream(SerialPortSettings settings) : base(settings)
|
||||
{
|
||||
this.encoder = new UI1236Encoder();
|
||||
}
|
||||
|
||||
public byte[] Write(params byte[] bytes)
|
||||
{
|
||||
this.StartListening();
|
||||
this.WriteBytes(bytes);
|
||||
|
||||
var response = new byte[0];
|
||||
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
for (int j = 0; j < 3; j++)
|
||||
{
|
||||
var message = this.DequeueMessage();
|
||||
|
||||
if (message != null)
|
||||
{
|
||||
if (this.encoder.TryDecode(message, out response))
|
||||
{
|
||||
this.ClearMessages();
|
||||
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
Thread.Sleep(200);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Thread.Sleep(200);
|
||||
}
|
||||
}
|
||||
|
||||
if (response.Length > 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
Thread.Sleep(200);
|
||||
}
|
||||
|
||||
this.StopListening();
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
public override void WriteBytes(params byte[] bytes)
|
||||
{
|
||||
if (this.encoder.TryEncode(bytes, out byte[] message))
|
||||
{
|
||||
base.WriteBytes(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,12 @@
|
||||
using OmniPlus.Enums;
|
||||
using OmniPlus.Hanlers;
|
||||
|
||||
using System;
|
||||
using System.IO.Ports;
|
||||
using System.Threading;
|
||||
|
||||
namespace OmniPlus
|
||||
namespace OmniPlus.Connections
|
||||
{
|
||||
using OmniPlus.Enums;
|
||||
using OmniPlus.Hanlers;
|
||||
|
||||
using System;
|
||||
using System.IO.Ports;
|
||||
using System.Threading;
|
||||
|
||||
internal class UniProConnection : SerialPortConnection
|
||||
{
|
||||
protected event DataReceivedHandler MessageReceived;
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
namespace OmniPlus.Connections
|
||||
{
|
||||
internal class UniProEncoder : SerialDataEncoder
|
||||
{
|
||||
public object Device2PC { get; } = SerialDataExtensions.UNIPRO_REG2PC;
|
||||
|
||||
public override bool TryDecode(byte[] encoded, out byte[] decoded)
|
||||
{
|
||||
decoded = encoded.FromUniProMessage();
|
||||
|
||||
return decoded.Length > 0;
|
||||
}
|
||||
|
||||
public override bool TryEncode(byte[] decoded, out byte[] encoded)
|
||||
{
|
||||
encoded = decoded.FromUniProMessage();
|
||||
|
||||
return encoded.Length > 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
namespace OmniPlus.Connections
|
||||
{
|
||||
using System;
|
||||
using System.Threading;
|
||||
|
||||
internal class UniProStream : SerialDataReader
|
||||
{
|
||||
private readonly UniProEncoder encoder;
|
||||
|
||||
public UniProStream(SerialPortSettings settings) : base(settings)
|
||||
{
|
||||
this.encoder = new UniProEncoder();
|
||||
}
|
||||
|
||||
public byte[] Write(params byte[] bytes)
|
||||
{
|
||||
this.StartListening();
|
||||
this.WriteBytes(bytes);
|
||||
|
||||
var response = new byte[0];
|
||||
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
for (int j = 0; j < 3; j++)
|
||||
{
|
||||
var message = this.DequeueMessage();
|
||||
|
||||
if (message != null)
|
||||
{
|
||||
if (this.encoder.TryDecode(message, out response))
|
||||
{
|
||||
this.ClearMessages();
|
||||
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
Thread.Sleep(200);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Thread.Sleep(200);
|
||||
}
|
||||
}
|
||||
|
||||
if (response.Length > 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
Thread.Sleep(200);
|
||||
}
|
||||
|
||||
this.StopListening();
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
public override void WriteBytes(params byte[] bytes)
|
||||
{
|
||||
if (this.encoder.TryEncode(bytes, out byte[] message))
|
||||
{
|
||||
base.WriteBytes(message);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void BeginRead(byte[] buffer)
|
||||
{
|
||||
var start = Array.IndexOf(buffer, this.encoder.Device2PC);
|
||||
|
||||
if (start >= 0)
|
||||
{
|
||||
if (this.encoder.TryDecode(buffer, out byte[] message))
|
||||
{
|
||||
this.EnqueueMessage(message);
|
||||
this.RemoveRange(message.Length);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
this.RemoveRange(buffer.Length);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -47,8 +47,10 @@
|
||||
/// </summary>
|
||||
public uint Duration
|
||||
{
|
||||
get => BitConverter.ToUInt16(this.bytes, 3);
|
||||
get => BitConverter.ToUInt32(this.bytes, 3);
|
||||
set => BitConverter.GetBytes(value).CopyTo(this.bytes, 3);
|
||||
}
|
||||
|
||||
public double DurationSec => this.Duration * (1D / 32768);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,6 +47,20 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Connections\IrdaConnection.cs" />
|
||||
<Compile Include="Connections\IrdaEncoder.cs" />
|
||||
<Compile Include="Connections\IrdaStream.cs" />
|
||||
<Compile Include="Connections\Program.cs" />
|
||||
<Compile Include="Connections\SerialDataEncoder.cs" />
|
||||
<Compile Include="Connections\SerialDataExtensions.cs" />
|
||||
<Compile Include="Connections\SerialDataReader.cs" />
|
||||
<Compile Include="Connections\SerialDataStream.cs" />
|
||||
<Compile Include="Connections\SerialPortSettings.cs" />
|
||||
<Compile Include="Connections\SerialPortStream.cs" />
|
||||
<Compile Include="Connections\SerialTextStream.cs" />
|
||||
<Compile Include="Connections\UI1236Encoder.cs" />
|
||||
<Compile Include="Connections\UI1236Stream.cs" />
|
||||
<Compile Include="Connections\UniProEncoder.cs" />
|
||||
<Compile Include="Connections\UniProStream.cs" />
|
||||
<Compile Include="Enums\MessurementUnits.cs" />
|
||||
<Compile Include="Enums\ReadingSettings.cs" />
|
||||
<Compile Include="Enums\Status.cs" />
|
||||
|
||||
@@ -1,21 +1,37 @@
|
||||
using System;
|
||||
using OmniPlus.Features;
|
||||
using OmniPlus.Hanlers;
|
||||
|
||||
using static OmniPlus.Features.Features;
|
||||
|
||||
namespace OmniPlus
|
||||
namespace OmniPlus
|
||||
{
|
||||
using OmniPlus.Connections;
|
||||
using OmniPlus.Features;
|
||||
using OmniPlus.Hanlers;
|
||||
|
||||
using System;
|
||||
using System.IO.Ports;
|
||||
using static OmniPlus.Features.Features;
|
||||
|
||||
public sealed class OmniPlusConnection
|
||||
{
|
||||
private Func<bool> connected;
|
||||
private readonly IrdaConnection irdaConnection;
|
||||
private readonly UniProConnection uniProConnection;
|
||||
private readonly UI1236Stream ui1236;
|
||||
private readonly UniProStream unipro;
|
||||
|
||||
public OmniPlusConnection(string portName)
|
||||
{
|
||||
this.irdaConnection = new IrdaConnection(portName);
|
||||
this.uniProConnection = new UniProConnection(portName);
|
||||
this.ui1236 = new UI1236Stream(new SerialPortSettings
|
||||
{
|
||||
BaudRate = 115200,
|
||||
DataBits = 8,
|
||||
Parity = Parity.None,
|
||||
PortName = portName,
|
||||
StopBits = StopBits.One
|
||||
});
|
||||
this.unipro = new UniProStream(new SerialPortSettings
|
||||
{
|
||||
BaudRate = 2400,
|
||||
DataBits = 8,
|
||||
Parity = Parity.None,
|
||||
PortName = portName,
|
||||
StopBits = StopBits.One
|
||||
});
|
||||
}
|
||||
|
||||
internal MessageHandler MessageHandler;
|
||||
@@ -25,30 +41,30 @@ namespace OmniPlus
|
||||
|
||||
public bool ConnectIrda()
|
||||
{
|
||||
this.uniProConnection.Close();
|
||||
this.irdaConnection.Open();
|
||||
this.unipro.Dispose();
|
||||
this.ui1236.Open();
|
||||
|
||||
this.connected = () => this.irdaConnection.Connected;
|
||||
this.MessageHandler = this.irdaConnection.Send;
|
||||
this.connected = () => this.ui1236.IsOpen;
|
||||
this.MessageHandler = this.ui1236.Write;
|
||||
|
||||
return this.irdaConnection.Connected;
|
||||
return this.ui1236.IsOpen;
|
||||
}
|
||||
|
||||
public bool ConnectUniPro()
|
||||
{
|
||||
this.irdaConnection.Close();
|
||||
this.uniProConnection.Open();
|
||||
this.ui1236.Dispose();
|
||||
this.unipro.Open();
|
||||
|
||||
this.connected = () => this.uniProConnection.Connected;
|
||||
this.MessageHandler = this.uniProConnection.SendMessage;
|
||||
this.connected = () => this.unipro.IsOpen;
|
||||
this.MessageHandler = this.unipro.Write;
|
||||
|
||||
return this.irdaConnection.Connected;
|
||||
return this.unipro.IsOpen;
|
||||
}
|
||||
|
||||
public void Disconnect()
|
||||
{
|
||||
this.uniProConnection.Close();
|
||||
this.irdaConnection.Close();
|
||||
this.unipro.Dispose();
|
||||
this.ui1236.Dispose();
|
||||
}
|
||||
|
||||
public FactoryID ViewFactoryID()
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
{
|
||||
try
|
||||
{
|
||||
return 100 - this.MeterVolume / this.VolumeMessured * 100;
|
||||
return 100 + (this.MeterVolume - this.VolumeMessured) / this.VolumeMessured;
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
||||
@@ -30,7 +30,9 @@ namespace OmniPlus
|
||||
return seconds * milliliter / 1000 / 1000;
|
||||
}
|
||||
|
||||
public double VolumeM3(OmniPlusTest test)
|
||||
=> this.VolumeM3(test.Rotations, test.Duration);
|
||||
public double VolumeM3(OmniPlusTest test)
|
||||
{
|
||||
return this.VolumeM3(test.Rotations, test.Duration);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user