Python OPCUA DisplayNames not showing

2.5k Views Asked by At

When I try to launch a OPC UA server with Python (running python 3.7) and setting a DisplayName for a node I have weird behavior. The DisplayName attribute is set right. When I inspect it in a OPC UA client tool, like https://github.com/FreeOpcUa/opcua-client-gui you can see the values of the DisplayName in the attributes area … but as expected the tree view does not show the DisplayName in the first column.

Is there something wrong? Do I oversee something or probably doing something wrong? Is it maybe not supported? The thing is, if I set up a OPC UA Server with the python OPC UA Modeler https://github.com/FreeOpcUa/opcua-modeler and connect to this server the DisplayNames show up in the first column.

Any ideas or advices? THX in advance.

Here is the sample Code

import sys
import locale
import time
from datetime import datetime

from opcua import ua, uamethod, Server

# Set Locale
locale.setlocale(locale.LC_ALL, 'de_DE')
t = time.strftime("%a, %d %b %Y %H:%M:%S")
print (t) # works fine: Fr, 05 Jun 2020 14:37:02

# Set Server 
server = Server()

server.set_endpoint("opc.tcp://localhost:48400")

uri = "http://opcfoundation.org/UA/"
idx = server.register_namespace(uri)
objects = server.get_objects_node()

storage = objects.add_object(idx, "storage")
storage.set_attribute(ua.AttributeIds.DisplayName, ua.DataValue(ua.LocalizedText("Lager")))
storage.set_attribute(ua.AttributeIds.Description, ua.DataValue(ua.LocalizedText("")))
print("") 
print(storage.get_display_name()) # Works fine: LocalizedText(Encoding:2, Locale:None, Text:Lager)
print("")

st_ready = storage.add_variable(idx, "storage_ready", True)
st_ready.set_attribute(ua.AttributeIds.DisplayName, ua.DataValue(ua.LocalizedText("Lager bereit")))
st_ready.set_attribute(ua.AttributeIds.Description, ua.DataValue(ua.LocalizedText("")))

stock = storage.add_object(idx, "stock")
stock.set_attribute(ua.AttributeIds.DisplayName, ua.DataValue(ua.LocalizedText("Lagerbestand")))
stock.set_attribute(ua.AttributeIds.Description, ua.DataValue(ua.LocalizedText("")))

# Values in Stock
circles = stock.add_object(idx, "circles")
circles.set_attribute(ua.AttributeIds.DisplayName, ua.DataValue(ua.LocalizedText("Kreise")))
squaes = stock.add_object(idx, "squares")
squaes.set_attribute(ua.AttributeIds.DisplayName, ua.DataValue(ua.LocalizedText("Quadrate")))
triangles = stock.add_object(idx, "triangles")
triangles.set_attribute(ua.AttributeIds.DisplayName, ua.DataValue(ua.LocalizedText("Dreiecke")))

red_c = circles.add_variable(idx, "red", 1)
red_c.set_attribute(ua.AttributeIds.DisplayName, ua.DataValue(ua.LocalizedText("Rot")))
blue_c = circles.add_variable(idx, "blue", 1)
blue_c.set_attribute(ua.AttributeIds.DisplayName, ua.DataValue(ua.LocalizedText("Blau")))
red_s = squaes.add_variable(idx, "red", 1)
red_s.set_attribute(ua.AttributeIds.DisplayName, ua.DataValue(ua.LocalizedText("Rot")))
blue_s = squaes.add_variable(idx, "blue", 1)
blue_s.set_attribute(ua.AttributeIds.DisplayName, ua.DataValue(ua.LocalizedText("Blau")))
red_t = triangles.add_variable(idx, "red", 0)
red_t.set_attribute(ua.AttributeIds.DisplayName, ua.DataValue(ua.LocalizedText("Rot")))
blue_t = triangles.add_variable(idx, "blue", 1)
blue_t.set_attribute(ua.AttributeIds.DisplayName, ua.DataValue(ua.LocalizedText("Blau")))

# Start Server
server.start()

