Industrial network communications
OPC UA on a Raspberry Pi

© Lead Image © donatas1205, 123RF.com
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).
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 # opcua_server1.py - Create an OPC UA server and simulate 2 tags 02 # 03 import opcua 04 import random 05 import time 06 07 s = opcua.Server() 08 s.set_server_name("OpcUa Test Server") 09 s.set_endpoint("opc.tcp://192.168.0.120:4841") 10 11 # Register the OPC UA namespace 12 idx = s.register_namespace("http://192.168.0.120:4841") 13 # start the OPC UA server (no tags at this point) 14 s.start() 15 16 objects = s.get_objects_node() 17 # Define a Weather Station object with some tags 18 myobject = objects.add_object(idx, "Station") 19 20 # Add a Temperature tag with a value and range 21 myvar1 = myobject.add_variable(idx, "Temperature", 25) 22 myvar1.set_writable(writable=True) 23 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) 27 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.
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://192.168.0.120:4841") >>> client.connect() >>> temptag = client.get_node("ns=2;i=2") >>> temptag.get_value() 26
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).
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 # station1.py - Put OPC UA data into gauges 02 # 03 import tkinter as tk 04 import tk_tools 05 import opcua 06 07 # Connect to the OPC UA server as a client 08 client = opcua.Client("opc.tcp://192.168.0.120:4841") 09 client.connect() 10 11 root = tk.Tk() 12 root.title("OPC-UA Weather Station 1") 13 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() 21 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) 27 28 root.after(500, update_gauge) 29 30 root.mainloop()
Buy this article as PDF
(incl. VAT)
Buy Linux Magazine
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.
News
-
elementary OS 7.1 Now Available for Download
The team behind elementary OS has released the latest version of its operating system with a focus on personalization, inclusivity, accessibility, and privacy.
-
The GNU Project Celebrates Its 40th Birthday
September 27 marks the 40th anniversary of the GNU Project, and it was celebrated with a hacker meeting in Biel/Bienne, Switzerland.
-
Linux Kernel Reducing Long-Term Support
LTS support for the Linux kernel is about to undergo some serious changes that will have a considerable impact on the future.
-
Fedora 39 Beta Now Available for Testing
For fans and users of Fedora Linux, the first beta of release 39 is now available, which is a minor upgrade but does include GNOME 45.
-
Fedora Linux 40 to Drop X11 for KDE Plasma
When Fedora 40 arrives in 2024, there will be a few big changes coming, especially for the KDE Plasma option.
-
Real-Time Ubuntu Available in AWS Marketplace
Anyone looking for a Linux distribution for real-time processing could do a whole lot worse than Real-Time Ubuntu.
-
KSMBD Finally Reaches a Stable State
For those who've been looking forward to the first release of KSMBD, after two years it's no longer considered experimental.
-
Nitrux 3.0.0 Has Been Released
The latest version of Nitrux brings plenty of innovation and fresh apps to the table.
-
Linux From Scratch 12.0 Now Available
If you're looking to roll your own Linux distribution, the latest version of Linux From Scratch is now available with plenty of updates.
-
Linux Kernel 6.5 Has Been Released
The newest Linux kernel, version 6.5, now includes initial support for two very exciting features.