Industrial network communications

OPC UA on a Raspberry Pi

© Lead Image © donatas1205,

© Lead Image © donatas1205,

Article from Issue 258/2022

Use Python and Node-RED to create an industrial client-server test system.

Industrial operations such as chemical refineries, power plants, and mineral processing operations have different network communications requirements than most IT installations. Some of the key industrial communication requirements include security, multivendor connectivity, time stamping of data, and alarm or quality indicators.

To meet industrial requirements, a communications standard called OLE for Process Control (OPC) [1] was created. The original OPC design was based on Microsoft's Object Linking and Embedding (OLE) technology, and it quickly became the standard for communications between control system consoles, historians (data storage devices), and third-party applications (Figure 1).

Figure 1: Typical plant OPC architecture.

The original OPC standard worked well, but it had major limitations in the areas of Linux and embedded systems, routing across wide-area networks (WANs), and new security concerns. To better address new industrial requirements, the Open Platform Communications Unified Architecture (OPC UA) standard [2] was created.

In this article, I look at three small projects that introduce you to OPC UA. The first project uses Python to create an OPC UA server with a client and a graphical user interface (GUI). The second project builds a Node-RED OPC UA server and client app. The final project uses Node-RED web dashboards for read-write access to a Python OPC UA server.

Getting Started

For my test system, I used a Raspberry Pi 4 and an Ubuntu laptop, but the test could also be done on a single Raspberry Pi or laptop. You have a number of OPC UA open source servers from which to choose. For C development applications, the open62541 project [3] offers a C99 architecture that runs on Windows, Linux, VxWorks, QNX (BlackBerry), Android, and a number of embedded systems.

For lightweight, quick testing, OPC UA servers are available in Python and Node-RED. The Free OPC-UA Library project [4] has a great selection of open source tools for people who want to learn and play with OPC UA.

To keep things simple, I am using the python-opcua library, which is a pure Python OPC UA server and client. (Note that a more complete Python OPC UA library, opcua-asyncio, is available for more detailed work.)

The Free OPC UA project also includes a number of useful tools, such as an OPC UA modeler and client GUI. The commands

# Python OPC UA server/client install
sudo apt install python-opcua
# OPC UA client/QT dependencies
sudo apt install PyQT*
pip3 install opcua-client
# OPC UA modeler tool
$ pip3 install opcua-modeler

load these items in Ubuntu/Debian/Raspian environments.

Simple Python OPC UA Server

As a first project, I create a simple OPC UA server with some simulated OPC UA tags (Listing 1) [5]. The first steps in setting up an OPC UA server are to define a server name, set a network location endpoint, and register the namespace (lines 7-12). A little later you will see that the namespace index is very important in the definition of OPC UA tags. To simplify my code, I hard-coded the IP address (lines 9 and 12). For a more flexible setup, the Python socket library could be used to determine this value for the endpoint and namespace.

Listing 1

Python OPC UA Simple Server

01 # - Create an OPC UA server and simulate 2 tags
02 #
03 import opcua
04 import random
05 import time
07 s = opcua.Server()
08 s.set_server_name("OpcUa Test Server")
09 s.set_endpoint("opc.tcp://")
11 # Register the OPC UA namespace
12 idx = s.register_namespace("")
13 # start the OPC UA server (no tags at this point)
14 s.start()
16 objects = s.get_objects_node()
17 # Define a Weather Station object with some tags
18 myobject = objects.add_object(idx, "Station")
20 # Add a Temperature tag with a value and range
21 myvar1 = myobject.add_variable(idx, "Temperature", 25)
22 myvar1.set_writable(writable=True)
24 # Add a Windspeed tag with a value and range
25 myvar2 = myobject.add_variable(idx, "Windspeed", 11,4,4)
26 myvar2.set_writable(writable=True)
28 # Cycle every 5 seconds with simulated data
29 while True:
30     myvar1.set_value(random.randrange(25, 29))
31     myvar2.set_value(random.randrange(10, 20))
32     time.sleep(5)

The OPC UA structure is based on objects and files, under which tags are configured. For this example a Station object is created (line 18), with Temperature and Windspeed tags (lines 21-26). The final step is to use the set_value method to update the tags with random values (lines 30-31).

