Skip to content

Commit 804e953

Browse files
committed
Update to .Net9.0, update NuGets and bug fixes.
1 parent cbfec94 commit 804e953

9 files changed

+65
-51
lines changed

Controllers/DashboardController.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ public IActionResult Display()
108108

109109
if (key.Contains("OPC Foundation"))
110110
{
111-
Environment.SetEnvironmentVariable("TOPIC", "starterkit/#");
111+
Environment.SetEnvironmentVariable("TOPIC", "#");
112112
break;
113113
}
114114

Dockerfile

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
#See https://aka.ms/containerfastmode to understand how Visual Studio uses this Dockerfile to build your images for faster debugging.
22

3-
FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS base
3+
FROM mcr.microsoft.com/dotnet/aspnet:9.0 AS base
44
WORKDIR /app
5-
EXPOSE 80
5+
EXPOSE 8080
66
EXPOSE 443
77

8-
FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build
8+
FROM mcr.microsoft.com/dotnet/sdk:9.0 AS build
99
WORKDIR /src
1010
COPY ["UACloudDashboard.csproj", "."]
1111
RUN dotnet restore "./UACloudDashboard.csproj"

Encoding/JsonDataSetMessage.cs

+10-4
Original file line numberDiff line numberDiff line change
@@ -497,7 +497,13 @@ private DataSet DecodePayloadContent(JsonDecoder jsonDecoder, DataSetReaderDataT
497497
for (int i = 0; i < dataValues.Count; i++)
498498
{
499499
Field dataField = new Field();
500-
dataField.FieldMetaData = dataSetMetaData?.Fields[(int)dataSetMetaData?.Fields.Count - dataValues.Count + i];
500+
501+
int metadataIndex = dataSetMetaData.Fields.Count - dataValues.Count + i;
502+
if ((dataSetMetaData != null) && (metadataIndex > 0) && (metadataIndex < dataSetMetaData.Fields.Count))
503+
{
504+
dataField.FieldMetaData = dataSetMetaData.Fields[metadataIndex];
505+
}
506+
501507
dataField.Value = dataValues[i];
502508

503509
dataFields.Add(dataField);
@@ -601,7 +607,7 @@ private void EncodeField(JsonEncoder encoder, Field field)
601607
// the field value is encoded as a Variant encoded using the reversible OPC UA JSON Data Encoding
602608
// defined in OPC 10000-6.
603609
encoder.ForceNamespaceUri = false;
604-
encoder.WriteVariant(fieldName, valueToEncode, true);
610+
encoder.WriteVariant(fieldName, valueToEncode);
605611
break;
606612

607613
case FieldTypeEncodingMask.RawData:
@@ -610,7 +616,7 @@ private void EncodeField(JsonEncoder encoder, Field field)
610616
// defined in OPC 10000-6
611617
encoder.ForceNamespaceUri = true;
612618

613-
encoder.WriteVariant(fieldName, valueToEncode, false);
619+
encoder.WriteVariant(fieldName, valueToEncode);
614620
break;
615621

616622
case FieldTypeEncodingMask.DataValue:
@@ -646,7 +652,7 @@ private void EncodeField(JsonEncoder encoder, Field field)
646652
// If the DataSetFieldContentMask results in a DataValue representation,
647653
// the field value is a DataValue encoded using the non-reversible OPC UA JSON Data Encoding
648654
encoder.ForceNamespaceUri = true;
649-
encoder.WriteDataValue(fieldName, dataValue, false);
655+
encoder.WriteDataValue(fieldName, dataValue);
650656
break;
651657
}
652658
}

Encoding/JsonNetworkMessage.cs

