using System; using System.Data.SqlClient; using System.Runtime.CompilerServices; using System.Threading.Tasks; namespace OmniFeaturesTest { internal 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_PC2REG = 0x33; public const byte IRDA_REG2PC = 0x43; public const byte IRDA_MIN_LENGTH = 5; public const byte IRDA_CRC_LENGTH = 2; /// /// UI1236 structure: /// 0. 0x0D - Start byte /// 1. .... - Length: max. 254 /// 2. .... - Control byte /// 3+n. .... - Payload /// n-2. .... - Checksum 0 /// n-1. .... - Checksum 1 /// 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); 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; } /// /// UI1236 structure: /// 0. 0x0D - Start byte /// 1. .... - Length: max. 254 /// 2. .... - Control byte /// 3+n. .... - Payload /// n-2. .... - Checksum 0 /// n-1. .... - Checksum 1 /// 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; } /// /// UniPro structure: /// 0. .... - Start byte /// 1. .... - Direction /// 2. .... - Length /// .. .... - Payload /// n-1. .... - Stop byte /// 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; } /// /// UniPro structure: /// 0. .... - Start byte /// 1. .... - Direction /// 2. .... - Length /// .. .... - Payload /// n-1. .... - Stop byte /// 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; } /// /// Irda structure: /// 0. .... - Start byte /// 1. .... - Direction /// 2. .... - Length / 2 /// 3+n. .... - Payload /// n-3. .... - aligned byte /// n-2. .... - CRC16 0 /// n-1. .... - CRC16 1 /// 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; } /// /// Irda structure: /// 0. .... - Start byte /// 1. .... - Direction /// 2. .... - Length / 2 /// 3+n. .... - Payload /// n-3. .... - aligned byte /// n-2. .... - CRC16 0 /// n-1. .... - CRC16 1 /// 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]; 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(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) { 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 bytes; } 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; } } }