Skip to content

Commit

Permalink
Test
Browse files Browse the repository at this point in the history
  • Loading branch information
marcschier committed Sep 2, 2024
1 parent b55cb00 commit 38e2ca0
Show file tree
Hide file tree
Showing 7 changed files with 99 additions and 25 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -450,13 +450,46 @@ public async Task CanSendKeyFramesWithExtensionFieldsToIoTHubTest()
Assert.All(expectedNames, n => fieldNames.Contains(n));
}

[Fact]
public async Task CanSendFullAndCompliantNetworkMessageWithEndpointUrlAndApplicationUriToIoTHubTest()
{
// Arrange
// Act
var (metadata, messages) = await ProcessMessagesAndMetadataAsync(
nameof(CanSendDataItemToIoTHubTest), "./Resources/DataItems.json", messageType: "ua-data",
arguments: new string[] { "--mm=PubSub", "--fm=true", "--strict" });

// Assert
var message = Assert.Single(messages).Message;
var firstDataSet = message.GetProperty("Messages")[0];
var payload = firstDataSet.GetProperty("Payload");
Assert.NotEqual(JsonValueKind.Null, payload.ValueKind);
var output = payload.GetProperty("Output");
Assert.NotEqual(JsonValueKind.Null, output.ValueKind);
Assert.InRange(output.GetProperty("Value").GetDouble(), double.MinValue, double.MaxValue);
var ep = payload.GetProperty("EndpointUrl").GetProperty("Value").GetString();
Assert.False(string.IsNullOrEmpty(ep));
var appuri = payload.GetProperty("ApplicationUri").GetProperty("Value").GetString();
Assert.False(string.IsNullOrEmpty(appuri));

Assert.NotNull(metadata);
var fields = metadata.Value.Message.GetProperty("MetaData").GetProperty("Fields");
Assert.Equal(JsonValueKind.Array, fields.ValueKind);
var fieldNames = fields.EnumerateArray().Select(v => v.GetProperty("Name").GetString()).ToList();
Assert.Equal(3, fieldNames.Count);
Assert.Equal("Output", fieldNames[0]);
Assert.Equal("EndpointUrl", fieldNames[1]);
Assert.Equal("ApplicationUri", fieldNames[2]);
}

