在创建了C服务器之后,部署在linux端。接着要在自己客户端的界面上添加关于节点变量的刷新和方法的调用。而OPCUA的客户端有比较多的通用版本,在第一节简单示例中便有一个WIndow版本的客户端,可以查看所有服务器中创建的节点,方法和类型等等。

Python-OPCUA

而本人要将该客户端服务集成到Python版本客户端去,经过查找资料发现是有Python版本的库的,源码在https://github.com/FreeOpcUa/python-opcua上,安装如下:

Python安装包安装:

pip install opcua

或者下载源码进行Python setup.py install的方式进行安装。

测试如下,则表示安装成功了:

python使用 opc通讯协议 opc ua python_OPCUA

 服务器方面的就不做详细说明,而且暂时没有使用Python进行编写服务器,交叉编译运行在arm上的服务器Python似乎有些困难的样子。

但是可以从Github上看到提供的一些关于创建服务器和客户端的例子,服务器的节点创建和Object创建都相当简单,如果能够使用Python进行编写服务器,我还是推荐Python,省得和指针捉迷藏了。

Client

本客户端是在一个线程进行刷新使用的,所以并没有使用到OPCUA的Pub/Sub订阅服务。

Python集成之后再次提供的接口真的相当简单,这里简单介绍使用,分为连接,读写节点,调用方法。

连接

简单的导入,添加地址:本linux端的ip为192.168.1.120,所以如下即可连接成功。

from opcua import Client
client = Client("opc.tcp://192.168.1.120:4840/freeopcua/server/")
client.connect()

读写节点

之前的服务器编辑节点时,大家应该知道我是使用的字符型id(ns=1;s=pos).

这里没有做扫描式显示,而是已经知道了服务器是有这么一个节点,便可以读可以写:

读值:

ret = client.get_node("ns=1;s=pos")
print(ret.get_value())

写值(这个未做尝试,但是看源码应该可以直接写个值,不要像下面第二行一样麻烦):

var = client.get_node("ns=1;s=pos")
var.set_value(23,ua.VariantType.Double)

调用方法

objects = client.get_objects_node()
met = objects.get_child("1:Pump")
retval = met.call_method("1:setpos", [True,True,True])
print(retval)

 objects为协议的objects的大目录,met是我之前在服务器创建的Object的反馈。

直接调用call_method即可,注意对应上服务器上方法需要的输入数组的数目与类型,防止出错。

调用多参数方法

#要获取该方法的父节点!
ob = client.get_node("ns=1;s=parent")
v1 = ua.Variant([8],ua.VariantType.UInt16,dimensions=1,is_array=1)  #参数是列表形式
v2 = ua.Variant(["arg11"],ua.VariantType.String,dimensions=1,is_array=1) #参数是列表形式
ob.call_method("1:XXX",v1,v2)
#注意版本的更新,使用的0.98.12是可以的,0.98.7就有报错

客户端框架

调用一个线程即可,在里面0.1s进行连接与检测是否断开,断开的话1s再次不断循环连接,达到稳定的客户端的效果。

def run(self):#运行一个线程
        flag = 0
        while True:
            if flag == 0:
                try:
                    self.client = Client("opc.tcp://127.0.0.1:4840/freeopcua/server/")
                    self.client.connect()
                    self.objects = self.client.get_objects_node()
                    flag = 1
                except :
                    time.sleep(1)
                    continue
            try:
                actpos0 = self.client.get_node(XXX)
                YYY = actpos0.get_value()
                try:
                    self.client.disconnect()
                except:
                    pass
                flag = 0
            time.sleep(0.1)

注意

1.定义方法的int型输入数组时,个人遇到反复无法成功调用方法的问题,后来发现设置int64可行,int16无法和Python版本的变量对应上。

2.INT64,INT32数据在实际使用上区分吧,有时候INT64不行的

3.数组类型进行赋值的时候目前只能将整个数组进行重新赋值,无法针对某一个元素进行单独赋值。这是我目前的已知,如果发现了单独赋值的功能再说。