using System; using System.Collections.Generic; namespace TBF.Rig.TestMethods.iPerlCommunication.communication.C4.IperlHatProtocol { public sealed class IperlHatFrameParser { public IperlHatResponse Parse(byte[] data) { if (data == null) throw new ArgumentNullException(nameof(data)); if (data.Length < 5) throw new FormatException("Frame too short."); if (data[0] != TestMethods.iPerlCommunication.communication.C4.IperlHatProtocol.IperlHatProtocolConstants.Start) { //if version parse version if (data[0] == TestMethods.iPerlCommunication.communication.C4.IperlHatProtocol.IperlHatProtocolConstants.Question) { //Define Question answer var prefix = new List{ TestMethods.iPerlCommunication.communication.C4.IperlHatProtocol.IperlHatProtocolConstants.Question }; var end = new List{ TestMethods.iPerlCommunication.communication.C4.IperlHatProtocol.IperlHatProtocolConstants.End }; if (IsPrefixValid(data, prefix, end)) { //whole payload may be like "vers: Harry T:B800, V:06.06.01, FW:190215, 7ECE, B1.6.01, HW:4, Serial:0" prefix = new List{ TestMethods.iPerlCommunication.communication.C4.IperlHatProtocol.IperlHatProtocolConstants.Question }; byte[] payloadVersion = ExtractPayloadUsePrefix(data, prefix, end); return new IperlHatResponse(TestMethods.iPerlCommunication.communication.C4.IperlHatProtocol.IperlHatProtocolConstants.Question, payloadVersion.Length > 0 ? TestMethods.iPerlCommunication.communication.C4.IperlHatProtocol.IperlHatProtocolConstants.StatusOk : TestMethods.iPerlCommunication.communication.C4.IperlHatProtocol.IperlHatProtocolConstants.StatusNok, payloadVersion); } } throw new FormatException("Invalid START byte."); } if (data[1] != TestMethods.iPerlCommunication.communication.C4.IperlHatProtocol.IperlHatProtocolConstants.Read) throw new FormatException("Frame is no Response."); byte length = data[2]; if (length != data.Length) throw new FormatException("Length mismatch."); byte direction = data[1]; byte status = data[3]; var prefixCommand = new List{ TestMethods.iPerlCommunication.communication.C4.IperlHatProtocol.IperlHatProtocolConstants.Start,direction,length,status }; var endCommand = new List{ TestMethods.iPerlCommunication.communication.C4.IperlHatProtocol.IperlHatProtocolConstants.End }; byte[] payload = ExtractPayloadUsePrefix(data,prefixCommand,endCommand); return new IperlHatResponse(0x00, status, payload); } private static byte[] ExtractPayloadUsePrefix(byte[] data, List prefix, List end) { // payload exists only if frame longer than: // START + DIRECTION + LEN + CTRL + END = 5 bytes // OR VERSION_START + VERSION = 5 bytes if (data.Length <= 5) return Array.Empty(); //check prefix is equal int prefixLength = prefix.Count; byte[] commandPrefix = new byte[prefixLength]; Buffer.BlockCopy(data, 0, commandPrefix, 0, prefixLength); if (StartsWithPrefix(end, commandPrefix)) { return Array.Empty(); } int payloadLength = data.Length - (prefix.Count + end.Count); byte[] payload = new byte[payloadLength]; Buffer.BlockCopy(data, prefix.Count, payload, 0, payloadLength); return payload; } private static bool IsPrefixValid(byte[] data, List prefix, List end) { int prefixLength = prefix.Count; // payload exists only if frame longer than: // OR VERSION_START + VERSION = 5 bytes - "?VERS" version implemented if (data.Length <= prefixLength) // need be and on END return false; //check prefix is equal byte[] commandPrefix = new byte[prefixLength]; Buffer.BlockCopy(data, 0, commandPrefix, 0, prefixLength); if (StartsWithPrefix(end, commandPrefix)) { return false; } return true; } private static bool StartsWithPrefix(List data, byte[] prefix) { if (data.Count < prefix.Length) return false; for (int i = 0; i < prefix.Length; i++) { if (data[i] != prefix[i]) return false; } return true; } private static byte[] ExtractVersionPayload(byte[] data) { // payload exists only if frame longer than: // START + LEN + CTRL + STATUS + CHK_HI + CHK_LO = 6 bytes if (data.Length <= 5) return Array.Empty(); int payloadLength = data.Length - 4; byte[] payload = new byte[payloadLength]; Buffer.BlockCopy(data, 5, payload, 0, payloadLength); return payload; } } }