[Fact]
public async Task CanSendKeyFramesWithExtensionFieldsToIoTHubTestJsonReversible()
{
// Arrange
// Act
var (metadata, messages) = await ProcessMessagesAndMetadataAsync(
nameof(CanSendDataItemToIoTHubTest), "./Resources/KeyFrames.json", messageType: "ua-data",
// NOTE: while we --fm and fullnetworkmessage, the keyframes.json overrides this back to PubSub
arguments: new string[] { "--mm=FullNetworkMessages", "--me=JsonReversible", "--fm=true", "--strict" });

// Assert
Expand All @@ -469,6 +502,12 @@ public async Task CanSendKeyFramesWithExtensionFieldsToIoTHubTestJsonReversible(
var time = payload.GetProperty("CurrentTime").GetProperty("Value");
Assert.NotEqual(JsonValueKind.Null, time.ValueKind);
Assert.True(time.GetProperty("Body").GetDateTime() < DateTime.UtcNow);

var ep = payload.TryGetProperty("EndpointUrl", out _);
Assert.False(ep);
var appuri = payload.TryGetProperty("ApplicationUri", out _);
Assert.False(appuri);

Assert.False(payload.GetProperty("Important").GetProperty("Value").GetProperty("Body").GetBoolean());
Assert.Equal("5", payload.GetProperty("AssetId").GetProperty("Value").GetProperty("Body").GetString());
Assert.Equal("mm/sec", payload.GetProperty("EngineeringUnits").GetProperty("Value").GetProperty("Body").GetString());
Expand All @@ -483,7 +522,6 @@ public async Task CanSendKeyFramesWithExtensionFieldsToIoTHubTestJsonReversible(
Assert.All(expectedNames, n => fieldNames.Contains(n));
// TODO: Need to have order in fields! Assert.Equal(metadataFields.EnumerateArray().Select(v => v.GetProperty("Name").GetString()),
// TODO: Need to have order in fields! payload.EnumerateObject().Select(p => p.Name));
Assert.NotNull(metadata);
}

[Fact]
Expand Down
21 changes: 13 additions & 8 deletions src/Azure.IIoT.OpcUa.Publisher/src/Models/MessagingProfile.cs
Original file line number Diff line number Diff line change
Expand Up @@ -241,11 +241,11 @@ static MessagingProfile()
// Sample mode
AddProfile(MessagingMode.Samples, BuildDataSetContentMask(),
BuildNetworkMessageContentMask(true),
BuildDataSetFieldContentMask(),
BuildDataSetFieldContentMask(false, true),
MessageEncoding.Json);
AddProfile(MessagingMode.FullSamples, BuildDataSetContentMask(true),
BuildNetworkMessageContentMask(true),
BuildDataSetFieldContentMask(true),
BuildDataSetFieldContentMask(true, true),
MessageEncoding.Json);

//
Expand Down Expand Up @@ -287,11 +287,11 @@ static MessagingProfile()
MessageEncoding.JsonReversible, MessageEncoding.JsonReversibleGzip);
AddProfile(MessagingMode.Samples, BuildDataSetContentMask(false, true),
BuildNetworkMessageContentMask(true),
BuildDataSetFieldContentMask(),
BuildDataSetFieldContentMask(false, true),
MessageEncoding.JsonReversible, MessageEncoding.JsonReversibleGzip);
AddProfile(MessagingMode.FullSamples, BuildDataSetContentMask(true, true),
BuildNetworkMessageContentMask(true),
BuildDataSetFieldContentMask(true),
BuildDataSetFieldContentMask(true, true),
MessageEncoding.JsonReversible, MessageEncoding.JsonReversibleGzip);

// Without network message header
Expand Down Expand Up @@ -423,21 +423,26 @@ private static void AddProfile(MessagingMode messagingMode,
/// <summary>
/// From published nodes jobs converter
/// </summary>
/// <param name="isSampleMessage"></param>
/// <param name="fullFeaturedMessage"></param>
/// <returns></returns>
private static DataSetFieldContentFlags BuildDataSetFieldContentMask(
bool fullFeaturedMessage = false)
bool fullFeaturedMessage = false, bool isSampleMessage = false)
{
return
DataSetFieldContentFlags.StatusCode |
DataSetFieldContentFlags.SourceTimestamp |
(fullFeaturedMessage ?
(DataSetFieldContentFlags.ServerTimestamp |
DataSetFieldContentFlags.ApplicationUri |
DataSetFieldContentFlags.EndpointUrl |
DataSetFieldContentFlags.ExtensionFields) : 0) |
DataSetFieldContentFlags.NodeId |
DataSetFieldContentFlags.DisplayName |
DataSetFieldContentFlags.EndpointUrl;
(isSampleMessage ?
(DataSetFieldContentFlags.NodeId |
DataSetFieldContentFlags.DisplayName |
DataSetFieldContentFlags.EndpointUrl) :
DataSetFieldContentFlags.ServerTimestamp )
;
}

private static DataSetMessageContentFlags BuildDataSetContentMask(
Expand Down
11 changes: 6 additions & 5 deletions src/Azure.IIoT.OpcUa.Publisher/src/Services/DataSetWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ namespace Azure.IIoT.OpcUa.Publisher.Services
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Avro.Generic;

public sealed partial class WriterGroupDataSource
{
Expand Down Expand Up @@ -1040,22 +1041,22 @@ internal async Task UpdateMetaDataAsync(CancellationToken ct = default)
_writer._logger.LogDebug("Loading Metadata {Major}.{Minor} for {Writer}...",
dataSetMetaData.MajorVersion ?? 1, minor, _writer.Id);

var metaData = await subscription.CollectMetaDataAsync(_writer,
var fieldMask = _writer._writer.Writer.DataSetFieldContentMask;
var metaData = await subscription.CollectMetaDataAsync(_writer, fieldMask,
dataSetMetaData, minor, ct).ConfigureAwait(false);

_writer._logger.LogInformation(
"Loading Metadata {Major}.{Minor} for {Writer} took {Duration}.",
dataSetMetaData.MajorVersion ?? 1, minor, _writer.Id,
sw.Elapsed);

var msgMask = _writer._writer.Writer.MessageSettings?.DataSetMessageContentMask;
MetaData = new PublishedDataSetMessageSchemaModel
{
MetaData = metaData,
TypeName = null,
DataSetFieldContentFlags =
_writer._writer.Writer.DataSetFieldContentMask,
DataSetMessageContentFlags =
_writer._writer.Writer.MessageSettings?.DataSetMessageContentMask
DataSetFieldContentFlags = fieldMask,
DataSetMessageContentFlags = msgMask
};
}

Expand Down
6 changes: 4 additions & 2 deletions src/Azure.IIoT.OpcUa.Publisher/src/Stack/ISubscription.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,15 @@ public interface ISubscription : IAsyncDisposable
/// Collect metadata
/// </summary>
/// <param name="owner"></param>
/// <param name="fieldMask"></param>
/// <param name="dataSetMetaData"></param>
/// <param name="minorVersion"></param>
/// <param name="ct"></param>
/// <returns></returns>
ValueTask<PublishedDataSetMetaDataModel> CollectMetaDataAsync(
ISubscriber owner, DataSetMetaDataModel dataSetMetaData,
uint minorVersion, CancellationToken ct = default);
ISubscriber owner, DataSetFieldContentFlags? fieldMask,
DataSetMetaDataModel dataSetMetaData, uint minorVersion,
CancellationToken ct = default);

/// <summary>
/// Create a keep alive notification
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -455,16 +455,17 @@ public void NotifyMonitoredItemsChanged()

/// <inheritdoc/>
public async ValueTask<PublishedDataSetMetaDataModel> CollectMetaDataAsync(
ISubscriber owner, DataSetMetaDataModel dataSetMetaData,
uint minorVersion, CancellationToken ct = default)
ISubscriber owner, DataSetFieldContentFlags? fieldMask,
DataSetMetaDataModel dataSetMetaData, uint minorVersion,
CancellationToken ct = default)
{
if (!_outer.TryGetSubscription(Subscription, out var subscription))
{
throw new ServiceResultException(StatusCodes.BadNoSubscription,
"Subscription not found");
}
return await subscription.CollectMetaDataAsync(owner, dataSetMetaData,
minorVersion, ct).ConfigureAwait(false);
return await subscription.CollectMetaDataAsync(owner, fieldMask,
dataSetMetaData, minorVersion, ct).ConfigureAwait(false);
}

private readonly OpcUaClient _outer;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -343,15 +343,16 @@ protected override void Dispose(bool disposing)
/// Collect metadata
/// </summary>
/// <param name="owner"></param>
/// <param name="dataSetFieldContentMask"></param>
/// <param name="dataSetMetaData"></param>
/// <param name="minorVersion"></param>
/// <param name="ct"></param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
/// <exception cref="ServiceResultException"></exception>
internal async ValueTask<PublishedDataSetMetaDataModel> CollectMetaDataAsync(
ISubscriber owner, DataSetMetaDataModel dataSetMetaData, uint minorVersion,
CancellationToken ct)
ISubscriber owner, DataSetFieldContentFlags? dataSetFieldContentMask,
DataSetMetaDataModel dataSetMetaData, uint minorVersion, CancellationToken ct)
{
if (Session is not OpcUaSession session)
{
Expand All @@ -368,6 +369,21 @@ await monitoredItem.GetMetaDataAsync(session, typeSystem,
fields, dataTypes, ct).ConfigureAwait(false);
}

//
// For full featured messages there are additional fields that are required
// see data set json dataset message encoder for more information. This will
// not apply to other encodings yet, since they do not support full featured
// message modes.
//
if ((dataSetFieldContentMask & DataSetFieldContentFlags.EndpointUrl) != 0)
{
AddExtraField(fields, nameof(DataSetFieldContentFlags.EndpointUrl));
}
if ((dataSetFieldContentMask & DataSetFieldContentFlags.ApplicationUri) != 0)
{
AddExtraField(fields, nameof(DataSetFieldContentFlags.ApplicationUri));
}

return new PublishedDataSetMetaDataModel
{
DataSetMetaData =
Expand All @@ -383,6 +399,18 @@ await monitoredItem.GetMetaDataAsync(session, typeSystem,
MinorVersion =
minorVersion
};

static void AddExtraField(List<PublishedFieldMetaDataModel> fields,
string name)
{
fields.Add(new PublishedFieldMetaDataModel
{
Name = name,
DataType = "String",
ValueRank = ValueRanks.Scalar,
BuiltInType = (byte)BuiltInType.String
});
}
}

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -160,9 +160,8 @@ void WritePayload(JsonEncoderEx jsonEncoder, string? propertyName = null)
{
jsonEncoder.UseReversibleEncoding = useReversibleEncoding;

if ((Payload.DataSetFieldContentMask &
(DataSetFieldContentFlags.EndpointUrl |
DataSetFieldContentFlags.ApplicationUri)) != 0)
if ((Payload.DataSetFieldContentMask & (DataSetFieldContentFlags.EndpointUrl |
DataSetFieldContentFlags.ApplicationUri)) != 0)
{
var extraFields = Enumerable.Empty<KeyValuePair<string, Opc.Ua.DataValue?>>();
if ((Payload.DataSetFieldContentMask & DataSetFieldContentFlags.EndpointUrl) != 0 &&
Expand Down

0 comments on commit 38e2ca0

Please sign in to comment.