/// <summary> /// Atempt to decode dataset from the Keyvalue pairs /// </summary> private void DecodePossibleDataSetReader(JsonDecoder jsonDecoder, DataSetReaderDataType dataSetReader) { // check if there shall be a dataset header and decode it if (HasDataSetMessageHeader) { DecodeDataSetMessageHeader(jsonDecoder); } if (dataSetReader.DataSetWriterId != 0 && DataSetWriterId != dataSetReader.DataSetWriterId) { return; } object token = null; string payloadStructureName = kFieldPayload; // try to read "Payload" structure if (!jsonDecoder.ReadField(kFieldPayload, out token)) { // Decode the Messages element in case there is no "Payload" structure jsonDecoder.ReadField(null, out token); payloadStructureName = null; } Dictionary <string, object> payload = token as Dictionary <string, object>; if (payload != null) { if (payload.Count > dataSetReader.DataSetMetaData.Fields.Count) { // filter out payload that has more fields than the searched datasetMetadata return; } // check also the field names from reader, if any extra field names then the payload is not matching foreach (string key in payload.Keys) { var field = dataSetReader.DataSetMetaData.Fields.FirstOrDefault(f => f.Name == key); if (field == null) { // the field from payload was not found in dataSetReader therefore the payload is not suitable to be decoded return; } } } try { // try decoding Payload Structure bool wasPush = jsonDecoder.PushStructure(payloadStructureName); if (wasPush) { DataSet = DecodePayloadContent(jsonDecoder, dataSetReader); } } finally { // redo decode stack jsonDecoder.Pop(); } }
/// <summary> /// Decode dataset from the provided json decoder using the provided <see cref="DataSetReaderDataType"/>. /// </summary> /// <param name="jsonDecoder">The json decoder that contains the json stream.</param> /// <param name="messagesCount">Number of Messages found in current jsonDecoder. If 0 then there is SingleDataSetMessage</param> /// <param name="messagesListName">The name of the Messages list</param> /// <param name="dataSetReader">The <see cref="DataSetReaderDataType"/> used to decode the data set.</param> public void DecodePossibleDataSetReader(JsonDecoder jsonDecoder, int messagesCount, string messagesListName, DataSetReaderDataType dataSetReader) { if (messagesCount == 0) { // check if there shall be a dataset header and decode it if (HasDataSetMessageHeader) { DecodeDataSetMessageHeader(jsonDecoder); // push into PayloadStructure if there was a dataset header jsonDecoder.PushStructure(kFieldPayload); } DecodeErrorReason = ValidateMetadataVersion(dataSetReader?.DataSetMetaData?.ConfigurationVersion); if (IsMetadataMajorVersionChange) { return; } // handle single dataset with no network message header & no dataset message header (the content of the payload) DataSet = DecodePayloadContent(jsonDecoder, dataSetReader); } else { for (int index = 0; index < messagesCount; index++) { bool wasPush = jsonDecoder.PushArray(messagesListName, index); if (wasPush) { // atempt decoding the DataSet fields DecodePossibleDataSetReader(jsonDecoder, dataSetReader); // redo jsonDecoder stack jsonDecoder.Pop(); if (DataSet != null) { // the dataset was decoded return; } } } } }
/// <summary> /// Decode the Content of the Payload and create a DataSet object from it /// </summary> private DataSet DecodePayloadContent(JsonDecoder jsonDecoder, DataSetReaderDataType dataSetReader) { TargetVariablesDataType targetVariablesData = ExtensionObject.ToEncodeable(dataSetReader.SubscribedDataSet) as TargetVariablesDataType; DataSetMetaDataType dataSetMetaData = dataSetReader.DataSetMetaData; object token; List <DataValue> dataValues = new List <DataValue>(); for (int index = 0; index < dataSetMetaData?.Fields.Count; index++) { FieldMetaData fieldMetaData = dataSetMetaData?.Fields[index]; if (jsonDecoder.ReadField(fieldMetaData.Name, out token)) { switch (m_fieldTypeEncoding) { case FieldTypeEncodingMask.Variant: Variant variantValue = jsonDecoder.ReadVariant(fieldMetaData.Name); dataValues.Add(new DataValue(variantValue)); break; case FieldTypeEncodingMask.RawData: object value = DecodeRawData(jsonDecoder, dataSetMetaData?.Fields[index], dataSetMetaData?.Fields[index].Name); dataValues.Add(new DataValue(new Variant(value))); break; case FieldTypeEncodingMask.DataValue: bool wasPush2 = jsonDecoder.PushStructure(fieldMetaData.Name); DataValue dataValue = new DataValue(Variant.Null); try { if (wasPush2 && jsonDecoder.ReadField("Value", out token)) { // the Value was encoded using the non reversible json encoding token = DecodeRawData(jsonDecoder, dataSetMetaData?.Fields[index], "Value"); dataValue = new DataValue(new Variant(token)); } else { // handle Good StatusCode that was not encoded if (dataSetMetaData?.Fields[index].BuiltInType == (byte)BuiltInType.StatusCode) { dataValue = new DataValue(new Variant(new StatusCode(StatusCodes.Good))); } } if ((FieldContentMask & DataSetFieldContentMask.StatusCode) != 0) { if (jsonDecoder.ReadField("StatusCode", out token)) { bool wasPush3 = jsonDecoder.PushStructure("StatusCode"); if (wasPush3) { dataValue.StatusCode = jsonDecoder.ReadStatusCode("Code"); jsonDecoder.Pop(); } } } if ((FieldContentMask & DataSetFieldContentMask.SourceTimestamp) != 0) { dataValue.SourceTimestamp = jsonDecoder.ReadDateTime("SourceTimestamp"); } if ((FieldContentMask & DataSetFieldContentMask.SourcePicoSeconds) != 0) { dataValue.SourcePicoseconds = jsonDecoder.ReadUInt16("SourcePicoseconds"); } if ((FieldContentMask & DataSetFieldContentMask.ServerTimestamp) != 0) { dataValue.ServerTimestamp = jsonDecoder.ReadDateTime("ServerTimestamp"); } if ((FieldContentMask & DataSetFieldContentMask.ServerPicoSeconds) != 0) { dataValue.ServerPicoseconds = jsonDecoder.ReadUInt16("ServerPicoseconds"); } dataValues.Add(dataValue); } finally { if (wasPush2) { jsonDecoder.Pop(); } } break; } } else { switch (m_fieldTypeEncoding) { case FieldTypeEncodingMask.Variant: case FieldTypeEncodingMask.RawData: // handle StatusCodes.Good which is not encoded and therefore must be created at decode if (dataSetMetaData?.Fields[index].BuiltInType == (byte)BuiltInType.StatusCode) { dataValues.Add(new DataValue(new Variant(new StatusCode(StatusCodes.Good)))); } else { // the field is null dataValues.Add(new DataValue(Variant.Null)); } break; } } } if (dataValues.Count != dataSetMetaData?.Fields.Count) { return(null); } //build the DataSet Fields collection based on the decoded values and the target List <Field> dataFields = new List <Field>(); for (int i = 0; i < dataValues.Count; i++) { Field dataField = new Field(); dataField.FieldMetaData = dataSetMetaData?.Fields[i]; dataField.Value = dataValues[i]; if (targetVariablesData != null && targetVariablesData.TargetVariables != null && i < targetVariablesData.TargetVariables.Count) { // remember the target Attribute and target nodeId dataField.TargetAttribute = targetVariablesData.TargetVariables[i].AttributeId; dataField.TargetNodeId = targetVariablesData.TargetVariables[i].TargetNodeId; } dataFields.Add(dataField); } // build the dataset object DataSet dataSet = new DataSet(dataSetMetaData?.Name); dataSet.Fields = dataFields.ToArray(); dataSet.DataSetWriterId = DataSetWriterId; dataSet.SequenceNumber = SequenceNumber; return(dataSet); }