您现在的位置是:首页 >技术杂谈 >python 006:通过OPC UA协议连接KepServerEx进行读、写、订阅操作网站首页技术杂谈

python 006:通过OPC UA协议连接KepServerEx进行读、写、订阅操作

qq_28530139 2023-06-12 00:00:03
简介python 006:通过OPC UA协议连接KepServerEx进行读、写、订阅操作

我Hyb在2023-4-18调通了自己的PythonOpcUaDemo。具体Java代码和KepServerEX延时补丁都在资源中。

第1步:安装激活KepServer,补丁在资源中,不详述。

第2步:在KepServer中做OpcUa配置。

2.1 先看桌面右下角有没EX图标

2.2 如果没有EX图标,要去开始菜单中找到KEPServerEX 6 Administration,点击打开它后,桌面右下角就会出现EX图标:

2.3 右键点击EX图标,选择“OPC UA 配置”,设置过程看这个动图:(一定要关注动图中192.168.10.60这个ip及端口的设置,它要与你代码中一致!

第3步:在KepServer中设置用户名密码。

3.1 再一次点桌面右下角的EX图标,选择“设置”,点“用户管理器”,在Administrators右键选择“添加用户”。见图操作:

第4步:在KepServer中设置opcua匿名账户登录。

在KepServerEX界面,在“项目”右键,选择“属性”,选择“OPC UA”。在“客户端会话”、“允许匿名登录”中,选择“是”。如图:

以上KepServerEX设置完成后,就可以写Python代码了。


第5步:先使用国内镜像源安装asyncua模块:

py -m pip install asyncua -i https://pypi.tuna.tsinghua.edu.cn/simple/

asyncua开源代码库 https://github.com/FreeOpcUa/opcua-asyncio ,其英文文档是 https://opcua-asyncio.readthedocs.io/en/latest

第6:先贴份简单的python代码,能连接KepServerEX进行读写操作(并有实际运行动图,这个动图也录制了pip和asyncio的安装过程):

from asyncua import Client, ua
import asyncio

async def get_text():
	async with Client(url='opc.tcp://192.168.10.150:49320') as client:
		while True:
			node = client.get_node('ns=2;s=通道 1.设备 1.标记 2')
			value = await node.read_value()
			print(value)
			await node.write_value(ua.DataValue(ua.Variant(value+1, ua.VariantType.Int16, None, None), None))
			await asyncio.sleep(1)

def main():
	loop = asyncio.get_event_loop()
	task = get_text()
	loop.run_until_complete(task)
	loop.close()

if __name__ == '__main__':
	main()

第7:再贴份稍复杂的python代码,能连接KepServerEX订阅数据变化(并有实际运行动图):

import sys
sys.path.insert(0, "..")
import os
# os.environ['PYOPCUA_NO_TYPO_CHECK'] = 'True'

import asyncio
import logging

from asyncua import Client, ua


class SubHandler(object):
	def datachange_notification(self, node, val, data):
		idNode = node.nodeid.Identifier.split('.', maxsplit=2)
		idDevice = idNode[1]
		tag = idNode[2]
		print(idDevice, tag, val)

async def main():
	url = "opc.tcp://192.168.10.150:49320"
	# url = "opc.tcp://localhost:53530/OPCUA/SimulationServer/"
	# url = "opc.tcp://olivier:olivierpass@localhost:53530/OPCUA/SimulationServer/"
	async with Client(url=url) as client:
		#print("Root children are", await client.nodes.root.get_children())

		tag1 = client.get_node("ns=2;s=通道 1.设备 1.标记 1")
		tag1Val = await tag1.read_value()
		print(f"tag1:{tag1}, VALUE={tag1Val}, TYPE={type(tag1Val)}")

		tag2 = client.get_node("ns=2;s=通道 1.设备 1.标记 2")
		tag2Val = await tag2.read_value()
		print(f"tag2:{tag2}, VALUE={tag2Val}, TYPE={type(tag2Val)}")

		await tag2.write_value(ua.DataValue(ua.Variant(25, ua.VariantType.Int16, None, None), None))
		#await tag2.write_value(ua.Variant(23, ua.VariantType.Int16, None, None))
		#await tag2.write_value(100) # asyncua.ua.uaerrors._auto.BadWriteNotSupported 服务器不支持写入所提供的值、状态和时间戳的组合

		handler = SubHandler()
		sub = await client.create_subscription(1000, handler)
		handle1 = await sub.subscribe_data_change(tag1) # 标记1是用于验证客户端连接的加速读/写标记,该值会每秒加1,
		                                                # 但订阅时发现加1的频率被篡改。不过,java端没有这个问题。
		                                                # 所以我分析这是asyncio源代码bug,不过目前还没实力改这个源码。
		handle2 = await sub.subscribe_data_change(tag2)
		while True:await asyncio.sleep(sys.maxsize)

		# await sub.subscribe_events()
		# await sub.unsubscribe(handle1)
		# await sub.unsubscribe(handle2)
		# await sub.delete()

if __name__ == "__main__":
	logging.basicConfig(level=logging.WARN)
	asyncio.run(main())

注意观察代码的运行动图会发现:

7.1 订阅标记2没有问题,其数值被改后,立马同步给了客户端。

7.2 但订阅标记1就有问题,本来它是每秒自增1。但订阅后,变成每秒自增10。但同样 java端订阅 时没有这个问题!我估计是asyncio模块源码本身的问题,但目前限于python水平有限,还没有阅读源码和修改的能力。所以,就这样吧。。。


本文涉及的java项目代码和KepServerEX补丁下载地址:https://download.csdn.net/download/qq_28530139/87579334

Hyb本文结束,谢谢浏览【VX:m3920752】!个人资源的解压密码是: hyb


风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。