翼度科技»论坛 编程开发 python 查看内容

Python访问OPCUA服务器,订阅一个变量标签方式

12

主题

12

帖子

36

积分

新手上路

Rank: 1

积分
36
Python访问OPCUA服务器,订阅一个变量标签
  1. from opcua import Client
  2. from opcua import ua
  3. import time
  4. #By Weloveut:Python访问OPCUA服务器,展示get变量的方法和注册逢变触发的回调函数
  5. #自定义回调函数
  6. class SubHandler(object):
  7.         def data_change(self, handle, node, val, attr):
  8.                 print("Python: New data change event", handle, node, val, attr)
  9. #创建UA的客户端,包含IP地址和端口号
  10. client = Client("opc.tcp://172.32.1.82:4840/")
  11. #建立到服务器连接
  12. client.connect()
  13. #获取object对象
  14. objects = client.get_objects_node()
  15. #获取根对象
  16. root = client.get_root_node()
  17. #依据变量地址创建变量对象
  18. myvar = client.get_node('ns=3;s="clocl0.5hz"."tags"[0]')
  19. #获取变量当前值
  20. valuetmp=myvar.get_value()
  21. print(valuetmp)
  22. #注册到服务器的变量订阅,变量逢变触发
  23. handler = SubHandler()
  24. sub = client.create_subscription(500, handler)
  25. sub.subscribe_data_change(myvar)
  26. time.sleep(100000)
  27. client.disconnect()
复制代码
opcua-python学习踩坑记录


OPCUA通信协议介绍

OPC UA(OPC 统一架构)是一种用于工业控制系统的通信协议。它是一种开放的、平台无关的协议,可用于连接各种工业设备和软件应用程序,使它们能够互相通信并共享数据。
OPC UA 的主要优点在于,它能够提供一种统一的方式来连接不同厂商的设备和应用程序。这意味着,使用 OPC UA 的软件应用程序可以与使用其他协议的设备和应用程序进行通信,而无需考虑底层的通信协议。
其实这类似于物联网中的mqtt协议,只不过mqtt较为轻量级,opcua则是用于工业相关的控制系统

OPCUA的两种工作方式


  • 客户端/服务器模式:在这种模式下,OPC UA 客户端向 OPC UA 服务器请求数据,服务器接收请求并向客户端发送数据。
  • 发布/订阅模式:在这种模式下,OPC UA 服务器将数据“发布”到网络上,而客户端可以“订阅”特定的数据。当服务器更新数据时,客户端会收到更新的数据。
这两种模式可以根据应用场景的需要进行选择。例如,客户端/服务器模式适用于客户端需要向服务器请求单个数据项的情况,而发布/订阅模式则适用于客户端需要定期接收大量数据的情况。
个人觉得客户端/服务器模式类似于TCP通讯协议,是点对点的,对实时性要求比较高,而发布订阅模式类似于UDP通讯协议,对实时性要求并没有那么高,但接收数据较多
其中发布订阅模式对小的嵌入式设备(stm32系列)比较友好,可以融合物联网的mqtt协议,真正将opcua纳入网络,而不只是自己的工业网络

OPCUA-python是什么?

顾名思义,那就是利用python实现这种通信协议的库呗,这个库目前已经停止更新,开发者们开发了一个新的库,名为opcua-asyncio,可通过如下链接访问:
https://github.com/FreeOpcUa/opcua-asyncio
不过做一些比较基本的功能,只用OPCUA-python这个库还是够用的
服务器常用函数
  1. endpoint = "opc.tcp://{}:{}".format(url, port)
  2. myserver.set_endpoint(endpoint)
复制代码
设置endpoint(其实endpoint就像一个服务器链接)
  1. myserver = opcua.Server()
复制代码
开启opcua服务器
  1. objects = myserver.get_objects_node()
复制代码
设置服务器节点(使客户端得以访问)
  1. addspace = myserver.register_namespace(name)
复制代码
设置服务器命名空间
  1. root = myserver.get_root_node()
复制代码
获取服务器根节点
  1. objects.add_method(1, "Conveyor", Start_Conveyor_prog)
复制代码
为节点(objects) 添加方法Start_Conveyor_prog

客户端常用函数
  1. myclient = Client(endpoint)
复制代码
在客户端引用endpoint
  1. myclient.get_node("ns=2;i=3")
复制代码
在客户端里使用ns=2;i=3这个节点
  1. Start_Lathe_Prog1 = method[4]
复制代码
调用服务器里设置的方法
  1. Workpiece = objects_node.call_method(Start_Conveyor_prog,[WorkpieceID.get_value()])
