public DataBlock(byte[] data, DataInformationField dataInformationField, List <DataInformationExtensionField> dataInformationFieldExtensions, PrimaryValueInformationField valueInformationField, List <ValueInformationExtensionField> valueInformationFieldExtensions) { _data = data ?? throw new ArgumentNullException(nameof(data)); DataInformationField = dataInformationField ?? throw new ArgumentNullException(nameof(dataInformationField)); DataInformationFieldExtensions = dataInformationFieldExtensions ?? throw new ArgumentNullException(nameof(dataInformationFieldExtensions)); ValueInformationField = valueInformationField ?? throw new ArgumentNullException(nameof(valueInformationField)); ValueInformationFieldExtensions = valueInformationFieldExtensions ?? throw new ArgumentNullException(nameof(valueInformationFieldExtensions)); Parse(); }
public static DataInformationField Parse(int dif) { if (dif == 0x0f || dif == 0x1f) { return(null); } var result = new DataInformationField { HasExtendedBlock = (dif & 0x80) == 0x80, StorageNumberLsb = (dif & 0x40) << 6, FunctionValue = (FunctionValueType)((dif & 30) >> 4), DataType = (DataType)(dif & 0x0f) }; return(result); }
/// <summary> /// parse the records. /// </summary> /// <param name="header">the mbus header. Useful for manufacturer specific parsing.</param> /// <param name="payload">the payload.</param> /// <param name="decryptionKey">the decryption key.</param> /// <param name="initializationVector">the initialization vector.</param> /// <returns>a IList<MbusRecord> containing the parse records.</returns> private IList <VariableDataRecord> ParseRecords(MBusHeader header, IList <byte> payload, byte[] decryptionKey) { List <byte> payloadBody; // Todo find out whats wrong with this. if (header.ExtendedLinkLayer != null) { payloadBody = payload.Skip(header.PayloadStartsAtIndex - 2).ToList(); } else { payloadBody = payload.Skip(header.PayloadStartsAtIndex).ToList(); } if (decryptionKey != null) { payloadBody = DecryptPayload(header, payloadBody, decryptionKey); } if (payloadBody == null) { return(null); } if (header.ExtendedLinkLayer != null) { var frameType = ControlInformationLookup.Find(payloadBody.First()).frameType; if (frameType != FrameType.Full) { return(null); } payloadBody = payloadBody.Skip(1).ToList(); } while (payloadBody.Last() == 0x2F) { payloadBody.RemoveAt(payloadBody.Count() - 1); } var list = new List <VariableDataRecord>(); // MBus has a maximum length of 255. byte indexer = 0; while (indexer < payloadBody.Count) { var difFieldByte = payloadBody[indexer++]; // TODO Handle special case stuff if (difFieldByte == 0x1F || difFieldByte == 0x0F) { break; } var dataInformationField = new DataInformationField(difFieldByte); var dataInformationFieldExtensions = new List <DataInformationExtensionField>(); var difesAvailable = dataInformationField.HasExtensionBit; while (difesAvailable) { var extension = new DataInformationExtensionField(payloadBody[indexer++]); dataInformationFieldExtensions.Add(extension); difesAvailable = extension.HasExtensionBit; } var valueInformationField = new PrimaryValueInformationField(payloadBody[indexer++], dataInformationField.DataField); var valueInformationFieldExtensions = new List <ValueInformationExtensionField>(); var vifesAvailable = valueInformationField.HasExtensionBit; while (vifesAvailable) { ValueInformationExtensionField?extension = null; if (!valueInformationFieldExtensions.Any()) { switch (valueInformationField.Type) { case PrimaryValueInformation.FBValueInformationExtension: extension = new FBValueInformationExtensionField(payloadBody[indexer++]); break; case PrimaryValueInformation.FDValueInformationExtension: extension = new FDValueInformationExtensionField(payloadBody[indexer++]); break; case PrimaryValueInformation.ManufacturerSpecific: switch (header.ManufacturerName.ToLowerInvariant()) { case "kam": extension = new KamstrupValueInformationExtensionField(payloadBody[indexer++]); break; } break; default: extension = new UnknownValueInformationExtensionField(payloadBody[indexer++]); break; } } else { extension = new OrthogonalValueInformationExtensionField(payloadBody[indexer++]); } valueInformationFieldExtensions.Add(extension); vifesAvailable = extension.HasExtensionBit; } // is LVAR, the length of the data is in the first byte of the "real" data. if (dataInformationField.DataLength == null && dataInformationField.DataField == DataField.VariableLength) { dataInformationField.DataLength = payloadBody[indexer++]; } var dataBlock = new DataBlock(payloadBody.Skip(indexer).Take(dataInformationField.DataLength.Value).ToArray(), dataInformationField, dataInformationFieldExtensions, valueInformationField, valueInformationFieldExtensions); indexer = (byte)(indexer + dataInformationField.DataLength.Value); list.Add(new VariableDataRecord(dataBlock)); } return(list); }