Opuca Connector : QualifiedName constructor args have wrong types
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
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
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()
@imbeacon Could you please share the OPUCA configuration(opcua.json) used in your demo server?
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": []
}
]
}
}
thanks @imbeacon do you have an idea why my server code that I shared is note working ?
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.
thank's a lot @imbeacon
Hi,
The new version is released. Please try to use it, feel free to open new issue if you discover something.
@imbeacon is the issue that I mentiened solved ?
@khelef should be solved.
thank's @imbeacon in production environnement what's the max devices that I can put in one opcua json config file ?
Hi @khelef,
There is no actual limit, except max payload size in MQTT message configured on the server (NETTY_MAX_PAYLOAD_SIZE parameter)
thank's @imbeacon