thingsboard-gateway icon indicating copy to clipboard operation
thingsboard-gateway copied to clipboard

Opuca Connector : QualifiedName constructor args have wrong types

Open khelef opened this issue 7 months ago • 7 comments

I created an opcua server using python opcua library, I used the opcua.json config

I got this error:

2025-05-15 10:58:47.118 - |ERROR| - [tb_logger.py] - tb_logger - exception - 182 - QualifiedName constructor args have wrong types, QualifiedName(NamespaceIndex=0, Name={'path': '0:Objects', 'node': Node(NodeId(Identifier=85, NamespaceIndex=0, NodeIdType=<NodeIdType.Numeric: 2>))}) Traceback (most recent call last): File "C:\code\integration\myenv\Lib\site-packages\thingsboard_gateway\connectors\opcua\opcua_connector.py", line 613, in _get_device_info_by_pattern var = await self.__client.nodes.root.get_child(node) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\code\integration\myenv\Lib\site-packages\asyncua\common\node.py", line 613, in get_child

khelef avatar May 15 '25 12:05 khelef

Hi @khelef,

Thank you for your interest in ThingsBoard IoT Gtaeway. It looks like some issue with retrieving root node from your server. Unfortunately it is difficult to say what is wrong without having the code of your server and configuration for OPC UA connector. We also using freeopcua for our demo server, you can find the code in the container. https://hub.docker.com/r/thingsboard/tb-gw-opcua-server

imbeacon avatar May 16 '25 03:05 imbeacon

Hi @imbeacon Thank you for your prompt response

I used the same configuration (opcua.json) for OPCUA connector available in github project

For my server here is my code :

from opcua import ua, Server
import random
import time
import threading



# Initialize server
server = Server()
server.set_endpoint("opc.tcp://localhost:4840/freeopcua/server/")

# Setup namespace
uri =  "http://holisticview.org/opcua/"
idx = server.register_namespace(uri)

# Get Objects node
objects = server.get_objects_node()

# Add our sensor object
device1 = objects.add_object(idx, "Device1")
serialNumber= device1.add_variable(idx, "serialNumber", 124566)
sensor = device1.add_object(idx, "TemperatureAndHumiditySensor")
battery=device1.add_object(idx, "Battery")

# Add variables with initial values
temperature = sensor.add_variable(idx, "Temperature", 20.0)
humidity = sensor.add_variable(idx, "Humidity", 101.3)
blevel = battery.add_variable(idx, "batteryLevel", 20.3)


# Make variables writable by clients
temperature.set_writable()
#temperature.set_attribute(ua.AttributeIds.AccessLevel, ua.DataValue(ua.AccessLevel.CurrentRead | ua.AccessLevel.CurrentWrite))
humidity.set_writable()
#pressure.set_attribute(ua.AttributeIds.AccessLevel, ua.DataValue(ua.AccessLevel.CurrentRead | ua.AccessLevel.CurrentWrite))
blevel.set_writable()
# Get and display node paths
def get_node_path(node):
    path = []
    while node:  # Walk up the node hierarchy
        path.append(node.get_browse_name().Name)
        node = node.get_parent()
    return '.'.join(reversed(path))

print(f"Namespace index for your nodes: {idx}")
print(f"Namespace URI: {server.get_namespace_array()[idx]}")

print("BrowseName of Temperature node:", temperature.get_browse_name())
print("Type of BrowseName.Name:", type(temperature.get_browse_name().Name))

print("Temperature node path:", get_node_path(temperature))
print("Humidity node path:", get_node_path(humidity))
print("serialNumber node path:", get_node_path(serialNumber))
print("Battey level node path:", get_node_path(blevel))

# Start server
server.start()
print("Server started at opc.tcp://localhost:4840/freeopcua/server/")
def update_sensor_data():
    while True:
        # Random values that change realistically
        new_temp = temperature.get_value() + random.uniform(-0.5, 0.5)
        new_hum = humidity.get_value() + random.uniform(-0.1, 0.1)
        new_level=  random.uniform(10, 50)
        
        # Keep within reasonable ranges
        new_temp = max(15.0, min(30.0, new_temp))
        new_hum = max(98.0, min(105.0, new_hum))
        
        temperature.set_value(new_temp)
        humidity.set_value(new_hum)
        blevel.set_value(new_level)
        
        time.sleep(1)
  
update_thread = threading.Thread(target=update_sensor_data, daemon=True)
update_thread.start()

khelef avatar May 16 '25 08:05 khelef

@imbeacon Could you please share the OPUCA configuration(opcua.json) used in your demo server?

khelef avatar May 16 '25 10:05 khelef

Hi @khelef,

here is an example of configuration for OPCUA demo server:

{
  "server": {
    "name": "OPC-UA Demo Server",
    "url": "opc.tcp://host.docker.internal:4840/freeopcua/server/",
    "timeoutInMillis": 5000,
    "scanPeriodInMillis": 5000,
    "disableSubscriptions": false,
    "subCheckPeriodInMillis": 100,
    "showMap": true,
    "security": "Basic128Rsa15",
    "identity": {
      "type": "anonymous"
    },
    "mapping": [
      {
        "deviceNodePattern": "Root\\.Objects\\.MyObject",
        "deviceNamePattern": "Demo Device",
        "deviceTypePattern": "default",
        "attributes": [
          {
            "key": "frequency",
            "path": "${Frequency}"
          },
          {
            "key": "power",
            "path": "${Power}"
          }
        ],
        "timeseries": [
          {
            "key": "temperature",
            "path": "${Temperature}"
          },
          {
            "key": "humidity",
            "path": "${Humidity}"
          }
        ],
        "rpc_methods": [],
        "attributes_updates": []
      }
    ]
  }
}

imbeacon avatar May 21 '25 15:05 imbeacon

thanks @imbeacon do you have an idea why my server code that I shared is note working ?

khelef avatar May 23 '25 19:05 khelef

Hi @khelef,

It looks like the issue in the gateway, with device name resolving, unfortunately, we discovered it after release and the fix for it will be available only in the next one or in the master branch. To avoid it - you can just change your device name expression to the constant, instead of using expression.

Fix is added in commit - 7df9be1be8d844ddbc2c0f34ef732b84be4188aa.

imbeacon avatar Jun 03 '25 07:06 imbeacon

thank's a lot @imbeacon

khelef avatar Jun 10 '25 08:06 khelef

Hi,

The new version is released. Please try to use it, feel free to open new issue if you discover something.

imbeacon avatar Jul 08 '25 06:07 imbeacon

@imbeacon is the issue that I mentiened solved ?

khelef avatar Jul 08 '25 16:07 khelef

@khelef should be solved.

imbeacon avatar Jul 09 '25 03:07 imbeacon

thank's @imbeacon in production environnement what's the max devices that I can put in one opcua json config file ?

khelef avatar Jul 09 '25 08:07 khelef

Hi @khelef,

There is no actual limit, except max payload size in MQTT message configured on the server (NETTY_MAX_PAYLOAD_SIZE parameter)

imbeacon avatar Jul 10 '25 11:07 imbeacon

thank's @imbeacon

khelef avatar Jul 18 '25 16:07 khelef