+4-2
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,8 @@ public override void Decode(IServiceMessageContext context, byte[] message, ILis
265265

266266
using (JsonDecoder jsonDecoder = new JsonDecoder(json, context))
267267
{
268+
jsonDecoder.UpdateNamespaceTable = true;
269+
268270
// 1. decode network message header (PublisherId & DataSetClassId)
269271
DecodeNetworkMessageHeader(jsonDecoder);
270272

@@ -669,12 +671,12 @@ private void DecodeStatus(JsonDecoder jsonDecoder, IList<DataSetReaderDataType>
669671
jsonDecoder.ReadField("Status", out object status);
670672
PubSubState state = (PubSubState)jsonDecoder.ReadEnumerated("Status", typeof(PubSubState));
671673
Field dataField2 = new Field();
672-
dataField2.Value = new DataValue(status.ToString());
674+
dataField2.Value = new DataValue(status?.ToString());
673675
dataField2.FieldMetaData = new FieldMetaData();
674676
dataField2.FieldMetaData.Name = "Status";
675677
dataFields.Add(dataField2);
676678

677-
if ((bool)cyclic)
679+
if ((cyclic != null) && (bool)cyclic)
678680
{
679681
jsonDecoder.ReadField("NextReportTime", out object nextTime);
680682
Field dataField3 = new Field();

Encoding/UadpNetworkMessage.cs

+23-23
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
* Copyright (c) 2005-2021 The OPC Foundation, Inc. All rights reserved.
33
*
44
* OPC Foundation MIT License 1.00
5-
*
5+
*
66
* Permission is hereby granted, free of charge, to any person
77
* obtaining a copy of this software and associated documentation
88
* files (the "Software"), to deal in the Software without
@@ -11,7 +11,7 @@
1111
* copies of the Software, and to permit persons to whom the
1212
* Software is furnished to do so, subject to the following
1313
* conditions:
14-
*
14+
*
1515
* The above copyright notice and this permission notice shall be
1616
* included in all copies or substantial portions of the Software.
1717
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
@@ -65,7 +65,7 @@ public class UadpNetworkMessage : UaNetworkMessage
6565
/// <summary>
6666
/// Create new instance of UadpNetworkMessage
6767
/// </summary>
68-
/// <param name="writerGroupConfiguration">The <see cref="WriterGroupDataType"/> conflagration object that produced this message.</param>
68+
/// <param name="writerGroupConfiguration">The <see cref="WriterGroupDataType"/> conflagration object that produced this message.</param>
6969
/// <param name="uadpDataSetMessages"><see cref="UadpDataSetMessage"/> list as input</param>
7070
public UadpNetworkMessage(WriterGroupDataType writerGroupConfiguration, List<UadpDataSetMessage> uadpDataSetMessages)
7171
: base(writerGroupConfiguration, uadpDataSetMessages?.ConvertAll<UaDataSetMessage>(x => (UaDataSetMessage)x) ?? new List<UaDataSetMessage>())
@@ -114,7 +114,7 @@ public UadpNetworkMessage(UADPNetworkMessageDiscoveryType discoveryType)
114114
#region Properties
115115

116116
/// <summary>
117-
/// NetworkMessageContentMask contains the mask that will be used to check NetworkMessage options selected for usage
117+
/// NetworkMessageContentMask contains the mask that will be used to check NetworkMessage options selected for usage
118118
/// </summary>
119119
public UadpNetworkMessageContentMask NetworkMessageContentMask { get; private set; }
120120

@@ -130,7 +130,7 @@ public UADPNetworkMessageType UADPNetworkMessageType
130130
}
131131

132132
/// <summary>
133-
/// Get the UADP network message discovery type
133+
/// Get the UADP network message discovery type
134134
/// </summary>
135135
public UADPNetworkMessageDiscoveryType UADPDiscoveryType
136136
{
@@ -186,7 +186,7 @@ public object PublisherId
186186
get { return m_publisherId; }
187187
set
188188
{
189-
// Just in case value is a positive signed Integer
189+
// Just in case value is a positive signed Integer
190190
// Try to bring it to an accepted type (will overflow if value doesn't fit)
191191

192192
object adjustedValue = value;
@@ -371,7 +371,7 @@ public override byte[] Encode(IServiceMessageContext messageContext)
371371
/// <param name="stream">The stream to use.</param>
372372
public override void Encode(IServiceMessageContext messageContext, Stream stream)
373373
{
374-
using (BinaryEncoder encoder = new BinaryEncoder(stream, messageContext))
374+
using (BinaryEncoder encoder = new BinaryEncoder(stream, messageContext, false))
375375
{
376376
if (m_uadpNetworkMessageType == UADPNetworkMessageType.DataSetMessage)
377377
{
@@ -409,7 +409,7 @@ public override void Encode(IServiceMessageContext messageContext, Stream stream
409409
}
410410

411411
/// <summary>
412-
/// Decodes the message
412+
/// Decodes the message
413413
/// </summary>
414414
/// <param name="context"></param>
415415
/// <param name="message"></param>
@@ -482,20 +482,20 @@ private void EncodeDataSetNetworkMessageType(BinaryEncoder binaryEncoder)
482482
}
483483

484484
/// <summary>
485-
/// Encodes the NetworkMessage as a DiscoveryResponse of DataSetMetaData Type
485+
/// Encodes the NetworkMessage as a DiscoveryResponse of DataSetMetaData Type
486486
/// </summary>
487487
/// <param name="binaryEncoder"></param>
488488
private void EncodeDataSetMetaData(BinaryEncoder binaryEncoder)
489489
{
490490
binaryEncoder.WriteUInt16("DataSetWriterId", DataSetWriterId);
491-
491+
492492
if (m_metadata == null)
493493
{
494494
Utils.Trace("The UADP DiscoveryResponse DataSetMetaData message cannot be encoded: The MetaData property is missing. Value null will be used.");
495495
}
496496
binaryEncoder.WriteEncodeable("MetaData", m_metadata, typeof(DataSetMetaDataType));
497497

498-
// temporary write StatusCode.Good
498+
// temporary write StatusCode.Good
499499
binaryEncoder.WriteStatusCode("StatusCode", StatusCodes.Good);
500500
}
501501

@@ -647,12 +647,12 @@ private void SetFlagsDiscoveryResponseMetaData()
647647
ExtendedFlags1 = ExtendedFlags1EncodingMask.Security | ExtendedFlags1EncodingMask.ExtendedFlags2;
648648
ExtendedFlags2 = ExtendedFlags2EncodingMask.NetworkMessageWithDiscoveryResponse;
649649

650-
// enable encoding of PublisherId in message header
650+
// enable encoding of PublisherId in message header
651651
NetworkMessageContentMask = UadpNetworkMessageContentMask.PublisherId;
652652
}
653653

654654
/// <summary>
655-
/// Set All flags before encode/decode for a NetworkMessage that contains A DiscoveryRequest
655+
/// Set All flags before encode/decode for a NetworkMessage that contains A DiscoveryRequest
656656
/// </summary>
657657
private void SetFlagsDiscoveryRequest()
658658
{
@@ -671,8 +671,8 @@ private void SetFlagsDiscoveryRequest()
671671

672672

673673
/// <summary>
674-
/// Decode the stream from decoder parameter and produce a Dataset
675-
/// </summary>
674+
/// Decode the stream from decoder parameter and produce a Dataset
675+
/// </summary>
676676
/// <param name="binaryDecoder"></param>
677677
/// <param name="dataSetReaders"></param>
678678
/// <returns></returns>
@@ -763,7 +763,7 @@ If the value is 0 (null), the parameter shall be ignored and all received DataSe
763763
uadpDataSetMessages.Add(new UadpDataSetMessage());
764764
}
765765

766-
// 6.2 Decode payload into DataSets
766+
// 6.2 Decode payload into DataSets
767767
// Restore the encoded fields (into dataset for now) for each possible dataset reader
768768
foreach (UadpDataSetMessage uadpDataSetMessage in uadpDataSetMessages)
769769
{
@@ -807,7 +807,7 @@ If the value is 0 (null), the parameter shall be ignored and all received DataSe
807807
m_uaDataSetMessages.Clear();
808808
m_uaDataSetMessages.AddRange(dataSetMessages);
809809
}
810-
810+
811811
}
812812
catch (Exception ex)
813813
{
@@ -825,7 +825,7 @@ private void DecodeMetaDataMessage(BinaryDecoder binaryDecoder)
825825
DataSetWriterId = binaryDecoder.ReadUInt16("DataSetWriterId");
826826
m_metadata = binaryDecoder.ReadEncodeable("MetaData", typeof(DataSetMetaDataType)) as DataSetMetaDataType;
827827

828-
// temporary write StatusCode.Good
828+
// temporary write StatusCode.Good
829829
StatusCode statusCode = binaryDecoder.ReadStatusCode("StatusCode");
830830
Utils.Trace("DecodeMetaDataMessage returned: " + statusCode.ToString());
831831
}
@@ -975,7 +975,7 @@ private void EncodePromotedFields(BinaryEncoder encoder)
975975
}
976976

977977
/// <summary>
978-
/// Encode security header
978+
/// Encode security header
979979
/// </summary>
980980
/// <param name="encoder"></param>
981981
private void EncodeSecurityHeader(BinaryEncoder encoder)
@@ -1006,7 +1006,7 @@ private void EncodePayload(BinaryEncoder encoder)
10061006
if (DataSetMessages.Count > 1
10071007
&& (NetworkMessageContentMask & UadpNetworkMessageContentMask.PayloadHeader) != 0)
10081008
{
1009-
//skip 2 * dataset count for each dataset payload size
1009+
//skip 2 * dataset count for each dataset payload size
10101010
encoder.Position += 2 * DataSetMessages.Count;
10111011
}
10121012
//encode dataset message payload
@@ -1050,7 +1050,7 @@ private void EncodeSignature(BinaryEncoder encoder)
10501050

10511051
#endregion
10521052

1053-
#region Private Methods - Decoding
1053+
#region Private Methods - Decoding
10541054

10551055
/// <summary>
10561056
/// Encode Network Message Header
@@ -1237,7 +1237,7 @@ private void DecodePayloadSize(BinaryDecoder decoder)
12371237
if (binaryDecoder != null)
12381238
{
12391239
int offset = 0;
1240-
// set start position of dataset message in binary stream
1240+
// set start position of dataset message in binary stream
12411241
foreach (UadpDataSetMessage uadpDataSetMessage in DataSetMessages)
12421242
{
12431243
uadpDataSetMessage.StartPositionInStream = binaryDecoder.Position + offset;
@@ -1247,7 +1247,7 @@ private void DecodePayloadSize(BinaryDecoder decoder)
12471247
}
12481248

12491249
/// <summary>
1250-
/// Decode security header
1250+
/// Decode security header
12511251
/// </summary>
12521252
/// <param name="decoder"></param>
12531253
private void DecodeSecurityHeader(BinaryDecoder decoder)

MQTTSubscriber.cs

+10-10
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@ namespace Opc.Ua.Cloud.Dashboard
33
{
44
using Microsoft.Extensions.Logging;
55
using MQTTnet;
6-
using MQTTnet.Adapter;
7-
using MQTTnet.Client;
6+
using MQTTnet.Exceptions;
87
using MQTTnet.Packets;
98
using MQTTnet.Protocol;
109
using System;
10+
using System.Buffers;
1111
using System.Collections.Generic;
1212
using System.Globalization;
1313
using System.Linq;
@@ -70,13 +70,13 @@ private bool Connect()
7070
}
7171

7272
// create MQTT client
73-
_client = new MqttFactory().CreateMqttClient();
73+
_client = new MqttClientFactory().CreateMqttClient();
7474
_client.ApplicationMessageReceivedAsync += msg => HandleMessageAsync(msg);
7575
var clientOptions = new MqttClientOptionsBuilder()
7676
.WithTcpServer(opt => opt.NoDelay = true)
7777
.WithClientId(Environment.GetEnvironmentVariable("CLIENT_NAME"))
7878
.WithTcpServer(Environment.GetEnvironmentVariable("BROKER_NAME"), int.Parse(Environment.GetEnvironmentVariable("BROKER_PORT")))
79-
.WithTls(new MqttClientOptionsBuilderTlsParameters { UseTls = !string.IsNullOrEmpty(Environment.GetEnvironmentVariable("USE_TLS")) })
79+
.WithTlsOptions(new MqttClientTlsOptions { UseTls = !string.IsNullOrEmpty(Environment.GetEnvironmentVariable("USE_TLS")) })
8080
.WithProtocolVersion(MQTTnet.Formatter.MqttProtocolVersion.V311)
8181
.WithTimeout(TimeSpan.FromSeconds(10))
8282
.WithKeepAlivePeriod(TimeSpan.FromSeconds(100))
@@ -125,14 +125,14 @@ private bool Connect()
125125

126126
return true;
127127
}
128-
catch (MqttConnectingFailedException ex)
128+
catch (MqttCommunicationException ex)
129129
{
130-
_logger.LogError($"Failed to connect with reason {ex.ResultCode} and message: {ex.Message}");
131-
if (ex.Result?.UserProperties != null)
130+
_logger.LogError($"Failed to connect with reason {ex.HResult} and message: {ex.Message}");
131+
if ((ex.Data != null) && (ex.Data.Count > 0))
132132
{
133-
foreach (var prop in ex.Result.UserProperties)
133+
foreach (var prop in ex.Data)
134134
{
135-
_logger.LogError($"{prop.Name}: {prop.Value}");
135+
_logger.LogError($"{prop.ToString()}");
136136
}
137137
}
138138

@@ -173,7 +173,7 @@ private async Task HandleMessageAsync(MqttApplicationMessageReceivedEventArgs ar
173173
{
174174
try
175175
{
176-
_uaMessageProcessor.ProcessMessage(args.ApplicationMessage.PayloadSegment.Array, DateTime.UtcNow, args.ApplicationMessage.ContentType);
176+
_uaMessageProcessor.ProcessMessage(args.ApplicationMessage.Payload.ToArray(), DateTime.UtcNow, args.ApplicationMessage.ContentType);
177177

178178
// send reponse to MQTT broker, if required
179179
if (args.ApplicationMessage.ResponseTopic != null)

UACloudDashboard.csproj

+5-5
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<Project Sdk="Microsoft.NET.Sdk.Web">
22

33
<PropertyGroup>
4-
<TargetFramework>net6.0</TargetFramework>
4+
<TargetFramework>net9.0</TargetFramework>
55
<UserSecretsId>b2d0ab73-8f42-4b3f-9415-ab542610a5f8</UserSecretsId>
66
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
77
<DockerfileContext>.</DockerfileContext>
@@ -16,10 +16,10 @@
1616
</ItemGroup>
1717

1818
<ItemGroup>
19-
<PackageReference Include="Confluent.Kafka" Version="2.1.1" />
20-
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.18.1" />
21-
<PackageReference Include="MQTTnet" Version="4.2.1.781" />
22-
<PackageReference Include="OPCFoundation.NetStandard.Opc.Ua" Version="1.4.371.96" />
19+
<PackageReference Include="Confluent.Kafka" Version="2.8.0" />
20+
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.21.1" />
21+
<PackageReference Include="MQTTnet" Version="5.0.1.1416" />
22+
<PackageReference Include="OPCFoundation.NetStandard.Opc.Ua" Version="1.5.375.443" />
2323
</ItemGroup>
2424

2525
<ItemGroup>

UAPubSubMessageProcessor.cs

+8-2
Original file line numberDiff line numberDiff line change
@@ -242,11 +242,17 @@ private void DecodeMessage(byte[] payload, DateTime receivedTime, UaNetworkMessa
242242
// convert to string
243243
DataValue value = new DataValue(new Variant(field.Value.ToString()), field.Value.StatusCode, field.Value.SourceTimestamp);
244244

245-
flattenedPublishedNodes.Add(telemetryName, value);
245+
if (!flattenedPublishedNodes.ContainsKey(telemetryName))
246+
{
247+
flattenedPublishedNodes.Add(telemetryName, value);
248+
}
246249
}
247250
else
248251
{
249-
flattenedPublishedNodes.Add(telemetryName, field.Value);
252+
if (!flattenedPublishedNodes.ContainsKey(telemetryName))
253+
{
254+
flattenedPublishedNodes.Add(telemetryName, field.Value);
255+
}
250256
}
251257
}
252258
catch (Exception ex)

Views/Dashboard/Graph.cshtml

+1-1
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@
129129
130130
for (var j = 0; j < myChart.data.datasets.length; j++)
131131
{
132-
var value = parseFloat(values[j].replace(',', '.'));
132+
var value = parseFloat(values[j]);
133133
myChart.data.datasets[j].data.push(value);
134134
if (myChart.data.datasets[j].data.length > 100)
135135
{

0 commit comments

Comments
 (0)