And here is the first column without DisplayNames but with set value in attributes area in the OPC UA client window.

OPC UA client window

2

There are 2 best solutions below

1
On

The set_attribute function updates the value only in Attributes section. If you wish to use python-opcua and get the DisplayName in tree view, then you can try the code below (code modified from your sample code). The display name and browse name is set in tree view by using the add_<function_name> function. You can see the screenshot of the OPC UA client tool in which the DisplayName is displayed as expected in the tree view. enter image description here

import sys
import locale
import time
from datetime import datetime

from opcua import ua, uamethod, Server

# Set Locale
locale.setlocale(locale.LC_ALL, 'de_DE')
t = time.strftime("%a, %d %b %Y %H:%M:%S")
print (t) # works fine: Fr, 05 Jun 2020 14:37:02

# Set Server 
server = Server()

server.set_endpoint("opc.tcp://localhost:48400")

uri = "http://opcfoundation.org/UA/"
idx = server.register_namespace(uri)
objects = server.get_objects_node()

storage = objects.add_object(idx, "Lager")
storage.set_attribute(ua.AttributeIds.Description, ua.DataValue(ua.LocalizedText("")))
print("") 
print(storage.get_display_name()) # Works fine: LocalizedText(Encoding:2, Locale:None, Text:Lager)
print("")

st_ready = storage.add_variable(idx, "Lager bereit", True)
st_ready.set_attribute(ua.AttributeIds.Description, ua.DataValue(ua.LocalizedText("")))

stock = storage.add_object(idx, "Lagerbestand")
stock.set_attribute(ua.AttributeIds.Description, ua.DataValue(ua.LocalizedText("")))

# Values in Stock
circles = stock.add_object(idx, "Kreise")
circles.set_attribute(ua.AttributeIds.Description, ua.DataValue(ua.LocalizedText("circles")))
squares = stock.add_object(idx, "Quadrate")
squares.set_attribute(ua.AttributeIds.Description, ua.DataValue(ua.LocalizedText("squares")))
triangles = stock.add_object(idx, "Dreiecke")
triangles.set_attribute(ua.AttributeIds.Description, ua.DataValue(ua.LocalizedText("triangles")))

red_c = circles.add_variable(idx, "Rot", 1)
red_c.set_attribute(ua.AttributeIds.Description, ua.DataValue(ua.LocalizedText("red")))
blue_c = circles.add_variable(idx, "Blau", 1)
blue_c.set_attribute(ua.AttributeIds.Description, ua.DataValue(ua.LocalizedText("blue")))
red_s = squares.add_variable(idx, "Rot", 1)
red_s.set_attribute(ua.AttributeIds.Description, ua.DataValue(ua.LocalizedText("red")))
blue_s = squares.add_variable(idx, "Blau", 1)
blue_s.set_attribute(ua.AttributeIds.Description, ua.DataValue(ua.LocalizedText("blue")))
red_t = triangles.add_variable(idx, "Rot", 0)
red_t.set_attribute(ua.AttributeIds.Description, ua.DataValue(ua.LocalizedText("red")))
blue_t = triangles.add_variable(idx, "Blau", 1)
blue_t.set_attribute(ua.AttributeIds.Description, ua.DataValue(ua.LocalizedText("blue")))

# Start Server
server.start()

Since the python-opcua library is in maintenance mode, you can try out the examples available in opcua-asyncio which is the fork of python-opcua: https://github.com/FreeOpcUa/opcua-asyncio/tree/master/examples

You can refer to the documentation available here: https://opcua-asyncio.readthedocs.io/en/latest/ You can also try out these open source OPC UA implementations that you might find interesting:

If you are looking for more hands-on information (it uses another open source stack) , you can also check out these resources:

1
On

I suggest to use another OPC UA client tool:

UaExpert — A Full-Featured OPC UA Client

Reason:

  1. FreeOpcUa is not under continuous development
  2. Limited support document
  3. The UaExpert is designed as a general purpose test client supporting OPC UA features like DataAccess, Alarms & Conditions, Historical Access and calling of UA Methods.
  4. It provides tree view and other features