FreeOpcUa/opcua-asyncio

Bulk reading node attributes causes disconnect

Closed this issue · 0 comments

Hi, so I've written a python program that connects to an SPS 1200 OPC UA Server and browses the node structure.
I want to read some node attributes after browsing the complete node structure starting with the objects node.
I've tried using the asyncio taskgroups for that since this really speeds up the process but I ran into the problem where the connection to the server would get disconnected.

My code:

async def gahter_node_data(self):

  nodes = [] # <- List of Nodes

  async with asyncio.TaskGroup() as group:
    tasks = [group.create_task(self._collect_node_data(unbrowsed_node)) for unbrowsed_node in nodes]

  
  # Iterate over results
  for task in tasks:
    # Get result from task
    task.result()

async def _collect_node_data(self, node:Node):

        # Define required attributes
        required_attributes = [
            AttributeIds.BrowseName,
            AttributeIds.DisplayName,
            AttributeIds.NodeClass,
            AttributeIds.DataType,
            AttributeIds.AccessLevel,
            AttributeIds.ArrayDimensions
            ]

        # Bulk request all attributes
        node_attributes:List[ua.DataValue] = await node.read_attributes(required_attributes)

When I execute the code I get the following error:

Traceback (most recent call last):
    |   File "/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/asyncio/tasks.py", line 490, in wait_for
    |     return fut.result()
    |            ^^^^^^^^^^^^
    | asyncio.exceptions.CancelledError
    | 
    | The above exception was the direct cause of the following exception:
    | 
    | Traceback (most recent call last):
    |   File "...", in _collect_node_data
    |     node_attributes:List[ua.DataValue] = await node.read_attributes(required_attributes)
    |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |   File ".../Python/3.11/lib/python/site-packages/asyncua/common/node.py", line 359, in read_attributes
    |     results = await self.session.read(params)
    |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |   File ".../Python/3.11/lib/python/site-packages/asyncua/client/ua_client.py", line 404, in read
    |     data = await self.protocol.send_request(request)
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |   File ".../Python/3.11/lib/python/site-packages/asyncua/client/ua_client.py", line 167, in send_request
    |     data = await asyncio.wait_for(self._send_request(request, timeout, message_type), timeout if timeout else None)
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |   File "/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/asyncio/tasks.py", line 492, in wait_for
    |     raise exceptions.TimeoutError() from exc
    | TimeoutError

When I iterate over each node and call the _collect_node_data()function it works fine but can take very long when gathering data from many nodes.

Is there a better or an intended way of doing this kind of operation?