复制代码
call_method函数,第一个参数是节点名称,第二个参数是值,是这个节点里的值,属于数组,或者传递字典也是可以的
  1. return_value_kuka_prog1 = objects_node.call_method(Start_Kuka_Prog1)
复制代码
返回某个方法

示例程序:温度实时检测,每隔五秒传到客户端

服务器程序:
  1. import opcua
  2. from time import sleep
  3. from random import randint
  4. from datetime import datetime

  5. # Assign endpoint URL
  6. url = "localhost"
  7. port = 5001
  8. endpoint = "opc.tcp://{}:{}".format(url, port)

  9. # create instance/object of type opcua.Server
  10. myserver = opcua.Server()

  11. # Assign endpoint url on the OPC UA server address space
  12. myserver.set_endpoint(endpoint)

  13. # Create a name for OPC UA namespace
  14. name = "Temperature Sensor"

  15. # Register the name on OPC UA namespace
  16. addspace = myserver.register_namespace(name)

  17. # Get reference to the Objects node of the OPC UA server
  18. objects = myserver.get_objects_node()

  19. # Create objects on the object node
  20. param = objects.add_object(addspace, "parameters")

  21. # Create variables
  22. Sensor_name = param.add_variable(addspace, "Sensor Name", "Temperature_Sensor_SF12")
  23. Temperature = param.add_variable(addspace, "Temperature Value", 'NA')

  24. # Set variable as writable
  25. Sensor_name.set_writable()
  26. Temperature.set_writable()

  27. #########################################################################################
  28. # Present the data structure of the OPC UA server
  29. root = myserver.get_root_node()
  30. print("Root Node Id: %s" % root)
  31. print("Children of root are: %s" % root.get_children())
  32. print()

  33. my_objects = myserver.get_objects_node()
  34. print("Defined object Node Id: %s" % my_objects)
  35. print("Children of the defined object are: %s" % my_objects.get_children())
  36. print()

  37. sensor_name_node = my_objects.get_children()[1].get_children()[0]
  38. print("Sensor name node Id: %s" % sensor_name_node)
  39. print("Sensor name node browse name: %s" % sensor_name_node.get_browse_name())
  40. print("Sensor name default value: %s" % sensor_name_node.get_value())
  41. print()

  42. temperature_node = my_objects.get_children()[1].get_children()[1]
  43. print("Temperature node Id: %s" % temperature_node)
  44. print("Temperature node browse name: %s" % temperature_node.get_browse_name())
  45. print("Temperature default value: %s" % temperature_node.get_value())
  46. print()
  47. ########################################################################################

  48. # starting! The server will continue running
  49. myserver.start()
  50. current_time = str(datetime.now().time())[:-7]
  51. print("{} - Server is initialising...".format(current_time))

  52. while True:
  53.     sleep(5)
  54.     current_time = str(datetime.now().time())[:-7]
  55.     current_temp = randint(10, 25)

  56.     Temperature.set_value(current_temp)  # publish temperature value
  57.     print("{} - Current temperature: {} Celsius".format(current_time, current_temp))
复制代码
客户端程序:
  1. from opcua import Client
  2. from datetime import datetime

  3. # Assign endpoint URL
  4. url = "localhost"
  5. port = 5001
  6. endpoint = "opc.tcp://{}:{}".format(url, port)

  7. # Assign endpoint url on the OPC UA client  address space
  8. myclient = Client(endpoint)

  9. # Connect to server
  10. myclient.connect()

  11. # Assign nodes
  12. Temperature_node = myclient.get_node("ns=2;i=3")

  13. # Subhandler Class from OPC UA
  14. class SubHandler(object):
  15.     """
  16.     Subscription Handler. To receive events from server for a subscription
  17.     """

  18.     def datachange_notification(self, node, val, data):
  19.         """
  20.         called for every datachange notification from server
  21.         """
  22.         global DataChange  # Global variable
  23.         current_time = str(datetime.now().time())[:-7]
  24.         DataChange = val  # Assigning value to global variable
  25.         print("{} - Received temperature: {} Celsius".format(current_time, val))

  26.     # Initailise variable


  27. nodes = myclient.get_objects_node()
  28. DataChange = "null"

  29. # Create Sub handler
  30. handler = SubHandler()

  31. # create subscription by passing period in milliseconds and handler
  32. subscribe = myclient.create_subscription(0, handler)

  33. # pass variable node to subscribe data change method
  34. handler = subscribe.subscribe_data_change(Temperature_node)
复制代码
程序运行效果:服务器

程序运行效果:客户端


总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

来源:https://www.jb51.net/python/316198wxe.htm
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x

举报 回复 使用道具