An OPC UA client reads and writes data from and to an OPC UA client. The OPC UA client can be implemented in various programming languages and environments to access any device with an OPC UA Server implementation. In Python, the OPC UA client is implemented with help of the the python opcua library.
from opcua import Client
The polling method
The simplest way to read and write data from the server is to implement a polling mechanism, that reads or writes data from and to the server in an infinite loop.
while True:
# get the node from the server
tempNode = client.get_node("ns=3;i=1008")
# Display Node information
temperature = tempNode.get_value()
print("Temperature: ", temperature)
Drawback of the polling method
The drawbacks from the polling method include the following
- Resources: Since data is read in an infinite loop even when there is no change in the data values on the server, processing recourses including memory and CPU are being consumed unnecessarily.
- Band width: Imagine a scenario where you are reading thousand so data units. Reading all this data in a loop without taking into consideration if the data values have changed or not is misuse of bandwidth
The Subscription Method
Under this method, the OPC UA client subscribes to different nodes of interest on the server. The client is notified when the data value of the subscribed node changes and this is the only time data is read. This method solves the drawbacks of the polling method, since processing only takes place when a value changes on the OPC UA server.
Implementation of the OPC UA Client Subscription method
There are there steps required to implement the subscription method
The Subscription Handler
The subscription handler handles the Server notification that is sent to the client when the value of a subscribed node changes. This is a class object with a defined function to handle the notification. Inside the notification, the server send the following information.
- The subscribed node
- The node value
- The data
class EventHandler(object):
# event handler function
def datachange_notification(self, node, val, data):
print("Received data: ", val)
In the above handler implementation, the datachange_notification() function simply prints out the value of the node sent within the notification
The subscriber
The subscriber defines the nodes of interest on the server to subscribe to as well as the handling function. The subscriber object is created from the opcua client library and using the the create_subscription(period, handler) method. The period specifies the minimum duration between two notifications from the server.
handler = EventHandler()
sub = client.create_subscription(500, handler)
The subscriber uses the subscribe_data_change(Node) function to specify the node or list of nodes it wishes to subscribe to.
handle = sub.subscribe_data_change(Node)
Example
'''
OPC UA client with subscription method
instead of polling method
'''
import sys
from opcua import Client
import time
# OPC UA Server endpoint
url = "opc.tcp://DESKTOP-FL73J86:53530/OPCUA/SimulationServer"
# create cient and connect to serber
try:
client = Client(url)
client.connect()
print("Connected to OPC UA Server")
except Exception as err:
print("server not found")
sys.exit(1)
# defining an event handler class
class EventHandler(object):
# event handler function
def datachange_notification(self, node, val, data):
print("Received data: ", val)
if __name__ == '__main__':
# get node data from your server
tempNode = client.get_node("ns=3;i=1008")
# handler object
handler = EventHandler()
# subscription object
sub = client.create_subscription(500, handler)
# node
handle = sub.subscribe_data_change(tempNode)