/// <summary> /// Sorts packet's bytes into easily accessible structures. Manipulates endianess. /// </summary> /// <param name="data">Expects bytes, composed of fully decoded bits (Decode, then SeparatePackets, then DestuffZeros, then PackIntoBytes).</param> /// <param name="time">x10nS</param> /// <param name="littleEndian">See Communications.Parse</param> /// <returns></returns> public static EncoderPacket Parse(byte[] data, int time, bool littleEndian = false) { //bool containsSub = data.Length > OrdinaryPacketLength; byte[][] result = new byte[FieldLength.Count][]; int dataLen = data.Length - FieldLength[Fields.FCS]; List <byte> fcs = new List <byte>(dataLen > -1 ? dataLen : 0); int current = 0; try { for (int i = 0; i < FieldLength.Count; i++) { if (OrdinaryPacketFieldsToExclude.Any(x => x == (Fields)i)) { continue; } int l = FieldLength[(Fields)i]; if (l == -1) { l = data.Length - FieldLength.Sum(x => x.Value) - 1; //-1 stands for "variable length" } result[i] = new byte[l]; //Multibyte fields may be little-endian at physical layer (in fact they should be, but it turns out they're not...) //All in all, we'd better implement a switch for (int j = 0; j < l; j++) { result[i][j] = data[current + (littleEndian ? (l - j - 1) : (j))]; if ((Fields)i != Fields.FCS) { fcs.Add(result[i][j]); } } current += l; } } catch (OverflowException) { ErrorListener.Add(new Exception(string.Format("Packet at {0} is incomplete!", time))); } var toParse = result[(int)Fields.Unknown]; //if (containsSub) toParse = toParse.Concat(result[(int)Fields.SubcommandData]).ToArray(); var packet = new EncoderPacket(result, EncoderCommand.Parse(toParse), time); packet.ComputedFCS = HDLCManchesterDecoder.ComputeFCS(fcs.ToArray()); try { packet.FCSError = !packet.ComputedFCS.SequenceEqual(packet.ParsedData[(int)Fields.FCS]); } catch (ArgumentNullException) { packet.FCSError = true; } packet.DatabaseReport = EncoderCommandDatabase.GetReport(packet); return(packet); }
/// <summary> /// Sorts packet's bytes into easily accessible structures. Manipulates endianess. /// </summary> /// <param name="data">Expects bytes, composed of fully decoded bits (Decode, then SeparatePackets, then DestuffZeros, then PackIntoBytes).</param> /// <param name="time">x10nS</param> /// <param name="littleEndian">See Communications.Parse</param> /// <returns></returns> public static MechatrolinkPacket Parse(byte[] data, int time, bool littleEndian = false) { bool containsSub = data.Length > OrdinaryPacketLength; byte[][] result = new byte[FieldLength.Count][]; List <byte> fcs = new List <byte>(data.Length - FieldLength[Fields.FCS]); int current = 0; for (int i = 0; i < FieldLength.Count; i++) { if (OrdinaryPacketFieldsToExclude.Any(x => x == (Fields)i)) { continue; } int l = FieldLength[(Fields)i]; result[i] = new byte[l]; //Multibyte fields may be little-endian at physical layer (in fact they should be, but it turns out they're not...) //All in all, we'd better implement a switch for (int j = 0; j < l; j++) { result[i][j] = data[current + (littleEndian ? (l - j - 1) : (j))]; if ((Fields)i != Fields.FCS) { fcs.Add(result[i][j]); } } current += l; } var toParse = result[(int)Fields.CommandData]; if (containsSub) { toParse = toParse.Concat(result[(int)Fields.SubcommandData]).ToArray(); } var packet = new MechatrolinkPacket(result, MechatrolinkCommand.Parse(toParse), time); packet.ComputedFCS = HDLCManchesterDecoder.ComputeFCS(fcs.ToArray()); packet.FCSError = !packet.ComputedFCS.SequenceEqual(packet.ParsedData[(int)Fields.FCS]); packet.DatabaseReport = MechatrolinkCommandDatabase.GetReport(packet); return(packet); }