namespace Common.Hardware.Ports { using System; using System.Collections.Generic; using System.Text.RegularExpressions; public static class SerialDataExtensions { private const int ByteSize = 8; private const int SByteSize = 16; private const int Int16Size = 16; private const int UInt16Size = 16; private const int Int32Size = 32; private const int UInt32Size = 32; private const int Int64Size = 64; private const int UInt64Size = 64; public static byte[] GetBitsBE(this byte value) { var bits = new byte[ByteSize]; for (int i = 7, x = 0; i >= 0; i--, x++) { bits[x] = (byte)((value >> i) & 1); } return bits; } public static byte[] GetBitsLE(this byte value) { var bits = new byte[ByteSize]; for (var i = 0; i < ByteSize; i++) { bits[i] = (byte)((value >> i) & 1); } return bits; } public static byte[] GetBitsLE(this ushort value) { var bits = new byte[UInt16Size]; for (var i = 0; i < UInt16Size; i++) { bits[i] = (byte)((value >> i) & 1); } return bits; } public static byte GetByteLE(this byte[] bits) { if (bits is null) { return default(byte); } var value = default(byte); for (var i = 0; i < ByteSize; i++) { value ^= (byte)(bits[i] << i); } return value; } public static byte GetByteLE(this byte[] bits, int start = 0, int count = 0) { if (bits is null) { return default(byte); } if (count == 0) { count = bits.Length; } var length = start + count; var _byte = default(byte); for (int i = start, x = 0; i < length; i++, x++) { _byte ^= (byte)(bits[i] << x); } return _byte; } public static void SetBitsLE(this byte value, byte[] bits, int start = 0, int count = 0) { if (bits is null) { return; } if (count == 0 || count > bits.Length) { count = bits.Length; } for (int i = start, x = 0; i < count; i++, x++) { bits[i] = (byte)((value >> x) % 2); } } public static byte[] GetBytesBE(this sbyte value) { var bytes = new byte[2]; var index = 0; bytes[index++] = (byte)(value >> 8); bytes[index] = (byte)value; return bytes; } public static byte[] GetBytesBE(this short value) { var bytes = new byte[2]; var index = 0; bytes[index++] = (byte)(value >> 8); bytes[index] = (byte)value; return bytes; } public static byte[] GetBytesBE(this int value) { var bytes = new byte[4]; var index = 0; bytes[index++] = (byte)(value >> 24); bytes[index++] = (byte)(value >> 16); bytes[index++] = (byte)(value >> 8); bytes[index] = (byte)value; return bytes; } public static byte[] GetBytesBE(this long value) { var bytes = new byte[8]; var index = 0; bytes[index++] = (byte)(value >> 56); bytes[index++] = (byte)(value >> 48); bytes[index++] = (byte)(value >> 40); bytes[index++] = (byte)(value >> 32); bytes[index++] = (byte)(value >> 24); bytes[index++] = (byte)(value >> 16); bytes[index++] = (byte)(value >> 8); bytes[index] = (byte)value; return bytes; } public static byte[] GetBytesBE(this ushort value) { var bytes = new byte[2]; var index = 0; bytes[index++] = (byte)(value >> 8); bytes[index] = (byte)value; return bytes; } public static byte[] GetBytesBE(this uint value) { var bytes = new byte[4]; var index = 0; bytes[index++] = (byte)(value >> 24); bytes[index++] = (byte)(value >> 16); bytes[index++] = (byte)(value >> 8); bytes[index] = (byte)value; return bytes; } public static byte[] GetBytesBE(this ulong value) { var bytes = new byte[8]; var index = 0; bytes[index++] = (byte)(value >> 56); bytes[index++] = (byte)(value >> 48); bytes[index++] = (byte)(value >> 40); bytes[index++] = (byte)(value >> 32); bytes[index++] = (byte)(value >> 24); bytes[index++] = (byte)(value >> 16); bytes[index++] = (byte)(value >> 8); bytes[index] = (byte)value; return bytes; } public static byte[] GetBytesLE(this sbyte value) { var bytes = new byte[2]; var index = 0; bytes[index++] = (byte)value; bytes[index] = (byte)(value >> 8); return bytes; } public static byte[] GetBytesLE(this short value) { var bytes = new byte[2]; var index = 0; bytes[index++] = (byte)value; bytes[index] = (byte)(value >> 8); return bytes; } public static byte[] GetBytesLE(this int value) { var bytes = new byte[4]; var index = 0; bytes[index++] = (byte)value; bytes[index++] = (byte)(value >> 8); bytes[index++] = (byte)(value >> 16); bytes[index] = (byte)(value >> 24); return bytes; } public static byte[] GetBytesLE(this long value) { var bytes = new byte[8]; var index = 0; bytes[index++] = (byte)value; bytes[index++] = (byte)(value >> 8); bytes[index++] = (byte)(value >> 16); bytes[index++] = (byte)(value >> 24); bytes[index++] = (byte)(value >> 32); bytes[index++] = (byte)(value >> 40); bytes[index++] = (byte)(value >> 48); bytes[index] = (byte)(value >> 56); return bytes; } public static byte[] GetBytesLE(this ushort value) { var bytes = new byte[2]; var index = 0; bytes[index++] = (byte)value; bytes[index] = (byte)(value >> 8); return bytes; } public static byte[] GetBytesLE(this uint value) { var bytes = new byte[4]; var index = 0; bytes[index++] = (byte)value; bytes[index++] = (byte)(value >> 8); bytes[index++] = (byte)(value >> 16); bytes[index] = (byte)(value >> 24); return bytes; } public static byte[] GetBytesLE(this ulong value) { var bytes = new byte[8]; var index = 0; bytes[index++] = (byte)value; bytes[index++] = (byte)(value >> 8); bytes[index++] = (byte)(value >> 16); bytes[index++] = (byte)(value >> 24); bytes[index++] = (byte)(value >> 32); bytes[index++] = (byte)(value >> 40); bytes[index++] = (byte)(value >> 48); bytes[index] = (byte)(value >> 56); return bytes; } public static sbyte ToSByteBE(this byte[] bytes, int start = 0) { var value = default(sbyte); value ^= (sbyte)(bytes[start++] << 8); value ^= (sbyte)bytes[start]; return value; } public static short ToInt16BE(this byte[] bytes, int start = 0) { var value = default(short); value ^= (short)(bytes[start++] << 8); value ^= bytes[start]; return value; } public static int ToInt32BE(this byte[] bytes, int start = 0) { var value = default(int); value ^= bytes[start++] << 24; value ^= bytes[start++] << 16; value ^= bytes[start++] << 8; value ^= bytes[start]; return value; } public static long ToInt64BE(this byte[] bytes, int start = 0) { var value = default(long); value ^= bytes[start++] << 56; value ^= bytes[start++] << 48; value ^= bytes[start++] << 40; value ^= bytes[start++] << 32; value ^= bytes[start++] << 24; value ^= bytes[start++] << 16; value ^= bytes[start++] << 8; value ^= bytes[start]; return value; } public static ushort ToUInt16BE(this byte[] bytes, int start = 0) { var value = default(ushort); value ^= (ushort)(bytes[start++] << 8); value ^= bytes[start]; return value; } public static uint ToUInt32BE(this byte[] bytes, int start = 0) { var value = default(uint); value ^= (uint)(bytes[start++] << 24); value ^= (uint)(bytes[start++] << 16); value ^= (uint)(bytes[start++] << 8); value ^= bytes[start]; return value; } public static ulong ToUInt64BE(this byte[] bytes, int start = 0) { var value = default(ulong); value ^= (ulong)(bytes[start++] << 56); value ^= (ulong)(bytes[start++] << 48); value ^= (ulong)(bytes[start++] << 40); value ^= (ulong)(bytes[start++] << 32); value ^= (ulong)(bytes[start++] << 24); value ^= (ulong)(bytes[start++] << 16); value ^= (ulong)(bytes[start++] << 8); value ^= bytes[start]; return value; } public static sbyte ToSByteLE(this byte[] bytes, int start = 0) { var value = default(sbyte); value ^= (sbyte)bytes[start++]; value ^= (sbyte)(bytes[start] << 8); return value; } public static short ToInt16LE(this byte[] bytes, int start = 0) { var value = default(short); value ^= bytes[start++]; value ^= (short)(bytes[start] << 8); return value; } public static int ToInt32LE(this byte[] bytes, int start = 0) { var value = default(int); value ^= bytes[start++]; value ^= bytes[start++] << 8; value ^= bytes[start++] << 16; value ^= bytes[start] << 24; return value; } public static long ToInt64LE(this byte[] bytes, int start = 0) { var value = default(long); value ^= bytes[start++]; value ^= bytes[start++] << 8; value ^= bytes[start++] << 16; value ^= bytes[start++] << 24; value ^= bytes[start++] << 32; value ^= bytes[start++] << 40; value ^= bytes[start++] << 48; value ^= bytes[start] << 56; return value; } public static ushort ToUInt16LE(this byte[] bytes, int start = 0) { var value = default(ushort); value ^= bytes[start++]; value ^= (ushort)(bytes[start] << 8); return value; } public static ushort ToUIint16LEFromBits(this byte[] bits) { const int size = 16; if (bits is null) { bits = new byte[size]; } Array.Resize(ref bits, size); ushort value = 0; for (var i = 0; i < size; i++) { value ^= (ushort)(bits[i] << i); } return value; } public static uint ToUInt32LE(this byte[] bytes, int start = 0) { var value = default(uint); value ^= bytes[start++]; value ^= (uint)(bytes[start++] << 8); value ^= (uint)(bytes[start++] << 16); value ^= (uint)(bytes[start] << 24); return value; } public static ulong ToUInt64LE(this byte[] bytes, int start = 0) { var value = default(ulong); value ^= bytes[start++]; value ^= (ulong)(bytes[start++] << 8); value ^= (ulong)(bytes[start++] << 16); value ^= (ulong)(bytes[start++] << 24); value ^= (ulong)(bytes[start++] << 32); value ^= (ulong)(bytes[start++] << 40); value ^= (ulong)(bytes[start++] << 48); value ^= (ulong)(bytes[start] << 56); return value; } public static ushort CRCCCITT(this byte[] bytes, int start = 0, int length = 0) { if (length == 0) { length = bytes.Length; } var crc = (ushort)0xFFFF; for (var b = start; b < length; b++) { var _byte = bytes[b]; var token = (ushort)((_byte << 8) & 0xFF00); for (var i = 0; i < 8; i++) { if (0x8000 == ((crc ^ token) & 0x8000)) { crc <<= 1; crc ^= 0x1021; } else { crc <<= 1; } token <<= 1; } } return crc; } public static byte[] GetBytes(this string hexString) { var bytes = new List(); if (!string.IsNullOrWhiteSpace(hexString)) { hexString = Regex.Replace(hexString, "[^a-fA-F0-9]*", string.Empty); var first = true; var x = 0; foreach (var hex in hexString) { if ('0' <= hex && hex <= '9') { x += hex - '0'; } else if ('A' <= hex && hex <= 'F') { x += hex - 'A' + 10; } else if ('a' <= hex && hex <= 'f') { x = hex - 'a' + 10; } else { continue; } if (first) { x *= 16; } else { bytes.Add((byte)x); x = 0; } first = !first; } } return bytes.ToArray(); } public static byte[] GetEncryptionKey(this string hexString, int requiredLength = 16) { var bytes = hexString.GetBytes(); if (bytes?.Length != requiredLength) { return default(byte[]); } return bytes; } } }