From ae22b89de37ea976486d7df4d63da4cf3bce7fa4 Mon Sep 17 00:00:00 2001 From: Tim Marius Joehnk Date: Wed, 22 Feb 2023 15:25:43 +0100 Subject: [PATCH 01/16] added properties for signed numeric datatypes --- .../SparkplugNodeSequentialTest.cs | 13 +- .../SparkplugMessageGeneratorTest.cs | 62 +++++++-- .../Messages/SparkplugMessageGenerator.cs | 2 +- src/SparkplugNet/Core/PayloadConverter.cs | 107 ++++++++++----- .../VersionB/Data/ValueBaseVersionB.cs | 71 +++++++--- .../VersionB/ProtoBuf/ProtobufPayload.cs | 126 ++++++++++++++---- 6 files changed, 286 insertions(+), 95 deletions(-) diff --git a/src/SparkplugNet.IntegrationTests/SparkplugNodeSequentialTest.cs b/src/SparkplugNet.IntegrationTests/SparkplugNodeSequentialTest.cs index ae21be1..d498d2e 100644 --- a/src/SparkplugNet.IntegrationTests/SparkplugNodeSequentialTest.cs +++ b/src/SparkplugNet.IntegrationTests/SparkplugNodeSequentialTest.cs @@ -37,7 +37,6 @@ public class SparkplugNodeSequentialTest /// /// A representing any asynchronous operation. [TestMethod] - [Ignore] public async Task T1TestNodeVersionBConnectBirth() { Log.Logger = new LoggerConfiguration() @@ -75,7 +74,6 @@ public async Task T1TestNodeVersionBConnectBirth() /// /// A representing any asynchronous operation. [TestMethod] - [Ignore] public async Task T2TestNodeVersionBPublishMetrics() { // Publish metrics with changes. @@ -97,7 +95,6 @@ public async Task T2TestNodeVersionBPublishMetrics() /// /// A representing any asynchronous operation. [TestMethod] - [Ignore] public async Task T3TestNodeVersionBStopDisconnect() { // Assert that the node is not null. @@ -125,8 +122,8 @@ private static List GetTestMetrics() var testMetrics = new List { new () { Name = "General/Name", Timestamp = unixNow, ValueCase = (uint)DataType.String, StringValue = "Some Name" }, - new () { Name = "General/Some Int Value", Timestamp = unixNow, ValueCase = (uint)DataType.Int64, LongValue = (ulong)random.Next(0, int.MaxValue) }, - new () { Name = "General/Aggregates/Some Int Value", Timestamp = unixNow, ValueCase = (uint)DataType.Int64, LongValue = (ulong)random.Next(0, int.MaxValue) } + new () { Name = "General/Some Int Value", Timestamp = unixNow, ValueCase = (uint)DataType.Int64, LongValue = random.Next(0, int.MaxValue) }, + new () { Name = "General/Aggregates/Some Int Value", Timestamp = unixNow, ValueCase = (uint)DataType.Int64, LongValue = random.Next(0, int.MaxValue) } }; return testMetrics; @@ -147,7 +144,7 @@ private static void UpdateTestMetrics(ICollection newMetrics) Name = "General/Extra Metric", Timestamp = unixUtcNow, ValueCase = (uint)DataType.Int64, - LongValue = (ulong)random.Next(0, int.MaxValue) + LongValue = random.Next(0, int.MaxValue) }); foreach (var metric in newMetrics) @@ -171,12 +168,12 @@ private static void UpdateTestMetrics(ICollection newMetrics) case (int)DataType.UInt16: case (int)DataType.Int32: case (int)DataType.UInt32: - metric.IntValue = (uint)random.Next(0, int.MaxValue); + metric.IntValue = random.Next(0, int.MaxValue); break; case (int)DataType.Int64: case (int)DataType.UInt64: case (int)DataType.DateTime: - metric.LongValue = (ulong)random.Next(0, int.MaxValue); + metric.LongValue = random.Next(0, int.MaxValue); break; case (int)DataType.Float: metric.FloatValue = random.Next(0, int.MaxValue); diff --git a/src/SparkplugNet.Tests/SparkplugMessageGeneratorTest.cs b/src/SparkplugNet.Tests/SparkplugMessageGeneratorTest.cs index 11ebb00..54c96f5 100644 --- a/src/SparkplugNet.Tests/SparkplugMessageGeneratorTest.cs +++ b/src/SparkplugNet.Tests/SparkplugMessageGeneratorTest.cs @@ -158,7 +158,7 @@ public void TestDeviceBirthMessageNamespaceB() Assert.AreEqual(this.metricsB.First().ValueCase, payloadVersionB.Metrics.ElementAt(0).Datatype); Assert.AreEqual(this.seqMetricB.Name, payloadVersionB.Metrics.ElementAt(1).Name); - Assert.AreEqual(this.seqMetricB.LongValue, payloadVersionB.Metrics.ElementAt(1).LongValue); + Assert.AreEqual(this.seqMetricB.ULongValue, payloadVersionB.Metrics.ElementAt(1).UlongValue); Assert.AreEqual(this.seqMetricB.ValueCase, payloadVersionB.Metrics.ElementAt(1).Datatype); } @@ -206,7 +206,7 @@ public void TestNodeBirthMessageNamespaceB() Assert.AreEqual(this.metricsB.First().ValueCase, payloadVersionB.Metrics.ElementAt(0).Datatype); Assert.AreEqual(this.seqMetricB.Name, payloadVersionB.Metrics.ElementAt(1).Name); - Assert.AreEqual(this.seqMetricB.LongValue, payloadVersionB.Metrics.ElementAt(1).LongValue); + Assert.AreEqual(this.seqMetricB.ULongValue, payloadVersionB.Metrics.ElementAt(1).UlongValue); Assert.AreEqual(this.seqMetricB.ValueCase, payloadVersionB.Metrics.ElementAt(1).Datatype); } @@ -246,7 +246,7 @@ public void TestDeviceDeathMessageNamespaceB() Assert.AreEqual(1, payloadVersionB.Metrics.Count); Assert.AreEqual(this.seqMetricB.Name, payloadVersionB.Metrics.ElementAt(0).Name); - Assert.AreEqual(this.seqMetricB.LongValue, payloadVersionB.Metrics.ElementAt(0).LongValue); + Assert.AreEqual(this.seqMetricB.ULongValue, payloadVersionB.Metrics.ElementAt(0).UlongValue); Assert.AreEqual(this.seqMetricB.ValueCase, payloadVersionB.Metrics.ElementAt(0).Datatype); } @@ -282,7 +282,7 @@ public void TestNodeDeathMessageNamespaceB() Assert.AreEqual(1, payloadVersionB.Metrics.Count); Assert.AreEqual(this.seqMetricB.Name, payloadVersionB.Metrics.ElementAt(0).Name); - Assert.AreEqual(this.seqMetricB.LongValue, payloadVersionB.Metrics.ElementAt(0).LongValue); + Assert.AreEqual(this.seqMetricB.ULongValue, payloadVersionB.Metrics.ElementAt(0).UlongValue); Assert.AreEqual(this.seqMetricB.ValueCase, payloadVersionB.Metrics.ElementAt(0).Datatype); } @@ -293,7 +293,7 @@ public void TestNodeDeathMessageNamespaceB() public void TestDeviceDataMessageNamespaceA() { var dateTime = DateTimeOffset.Now; - var message = this.messageGenerator.GetSparkPlugDeviceDataMessage(SparkplugNamespace.VersionA, "group1", "edge1", "device1", this.metricsA, 0, 1, dateTime,true); + var message = this.messageGenerator.GetSparkPlugDeviceDataMessage(SparkplugNamespace.VersionA, "group1", "edge1", "device1", this.metricsA, 0, 1, dateTime, true); var payloadVersionA = PayloadHelper.Deserialize(message.Payload); Assert.AreEqual("spAv1.0/group1/DDATA/edge1/device1", message.Topic); @@ -317,7 +317,7 @@ public void TestDeviceDataMessageNamespaceA() public void TestDeviceDataMessageNamespaceB() { var dateTime = DateTimeOffset.Now; - var message = this.messageGenerator.GetSparkPlugDeviceDataMessage(SparkplugNamespace.VersionB, "group1", "edge1", "device1", this.metricsB, 0, 1, dateTime,true); + var message = this.messageGenerator.GetSparkPlugDeviceDataMessage(SparkplugNamespace.VersionB, "group1", "edge1", "device1", this.metricsB, 0, 1, dateTime, true); var payloadVersionB = PayloadHelper.Deserialize(message.Payload); Assert.AreEqual("spBv1.0/group1/DDATA/edge1/device1", message.Topic); @@ -330,7 +330,7 @@ public void TestDeviceDataMessageNamespaceB() Assert.AreEqual(this.metricsB.First().ValueCase, payloadVersionB.Metrics.ElementAt(0).Datatype); Assert.AreEqual(this.seqMetricB.Name, payloadVersionB.Metrics.ElementAt(1).Name); - Assert.AreEqual(this.seqMetricB.LongValue, payloadVersionB.Metrics.ElementAt(1).LongValue); + Assert.AreEqual(this.seqMetricB.ULongValue, payloadVersionB.Metrics.ElementAt(1).UlongValue); Assert.AreEqual(this.seqMetricB.ValueCase, payloadVersionB.Metrics.ElementAt(1).Datatype); } @@ -341,7 +341,7 @@ public void TestDeviceDataMessageNamespaceB() public void TestNodeDataMessageNamespaceA() { var dateTime = DateTimeOffset.Now; - var message = this.messageGenerator.GetSparkPlugNodeDataMessage(SparkplugNamespace.VersionA, "group1", "edge1", this.metricsA, 0, 1, dateTime,true); + var message = this.messageGenerator.GetSparkPlugNodeDataMessage(SparkplugNamespace.VersionA, "group1", "edge1", this.metricsA, 0, 1, dateTime, true); var payloadVersionA = PayloadHelper.Deserialize(message.Payload); Assert.AreEqual("spAv1.0/group1/NDATA/edge1", message.Topic); @@ -378,7 +378,7 @@ public void TestNodeDataMessageNamespaceB() Assert.AreEqual(this.metricsB.First().ValueCase, payloadVersionB.Metrics.ElementAt(0).Datatype); Assert.AreEqual(this.seqMetricB.Name, payloadVersionB.Metrics.ElementAt(1).Name); - Assert.AreEqual(this.seqMetricB.LongValue, payloadVersionB.Metrics.ElementAt(1).LongValue); + Assert.AreEqual(this.seqMetricB.ULongValue, payloadVersionB.Metrics.ElementAt(1).UlongValue); Assert.AreEqual(this.seqMetricB.ValueCase, payloadVersionB.Metrics.ElementAt(1).Datatype); } @@ -389,7 +389,7 @@ public void TestNodeDataMessageNamespaceB() public void TestDeviceCommandMessageNamespaceA() { var dateTime = DateTimeOffset.Now; - var message = SparkplugMessageGenerator.GetSparkPlugDeviceCommandMessage(SparkplugNamespace.VersionA, "group1", "edge1", "device1", this.metricsA, 0, 1, dateTime,true); + var message = SparkplugMessageGenerator.GetSparkPlugDeviceCommandMessage(SparkplugNamespace.VersionA, "group1", "edge1", "device1", this.metricsA, 0, 1, dateTime, true); var payloadVersionA = PayloadHelper.Deserialize(message.Payload); Assert.AreEqual("spAv1.0/group1/DCMD/edge1/device1", message.Topic); @@ -426,7 +426,7 @@ public void TestDeviceCommandMessageNamespaceB() Assert.AreEqual(this.metricsB.First().ValueCase, payloadVersionB.Metrics.ElementAt(0).Datatype); Assert.AreEqual(this.seqMetricB.Name, payloadVersionB.Metrics.ElementAt(1).Name); - Assert.AreEqual(this.seqMetricB.LongValue, payloadVersionB.Metrics.ElementAt(1).LongValue); + Assert.AreEqual(this.seqMetricB.ULongValue, payloadVersionB.Metrics.ElementAt(1).UlongValue); Assert.AreEqual(this.seqMetricB.ValueCase, payloadVersionB.Metrics.ElementAt(1).Datatype); } @@ -474,7 +474,45 @@ public void TestNodeCommandMessageNamespaceB() Assert.AreEqual(this.metricsB.First().ValueCase, payloadVersionB.Metrics.ElementAt(0).Datatype); Assert.AreEqual(this.seqMetricB.Name, payloadVersionB.Metrics.ElementAt(1).Name); - Assert.AreEqual(this.seqMetricB.LongValue, payloadVersionB.Metrics.ElementAt(1).LongValue); + Assert.AreEqual(this.seqMetricB.ULongValue, payloadVersionB.Metrics.ElementAt(1).UlongValue); Assert.AreEqual(this.seqMetricB.ValueCase, payloadVersionB.Metrics.ElementAt(1).Datatype); } + + + /// + /// Tests the Sparkplug message generator with a node command message with a version B namespace. + /// + [TestMethod] + public void TestSignedDataTypesConsistency() + { + var dateTime = DateTimeOffset.Now; + List metrics = new() + { + new VersionB.Data.Metric("Int8", VersionB.Data.DataType.Int8, (sbyte)-1), + new VersionB.Data.Metric("Int16", VersionB.Data.DataType.Int16, (short)-1), + new VersionB.Data.Metric("Int32", VersionB.Data.DataType.Int32, -1), + new VersionB.Data.Metric("Int64", VersionB.Data.DataType.Int64, -1L), + }; + + var message = SparkplugMessageGenerator.GetSparkPlugNodeCommandMessage(SparkplugNamespace.VersionB, "group1", "edge1", metrics, 0, 1, dateTime, true); + var payloadVersionB = PayloadHelper.Deserialize(message.Payload); + + Assert.AreEqual("spBv1.0/group1/NCMD/edge1", message.Topic); + Assert.IsNotNull(payloadVersionB); + Assert.AreEqual((ulong)dateTime.ToUnixTimeMilliseconds(), payloadVersionB.Timestamp); + Assert.AreEqual(metrics.Count + 1, payloadVersionB.Metrics.Count); + + VersionB.Data.Metric metric = metrics[0]; + VersionBProtoBufPayload.Metric protobufMetric = payloadVersionB.Metrics[0]; + Assert.AreEqual(metric.IntValue, protobufMetric.IntValue); + metric = metrics[1]; + protobufMetric = payloadVersionB.Metrics[1]; + Assert.AreEqual(metric.IntValue, protobufMetric.IntValue); + metric = metrics[2]; + protobufMetric = payloadVersionB.Metrics[2]; + Assert.AreEqual(metric.IntValue, protobufMetric.IntValue); + metric = metrics[3]; + protobufMetric = payloadVersionB.Metrics[3]; + Assert.AreEqual(metric.LongValue, protobufMetric.LongValue); + } } diff --git a/src/SparkplugNet/Core/Messages/SparkplugMessageGenerator.cs b/src/SparkplugNet/Core/Messages/SparkplugMessageGenerator.cs index d1cef5c..f16d287 100644 --- a/src/SparkplugNet/Core/Messages/SparkplugMessageGenerator.cs +++ b/src/SparkplugNet/Core/Messages/SparkplugMessageGenerator.cs @@ -585,7 +585,7 @@ public static MqttApplicationMessage GetSparkPlugDeviceCommandMessage( new VersionBData.Metric { Name = Constants.SessionNumberMetricName, - LongValue = (ulong)sessionSequenceNumber, + ULongValue = (ulong)sessionSequenceNumber, ValueCase = (uint)VersionBData.DataType.Int64 } }); diff --git a/src/SparkplugNet/Core/PayloadConverter.cs b/src/SparkplugNet/Core/PayloadConverter.cs index f9d9bf8..b648500 100644 --- a/src/SparkplugNet/Core/PayloadConverter.cs +++ b/src/SparkplugNet/Core/PayloadConverter.cs @@ -164,7 +164,9 @@ public static VersionBDataTypeEnum ConvertVersionBDataTypeDataSetValue(VersionBP { VersionBProtoBuf.ProtoBufPayload.DataSet.DataSetValue.ValueOneofCase.None => VersionBDataTypeEnum.Unknown, VersionBProtoBuf.ProtoBufPayload.DataSet.DataSetValue.ValueOneofCase.IntValue => VersionBDataTypeEnum.Int32, + VersionBProtoBuf.ProtoBufPayload.DataSet.DataSetValue.ValueOneofCase.UintValue => VersionBDataTypeEnum.UInt32, VersionBProtoBuf.ProtoBufPayload.DataSet.DataSetValue.ValueOneofCase.LongValue => VersionBDataTypeEnum.Int64, + VersionBProtoBuf.ProtoBufPayload.DataSet.DataSetValue.ValueOneofCase.UlongValue => VersionBDataTypeEnum.UInt64, VersionBProtoBuf.ProtoBufPayload.DataSet.DataSetValue.ValueOneofCase.FloatValue => VersionBDataTypeEnum.Float, VersionBProtoBuf.ProtoBufPayload.DataSet.DataSetValue.ValueOneofCase.DoubleValue => VersionBDataTypeEnum.Double, VersionBProtoBuf.ProtoBufPayload.DataSet.DataSetValue.ValueOneofCase.BooleanValue => VersionBDataTypeEnum.Boolean, @@ -186,15 +188,15 @@ public static VersionBProtoBuf.ProtoBufPayload.DataSet.DataSetValue.ValueOneofCa VersionBDataTypeEnum.Int16 => VersionBProtoBuf.ProtoBufPayload.DataSet.DataSetValue.ValueOneofCase.IntValue, VersionBDataTypeEnum.Int32 => VersionBProtoBuf.ProtoBufPayload.DataSet.DataSetValue.ValueOneofCase.IntValue, VersionBDataTypeEnum.Int64 => VersionBProtoBuf.ProtoBufPayload.DataSet.DataSetValue.ValueOneofCase.LongValue, - VersionBDataTypeEnum.UInt8 => VersionBProtoBuf.ProtoBufPayload.DataSet.DataSetValue.ValueOneofCase.IntValue, - VersionBDataTypeEnum.UInt16 => VersionBProtoBuf.ProtoBufPayload.DataSet.DataSetValue.ValueOneofCase.IntValue, - VersionBDataTypeEnum.UInt32 => VersionBProtoBuf.ProtoBufPayload.DataSet.DataSetValue.ValueOneofCase.IntValue, - VersionBDataTypeEnum.UInt64 => VersionBProtoBuf.ProtoBufPayload.DataSet.DataSetValue.ValueOneofCase.LongValue, + VersionBDataTypeEnum.UInt8 => VersionBProtoBuf.ProtoBufPayload.DataSet.DataSetValue.ValueOneofCase.UintValue, + VersionBDataTypeEnum.UInt16 => VersionBProtoBuf.ProtoBufPayload.DataSet.DataSetValue.ValueOneofCase.UintValue, + VersionBDataTypeEnum.UInt32 => VersionBProtoBuf.ProtoBufPayload.DataSet.DataSetValue.ValueOneofCase.UintValue, + VersionBDataTypeEnum.UInt64 => VersionBProtoBuf.ProtoBufPayload.DataSet.DataSetValue.ValueOneofCase.UlongValue, VersionBDataTypeEnum.Float => VersionBProtoBuf.ProtoBufPayload.DataSet.DataSetValue.ValueOneofCase.FloatValue, VersionBDataTypeEnum.Double => VersionBProtoBuf.ProtoBufPayload.DataSet.DataSetValue.ValueOneofCase.DoubleValue, VersionBDataTypeEnum.Boolean => VersionBProtoBuf.ProtoBufPayload.DataSet.DataSetValue.ValueOneofCase.BooleanValue, VersionBDataTypeEnum.String => VersionBProtoBuf.ProtoBufPayload.DataSet.DataSetValue.ValueOneofCase.StringValue, - VersionBDataTypeEnum.DateTime => VersionBProtoBuf.ProtoBufPayload.DataSet.DataSetValue.ValueOneofCase.LongValue, + VersionBDataTypeEnum.DateTime => VersionBProtoBuf.ProtoBufPayload.DataSet.DataSetValue.ValueOneofCase.UlongValue, VersionBDataTypeEnum.Text => VersionBProtoBuf.ProtoBufPayload.DataSet.DataSetValue.ValueOneofCase.StringValue, VersionBDataTypeEnum.Uuid => VersionBProtoBuf.ProtoBufPayload.DataSet.DataSetValue.ValueOneofCase.StringValue, VersionBDataTypeEnum.DataSet => VersionBProtoBuf.ProtoBufPayload.DataSet.DataSetValue.ValueOneofCase.None, @@ -216,7 +218,9 @@ public static VersionBDataTypeEnum ConvertVersionBDataTypeMetric(VersionBProtoBu { VersionBProtoBuf.ProtoBufPayload.Metric.ValueOneofCase.None => VersionBDataTypeEnum.Unknown, VersionBProtoBuf.ProtoBufPayload.Metric.ValueOneofCase.IntValue => VersionBDataTypeEnum.Int32, + VersionBProtoBuf.ProtoBufPayload.Metric.ValueOneofCase.UintValue => VersionBDataTypeEnum.UInt32, VersionBProtoBuf.ProtoBufPayload.Metric.ValueOneofCase.LongValue => VersionBDataTypeEnum.Int64, + VersionBProtoBuf.ProtoBufPayload.Metric.ValueOneofCase.UlongValue => VersionBDataTypeEnum.UInt64, VersionBProtoBuf.ProtoBufPayload.Metric.ValueOneofCase.FloatValue => VersionBDataTypeEnum.Float, VersionBProtoBuf.ProtoBufPayload.Metric.ValueOneofCase.DoubleValue => VersionBDataTypeEnum.Double, VersionBProtoBuf.ProtoBufPayload.Metric.ValueOneofCase.BooleanValue => VersionBDataTypeEnum.Boolean, @@ -241,15 +245,15 @@ public static VersionBProtoBuf.ProtoBufPayload.Metric.ValueOneofCase ConvertVers VersionBDataTypeEnum.Int16 => VersionBProtoBuf.ProtoBufPayload.Metric.ValueOneofCase.IntValue, VersionBDataTypeEnum.Int32 => VersionBProtoBuf.ProtoBufPayload.Metric.ValueOneofCase.IntValue, VersionBDataTypeEnum.Int64 => VersionBProtoBuf.ProtoBufPayload.Metric.ValueOneofCase.LongValue, - VersionBDataTypeEnum.UInt8 => VersionBProtoBuf.ProtoBufPayload.Metric.ValueOneofCase.IntValue, - VersionBDataTypeEnum.UInt16 => VersionBProtoBuf.ProtoBufPayload.Metric.ValueOneofCase.IntValue, - VersionBDataTypeEnum.UInt32 => VersionBProtoBuf.ProtoBufPayload.Metric.ValueOneofCase.IntValue, - VersionBDataTypeEnum.UInt64 => VersionBProtoBuf.ProtoBufPayload.Metric.ValueOneofCase.LongValue, + VersionBDataTypeEnum.UInt8 => VersionBProtoBuf.ProtoBufPayload.Metric.ValueOneofCase.UintValue, + VersionBDataTypeEnum.UInt16 => VersionBProtoBuf.ProtoBufPayload.Metric.ValueOneofCase.UintValue, + VersionBDataTypeEnum.UInt32 => VersionBProtoBuf.ProtoBufPayload.Metric.ValueOneofCase.UintValue, + VersionBDataTypeEnum.UInt64 => VersionBProtoBuf.ProtoBufPayload.Metric.ValueOneofCase.UlongValue, VersionBDataTypeEnum.Float => VersionBProtoBuf.ProtoBufPayload.Metric.ValueOneofCase.FloatValue, VersionBDataTypeEnum.Double => VersionBProtoBuf.ProtoBufPayload.Metric.ValueOneofCase.DoubleValue, VersionBDataTypeEnum.Boolean => VersionBProtoBuf.ProtoBufPayload.Metric.ValueOneofCase.BooleanValue, VersionBDataTypeEnum.String => VersionBProtoBuf.ProtoBufPayload.Metric.ValueOneofCase.StringValue, - VersionBDataTypeEnum.DateTime => VersionBProtoBuf.ProtoBufPayload.Metric.ValueOneofCase.LongValue, + VersionBDataTypeEnum.DateTime => VersionBProtoBuf.ProtoBufPayload.Metric.ValueOneofCase.UlongValue, VersionBDataTypeEnum.Text => VersionBProtoBuf.ProtoBufPayload.Metric.ValueOneofCase.StringValue, VersionBDataTypeEnum.Uuid => VersionBProtoBuf.ProtoBufPayload.Metric.ValueOneofCase.StringValue, VersionBDataTypeEnum.DataSet => VersionBProtoBuf.ProtoBufPayload.Metric.ValueOneofCase.None, @@ -271,7 +275,9 @@ public static VersionBDataTypeEnum ConvertVersionBDataTypeParameter(VersionBProt { VersionBProtoBuf.ProtoBufPayload.Template.Parameter.ValueOneofCase.None => VersionBDataTypeEnum.Unknown, VersionBProtoBuf.ProtoBufPayload.Template.Parameter.ValueOneofCase.IntValue => VersionBDataTypeEnum.Int32, + VersionBProtoBuf.ProtoBufPayload.Template.Parameter.ValueOneofCase.UintValue => VersionBDataTypeEnum.UInt32, VersionBProtoBuf.ProtoBufPayload.Template.Parameter.ValueOneofCase.LongValue => VersionBDataTypeEnum.Int64, + VersionBProtoBuf.ProtoBufPayload.Template.Parameter.ValueOneofCase.UlongValue => VersionBDataTypeEnum.UInt64, VersionBProtoBuf.ProtoBufPayload.Template.Parameter.ValueOneofCase.FloatValue => VersionBDataTypeEnum.Float, VersionBProtoBuf.ProtoBufPayload.Template.Parameter.ValueOneofCase.DoubleValue => VersionBDataTypeEnum.Double, VersionBProtoBuf.ProtoBufPayload.Template.Parameter.ValueOneofCase.BooleanValue => VersionBDataTypeEnum.Boolean, @@ -293,15 +299,15 @@ public static VersionBProtoBuf.ProtoBufPayload.Template.Parameter.ValueOneofCase VersionBDataTypeEnum.Int16 => VersionBProtoBuf.ProtoBufPayload.Template.Parameter.ValueOneofCase.IntValue, VersionBDataTypeEnum.Int32 => VersionBProtoBuf.ProtoBufPayload.Template.Parameter.ValueOneofCase.IntValue, VersionBDataTypeEnum.Int64 => VersionBProtoBuf.ProtoBufPayload.Template.Parameter.ValueOneofCase.LongValue, - VersionBDataTypeEnum.UInt8 => VersionBProtoBuf.ProtoBufPayload.Template.Parameter.ValueOneofCase.IntValue, - VersionBDataTypeEnum.UInt16 => VersionBProtoBuf.ProtoBufPayload.Template.Parameter.ValueOneofCase.IntValue, - VersionBDataTypeEnum.UInt32 => VersionBProtoBuf.ProtoBufPayload.Template.Parameter.ValueOneofCase.IntValue, - VersionBDataTypeEnum.UInt64 => VersionBProtoBuf.ProtoBufPayload.Template.Parameter.ValueOneofCase.LongValue, + VersionBDataTypeEnum.UInt8 => VersionBProtoBuf.ProtoBufPayload.Template.Parameter.ValueOneofCase.UintValue, + VersionBDataTypeEnum.UInt16 => VersionBProtoBuf.ProtoBufPayload.Template.Parameter.ValueOneofCase.UintValue, + VersionBDataTypeEnum.UInt32 => VersionBProtoBuf.ProtoBufPayload.Template.Parameter.ValueOneofCase.UintValue, + VersionBDataTypeEnum.UInt64 => VersionBProtoBuf.ProtoBufPayload.Template.Parameter.ValueOneofCase.UlongValue, VersionBDataTypeEnum.Float => VersionBProtoBuf.ProtoBufPayload.Template.Parameter.ValueOneofCase.FloatValue, VersionBDataTypeEnum.Double => VersionBProtoBuf.ProtoBufPayload.Template.Parameter.ValueOneofCase.DoubleValue, VersionBDataTypeEnum.Boolean => VersionBProtoBuf.ProtoBufPayload.Template.Parameter.ValueOneofCase.BooleanValue, VersionBDataTypeEnum.String => VersionBProtoBuf.ProtoBufPayload.Template.Parameter.ValueOneofCase.StringValue, - VersionBDataTypeEnum.DateTime => VersionBProtoBuf.ProtoBufPayload.Template.Parameter.ValueOneofCase.LongValue, + VersionBDataTypeEnum.DateTime => VersionBProtoBuf.ProtoBufPayload.Template.Parameter.ValueOneofCase.UlongValue, VersionBDataTypeEnum.Text => VersionBProtoBuf.ProtoBufPayload.Template.Parameter.ValueOneofCase.StringValue, VersionBDataTypeEnum.Uuid => VersionBProtoBuf.ProtoBufPayload.Template.Parameter.ValueOneofCase.StringValue, VersionBDataTypeEnum.DataSet => VersionBProtoBuf.ProtoBufPayload.Template.Parameter.ValueOneofCase.None, @@ -323,7 +329,9 @@ public static VersionBDataTypeEnum ConvertVersionBDataTypePropertyValue(VersionB { VersionBProtoBuf.ProtoBufPayload.PropertyValue.ValueOneofCase.None => VersionBDataTypeEnum.Unknown, VersionBProtoBuf.ProtoBufPayload.PropertyValue.ValueOneofCase.IntValue => VersionBDataTypeEnum.Int32, + VersionBProtoBuf.ProtoBufPayload.PropertyValue.ValueOneofCase.UintValue => VersionBDataTypeEnum.UInt32, VersionBProtoBuf.ProtoBufPayload.PropertyValue.ValueOneofCase.LongValue => VersionBDataTypeEnum.Int64, + VersionBProtoBuf.ProtoBufPayload.PropertyValue.ValueOneofCase.UlongValue => VersionBDataTypeEnum.UInt64, VersionBProtoBuf.ProtoBufPayload.PropertyValue.ValueOneofCase.FloatValue => VersionBDataTypeEnum.Float, VersionBProtoBuf.ProtoBufPayload.PropertyValue.ValueOneofCase.DoubleValue => VersionBDataTypeEnum.Double, VersionBProtoBuf.ProtoBufPayload.PropertyValue.ValueOneofCase.BooleanValue => VersionBDataTypeEnum.Boolean, @@ -345,15 +353,15 @@ public static VersionBProtoBuf.ProtoBufPayload.PropertyValue.ValueOneofCase Conv VersionBDataTypeEnum.Int16 => VersionBProtoBuf.ProtoBufPayload.PropertyValue.ValueOneofCase.IntValue, VersionBDataTypeEnum.Int32 => VersionBProtoBuf.ProtoBufPayload.PropertyValue.ValueOneofCase.IntValue, VersionBDataTypeEnum.Int64 => VersionBProtoBuf.ProtoBufPayload.PropertyValue.ValueOneofCase.LongValue, - VersionBDataTypeEnum.UInt8 => VersionBProtoBuf.ProtoBufPayload.PropertyValue.ValueOneofCase.IntValue, - VersionBDataTypeEnum.UInt16 => VersionBProtoBuf.ProtoBufPayload.PropertyValue.ValueOneofCase.IntValue, - VersionBDataTypeEnum.UInt32 => VersionBProtoBuf.ProtoBufPayload.PropertyValue.ValueOneofCase.IntValue, - VersionBDataTypeEnum.UInt64 => VersionBProtoBuf.ProtoBufPayload.PropertyValue.ValueOneofCase.LongValue, + VersionBDataTypeEnum.UInt8 => VersionBProtoBuf.ProtoBufPayload.PropertyValue.ValueOneofCase.UintValue, + VersionBDataTypeEnum.UInt16 => VersionBProtoBuf.ProtoBufPayload.PropertyValue.ValueOneofCase.UintValue, + VersionBDataTypeEnum.UInt32 => VersionBProtoBuf.ProtoBufPayload.PropertyValue.ValueOneofCase.UintValue, + VersionBDataTypeEnum.UInt64 => VersionBProtoBuf.ProtoBufPayload.PropertyValue.ValueOneofCase.UlongValue, VersionBDataTypeEnum.Float => VersionBProtoBuf.ProtoBufPayload.PropertyValue.ValueOneofCase.FloatValue, VersionBDataTypeEnum.Double => VersionBProtoBuf.ProtoBufPayload.PropertyValue.ValueOneofCase.DoubleValue, VersionBDataTypeEnum.Boolean => VersionBProtoBuf.ProtoBufPayload.PropertyValue.ValueOneofCase.BooleanValue, VersionBDataTypeEnum.String => VersionBProtoBuf.ProtoBufPayload.PropertyValue.ValueOneofCase.StringValue, - VersionBDataTypeEnum.DateTime => VersionBProtoBuf.ProtoBufPayload.PropertyValue.ValueOneofCase.LongValue, + VersionBDataTypeEnum.DateTime => VersionBProtoBuf.ProtoBufPayload.PropertyValue.ValueOneofCase.UlongValue, VersionBDataTypeEnum.Text => VersionBProtoBuf.ProtoBufPayload.PropertyValue.ValueOneofCase.StringValue, VersionBDataTypeEnum.Uuid => VersionBProtoBuf.ProtoBufPayload.PropertyValue.ValueOneofCase.StringValue, VersionBDataTypeEnum.DataSet => VersionBProtoBuf.ProtoBufPayload.PropertyValue.ValueOneofCase.None, @@ -411,7 +419,9 @@ private static VersionBData.DataSetValue ConvertVersionBDataSetValue(VersionBPro }, FloatValue = dataSetValue.FloatValue, IntValue = dataSetValue.IntValue, + UIntValue = dataSetValue.UintValue, LongValue = dataSetValue.LongValue, + ULongValue = dataSetValue.UlongValue, StringValue = dataSetValue.StringValue, DataType = ConvertVersionBDataTypeDataSetValue(dataSetValue.ValueCase) }; @@ -426,18 +436,24 @@ private static VersionBProtoBuf.ProtoBufPayload.DataSet.DataSetValue ConvertVers { VersionBDataTypeEnum.Int8 or VersionBDataTypeEnum.Int16 - or VersionBDataTypeEnum.Int32 - or VersionBDataTypeEnum.UInt8 + or VersionBDataTypeEnum.Int32 => new VersionBProtoBuf.ProtoBufPayload.DataSet.DataSetValue + { + IntValue = dataSetValue.IntValue + }, + VersionBDataTypeEnum.Int64 => new VersionBProtoBuf.ProtoBufPayload.DataSet.DataSetValue + { + LongValue = dataSetValue.LongValue + }, + VersionBDataTypeEnum.UInt8 or VersionBDataTypeEnum.UInt16 or VersionBDataTypeEnum.UInt32 => new VersionBProtoBuf.ProtoBufPayload.DataSet.DataSetValue { - IntValue = dataSetValue.IntValue + UintValue = dataSetValue.UIntValue }, - VersionBDataTypeEnum.Int64 - or VersionBDataTypeEnum.UInt64 + VersionBDataTypeEnum.UInt64 or VersionBDataTypeEnum.DateTime => new VersionBProtoBuf.ProtoBufPayload.DataSet.DataSetValue { - LongValue = dataSetValue.LongValue + UlongValue = dataSetValue.ULongValue }, VersionBDataTypeEnum.Float => new VersionBProtoBuf.ProtoBufPayload.DataSet.DataSetValue { @@ -591,7 +607,9 @@ private static VersionBData.Parameter ConvertVersionBParameter(VersionBProtoBuf. }, FloatValue = parameter.FloatValue, IntValue = parameter.IntValue, + UIntValue = parameter.UintValue, LongValue = parameter.LongValue, + ULongValue = parameter.UlongValue, Name = parameter.Name, StringValue = parameter.StringValue, ValueCase = parameter.Type, @@ -616,15 +634,19 @@ private static VersionBProtoBuf.ProtoBufPayload.Template.Parameter ConvertVersio case VersionBDataTypeEnum.Int8: case VersionBDataTypeEnum.Int16: case VersionBDataTypeEnum.Int32: + pbTplParam.IntValue = parameter.IntValue; + break; + case VersionBDataTypeEnum.Int64: + pbTplParam.LongValue = parameter.LongValue; + break; case VersionBDataTypeEnum.UInt8: case VersionBDataTypeEnum.UInt16: case VersionBDataTypeEnum.UInt32: - pbTplParam.IntValue = parameter.IntValue; + pbTplParam.UintValue = parameter.UIntValue; break; - case VersionBDataTypeEnum.Int64: case VersionBDataTypeEnum.UInt64: case VersionBDataTypeEnum.DateTime: - pbTplParam.LongValue = parameter.LongValue; + pbTplParam.UlongValue = parameter.ULongValue; break; case VersionBDataTypeEnum.Float: pbTplParam.FloatValue = parameter.FloatValue; @@ -679,10 +701,12 @@ private static VersionBData.Metric ConvertVersionBMetric(VersionBProtoBuf.ProtoB } : null, FloatValue = metric.FloatValue, IntValue = metric.IntValue, + UIntValue = metric.UintValue, IsHistorical = metric.IsHistorical, IsNull = metric.IsNull, IsTransient = metric.IsTransient, LongValue = metric.LongValue, + ULongValue = metric.UlongValue, Metadata = ConvertVersionBMetaData(metric.Metadata), Name = metric.Name, Properties = ConvertVersionBPropertySet(metric.Properties), @@ -717,15 +741,19 @@ private static VersionBProtoBuf.ProtoBufPayload.Metric ConvertVersionBMetric(Ver case VersionBDataTypeEnum.Int8: case VersionBDataTypeEnum.Int16: case VersionBDataTypeEnum.Int32: + pbMetric.IntValue = metric.IntValue; + break; + case VersionBDataTypeEnum.Int64: + pbMetric.LongValue = metric.LongValue; + break; case VersionBDataTypeEnum.UInt8: case VersionBDataTypeEnum.UInt16: case VersionBDataTypeEnum.UInt32: - pbMetric.IntValue = metric.IntValue; + pbMetric.UintValue = metric.UIntValue; break; - case VersionBDataTypeEnum.Int64: case VersionBDataTypeEnum.UInt64: case VersionBDataTypeEnum.DateTime: - pbMetric.LongValue = metric.LongValue; + pbMetric.UlongValue = metric.ULongValue; break; case VersionBDataTypeEnum.Float: pbMetric.FloatValue = metric.FloatValue; @@ -848,8 +876,10 @@ private static VersionBData.PropertyValue ConvertVersionBPropertyValue(VersionBP }, FloatValue = propertyValue.FloatValue, IntValue = propertyValue.IntValue, + UIntValue = propertyValue.UintValue, IsNull = propertyValue.IsNull, LongValue = propertyValue.LongValue, + ULongValue = propertyValue.UlongValue, PropertySetValue = ConvertVersionBPropertySet(propertyValue.PropertysetValue), StringValue = propertyValue.StringValue, ValueCase = propertyValue.Type, @@ -871,17 +901,22 @@ private static VersionBProtoBuf.ProtoBufPayload.PropertyValue ConvertVersionBPro switch (propertyValue.DataType) { + case VersionBDataTypeEnum.Int8: case VersionBDataTypeEnum.Int16: case VersionBDataTypeEnum.Int32: + pbPropValue.IntValue = propertyValue.IntValue; + break; + case VersionBDataTypeEnum.Int64: + pbPropValue.LongValue = propertyValue.LongValue; + break; case VersionBDataTypeEnum.UInt8: case VersionBDataTypeEnum.UInt16: case VersionBDataTypeEnum.UInt32: - pbPropValue.IntValue = propertyValue.IntValue; + pbPropValue.UintValue = propertyValue.UIntValue; break; - case VersionBDataTypeEnum.Int64: case VersionBDataTypeEnum.UInt64: case VersionBDataTypeEnum.DateTime: - pbPropValue.LongValue = propertyValue.LongValue; + pbPropValue.UlongValue = propertyValue.ULongValue; break; case VersionBDataTypeEnum.Float: pbPropValue.FloatValue = propertyValue.FloatValue; @@ -916,6 +951,6 @@ private static VersionBProtoBuf.ProtoBufPayload.PropertyValue ConvertVersionBPro break; } - return pbPropValue; + return pbPropValue; } } diff --git a/src/SparkplugNet/VersionB/Data/ValueBaseVersionB.cs b/src/SparkplugNet/VersionB/Data/ValueBaseVersionB.cs index f6a9944..df5450f 100644 --- a/src/SparkplugNet/VersionB/Data/ValueBaseVersionB.cs +++ b/src/SparkplugNet/VersionB/Data/ValueBaseVersionB.cs @@ -8,17 +8,27 @@ public abstract class ValueBaseVersionB : ValueBase /// /// The integer value. /// - private uint? intValue; + private uint? uintValue; + + /// + /// The integer value. + /// + private int? intValue; + + /// + /// The long value. + /// + private long? longValue; /// /// The long value. /// - private ulong? longValue; + private ulong? ulongValue; /// /// Gets or sets the integer value. /// - public virtual uint IntValue + public virtual int IntValue { get => this.intValue ?? default; set @@ -28,10 +38,24 @@ public virtual uint IntValue } } + /// + /// Gets or sets the integer value. + /// + public virtual uint UIntValue + { + get => this.uintValue ?? default; + set + { + this.uintValue = value; + this.DataType = VersionBDataTypeEnum.UInt32; + } + } + + /// /// Gets or sets the long value. /// - public virtual ulong LongValue + public virtual long LongValue { get => this.longValue ?? default; set @@ -41,6 +65,19 @@ public virtual ulong LongValue } } + /// + /// Gets or sets the ulong value. + /// + public virtual ulong ULongValue + { + get => this.ulongValue ?? default; + set + { + this.ulongValue = value; + this.DataType = VersionBDataTypeEnum.UInt64; + } + } + /// /// Gets or sets the float value. /// @@ -111,17 +148,17 @@ public override uint ValueCase { VersionBDataTypeEnum.Int8 => (sbyte)this.IntValue, VersionBDataTypeEnum.Int16 => (short)this.IntValue, - VersionBDataTypeEnum.Int32 => (int)this.IntValue, - VersionBDataTypeEnum.Int64 => (long)this.LongValue, - VersionBDataTypeEnum.UInt8 => (byte)this.IntValue, - VersionBDataTypeEnum.UInt16 => (ushort)this.IntValue, - VersionBDataTypeEnum.UInt32 => this.IntValue, - VersionBDataTypeEnum.UInt64 => this.LongValue, + VersionBDataTypeEnum.Int32 => this.IntValue, + VersionBDataTypeEnum.Int64 => this.LongValue, + VersionBDataTypeEnum.UInt8 => (byte)this.UIntValue, + VersionBDataTypeEnum.UInt16 => (ushort)this.UIntValue, + VersionBDataTypeEnum.UInt32 => this.UIntValue, + VersionBDataTypeEnum.UInt64 => this.ULongValue, VersionBDataTypeEnum.Float => this.FloatValue, VersionBDataTypeEnum.Double => this.DoubleValue, VersionBDataTypeEnum.Boolean => this.BooleanValue, VersionBDataTypeEnum.String => this.StringValue, - VersionBDataTypeEnum.DateTime => DateTimeOffset.FromUnixTimeMilliseconds((long)this.LongValue).DateTime, + VersionBDataTypeEnum.DateTime => DateTimeOffset.FromUnixTimeMilliseconds((long)this.ULongValue).DateTime, VersionBDataTypeEnum.Text => this.StringValue, VersionBDataTypeEnum.Uuid => Guid.Parse(this.StringValue), _ => null, @@ -142,14 +179,18 @@ public override IValue SetValue(VersionBDataTypeEnum dataT case VersionBDataTypeEnum.Int8: case VersionBDataTypeEnum.Int16: case VersionBDataTypeEnum.Int32: + this.IntValue = value.ConvertTo(); + break; + case VersionBDataTypeEnum.Int64: + this.LongValue = value.ConvertTo(); + break; case VersionBDataTypeEnum.UInt8: case VersionBDataTypeEnum.UInt16: case VersionBDataTypeEnum.UInt32: - this.IntValue = value.ConvertTo(); + this.UIntValue = value.ConvertTo(); break; - case VersionBDataTypeEnum.Int64: case VersionBDataTypeEnum.UInt64: - this.LongValue = value.ConvertTo(); + this.ULongValue = value.ConvertTo(); break; case VersionBDataTypeEnum.Float: this.FloatValue = value.ConvertTo(); @@ -166,7 +207,7 @@ public override IValue SetValue(VersionBDataTypeEnum dataT this.StringValue = value.ConvertOrDefaultTo(); break; case VersionBDataTypeEnum.DateTime: - this.LongValue = (ulong)new DateTimeOffset(value.ConvertTo()).ToUnixTimeMilliseconds(); + this.ULongValue = (ulong)new DateTimeOffset(value.ConvertTo()).ToUnixTimeMilliseconds(); break; default: throw new NotImplementedException($"Type {dataType} is not supported yet"); diff --git a/src/SparkplugNet/VersionB/ProtoBuf/ProtobufPayload.cs b/src/SparkplugNet/VersionB/ProtoBuf/ProtobufPayload.cs index a92c12f..83797a6 100644 --- a/src/SparkplugNet/VersionB/ProtoBuf/ProtobufPayload.cs +++ b/src/SparkplugNet/VersionB/ProtoBuf/ProtobufPayload.cs @@ -78,9 +78,9 @@ internal partial class Parameter : global::ProtoBuf.IExtensible public uint Type { get; set; } [global::ProtoBuf.ProtoMember(3, Name = @"int_value")] - public uint IntValue + public int IntValue { - get => __pbn__value.Is(3) ? __pbn__value.UInt32 : default; + get => __pbn__value.Is(3) ? __pbn__value.Int32 : default; set => __pbn__value = new global::ProtoBuf.DiscriminatedUnion64Object(3, value); } public bool ShouldSerializeIntValue() => __pbn__value.Is(3); @@ -89,9 +89,9 @@ public uint IntValue private global::ProtoBuf.DiscriminatedUnion64Object __pbn__value; [global::ProtoBuf.ProtoMember(4, Name = @"long_value")] - public ulong LongValue + public long LongValue { - get => __pbn__value.Is(4) ? __pbn__value.UInt64 : default; + get => __pbn__value.Is(4) ? __pbn__value.Int64 : default; set => __pbn__value = new global::ProtoBuf.DiscriminatedUnion64Object(4, value); } public bool ShouldSerializeLongValue() => __pbn__value.Is(4); @@ -128,7 +128,7 @@ public bool BooleanValue [global::System.ComponentModel.DefaultValue("")] public string StringValue { - get => __pbn__value.Is(8) ? ((string)__pbn__value.Object) : ""; + get => __pbn__value.Is(8) ? ((string)__pbn__value.Object) : string.Empty; set => __pbn__value = new global::ProtoBuf.DiscriminatedUnion64Object(8, value); } public bool ShouldSerializeStringValue() => __pbn__value.Is(8); @@ -143,6 +143,24 @@ public ParameterValueExtension ExtensionValue public bool ShouldSerializeExtensionValue() => __pbn__value.Is(9); public void ResetExtensionValue() => global::ProtoBuf.DiscriminatedUnion64Object.Reset(ref __pbn__value, 9); + [global::ProtoBuf.ProtoMember(10, Name = @"uint_value")] + public uint UintValue + { + get => __pbn__value.Is(10) ? __pbn__value.UInt32 : default; + set => __pbn__value = new global::ProtoBuf.DiscriminatedUnion64Object(10, value); + } + public bool ShouldSerializeUintValue() => __pbn__value.Is(10); + public void ResetUintValue() => global::ProtoBuf.DiscriminatedUnion64Object.Reset(ref __pbn__value, 10); + + [global::ProtoBuf.ProtoMember(11, Name = @"ulong_value")] + public ulong UlongValue + { + get => __pbn__value.Is(11) ? __pbn__value.UInt64 : default; + set => __pbn__value = new global::ProtoBuf.DiscriminatedUnion64Object(11, value); + } + public bool ShouldSerializeUlongValue() => __pbn__value.Is(11); + public void ResetUlongValue() => global::ProtoBuf.DiscriminatedUnion64Object.Reset(ref __pbn__value, 11); + public ValueOneofCase ValueCase => (ValueOneofCase)__pbn__value.Discriminator; public enum ValueOneofCase @@ -155,6 +173,8 @@ public enum ValueOneofCase BooleanValue = 7, StringValue = 8, ExtensionValue = 9, + UintValue = 10, + UlongValue = 11, } [global::ProtoBuf.ProtoContract()] @@ -203,9 +223,9 @@ internal partial class DataSetValue : global::ProtoBuf.IExtensible => global::ProtoBuf.Extensible.GetExtensionObject(ref __pbn__extensionData, createIfMissing); [global::ProtoBuf.ProtoMember(1, Name = @"int_value")] - public uint IntValue + public int IntValue { - get => __pbn__value.Is(1) ? __pbn__value.UInt32 : default; + get => __pbn__value.Is(1) ? __pbn__value.Int32 : default; set => __pbn__value = new global::ProtoBuf.DiscriminatedUnion64Object(1, value); } public bool ShouldSerializeIntValue() => __pbn__value.Is(1); @@ -214,9 +234,9 @@ public uint IntValue private global::ProtoBuf.DiscriminatedUnion64Object __pbn__value; [global::ProtoBuf.ProtoMember(2, Name = @"long_value")] - public ulong LongValue + public long LongValue { - get => __pbn__value.Is(2) ? __pbn__value.UInt64 : default; + get => __pbn__value.Is(2) ? __pbn__value.Int64 : default; set => __pbn__value = new global::ProtoBuf.DiscriminatedUnion64Object(2, value); } public bool ShouldSerializeLongValue() => __pbn__value.Is(2); @@ -268,6 +288,24 @@ public DataSetValueExtension ExtensionValue public bool ShouldSerializeExtensionValue() => __pbn__value.Is(7); public void ResetExtensionValue() => global::ProtoBuf.DiscriminatedUnion64Object.Reset(ref __pbn__value, 7); + [global::ProtoBuf.ProtoMember(8, Name = @"uint_value")] + public uint UintValue + { + get => __pbn__value.Is(8) ? __pbn__value.UInt32 : default; + set => __pbn__value = new global::ProtoBuf.DiscriminatedUnion64Object(8, value); + } + public bool ShouldSerializeUintValue() => __pbn__value.Is(8); + public void ResetUintValue() => global::ProtoBuf.DiscriminatedUnion64Object.Reset(ref __pbn__value, 8); + + [global::ProtoBuf.ProtoMember(9, Name = @"ulong_value")] + public ulong UlongValue + { + get => __pbn__value.Is(9) ? __pbn__value.UInt64 : default; + set => __pbn__value = new global::ProtoBuf.DiscriminatedUnion64Object(9, value); + } + public bool ShouldSerializeUlongValue() => __pbn__value.Is(9); + public void ResetUlongValue() => global::ProtoBuf.DiscriminatedUnion64Object.Reset(ref __pbn__value, 9); + public ValueOneofCase ValueCase => (ValueOneofCase)__pbn__value.Discriminator; public enum ValueOneofCase @@ -280,6 +318,8 @@ public enum ValueOneofCase BooleanValue = 5, StringValue = 6, ExtensionValue = 7, + UintValue = 8, + UlongValue = 9, } [global::ProtoBuf.ProtoContract()] @@ -327,9 +367,9 @@ internal partial class PropertyValue : global::ProtoBuf.IExtensible public bool IsNull { get; set; } [global::ProtoBuf.ProtoMember(3, Name = @"int_value")] - public uint IntValue + public int IntValue { - get => __pbn__value.Is(3) ? __pbn__value.UInt32 : default; + get => __pbn__value.Is(3) ? __pbn__value.Int32 : default; set => __pbn__value = new global::ProtoBuf.DiscriminatedUnion64Object(3, value); } public bool ShouldSerializeIntValue() => __pbn__value.Is(3); @@ -338,9 +378,9 @@ public uint IntValue private global::ProtoBuf.DiscriminatedUnion64Object __pbn__value; [global::ProtoBuf.ProtoMember(4, Name = @"long_value")] - public ulong LongValue + public long LongValue { - get => __pbn__value.Is(4) ? __pbn__value.UInt64 : default; + get => __pbn__value.Is(4) ? __pbn__value.Int64 : default; set => __pbn__value = new global::ProtoBuf.DiscriminatedUnion64Object(4, value); } public bool ShouldSerializeLongValue() => __pbn__value.Is(4); @@ -377,7 +417,7 @@ public bool BooleanValue [global::System.ComponentModel.DefaultValue("")] public string StringValue { - get => __pbn__value.Is(8) ? ((string)__pbn__value.Object) : ""; + get => __pbn__value.Is(8) ? ((string)__pbn__value.Object) : string.Empty; set => __pbn__value = new global::ProtoBuf.DiscriminatedUnion64Object(8, value); } public bool ShouldSerializeStringValue() => __pbn__value.Is(8); @@ -402,7 +442,7 @@ public PropertySetList? PropertysetsValue public void ResetPropertysetsValue() => global::ProtoBuf.DiscriminatedUnion64Object.Reset(ref __pbn__value, 10); [global::ProtoBuf.ProtoMember(11, Name = @"extension_value")] - public PropertyValueExtension ExtensionValue + public PropertyValueExtension? ExtensionValue { get => __pbn__value.Is(11) ? ((PropertyValueExtension)__pbn__value.Object) : new(); set => __pbn__value = new global::ProtoBuf.DiscriminatedUnion64Object(11, value); @@ -410,6 +450,24 @@ public PropertyValueExtension ExtensionValue public bool ShouldSerializeExtensionValue() => __pbn__value.Is(11); public void ResetExtensionValue() => global::ProtoBuf.DiscriminatedUnion64Object.Reset(ref __pbn__value, 11); + [global::ProtoBuf.ProtoMember(12, Name = @"uint_value")] + public uint UintValue + { + get => __pbn__value.Is(12) ? __pbn__value.UInt32 : default; + set => __pbn__value = new global::ProtoBuf.DiscriminatedUnion64Object(12, value); + } + public bool ShouldSerializeUintValue() => __pbn__value.Is(12); + public void ResetUintValue() => global::ProtoBuf.DiscriminatedUnion64Object.Reset(ref __pbn__value, 12); + + [global::ProtoBuf.ProtoMember(13, Name = @"ulong_value")] + public ulong UlongValue + { + get => __pbn__value.Is(13) ? __pbn__value.UInt64 : default; + set => __pbn__value = new global::ProtoBuf.DiscriminatedUnion64Object(13, value); + } + public bool ShouldSerializeUlongValue() => __pbn__value.Is(13); + public void ResetUlongValue() => global::ProtoBuf.DiscriminatedUnion64Object.Reset(ref __pbn__value, 13); + public ValueOneofCase ValueCase => (ValueOneofCase)__pbn__value.Discriminator; public enum ValueOneofCase @@ -424,6 +482,8 @@ public enum ValueOneofCase PropertysetValue = 9, PropertysetsValue = 10, ExtensionValue = 11, + UintValue = 12, + UlongValue = 13, } [global::ProtoBuf.ProtoContract()] @@ -544,15 +604,15 @@ internal partial class Metric : global::ProtoBuf.IExtensible public bool IsNull { get; set; } [global::ProtoBuf.ProtoMember(8, Name = @"metadata")] - public MetaData? Metadata { get; set; } = new(); + public MetaData? Metadata { get; set; } [global::ProtoBuf.ProtoMember(9, Name = @"properties")] - public PropertySet? Properties { get; set; } = new(); + public PropertySet? Properties { get; set; } [global::ProtoBuf.ProtoMember(10, Name = @"int_value")] - public uint IntValue + public int IntValue { - get => __pbn__value.Is(10) ? __pbn__value.UInt32 : default; + get => __pbn__value.Is(10) ? __pbn__value.Int32 : default; set => __pbn__value = new global::ProtoBuf.DiscriminatedUnion64Object(10, value); } public bool ShouldSerializeIntValue() => __pbn__value.Is(10); @@ -561,9 +621,9 @@ public uint IntValue private global::ProtoBuf.DiscriminatedUnion64Object __pbn__value; [global::ProtoBuf.ProtoMember(11, Name = @"long_value")] - public ulong LongValue + public long LongValue { - get => __pbn__value.Is(11) ? __pbn__value.UInt64 : default; + get => __pbn__value.Is(11) ? __pbn__value.Int64 : default; set => __pbn__value = new global::ProtoBuf.DiscriminatedUnion64Object(11, value); } public bool ShouldSerializeLongValue() => __pbn__value.Is(11); @@ -600,7 +660,7 @@ public bool BooleanValue [global::System.ComponentModel.DefaultValue("")] public string StringValue { - get => __pbn__value.Is(15) ? ((string)__pbn__value.Object) : ""; + get => __pbn__value.Is(15) ? ((string)__pbn__value.Object) : string.Empty; set => __pbn__value = new global::ProtoBuf.DiscriminatedUnion64Object(15, value); } public bool ShouldSerializeStringValue() => __pbn__value.Is(15); @@ -616,7 +676,7 @@ public byte[] BytesValue public void ResetBytesValue() => global::ProtoBuf.DiscriminatedUnion64Object.Reset(ref __pbn__value, 16); [global::ProtoBuf.ProtoMember(17, Name = @"dataset_value")] - public DataSet DatasetValue + public DataSet? DatasetValue { get => __pbn__value.Is(17) ? ((DataSet)__pbn__value.Object) : new(); set => __pbn__value = new global::ProtoBuf.DiscriminatedUnion64Object(17, value); @@ -642,6 +702,24 @@ public MetricValueExtension? ExtensionValue public bool ShouldSerializeExtensionValue() => __pbn__value.Is(19); public void ResetExtensionValue() => global::ProtoBuf.DiscriminatedUnion64Object.Reset(ref __pbn__value, 19); + [global::ProtoBuf.ProtoMember(20, Name = @"uint_value")] + public uint UintValue + { + get => __pbn__value.Is(20) ? __pbn__value.UInt32 : default; + set => __pbn__value = new global::ProtoBuf.DiscriminatedUnion64Object(20, value); + } + public bool ShouldSerializeUintValue() => __pbn__value.Is(20); + public void ResetUintValue() => global::ProtoBuf.DiscriminatedUnion64Object.Reset(ref __pbn__value, 20); + + [global::ProtoBuf.ProtoMember(21, Name = @"ulong_value")] + public ulong UlongValue + { + get => __pbn__value.Is(21) ? __pbn__value.UInt64 : default; + set => __pbn__value = new global::ProtoBuf.DiscriminatedUnion64Object(21, value); + } + public bool ShouldSerializeUlongValue() => __pbn__value.Is(21); + public void ResetUlongValue() => global::ProtoBuf.DiscriminatedUnion64Object.Reset(ref __pbn__value, 21); + public ValueOneofCase ValueCase => (ValueOneofCase)__pbn__value.Discriminator; public enum ValueOneofCase @@ -657,6 +735,8 @@ public enum ValueOneofCase DatasetValue = 17, TemplateValue = 18, ExtensionValue = 19, + UintValue = 20, + UlongValue = 21, } [global::ProtoBuf.ProtoContract()] From 72b4666a930b37dd32266411ead52664467dea75 Mon Sep 17 00:00:00 2001 From: Tim Marius Joehnk Date: Wed, 22 Feb 2023 16:40:05 +0100 Subject: [PATCH 02/16] Readded ignore attributes to integration tests --- .../SparkplugNodeSequentialTest.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/SparkplugNet.IntegrationTests/SparkplugNodeSequentialTest.cs b/src/SparkplugNet.IntegrationTests/SparkplugNodeSequentialTest.cs index d498d2e..1119e13 100644 --- a/src/SparkplugNet.IntegrationTests/SparkplugNodeSequentialTest.cs +++ b/src/SparkplugNet.IntegrationTests/SparkplugNodeSequentialTest.cs @@ -37,6 +37,7 @@ public class SparkplugNodeSequentialTest /// /// A representing any asynchronous operation. [TestMethod] + [Ignore] public async Task T1TestNodeVersionBConnectBirth() { Log.Logger = new LoggerConfiguration() @@ -74,6 +75,7 @@ public async Task T1TestNodeVersionBConnectBirth() /// /// A representing any asynchronous operation. [TestMethod] + [Ignore] public async Task T2TestNodeVersionBPublishMetrics() { // Publish metrics with changes. @@ -95,6 +97,7 @@ public async Task T2TestNodeVersionBPublishMetrics() /// /// A representing any asynchronous operation. [TestMethod] + [Ignore] public async Task T3TestNodeVersionBStopDisconnect() { // Assert that the node is not null. From 3267c46b72a28d29ca4d5e7fecbcbc1a8c5ae810 Mon Sep 17 00:00:00 2001 From: Tim Marius Joehnk Date: Wed, 22 Feb 2023 17:19:41 +0100 Subject: [PATCH 03/16] added missing changes in SparkplugB.proto --- doc/SparkplugB.proto | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/doc/SparkplugB.proto b/doc/SparkplugB.proto index 3cd5ef9..95059ed 100644 --- a/doc/SparkplugB.proto +++ b/doc/SparkplugB.proto @@ -22,9 +22,9 @@ package org.eclipse.tahu.protobuf; option java_package = "org.eclipse.tahu.protobuf"; option java_outer_classname = "SparkplugBProto"; +option csharp_namespace = "SparkplugNet.VersionBProtoBuf"; - -message Payload { +message ProtoBufPayload { /* // Indexes of Data Types // Unknown placeholder for future expansion. @@ -62,13 +62,15 @@ message Payload { uint32 type = 2; oneof value { - uint32 int_value = 3; - uint64 long_value = 4; + int32 int_value = 3; + int64 long_value = 4; float float_value = 5; double double_value = 6; bool boolean_value = 7; string string_value = 8; ParameterValueExtension extension_value = 9; + uint32 uint_value = 10; + uint64 ulong_value = 11; } message ParameterValueExtension { @@ -89,13 +91,15 @@ message Payload { message DataSetValue { oneof value { - uint32 int_value = 1; - uint64 long_value = 2; + int32 int_value = 1; + int64 long_value = 2; float float_value = 3; double double_value = 4; bool boolean_value = 5; string string_value = 6; DataSetValueExtension extension_value = 7; + uint32 uint_value = 8; + uint64 ulong_value = 9; } message DataSetValueExtension { @@ -121,8 +125,8 @@ message Payload { bool is_null = 2; oneof value { - uint32 int_value = 3; - uint64 long_value = 4; + int32 int_value = 3; + int64 long_value = 4; float float_value = 5; double double_value = 6; bool boolean_value = 7; @@ -130,6 +134,8 @@ message Payload { PropertySet propertyset_value = 9; PropertySetList propertysets_value = 10; // List of Property Values PropertyValueExtension extension_value = 11; + uint32 uint_value = 12; + uint64 ulong_value = 13; } message PropertyValueExtension { @@ -180,8 +186,8 @@ message Payload { PropertySet properties = 9; oneof value { - uint32 int_value = 10; - uint64 long_value = 11; + int32 int_value = 10; + int64 long_value = 11; float float_value = 12; double double_value = 13; bool boolean_value = 14; @@ -190,6 +196,8 @@ message Payload { DataSet dataset_value = 17; Template template_value = 18; MetricValueExtension extension_value = 19; + uint32 uint_value = 20; + uint64 ulong_value = 21; } message MetricValueExtension { From cb7304d4306939b28ca9205a3788d9143839e5f1 Mon Sep 17 00:00:00 2001 From: SeppPenner Date: Fri, 7 Apr 2023 19:23:29 +0200 Subject: [PATCH 04/16] Updated protobuf-net. --- src/SparkplugNet/SparkplugNet.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/SparkplugNet/SparkplugNet.csproj b/src/SparkplugNet/SparkplugNet.csproj index e1fc6cf..847ccdc 100644 --- a/src/SparkplugNet/SparkplugNet.csproj +++ b/src/SparkplugNet/SparkplugNet.csproj @@ -37,7 +37,7 @@ runtime; build; native; contentfiles; analyzers; buildtransitive - + From e4df5e49ca98d1727aadec614b12af40feee601d Mon Sep 17 00:00:00 2001 From: SeppPenner Date: Sat, 8 Apr 2023 18:03:36 +0200 Subject: [PATCH 05/16] Removed Version A payload types as they're deprecated. --- src/SparkplugNet.Examples/GlobalUsings.cs | 1 - src/SparkplugNet.Examples/Program.cs | 315 +------------ src/SparkplugNet.Tests/GlobalUsings.cs | 1 - .../SparkplugMessageGeneratorTest.cs | 229 ---------- .../SparkplugPayloadConverterTest.cs | 40 -- .../Core/Enumerations/SparkplugNamespace.cs | 6 - .../Messages/SparkplugMessageGenerator.cs | 430 ------------------ src/SparkplugNet/Core/PayloadConverter.cs | 108 ----- src/SparkplugNet/Core/SparkplugBase.cs | 6 +- .../Core/Topics/SparkplugTopic.cs | 9 - src/SparkplugNet/GlobalUsings.cs | 2 - src/SparkplugNet/VersionA/Data/DataType.cs | 51 --- src/SparkplugNet/VersionA/Data/KuraMetric.cs | 41 -- .../VersionA/Data/KuraPosition.cs | 124 ----- src/SparkplugNet/VersionA/Data/Payload.cs | 45 -- .../VersionA/Data/ValueBaseVersionA.cs | 176 ------- .../VersionA/ProtoBuf/ProtoBufPayload.cs | 242 ---------- .../VersionA/SparkplugApplication.cs | 240 ---------- src/SparkplugNet/VersionA/SparkplugNode.cs | 130 ------ .../VersionB/SparkplugApplication.cs | 2 +- 20 files changed, 5 insertions(+), 2193 deletions(-) delete mode 100644 src/SparkplugNet/VersionA/Data/DataType.cs delete mode 100644 src/SparkplugNet/VersionA/Data/KuraMetric.cs delete mode 100644 src/SparkplugNet/VersionA/Data/KuraPosition.cs delete mode 100644 src/SparkplugNet/VersionA/Data/Payload.cs delete mode 100644 src/SparkplugNet/VersionA/Data/ValueBaseVersionA.cs delete mode 100644 src/SparkplugNet/VersionA/ProtoBuf/ProtoBufPayload.cs delete mode 100644 src/SparkplugNet/VersionA/SparkplugApplication.cs delete mode 100644 src/SparkplugNet/VersionA/SparkplugNode.cs diff --git a/src/SparkplugNet.Examples/GlobalUsings.cs b/src/SparkplugNet.Examples/GlobalUsings.cs index ed9305f..9fef49f 100644 --- a/src/SparkplugNet.Examples/GlobalUsings.cs +++ b/src/SparkplugNet.Examples/GlobalUsings.cs @@ -4,6 +4,5 @@ global using SparkplugNet.Core.Application; global using SparkplugNet.Core.Node; -global using VersionAData = SparkplugNet.VersionA.Data; global using VersionBData = SparkplugNet.VersionB.Data; #pragma warning restore IDE0065 // Die using-Anweisung wurde falsch platziert. \ No newline at end of file diff --git a/src/SparkplugNet.Examples/Program.cs b/src/SparkplugNet.Examples/Program.cs index 57e96ff..3db88ed 100644 --- a/src/SparkplugNet.Examples/Program.cs +++ b/src/SparkplugNet.Examples/Program.cs @@ -20,52 +20,7 @@ public class Program private static readonly CancellationTokenSource CancellationTokenSource = new(); /// - /// The version A metrics for an application. - /// - private static readonly List VersionAMetricsApplication = new() - { - new () - { - Name = "temperatureApplication", DataType = VersionAData.DataType.Double, DoubleValue = 1.20 - }, - new () - { - Name = "climateactiveApplication", DataType = VersionAData.DataType.Boolean, BooleanValue = true - } - }; - - /// - /// The version A metrics for a node. - /// - private static readonly List VersionAMetricsNode = new() - { - new () - { - Name = "temperatureNode", DataType = VersionAData.DataType.Double, DoubleValue = 1.20 - }, - new () - { - Name = "climateactiveNode", DataType = VersionAData.DataType.Boolean, BooleanValue = true - } - }; - - /// - /// The version A metrics for a device. - /// - private static readonly List VersionAMetricsDevice = new() - { - new () - { - Name = "temperatureDevice", DataType = VersionAData.DataType.Double, DoubleValue = 1.20 - }, - new () - { - Name = "climateactiveDevice", DataType = VersionAData.DataType.Boolean, BooleanValue = true - } - }; - - /// - /// The version A metrics for an application. + /// The version B metrics for an application. /// private static readonly List VersionBMetricsApplication = new() { @@ -81,7 +36,7 @@ public class Program }; /// - /// The version A metrics for a node. + /// The version B metrics for a node. /// private static readonly List VersionBMetricsNode = new() { @@ -97,7 +52,7 @@ public class Program }; /// - /// The version A metrics for a device. + /// The version B metrics for a device. /// private static readonly List VersionBMetricsDevice = new() { @@ -124,7 +79,6 @@ public static async Task Main() .WriteTo.Console() .CreateLogger(); - // await RunVersionA(); await RunVersionB(); Log.Information("Simulation is done."); @@ -139,16 +93,6 @@ public static async Task Main() } } - /// - /// Runs a version A simulation. - /// - /// A representing any asynchronous operation. - private static async Task RunVersionA() - { - await RunVersionAApplication(); - await RunVersionANode(); - } - /// /// Runs a version B simulation. /// @@ -159,117 +103,6 @@ private static async Task RunVersionB() await RunVersionBNode(); } - /// - /// Runs the version A application. - /// - /// A representing any asynchronous operation. - private static async Task RunVersionAApplication() - { - var application = new VersionA.SparkplugApplication(VersionAMetricsApplication, Log.Logger); - var applicationOptions = new SparkplugApplicationOptions("localhost", 1883, nameof(RunVersionAApplication), "user", "password", false, "scada1", TimeSpan.FromSeconds(30), true, null, null, CancellationTokenSource.Token); - - // Start an application. - Log.Information("Starting application..."); - await application.Start(applicationOptions); - Log.Information("Application started..."); - - // Handles the application's connected and disconnected events. - application.ConnectedAsync += OnApplicationVersionAConnected; - application.DisconnectedAsync += OnApplicationVersionADisconnected; - - // Handles the application's device related events. - application.DeviceBirthReceivedAsync += OnApplicationVersionADeviceBirthReceived; - application.DeviceDataReceivedAsync += OnApplicationVersionADeviceDataReceived; - application.DeviceDeathReceivedAsync += OnApplicationVersionADeviceDeathReceived; - - // Handles the application's node related events. - application.NodeBirthReceivedAsync += OnApplicationVersionANodeBirthReceived; - application.NodeDataReceivedAsync += OnApplicationVersionANodeDataReceived; - application.NodeDeathReceivedAsync += OnApplicationVersionANodeDeathReceived; - - // Publish node commands. - Log.Information("Publishing a node command ..."); - await application.PublishNodeCommand(VersionAMetricsApplication, "group1", "edge1"); - - // Publish device commands. - Log.Information("Publishing a device command ..."); - await application.PublishDeviceCommand(VersionAMetricsApplication, "group1", "edge1", "device1"); - - // Get the known metrics from an application. - var currentlyKnownMetrics = application.KnownMetrics; - - // Get the device states from an application. - var currentDeviceStates = application.DeviceStates; - - // Get the node states from an application. - var currentNodeStates = application.NodeStates; - - // Check whether an application is connected. - var isApplicationConnected = application.IsConnected; - - // Stopping an application. - await application.Stop(); - Log.Information("Application stopped..."); - } - - /// - /// Runs the version A node. - /// - /// A representing any asynchronous operation. - private static async Task RunVersionANode() - { - var node = new VersionA.SparkplugNode(VersionAMetricsNode, Log.Logger); - var nodeOptions = new SparkplugNodeOptions("localhost", 1883, "node 1", "user", "password", false, "scada1A", "group1", "node1", TimeSpan.FromSeconds(30), null, null, CancellationTokenSource.Token); - - // Start a node. - Log.Information("Starting node..."); - await node.Start(nodeOptions); - Log.Information("Node started..."); - - // Publish node metrics. - await node.PublishMetrics(VersionAMetricsNode); - - // Get the known node metrics from a node. - var currentlyKnownMetrics = node.KnownMetrics; - - // Check whether a node is connected. - var isApplicationConnected = node.IsConnected; - - // Handles the node's connected and disconnected events. - node.ConnectedAsync += OnVersionANodeConnected; - node.DisconnectedAsync += OnVersionANodeDisconnected; - - // Handles the node's device related events. - node.DeviceBirthPublishingAsync += OnVersionANodeDeviceBirthPublishing; - node.DeviceCommandReceivedAsync += OnVersionANodeDeviceCommandReceived; - node.DeviceDeathPublishingAsync += OnVersionANodeDeviceDeathPublishing; - - // Handles the node's node command received event. - node.NodeCommandReceivedAsync += OnVersionANodeNodeCommandReceived; - - // Handles the node's status message received event. - node.StatusMessageReceivedAsync += OnVersionANodeStatusMessageReceived; - - // Get the known devices. - var knownDevices = node.KnownDevices; - - // Handling devices. - const string DeviceIdentifier = "device1"; - - // Publish a device birth message. - await node.PublishDeviceBirthMessage(VersionAMetricsDevice, DeviceIdentifier); - - // Publish a device data message. - await node.PublishDeviceData(VersionAMetricsDevice, DeviceIdentifier); - - // Publish a device death message. - await node.PublishDeviceDeathMessage(DeviceIdentifier); - - // Stopping a node. - await node.Stop(); - Log.Information("Node stopped..."); - } - /// /// Runs the version B application. /// @@ -381,148 +214,6 @@ private static async Task RunVersionBNode() Log.Information("Node stopped..."); } - #region VersionAEvents - /// - /// Handles the connected callback for version A applications. - /// - private static Task OnApplicationVersionAConnected(Core.SparkplugBase.SparkplugEventArgs arg) - { - // Do something. - return Task.CompletedTask; - } - - /// - /// Handles the disconnected callback for version A applications. - /// - private static Task OnApplicationVersionADisconnected(VersionA.SparkplugApplication.SparkplugEventArgs arg) - { - // Do something. - return Task.CompletedTask; - } - - /// - /// Handles the device birth received callback for version A applications. - /// - private static Task OnApplicationVersionADeviceBirthReceived(Core.SparkplugBase.DeviceBirthEventArgs arg) - { - // Do something. - return Task.CompletedTask; - } - - /// - /// Handles the device data received callback for version A applications. - /// - private static Task OnApplicationVersionADeviceDataReceived(VersionA.SparkplugApplication.DeviceDataEventArgs args) - { - // Do something. - return Task.CompletedTask; - } - - /// - /// Handles the device death received callback for version A applications. - /// - private static Task OnApplicationVersionADeviceDeathReceived(Core.SparkplugBase.DeviceEventArgs arg) - { - // Do something. - return Task.CompletedTask; - } - - /// - /// Handles the node birth received callback for version A applications. - /// - private static Task OnApplicationVersionANodeBirthReceived(Core.SparkplugBase.NodeBirthEventArgs arg) - { - // Do something. - return Task.CompletedTask; - } - - /// - /// Handles the node data received callback for version A applications. - /// - private static Task OnApplicationVersionANodeDataReceived(VersionA.SparkplugApplication.NodeDataEventArgs args) - { - // Do something. - return Task.CompletedTask; - } - - /// - /// Handles the node death received callback for version A applications. - /// - private static Task OnApplicationVersionANodeDeathReceived(Core.SparkplugBase.NodeEventArgs arg) - { - // Do something. - return Task.CompletedTask; - } - - /// - /// Handles the connected callback for version A nodes. - /// - private static Task OnVersionANodeConnected(Core.SparkplugBase.SparkplugEventArgs arg) - { - // Do something. - return Task.CompletedTask; - } - - /// - /// Handles the disconnected callback for version A nodes. - /// - private static Task OnVersionANodeDisconnected(VersionA.SparkplugNode.SparkplugEventArgs arg) - { - // Do something. - return Task.CompletedTask; - } - - /// - /// Handles the device birth callback for version A nodes. - /// - /// The received args. - private static Task OnVersionANodeDeviceBirthPublishing(VersionA.SparkplugNode.DeviceBirthEventArgs args) - { - // Do something. - return Task.CompletedTask; - } - - /// - /// Handles the device command callback for version A nodes. - /// - /// The received args. - private static Task OnVersionANodeDeviceCommandReceived(VersionA.SparkplugNode.NodeCommandEventArgs args) - { - // Do something. - return Task.CompletedTask; - } - - /// - /// Handles the device death callback for version A nodes. - /// - /// The received args. - private static Task OnVersionANodeDeviceDeathPublishing(VersionA.SparkplugNode.DeviceEventArgs args) - { - // Do something. - return Task.CompletedTask; - } - - /// - /// Handles the node command callback for version A nodes. - /// - /// The received args. - private static Task OnVersionANodeNodeCommandReceived(VersionA.SparkplugNode.NodeCommandEventArgs args) - { - // Do something. - return Task.CompletedTask; - } - - /// - /// Handles the status message callback for version A nodes. - /// - /// The status. - private static Task OnVersionANodeStatusMessageReceived(VersionA.SparkplugNode.StatusMessageEventArgs args) - { - // Do something. - return Task.CompletedTask; - } - #endregion - #region VersionBEvents /// /// Handles the connected callback for version B applications. diff --git a/src/SparkplugNet.Tests/GlobalUsings.cs b/src/SparkplugNet.Tests/GlobalUsings.cs index fb38e8c..ecfb7fd 100644 --- a/src/SparkplugNet.Tests/GlobalUsings.cs +++ b/src/SparkplugNet.Tests/GlobalUsings.cs @@ -9,6 +9,5 @@ global using SparkplugNet.Core.Enumerations; global using SparkplugNet.Core.Messages; -global using VersionAProtoBufPayload = SparkplugNet.VersionA.ProtoBuf.ProtoBufPayload; global using VersionBProtoBufPayload = SparkplugNet.VersionB.ProtoBuf.ProtoBufPayload; #pragma warning restore IDE0065 // Die using-Anweisung wurde falsch platziert. \ No newline at end of file diff --git a/src/SparkplugNet.Tests/SparkplugMessageGeneratorTest.cs b/src/SparkplugNet.Tests/SparkplugMessageGeneratorTest.cs index 11ebb00..c494fe1 100644 --- a/src/SparkplugNet.Tests/SparkplugMessageGeneratorTest.cs +++ b/src/SparkplugNet.Tests/SparkplugMessageGeneratorTest.cs @@ -15,19 +15,6 @@ namespace SparkplugNet.Tests; [TestClass] public class SparkplugMessageGeneratorTest { - /// - /// The metrics for namespace A. - /// - private readonly List metricsA = new() - { - new VersionA.Data.KuraMetric - { - Name = "Test", - BooleanValue = true, - DataType = VersionA.Data.DataType.Boolean - } - }; - /// /// The metrics for namespace B. /// @@ -41,16 +28,6 @@ public class SparkplugMessageGeneratorTest } }; - /// - /// The SEQ metric for namespace A. - /// - private readonly VersionA.Data.KuraMetric seqMetricA = new() - { - Name = Constants.SessionNumberMetricName, - LongValue = 1, - DataType = VersionA.Data.DataType.Int64 - }; - /// /// The SEQ metric for namespace B. /// @@ -66,30 +43,6 @@ public class SparkplugMessageGeneratorTest /// private readonly SparkplugMessageGenerator messageGenerator = new(new LoggerConfiguration().WriteTo.Console().CreateLogger()); - /// - /// Tests the Sparkplug message generator with a message with a version A namespace and a online state. - /// - [TestMethod] - public void TestStateMessageNamespaceAOnline() - { - var message = SparkplugMessageGenerator.GetSparkplugStateMessage(SparkplugNamespace.VersionA, "scada1", true); - - Assert.AreEqual("STATE/scada1", message.Topic); - Assert.AreEqual("ONLINE", message.ConvertPayloadToString()); - } - - /// - /// Tests the Sparkplug message generator with a message with a version A namespace and a offline state. - /// - [TestMethod] - public void TestStateMessageNamespaceAOffline() - { - var message = SparkplugMessageGenerator.GetSparkplugStateMessage(SparkplugNamespace.VersionA, "scada1", false); - - Assert.AreEqual("STATE/scada1", message.Topic); - Assert.AreEqual("OFFLINE", message.ConvertPayloadToString()); - } - /// /// Tests the Sparkplug message generator with a message with a version B namespace and a online state. /// @@ -114,30 +67,6 @@ public void TestStateMessageNamespaceBOffline() Assert.AreEqual("OFFLINE", message.ConvertPayloadToString()); } - /// - /// Tests the Sparkplug message generator with a device birth message with a version A namespace. - /// - [TestMethod] - public void TestDeviceBirthMessageNamespaceA() - { - var dateTime = DateTimeOffset.Now; - var message = this.messageGenerator.GetSparkPlugDeviceBirthMessage(SparkplugNamespace.VersionA, "group1", "edge1", "device1", this.metricsA, 0, 1, dateTime); - var payloadVersionA = PayloadHelper.Deserialize(message.Payload); - - Assert.AreEqual("spAv1.0/group1/DBIRTH/edge1/device1", message.Topic); - Assert.IsNotNull(payloadVersionA); - Assert.AreEqual(dateTime.ToUnixTimeMilliseconds(), payloadVersionA.Timestamp); - Assert.AreEqual(2, payloadVersionA.Metrics.Count); - - Assert.AreEqual(this.metricsA.First().Name, payloadVersionA.Metrics.ElementAt(0).Name); - Assert.AreEqual(this.metricsA.First().BooleanValue, payloadVersionA.Metrics.ElementAt(0).BoolValue); - Assert.AreEqual(this.metricsA.First().DataType, PayloadConverter.ConvertVersionADataType(payloadVersionA.Metrics.ElementAt(0).Type)); - - Assert.AreEqual(this.seqMetricA.Name, payloadVersionA.Metrics.ElementAt(1).Name); - Assert.AreEqual(this.seqMetricA.LongValue, payloadVersionA.Metrics.ElementAt(1).LongValue); - Assert.AreEqual(this.seqMetricA.DataType, PayloadConverter.ConvertVersionADataType(payloadVersionA.Metrics.ElementAt(1).Type)); - } - /// /// Tests the Sparkplug message generator with a device birth message with a version B namespace. /// @@ -162,30 +91,6 @@ public void TestDeviceBirthMessageNamespaceB() Assert.AreEqual(this.seqMetricB.ValueCase, payloadVersionB.Metrics.ElementAt(1).Datatype); } - /// - /// Tests the Sparkplug message generator with a node birth message with a version A namespace. - /// - [TestMethod] - public void TestNodeBirthMessageNamespaceA() - { - var dateTime = DateTimeOffset.Now; - var message = this.messageGenerator.GetSparkPlugNodeBirthMessage(SparkplugNamespace.VersionA, "group1", "edge1", this.metricsA, 0, 1, dateTime); - var payloadVersionA = PayloadHelper.Deserialize(message.Payload); - - Assert.AreEqual("spAv1.0/group1/NBIRTH/edge1", message.Topic); - Assert.IsNotNull(payloadVersionA); - Assert.AreEqual(dateTime.ToUnixTimeMilliseconds(), payloadVersionA.Timestamp); - Assert.AreEqual(2, payloadVersionA.Metrics.Count); - - Assert.AreEqual(this.metricsA.First().Name, payloadVersionA.Metrics.ElementAt(0).Name); - Assert.AreEqual(this.metricsA.First().BooleanValue, payloadVersionA.Metrics.ElementAt(0).BoolValue); - Assert.AreEqual(this.metricsA.First().DataType, PayloadConverter.ConvertVersionADataType(payloadVersionA.Metrics.ElementAt(0).Type)); - - Assert.AreEqual(this.seqMetricA.Name, payloadVersionA.Metrics.ElementAt(1).Name); - Assert.AreEqual(this.seqMetricA.LongValue, payloadVersionA.Metrics.ElementAt(1).LongValue); - Assert.AreEqual(this.seqMetricA.DataType, PayloadConverter.ConvertVersionADataType(payloadVersionA.Metrics.ElementAt(1).Type)); - } - /// /// Tests the Sparkplug message generator with a node birth message with a version B namespace. /// @@ -210,26 +115,6 @@ public void TestNodeBirthMessageNamespaceB() Assert.AreEqual(this.seqMetricB.ValueCase, payloadVersionB.Metrics.ElementAt(1).Datatype); } - /// - /// Tests the Sparkplug message generator with a device death message with a version A namespace. - /// - [TestMethod] - public void TestDeviceDeathMessageNamespaceA() - { - var dateTime = DateTimeOffset.Now; - var message = this.messageGenerator.GetSparkPlugDeviceDeathMessage(SparkplugNamespace.VersionA, "group1", "edge1", "device1", 0, 1, dateTime); - var payloadVersionA = PayloadHelper.Deserialize(message.Payload); - - Assert.AreEqual("spAv1.0/group1/DDEATH/edge1/device1", message.Topic); - Assert.IsNotNull(payloadVersionA); - Assert.AreEqual(dateTime.ToUnixTimeMilliseconds(), payloadVersionA.Timestamp); - Assert.AreEqual(1, payloadVersionA.Metrics.Count); - - Assert.AreEqual(this.seqMetricA.Name, payloadVersionA.Metrics.ElementAt(0).Name); - Assert.AreEqual(this.seqMetricA.LongValue, payloadVersionA.Metrics.ElementAt(0).LongValue); - Assert.AreEqual(this.seqMetricA.DataType, PayloadConverter.ConvertVersionADataType(payloadVersionA.Metrics.ElementAt(0).Type)); - } - /// /// Tests the Sparkplug message generator with a device death message with a version B namespace. /// @@ -250,24 +135,6 @@ public void TestDeviceDeathMessageNamespaceB() Assert.AreEqual(this.seqMetricB.ValueCase, payloadVersionB.Metrics.ElementAt(0).Datatype); } - /// - /// Tests the Sparkplug message generator with a node death message with a version A namespace. - /// - [TestMethod] - public void TestNodeDeathMessageNamespaceA() - { - var message = this.messageGenerator.GetSparkPlugNodeDeathMessage(SparkplugNamespace.VersionA, "group1", "edge1", 1); - var payloadVersionA = PayloadHelper.Deserialize(message.Payload); - - Assert.AreEqual("spAv1.0/group1/NDEATH/edge1", message.Topic); - Assert.IsNotNull(payloadVersionA); - Assert.AreEqual(1, payloadVersionA.Metrics.Count); - - Assert.AreEqual(this.seqMetricA.Name, payloadVersionA.Metrics.ElementAt(0).Name); - Assert.AreEqual(this.seqMetricA.LongValue, payloadVersionA.Metrics.ElementAt(0).LongValue); - Assert.AreEqual(this.seqMetricA.DataType, PayloadConverter.ConvertVersionADataType(payloadVersionA.Metrics.ElementAt(0).Type)); - } - /// /// Tests the Sparkplug message generator with a node death message with a version B namespace. /// @@ -286,30 +153,6 @@ public void TestNodeDeathMessageNamespaceB() Assert.AreEqual(this.seqMetricB.ValueCase, payloadVersionB.Metrics.ElementAt(0).Datatype); } - /// - /// Tests the Sparkplug message generator with a device data message with a version A namespace. - /// - [TestMethod] - public void TestDeviceDataMessageNamespaceA() - { - var dateTime = DateTimeOffset.Now; - var message = this.messageGenerator.GetSparkPlugDeviceDataMessage(SparkplugNamespace.VersionA, "group1", "edge1", "device1", this.metricsA, 0, 1, dateTime,true); - var payloadVersionA = PayloadHelper.Deserialize(message.Payload); - - Assert.AreEqual("spAv1.0/group1/DDATA/edge1/device1", message.Topic); - Assert.IsNotNull(payloadVersionA); - Assert.AreEqual(dateTime.ToUnixTimeMilliseconds(), payloadVersionA.Timestamp); - Assert.AreEqual(2, payloadVersionA.Metrics.Count); - - Assert.AreEqual(this.metricsA.First().Name, payloadVersionA.Metrics.ElementAt(0).Name); - Assert.AreEqual(this.metricsA.First().BooleanValue, payloadVersionA.Metrics.ElementAt(0).BoolValue); - Assert.AreEqual(this.metricsA.First().DataType, PayloadConverter.ConvertVersionADataType(payloadVersionA.Metrics.ElementAt(0).Type)); - - Assert.AreEqual(this.seqMetricA.Name, payloadVersionA.Metrics.ElementAt(1).Name); - Assert.AreEqual(this.seqMetricA.LongValue, payloadVersionA.Metrics.ElementAt(1).LongValue); - Assert.AreEqual(this.seqMetricA.DataType, PayloadConverter.ConvertVersionADataType(payloadVersionA.Metrics.ElementAt(1).Type)); - } - /// /// Tests the Sparkplug message generator with a device data message with a version B namespace. /// @@ -334,30 +177,6 @@ public void TestDeviceDataMessageNamespaceB() Assert.AreEqual(this.seqMetricB.ValueCase, payloadVersionB.Metrics.ElementAt(1).Datatype); } - /// - /// Tests the Sparkplug message generator with a node data message with a version A namespace. - /// - [TestMethod] - public void TestNodeDataMessageNamespaceA() - { - var dateTime = DateTimeOffset.Now; - var message = this.messageGenerator.GetSparkPlugNodeDataMessage(SparkplugNamespace.VersionA, "group1", "edge1", this.metricsA, 0, 1, dateTime,true); - var payloadVersionA = PayloadHelper.Deserialize(message.Payload); - - Assert.AreEqual("spAv1.0/group1/NDATA/edge1", message.Topic); - Assert.IsNotNull(payloadVersionA); - Assert.AreEqual(dateTime.ToUnixTimeMilliseconds(), payloadVersionA.Timestamp); - Assert.AreEqual(2, payloadVersionA.Metrics.Count); - - Assert.AreEqual(this.metricsA.First().Name, payloadVersionA.Metrics.ElementAt(0).Name); - Assert.AreEqual(this.metricsA.First().BooleanValue, payloadVersionA.Metrics.ElementAt(0).BoolValue); - Assert.AreEqual(this.metricsA.First().DataType, PayloadConverter.ConvertVersionADataType(payloadVersionA.Metrics.ElementAt(0).Type)); - - Assert.AreEqual(this.seqMetricA.Name, payloadVersionA.Metrics.ElementAt(1).Name); - Assert.AreEqual(this.seqMetricA.LongValue, payloadVersionA.Metrics.ElementAt(1).LongValue); - Assert.AreEqual(this.seqMetricA.DataType, PayloadConverter.ConvertVersionADataType(payloadVersionA.Metrics.ElementAt(1).Type)); - } - /// /// Tests the Sparkplug message generator with a node data message with a version B namespace. /// @@ -382,30 +201,6 @@ public void TestNodeDataMessageNamespaceB() Assert.AreEqual(this.seqMetricB.ValueCase, payloadVersionB.Metrics.ElementAt(1).Datatype); } - /// - /// Tests the Sparkplug message generator with a device command message with a version A namespace. - /// - [TestMethod] - public void TestDeviceCommandMessageNamespaceA() - { - var dateTime = DateTimeOffset.Now; - var message = SparkplugMessageGenerator.GetSparkPlugDeviceCommandMessage(SparkplugNamespace.VersionA, "group1", "edge1", "device1", this.metricsA, 0, 1, dateTime,true); - var payloadVersionA = PayloadHelper.Deserialize(message.Payload); - - Assert.AreEqual("spAv1.0/group1/DCMD/edge1/device1", message.Topic); - Assert.IsNotNull(payloadVersionA); - Assert.AreEqual(dateTime.ToUnixTimeMilliseconds(), payloadVersionA.Timestamp); - Assert.AreEqual(2, payloadVersionA.Metrics.Count); - - Assert.AreEqual(this.metricsA.First().Name, payloadVersionA.Metrics.ElementAt(0).Name); - Assert.AreEqual(this.metricsA.First().BooleanValue, payloadVersionA.Metrics.ElementAt(0).BoolValue); - Assert.AreEqual(this.metricsA.First().DataType, PayloadConverter.ConvertVersionADataType(payloadVersionA.Metrics.ElementAt(0).Type)); - - Assert.AreEqual(this.seqMetricA.Name, payloadVersionA.Metrics.ElementAt(1).Name); - Assert.AreEqual(this.seqMetricA.LongValue, payloadVersionA.Metrics.ElementAt(1).LongValue); - Assert.AreEqual(this.seqMetricA.DataType, PayloadConverter.ConvertVersionADataType(payloadVersionA.Metrics.ElementAt(1).Type)); - } - /// /// Tests the Sparkplug message generator with a device command message with a version B namespace. /// @@ -430,30 +225,6 @@ public void TestDeviceCommandMessageNamespaceB() Assert.AreEqual(this.seqMetricB.ValueCase, payloadVersionB.Metrics.ElementAt(1).Datatype); } - /// - /// Tests the Sparkplug message generator with a node command message with a version A namespace. - /// - [TestMethod] - public void TestNodeCommandMessageNamespaceA() - { - var dateTime = DateTimeOffset.Now; - var message = SparkplugMessageGenerator.GetSparkPlugNodeCommandMessage(SparkplugNamespace.VersionA, "group1", "edge1", this.metricsA, 0, 1, dateTime, true); - var payloadVersionA = PayloadHelper.Deserialize(message.Payload); - - Assert.AreEqual("spAv1.0/group1/NCMD/edge1", message.Topic); - Assert.IsNotNull(payloadVersionA); - Assert.AreEqual(dateTime.ToUnixTimeMilliseconds(), payloadVersionA.Timestamp); - Assert.AreEqual(2, payloadVersionA.Metrics.Count); - - Assert.AreEqual(this.metricsA.First().Name, payloadVersionA.Metrics.ElementAt(0).Name); - Assert.AreEqual(this.metricsA.First().BooleanValue, payloadVersionA.Metrics.ElementAt(0).BoolValue); - Assert.AreEqual(this.metricsA.First().DataType, PayloadConverter.ConvertVersionADataType(payloadVersionA.Metrics.ElementAt(0).Type)); - - Assert.AreEqual(this.seqMetricA.Name, payloadVersionA.Metrics.ElementAt(1).Name); - Assert.AreEqual(this.seqMetricA.LongValue, payloadVersionA.Metrics.ElementAt(1).LongValue); - Assert.AreEqual(this.seqMetricA.DataType, PayloadConverter.ConvertVersionADataType(payloadVersionA.Metrics.ElementAt(1).Type)); - } - /// /// Tests the Sparkplug message generator with a node command message with a version B namespace. /// diff --git a/src/SparkplugNet.Tests/SparkplugPayloadConverterTest.cs b/src/SparkplugNet.Tests/SparkplugPayloadConverterTest.cs index 223d4e4..eacb4bb 100644 --- a/src/SparkplugNet.Tests/SparkplugPayloadConverterTest.cs +++ b/src/SparkplugNet.Tests/SparkplugPayloadConverterTest.cs @@ -15,26 +15,6 @@ namespace SparkplugNet.Tests; [TestClass] public class SparkplugPayloadConverterTest { - /// - /// Tests the Sparkplug payload converter for converting a version A payload from Proto. - /// - [TestMethod] - public void TestConvertVersionAPayloadFromProto() - { - var payload = PayloadConverter.ConvertVersionAPayload(new VersionAProtoBufPayload()); - Assert.IsNotNull(payload); - } - - /// - /// Tests the Sparkplug payload converter for converting a version A payload to Proto. - /// - [TestMethod] - public void TestConvertVersionAPayloadToProto() - { - var payload = PayloadConverter.ConvertVersionAPayload(new VersionA.Data.Payload()); - Assert.IsNotNull(payload); - } - /// /// Tests the Sparkplug payload converter for converting a version B payload from Proto. /// @@ -55,26 +35,6 @@ public void TestConvertVersionBPayloadToProto() Assert.IsNotNull(payload); } - /// - /// Tests the Sparkplug payload converter for converting a version A data type from Proto. - /// - [TestMethod] - public void TestConvertVersionADataTypeFromProto() - { - var payload = PayloadConverter.ConvertVersionADataType(new VersionAProtoBufPayload.KuraMetric.ValueType()); - Assert.IsNotNull(payload); - } - - /// - /// Tests the Sparkplug payload converter for converting a version A data type to Proto. - /// - [TestMethod] - public void TestConvertVersionADataTypeToProto() - { - var payload = PayloadConverter.ConvertVersionADataType(new VersionA.Data.DataType()); - Assert.IsNotNull(payload); - } - /// /// Tests the Sparkplug payload converter for converting a version B data type data set value from Proto. /// diff --git a/src/SparkplugNet/Core/Enumerations/SparkplugNamespace.cs b/src/SparkplugNet/Core/Enumerations/SparkplugNamespace.cs index 0575fa2..7eef16f 100644 --- a/src/SparkplugNet/Core/Enumerations/SparkplugNamespace.cs +++ b/src/SparkplugNet/Core/Enumerations/SparkplugNamespace.cs @@ -14,12 +14,6 @@ namespace SparkplugNet.Core.Enumerations; /// public enum SparkplugNamespace { - /// - /// The version A namespace. - /// - [Description(SparkplugTopic.NamespaceSparkplugA)] - VersionA, - /// /// The version B namespace. /// diff --git a/src/SparkplugNet/Core/Messages/SparkplugMessageGenerator.cs b/src/SparkplugNet/Core/Messages/SparkplugMessageGenerator.cs index d1cef5c..a52efbf 100644 --- a/src/SparkplugNet/Core/Messages/SparkplugMessageGenerator.cs +++ b/src/SparkplugNet/Core/Messages/SparkplugMessageGenerator.cs @@ -49,7 +49,6 @@ public static MqttApplicationMessage GetSparkplugStateMessage( return nameSpace switch { - SparkplugNamespace.VersionA => GetSparkplugStateMessageA(scadaHostIdentifier, online), SparkplugNamespace.VersionB => GetSparkplugStateMessageB(scadaHostIdentifier, online), _ => throw new ArgumentOutOfRangeException(nameof(nameSpace)) }; @@ -91,13 +90,6 @@ public MqttApplicationMessage GetSparkPlugNodeBirthMessage( switch (nameSpace) { - case SparkplugNamespace.VersionA: - { - var newMetrics = metrics as IEnumerable ?? new List(); - return this.GetSparkPlugNodeBirthA(nameSpace, groupIdentifier, edgeNodeIdentifier, - AddSessionNumberToMetrics(newMetrics, sessionNumber), dateTime); - } - case SparkplugNamespace.VersionB: { var newMetrics = metrics as IEnumerable ?? new List(); @@ -153,14 +145,6 @@ public MqttApplicationMessage GetSparkPlugDeviceBirthMessage( switch (nameSpace) { - case SparkplugNamespace.VersionA: - { - var newMetrics = metrics as IEnumerable - ?? new List(); - return this.GetSparkPlugDeviceBirthA(nameSpace, groupIdentifier, edgeNodeIdentifier, deviceIdentifier, - AddSessionNumberToMetrics(newMetrics, sessionNumber), dateTime); - } - case SparkplugNamespace.VersionB: { var newMetrics = metrics as IEnumerable ?? new List(); @@ -202,13 +186,6 @@ public MqttApplicationMessage GetSparkPlugNodeDeathMessage( switch (nameSpace) { - case SparkplugNamespace.VersionA: - { - var metrics = new List(); - return this.GetSparkPlugNodeDeathA(nameSpace, groupIdentifier, edgeNodeIdentifier, - AddSessionNumberToMetrics(metrics, sessionNumber)); - } - case SparkplugNamespace.VersionB: { var metrics = new List(); @@ -260,13 +237,6 @@ public MqttApplicationMessage GetSparkPlugDeviceDeathMessage( switch (nameSpace) { - case SparkplugNamespace.VersionA: - { - var metrics = new List(); - return this.GetSparkPlugDeviceDeathA(nameSpace, groupIdentifier, edgeNodeIdentifier, deviceIdentifier, - AddSessionNumberToMetrics(metrics, sessionNumber), dateTime); - } - case SparkplugNamespace.VersionB: { var metrics = new List(); @@ -317,14 +287,6 @@ public MqttApplicationMessage GetSparkPlugNodeDataMessage( switch (nameSpace) { - case SparkplugNamespace.VersionA: - { - var newMetrics = metrics as IEnumerable - ?? new List(); - return this.GetSparkPlugNodeDataA(nameSpace, groupIdentifier, edgeNodeIdentifier, - AddSessionNumberToMetrics(newMetrics, sessionNumber, !addSessionNumbers), dateTime); - } - case SparkplugNamespace.VersionB: { var newMetrics = metrics as IEnumerable @@ -383,14 +345,6 @@ public MqttApplicationMessage GetSparkPlugDeviceDataMessage( switch (nameSpace) { - case SparkplugNamespace.VersionA: - { - var newMetrics = metrics as IEnumerable - ?? new List(); - return this.GetSparkPlugDeviceDataA(nameSpace, groupIdentifier, edgeNodeIdentifier, deviceIdentifier, - AddSessionNumberToMetrics(newMetrics, sessionNumber, !addSessionNumbers), dateTime); - } - case SparkplugNamespace.VersionB: { var newMetrics = metrics as IEnumerable @@ -442,14 +396,6 @@ public static MqttApplicationMessage GetSparkPlugNodeCommandMessage( switch (nameSpace) { - case SparkplugNamespace.VersionA: - { - var newMetrics = metrics as IEnumerable - ?? new List(); - return GetSparkPlugNodeCommandA(nameSpace, groupIdentifier, edgeNodeIdentifier, - AddSessionNumberToMetrics(newMetrics, sessionNumber, !addSessionNumbers), dateTime); - } - case SparkplugNamespace.VersionB: { var newMetrics = metrics as IEnumerable @@ -508,15 +454,6 @@ public static MqttApplicationMessage GetSparkPlugDeviceCommandMessage( switch (nameSpace) { - case SparkplugNamespace.VersionA: - { - var newMetrics = metrics as IEnumerable - ?? new List(); - newMetrics = AddSessionNumberToMetrics(newMetrics, sessionNumber, !addSessionNumbers); - - return GetSparkPlugDeviceCommandA(nameSpace, groupIdentifier, edgeNodeIdentifier, deviceIdentifier, newMetrics, dateTime); - } - case SparkplugNamespace.VersionB: { var newMetrics = metrics as IEnumerable @@ -532,36 +469,6 @@ public static MqttApplicationMessage GetSparkPlugDeviceCommandMessage( } } - /// Adds the session number to the version A metrics. - /// The metrics. - /// The session sequence number. - /// A value indicating whether the session sequence number will be skipped or not. - /// The metrics. - private static IEnumerable AddSessionNumberToMetrics( - IEnumerable metrics, - long sessionSequenceNumber, - bool skipSessionSequenceNumber = false) - { - // The session sequence number in the message is disabled. - if (skipSessionSequenceNumber) - { - return metrics; - } - else - { - // Add a BDSEQ metric. - return metrics.Concat(new VersionAData.KuraMetric[] - { - new VersionAData.KuraMetric - { - Name = Constants.SessionNumberMetricName, - LongValue = sessionSequenceNumber, - DataType = VersionAData.DataType.Int64 - } - }); - } - } - /// Adds the session number to the version B metrics. /// The metrics. /// The session sequence number. @@ -592,19 +499,6 @@ public static MqttApplicationMessage GetSparkPlugDeviceCommandMessage( } } - /// - /// Gets a STATE message with namespace version A. - /// - /// The SCADA host identifier. - /// A value indicating whether the message sender is online or not. - /// A new STATE . - private static MqttApplicationMessage GetSparkplugStateMessageA(string scadaHostIdentifier, bool online) - { - return new MqttApplicationMessageBuilder() - .WithTopic(SparkplugTopicGenerator.GetSparkplugStateMessageTopic(scadaHostIdentifier)) - .WithPayload(online ? "ONLINE" : "OFFLINE").WithQualityOfServiceLevel(MqttQualityOfServiceLevel.AtLeastOnce).WithRetainFlag().Build(); - } - /// /// Gets a STATE message with namespace version B. /// @@ -618,46 +512,6 @@ private static MqttApplicationMessage GetSparkplugStateMessageB(string scadaHost .WithPayload(online ? "ONLINE" : "OFFLINE").WithQualityOfServiceLevel(MqttQualityOfServiceLevel.AtLeastOnce).WithRetainFlag().Build(); } - /// - /// Gets a NBIRTH message with namespace version A. - /// - /// The namespace. - /// The group identifier. - /// The edge node identifier. - /// The metrics. - /// The date time. - /// A new NBIRTH . - private MqttApplicationMessage GetSparkPlugNodeBirthA( - SparkplugNamespace nameSpace, - string groupIdentifier, - string edgeNodeIdentifier, - IEnumerable metrics, - DateTimeOffset dateTime) - { - var payload = new VersionAData.Payload - { - Metrics = metrics.ToList(), - Timestamp = dateTime.ToUnixTimeMilliseconds() - }; - - // Debug output. - this.logger?.Debug("NBIRTH: VersionADataPayload: {@Payload}", payload); - - var convertedPayload = PayloadConverter.ConvertVersionAPayload(payload); - var serialized = PayloadHelper.Serialize(convertedPayload); - - return new MqttApplicationMessageBuilder() - .WithTopic( - SparkplugTopicGenerator.GetTopic( - nameSpace, - groupIdentifier, - SparkplugMessageType.NodeBirth, - edgeNodeIdentifier, - string.Empty)).WithPayload(serialized) - .WithQualityOfServiceLevel(MqttQualityOfServiceLevel.AtLeastOnce) - .Build(); - } - /// /// Gets a NBIRTH message with namespace version B. /// @@ -702,49 +556,6 @@ private MqttApplicationMessage GetSparkPlugNodeBirthB( .Build(); } - /// - /// Gets a DBIRTH message with namespace version A. - /// - /// The namespace. - /// The group identifier. - /// The edge node identifier. - /// The device identifier. - /// The metrics. - /// The date time. - /// A new DBIRTH . - private MqttApplicationMessage GetSparkPlugDeviceBirthA( - SparkplugNamespace nameSpace, - string groupIdentifier, - string edgeNodeIdentifier, - string deviceIdentifier, - IEnumerable metrics, - DateTimeOffset dateTime) - { - var payload = new VersionAData.Payload - { - Metrics = metrics.ToList(), - Timestamp = dateTime.ToUnixTimeMilliseconds() - }; - - // Debug output. - this.logger?.Debug("DBIRTH: VersionADataPayload: {@Payload}", payload); - - var convertedPayload = PayloadConverter.ConvertVersionAPayload(payload); - var serialized = PayloadHelper.Serialize(convertedPayload); - - return new MqttApplicationMessageBuilder() - .WithTopic( - SparkplugTopicGenerator.GetTopic( - nameSpace, - groupIdentifier, - SparkplugMessageType.DeviceBirth, - edgeNodeIdentifier, - deviceIdentifier)) - .WithPayload(serialized) - .WithQualityOfServiceLevel(MqttQualityOfServiceLevel.AtLeastOnce) - .Build(); - } - /// /// Gets a DBIRTH message with namespace version B. /// @@ -791,44 +602,6 @@ private MqttApplicationMessage GetSparkPlugDeviceBirthB( .Build(); } - /// - /// Gets a NDEATH message with namespace version A. - /// - /// The namespace. - /// The group identifier. - /// The edge node identifier. - /// The metrics. - /// A new NDEATH . - private MqttApplicationMessage GetSparkPlugNodeDeathA( - SparkplugNamespace nameSpace, - string groupIdentifier, - string edgeNodeIdentifier, - IEnumerable metrics) - { - var payload = new VersionAData.Payload - { - Metrics = metrics.ToList() - }; - - // Debug output. - this.logger?.Debug("NDEATH: VersionADataPayload: {@Payload}", payload); - - var convertedPayload = PayloadConverter.ConvertVersionAPayload(payload); - var serialized = PayloadHelper.Serialize(convertedPayload); - - return new MqttApplicationMessageBuilder() - .WithTopic( - SparkplugTopicGenerator.GetTopic( - nameSpace, - groupIdentifier, - SparkplugMessageType.NodeDeath, - edgeNodeIdentifier, - string.Empty)) - .WithPayload(serialized) - .WithQualityOfServiceLevel(MqttQualityOfServiceLevel.AtLeastOnce) - .Build(); - } - /// /// Gets a NDEATH message with namespace version B. /// @@ -867,49 +640,6 @@ private MqttApplicationMessage GetSparkPlugNodeDeathB( .Build(); } - /// - /// Gets a DDEATH message with namespace version A. - /// - /// The namespace. - /// The group identifier. - /// The edge node identifier. - /// The device identifier. - /// The metrics. - /// The date time. - /// A new DDEATH . - private MqttApplicationMessage GetSparkPlugDeviceDeathA( - SparkplugNamespace nameSpace, - string groupIdentifier, - string edgeNodeIdentifier, - string deviceIdentifier, - IEnumerable metrics, - DateTimeOffset dateTime) - { - var payload = new VersionAData.Payload - { - Metrics = metrics.ToList(), - Timestamp = dateTime.ToUnixTimeMilliseconds() - }; - - // Debug output. - this.logger?.Debug("DDEATH: VersionADataPayload: {@Payload}", payload); - - var convertedPayload = PayloadConverter.ConvertVersionAPayload(payload); - var serialized = PayloadHelper.Serialize(convertedPayload); - - return new MqttApplicationMessageBuilder() - .WithTopic( - SparkplugTopicGenerator.GetTopic( - nameSpace, - groupIdentifier, - SparkplugMessageType.DeviceDeath, - edgeNodeIdentifier, - deviceIdentifier)) - .WithPayload(serialized) - .WithQualityOfServiceLevel(MqttQualityOfServiceLevel.AtLeastOnce) - .Build(); - } - /// /// Gets a DDEATH message with namespace version B. /// @@ -956,47 +686,6 @@ private MqttApplicationMessage GetSparkPlugDeviceDeathB( .Build(); } - /// - /// Gets a NDATA message with namespace version A. - /// - /// The namespace. - /// The group identifier. - /// The edge node identifier. - /// The metrics. - /// The date time. - /// A new NDATA . - private MqttApplicationMessage GetSparkPlugNodeDataA( - SparkplugNamespace nameSpace, - string groupIdentifier, - string edgeNodeIdentifier, - IEnumerable metrics, - DateTimeOffset dateTime) - { - var payload = new VersionAData.Payload - { - Metrics = metrics.ToList(), - Timestamp = dateTime.ToUnixTimeMilliseconds() - }; - - // Debug output. - this.logger?.Debug("NDATA: VersionADataPayload: {@Payload}", payload); - - var convertedPayload = PayloadConverter.ConvertVersionAPayload(payload); - var serialized = PayloadHelper.Serialize(convertedPayload); - - return new MqttApplicationMessageBuilder() - .WithTopic( - SparkplugTopicGenerator.GetTopic( - nameSpace, - groupIdentifier, - SparkplugMessageType.NodeData, - edgeNodeIdentifier, - string.Empty)) - .WithPayload(serialized) - .WithQualityOfServiceLevel(MqttQualityOfServiceLevel.AtLeastOnce) - .Build(); - } - /// /// Gets a NDATA message with namespace version B. /// @@ -1041,49 +730,6 @@ private MqttApplicationMessage GetSparkPlugNodeDataB( .Build(); } - /// - /// Gets a DDATA message with namespace version A. - /// - /// The namespace. - /// The group identifier. - /// The edge node identifier. - /// The device identifier. - /// The metrics. - /// The date time. - /// A new DDATA . - private MqttApplicationMessage GetSparkPlugDeviceDataA( - SparkplugNamespace nameSpace, - string groupIdentifier, - string edgeNodeIdentifier, - string deviceIdentifier, - IEnumerable metrics, - DateTimeOffset dateTime) - { - var payload = new VersionAData.Payload - { - Metrics = metrics.ToList(), - Timestamp = dateTime.ToUnixTimeMilliseconds() - }; - - // Debug output. - this.logger?.Debug("DDATA: VersionADataPayload: {@Payload}", payload); - - var convertedPayload = PayloadConverter.ConvertVersionAPayload(payload); - var serialized = PayloadHelper.Serialize(convertedPayload); - - return new MqttApplicationMessageBuilder() - .WithTopic( - SparkplugTopicGenerator.GetTopic( - nameSpace, - groupIdentifier, - SparkplugMessageType.DeviceData, - edgeNodeIdentifier, - deviceIdentifier)) - .WithPayload(serialized) - .WithQualityOfServiceLevel(MqttQualityOfServiceLevel.AtLeastOnce) - .Build(); - } - /// /// Gets a DDATA message with namespace version B. /// @@ -1130,43 +776,6 @@ private MqttApplicationMessage GetSparkPlugDeviceDataB( .Build(); } - /// - /// Gets a NCMD message with namespace version A. - /// - /// The namespace. - /// The group identifier. - /// The edge node identifier. - /// The metrics. - /// The date time. - /// A new NCMD . - private static MqttApplicationMessage GetSparkPlugNodeCommandA( - SparkplugNamespace nameSpace, - string groupIdentifier, - string edgeNodeIdentifier, - IEnumerable metrics, - DateTimeOffset dateTime) - { - var payload = new VersionAData.Payload - { - Metrics = metrics.ToList(), - Timestamp = dateTime.ToUnixTimeMilliseconds() - }; - - var convertedPayload = PayloadConverter.ConvertVersionAPayload(payload); - var serialized = PayloadHelper.Serialize(convertedPayload); - - return new MqttApplicationMessageBuilder() - .WithTopic( - SparkplugTopicGenerator.GetTopic( - nameSpace, - groupIdentifier, - SparkplugMessageType.NodeCommand, - edgeNodeIdentifier, - string.Empty)).WithPayload(serialized) - .WithQualityOfServiceLevel(MqttQualityOfServiceLevel.AtLeastOnce) - .Build(); - } - /// /// Gets a NCMD message with namespace version B. /// @@ -1207,45 +816,6 @@ private static MqttApplicationMessage GetSparkPlugNodeCommandB( .Build(); } - /// - /// Gets a DCMD message with namespace version A. - /// - /// The namespace. - /// The group identifier. - /// The edge node identifier. - /// The device identifier. - /// The metrics. - /// The date time. - /// A new DCMD . - private static MqttApplicationMessage GetSparkPlugDeviceCommandA( - SparkplugNamespace nameSpace, - string groupIdentifier, - string edgeNodeIdentifier, - string deviceIdentifier, - IEnumerable metrics, - DateTimeOffset dateTime) - { - var payload = new VersionAData.Payload - { - Metrics = metrics.ToList(), - Timestamp = dateTime.ToUnixTimeMilliseconds() - }; - - var convertedPayload = PayloadConverter.ConvertVersionAPayload(payload); - var serialized = PayloadHelper.Serialize(convertedPayload); - - return new MqttApplicationMessageBuilder() - .WithTopic( - SparkplugTopicGenerator.GetTopic( - nameSpace, - groupIdentifier, - SparkplugMessageType.DeviceCommand, - edgeNodeIdentifier, - deviceIdentifier)).WithPayload(serialized) - .WithQualityOfServiceLevel(MqttQualityOfServiceLevel.AtLeastOnce) - .Build(); - } - /// /// Gets a DCMD message with namespace version B. /// diff --git a/src/SparkplugNet/Core/PayloadConverter.cs b/src/SparkplugNet/Core/PayloadConverter.cs index f9d9bf8..ad0c02c 100644 --- a/src/SparkplugNet/Core/PayloadConverter.cs +++ b/src/SparkplugNet/Core/PayloadConverter.cs @@ -14,78 +14,6 @@ namespace SparkplugNet.Core; /// internal static class PayloadConverter { - /// - /// Gets the version A payload converted from the ProtoBuf payload. - /// - /// The . - /// The . - public static VersionAData.Payload ConvertVersionAPayload(VersionAProtoBuf.ProtoBufPayload payload) - => new VersionAData.Payload - { - Body = payload.Body, - Metrics = payload.Metrics.Select(m => new VersionAData.KuraMetric - { - Name = m.Name, - DataType = ConvertVersionADataType(m.Type), - BooleanValue = m.BoolValue ?? default, - BytesValue = m.BytesValue ?? Array.Empty(), - DoubleValue = m.DoubleValue ?? default, - FloatValue = m.FloatValue ?? default, - IntValue = m.IntValue ?? default, - LongValue = m.LongValue ?? default, - StringValue = m.StringValue ?? string.Empty - }).ToList(), - Position = new VersionAData.KuraPosition - { - Timestamp = payload.Position?.Timestamp ?? default, - Altitude = payload.Position?.Altitude ?? default, - Heading = payload.Position?.Heading ?? default, - Latitude = payload.Position?.Latitude ?? default, - Longitude = payload.Position?.Longitude ?? default, - Precision = payload.Position?.Precision ?? default, - Satellites = payload.Position?.Satellites ?? default, - Speed = payload.Position?.Speed ?? default, - Status = payload.Position?.Status ?? default - }, - Timestamp = payload.Timestamp - }; - - /// - /// Gets the ProtoBuf payload converted from the version A payload. - /// - /// The . - /// The . - public static VersionAProtoBuf.ProtoBufPayload ConvertVersionAPayload(VersionAData.Payload payload) - => new VersionAProtoBuf.ProtoBufPayload - { - Body = payload.Body, - Metrics = payload.Metrics.Select(m => new VersionAProtoBuf.ProtoBufPayload.KuraMetric - { - Type = ConvertVersionADataType(m.DataType), - BoolValue = m.BooleanValue, - BytesValue = m.BytesValue, - DoubleValue = m.DoubleValue, - FloatValue = m.FloatValue, - IntValue = m.IntValue, - LongValue = m.LongValue, - Name = m.Name, - StringValue = m.StringValue - }).ToList(), - Position = new VersionAProtoBuf.ProtoBufPayload.KuraPosition - { - Timestamp = payload.Position?.Timestamp ?? default, - Altitude = payload.Position?.Altitude ?? default, - Heading = payload.Position?.Heading ?? default, - Latitude = payload.Position?.Latitude ?? default, - Longitude = payload.Position?.Longitude ?? default, - Precision = payload.Position?.Precision ?? default, - Satellites = payload.Position?.Satellites ?? default, - Speed = payload.Position?.Speed ?? default, - Status = payload.Position?.Status ?? default - }, - Timestamp = payload.Timestamp - }; - /// /// Gets the version B payload converted from the ProtoBuf payload. /// @@ -118,42 +46,6 @@ public static VersionBProtoBuf.ProtoBufPayload ConvertVersionBPayload(VersionBDa Uuid = payload.Uuid }; - /// - /// Gets the version A data type from the version A ProtoBuf value type. - /// - /// The . - /// The . - public static VersionAData.DataType ConvertVersionADataType(VersionAProtoBuf.ProtoBufPayload.KuraMetric.ValueType type) - => type switch - { - VersionAProtoBuf.ProtoBufPayload.KuraMetric.ValueType.Bool => VersionAData.DataType.Boolean, - VersionAProtoBuf.ProtoBufPayload.KuraMetric.ValueType.Bytes => VersionAData.DataType.Bytes, - VersionAProtoBuf.ProtoBufPayload.KuraMetric.ValueType.Double => VersionAData.DataType.Double, - VersionAProtoBuf.ProtoBufPayload.KuraMetric.ValueType.Float => VersionAData.DataType.Float, - VersionAProtoBuf.ProtoBufPayload.KuraMetric.ValueType.Int32 => VersionAData.DataType.Int32, - VersionAProtoBuf.ProtoBufPayload.KuraMetric.ValueType.Int64 => VersionAData.DataType.Int64, - VersionAProtoBuf.ProtoBufPayload.KuraMetric.ValueType.String => VersionAData.DataType.String, - _ => VersionAData.DataType.String - }; - - /// - /// Gets the version A ProtoBuf value type from the version A data type. - /// - /// The . - /// The . - public static VersionAProtoBuf.ProtoBufPayload.KuraMetric.ValueType ConvertVersionADataType(VersionAData.DataType type) - => type switch - { - VersionAData.DataType.Boolean => VersionAProtoBuf.ProtoBufPayload.KuraMetric.ValueType.Bool, - VersionAData.DataType.Bytes => VersionAProtoBuf.ProtoBufPayload.KuraMetric.ValueType.Bytes, - VersionAData.DataType.Double => VersionAProtoBuf.ProtoBufPayload.KuraMetric.ValueType.Double, - VersionAData.DataType.Float => VersionAProtoBuf.ProtoBufPayload.KuraMetric.ValueType.Float, - VersionAData.DataType.Int32 => VersionAProtoBuf.ProtoBufPayload.KuraMetric.ValueType.Int32, - VersionAData.DataType.Int64 => VersionAProtoBuf.ProtoBufPayload.KuraMetric.ValueType.Int64, - VersionAData.DataType.String => VersionAProtoBuf.ProtoBufPayload.KuraMetric.ValueType.String, - _ => VersionAProtoBuf.ProtoBufPayload.KuraMetric.ValueType.String - }; - /// /// Gets the version B data type from the version B ProtoBuf value type for data set values. /// diff --git a/src/SparkplugNet/Core/SparkplugBase.cs b/src/SparkplugNet/Core/SparkplugBase.cs index 7500e46..1563972 100644 --- a/src/SparkplugNet/Core/SparkplugBase.cs +++ b/src/SparkplugNet/Core/SparkplugBase.cs @@ -55,11 +55,7 @@ public SparkplugBase(KnownMetricStorage knownMetricsStorage, ILogger? logger = n { this.knownMetrics = knownMetricsStorage; - if (typeof(T).IsAssignableFrom(typeof(VersionAData.KuraMetric))) - { - this.NameSpace = SparkplugNamespace.VersionA; - } - else + if (typeof(T).IsAssignableFrom(typeof(VersionBData.Metric))) { this.NameSpace = SparkplugNamespace.VersionB; } diff --git a/src/SparkplugNet/Core/Topics/SparkplugTopic.cs b/src/SparkplugNet/Core/Topics/SparkplugTopic.cs index 12cd533..0e20156 100644 --- a/src/SparkplugNet/Core/Topics/SparkplugTopic.cs +++ b/src/SparkplugNet/Core/Topics/SparkplugTopic.cs @@ -14,11 +14,6 @@ namespace SparkplugNet.Core.Topics; /// public class SparkplugTopic { - /// - /// The namespace for Sparkplug A. - /// - public const string NamespaceSparkplugA = "spAv1.0"; - /// /// The namespace for Sparkplug B. /// @@ -68,7 +63,6 @@ protected static string GetNamespace(SparkplugNamespace @namespace) { return @namespace switch { - SparkplugNamespace.VersionA => NamespaceSparkplugA, SparkplugNamespace.VersionB => NamespaceSparkplugB, _ => throw new FormatException($"Namespace ${@namespace} is unknown!"), }; @@ -84,9 +78,6 @@ protected static bool TryGetNamespace(string @namespace, out SparkplugNamespace { switch (@namespace) { - case NamespaceSparkplugA: - sparkplugNamespace = SparkplugNamespace.VersionA; - return true; case NamespaceSparkplugB: sparkplugNamespace = SparkplugNamespace.VersionB; return true; diff --git a/src/SparkplugNet/GlobalUsings.cs b/src/SparkplugNet/GlobalUsings.cs index f2f292d..3b18843 100644 --- a/src/SparkplugNet/GlobalUsings.cs +++ b/src/SparkplugNet/GlobalUsings.cs @@ -31,8 +31,6 @@ global using SparkplugNet.Core.Node; global using SparkplugNet.Core.Topics; -global using VersionAData = SparkplugNet.VersionA.Data; -global using VersionAProtoBuf = SparkplugNet.VersionA.ProtoBuf; global using VersionBData = SparkplugNet.VersionB.Data; global using VersionBDataTypeEnum = SparkplugNet.VersionB.Data.DataType; global using VersionBProtoBuf = SparkplugNet.VersionB.ProtoBuf; diff --git a/src/SparkplugNet/VersionA/Data/DataType.cs b/src/SparkplugNet/VersionA/Data/DataType.cs deleted file mode 100644 index 5fba466..0000000 --- a/src/SparkplugNet/VersionA/Data/DataType.cs +++ /dev/null @@ -1,51 +0,0 @@ -// -------------------------------------------------------------------------------------------------------------------- -// -// The project is licensed under the MIT license. -// -// -// The externally used Sparkplug A data type enumeration. -// -// -------------------------------------------------------------------------------------------------------------------- - -namespace SparkplugNet.VersionA.Data; - -/// -/// The externally used Sparkplug A data type enumeration. -/// -public enum DataType -{ - /// - /// The double data type. - /// - Double = 0, - - /// - /// The float data type. - /// - Float = 1, - - /// - /// The 64 bit integer data type. - /// - Int64 = 2, - - /// - /// The 32 bit integer data type. - /// - Int32 = 3, - - /// - /// The boolean data type. - /// - Boolean = 4, - - /// - /// The string data type. - /// - String = 5, - - /// - /// The bytes data type. - /// - Bytes = 6 -} diff --git a/src/SparkplugNet/VersionA/Data/KuraMetric.cs b/src/SparkplugNet/VersionA/Data/KuraMetric.cs deleted file mode 100644 index b00af6a..0000000 --- a/src/SparkplugNet/VersionA/Data/KuraMetric.cs +++ /dev/null @@ -1,41 +0,0 @@ -// -------------------------------------------------------------------------------------------------------------------- -// -// The project is licensed under the MIT license. -// -// -// The externally used Sparkplug A Kura metric class. -// -// -------------------------------------------------------------------------------------------------------------------- - -namespace SparkplugNet.VersionA.Data; - -/// -/// The externally used Sparkplug A Kura metric class. -/// -public class KuraMetric : ValueBaseVersionA, IMetric -{ - /// - /// Gets or sets the name. - /// - [DefaultValue("")] - public virtual string Name { get; set; } = string.Empty; - - /// - /// Initializes a new instance of the class. - /// - public KuraMetric() - { - } - - /// - /// Initializes a new instance of the class. - /// - /// Name of the string. - /// Type of the data. - /// The value. - public KuraMetric(string strName, DataType dataType, object value) - { - this.Name = strName; - this.SetValue(dataType, value); - } -} \ No newline at end of file diff --git a/src/SparkplugNet/VersionA/Data/KuraPosition.cs b/src/SparkplugNet/VersionA/Data/KuraPosition.cs deleted file mode 100644 index 5cdbdb8..0000000 --- a/src/SparkplugNet/VersionA/Data/KuraPosition.cs +++ /dev/null @@ -1,124 +0,0 @@ -// -------------------------------------------------------------------------------------------------------------------- -// -// The project is licensed under the MIT license. -// -// -// The externally used Sparkplug A Kura position class. -// -// -------------------------------------------------------------------------------------------------------------------- - -namespace SparkplugNet.VersionA.Data; - -/// -/// The externally used Sparkplug A Kura position class. -/// -public class KuraPosition -{ - /// - /// The altitude. - /// - private double? altitude; - - /// - /// The precision. - /// - private double? precision; - - /// - /// The heading. - /// - private double? heading; - - /// - /// The speed. - /// - private double? speed; - - /// - /// The timestamp. - /// - private long? timestamp; - - /// - /// The satellites. - /// - private int? satellites; - - /// - /// The status. - /// - private int? status; - - /// - /// Gets or sets the latitude. - /// - public double Latitude { get; set; } - - /// - /// Gets or sets the longitude. - /// - public double Longitude { get; set; } - - /// - /// Gets or sets the altitude. - /// - public double? Altitude - { - get => this.altitude.GetValueOrDefault(); - set => this.altitude = value; - } - - /// - /// Gets or sets the precision. - /// - public double? Precision - { - get => this.precision.GetValueOrDefault(); - set => this.precision = value; - } - - /// - /// Gets or sets the heading. - /// - public double? Heading - { - get => this.heading.GetValueOrDefault(); - set => this.heading = value; - } - - /// - /// Gets or sets the speed. - /// - public double? Speed - { - get => this.speed.GetValueOrDefault(); - set => this.speed = value; - } - - /// - /// Gets or sets the timestamp. - /// - public long? Timestamp - { - get => this.timestamp.GetValueOrDefault(); - set => this.timestamp = value; - } - - /// - /// Gets or sets the satellites. - /// - public int? Satellites - { - get => this.satellites.GetValueOrDefault(); - set => this.satellites = value; - } - - /// - /// Gets or sets the status. - /// - public int? Status - { - get => this.status.GetValueOrDefault(); - set => this.status = value; - } -} diff --git a/src/SparkplugNet/VersionA/Data/Payload.cs b/src/SparkplugNet/VersionA/Data/Payload.cs deleted file mode 100644 index 91a03c0..0000000 --- a/src/SparkplugNet/VersionA/Data/Payload.cs +++ /dev/null @@ -1,45 +0,0 @@ -// -------------------------------------------------------------------------------------------------------------------- -// -// The project is licensed under the MIT license. -// -// -// TThe externally used Sparkplug A payload class. -// -// -------------------------------------------------------------------------------------------------------------------- - -namespace SparkplugNet.VersionA.Data; - -/// -/// The externally used Sparkplug A payload class. -/// -public class Payload -{ - /// - /// The timestamp. - /// - private long? timestamp; - - /// - /// Gets or sets the timestamp. - /// - public long? Timestamp - { - get => this.timestamp.GetValueOrDefault(); - set => this.timestamp = value; - } - - /// - /// Gets or sets the position. - /// - public KuraPosition? Position { get; set; } - - /// - /// Gets or sets the metrics. - /// - public List Metrics { get; set; } = new(); - - /// - /// Gets or sets the body. - /// - public byte[] Body { get; set; } = Array.Empty(); -} diff --git a/src/SparkplugNet/VersionA/Data/ValueBaseVersionA.cs b/src/SparkplugNet/VersionA/Data/ValueBaseVersionA.cs deleted file mode 100644 index 31b00e5..0000000 --- a/src/SparkplugNet/VersionA/Data/ValueBaseVersionA.cs +++ /dev/null @@ -1,176 +0,0 @@ -namespace SparkplugNet.VersionA.Data; - -/// -/// Base class containing values using Sparkplug Version A -/// -public abstract class ValueBaseVersionA : ValueBase -{ - /// - /// The integer value. - /// - private int? intValue; - - /// - /// The long value. - /// - private long? longValue; - - /// - /// The bytes value. - /// - private byte[]? bytesValue; - - /// - /// Gets or sets the integer value. - /// - public virtual int IntValue - { - get => this.intValue ?? default; - set - { - this.intValue = value; - this.DataType = DataType.Int32; - } - } - - /// - /// Gets or sets the long value. - /// - public virtual long LongValue - { - get => this.longValue ?? default; - set - { - this.longValue = value; - this.DataType = DataType.Int64; - } - } - - /// - /// Gets or sets the float value. - /// - public override float FloatValue - { - set - { - base.FloatValue = value; - this.DataType = DataType.Float; - } - } - - /// - /// Gets or sets the double value. - /// - public override double DoubleValue - { - set - { - base.DoubleValue = value; - this.DataType = DataType.Double; - } - } - - /// - /// Gets or sets the boolean value. - /// - public override bool BooleanValue - { - set - { - base.BooleanValue = value; - this.DataType = DataType.Boolean; - } - } - - /// - /// Gets or sets the string value. - /// - [DefaultValue("")] - public override string StringValue - { - set - { - base.StringValue = value; - this.DataType = DataType.String; - } - } - - /// - /// Gets or sets the bytes value. - /// - public virtual byte[] BytesValue - { - get => this.bytesValue ?? Array.Empty(); - set - { - this.bytesValue = value; - this.DataType = DataType.Bytes; - } - } - - /// - /// Gets or sets the Value Case. - /// - public override uint ValueCase - { - get => (uint)this.DataType; - set => this.DataType = (DataType)value; - } - - /// - /// Gets or sets the DataType. - /// - public override DataType DataType { get; set; } = default!; - - /// - /// Gets the value. - /// - public override object? Value => this.DataType switch - { - DataType.Int32 => this.IntValue, - DataType.Int64 => this.LongValue, - DataType.Float => this.FloatValue, - DataType.Double => this.DoubleValue, - DataType.Boolean => this.BooleanValue, - DataType.String => this.StringValue, - DataType.Bytes => this.BytesValue, - _ => null, - }; - - /// - /// Sets the value. - /// - /// Type of the data. - /// The value. - public override IValue SetValue(DataType dataType, object? value) - { - switch (dataType) - { - case DataType.Double: - this.DoubleValue = value.ConvertTo(); - break; - case DataType.Float: - this.FloatValue = value.ConvertTo(); - break; - case DataType.Int64: - this.LongValue = value.ConvertTo(); - break; - case DataType.Int32: - this.IntValue = value.ConvertTo(); - break; - case DataType.Boolean: - this.BooleanValue = value.ConvertTo(); - break; - case DataType.String: - this.StringValue = value.ConvertOrDefaultTo(); - break; - case DataType.Bytes: - this.BytesValue = value.ConvertOrDefaultTo(); - break; - default: - throw new NotImplementedException($"Type {dataType} is not supported yet"); - } - - return this; - } -} \ No newline at end of file diff --git a/src/SparkplugNet/VersionA/ProtoBuf/ProtoBufPayload.cs b/src/SparkplugNet/VersionA/ProtoBuf/ProtoBufPayload.cs deleted file mode 100644 index 4ed94b6..0000000 --- a/src/SparkplugNet/VersionA/ProtoBuf/ProtoBufPayload.cs +++ /dev/null @@ -1,242 +0,0 @@ -// -// This file was generated by a tool; you should avoid making direct changes. -// Consider using 'partial classes' to extend these types -// Input: my.proto -// - -#region Designer generated code -#nullable enable -#pragma warning disable CS0612, CS0618, CS1591, CS3021, IDE0079, IDE1006, RCS1036, RCS1057, RCS1085, RCS1192 -[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("SparkplugNet.Tests")] -namespace SparkplugNet.VersionA.ProtoBuf -{ - [global::ProtoBuf.ProtoContract()] - internal partial class ProtoBufPayload : global::ProtoBuf.IExtensible - { - private global::ProtoBuf.IExtension? __pbn__extensionData; - global::ProtoBuf.IExtension global::ProtoBuf.IExtensible.GetExtensionObject(bool createIfMissing) - => global::ProtoBuf.Extensible.GetExtensionObject(ref __pbn__extensionData, createIfMissing); - - [global::ProtoBuf.ProtoMember(1, Name = @"timestamp")] - public long? Timestamp - { - get => __pbn__Timestamp.GetValueOrDefault(); - set => __pbn__Timestamp = value; - } - public bool ShouldSerializeTimestamp() => __pbn__Timestamp is not null; - public void ResetTimestamp() => __pbn__Timestamp = null; - private long? __pbn__Timestamp; - - [global::ProtoBuf.ProtoMember(2, Name = @"position")] - public KuraPosition? Position { get; set; } - - [global::ProtoBuf.ProtoMember(5000, Name = @"metric")] - public global::System.Collections.Generic.List Metrics { get; set; } = new global::System.Collections.Generic.List(); - - [global::ProtoBuf.ProtoMember(5001, Name = @"body")] - public byte[] Body - { - get => __pbn__Body; - set => __pbn__Body = value; - } - public bool ShouldSerializeBody() => __pbn__Body is not null; - public void ResetBody() => __pbn__Body = Array.Empty(); - private byte[] __pbn__Body = Array.Empty(); - - [global::ProtoBuf.ProtoContract()] - internal partial class KuraMetric : global::ProtoBuf.IExtensible - { - private global::ProtoBuf.IExtension? __pbn__extensionData; - global::ProtoBuf.IExtension global::ProtoBuf.IExtensible.GetExtensionObject(bool createIfMissing) - => global::ProtoBuf.Extensible.GetExtensionObject(ref __pbn__extensionData, createIfMissing); - - [global::ProtoBuf.ProtoMember(1, Name = @"name", IsRequired = true)] - public string Name { get; set; } = string.Empty; - - [global::ProtoBuf.ProtoMember(2, Name = @"type", IsRequired = true)] - public ValueType Type { get; set; } - - [global::ProtoBuf.ProtoMember(3, Name = @"double_value")] - public double? DoubleValue - { - get => __pbn__DoubleValue.GetValueOrDefault(); - set => __pbn__DoubleValue = value; - } - public bool ShouldSerializeDoubleValue() => __pbn__DoubleValue is not null; - public void ResetDoubleValue() => __pbn__DoubleValue = null; - private double? __pbn__DoubleValue; - - [global::ProtoBuf.ProtoMember(4, Name = @"float_value")] - public float? FloatValue - { - get => __pbn__FloatValue.GetValueOrDefault(); - set => __pbn__FloatValue = value; - } - public bool ShouldSerializeFloatValue() => __pbn__FloatValue is not null; - public void ResetFloatValue() => __pbn__FloatValue = null; - private float? __pbn__FloatValue; - - [global::ProtoBuf.ProtoMember(5, Name = @"long_value")] - public long? LongValue - { - get => __pbn__LongValue.GetValueOrDefault(); - set => __pbn__LongValue = value; - } - public bool ShouldSerializeLongValue() => __pbn__LongValue is not null; - public void ResetLongValue() => __pbn__LongValue = null; - private long? __pbn__LongValue; - - [global::ProtoBuf.ProtoMember(6, Name = @"int_value")] - public int? IntValue - { - get => __pbn__IntValue.GetValueOrDefault(); - set => __pbn__IntValue = value; - } - public bool ShouldSerializeIntValue() => __pbn__IntValue is not null; - public void ResetIntValue() => __pbn__IntValue = null; - private int? __pbn__IntValue; - - [global::ProtoBuf.ProtoMember(7, Name = @"bool_value")] - public bool? BoolValue - { - get => __pbn__BoolValue.GetValueOrDefault(); - set => __pbn__BoolValue = value; - } - public bool ShouldSerializeBoolValue() => __pbn__BoolValue is not null; - public void ResetBoolValue() => __pbn__BoolValue = null; - private bool? __pbn__BoolValue; - - [global::ProtoBuf.ProtoMember(8, Name = @"string_value")] - [global::System.ComponentModel.DefaultValue("")] - public string? StringValue - { - get => __pbn__StringValue ?? ""; - set => __pbn__StringValue = value; - } - public bool ShouldSerializeStringValue() => __pbn__StringValue is not null; - public void ResetStringValue() => __pbn__StringValue = null; - private string? __pbn__StringValue; - - [global::ProtoBuf.ProtoMember(9, Name = @"bytes_value")] - public byte[]? BytesValue - { - get => __pbn__BytesValue; - set => __pbn__BytesValue = value; - } - public bool ShouldSerializeBytesValue() => __pbn__BytesValue is not null; - public void ResetBytesValue() => __pbn__BytesValue = null; - private byte[]? __pbn__BytesValue; - - [global::ProtoBuf.ProtoContract()] - public enum ValueType - { - [global::ProtoBuf.ProtoEnum(Name = @"DOUBLE")] - Double = 0, - [global::ProtoBuf.ProtoEnum(Name = @"FLOAT")] - Float = 1, - [global::ProtoBuf.ProtoEnum(Name = @"INT64")] - Int64 = 2, - [global::ProtoBuf.ProtoEnum(Name = @"INT32")] - Int32 = 3, - [global::ProtoBuf.ProtoEnum(Name = @"BOOL")] - Bool = 4, - [global::ProtoBuf.ProtoEnum(Name = @"STRING")] - String = 5, - [global::ProtoBuf.ProtoEnum(Name = @"BYTES")] - Bytes = 6, - } - - } - - [global::ProtoBuf.ProtoContract()] - internal partial class KuraPosition : global::ProtoBuf.IExtensible - { - private global::ProtoBuf.IExtension? __pbn__extensionData; - global::ProtoBuf.IExtension global::ProtoBuf.IExtensible.GetExtensionObject(bool createIfMissing) - => global::ProtoBuf.Extensible.GetExtensionObject(ref __pbn__extensionData, createIfMissing); - - [global::ProtoBuf.ProtoMember(1, Name = @"latitude", IsRequired = true)] - public double Latitude { get; set; } - - [global::ProtoBuf.ProtoMember(2, Name = @"longitude", IsRequired = true)] - public double Longitude { get; set; } - - [global::ProtoBuf.ProtoMember(3, Name = @"altitude")] - public double? Altitude - { - get => __pbn__Altitude.GetValueOrDefault(); - set => __pbn__Altitude = value; - } - public bool ShouldSerializeAltitude() => __pbn__Altitude is not null; - public void ResetAltitude() => __pbn__Altitude = null; - private double? __pbn__Altitude; - - [global::ProtoBuf.ProtoMember(4, Name = @"precision")] - public double? Precision - { - get => __pbn__Precision.GetValueOrDefault(); - set => __pbn__Precision = value; - } - public bool ShouldSerializePrecision() => __pbn__Precision is not null; - public void ResetPrecision() => __pbn__Precision = null; - private double? __pbn__Precision; - - [global::ProtoBuf.ProtoMember(5, Name = @"heading")] - public double? Heading - { - get => __pbn__Heading.GetValueOrDefault(); - set => __pbn__Heading = value; - } - public bool ShouldSerializeHeading() => __pbn__Heading is not null; - public void ResetHeading() => __pbn__Heading = null; - private double? __pbn__Heading; - - [global::ProtoBuf.ProtoMember(6, Name = @"speed")] - public double? Speed - { - get => __pbn__Speed.GetValueOrDefault(); - set => __pbn__Speed = value; - } - public bool ShouldSerializeSpeed() => __pbn__Speed is not null; - public void ResetSpeed() => __pbn__Speed = null; - private double? __pbn__Speed; - - [global::ProtoBuf.ProtoMember(7, Name = @"timestamp")] - public long? Timestamp - { - get => __pbn__Timestamp.GetValueOrDefault(); - set => __pbn__Timestamp = value; - } - public bool ShouldSerializeTimestamp() => __pbn__Timestamp is not null; - public void ResetTimestamp() => __pbn__Timestamp = null; - private long? __pbn__Timestamp; - - [global::ProtoBuf.ProtoMember(8, Name = @"satellites")] - public int? Satellites - { - get => __pbn__Satellites.GetValueOrDefault(); - set => __pbn__Satellites = value; - } - public bool ShouldSerializeSatellites() => __pbn__Satellites is not null; - public void ResetSatellites() => __pbn__Satellites = null; - private int? __pbn__Satellites; - - [global::ProtoBuf.ProtoMember(9, Name = @"status")] - public int? Status - { - get => __pbn__Status.GetValueOrDefault(); - set => __pbn__Status = value; - } - public bool ShouldSerializeStatus() => __pbn__Status is not null; - public void ResetStatus() => __pbn__Status = null; - private int? __pbn__Status; - - } - - } - -} - -#pragma warning restore CS0612, CS0618, CS1591, CS3021, IDE0079, IDE1006, RCS1036, RCS1057, RCS1085, RCS1192 -#nullable disable -#endregion diff --git a/src/SparkplugNet/VersionA/SparkplugApplication.cs b/src/SparkplugNet/VersionA/SparkplugApplication.cs deleted file mode 100644 index e39e726..0000000 --- a/src/SparkplugNet/VersionA/SparkplugApplication.cs +++ /dev/null @@ -1,240 +0,0 @@ -// -------------------------------------------------------------------------------------------------------------------- -// -// The project is licensed under the MIT license. -// -// -// A class that handles a Sparkplug application. -// -// -------------------------------------------------------------------------------------------------------------------- - -namespace SparkplugNet.VersionA; - -/// -/// -/// A class that handles a Sparkplug application. -/// -/// -public class SparkplugApplication : SparkplugApplicationBase -{ - /// - /// - /// Initializes a new instance of the class. - /// - /// The known metrics. - /// The logger. - /// - public SparkplugApplication(IEnumerable knownMetrics, ILogger? logger = null) : base(knownMetrics, logger) - { - } - - /// - /// - /// Initializes a new instance of the class. - /// - /// The known metrics storage. - /// The logger. - /// - public SparkplugApplication(KnownMetricStorage knownMetricsStorage, ILogger? logger = null) : base(knownMetricsStorage, logger) - { - } - - /// - /// Publishes a version A node command message. - /// - /// The metrics. - /// The group identifier. - /// The edge node identifier. - /// Thrown if the options are null. - /// Thrown if an invalid metric type was specified. - /// A representing any asynchronous operation. - protected override async Task PublishNodeCommandMessage(IEnumerable metrics, string groupIdentifier, string edgeNodeIdentifier) - { - if (this.Options is null) - { - throw new ArgumentNullException(nameof(this.Options), "The options aren't set properly."); - } - - if (this.KnownMetrics is null) - { - throw new Exception("Invalid metric type specified for version A metric."); - } - - // Get the data message. - var dataMessage = SparkplugMessageGenerator.GetSparkPlugNodeCommandMessage( - this.NameSpace, - groupIdentifier, - edgeNodeIdentifier, - this.KnownMetricsStorage.FilterOutgoingMetrics(metrics), - this.LastSequenceNumber, - this.LastSessionNumber, - DateTimeOffset.Now, - this.Options.AddSessionNumberToCommandMessages); - - // Increment the sequence number. - this.IncrementLastSequenceNumber(); - - // Publish the message. - await this.Client.PublishAsync(dataMessage); - } - - /// - /// Publishes a version A device command message. - /// - /// The metrics. - /// The group identifier. - /// The edge node identifier. - /// The device identifier. - /// Thrown if the options are null. - /// Thrown if an invalid metric type was specified. - /// A representing any asynchronous operation. - protected override async Task PublishDeviceCommandMessage(IEnumerable metrics, string groupIdentifier, string edgeNodeIdentifier, string deviceIdentifier) - { - if (this.Options is null) - { - throw new ArgumentNullException(nameof(this.Options), "The options aren't set properly."); - } - - if (this.KnownMetrics is null) - { - throw new Exception("Invalid metric type specified for version A metric."); - } - - // Get the data message. - var dataMessage = SparkplugMessageGenerator.GetSparkPlugDeviceCommandMessage( - this.NameSpace, - groupIdentifier, - edgeNodeIdentifier, - deviceIdentifier, - this.KnownMetricsStorage.FilterOutgoingMetrics(metrics), - this.LastSequenceNumber, - this.LastSessionNumber, - DateTimeOffset.Now, - this.Options.AddSessionNumberToCommandMessages); - - // Debug output. - this.Logger?.Debug("NDATA Message: {@DataMessage}", dataMessage); - - // Increment the sequence number. - this.IncrementLastSequenceNumber(); - - // Publish the message. - await this.Client.PublishAsync(dataMessage); - } - - /// - /// Called when an application message was received. - /// - /// The topic. - /// The payload. - /// A representing any asynchronous operation. - protected override async Task OnMessageReceived(SparkplugMessageTopic topic, byte[] payload) - { - var payloadVersionA = PayloadHelper.Deserialize(payload); - - if (payloadVersionA is not null) - { - var convertedPayload = PayloadConverter.ConvertVersionAPayload(payloadVersionA); - await this.HandleMessagesForVersionA(topic, convertedPayload); - } - } - - /// - /// Handles the received messages for payload version A. - /// - /// The topic. - /// The payload. - /// Thrown if the known metrics are null. - /// Thrown if the metric is unknown. - /// A representing any asynchronous operation. - private async Task HandleMessagesForVersionA(SparkplugMessageTopic topic, VersionAData.Payload payload) - { - // If we have any not valid metric, throw an exception. - var metricsWithoutSequenceMetric = payload.Metrics.Where(m => m.Name != Constants.SessionNumberMetricName); - - this.KnownMetricsStorage.ValidateIncomingMetrics(metricsWithoutSequenceMetric); - - switch (topic.MessageType) - { - case SparkplugMessageType.NodeBirth: - await this.FireNodeBirthReceivedAsync(topic.GroupIdentifier, topic.EdgeNodeIdentifier, - this.ProcessPayload(topic, payload, SparkplugMetricStatus.Online)); - break; - case SparkplugMessageType.DeviceBirth: - await this.FireDeviceBirthReceivedAsync(topic.GroupIdentifier, topic.EdgeNodeIdentifier, topic.EdgeNodeIdentifier, - this.ProcessPayload(topic, payload, SparkplugMetricStatus.Online)); - break; - case SparkplugMessageType.NodeData: - foreach (var metric in this.ProcessPayload(topic, payload, SparkplugMetricStatus.Online)) - { - await this.FireNodeDataReceivedAsync(topic.GroupIdentifier, topic.EdgeNodeIdentifier, metric); - } - - break; - case SparkplugMessageType.DeviceData: - if (string.IsNullOrWhiteSpace(topic.DeviceIdentifier)) - { - throw new InvalidOperationException($"Topic {topic} is invalid!"); - } - - foreach (var metric in this.ProcessPayload(topic, payload, SparkplugMetricStatus.Online)) - { - await this.FireDeviceDataReceivedAsync(topic.GroupIdentifier, topic.EdgeNodeIdentifier, topic.DeviceIdentifier, metric); - } - - break; - case SparkplugMessageType.NodeDeath: - this.ProcessPayload(topic, payload, SparkplugMetricStatus.Offline); - await this.FireNodeDeathReceivedAsync(topic.GroupIdentifier, topic.EdgeNodeIdentifier); - break; - case SparkplugMessageType.DeviceDeath: - if (string.IsNullOrWhiteSpace(topic.DeviceIdentifier)) - { - throw new InvalidOperationException($"Topic {topic} is invalid!"); - } - - this.ProcessPayload(topic, payload, SparkplugMetricStatus.Offline); - await this.FireDeviceDeathReceivedAsync(topic.GroupIdentifier, topic.EdgeNodeIdentifier, topic.DeviceIdentifier); - break; - } - } - - /// - /// Handles the device message. - /// - /// The topic. - /// The payload. - /// The metric status. - /// Thrown if the metric cast is invalid. - private IEnumerable ProcessPayload(SparkplugMessageTopic topic, VersionAData.Payload payload, SparkplugMetricStatus metricStatus) - { - var metricState = new MetricState - { - MetricStatus = metricStatus - }; - - if (!string.IsNullOrWhiteSpace(topic.DeviceIdentifier)) - { - // No idea why we need a bang (!) operator here?! - this.DeviceStates[topic.DeviceIdentifier!] = metricState; - } - else - { - this.NodeStates[topic.EdgeNodeIdentifier] = metricState; - } - - foreach (var payloadMetric in payload.Metrics) - { - if (payloadMetric is not VersionAData.KuraMetric convertedMetric) - { - throw new InvalidCastException("The metric cast didn't work properly."); - } - - if (payloadMetric.Name is not null) - { - metricState.Metrics[payloadMetric.Name] = convertedMetric; - } - - yield return convertedMetric; - } - } -} diff --git a/src/SparkplugNet/VersionA/SparkplugNode.cs b/src/SparkplugNet/VersionA/SparkplugNode.cs deleted file mode 100644 index 0820b1d..0000000 --- a/src/SparkplugNet/VersionA/SparkplugNode.cs +++ /dev/null @@ -1,130 +0,0 @@ -// -------------------------------------------------------------------------------------------------------------------- -// -// The project is licensed under the MIT license. -// -// -// A class that handles a Sparkplug node. -// -// -------------------------------------------------------------------------------------------------------------------- - -namespace SparkplugNet.VersionA; - -/// -/// -/// A class that handles a Sparkplug node. -/// -/// -public class SparkplugNode : SparkplugNodeBase -{ - /// - /// - /// Initializes a new instance of the class. - /// - /// The known metrics. - /// The logger. - /// - public SparkplugNode(IEnumerable knownMetrics, ILogger? logger = null) : base(knownMetrics, logger) - { - } - - /// - /// - /// Initializes a new instance of the class. - /// - /// The metric names. - /// The logger. - /// - public SparkplugNode(KnownMetricStorage knownMetricsStorage, ILogger? logger = null) : base(knownMetricsStorage, logger) - { - } - - /// - /// Publishes version A metrics for a node. - /// - /// The metrics. - /// Thrown if the options are null. - /// Thrown if an invalid metric type was specified. - /// A . - protected override async Task PublishMessage(IEnumerable metrics) - { - if (this.Options is null) - { - throw new ArgumentNullException(nameof(this.Options), "The options aren't set properly."); - } - - if (this.KnownMetrics is null) - { - throw new Exception("Invalid metric type specified for version A metric."); - } - - // Get the data message. - var dataMessage = this.MessageGenerator.GetSparkPlugNodeDataMessage( - this.NameSpace, - this.Options.GroupIdentifier, - this.Options.EdgeNodeIdentifier, - this.KnownMetricsStorage.FilterOutgoingMetrics(metrics), - this.LastSequenceNumber, - this.LastSessionNumber, - DateTimeOffset.Now, - this.Options.AddSessionNumberToDataMessages); - - // Debug output. - this.Logger?.Debug("NDATA Message: {@DataMessage}", dataMessage); - - // Increment the sequence number. - this.IncrementLastSequenceNumber(); - - // Publish the message. - return await this.Client.PublishAsync(dataMessage); - } - - /// - /// Called when the node message is received. - /// - /// The topic. - /// The payload. - /// Thrown if the metric cast didn't work properly. - /// A representing any asynchronous operation. - protected override async Task OnMessageReceived(SparkplugMessageTopic topic, byte[] payload) - { - var payloadVersionA = PayloadHelper.Deserialize(payload); - - if (payloadVersionA is not null) - { - var convertedPayload = PayloadConverter.ConvertVersionAPayload(payloadVersionA); - - if (convertedPayload is not VersionAData.Payload convertedPayloadVersionA) - { - throw new InvalidCastException("The metric cast didn't work properly."); - } - - switch (topic.MessageType) - { - case SparkplugMessageType.DeviceCommand: - if (!string.IsNullOrWhiteSpace(topic.DeviceIdentifier)) - { - foreach (var metric in convertedPayloadVersionA.Metrics) - { - if (metric is VersionAData.KuraMetric convertedMetric) - { - await this.FireDeviceCommandReceivedAsync(topic.DeviceIdentifier, convertedMetric); - } - } - } - - break; - - case SparkplugMessageType.NodeCommand: - foreach (var metric in convertedPayloadVersionA.Metrics) - { - if (metric is VersionAData.KuraMetric convertedMetric) - { - await this.FireNodeCommandReceivedAsync(convertedMetric); - } - } - - break; - } - } - } -} diff --git a/src/SparkplugNet/VersionB/SparkplugApplication.cs b/src/SparkplugNet/VersionB/SparkplugApplication.cs index ef6c5b0..08da5dc 100644 --- a/src/SparkplugNet/VersionB/SparkplugApplication.cs +++ b/src/SparkplugNet/VersionB/SparkplugApplication.cs @@ -134,7 +134,7 @@ protected override async Task OnMessageReceived(SparkplugMessageTopic topic, byt } /// - /// Handles the received messages for payload version A. + /// Handles the received messages for payload version B. /// /// The topic. /// The payload. From a552c46562d967452a74ce713f4706c9868e5e30 Mon Sep 17 00:00:00 2001 From: SeppPenner Date: Sat, 8 Apr 2023 19:57:19 +0200 Subject: [PATCH 06/16] Updated readme. --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index 24709b5..d7078d8 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,6 @@ SparkplugNet is a library to use the Sparkplug industrial IoT (IIoT) standard in * Net 7.0 ## Net Core and Net Framework latest and LTS versions -* https://dotnet.microsoft.com/download/dotnet-framework * https://dotnet.microsoft.com/download/dotnet-core * https://dotnet.microsoft.com/download/dotnet From 1c04efd0d5deda0ea79dd5ef2b33e455ee07bee6 Mon Sep 17 00:00:00 2001 From: SeppPenner Date: Sat, 8 Apr 2023 20:07:43 +0200 Subject: [PATCH 07/16] Added logic to check for clean session flag on MQTT v3.1.1 and clean start and session expiry on MQTT v5.0, reworked constructors for options, removed logic for adding session numbers to data messages (Might be not according to the spec). --- src/SparkplugNet.Examples/GlobalUsings.cs | 3 + src/SparkplugNet.Examples/Program.cs | 34 +++- .../GlobalUsings.cs | 3 + .../MqttServerUnderTest.cs | 16 +- .../SparkplugNodeSequentialTest.cs | 2 + src/SparkplugNet.Tests/GlobalUsings.cs | 1 + .../SparkplugMessageGeneratorTest.cs | 10 +- .../Application/SparkplugApplicationBase.cs | 15 +- .../SparkplugApplicationOptions.cs | 149 ++++------------ .../SparkplugMqttProtocolVersion.cs | 26 +++ .../Messages/SparkplugMessageGenerator.cs | 61 ++++--- .../Core/Node/SparkplugNodeBase.Device.cs | 3 +- .../Core/Node/SparkplugNodeBase.cs | 17 +- .../Core/Node/SparkplugNodeOptions.cs | 165 +++++------------- src/SparkplugNet/Core/SparkplugBaseOptions.cs | 73 +++++--- .../VersionB/SparkplugApplication.cs | 6 +- src/SparkplugNet/VersionB/SparkplugNode.cs | 3 +- 17 files changed, 259 insertions(+), 328 deletions(-) create mode 100644 src/SparkplugNet/Core/Enumerations/SparkplugMqttProtocolVersion.cs diff --git a/src/SparkplugNet.Examples/GlobalUsings.cs b/src/SparkplugNet.Examples/GlobalUsings.cs index 9fef49f..a71fc0f 100644 --- a/src/SparkplugNet.Examples/GlobalUsings.cs +++ b/src/SparkplugNet.Examples/GlobalUsings.cs @@ -1,7 +1,10 @@ #pragma warning disable IDE0065 // Die using-Anweisung wurde falsch platziert. +global using MQTTnet.Protocol; + global using Serilog; global using SparkplugNet.Core.Application; +global using SparkplugNet.Core.Enumerations; global using SparkplugNet.Core.Node; global using VersionBData = SparkplugNet.VersionB.Data; diff --git a/src/SparkplugNet.Examples/Program.cs b/src/SparkplugNet.Examples/Program.cs index 3db88ed..9714405 100644 --- a/src/SparkplugNet.Examples/Program.cs +++ b/src/SparkplugNet.Examples/Program.cs @@ -109,7 +109,21 @@ private static async Task RunVersionB() /// A representing any asynchronous operation. private static async Task RunVersionBApplication() { - var applicationOptions = new SparkplugApplicationOptions("localhost", 1883, nameof(RunVersionBApplication), "user", "password", false, "scada1", TimeSpan.FromSeconds(30), true, null, null, CancellationTokenSource.Token); + var applicationOptions = new SparkplugApplicationOptions( + "localhost", + 1883, + nameof(RunVersionBApplication), + "user", + "password", + false, + "scada1", + TimeSpan.FromSeconds(30), + SparkplugMqttProtocolVersion.V311, + null, + null, + null, + true, + CancellationTokenSource.Token); var application = new VersionB.SparkplugApplication(VersionBMetricsApplication, Log.Logger); // Start an application. @@ -162,7 +176,23 @@ private static async Task RunVersionBApplication() /// A representing any asynchronous operation. private static async Task RunVersionBNode() { - var nodeOptions = new SparkplugNodeOptions("localhost", 1883, "node 1", "user", "password", false, "scada1B", "group1", "node1", TimeSpan.FromSeconds(30), null, null, CancellationTokenSource.Token); + var nodeOptions = new SparkplugNodeOptions( + "localhost", + 1883, + "node 1", + "user", + "password", + false, + "scada1B", + TimeSpan.FromSeconds(30), + SparkplugMqttProtocolVersion.V311, + null, + null, + null, + "group1", + "node1", + MqttQualityOfServiceLevel.AtMostOnce, + CancellationTokenSource.Token); var node = new VersionB.SparkplugNode(VersionBMetricsNode, Log.Logger); // Start a node. diff --git a/src/SparkplugNet.IntegrationTests/GlobalUsings.cs b/src/SparkplugNet.IntegrationTests/GlobalUsings.cs index 27d2357..f60862f 100644 --- a/src/SparkplugNet.IntegrationTests/GlobalUsings.cs +++ b/src/SparkplugNet.IntegrationTests/GlobalUsings.cs @@ -1,6 +1,9 @@ #pragma warning disable IDE0065 // Die using-Anweisung wurde falsch platziert. global using Microsoft.VisualStudio.TestTools.UnitTesting; +global using MQTTnet.Formatter; +global using MQTTnet.Protocol; + global using Serilog; global using SparkplugNet.Core; diff --git a/src/SparkplugNet.IntegrationTests/MqttServerUnderTest.cs b/src/SparkplugNet.IntegrationTests/MqttServerUnderTest.cs index be34c5b..c5cd5c5 100644 --- a/src/SparkplugNet.IntegrationTests/MqttServerUnderTest.cs +++ b/src/SparkplugNet.IntegrationTests/MqttServerUnderTest.cs @@ -15,22 +15,22 @@ namespace SparkplugNet.IntegrationTests; public static class MqttServerUnderTest { /// - /// Gets or sets the server address. + /// The server address. /// - public static string ServerAddress { get; set; } = "localhost"; + public const string ServerAddress = "localhost"; /// - /// Gets or sets the server port. + /// The server port. /// - public static int ServerPort { get; set; } = 1883; + public const int ServerPort = 1883; /// - /// Gets or sets the client identifier. + /// The client identifier. /// - public static string ClientId { get; set; } = "client1"; + public const string ClientId = "client1"; /// - /// Gets or sets the SCADA host identifier. + /// The SCADA host identifier. /// - public static string ScadaHostIdentifier { get; set; } = "scadaHost1"; + public const string ScadaHostIdentifier = "scadaHost1"; } diff --git a/src/SparkplugNet.IntegrationTests/SparkplugNodeSequentialTest.cs b/src/SparkplugNet.IntegrationTests/SparkplugNodeSequentialTest.cs index ae21be1..5ca6237 100644 --- a/src/SparkplugNet.IntegrationTests/SparkplugNodeSequentialTest.cs +++ b/src/SparkplugNet.IntegrationTests/SparkplugNodeSequentialTest.cs @@ -58,6 +58,8 @@ public async Task T1TestNodeVersionBConnectBirth() MqttServerUnderTest.ScadaHostIdentifier, GroupIdentifier, EdgeNodeIdentifier, + MqttProtocolVersion.V311, + MqttQualityOfServiceLevel.AtMostOnce, TimeSpan.FromSeconds(30), null, null, diff --git a/src/SparkplugNet.Tests/GlobalUsings.cs b/src/SparkplugNet.Tests/GlobalUsings.cs index ecfb7fd..eae830a 100644 --- a/src/SparkplugNet.Tests/GlobalUsings.cs +++ b/src/SparkplugNet.Tests/GlobalUsings.cs @@ -2,6 +2,7 @@ global using Microsoft.VisualStudio.TestTools.UnitTesting; global using MQTTnet; +global using MQTTnet.Protocol; global using Serilog; diff --git a/src/SparkplugNet.Tests/SparkplugMessageGeneratorTest.cs b/src/SparkplugNet.Tests/SparkplugMessageGeneratorTest.cs index c494fe1..d1327a4 100644 --- a/src/SparkplugNet.Tests/SparkplugMessageGeneratorTest.cs +++ b/src/SparkplugNet.Tests/SparkplugMessageGeneratorTest.cs @@ -141,7 +141,7 @@ public void TestDeviceDeathMessageNamespaceB() [TestMethod] public void TestNodeDeathMessageNamespaceB() { - var message = this.messageGenerator.GetSparkPlugNodeDeathMessage(SparkplugNamespace.VersionB, "group1", "edge1", 1); + var message = this.messageGenerator.GetSparkPlugNodeDeathMessage(SparkplugNamespace.VersionB, "group1", "edge1", 1, MqttQualityOfServiceLevel.AtMostOnce); var payloadVersionB = PayloadHelper.Deserialize(message.Payload); Assert.AreEqual("spBv1.0/group1/NDEATH/edge1", message.Topic); @@ -160,7 +160,7 @@ public void TestNodeDeathMessageNamespaceB() public void TestDeviceDataMessageNamespaceB() { var dateTime = DateTimeOffset.Now; - var message = this.messageGenerator.GetSparkPlugDeviceDataMessage(SparkplugNamespace.VersionB, "group1", "edge1", "device1", this.metricsB, 0, 1, dateTime,true); + var message = this.messageGenerator.GetSparkPlugDeviceDataMessage(SparkplugNamespace.VersionB, "group1", "edge1", "device1", this.metricsB, 0, 1, dateTime); var payloadVersionB = PayloadHelper.Deserialize(message.Payload); Assert.AreEqual("spBv1.0/group1/DDATA/edge1/device1", message.Topic); @@ -184,7 +184,7 @@ public void TestDeviceDataMessageNamespaceB() public void TestNodeDataMessageNamespaceB() { var dateTime = DateTimeOffset.Now; - var message = this.messageGenerator.GetSparkPlugNodeDataMessage(SparkplugNamespace.VersionB, "group1", "edge1", this.metricsB, 0, 1, dateTime, true); + var message = this.messageGenerator.GetSparkPlugNodeDataMessage(SparkplugNamespace.VersionB, "group1", "edge1", this.metricsB, 0, 1, dateTime); var payloadVersionB = PayloadHelper.Deserialize(message.Payload); Assert.AreEqual("spBv1.0/group1/NDATA/edge1", message.Topic); @@ -208,7 +208,7 @@ public void TestNodeDataMessageNamespaceB() public void TestDeviceCommandMessageNamespaceB() { var dateTime = DateTimeOffset.Now; - var message = SparkplugMessageGenerator.GetSparkPlugDeviceCommandMessage(SparkplugNamespace.VersionB, "group1", "edge1", "device1", this.metricsB, 0, 1, dateTime, true); + var message = SparkplugMessageGenerator.GetSparkPlugDeviceCommandMessage(SparkplugNamespace.VersionB, "group1", "edge1", "device1", this.metricsB, 0, 1, dateTime); var payloadVersionB = PayloadHelper.Deserialize(message.Payload); Assert.AreEqual("spBv1.0/group1/DCMD/edge1/device1", message.Topic); @@ -232,7 +232,7 @@ public void TestDeviceCommandMessageNamespaceB() public void TestNodeCommandMessageNamespaceB() { var dateTime = DateTimeOffset.Now; - var message = SparkplugMessageGenerator.GetSparkPlugNodeCommandMessage(SparkplugNamespace.VersionB, "group1", "edge1", this.metricsB, 0, 1, dateTime, true); + var message = SparkplugMessageGenerator.GetSparkPlugNodeCommandMessage(SparkplugNamespace.VersionB, "group1", "edge1", this.metricsB, 0, 1, dateTime); var payloadVersionB = PayloadHelper.Deserialize(message.Payload); Assert.AreEqual("spBv1.0/group1/NCMD/edge1", message.Topic); diff --git a/src/SparkplugNet/Core/Application/SparkplugApplicationBase.cs b/src/SparkplugNet/Core/Application/SparkplugApplicationBase.cs index 7f91ab4..8c0c76d 100644 --- a/src/SparkplugNet/Core/Application/SparkplugApplicationBase.cs +++ b/src/SparkplugNet/Core/Application/SparkplugApplicationBase.cs @@ -306,7 +306,6 @@ private Task OnApplicationMessageReceived(MqttApplicationMessageReceivedEventArg { return this.OnMessageReceived(topicParsed!, args.ApplicationMessage.Payload); } - else if (topic.Contains(SparkplugMessageType.StateMessage.GetDescription())) { // Skip the STATE messages as they're UTF-8 encoded. @@ -354,8 +353,18 @@ private async Task ConnectInternal() var builder = new MqttClientOptionsBuilder() .WithClientId(this.Options.ClientId) .WithCredentials(this.Options.UserName, this.Options.Password) - .WithCleanSession(false) - .WithProtocolVersion(MqttProtocolVersion.V311); + .WithProtocolVersion((MqttProtocolVersion)this.Options.MqttProtocolVersion); + + switch (this.Options.MqttProtocolVersion) + { + case SparkplugMqttProtocolVersion.V311: + builder.WithCleanSession(true); + break; + case SparkplugMqttProtocolVersion.V500: + // Todo: Set clean start?! + builder.WithSessionExpiryInterval(0); + break; + } if (this.Options.UseTls) { diff --git a/src/SparkplugNet/Core/Application/SparkplugApplicationOptions.cs b/src/SparkplugNet/Core/Application/SparkplugApplicationOptions.cs index ae5fce2..b518d4e 100644 --- a/src/SparkplugNet/Core/Application/SparkplugApplicationOptions.cs +++ b/src/SparkplugNet/Core/Application/SparkplugApplicationOptions.cs @@ -18,97 +18,9 @@ namespace SparkplugNet.Core.Application; public class SparkplugApplicationOptions : SparkplugBaseOptions { /// - /// The default option to add session numbers to command messages. + /// The default value whether the application is a primary application or not. /// - public const bool DefaultAddSessionNumberToCommandMessages = true; - - /// - /// - /// For serializers only. - /// Initializes a new instance of the class. - /// - /// - [EditorBrowsable(EditorBrowsableState.Never)] - public SparkplugApplicationOptions() : this(brokerAddress: DefaultBroker) - { - } - - /// - /// - /// Initializes a new instance of the class. - /// - /// The broker address. - /// The port. - /// The client identifier. - /// The name of the user. - /// The password. - /// A value indicating whether TLS is used or not. - /// The SCADA host identifier. - /// A value indicating whether the application is a primary application or not. - /// The delegate to provide TLS parameters. - /// The web socket parameters. - /// The proxy options. - /// - public SparkplugApplicationOptions( - string brokerAddress = DefaultBroker, - int port = DefaultPort, - string clientId = DefaultClientId, - string userName = DefaultUserName, - string password = DefaultPassword, - bool useTls = DefaultUseTls, - string scadaHostIdentifier = DefaultScadaHostIdentifier, - bool isPrimaryApplication = false, - GetTlsParametersDelegate? getTlsParameters = null, - MqttClientOptionsBuilderWebSocketParameters? webSocketParameters = null, - MqttClientWebSocketProxyOptions? proxyOptions = null) - : this(brokerAddress, port, clientId, userName, password, useTls, scadaHostIdentifier, - reconnectInterval: TimeSpan.FromSeconds(30), - isPrimaryApplication: isPrimaryApplication, - getTlsParameters: getTlsParameters, - webSocketParameters: webSocketParameters, - proxyOptions: proxyOptions) - { - } - - /// - /// - /// Initializes a new instance of the class. - /// - /// The broker address. - /// The port. - /// The client identifier. - /// The name of the user. - /// The password. - /// A value indicating whether TLS is used or not. - /// The SCADA host identifier. - /// The reconnect interval. - /// A value indicating whether the application is a primary application or not. - /// The web socket parameters. - /// The proxy options. - /// The cancellation token. - /// - public SparkplugApplicationOptions( - string brokerAddress, - int port, - string clientId, - string userName, - string password, - bool useTls, - string scadaHostIdentifier, - TimeSpan reconnectInterval, - bool isPrimaryApplication = false, - MqttClientOptionsBuilderWebSocketParameters? webSocketParameters = null, - MqttClientWebSocketProxyOptions? proxyOptions = null, - SystemCancellationToken? cancellationToken = null) - : this(brokerAddress, port, clientId, userName, password, useTls, scadaHostIdentifier, - reconnectInterval: reconnectInterval, - isPrimaryApplication: isPrimaryApplication, - getTlsParameters: null, - webSocketParameters: webSocketParameters, - proxyOptions: proxyOptions, - cancellationToken: cancellationToken) - { - } + public const bool DefaultIsPrimaryApplication = false; /// /// @@ -122,6 +34,7 @@ public SparkplugApplicationOptions( /// A value indicating whether TLS is used or not. /// The SCADA host identifier. /// The reconnect interval. + /// The MQTT protocol version. /// A value indicating whether the application is a primary application or not. /// The delegate to provide TLS parameters. /// The web socket parameters. @@ -129,32 +42,35 @@ public SparkplugApplicationOptions( /// The cancellation token. /// public SparkplugApplicationOptions( - string brokerAddress, - int port, - string clientId, - string userName, - string password, - bool useTls, - string scadaHostIdentifier, - TimeSpan reconnectInterval, - bool isPrimaryApplication = false, + string? brokerAddress = null, + int? port = null, + string? clientId = null, + string? userName = null, + string? password = null, + bool? useTls = null, + string? scadaHostIdentifier = null, + TimeSpan? reconnectInterval = null, + SparkplugMqttProtocolVersion? mqttProtocolVersion = null, GetTlsParametersDelegate? getTlsParameters = null, MqttClientOptionsBuilderWebSocketParameters? webSocketParameters = null, MqttClientWebSocketProxyOptions? proxyOptions = null, + bool? isPrimaryApplication = null, SystemCancellationToken? cancellationToken = null) - : base(brokerAddress: brokerAddress, - port: port, - clientId: clientId, - userName: userName, - password: password, - useTls: useTls, - scadaHostIdentifier: scadaHostIdentifier, - reconnectInterval: reconnectInterval, - getTlsParameters: getTlsParameters, - webSocketParameters: webSocketParameters, - proxyOptions: proxyOptions) + : base( + brokerAddress, + port, + clientId, + userName, + password, + useTls, + scadaHostIdentifier, + reconnectInterval, + mqttProtocolVersion, + getTlsParameters, + webSocketParameters, + proxyOptions) { - this.IsPrimaryApplication = isPrimaryApplication; + this.IsPrimaryApplication = isPrimaryApplication ?? DefaultIsPrimaryApplication; this.CancellationToken = cancellationToken ?? SystemCancellationToken.None; } @@ -162,13 +78,8 @@ public SparkplugApplicationOptions( /// Gets or sets a value indicating whether the application the primary application or not. /// If this value is set to true, the application sends STATE messages, else not. /// - public bool IsPrimaryApplication { get; set; } = false; - - /// - /// Gets or sets a value indicating whether session messages are added to command messages or not. - /// - [DefaultValue(DefaultAddSessionNumberToCommandMessages)] - public bool AddSessionNumberToCommandMessages { get; set; } = DefaultAddSessionNumberToCommandMessages; + [DefaultValue(DefaultIsPrimaryApplication)] + public bool IsPrimaryApplication { get; set; } = DefaultIsPrimaryApplication; /// /// Gets or sets the cancellation token. @@ -176,5 +87,5 @@ public SparkplugApplicationOptions( [JsonIgnore] [XmlIgnore] [Browsable(false)] - public SystemCancellationToken? CancellationToken { get; set; } + public SystemCancellationToken? CancellationToken { get; set; } = SystemCancellationToken.None; } diff --git a/src/SparkplugNet/Core/Enumerations/SparkplugMqttProtocolVersion.cs b/src/SparkplugNet/Core/Enumerations/SparkplugMqttProtocolVersion.cs new file mode 100644 index 0000000..fcf6899 --- /dev/null +++ b/src/SparkplugNet/Core/Enumerations/SparkplugMqttProtocolVersion.cs @@ -0,0 +1,26 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// The project is licensed under the MIT license. +// +// +// The Sparkplug MQTT protocol version. +// +// -------------------------------------------------------------------------------------------------------------------- + +namespace SparkplugNet.Core.Enumerations; + +/// +/// The Sparkplug MQTT protocol version. +/// +public enum SparkplugMqttProtocolVersion +{ + /// + /// MQTT protocol version 3.1.1. + /// + V311 = 4, + + /// + /// MQTT protocol version 5.0.0. + /// + V500 = 5 +} diff --git a/src/SparkplugNet/Core/Messages/SparkplugMessageGenerator.cs b/src/SparkplugNet/Core/Messages/SparkplugMessageGenerator.cs index a52efbf..83cc23b 100644 --- a/src/SparkplugNet/Core/Messages/SparkplugMessageGenerator.cs +++ b/src/SparkplugNet/Core/Messages/SparkplugMessageGenerator.cs @@ -165,6 +165,7 @@ public MqttApplicationMessage GetSparkPlugDeviceBirthMessage( /// The group identifier. /// The edge node identifier. /// The session number. + /// The quality of service level. /// Thrown if the group identifier or the edge node identifier is invalid. /// Thrown if the namespace is out of range. /// A new NDEATH . @@ -172,7 +173,8 @@ public MqttApplicationMessage GetSparkPlugNodeDeathMessage( SparkplugNamespace nameSpace, string groupIdentifier, string edgeNodeIdentifier, - long sessionNumber) + long sessionNumber, + MqttQualityOfServiceLevel qualityOfServiceLevel) { if (!groupIdentifier.IsIdentifierValid()) { @@ -190,7 +192,7 @@ public MqttApplicationMessage GetSparkPlugNodeDeathMessage( { var metrics = new List(); return this.GetSparkPlugNodeDeathB(nameSpace, groupIdentifier, edgeNodeIdentifier, - AddSessionNumberToMetrics(metrics, sessionNumber)); + AddSessionNumberToMetrics(metrics, sessionNumber), qualityOfServiceLevel); } default: @@ -260,7 +262,6 @@ public MqttApplicationMessage GetSparkPlugDeviceDeathMessage( /// The sequence number. /// The session number. /// The date time. - /// A value indicating whether to add the 'SessionNumber' metric or not. /// Thrown if the group identifier or the edge node identifier is invalid. /// Thrown if the namespace is out of range. /// A new NDATA . @@ -271,8 +272,7 @@ public MqttApplicationMessage GetSparkPlugNodeDataMessage( IEnumerable metrics, int sequenceNumber, long sessionNumber, - DateTimeOffset dateTime, - bool addSessionNumbers) + DateTimeOffset dateTime) where T : IMetric, new() { if (!groupIdentifier.IsIdentifierValid()) @@ -292,7 +292,7 @@ public MqttApplicationMessage GetSparkPlugNodeDataMessage( var newMetrics = metrics as IEnumerable ?? new List(); return this.GetSparkPlugNodeDataB(nameSpace, groupIdentifier, edgeNodeIdentifier, - AddSessionNumberToMetrics(newMetrics, sessionNumber, !addSessionNumbers), sequenceNumber, dateTime); + AddSessionNumberToMetrics(newMetrics, sessionNumber), sequenceNumber, dateTime); } default: @@ -312,7 +312,6 @@ public MqttApplicationMessage GetSparkPlugNodeDataMessage( /// The sequence number. /// The session number. /// The date time. - /// A value indicating whether to add the 'SessionNumber' metric or not. /// Thrown if the group identifier or the edge node identifier or the device identifier is invalid. /// Thrown if the namespace is out of range. /// A new DDATA . @@ -324,8 +323,7 @@ public MqttApplicationMessage GetSparkPlugDeviceDataMessage( IEnumerable metrics, int sequenceNumber, long sessionNumber, - DateTimeOffset dateTime, - bool addSessionNumbers) + DateTimeOffset dateTime) where T : IMetric, new() { if (!groupIdentifier.IsIdentifierValid()) @@ -350,7 +348,7 @@ public MqttApplicationMessage GetSparkPlugDeviceDataMessage( var newMetrics = metrics as IEnumerable ?? new List(); return this.GetSparkPlugDeviceDataB(nameSpace, groupIdentifier, edgeNodeIdentifier, deviceIdentifier, - AddSessionNumberToMetrics(newMetrics, sessionNumber, !addSessionNumbers), sequenceNumber, dateTime); + AddSessionNumberToMetrics(newMetrics, sessionNumber), sequenceNumber, dateTime); } default: @@ -369,7 +367,6 @@ public MqttApplicationMessage GetSparkPlugDeviceDataMessage( /// The sequence number. /// The session number. /// The date time. - /// A value indicating whether to add the 'SessionNumber' metric or not. /// Thrown if the group identifier or the edge node identifier is invalid. /// Thrown if the namespace is out of range. /// A new NCMD . @@ -380,8 +377,7 @@ public static MqttApplicationMessage GetSparkPlugNodeCommandMessage( IEnumerable metrics, int sequenceNumber, long sessionNumber, - DateTimeOffset dateTime, - bool addSessionNumbers) + DateTimeOffset dateTime) where T : IMetric, new() { if (!groupIdentifier.IsIdentifierValid()) @@ -402,7 +398,7 @@ public static MqttApplicationMessage GetSparkPlugNodeCommandMessage( ?? new List(); return GetSparkPlugNodeCommandB(nameSpace, groupIdentifier, edgeNodeIdentifier, - AddSessionNumberToMetrics(newMetrics, sessionNumber, !addSessionNumbers), sequenceNumber, dateTime); + AddSessionNumberToMetrics(newMetrics, sessionNumber), sequenceNumber, dateTime); } default: @@ -422,7 +418,6 @@ public static MqttApplicationMessage GetSparkPlugNodeCommandMessage( /// The sequence number. /// The session number. /// The date time. - /// A value indicating whether to add the 'SessionNumber' metric or not. /// Thrown if the group identifier or the edge node identifier or the device identifier is invalid. /// Thrown if the namespace is out of range. /// A new DCMD . @@ -434,7 +429,7 @@ public static MqttApplicationMessage GetSparkPlugDeviceCommandMessage( IEnumerable metrics, int sequenceNumber, long sessionNumber, - DateTimeOffset dateTime, bool addSessionNumbers) + DateTimeOffset dateTime) where T : IMetric, new() { if (!groupIdentifier.IsIdentifierValid()) @@ -459,7 +454,7 @@ public static MqttApplicationMessage GetSparkPlugDeviceCommandMessage( var newMetrics = metrics as IEnumerable ?? new List(); - newMetrics = AddSessionNumberToMetrics(newMetrics, sessionNumber, !addSessionNumbers); + newMetrics = AddSessionNumberToMetrics(newMetrics, sessionNumber); return GetSparkPlugDeviceCommandB(nameSpace, groupIdentifier, edgeNodeIdentifier, deviceIdentifier, newMetrics, sequenceNumber, dateTime); } @@ -509,7 +504,10 @@ private static MqttApplicationMessage GetSparkplugStateMessageB(string scadaHost { return new MqttApplicationMessageBuilder() .WithTopic(SparkplugTopicGenerator.GetSparkplugStateMessageTopic(scadaHostIdentifier)) - .WithPayload(online ? "ONLINE" : "OFFLINE").WithQualityOfServiceLevel(MqttQualityOfServiceLevel.AtLeastOnce).WithRetainFlag().Build(); + .WithPayload(online ? "ONLINE" : "OFFLINE") + .WithQualityOfServiceLevel(MqttQualityOfServiceLevel.AtLeastOnce) + .WithRetainFlag() + .Build(); } /// @@ -552,7 +550,8 @@ private MqttApplicationMessage GetSparkPlugNodeBirthB( edgeNodeIdentifier, string.Empty)) .WithPayload(serialized) - .WithQualityOfServiceLevel(MqttQualityOfServiceLevel.AtLeastOnce) + .WithQualityOfServiceLevel(MqttQualityOfServiceLevel.AtMostOnce) + .WithRetainFlag(false) .Build(); } @@ -598,7 +597,8 @@ private MqttApplicationMessage GetSparkPlugDeviceBirthB( edgeNodeIdentifier, deviceIdentifier)) .WithPayload(serialized) - .WithQualityOfServiceLevel(MqttQualityOfServiceLevel.AtLeastOnce) + .WithQualityOfServiceLevel(MqttQualityOfServiceLevel.AtMostOnce) + .WithRetainFlag(false) .Build(); } @@ -609,12 +609,14 @@ private MqttApplicationMessage GetSparkPlugDeviceBirthB( /// The group identifier. /// The edge node identifier. /// The metrics. + /// The quality of service level. /// A new NDEATH . private MqttApplicationMessage GetSparkPlugNodeDeathB( SparkplugNamespace nameSpace, string groupIdentifier, string edgeNodeIdentifier, - IEnumerable metrics) + IEnumerable metrics, + MqttQualityOfServiceLevel qualityOfServiceLevel) { var payload = new VersionBData.Payload { @@ -636,7 +638,7 @@ private MqttApplicationMessage GetSparkPlugNodeDeathB( edgeNodeIdentifier, string.Empty)) .WithPayload(serialized) - .WithQualityOfServiceLevel(MqttQualityOfServiceLevel.AtLeastOnce) + .WithQualityOfServiceLevel(qualityOfServiceLevel) .Build(); } @@ -682,7 +684,8 @@ private MqttApplicationMessage GetSparkPlugDeviceDeathB( edgeNodeIdentifier, deviceIdentifier)) .WithPayload(serialized) - .WithQualityOfServiceLevel(MqttQualityOfServiceLevel.AtLeastOnce) + .WithQualityOfServiceLevel(MqttQualityOfServiceLevel.AtMostOnce) + .WithRetainFlag(false) .Build(); } @@ -726,7 +729,8 @@ private MqttApplicationMessage GetSparkPlugNodeDataB( edgeNodeIdentifier, string.Empty)) .WithPayload(serialized) - .WithQualityOfServiceLevel(MqttQualityOfServiceLevel.AtLeastOnce) + .WithQualityOfServiceLevel(MqttQualityOfServiceLevel.AtMostOnce) + .WithRetainFlag(false) .Build(); } @@ -772,7 +776,8 @@ private MqttApplicationMessage GetSparkPlugDeviceDataB( edgeNodeIdentifier, deviceIdentifier)) .WithPayload(serialized) - .WithQualityOfServiceLevel(MqttQualityOfServiceLevel.AtLeastOnce) + .WithQualityOfServiceLevel(MqttQualityOfServiceLevel.AtMostOnce) + .WithRetainFlag(false) .Build(); } @@ -812,7 +817,8 @@ private static MqttApplicationMessage GetSparkPlugNodeCommandB( SparkplugMessageType.NodeCommand, edgeNodeIdentifier, string.Empty)).WithPayload(serialized) - .WithQualityOfServiceLevel(MqttQualityOfServiceLevel.AtLeastOnce) + .WithQualityOfServiceLevel(MqttQualityOfServiceLevel.AtMostOnce) + .WithRetainFlag(false) .Build(); } @@ -854,7 +860,8 @@ private static MqttApplicationMessage GetSparkPlugDeviceCommandB( SparkplugMessageType.DeviceCommand, edgeNodeIdentifier, deviceIdentifier)).WithPayload(serialized) - .WithQualityOfServiceLevel(MqttQualityOfServiceLevel.AtLeastOnce) + .WithQualityOfServiceLevel(MqttQualityOfServiceLevel.AtMostOnce) + .WithRetainFlag(false) .Build(); } } diff --git a/src/SparkplugNet/Core/Node/SparkplugNodeBase.Device.cs b/src/SparkplugNet/Core/Node/SparkplugNodeBase.Device.cs index 2c4eae8..ed84dce 100644 --- a/src/SparkplugNet/Core/Node/SparkplugNodeBase.Device.cs +++ b/src/SparkplugNet/Core/Node/SparkplugNodeBase.Device.cs @@ -175,8 +175,7 @@ protected virtual async Task PublishMessageForDevice(IE deviceMetricStorage.FilterOutgoingMetrics(metrics), this.LastSequenceNumber, this.LastSessionNumber, - DateTimeOffset.Now, - this.Options.AddSessionNumberToDataMessages); + DateTimeOffset.Now); // Increment the sequence number. this.IncrementLastSequenceNumber(); diff --git a/src/SparkplugNet/Core/Node/SparkplugNodeBase.cs b/src/SparkplugNet/Core/Node/SparkplugNodeBase.cs index 0c3a795..4303843 100644 --- a/src/SparkplugNet/Core/Node/SparkplugNodeBase.cs +++ b/src/SparkplugNet/Core/Node/SparkplugNodeBase.cs @@ -259,7 +259,8 @@ private async Task ConnectInternal() this.NameSpace, this.Options.GroupIdentifier, this.Options.EdgeNodeIdentifier, - this.LastSessionNumber); + this.LastSessionNumber, + this.Options.NodeDeathQualityOfServiceLevel); // Build up the MQTT client and connect. this.Options.CancellationToken ??= SystemCancellationToken.None; @@ -267,8 +268,18 @@ private async Task ConnectInternal() var builder = new MqttClientOptionsBuilder() .WithClientId(this.Options.ClientId) .WithCredentials(this.Options.UserName, this.Options.Password) - .WithCleanSession(false) - .WithProtocolVersion(MqttProtocolVersion.V311); + .WithProtocolVersion((MqttProtocolVersion)this.Options.MqttProtocolVersion); + + switch (this.Options.MqttProtocolVersion) + { + case SparkplugMqttProtocolVersion.V311: + builder.WithCleanSession(true); + break; + case SparkplugMqttProtocolVersion.V500: + // Todo: Set clean start?! + builder.WithSessionExpiryInterval(0); + break; + } if (this.Options.UseTls) { diff --git a/src/SparkplugNet/Core/Node/SparkplugNodeOptions.cs b/src/SparkplugNet/Core/Node/SparkplugNodeOptions.cs index 600ed78..ec2896f 100644 --- a/src/SparkplugNet/Core/Node/SparkplugNodeOptions.cs +++ b/src/SparkplugNet/Core/Node/SparkplugNodeOptions.cs @@ -27,107 +27,16 @@ public class SparkplugNodeOptions : SparkplugBaseOptions /// public const string DefaultEdgeNodeIdentifier = ""; - /// - /// The default option to add session numbers to data messages. - /// - public const bool DefaultAddSessionNumberToDataMessages = true; - + // Todo: Check if we still need this. /// /// The default option to publish known device metrics on reconnect. /// public const bool DefaultPublishKnownDeviceMetricsOnReconnect = true; - /// /// - /// Initializes a new instance of the class. + /// The default quality of service level for the node death command. /// - /// - public SparkplugNodeOptions() : this(brokerAddress: DefaultBroker) - { - } - - /// - /// - /// Initializes a new instance of the class. - /// - /// The broker address. - /// The port. - /// The client identifier. - /// The name of the user. - /// The password. - /// A value indicating whether TLS is used or not. - /// The SCADA host identifier. - /// The group identifier. - /// The edge node identifier. - /// The delegate to provide TLS parameters. - /// The web socket parameters. - /// The proxy options. - /// - public SparkplugNodeOptions( - string brokerAddress = DefaultBroker, - int port = DefaultPort, - string clientId = DefaultClientId, - string userName = DefaultUserName, - string password = DefaultPassword, - bool useTls = DefaultUseTls, - string scadaHostIdentifier = DefaultScadaHostIdentifier, - string groupIdentifier = DefaultGroupIdentifier, - string edgeNodeIdentifier = DefaultEdgeNodeIdentifier, - GetTlsParametersDelegate? getTlsParameters = null, - MqttClientOptionsBuilderWebSocketParameters? webSocketParameters = null, - MqttClientWebSocketProxyOptions? proxyOptions = null) - : this(brokerAddress, port, clientId, userName, password, useTls, scadaHostIdentifier, - reconnectInterval: TimeSpan.FromSeconds(30), - groupIdentifier: groupIdentifier, - edgeNodeIdentifier: edgeNodeIdentifier, - getTlsParameters: getTlsParameters, - webSocketParameters: webSocketParameters, - proxyOptions: proxyOptions) - { - } - - /// - /// - /// Initializes a new instance of the class. - /// - /// The broker address. - /// The port. - /// The client identifier. - /// The name of the user. - /// The password. - /// A value indicating whether TLS is used or not. - /// The SCADA host identifier. - /// The group identifier. - /// The edge node identifier. - /// The reconnect interval. - /// The web socket parameters. - /// The proxy options. - /// The cancellation token. - /// - public SparkplugNodeOptions( - string brokerAddress, - int port, - string clientId, - string userName, - string password, - bool useTls, - string scadaHostIdentifier, - string groupIdentifier, - string edgeNodeIdentifier, - TimeSpan reconnectInterval, - MqttClientOptionsBuilderWebSocketParameters? webSocketParameters = null, - MqttClientWebSocketProxyOptions? proxyOptions = null, - SystemCancellationToken? cancellationToken = null) - : this(brokerAddress, port, clientId, userName, password, useTls, scadaHostIdentifier, - reconnectInterval: reconnectInterval, - groupIdentifier: groupIdentifier, - edgeNodeIdentifier: edgeNodeIdentifier, - getTlsParameters: null, - webSocketParameters: webSocketParameters, - proxyOptions: proxyOptions, - cancellationToken: cancellationToken) - { - } + public const MqttQualityOfServiceLevel DefaultNodeDeathQualityOfServiceLevel = MqttQualityOfServiceLevel.AtMostOnce; /// /// @@ -143,40 +52,47 @@ public SparkplugNodeOptions( /// The group identifier. /// The edge node identifier. /// The reconnect interval. + /// The MQTT protocol version. + /// The quality of service level for the node death message. /// The delegate to provide TLS parameters. /// The web socket parameters. /// The proxy options. /// The cancellation token. /// public SparkplugNodeOptions( - string brokerAddress, - int port, - string clientId, - string userName, - string password, - bool useTls, - string scadaHostIdentifier, - string groupIdentifier, - string edgeNodeIdentifier, - TimeSpan reconnectInterval, + string? brokerAddress = null, + int? port = null, + string? clientId = null, + string? userName = null, + string? password = null, + bool? useTls = null, + string? scadaHostIdentifier = null, + TimeSpan? reconnectInterval = null, + SparkplugMqttProtocolVersion? mqttProtocolVersion = null, GetTlsParametersDelegate? getTlsParameters = null, MqttClientOptionsBuilderWebSocketParameters? webSocketParameters = null, MqttClientWebSocketProxyOptions? proxyOptions = null, + string? groupIdentifier = null, + string? edgeNodeIdentifier = null, + MqttQualityOfServiceLevel? nodeDeathQualityOfServiceLevel = null, SystemCancellationToken? cancellationToken = null) - : base(brokerAddress: brokerAddress, - port: port, - clientId: clientId, - userName: userName, - password: password, - useTls: useTls, - scadaHostIdentifier: scadaHostIdentifier, - reconnectInterval: reconnectInterval, - getTlsParameters: getTlsParameters, - webSocketParameters: webSocketParameters, - proxyOptions: proxyOptions) + : base( + brokerAddress, + port, + clientId, + userName, + password, + useTls, + scadaHostIdentifier, + reconnectInterval, + mqttProtocolVersion, + getTlsParameters, + webSocketParameters, + proxyOptions) { - this.GroupIdentifier = groupIdentifier; - this.EdgeNodeIdentifier = edgeNodeIdentifier; + this.GroupIdentifier = string.IsNullOrWhiteSpace(groupIdentifier) ? DefaultGroupIdentifier : groupIdentifier; + this.EdgeNodeIdentifier = string.IsNullOrWhiteSpace(edgeNodeIdentifier) ? DefaultEdgeNodeIdentifier : edgeNodeIdentifier; + this.NodeDeathQualityOfServiceLevel = nodeDeathQualityOfServiceLevel ?? DefaultNodeDeathQualityOfServiceLevel; this.CancellationToken = cancellationToken ?? SystemCancellationToken.None; } @@ -192,23 +108,24 @@ public SparkplugNodeOptions( [DefaultValue(DefaultEdgeNodeIdentifier)] public string EdgeNodeIdentifier { get; set; } = DefaultEdgeNodeIdentifier; - /// - /// Gets or sets a value indicating whether to add session numbers to data messages or not. - /// - [DefaultValue(DefaultAddSessionNumberToDataMessages)] - public bool AddSessionNumberToDataMessages { get; set; } = DefaultAddSessionNumberToDataMessages; - + // Todo: Check if we still need this. /// /// Gets or sets a value indicating whether to publish known device metrics on reconnect or not. /// [DefaultValue(DefaultPublishKnownDeviceMetricsOnReconnect)] public bool PublishKnownDeviceMetricsOnReconnect { get; set; } = DefaultPublishKnownDeviceMetricsOnReconnect; + /// + /// Gets or sets the quality of service level for the node death command. + /// + [DefaultValue(DefaultNodeDeathQualityOfServiceLevel)] + public MqttQualityOfServiceLevel NodeDeathQualityOfServiceLevel { get; set; } = DefaultNodeDeathQualityOfServiceLevel; + /// /// Gets or sets the cancellation token. /// [JsonIgnore] [XmlIgnore] [Browsable(false)] - public SystemCancellationToken? CancellationToken { get; set; } + public SystemCancellationToken? CancellationToken { get; set; } = SystemCancellationToken.None; } diff --git a/src/SparkplugNet/Core/SparkplugBaseOptions.cs b/src/SparkplugNet/Core/SparkplugBaseOptions.cs index 695ab55..3956d02 100644 --- a/src/SparkplugNet/Core/SparkplugBaseOptions.cs +++ b/src/SparkplugNet/Core/SparkplugBaseOptions.cs @@ -14,11 +14,6 @@ namespace SparkplugNet.Core; /// public abstract class SparkplugBaseOptions { - /// - /// Returns a instance or null - /// - public delegate MqttClientOptionsBuilderTlsParameters? GetTlsParametersDelegate(); - /// /// The default broker. /// @@ -59,6 +54,16 @@ public abstract class SparkplugBaseOptions /// public static readonly TimeSpan DefaultReconnectInterval = TimeSpan.FromSeconds(30); + /// + /// The default MQTT protocol version. + /// + public const SparkplugMqttProtocolVersion DefaultMqttProtocolVersion = SparkplugMqttProtocolVersion.V311; + + /// + /// Returns a instance or null. + /// + public delegate MqttClientOptionsBuilderTlsParameters? GetTlsParametersDelegate(); + /// /// Initializes a new instance of the class. /// @@ -70,33 +75,36 @@ public abstract class SparkplugBaseOptions /// The password. /// A value indicating whether TLS should be used or not. /// The SCADA host identifier. + /// The MQTT protocol version. /// The delegate to provide TLS parameters. /// The web socket parameters. /// The proxy options. public SparkplugBaseOptions( - string brokerAddress, - int port, - string clientId, - string userName, - string password, - bool useTls, - string scadaHostIdentifier, - TimeSpan reconnectInterval, + string? brokerAddress = null, + int? port = null, + string? clientId = null, + string? userName = null, + string? password = null, + bool? useTls = null, + string? scadaHostIdentifier = null, + TimeSpan? reconnectInterval = null, + SparkplugMqttProtocolVersion? mqttProtocolVersion = null, GetTlsParametersDelegate? getTlsParameters = null, MqttClientOptionsBuilderWebSocketParameters? webSocketParameters = null, MqttClientWebSocketProxyOptions? proxyOptions = null) { - this.BrokerAddress = brokerAddress; - this.Port = port; - this.ClientId = clientId; - this.UserName = userName; - this.Password = password; - this.UseTls = useTls; - this.ScadaHostIdentifier = scadaHostIdentifier; - this.ReconnectInterval = reconnectInterval; + this.BrokerAddress = string.IsNullOrWhiteSpace(brokerAddress) ? DefaultBroker : brokerAddress; + this.Port = port ?? DefaultPort; + this.ClientId = string.IsNullOrWhiteSpace(clientId) ? DefaultClientId : clientId; + this.UserName = string.IsNullOrWhiteSpace(userName) ? DefaultUserName : userName; + this.Password = string.IsNullOrWhiteSpace(password) ? DefaultPassword : password; + this.UseTls = useTls ?? DefaultUseTls; + this.ScadaHostIdentifier = string.IsNullOrWhiteSpace(scadaHostIdentifier) ? DefaultScadaHostIdentifier : scadaHostIdentifier; + this.ReconnectInterval = reconnectInterval ?? DefaultReconnectInterval; + this.MqttProtocolVersion = mqttProtocolVersion ?? DefaultMqttProtocolVersion; + this.GetTlsParameters = getTlsParameters; this.WebSocketParameters = webSocketParameters; this.ProxyOptions = proxyOptions; - this.GetTlsParameters = getTlsParameters; } /// @@ -146,6 +154,20 @@ public SparkplugBaseOptions( /// public TimeSpan ReconnectInterval { get; set; } = DefaultReconnectInterval; + /// + /// Gets or sets the MQTT protocol version. + /// + [DefaultValue(DefaultMqttProtocolVersion)] + public SparkplugMqttProtocolVersion MqttProtocolVersion { get; set; } = DefaultMqttProtocolVersion; + + /// + /// Gets or sets the delegate to provide TLS parameters. + /// + [XmlIgnore] + [JsonIgnore] + [DefaultValue(null)] + public GetTlsParametersDelegate? GetTlsParameters { get; set; } + /// /// Gets or sets the WebSocket parameters. /// @@ -159,11 +181,4 @@ public SparkplugBaseOptions( [TypeConverter(typeof(ExpandableObjectConverter))] [DefaultValue(null)] public MqttClientWebSocketProxyOptions? ProxyOptions { get; set; } - - /// - /// Gets or sets the delegate to provide TLS parameter. - /// - [XmlIgnore] - [JsonIgnore] - public GetTlsParametersDelegate? GetTlsParameters { get; set; } } diff --git a/src/SparkplugNet/VersionB/SparkplugApplication.cs b/src/SparkplugNet/VersionB/SparkplugApplication.cs index 08da5dc..43ad038 100644 --- a/src/SparkplugNet/VersionB/SparkplugApplication.cs +++ b/src/SparkplugNet/VersionB/SparkplugApplication.cs @@ -62,8 +62,7 @@ protected override async Task PublishNodeCommandMessage(IEnumerable PublishMessage(IEnumerabl this.KnownMetricsStorage.FilterOutgoingMetrics(metrics), this.LastSequenceNumber, this.LastSessionNumber, - DateTimeOffset.Now, - this.Options.AddSessionNumberToDataMessages); + DateTimeOffset.Now); // Debug output. this.Logger?.Debug("NDATA Message: {@DataMessage}", dataMessage); From 8e18dfd9e8ea14f3d02c4ddced900c7cedfa2de9 Mon Sep 17 00:00:00 2001 From: SeppPenner Date: Sat, 8 Apr 2023 20:20:42 +0200 Subject: [PATCH 08/16] Removed the node death QoS level. --- .../SparkplugMessageGeneratorTest.cs | 2 +- .../Core/Messages/SparkplugMessageGenerator.cs | 13 +++++-------- src/SparkplugNet/Core/Node/SparkplugNodeBase.cs | 3 +-- src/SparkplugNet/Core/Node/SparkplugNodeOptions.cs | 13 ------------- 4 files changed, 7 insertions(+), 24 deletions(-) diff --git a/src/SparkplugNet.Tests/SparkplugMessageGeneratorTest.cs b/src/SparkplugNet.Tests/SparkplugMessageGeneratorTest.cs index d1327a4..c942dc9 100644 --- a/src/SparkplugNet.Tests/SparkplugMessageGeneratorTest.cs +++ b/src/SparkplugNet.Tests/SparkplugMessageGeneratorTest.cs @@ -141,7 +141,7 @@ public void TestDeviceDeathMessageNamespaceB() [TestMethod] public void TestNodeDeathMessageNamespaceB() { - var message = this.messageGenerator.GetSparkPlugNodeDeathMessage(SparkplugNamespace.VersionB, "group1", "edge1", 1, MqttQualityOfServiceLevel.AtMostOnce); + var message = this.messageGenerator.GetSparkPlugNodeDeathMessage(SparkplugNamespace.VersionB, "group1", "edge1", 1); var payloadVersionB = PayloadHelper.Deserialize(message.Payload); Assert.AreEqual("spBv1.0/group1/NDEATH/edge1", message.Topic); diff --git a/src/SparkplugNet/Core/Messages/SparkplugMessageGenerator.cs b/src/SparkplugNet/Core/Messages/SparkplugMessageGenerator.cs index 83cc23b..9283521 100644 --- a/src/SparkplugNet/Core/Messages/SparkplugMessageGenerator.cs +++ b/src/SparkplugNet/Core/Messages/SparkplugMessageGenerator.cs @@ -165,7 +165,6 @@ public MqttApplicationMessage GetSparkPlugDeviceBirthMessage( /// The group identifier. /// The edge node identifier. /// The session number. - /// The quality of service level. /// Thrown if the group identifier or the edge node identifier is invalid. /// Thrown if the namespace is out of range. /// A new NDEATH . @@ -173,8 +172,7 @@ public MqttApplicationMessage GetSparkPlugNodeDeathMessage( SparkplugNamespace nameSpace, string groupIdentifier, string edgeNodeIdentifier, - long sessionNumber, - MqttQualityOfServiceLevel qualityOfServiceLevel) + long sessionNumber) { if (!groupIdentifier.IsIdentifierValid()) { @@ -192,7 +190,7 @@ public MqttApplicationMessage GetSparkPlugNodeDeathMessage( { var metrics = new List(); return this.GetSparkPlugNodeDeathB(nameSpace, groupIdentifier, edgeNodeIdentifier, - AddSessionNumberToMetrics(metrics, sessionNumber), qualityOfServiceLevel); + AddSessionNumberToMetrics(metrics, sessionNumber)); } default: @@ -609,14 +607,12 @@ private MqttApplicationMessage GetSparkPlugDeviceBirthB( /// The group identifier. /// The edge node identifier. /// The metrics. - /// The quality of service level. /// A new NDEATH . private MqttApplicationMessage GetSparkPlugNodeDeathB( SparkplugNamespace nameSpace, string groupIdentifier, string edgeNodeIdentifier, - IEnumerable metrics, - MqttQualityOfServiceLevel qualityOfServiceLevel) + IEnumerable metrics) { var payload = new VersionBData.Payload { @@ -638,7 +634,8 @@ private MqttApplicationMessage GetSparkPlugNodeDeathB( edgeNodeIdentifier, string.Empty)) .WithPayload(serialized) - .WithQualityOfServiceLevel(qualityOfServiceLevel) + .WithQualityOfServiceLevel(MqttQualityOfServiceLevel.AtLeastOnce) + .WithRetainFlag(false) .Build(); } diff --git a/src/SparkplugNet/Core/Node/SparkplugNodeBase.cs b/src/SparkplugNet/Core/Node/SparkplugNodeBase.cs index 4303843..f2e2fd5 100644 --- a/src/SparkplugNet/Core/Node/SparkplugNodeBase.cs +++ b/src/SparkplugNet/Core/Node/SparkplugNodeBase.cs @@ -259,8 +259,7 @@ private async Task ConnectInternal() this.NameSpace, this.Options.GroupIdentifier, this.Options.EdgeNodeIdentifier, - this.LastSessionNumber, - this.Options.NodeDeathQualityOfServiceLevel); + this.LastSessionNumber); // Build up the MQTT client and connect. this.Options.CancellationToken ??= SystemCancellationToken.None; diff --git a/src/SparkplugNet/Core/Node/SparkplugNodeOptions.cs b/src/SparkplugNet/Core/Node/SparkplugNodeOptions.cs index ec2896f..65c82b4 100644 --- a/src/SparkplugNet/Core/Node/SparkplugNodeOptions.cs +++ b/src/SparkplugNet/Core/Node/SparkplugNodeOptions.cs @@ -33,11 +33,6 @@ public class SparkplugNodeOptions : SparkplugBaseOptions /// public const bool DefaultPublishKnownDeviceMetricsOnReconnect = true; - /// - /// The default quality of service level for the node death command. - /// - public const MqttQualityOfServiceLevel DefaultNodeDeathQualityOfServiceLevel = MqttQualityOfServiceLevel.AtMostOnce; - /// /// /// Initializes a new instance of the class. @@ -53,7 +48,6 @@ public class SparkplugNodeOptions : SparkplugBaseOptions /// The edge node identifier. /// The reconnect interval. /// The MQTT protocol version. - /// The quality of service level for the node death message. /// The delegate to provide TLS parameters. /// The web socket parameters. /// The proxy options. @@ -92,7 +86,6 @@ public SparkplugNodeOptions( { this.GroupIdentifier = string.IsNullOrWhiteSpace(groupIdentifier) ? DefaultGroupIdentifier : groupIdentifier; this.EdgeNodeIdentifier = string.IsNullOrWhiteSpace(edgeNodeIdentifier) ? DefaultEdgeNodeIdentifier : edgeNodeIdentifier; - this.NodeDeathQualityOfServiceLevel = nodeDeathQualityOfServiceLevel ?? DefaultNodeDeathQualityOfServiceLevel; this.CancellationToken = cancellationToken ?? SystemCancellationToken.None; } @@ -115,12 +108,6 @@ public SparkplugNodeOptions( [DefaultValue(DefaultPublishKnownDeviceMetricsOnReconnect)] public bool PublishKnownDeviceMetricsOnReconnect { get; set; } = DefaultPublishKnownDeviceMetricsOnReconnect; - /// - /// Gets or sets the quality of service level for the node death command. - /// - [DefaultValue(DefaultNodeDeathQualityOfServiceLevel)] - public MqttQualityOfServiceLevel NodeDeathQualityOfServiceLevel { get; set; } = DefaultNodeDeathQualityOfServiceLevel; - /// /// Gets or sets the cancellation token. /// From 011b870127d8993739bac6891b8548b6211fe704 Mon Sep 17 00:00:00 2001 From: SeppPenner Date: Sat, 8 Apr 2023 20:21:38 +0200 Subject: [PATCH 09/16] Removed the node death QoS level. --- src/SparkplugNet.Examples/Program.cs | 1 - src/SparkplugNet/Core/Node/SparkplugNodeOptions.cs | 1 - 2 files changed, 2 deletions(-) diff --git a/src/SparkplugNet.Examples/Program.cs b/src/SparkplugNet.Examples/Program.cs index 9714405..deebb44 100644 --- a/src/SparkplugNet.Examples/Program.cs +++ b/src/SparkplugNet.Examples/Program.cs @@ -191,7 +191,6 @@ private static async Task RunVersionBNode() null, "group1", "node1", - MqttQualityOfServiceLevel.AtMostOnce, CancellationTokenSource.Token); var node = new VersionB.SparkplugNode(VersionBMetricsNode, Log.Logger); diff --git a/src/SparkplugNet/Core/Node/SparkplugNodeOptions.cs b/src/SparkplugNet/Core/Node/SparkplugNodeOptions.cs index 65c82b4..be98da8 100644 --- a/src/SparkplugNet/Core/Node/SparkplugNodeOptions.cs +++ b/src/SparkplugNet/Core/Node/SparkplugNodeOptions.cs @@ -68,7 +68,6 @@ public SparkplugNodeOptions( MqttClientWebSocketProxyOptions? proxyOptions = null, string? groupIdentifier = null, string? edgeNodeIdentifier = null, - MqttQualityOfServiceLevel? nodeDeathQualityOfServiceLevel = null, SystemCancellationToken? cancellationToken = null) : base( brokerAddress, From 5d5a09d64d49b19c1bfde5bf81a3417cfaa93935 Mon Sep 17 00:00:00 2001 From: SeppPenner Date: Sat, 8 Apr 2023 21:05:05 +0200 Subject: [PATCH 10/16] Smaller changes. --- .../Core/Extensions/DataTypeExtensions.cs | 78 ++++++++++--------- src/SparkplugNet/GlobalUsings.cs | 1 + 2 files changed, 44 insertions(+), 35 deletions(-) diff --git a/src/SparkplugNet/Core/Extensions/DataTypeExtensions.cs b/src/SparkplugNet/Core/Extensions/DataTypeExtensions.cs index ea1af05..4b19067 100644 --- a/src/SparkplugNet/Core/Extensions/DataTypeExtensions.cs +++ b/src/SparkplugNet/Core/Extensions/DataTypeExtensions.cs @@ -1,45 +1,53 @@ -namespace SparkplugNet.Core.Extensions -{ - using SparkplugNet.VersionB.Data; +// -------------------------------------------------------------------------------------------------------------------- +// +// The project is licensed under the MIT license. +// +// +// A class that contains data type extension methods. +// +// -------------------------------------------------------------------------------------------------------------------- + +namespace SparkplugNet.Core.Extensions; +/// +/// A class that contains data type extension methods. +/// +internal static class DataTypeExtensions +{ /// - /// A class that contains data type extension methods. + /// Converts the value to type T. /// - internal static class DataTypeExtensions + /// The type parameter. + /// The object value. + /// The converted value. + public static T? ConvertTo(this object? objValue) { - /// - /// Converts the value to type T - /// - /// - /// The object value. - /// The converted value. - public static T? ConvertTo(this object? objValue) + if (objValue is null) { - if (objValue == null) - return default; - - return objValue is T valueAsT - ? valueAsT - : (T)Convert.ChangeType(objValue, typeof(T)); + return default; } - /// - /// Converts the value to type T or uses a default value - /// - /// - /// - /// The converted or default value. - public static T ConvertOrDefaultTo(this object? objValue) - { - T? value = objValue.ConvertTo(); + return objValue is T valueAsT + ? valueAsT + : (T)Convert.ChangeType(objValue, typeof(T)); + } - return value != null ? value - : typeof(T) == typeof(string) ? (T)(object)string.Empty - : typeof(T) == typeof(byte[]) ? (T)(object)Array.Empty() - : typeof(T) == typeof(DataSet) ? (T)(object)new DataSet() - : typeof(T) == typeof(Template) ? (T)(object)new Template() - : typeof(T) == typeof(PropertySet) ? (T)(object)new PropertySet() - : (T)(object)new(); // Last Resort - } + /// + /// Converts the value to type T or uses a default value. + /// + /// The type parameter. + /// The object value. + /// The converted or default value. + public static T ConvertOrDefaultTo(this object? objValue) + { + T? value = objValue.ConvertTo(); + + return value is not null ? value + : typeof(T) == typeof(string) ? (T)(object)string.Empty + : typeof(T) == typeof(byte[]) ? (T)(object)Array.Empty() + : typeof(T) == typeof(DataSet) ? (T)(object)new DataSet() + : typeof(T) == typeof(Template) ? (T)(object)new Template() + : typeof(T) == typeof(PropertySet) ? (T)(object)new PropertySet() + : (T)(object)new(); // Last Resort } } diff --git a/src/SparkplugNet/GlobalUsings.cs b/src/SparkplugNet/GlobalUsings.cs index 3b18843..3180424 100644 --- a/src/SparkplugNet/GlobalUsings.cs +++ b/src/SparkplugNet/GlobalUsings.cs @@ -30,6 +30,7 @@ global using SparkplugNet.Core.Messages; global using SparkplugNet.Core.Node; global using SparkplugNet.Core.Topics; +global using SparkplugNet.VersionB.Data; global using VersionBData = SparkplugNet.VersionB.Data; global using VersionBDataTypeEnum = SparkplugNet.VersionB.Data.DataType; From ffe4bb569b58f96a6e8ebdbb69034c092c8daffe Mon Sep 17 00:00:00 2001 From: SeppPenner Date: Sat, 8 Apr 2023 21:05:23 +0200 Subject: [PATCH 11/16] Added option for strict identifier checking. --- .../Core/Extensions/StringExtensions.cs | 11 ++++++++++ src/SparkplugNet/Core/SparkplugGlobals.cs | 22 +++++++++++++++++++ 2 files changed, 33 insertions(+) create mode 100644 src/SparkplugNet/Core/SparkplugGlobals.cs diff --git a/src/SparkplugNet/Core/Extensions/StringExtensions.cs b/src/SparkplugNet/Core/Extensions/StringExtensions.cs index 7ebf5fb..cacd57b 100644 --- a/src/SparkplugNet/Core/Extensions/StringExtensions.cs +++ b/src/SparkplugNet/Core/Extensions/StringExtensions.cs @@ -14,6 +14,12 @@ namespace SparkplugNet.Core.Extensions; /// internal static class StringExtensions { + /// + /// The strict identifiers. + /// + private static readonly string[] strictIdentifers = new[] { ".", ",", "\\", "@", "#", "$", "%", "^", "&", "*", "(", "", "", ")", "[", "]", + "{", "}", "|", "!", "`", "~", ":", ";", "'", "\"", "<", ">", "?", "/", "+" }; + /// /// Checks whether the given identifier is valid or not. /// @@ -21,6 +27,11 @@ internal static class StringExtensions /// A value indicating whether the identifier is valid or not. internal static bool IsIdentifierValid(this string value) { + if (SparkplugGlobals.UseStrictIdentifierChecking) + { + return string.IsNullOrWhiteSpace(value) && strictIdentifers.Any(value.Contains); + } + return !string.IsNullOrWhiteSpace(value) && !value.Contains('/') && !value.Contains('#') && !value.Contains('+'); } } diff --git a/src/SparkplugNet/Core/SparkplugGlobals.cs b/src/SparkplugNet/Core/SparkplugGlobals.cs new file mode 100644 index 0000000..4ef6d57 --- /dev/null +++ b/src/SparkplugNet/Core/SparkplugGlobals.cs @@ -0,0 +1,22 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// The project is licensed under the MIT license. +// +// +// A class that contains global settings. +// +// -------------------------------------------------------------------------------------------------------------------- + +namespace SparkplugNet.Core; + +/// +/// A class that contains global settings. +/// +public static class SparkplugGlobals +{ + /// + /// Gets or sets a value indicating whether strict identifier checking is enabled or not. + /// This prevents users from using the following chars in identifiers like .,\@#$%^&*()[]{}|!`~:;'"<>? + /// + public static bool UseStrictIdentifierChecking { get; set; } +} From 77711d2133f7b7e99d80c5481262638273c81b59 Mon Sep 17 00:00:00 2001 From: SeppPenner Date: Sat, 8 Apr 2023 21:08:13 +0200 Subject: [PATCH 12/16] Added no warn for non HTTPS NuGet sources. --- .../SparkplugNet.Examples.csproj | 35 ++++++------- .../SparkplugNet.Tests.csproj | 49 ++++++++++--------- src/SparkplugNet/Core/SparkplugGlobals.cs | 2 +- 3 files changed, 44 insertions(+), 42 deletions(-) diff --git a/src/SparkplugNet.Examples/SparkplugNet.Examples.csproj b/src/SparkplugNet.Examples/SparkplugNet.Examples.csproj index c8360ae..5e33598 100644 --- a/src/SparkplugNet.Examples/SparkplugNet.Examples.csproj +++ b/src/SparkplugNet.Examples/SparkplugNet.Examples.csproj @@ -1,23 +1,24 @@ - - Exe - net7.0 - latest - enable - enable - + + Exe + net7.0 + latest + enable + enable + NU1803 + - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + - - - + + + diff --git a/src/SparkplugNet.Tests/SparkplugNet.Tests.csproj b/src/SparkplugNet.Tests/SparkplugNet.Tests.csproj index d01aa8f..b73167e 100644 --- a/src/SparkplugNet.Tests/SparkplugNet.Tests.csproj +++ b/src/SparkplugNet.Tests/SparkplugNet.Tests.csproj @@ -1,30 +1,31 @@ - - Library - net7.0 - latest - enable - enable - + + Library + net7.0 + latest + enable + enable + NU1803 + - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + - - - + + + diff --git a/src/SparkplugNet/Core/SparkplugGlobals.cs b/src/SparkplugNet/Core/SparkplugGlobals.cs index 4ef6d57..f8c11a4 100644 --- a/src/SparkplugNet/Core/SparkplugGlobals.cs +++ b/src/SparkplugNet/Core/SparkplugGlobals.cs @@ -16,7 +16,7 @@ public static class SparkplugGlobals { /// /// Gets or sets a value indicating whether strict identifier checking is enabled or not. - /// This prevents users from using the following chars in identifiers like .,\@#$%^&*()[]{}|!`~:;'"<>? + /// This prevents users from using the following chars in identifiers like .,\@#$%^&*()[]{}|!`~:;'"<>? /// public static bool UseStrictIdentifierChecking { get; set; } } From c395204509a70066f895cadf26e5b63eebbbd3c1 Mon Sep 17 00:00:00 2001 From: SeppPenner Date: Sat, 8 Apr 2023 21:08:22 +0200 Subject: [PATCH 13/16] Added no warn for non HTTPS NuGet sources. --- src/SparkplugNet/SparkplugNet.csproj | 1 + 1 file changed, 1 insertion(+) diff --git a/src/SparkplugNet/SparkplugNet.csproj b/src/SparkplugNet/SparkplugNet.csproj index 847ccdc..f95aac2 100644 --- a/src/SparkplugNet/SparkplugNet.csproj +++ b/src/SparkplugNet/SparkplugNet.csproj @@ -25,6 +25,7 @@ true snupkg enable + NU1803 From 45cbee31f51e227e602400eed461c9e8ebed383e Mon Sep 17 00:00:00 2001 From: SeppPenner Date: Sat, 8 Apr 2023 21:09:51 +0200 Subject: [PATCH 14/16] Updated readme. --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index d7078d8..b6962bb 100644 --- a/README.md +++ b/README.md @@ -57,7 +57,8 @@ For basic usage, see the [How to use file](./HowToUse.md) or the [example projec * [MQTT.fx](http://www.mqttfx.jensd.de/) has a Sparkplug data decoder. The binaries for version 1.7.1 can also be taken from https://github.com/SeppPenner/mqttfx171-backup (The software is now under development by a company and requires a license for version 1.7.1+). ## Supported Sparkplug standards -* Version 2.2, spAv1.0 and spBv1.0. +* Version 1.3.0 and above: Sparkplug, version 3.0, spBv1.0. +* Version 1.2.0 and below: Sparkplug, version 2.2, spAv1.0 and spBv1.0. ## Special notes * Version 1.1.0 introduces the async event pattern and deprecates the "old, synchronous" events, Version 1.2.0+ will remove the old events completely. (BREAKING) From 48be51500d58da8a89c4589e1eb748572ac65c02 Mon Sep 17 00:00:00 2001 From: SeppPenner Date: Wed, 12 Apr 2023 11:22:10 +0200 Subject: [PATCH 15/16] Added setting of clean start option for the MQTT version 5, fixes https://github.com/SeppPenner/SparkplugNet/issues/46. --- src/SparkplugNet/Core/Application/SparkplugApplicationBase.cs | 3 ++- src/SparkplugNet/Core/Node/SparkplugNodeBase.cs | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/SparkplugNet/Core/Application/SparkplugApplicationBase.cs b/src/SparkplugNet/Core/Application/SparkplugApplicationBase.cs index 8c0c76d..4e49b89 100644 --- a/src/SparkplugNet/Core/Application/SparkplugApplicationBase.cs +++ b/src/SparkplugNet/Core/Application/SparkplugApplicationBase.cs @@ -361,7 +361,8 @@ private async Task ConnectInternal() builder.WithCleanSession(true); break; case SparkplugMqttProtocolVersion.V500: - // Todo: Set clean start?! + // Todo: Use WithCleanStart when available from release build! + builder.WithCleanSession(true); builder.WithSessionExpiryInterval(0); break; } diff --git a/src/SparkplugNet/Core/Node/SparkplugNodeBase.cs b/src/SparkplugNet/Core/Node/SparkplugNodeBase.cs index f2e2fd5..a1f8c8c 100644 --- a/src/SparkplugNet/Core/Node/SparkplugNodeBase.cs +++ b/src/SparkplugNet/Core/Node/SparkplugNodeBase.cs @@ -275,7 +275,8 @@ private async Task ConnectInternal() builder.WithCleanSession(true); break; case SparkplugMqttProtocolVersion.V500: - // Todo: Set clean start?! + // Todo: Use WithCleanStart when available from release build! + builder.WithCleanSession(true); builder.WithSessionExpiryInterval(0); break; } From 1929a1254c570b7fc32bd9cd7eeaa42b84617b5e Mon Sep 17 00:00:00 2001 From: Tim Marius Joehnk Date: Fri, 21 Apr 2023 10:37:14 +0200 Subject: [PATCH 16/16] Fixed bdseq is always 0 bdseq metric datatype (long) and metric property (ulong) did not match due to changes with signed numerics --- src/SparkplugNet/Core/Messages/SparkplugMessageGenerator.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/SparkplugNet/Core/Messages/SparkplugMessageGenerator.cs b/src/SparkplugNet/Core/Messages/SparkplugMessageGenerator.cs index f16d287..a66b4b0 100644 --- a/src/SparkplugNet/Core/Messages/SparkplugMessageGenerator.cs +++ b/src/SparkplugNet/Core/Messages/SparkplugMessageGenerator.cs @@ -586,7 +586,7 @@ public static MqttApplicationMessage GetSparkPlugDeviceCommandMessage( { Name = Constants.SessionNumberMetricName, ULongValue = (ulong)sessionSequenceNumber, - ValueCase = (uint)VersionBData.DataType.Int64 + ValueCase = (uint)VersionBData.DataType.UInt64 } }); }