The Free OPC UA project's opcua-client GUI tool lets you view the OPC UA server and its tags. Figure 2 shows the server with two simulated tags and their NodeIDs.

Figure 2: Free OPC UA client tool.

OPC UA items are accessed by their NodeIDs. The OPC UA server will autocreate a NodeID if one isn't defined when an object or tag is added. In this example, Temperature is given the NodeID ns=2,i=2, which means it has an index of 2 in node space 2. In the next sections, I show how NodeIDs are used and how they can be created.

In OPC UA, the terms "tags" and "variables" are often used interchangeably. In an industrial plant, hardware signals such as pumps and sensors are usually referred to as "tags" in the control systems; however, within the OPC UA server, the term "variable" is used. The key difference is that a variable can also be an internal or software-generated point, such as a counter.

Python OPC UA Client App

The opcua library is used for both server and client applications. An OPC UA client app only requires five lines to connect to a server and define a NodeID object and get its value. Listing 2 shows how to get the previously defined Temperature tag.

Listing 2

Getting a Tag Value

>>> import opcua
>>> # Connect as an OPC UA client and get a tag value
>>> client = opcua.Client("opc.tcp://")
>>> client.connect()
>>> temptag = client.get_node("ns=2;i=2")
>>> temptag.get_value()

The Client method defines the OPC UA server's endpoint location, and the connect method enables the client connection. An OPC UA NodeID object is defined by a namespace number (ns) and an index (i), and the get_value method returns the current value. For my Python client application, I use this basic code to show tag values on a gauge chart (Figure 3).

Figure 3: Python OPC UA client app.

The Python tk_tools [6] library contains some useful graphic widgets (e.g., charts, gauges, LEDs, seven-segment displays). To install, enter:

pip install tk_tools

The client app (Listing 3) creates a Tkinter object (line 11) and then adds two gauge components (lines 15-20). The Tkinter after(<msec>,<function_name>) method calls an update function (line 26) that refreshes the gauge components with OPC UA tag updates (lines 26 and 28).

Listing 3

Python OPC UA Client App

01 # - Put OPC UA data into gauges
02 #
03 import tkinter as tk
04 import tk_tools
05 import opcua
07 # Connect to the OPC UA server as a client
08 client = opcua.Client("opc.tcp://")
09 client.connect()
11 root = tk.Tk()
12 root.title("OPC-UA Weather Station 1")
14 # Create 2 gauge objects
15 gtemp = tk_tools.Gauge(root, height = 200, width = 400,
16             max_value=50, label='Temperature', unit='infinityC')
17 gtemp.pack()
18 gwind = tk_tools.Gauge(root, height = 200, width = 400,
19             max_value=100, label='Windspeed', unit='kph')
20 gwind.pack()
22 def update_gauge():
23     # update the gauges with the OPC UA values every 1 second
24     gtemp.set_value(client.get_node("ns=2;i=2").get_value())
25     gwind.set_value(client.get_node("ns=2;i=5").get_value())
26     root.after(1000, update_gauge)
28 root.after(500, update_gauge)
30 root.mainloop()

Buy this article as PDF

Express-Checkout as PDF
Price $2.95
(incl. VAT)

Buy Linux Magazine

Get it on Google Play

US / Canada

Get it on Google Play

UK / Australia

Related content

  • Monitoring Old Devices

    Create monitoring dashboards with SSH, command-line tools, and Node-RED.

  • IoT with RabbitMQ

    Connect multiple protocols and servers together on your IoT projects.

  • Node-RED

    Node-RED lets you connect ready-made code building blocks to create event-driven applications with little or no code writing.

  • Web Scraping with Bash

    You can use one line of Bash code to scrape a web page and show the data you're tracking in Home Assistant or Node-RED.

  • WiFi Thermo-Hygrometer

    A WiFi sensor monitors indoor humidity and temperature and a Node-RED dashboard reports the results, helping you to maintain a pleasant environment.

comments powered by Disqus
Subscribe to our Linux Newsletters
Find Linux and Open Source Jobs
Subscribe to our ADMIN Newsletters

Support Our Work

Linux Magazine content is made possible with support from readers like you. Please consider contributing when you’ve found an article to be beneficial.

Learn More