Azure / Industrial-IoT

Azure Industrial IoT Platform
MIT License
521 stars 214 forks source link

Setting Heartbeat Interval with API is using milliseconds instead of seconds #2292

Closed kappa-lhirsch closed 1 month ago

kappa-lhirsch commented 1 month ago

Hello, I'm using the publisher module und web api with version 2.9.2. When I'm publishing a node I set the PublishingInterval, SamplingInterval andHeartbeatInterval to a string of the format: [d.]hh:mm:ss[.ffffff] like written in the documentation.

The backend converts this timespan string to milliseconds, eg. '00:01:00' to '60000' milliseconds. However since the HeartbeatInterval is configured in seconds, I'm not sure why this is different but hey, the resulting Interval is 60000 seconds aka '16h and 40minutes'. So the HeartbeatInterval is off by a factor of 1000!!

Also when reading the published nodes, the api returns 00:01:00 although it's 60000 seconds, you can look it up in the config file. After restarting the module and reading the published nodes again, the api returns the "correct" 16:40:00.

To Reproduce Steps to reproduce the behavior:

  1. Install publisher V2.9.2
  2. Publish a node with a heartbeat interval

Expected behavior HeartbeatInterval is interpreted properly.

kappa-lhirsch commented 1 month ago

Will this be fixed?

marcschier commented 1 month ago

I need to first repro. You can help me if you can confirm this is an issue on 2.9.9 (last release). But this is something I would do hopefully this week.

marcschier commented 1 month ago

I re-read what you are doing, you set the HeartbeatInterval to a string? It is a number value, which is the number of seconds. There is a HeartbeatIntervalTimespan property that you must use if you want to specify a duration string. Can you confirm/post the request you are sending and the endpoint you are sending to? If this is a doc issue, can you point me to it?

kappa-lhirsch commented 1 month ago

image The swagger docs, and also the docs on github, define the 'HeartbeatInterval' as string($date-span)

The request I make is the following: POST https://{{OPC-SERVICEURL}}/publisher/v2/publish/{{endpointId}}/start Payload:

{
    "item": {
        "nodeId": "{{nodeId}}",
        "publishingInterval": "00:01:00",
        "samplingInterval": "00:01:00",
        "heartbeatInterval": "00:01:00"
    },
    "header": {
        "elevation": {
            "type": "UserName",
            "value": {
                "user": "{{user}}",
                "password": "{{password}}"
            }
        },
        "namespaceFormat": "Uri"
    }
}

You can see the HeartbeatInterval is the same as the Publishing- and SamplingInterval. After this request the config file shows the following:

{
        "Id": "{{nodeId}}",
        "OpcPublishingInterval": 60000,
        "HeartbeatInterval": 60000,
        "OpcSamplingInterval": 60000
}

The HeartbeatInterval is set to '60000' which is not correct since it should be 60.

kappa-lhirsch commented 1 month ago

I tested it with V2.9.9 and the problem still exists.

marcschier commented 1 month ago

Thank you so much, now I understand better, you are using the start/stop API. Thanks for the details! And thanks for re-testing.

kappa-lhirsch commented 1 month ago

I think a found the problem. TotalMilliseconds is used instead of TotalSeconds: https://github.com/Azure/Industrial-IoT/blob/2.9.9/src/Azure.IIoT.OpcUa.Publisher/src/Storage/PublishedNodesConverter.cs#L218

marcschier commented 1 month ago

Great find, yes, I also just fixed this in the open pull request and added unit tests for this API.