FreeOpcUa/opcua-asyncio

SourceTimeStamp is identical to ServerTimeStamp

Closed this issue · 1 comments

Describe the bug

When subscribing to a node component on an OPCUA server the SourceTimeStamp is identical to the ServerTimeStamp. When viewing the data with UaExpert or similar software these two are different. The same goes for logging these values with these softwares.

To Reproduce

  • Setup a server with a node that recieves data with a source timestamp (Double data type) in batch. The time difference between each data point is 2 minutes while the transmission frequency is 1 hour (so every hour 30 values are sent).
    bilde
  • Subscribe to the node using the example subscribe client supplied here (with username and password in my case)
  • View the logged output.

The used code

#%%
import asyncio
import logging

from asyncua import Client, Node, ua

logging.basicConfig(level=logging.INFO)
_logger = logging.getLogger("asyncua")


class SubscriptionHandler:
    """
    The SubscriptionHandler is used to handle the data that is received for the subscription.
    """

    def datachange_notification(self, node: Node, val, data):
        """
        Callback for asyncua Subscription.
        This method will be called when the Client received a data change message from the Server.
        """
        server_timestamp = data.monitored_item.Value.ServerTimestamp
        source_timestamp = data.monitored_item.Value.SourceTimestamp
        print(f"Server Timestamp: {server_timestamp}")
        print(f"Source Timestamp: {source_timestamp}")
        _logger.info("datachange_notification %r %s", node, val)


async def main(url,username,password):
    """
    Main task of this Client-Subscription example.
    """
    node_addresses = ["ns=2;s=DL_01.NI_0094.HValue"]
    client = Client(url)
    client.set_user(username)
    client.set_password(password)
    async with client:
        nodes = [client.get_node(address) for address in node_addresses]
        var = nodes[0]
        handler = SubscriptionHandler()
        # We create a Client Subscription.
        subscription = await client.create_subscription(500, handler)
        nodes = [
            var,
            client.get_node(ua.ObjectIds.Server_ServerStatus_CurrentTime),
        ]
        # We subscribe to data changes for two nodes (variables).
        await subscription.subscribe_data_change(nodes)
        # We let the subscription run for ten seconds
        await asyncio.sleep(4)
        # We delete the subscription (this un-subscribes from the data changes of the two variables).
        # This is optional since closing the connection will also delete all subscriptions.
        await subscription.delete()
        # After one second we exit the Client context manager - this will close the connection.
        await asyncio.sleep(1)

#%%
if __name__ == "__main__":
    url = "opc.tcp://servername:4840"
    username = "*******"
    password = "*******"
    await main(url,username,password)

Some example output from my testing

INFO:asyncua.common.subscription:Publish callback called with result: PublishResult(SubscriptionId=3367183, AvailableSequenceNumbers=[7], MoreNotifications=False, NotificationMessage_=NotificationMessage(SequenceNumber=7, 
PublishTime=datetime.datetime(2024, 12, 3, 10, 53, 0, 834848, tzinfo=datetime.timezone.utc), NotificationData=[DataChangeNotification(MonitoredItems=[MonitoredItemNotification(ClientHandle=202, Value=DataValue(Value=Variant(
Value=datetime.datetime(2024, 12, 3, 10, 53, 0, 802766, tzinfo=datetime.timezone.utc), VariantType=<VariantType.DateTime: 13>, Dimensions=None, is_array=False), StatusCode_=StatusCode(value=0), 
SourceTimestamp=datetime.datetime(2024, 12, 3, 10, 53, 0, 802766, tzinfo=datetime.timezone.utc),
ServerTimestamp=datetime.datetime(2024, 12, 3, 10, 53, 0, 802766, tzinfo=datetime.timezone.utc), SourcePicoseconds=None, ServerPicoseconds=None))], DiagnosticInfos=[])]), Results=[StatusCode(value=0)], DiagnosticInfos=[])
INFO:asyncua:datachange_notification Node(NodeId(Identifier=2258, NamespaceIndex=0, NodeIdType=<NodeIdType.FourByte: 1>))
2024-12-03 10:53:00.802766+00:00 2024-12-03 10:53:00.802766+00:00

Expected behavior

The data recieved by the server has the Source timestamps with 2 minute difference, but the recieved data with the python client shows the SourceTimeStamp as identical with the ServerTimeStamp.

Screenshots

The data logged using UaExports data logger view shows the logged timestamps being different (expected behavior).
bilde

Printout of the python opcua clients subscribe timestamps.
bilde

Version

Python-Version:

3.11.7
opcua-asyncio Version (e.g. master branch, 0.9):
asyncua == 1.1.5

nvm, i was being a silly goose and didn't realize i passed the ua.ObjectIds.Server_ServerStatus_CurrentTime alongside the node i was interested in.