/// <summary> /// Returns TRUE if the next DataSetMessage is a delta frame. /// </summary> public bool HasMetaDataChanged(DataSetWriterDataType writer, DataSetMetaDataType metadata) { if (metadata == null) { return(false); } lock (m_dataSetStates) { DataSetState state = GetState(writer); ConfigurationVersionDataType version = state.ConfigurationVersion; // no matter what the TransportSettings.MetaDataUpdateTime is the ConfigurationVersion is checked if (version == null) { // keep a copy of ConfigurationVersion state.ConfigurationVersion = metadata.ConfigurationVersion.MemberwiseClone() as ConfigurationVersionDataType; state.LastMetaDataUpdate = DateTime.UtcNow; return(true); } if (version.MajorVersion != metadata.ConfigurationVersion.MajorVersion || version.MinorVersion != metadata.ConfigurationVersion.MinorVersion) { // keep a copy of ConfigurationVersion state.ConfigurationVersion = metadata.ConfigurationVersion.MemberwiseClone() as ConfigurationVersionDataType; state.LastMetaDataUpdate = DateTime.UtcNow; return(true); } } return(false); }
private static void Compare(ConfigurationVersionDataType source, ConfigurationVersionDataType mirror) { Assert.IsNotNull(source); Assert.IsNotNull(mirror); Assert.AreEqual <int>(source.MajorVersion, mirror.MajorVersion); Assert.AreEqual <int>(source.MinorVersion, mirror.MinorVersion); }
public void Send (Func <int, IProducerBinding> producerBinding, ushort length, ulong contentMask, FieldEncodingEnum encoding, DataSelector dataSelector, ushort messageSequenceNumber, DateTime timeStamp, ConfigurationVersionDataType configurationVersion) { IsOk++; Assert.AreEqual <int>(3, length); }
public void ConfigurationVersionDataTypeTestMethod() { ConfigurationVersionDataType _newInstance = new ConfigurationVersionDataType() { MajorVersion = 1, MinorVersion = 2 }; Assert.AreEqual <string>("1.2", _newInstance.ToString()); }
public ProducerMessageHeader(IBinaryHeaderEncoder writer, FieldEncodingEnum encoding, MessageLengthFieldTypeEnum lengthFieldType, MessageTypeEnum messageType, ConfigurationVersionDataType configurationVersion) { m_MessageType = messageType; m_Encoding = encoding; m_lengthFieldType = lengthFieldType; m_HeaderWriter = new HeaderWriter(writer, PackageHeaderLength()); MessageSequenceNumber = 0; ConfigurationVersion = configurationVersion; }
/// <summary> /// Create new instance of <see cref="UaDataSetMessage"/> /// </summary> public UaDataSetMessage() { Timestamp = DateTime.UtcNow; MetaDataVersion = new ConfigurationVersionDataType() { MajorVersion = ConfigMajorVersion, MinorVersion = ConfigMinorVersion }; }
/// <summary> /// Create new instance of <see cref="UaDataSetMessage"/> /// </summary> public UaDataSetMessage() { DecodeErrorReason = DataSetDecodeErrorReason.NoError; Timestamp = DateTime.UtcNow; MetaDataVersion = new ConfigurationVersionDataType() { MajorVersion = kDefaultConfigMajorVersion, MinorVersion = kDefaultConfigMinorVersion }; }
/// <summary> /// Decode DataSet message header /// </summary> /// <param name="decoder"></param> private void DecodeDataSetMessageHeader(IDecoder decoder) { if ((DataSetFlags1 & DataSetFlags1EncodingMask.MessageIsValid) != 0) { DataSetFlags1 = (DataSetFlags1EncodingMask)decoder.ReadByte("DataSetFlags1"); } if ((DataSetFlags1 & DataSetFlags1EncodingMask.DataSetFlags2) != 0) { DataSetFlags2 = (DataSetFlags2EncodingMask)decoder.ReadByte("DataSetFlags2"); } if ((DataSetFlags1 & DataSetFlags1EncodingMask.SequenceNumber) != 0) { SequenceNumber = decoder.ReadUInt16("SequenceNumber"); } if ((DataSetFlags2 & DataSetFlags2EncodingMask.Timestamp) != 0) { Timestamp = decoder.ReadDateTime("Timestamp"); } if ((DataSetFlags2 & DataSetFlags2EncodingMask.PicoSeconds) != 0) { PicoSeconds = decoder.ReadUInt16("Picoseconds"); } if ((DataSetFlags1 & DataSetFlags1EncodingMask.Status) != 0) { // This is the high order 16 bits of the StatusCode DataType representing // the numeric value of the Severity and SubCode of the StatusCode DataType. UInt16 code = decoder.ReadUInt16("Status"); Status = ((uint)code) << 16; } uint minorVersion = kDefaultConfigMinorVersion; uint majorVersion = kDefaultConfigMajorVersion; if ((DataSetFlags1 & DataSetFlags1EncodingMask.ConfigurationVersionMajorVersion) != 0) { majorVersion = decoder.ReadUInt32("ConfigurationMajorVersion"); } if ((DataSetFlags1 & DataSetFlags1EncodingMask.ConfigurationVersionMinorVersion) != 0) { minorVersion = decoder.ReadUInt32("ConfigurationMinorVersion"); } MetaDataVersion = new ConfigurationVersionDataType() { MinorVersion = minorVersion, MajorVersion = majorVersion }; }
/// <summary> /// Validates the MetadataVersion against a given ConfigurationVersionDataType /// </summary> /// <param name="configurationVersionDataType">The value to validate MetadataVersion against</param> /// <returns>NoError if validation passes or the cause of the failure</returns> protected DataSetDecodeErrorReason ValidateMetadataVersion(ConfigurationVersionDataType configurationVersionDataType) { if (MetaDataVersion.MajorVersion != kDefaultConfigMajorVersion) { if (MetaDataVersion.MajorVersion != configurationVersionDataType.MajorVersion) { return(DataSetDecodeErrorReason.MetadataMajorVersion); } } return(DataSetDecodeErrorReason.NoError); }
/// <summary> /// Sends the data described by a data set collection to remote destination. /// </summary> /// <param name="producerBinding">Encapsulates functionality used by the <see cref="T:UAOOI.Networking.SemanticData.MessageHandling.IMessageWriter" /> to collect all the data (data set items) required to prepare new message and send it over the network.</param> /// <param name="length">Number of items to be send used to calculate the length of the message.</param> /// <param name="contentMask">The content mask represented as unsigned number <see cref="T:System.UInt64" />. The order of the bits starting from the least significant /// bit matches the order of the data items within the data set.</param> /// <param name="encoding">The encoding.</param> /// <param name="dataSelector">The data selector.</param> /// <param name="messageSequenceNumber">The message sequence number. A monotonically increasing sequence number assigned by the publisher to each message sent.</param> /// <param name="timeStamp">The time stamp - the time the Data was collected.</param> /// <param name="configurationVersion">The configuration version.</param> /// <exception cref="ArgumentOutOfRangeException">length</exception> public void Send (Func <int, IProducerBinding> producerBinding, ushort length, ulong contentMask, FieldEncodingEnum encoding, DataSelector dataSelector, ushort messageSequenceNumber, DateTime timeStamp, ConfigurationVersionDataType configurationVersion) { if (length > 2) { throw new ArgumentOutOfRangeException("length"); } m_Buffer = new Object[length]; for (int i = 0; i < 2; i++) { m_Buffer[i] = producerBinding(i); } m_HaveSendData = true; }
/// <summary> /// Encode as binary /// </summary> /// <param name="decoder"></param> private void DecodeBinary(IDecoder decoder) { MessageContentMask = decoder.ReadUInt32(nameof(MessageContentMask)); DataSetWriterId = decoder.ReadString(nameof(DataSetWriterId)); if ((MessageContentMask & (uint)UadpDataSetMessageContentMask.SequenceNumber) != 0) { SequenceNumber = decoder.ReadUInt32(nameof(UadpDataSetMessageContentMask.SequenceNumber)); } MetaDataVersion = new ConfigurationVersionDataType() { MajorVersion = 0, MinorVersion = 0 }; if ((MessageContentMask & (uint)UadpDataSetMessageContentMask.MajorVersion) != 0) { MetaDataVersion.MajorVersion = decoder.ReadUInt32(nameof(UadpDataSetMessageContentMask.MajorVersion)); } if ((MessageContentMask & (uint)UadpDataSetMessageContentMask.MinorVersion) != 0) { MetaDataVersion.MinorVersion = decoder.ReadUInt32(nameof(UadpDataSetMessageContentMask.MinorVersion)); } if ((MessageContentMask & (uint)UadpDataSetMessageContentMask.Timestamp) != 0) { Timestamp = decoder.ReadDateTime(nameof(UadpDataSetMessageContentMask.Timestamp)); } // TODO probably required /* * if ((MessageContentMask & (uint)UadpDataSetMessageContentMask.PicoSeconds) != 0) { * Picoseconds = encoder.ReadUInt32(nameof(UadpDataSetMessageContentMask.PicoSeconds)); * } */ if ((MessageContentMask & (uint)UadpDataSetMessageContentMask.Status) != 0) { Status = decoder.ReadStatusCode(nameof(Status)); } var payload = (KeyDataValuePairCollection)decoder.ReadEncodeableArray(nameof(Payload), typeof(KeyDataValuePair)); Payload = new DataSet(); foreach (var tuple in payload) { Payload[tuple.Key] = new DataValue(tuple.Value); } }
/// <summary> /// Returns TRUE if the next DataSetMessage is a delta frame. /// </summary> public bool HasMetaDataChanged(DataSetWriterDataType writer, DataSetMetaDataType metadata, double updateTime) { if (metadata == null) { return(false); } lock (DataSets) { DataSetState state = GetState(writer); ConfigurationVersionDataType version = state.ConfigurationVersion; if (version == null) { state.ConfigurationVersion = metadata.ConfigurationVersion; state.LastMetaDataUpdate = DateTime.UtcNow; return(true); } if (version.MajorVersion != metadata.ConfigurationVersion.MajorVersion || version.MinorVersion != metadata.ConfigurationVersion.MinorVersion) { state.ConfigurationVersion = metadata.ConfigurationVersion; state.LastMetaDataUpdate = DateTime.UtcNow; return(true); } if (updateTime > 0) { if (state.LastMetaDataUpdate.AddMilliseconds(updateTime) <= DateTime.UtcNow) { state.LastMetaDataUpdate = DateTime.UtcNow; return(true); } } } return(false); }
/// <summary> /// Sends the data described by a data set collection to remote destination. /// </summary> /// <param name="producerBinding">Encapsulates functionality used by the <see cref="IMessageWriter" /> to collect all the data (data set items) required to prepare new message and send it over the network.</param> /// <param name="length">Number of items to be send used to calculate the length of the message.</param> /// <param name="contentMask">The content mask represented as unsigned number <see cref="UInt64" />. The order of the bits starting from the least significant /// bit matches the order of the data items within the data set.</param> /// <param name="encoding">The encoding.</param> /// <param name="dataSelector">The data selector.</param> /// <param name="messageSequenceNumber">The message sequence number. A monotonically increasing sequence number assigned by the publisher to each message sent.</param> /// <param name="timeStamp">The time stamp - the time the Data was collected.</param> /// <param name="configurationVersion">The configuration version.</param> /// <exception cref="System.ArgumentOutOfRangeException">Impossible to convert null value /// or</exception> void IMessageWriter.Send (Func <int, IProducerBinding> producerBinding, ushort length, ulong contentMask, FieldEncodingEnum encoding, DataSelector dataSelector, ushort messageSequenceNumber, DateTime timeStamp, ConfigurationVersionDataType configurationVersion) { lock (this) { if (State.State != HandlerState.Operational) { return; } ContentMask = contentMask; CreateMessage(encoding, dataSelector.PublisherId, dataSelector.DataSetWriterId, length, messageSequenceNumber, timeStamp, configurationVersion); //UInt64 _mask = 0x1; for (int i = 0; i < length; i++) { //TODO: Implement ContentMask https://github.com/mpostol/OPC-UA-OOI/issues/89 //if ((ContentMask & _mask) > 0) //{ IProducerBinding _pb = producerBinding(i); switch (encoding) { case FieldEncodingEnum.VariantFieldEncoding: WriteValueVariant(_pb); break; case FieldEncodingEnum.CompressedFieldEncoding: WriteValue(_pb); break; case FieldEncodingEnum.DataValueFieldEncoding: WriteDataValue(_pb); break; } //} //_mask = _mask << 1; } SendMessage(); } }
/// <summary> /// Gets the producer message header. /// </summary> /// <param name="writer">The writer <see cref="IBinaryHeaderEncoder" /> to populate the payload with the header information.</param> /// <param name="encoding">The encoding.</param> /// <param name="lengthFieldType">Type of the length field in the the message header.</param> /// <param name="messageType">Type of the message.</param> /// <param name="configurationVersion">The configuration version.</param> /// <returns>MessageHeader.</returns> internal static MessageHeader GetProducerMessageHeader(IBinaryHeaderEncoder writer, FieldEncodingEnum encoding, MessageLengthFieldTypeEnum lengthFieldType, MessageTypeEnum messageType, ConfigurationVersionDataType configurationVersion) { return(new ProducerMessageHeader(writer, encoding, lengthFieldType, messageType, configurationVersion)); }
protected internal override void CreateMessage (FieldEncodingEnum encoding, Guid prodicerId, ushort dataSetWriterId, ushort fieldCount, ushort sequenceNumber, DateTime timeStamp, ConfigurationVersionDataType configurationVersion) { MassageCreated = true; }
//methods /// <summary> /// Creates the message. /// </summary> /// <param name="encoding">The selected encoding for the message.</param> /// <param name="producerId">The producer identifier.</param> /// <param name="dataSetWriterId">The data set writer identifier.</param> /// <param name="fieldCount">The field count.</param> /// <param name="sequenceNumber">The sequence number.</param> /// <param name="timeStamp">The time stamp.</param> /// <param name="configurationVersion">The configuration version.</param> protected internal abstract void CreateMessage (FieldEncodingEnum encoding, Guid producerId, ushort dataSetWriterId, ushort fieldCount, ushort sequenceNumber, DateTime timeStamp, ConfigurationVersionDataType configurationVersion);
/// <summary> /// Creates the message. /// </summary> /// <param name="encoding">The selected encoding for the message.</param> /// <param name="prodicerId">The producer identifier.</param> /// <param name="dataSetWriterId">The data set writer identifier.</param> /// <param name="fieldCount">The field count.</param> /// <param name="sequenceNumber">The sequence number.</param> /// <param name="timeStamp">The time stamp.</param> /// <param name="configurationVersion">The configuration version.</param> protected internal override void CreateMessage (FieldEncodingEnum encoding, Guid prodicerId, ushort dataSetWriterId, ushort fieldCount, ushort sequenceNumber, DateTime timeStamp, ConfigurationVersionDataType configurationVersion) { OnMessageAdding(prodicerId, dataSetWriterId); MessageHeader = MessageHeader.GetProducerMessageHeader(this, encoding, m_lengthFieldType, MessageTypeEnum.DataKeyFrame, configurationVersion); //Create message header and placeholder for further header content. MessageHeader.FieldCount = fieldCount; MessageHeader.MessageSequenceNumber = sequenceNumber; MessageHeader.TimeStamp = timeStamp; }