/// <summary> /// Encode Network Message Header /// </summary> /// <param name="jsonDecoder"></param> private void DecodeNetworkMessageHeader(JsonDecoder jsonDecoder) { object token = null; if (jsonDecoder.ReadField(nameof(MessageId), out token)) { MessageId = jsonDecoder.ReadString(nameof(MessageId)); NetworkMessageContentMask = JsonNetworkMessageContentMask.NetworkMessageHeader; } if (jsonDecoder.ReadField(nameof(MessageType), out token)) { MessageType = jsonDecoder.ReadString(nameof(MessageType)); } if (jsonDecoder.ReadField(nameof(PublisherId), out token)) { PublisherId = jsonDecoder.ReadString(nameof(PublisherId)); NetworkMessageContentMask |= JsonNetworkMessageContentMask.PublisherId; } if (jsonDecoder.ReadField(nameof(DataSetClassId), out token)) { DataSetClassId = jsonDecoder.ReadString(nameof(DataSetClassId)); NetworkMessageContentMask |= JsonNetworkMessageContentMask.DataSetClassId; } }
/// <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> /// Decodes the DataSetMessageHeader /// </summary> private void DecodeDataSetMessageHeader(JsonDecoder jsonDecoder) { object token = null; if ((DataSetMessageContentMask & JsonDataSetMessageContentMask.DataSetWriterId) != 0) { if (jsonDecoder.ReadField(nameof(DataSetWriterId), out token)) { DataSetWriterId = Convert.ToUInt16(jsonDecoder.ReadString(nameof(DataSetWriterId))); } } if ((DataSetMessageContentMask & JsonDataSetMessageContentMask.SequenceNumber) != 0) { if (jsonDecoder.ReadField(nameof(SequenceNumber), out token)) { SequenceNumber = jsonDecoder.ReadUInt32(nameof(SequenceNumber)); } } if ((DataSetMessageContentMask & JsonDataSetMessageContentMask.MetaDataVersion) != 0) { if (jsonDecoder.ReadField(nameof(MetaDataVersion), out token)) { MetaDataVersion = jsonDecoder.ReadEncodeable(nameof(MetaDataVersion), typeof(ConfigurationVersionDataType)) as ConfigurationVersionDataType; } } if ((DataSetMessageContentMask & JsonDataSetMessageContentMask.Timestamp) != 0) { if (jsonDecoder.ReadField(nameof(Timestamp), out token)) { Timestamp = jsonDecoder.ReadDateTime(nameof(Timestamp)); } } if ((DataSetMessageContentMask & JsonDataSetMessageContentMask.Status) != 0) { if (jsonDecoder.ReadField(nameof(Status), out token)) { Status = jsonDecoder.ReadStatusCode(nameof(Status)); } } }
/// <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); }
/// <summary> /// Decode the stream from decoder parameter and produce a Dataset /// </summary> /// <param name="jsonDecoder"></param> /// <param name="dataSetReaders"></param> /// <returns></returns> public void DecodeSubscribedDataSets(JsonDecoder jsonDecoder, IEnumerable <DataSetReaderDataType> dataSetReaders) { try { List <DataSetReaderDataType> dataSetReadersFiltered = new List <DataSetReaderDataType>(); // 1. decode network message header (PublisherId & DataSetClassId) DecodeNetworkMessageHeader(jsonDecoder); // ignore network messages that are not dataSet messages if (m_jsonNetworkMessageType != JSONNetworkMessageType.DataSetMessage) { return; } //* 6.2.8.1 PublisherId // The parameter PublisherId defines the Publisher to receive NetworkMessages from. // If the value is null, the parameter shall be ignored and all received NetworkMessages pass the PublisherId filter. */ foreach (DataSetReaderDataType dataSetReader in dataSetReaders) { if (dataSetReader.PublisherId == Variant.Null) { dataSetReadersFiltered.Add(dataSetReader); } // publisher id else if ((NetworkMessageContentMask & JsonNetworkMessageContentMask.PublisherId) != 0 && PublisherId != null && PublisherId.Equals(dataSetReader.PublisherId.Value.ToString())) { dataSetReadersFiltered.Add(dataSetReader); } } if (dataSetReadersFiltered.Count == 0) { return; } dataSetReaders = dataSetReadersFiltered; object messagesToken = null; List <object> messagesList = null; string messagesListName = string.Empty; if (jsonDecoder.ReadField(kFieldMessages, out messagesToken)) { messagesList = messagesToken as List <object>; if (messagesList == null) { // this is a SingleDataSetMessage encoded as the conteten of Messages jsonDecoder.PushStructure(kFieldMessages); messagesList = new List <object>(); } else { messagesListName = kFieldMessages; } } else if (jsonDecoder.ReadField(JsonDecoder.RootArrayName, out messagesToken)) { messagesList = messagesToken as List <object>; messagesListName = JsonDecoder.RootArrayName; } else { // this is a SingleDataSetMessage encoded as the conteten of json messagesList = new List <object>(); } if (messagesList != null) { // atempt decoding for each data set reader foreach (DataSetReaderDataType dataSetReader in dataSetReaders) { JsonDataSetReaderMessageDataType jsonMessageSettings = ExtensionObject.ToEncodeable(dataSetReader.MessageSettings) as JsonDataSetReaderMessageDataType; if (jsonMessageSettings == null) { // The reader MessageSettings is not set up corectly continue; } JsonNetworkMessageContentMask networkMessageContentMask = (JsonNetworkMessageContentMask)jsonMessageSettings.NetworkMessageContentMask; if ((networkMessageContentMask & NetworkMessageContentMask) != NetworkMessageContentMask) { // The reader MessageSettings.NetworkMessageContentMask is not set up corectly continue; } // initialize the dataset message JsonDataSetMessage jsonDataSetMessage = new JsonDataSetMessage(); jsonDataSetMessage.DataSetMessageContentMask = (JsonDataSetMessageContentMask)jsonMessageSettings.DataSetMessageContentMask; jsonDataSetMessage.SetFieldContentMask((DataSetFieldContentMask)dataSetReader.DataSetFieldContentMask); // set the flag that indicates if dataset message shall have a header jsonDataSetMessage.HasDataSetMessageHeader = (networkMessageContentMask & JsonNetworkMessageContentMask.DataSetMessageHeader) != 0; jsonDataSetMessage.DecodePossibleDataSetReader(jsonDecoder, messagesList.Count, messagesListName, dataSetReader); if (jsonDataSetMessage.DataSet != null) { m_uaDataSetMessages.Add(jsonDataSetMessage); } } } } catch (Exception ex) { // Unexpected exception in DecodeSubscribedDataSets Utils.Trace(ex, "JsonNetworkMessage.DecodeSubscribedDataSets"); } }
/// <summary> /// Encode Network Message Header /// </summary> /// <param name="jsonDecoder"></param> private void DecodeNetworkMessageHeader(JsonDecoder jsonDecoder) { object token = null; if (jsonDecoder.ReadField(nameof(MessageId), out token)) { MessageId = jsonDecoder.ReadString(nameof(MessageId)); NetworkMessageContentMask = JsonNetworkMessageContentMask.NetworkMessageHeader; } if (jsonDecoder.ReadField(nameof(MessageType), out token)) { MessageType = jsonDecoder.ReadString(nameof(MessageType)); // detect the json network message type if (MessageType == kDataSetMessageType) { m_jsonNetworkMessageType = JSONNetworkMessageType.DataSetMessage; } else if (MessageType == kMetaDataMessageType) { m_jsonNetworkMessageType = JSONNetworkMessageType.DataSetMetaData; } else { m_jsonNetworkMessageType = JSONNetworkMessageType.Invalid; Utils.Format("Invalid JSON MessageType: {0}. Supported values are {1} and {2}.", MessageType, kDataSetMessageType, kMetaDataMessageType); } } if (jsonDecoder.ReadField(nameof(PublisherId), out token)) { PublisherId = jsonDecoder.ReadString(nameof(PublisherId)); if (m_jsonNetworkMessageType == JSONNetworkMessageType.DataSetMessage) { // the NetworkMessageContentMask is set only for DataSet messages NetworkMessageContentMask |= JsonNetworkMessageContentMask.PublisherId; } } if (jsonDecoder.ReadField(nameof(DataSetClassId), out token)) { DataSetClassId = jsonDecoder.ReadString(nameof(DataSetClassId)); NetworkMessageContentMask |= JsonNetworkMessageContentMask.DataSetClassId; } if (m_jsonNetworkMessageType == JSONNetworkMessageType.DataSetMetaData) { // for metadata messages the DataSetWriterId field is mandatory if (jsonDecoder.ReadField(nameof(DataSetWriterId), out token)) { DataSetWriterId = jsonDecoder.ReadUInt16(nameof(DataSetWriterId)); } else { Utils.Trace("The JSON MetaDataMessage cannot be decoded: The DataSetWriterId property is missing for MessageId:{0}.", MessageId); } } }