436 lines
12 KiB
C#
436 lines
12 KiB
C#
using OmniPlus.Options;
|
|
|
|
using System;
|
|
using System.Data.SqlClient;
|
|
using System.Threading.Tasks;
|
|
|
|
namespace OmniPlus
|
|
{
|
|
public static class OmniPlusExtensions
|
|
{
|
|
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;
|
|
|
|
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];
|
|
|
|
Array.Copy(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];
|
|
|
|
Array.Copy(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 bytesLength = bytes.Length;
|
|
|
|
if (bytesLength >= 2)
|
|
{
|
|
if (bytes[1] == IRDA_PING)
|
|
{
|
|
return payload;
|
|
}
|
|
}
|
|
|
|
var payloadLength = bytes.Length - IRDA_MIN_LENGTH;
|
|
|
|
if (payloadLength <= OxOO)
|
|
{
|
|
return payload;
|
|
}
|
|
|
|
payload = new byte[payloadLength];
|
|
|
|
Array.Copy(bytes, OxO3, payload, OxOO, payloadLength);
|
|
|
|
return payload;
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
public static void Clear(this byte[] bytes)
|
|
{
|
|
var length = bytes.Length;
|
|
|
|
for (int i = OxOO; i < length; i++)
|
|
{
|
|
bytes[i] = OxOO;
|
|
}
|
|
}
|
|
|
|
public static string ToASCIIString(this byte[] bytes, int start, int length)
|
|
{
|
|
var asciiString = string.Empty;
|
|
|
|
while (start >= 0 && start < bytes.Length)
|
|
{
|
|
asciiString += (char)bytes[start++];
|
|
}
|
|
|
|
return asciiString;
|
|
}
|
|
|
|
public static void ContinueWhenAll(this Task[] tasks)
|
|
=> Task.Factory
|
|
.ContinueWhenAll(tasks, _ => { })
|
|
.Wait();
|
|
|
|
public static void OpenConnection(this SqlConnection sqlConnection)
|
|
{
|
|
sqlConnection.FireInfoMessageEventOnUserErrors = true;
|
|
sqlConnection.InfoMessage += SqlConnection_InfoMessage;
|
|
sqlConnection.Open();
|
|
}
|
|
|
|
private static void SqlConnection_InfoMessage(object _, SqlInfoMessageEventArgs args)
|
|
{
|
|
Console.WriteLine(args.Message);
|
|
}
|
|
|
|
public static T GetValue<T>(this SqlDataReader reader, int field)
|
|
{
|
|
if (!reader.IsDBNull(field) && reader.GetValue(field) is T value)
|
|
{
|
|
return value;
|
|
}
|
|
|
|
return default(T);
|
|
}
|
|
|
|
public static double MlPerRotation(byte intPart, ushort fraction, short correctionFactor)
|
|
=> (intPart + (double)fraction / ushort.MaxValue) * correctionFactor;
|
|
|
|
public static double GPM2M3H(double value)
|
|
=> value * 3785.411784 / 1000 / 1000 * 60;
|
|
|
|
public static double GetCorrectionFactor(this double[] points)
|
|
{
|
|
if (points?.Length != 3)
|
|
{
|
|
return double.MinValue;
|
|
}
|
|
|
|
var min = points[0];
|
|
var mid = points[1];
|
|
var max = points[2];
|
|
|
|
if (Math.Abs(mid - max) <= 3 && Math.Max(mid, max) - min <= 6.5)
|
|
{
|
|
var avgMidMax = (mid + max) / 2;
|
|
|
|
if (100 - avgMidMax + min < 95)
|
|
{
|
|
return 95 - min;
|
|
}
|
|
else
|
|
{
|
|
return 100 - avgMidMax;
|
|
}
|
|
}
|
|
|
|
return double.MaxValue;
|
|
}
|
|
|
|
public static byte[] GetBits(this byte value)
|
|
{
|
|
var bits = new byte[BYTE_BITS];
|
|
|
|
for (byte i = 0; i < BYTE_BITS; i++)
|
|
{
|
|
bits[i] = (byte)(value >> i & 1);
|
|
}
|
|
|
|
return bits;
|
|
}
|
|
|
|
public static byte[] GetBits(this byte[] bytes)
|
|
{
|
|
var bytesL = bytes.Length;
|
|
var bitsL = bytesL * BYTE_BITS;
|
|
var bits = new byte[bitsL];
|
|
|
|
for (int i = 0; i < bytesL; i++)
|
|
{
|
|
for (int b = 0; b < BYTE_BITS; b++)
|
|
{
|
|
bits[i + b] = (byte)(bytes[i] >> b & 1);
|
|
}
|
|
}
|
|
|
|
return bits;
|
|
}
|
|
|
|
public static byte ToUint8(this byte[] bits)
|
|
{
|
|
var sum = default(byte);
|
|
|
|
for (byte i = 0; i < bits.Length; i++)
|
|
{
|
|
sum ^= (byte)(bits[i] << i);
|
|
}
|
|
|
|
return sum;
|
|
}
|
|
|
|
public static byte GetUint8(this byte x, int start, int length)
|
|
{
|
|
var src = x.GetBits();
|
|
var dst = new byte[8];
|
|
|
|
Array.Copy(src, start, dst, 0, length);
|
|
|
|
return dst.ToUint8();
|
|
}
|
|
|
|
public static void SetUint8(this ref byte x, int start, int length, byte value)
|
|
{
|
|
var src = value.GetBits();
|
|
var dst = x.GetBits();
|
|
|
|
Array.Copy(src, 0, dst, start, length);
|
|
|
|
x = dst.ToUint8();
|
|
}
|
|
|
|
public static byte[] Subarray(this byte[] bytes, int start, int length)
|
|
{
|
|
var subarray = new byte[length];
|
|
|
|
Array.Copy(bytes, start, subarray, 0, length);
|
|
|
|
return subarray;
|
|
}
|
|
|
|
public static byte[] Reverse(this byte[] bytes)
|
|
{
|
|
var length = bytes.Length / 2;
|
|
|
|
for (int i = 0; i < length; i++)
|
|
{
|
|
var last = length - i - 1;
|
|
var first = bytes[i];
|
|
bytes[i] = bytes[last];
|
|
bytes[last] = first;
|
|
}
|
|
|
|
return bytes;
|
|
}
|
|
}
|
|
}
|