namespace Common.Hardware.Ports { using System; public static partial class SerialPortExtensions { 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; /// /// UniPro structure: /// 0. .... - Start Byte /// 1. .... - Direction /// 2. .... - Length /// .. .... - Payload /// n-1. .... - Stop Byte /// public static Boolean TryParseToUniPro(this Byte[] data, out Byte[] bytes) { if (data is null) { data = new Byte[0]; } var dataLength = data.Length; var bytesLength = dataLength + UNIPRO_MIN_LENGTH; bytes = new Byte[bytesLength]; bytes[0] = UNIPRO_START; bytes[1] = UNIPRO_PC2REG; bytes[2] = (Byte)bytesLength; bytes[bytesLength - 1] = UNIPRO_STOP; Array.Copy(data, 0, bytes, 3, dataLength); return true; } /// /// UniPro structure: /// 0. .... - Start Byte /// 1. .... - Direction /// 2. .... - Length /// .. .... - Payload /// n-1. .... - Stop Byte /// public static Boolean TryParseFromUniPro(this Byte[] bytes, out Byte[] data) { data = new Byte[0]; if (bytes is null) { return false; } var start = Array.IndexOf(bytes, UNIPRO_START); if (start < 0) { return false; } var direction = Array.IndexOf(bytes, UNIPRO_REG2PC, start + 1); if (direction < 0) { return false; } var bytesLength = bytes.Length; var lengthIndex = direction + 1; if (lengthIndex >= bytesLength) { return false; } var dataIndex = lengthIndex + 1; if (dataIndex >= bytesLength) { return false; } var dataLength = bytes[lengthIndex] - UNIPRO_MIN_LENGTH; if (dataLength < 0 || dataIndex + dataLength > bytesLength) { return false; } data = new Byte[dataLength]; Array.Copy(bytes, dataIndex, data, 0, dataLength); return true; } 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_LEN_INDEX = 2; public const Byte IRDA_DATA_INDEX = 3; public const Byte IRDA_MIN_LENGTH = 5; /// /// 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 Boolean TryParseToIrda(this Byte[] data, out Byte[] bytes) { bytes = new Byte[0]; if (data is null) { data = new Byte[0]; } var offset = data.Length % 2; var dataLength = data.Length + offset; var bytesLength = dataLength + IRDA_MIN_LENGTH; bytes = new Byte[bytesLength]; bytes[0] = IRDA_START; bytes[1] = IRDA_PC2REG; bytes[2] = (Byte)(dataLength / 2); Array.Copy(data, 0, bytes, 3, data.Length); var crc = bytes.CalculateCRC8408(1, bytesLength - 2); bytes[bytesLength - 2] = crc[0]; bytes[bytesLength - 1] = crc[1]; return true; } /// /// 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 Boolean TryParseFromIrda(this Byte[] bytes, out Byte[] data) { data = new Byte[0]; if (bytes is null) { return false; } var bytesLength = bytes.Length; var directionIX = -1; var startIX = 0; while (bytesLength > startIX) { startIX = Array.IndexOf(bytes, IRDA_START, startIX); if (startIX < 0) { break; } directionIX = Array.IndexOf(bytes, IRDA_REG2PC, ++startIX); if (directionIX > 0) { break; } else { directionIX = Array.IndexOf(bytes, (Byte)0x82, startIX++); if (directionIX >= 0) { directionIX = -1; } } } if (startIX < 0) { return false; } var lengthIndex = directionIX + 1; if (lengthIndex >= bytesLength) { return false; } var dataIndex = lengthIndex + 1; if (dataIndex >= bytesLength) { return false; } var dataLength = bytes[lengthIndex] * 2; if (dataIndex + dataLength > bytesLength) { return false; } data = new Byte[dataLength]; Array.Copy(bytes, dataIndex, data, 0, dataLength); return true; } public const Byte UI1236_START = 0x0D; public const Byte UI1236_LEN_INDEX = 1; public const Byte UI1236_DATA_INDEX = 3; public const Byte UI1236_MIN_LENGTH = 5; /// /// 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 Boolean TryParseToUI1236(this Byte[] data, out Byte[] bytes) { bytes = new Byte[0]; if (data is null) { data = new Byte[0]; } var dataLength = data.Length; var bytesLength = dataLength + UI1236_MIN_LENGTH; bytes = new Byte[bytesLength]; bytes[0] = UI1236_START; bytes[1] = (Byte)(bytesLength - 2); UI1236Control control = 0; control.ReturnResponse = true; bytes[2] = control; Array.Copy(data, 0, bytes, 3, dataLength); var checksum = bytes.CalculateCheckSUM(bytes.Length - 2); bytes[bytesLength - 2] = checksum[1]; bytes[bytesLength - 1] = checksum[0]; return true; } /// /// 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 Boolean TryParseFromUI1236(this Byte[] bytes, out Byte[] data) { data = new Byte[0]; if (bytes is null) { return false; } var start = Array.IndexOf(bytes, UI1236_START); if (start < 0) { return false; } var bytesLength = bytes.Length; var lengthIndex = start + 1; if (lengthIndex >= bytesLength) { return false; } var dataIndex = lengthIndex + 2; if (dataIndex >= bytesLength) { return false; } var dataLength = bytes[lengthIndex] - 3; // 3 = protocol bytes length (start|control|length) if (dataIndex + dataLength > bytesLength) { return false; } data = new Byte[dataLength]; Array.Copy(bytes, dataIndex, data, 0, dataLength); return true; } public static Byte[] CalculateCRC8408(this Byte[] bytes, Int32 start, Int32 length) { var crc = 0xFFFF; while (start < length) { crc ^= 0x00FF & bytes[start]; for (var i = 8; i > 0; i--) { if ((crc & 0x0001) != 0) { crc = (crc >> 1) ^ 0x8408; } else { crc >>= 1; } } start++; } crc = ~crc; return BitConverter.GetBytes((UInt16)crc); } public static Byte[] CalculateCheckSUM(this Byte[] bytes, Int32 length) { UInt16 checksum = 0; for (var i = 0; i < length; i++) { checksum += bytes[i]; } return BitConverter.GetBytes(checksum); } public static Byte[] CalculateCRC16(this Byte[] data, Int32 start, Int32 length) { var dataLength = data.Length; var maxLength = start + length; var crc = (UInt16)0xFFFF; Byte test; Byte current; if (data.Length > maxLength) { while (start < maxLength) { current = data[start]; for (Byte h = 0; h < 8; h++) { test = 0; if ((crc & 0x8000) != 0) { test = 0x80; } crc <<= 1; if (((current & 0x80) ^ test) != 0) { crc ^= 0x1021; } current <<= 1; } start++; } } return BitConverter.GetBytes(crc); } public static Byte[] CalculateCRC1021(this Byte[] bytes, Int32 start, Int32 length) { UInt16 crcSum = 0xFFFF; while (start < length) { var @byte = bytes[start]; for (int bit = 0; bit < 8; bit++) { var test = default(Byte); if ((crcSum & 0x8000) != 0) { test = 0x80; } crcSum <<= 1; if (((@byte & 0x80) ^ test) != 0) { crcSum ^= 0x1021; } @byte <<= 1; } start++; } return BitConverter.GetBytes(crcSum); } } }