Python OPC UA

OPC UA server stores data and clients read and write data for real-time monitoring and control applications. OPC (Object Linking and Embedding (OLE) for Process Control) is commonly used with a Distributed Control Systems (DCS), Programmable Logic Controllers (PLCs), Human Machine Interfaces (HMIs), and other data transfer applications. It is a newer standard than the older Modbus protocol. OPC UA is platform independent version while OPC DA or OPC HDA (older version) relies on the Microsoft DCOM communication that has inadequate security controls and is not cross-platform. OPC UA support access to current data as well as historical events, multiple hierarchies, and provides commands (methods and programs).

Install opcua

The opcua Python package is a full-featured set of methods that include an OPC UA server and OPC UA client. Install the opcua, opcua-client, and opcua-webclient packages with pip from PyPI repositories.

pip install opcua
pip install opcua-client
pip install opcua-webclient

There are several example applications in the opcua documentation to help build server and client applications. OPC UA includes a server that stores the values and clients that read and write to the server. There may be multiple clients that read and write values to the server. The client and server may also be on the same computer.

OPC UA Python Server (Run First)

This example code is an OPC UA server that creates MyObject with MyVariable value that increments by 0.1 every second. The code runs the server on localhost (IP Address: 127.0.0.1) with port 502. Run the OPC UA server before running the client or webclient because they need an OPC server to read or write values.

import sys
sys.path.insert(0, "..")
import time
from opcua import ua, Server

if __name__ == "__main__":

    # setup our server
    server = Server()
    server.set_endpoint("opc.tcp://0.0.0.0:4840/freeopcua/server/")

    # setup our own namespace, not really necessary but should as spec
    uri = "http://examples.freeopcua.github.io"
    idx = server.register_namespace(uri)

    # get Objects node, this is where we should put our nodes
    objects = server.get_objects_node()

    # populating our address space
    myobj = objects.add_object(idx, "MyObject")
    myvar = myobj.add_variable(idx, "MyVariable", 6.7)
    myvar.set_writable()    # Set MyVariable to be writable by clients

    # starting!
    server.start()

    try:
        count = 0
        while True:
            time.sleep(1)
            count += 0.1
            myvar.set_value(count)
    finally:
        #close connection, remove subscriptions, etc
        server.stop()

OPC UA Python Client

With the OPC UA server running, test a simple client that reads or writes.

import sys
sys.path.insert(0, "..")
from opcua import Client

if __name__ == "__main__":
    client = Client("opc.tcp://localhost:4840/freeopcua/server/")
    #connect using a user
    # client = Client("opc.tcp://admin@localhost:4840/freeopcua/server/")
    try:
        client.connect()

        # Client has a few methods to get proxy to UA nodes that
        #  should always be in address space such as Root or Objects
        root = client.get_root_node()
        print("Objects node is: ", root)

        # Node objects have methods to read and write node attributes
        #  as well as browse or populate address space
        print("Children of root are: ", root.get_children())

        # get a specific node knowing its node id
        #var = client.get_node(ua.NodeId(1002, 2))
        #var = client.get_node("ns=3;i=2002")
        #print(var)
        #var.get_data_value() # get value of node as a DataValue object
        #var.get_value() # get value of node as a python builtin
        #var.set_value(3.9) # set node value using implicit data type

        # Now getting a variable node using its browse path
        myvar = root.get_child(["0:Objects", "2:MyObject", "2:MyVariable"])
        obj = root.get_child(["0:Objects", "2:MyObject"])
        print("myvar is: ", myvar)
        print("myobj is: ", obj)
        print(myvar.get_value())

    finally:
        client.disconnect()

OPC UA Web Client

Run the opcua-webclient by running the command to start on 127.0.0.1 (localhost) on port 8080. Optionally include python3 -m at the beginning to specify the python version to run the web client.

opcua-webclient 127.0.0.1:8080

With the web client running, open a new browser window with the address http://127.0.0.1:8080 or click on the link. The OPC UA Web Client is a basic interface to browse the OPC UA server Root, Objects, Types, and Views.

OPC UA Client

A more full-featured viewer is the OPC UA Client that runs with pyQT as a GUI application. This client allows subscription to data changes and events, writing of variable values, attributes, and references, and the ability to call methods. There is a contextual menu with a tree architecture to view object hierarchies and create simple real-time trends of data. Run opcua-client from the terminal or command prompt.

opcua-client


✅ Knowledge Check

1. What is the primary purpose of an OPC UA server in Python?

A. It is primarily for creating website-based applications.
Incorrect. An OPC UA server's primary function is not to create website-based applications. Instead, it's more about serving data for real-time monitoring and control applications in automation systems.
B. It enables a GUI application for data visualization.
Incorrect. While OPC UA does have GUI applications, like the OPC UA Client, the primary function of the server is to store values for monitoring and control.
C. It provides a mechanism to store values and allows clients to read and write to those values.
Correct. The OPC UA server stores values for real-time monitoring and control, and clients can read and write to those values.
D. It primarily serves to install Python packages.
Incorrect. The OPC UA server doesn't serve to install Python packages. It's more related to real-time monitoring and control in automation systems.

2. Which of the following best describes OPC UA compared to the older Modbus protocol?

A. OPC UA relies on the Microsoft DCOM communication, which has poor security controls.
Incorrect. It's the older OPC DA or OPC HDA that relies on Microsoft DCOM communication, not OPC UA. OPC UA is platform-independent.
B. OPC UA is an older standard compared to the Modbus protocol.
Incorrect. Modbus is an older protocol compared to OPC UA.
C. OPC UA provides commands, supports access to both current and historical data, and has multiple hierarchies.
Correct. OPC UA offers these features, which makes it versatile and suitable for modern automation systems.
D. OPC UA is platform-dependent and is mostly used only on Windows systems.
Incorrect. OPC UA is platform-independent and doesn't rely on any specific operating system like Windows.