SparkplugNet icon indicating copy to clipboard operation
SparkplugNet copied to clipboard

Negative integer set value

Open petrosinoE80 opened this issue 1 year ago • 3 comments

Hey there, while testing the NuGet 1.3.8 update, I noticed that I'm no longer receiving messages with negative integers in the MQTT broker side.

Here's an example:


Metric metric = new()
{
	Name = "Test",
	Timestamp = timestamp_var
};

Int32 negativeInt = -1;

metric.SetValue(DataType.Int32, negativeInt);

In previous versions of the NuGet, I had a workaround where I casted the data to Float, but now I'm still not getting anything. Is this a known issue? Any possible solutions?

Thanks in advance for all the efforts you put into improving this fantastic NuGet.

petrosinoE80 avatar Apr 16 '24 12:04 petrosinoE80

I guess, this can't be fixed with version 3 anymore and is a known issue within Sparkplug still: https://github.com/eclipse/tahu/issues/71, https://github.com/eclipse-sparkplug/sparkplug/issues/114 and https://github.com/eclipse-sparkplug/sparkplug/issues/62.

I have seen this issue coming since I saw version 3 of the Sparkplug spec in detail. I have not yet a good idea on how to handle this except maybe to use the byte array with custom encoding / mapping on the client side. This is stupid if you ask me...

SeppPenner avatar Apr 22 '24 18:04 SeppPenner

Hi, thank you very much for addressing this issue. I'm also struggling with this right now and I'm trying to find a possible workaround.

When I try to send -1 int on version 1.3.8, I get OverflowException.

System.OverflowException: Value was either too large or too small for a UInt32.
   at System.Convert.ThrowUInt32OverflowException()
   at System.Int32.System.IConvertible.ToUInt32(IFormatProvider provider)
   at System.Convert.ChangeType(Object value, Type conversionType, IFormatProvider provider)
   at System.Convert.ChangeType(Object value, Type conversionType)
   at SparkplugNet.Core.Extensions.DataTypeExtensions.ConvertTo[T](Object objValue)
   at SparkplugNet.Core.Extensions.DataTypeExtensions.ConvertOrDefaultTo[T](Object objValue)
   at SparkplugNet.VersionB.PayloadConverter.ConvertVersionBMetric(Metric metric)
   at System.Linq.Enumerable.SelectListIterator`2.ToList()
   at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
   at SparkplugNet.VersionB.PayloadConverter.ConvertVersionBPayload(Payload payload)
   at SparkplugNet.Core.Messages.SparkplugMessageGenerator.GetSparkplugNodeDataB(SparkplugNamespace nameSpace, String groupIdentifier, String edgeNodeIdentifier, IEnumerable`1 metrics, Int32 sequenceNumber, DateTimeOffset dateTime)
   at SparkplugNet.Core.Messages.SparkplugMessageGenerator.GetSparkplugNodeDataMessage[T](SparkplugNamespace nameSpace, String groupIdentifier, String edgeNodeIdentifier, IEnumerable`1 metrics, Int32 sequenceNumber, Int64 sessionNumber, DateTimeOffset dateTime)
   at SparkplugNet.VersionB.SparkplugNode.PublishMessage(IEnumerable`1 metrics)
   at SparkplugNet.Core.Node.SparkplugNodeBase`1.PublishMetrics(IEnumerable`1 metrics)

As far as I can tell, the correct approach for sending negative values with the current sparkplug specification is the following:

  • Set correct Metric.datatype field e.g. Int32
  • Cast the INT32 Value, for example “-32” to UINT32, e.g. “4294967264”
  • Add the converted value as metric.int_value
  • Send via MQTT

I have seen this described here and here and have tested it using Node-RED. Looks like it is working well.

Update: I have tested this approach with AVEVA System Platform MQTT driver and it interprets 4294967264 with Int32 datatype correctly as -32.

Could this logic be part of SparkplugNet?

faramart avatar May 09 '24 15:05 faramart

It seems like C# doesn't convert the types properly with Convert...

SeppPenner avatar May 13 '24 16:05 SeppPenner

This is basically just:

int intValue = -32;
uint uintValue = unchecked((uint)intValue);
Console.WriteLine(uintValue);

SeppPenner avatar Jul 02 '24 13:07 SeppPenner

I have updated the tests and nearly fixed this in https://github.com/SeppPenner/SparkplugNet/commit/d3ff29bd4c26c35c8cf963955a7105349177e0c1. However, the conversions back from https://github.com/SeppPenner/SparkplugNet/blob/d3ff29bd4c26c35c8cf963955a7105349177e0c1/src/SparkplugNet/VersionB/PayloadConverter.cs#L219 and https://github.com/SeppPenner/SparkplugNet/blob/d3ff29bd4c26c35c8cf963955a7105349177e0c1/src/SparkplugNet/VersionB/PayloadConverter.cs#L224 don't work yet properly. Feel free to share your thoughts, I don't see the issue here yet...

SeppPenner avatar Jul 02 '24 15:07 SeppPenner

This code is crazy now: https://github.com/SeppPenner/SparkplugNet/blob/758b561206807f8c46ee11e6594054ce3ca75ff8/src/SparkplugNet/Core/Extensions/DataTypeExtensions.cs#L1 :D

SeppPenner avatar Jul 02 '24 16:07 SeppPenner

Thank you for the changes. ❤ It is working ok for my use case and I'm able to send negative values without any issue.

faramart avatar Aug 16 '24 13:08 faramart