Python-opcua 编程(1)

     Python-opcua 编程(1)_第1张图片

      任何一项新标准如果不能充分应用是不可能推广的,最近看了一些国外网站,发现类似OPC UA 的应用以及比较广泛了,而且有许多课程。相比之下,我国OPCUA 标准的普及工作仍然停留在概述的阶段,为此,我将逐步介绍一些编写OPC UA 应用程序实例,同时也介绍一些OPCUA 的应用场合。为了避免程序设计的细节,我们采用Python Opcua。

     Python已经成为非常流行的程序设计语言,它在网络编程,数值运算和人工智能领域应用广泛。并且在这些领域的应用程序也非常多,使人们能够很块地进入人工智能,数值运算,图像处理等领域的程序设计。而OPCUA 是一个正在普及的工业自动化协议和信息模型系统,opcua 是进入OT领域的接口。

Python 在工业软件中的应用

     在工业软件中,使用Python并不多,人们更倾向C#,C++和Matlab、labview 等程序设计语言编程。不过,Python 在以数值技术为中心的应用中具备优势,例如,复杂的控制算法,视觉识别,数据分析,工业AI应用中使用python 更加适合,同时,如果你有一些想法,希望快速成型,验证。使用python 无疑是高效率的。

OPC UA  协议

       OPC UA 是一个在工业领域应用越来越广泛的通信协议。它主要采取服务器/客户端通信方式,也支持发布/订阅方式。OPC UA 协议中包含了构建信息模型的方法,并且不断地制定行业规范。工业4.0 和MTP等主要的协议都是基于OPCUA的。因此,采用OPC UA 作为产品和服务的接口协议能够实现兼容性,目前各种主流的PLC 已经支持OPCUA。

Python与OPC UA 消除IT/OT 的鸿沟

使用Python 编程,OPC UA 协议作为IT 连接OT 领域的PLC ,传感器,执行器的接口。这种方式为IT 行业的最新技术导入OT 是十分有效的方式,例如视觉识别,AI,数据分析等技术发展速度惊人。通过Python-Opcua 组合在算法研究,快速原型设计和新产品开发验证中带来的效率。

下面是一个应用实例

Python-opcua 编程(1)_第2张图片

在这个例子中,使用python+OpenCV 完成视觉识别。它们可以在一个小型的Linux 控制器上运行。PLC 和视觉控制器之间通过网线连接,并且使用OPC UA 交互,PLC 是服务器端,视觉控制器是Client 端。

  

 实例

       Python 的OPCUA 模块是,python-opcua。使用它来编写OPCUA 的服务器和客户端程序要比C#的OPC Foundation .Net 容易的多。如果编写一些OPC UA 的小程序,正巧你有会使用python的话,强烈建议使用python。

     所有编程语言的文档都是十分枯燥的,最好的方式是通过实例来学习。在这一系列博文中,我们从实例的方式来介绍Python opcua的编程技巧。

实例(1)-简单的服务器

import sys
sys.path.insert(0, "..")
import time
from opcua import  Server

if __name__ == "__main__":

    # setup our server
    server = Server()
    server.set_endpoint("opc.tcp://127.0.0.1:48400/freeopcua/server/")

    # setup our own namespace, not really necessary but should as spec
    uri = "http://examples.freeopcua.github.io"
    idx = server.register_namespace(uri)

    # get Objects node, this is where we should put our nodes
    objects = server.get_objects_node()

    # populating our address space
    myobj = objects.add_object(idx, "MyObject")
    myvar = myobj.add_variable(idx, "MyVariable", 6.7)
    myvar.set_writable()    # Set MyVariable to be writable by clients

    # starting!
    server.start()
    
    try:
        count = 0
        while True:
            time.sleep(1)
            count += 0.1
            myvar.set_value(count)
    finally:
        #close connection, remove subcsriptions, etc
        server.stop()

实例(2)-简单的客户端

import sys
sys.path.insert(0, "..")


from opcua import Client


if __name__ == "__main__":

    client = Client("opc.tcp://localhost:48400/freeopcua/server/")
    # client = Client("opc.tcp://admin@localhost:4840/freeopcua/server/") #connect using a user
    try:
        client.connect()

        # Client has a few methods to get proxy to UA nodes that should always be in address space such as Root or Objects
        root = client.get_root_node()
        print("Objects node is: ", root)

        # Node objects have methods to read and write node attributes as well as browse or populate address space
        print("Children of root are: ", root.get_children())

        # get a specific node knowing its node id
        #var = client.get_node(ua.NodeId(1002, 2))
        #var = client.get_node("ns=3;i=2002")
        #print(var)
        #var.get_data_value() # get value of node as a DataValue object
        #var.get_value() # get value of node as a python builtin
        #var.set_value(ua.Variant([23], ua.VariantType.Int64)) #set node value using explicit data type
        #var.set_value(3.9) # set node value using implicit data type

        # Now getting a variable node using its browse path
        myvar = root.get_child(["0:Objects", "2:MyObject", "2:MyVariable"])
        obj = root.get_child(["0:Objects", "2:MyObject"])
        print("myvar is: ", myvar)
        print("myobj is: ", obj)

        # Stacked myvar access
        # print("myvar is: ", root.get_children()[0].get_children()[1].get_variables()[0].get_value())

    finally:
        client.disconnect()

实例(3)-导入NodeSet2.xml

     OPC UA 的信息模型采用标准化模板的xml 来表达,它被称为NodeSet。NodeSet是使用OPC UA 的建模工具来生成的,例如、luaModeler,SiOME等基于图像界面的建模工具,也可以使用UA ModelCompile 编译工具。python-opcua 的服务器能够导入外部生成的NodeSet2信息模型。

  python-opcua server 通过 import_xml 导入NodeSet2 文档。

import sys
sys.path.insert(0, "..")
import time


from opcua import ua, Server


if __name__ == "__main__":

    # setup our server
    server = Server()
    server.set_endpoint("opc.tcp://localhost:4840/freeopcua/server/")

    server.import_xml("../schemas/UA-Nodeset/DI/Opc.Ua.Di.NodeSet2.xml")
    server.import_xml("../schemas/UA-Nodeset/Robotics/Opc.Ua.Robotics.NodeSet2.xml")

    # setup our own namespace, not really necessary but should as spec
    uri = "http://examples.freeopcua.github.io"
    idx = server.register_namespace(uri)

    # get Objects node, this is where we should put our nodes
    objects = server.get_objects_node()

    # populating our address space
    myobj = objects.add_object(idx, "MyObject")
    myvar = myobj.add_variable(idx, "MyVariable", 6.7)
    myvar.set_writable()    # Set MyVariable to be writable by clients

    # starting!
    server.start()

    try:
        count = 0
        while True:
            time.sleep(1)
            count += 0.1
            myvar.set_value(count)
    finally:
        #close connection, remove subcsriptions, etc
        server.stop()

实例(4)-定义读取命名空间

可以使用多个xml 文档来描述信息模型,比如最基本的命名模型的URI 是http://www.opcfoundation.org/UA。

在该基础上可以导入其它的命名空间,例如

http://www.opcfoundation.org/UA/DI

http://www.opcfoundation.org/PLCOpen

你也可以导入自定义的信息模型,URI 可以为

http://www.maxim.com/App

在Python-opcua 中,可以注册python 程序的命名空间,例如

    uri = "http://www.maxim.org/app/"
    idx = server.register_namespace(uri)

 注意,这里注册的命名空间并不是你装入的命名空间,而是你Python 程序的命名空间,它返回一个idx。在程序中新建一个变量的话,可以使用该idx

    在Python-opcua 中,命名空间是存放在namespaceArray中的,可以定义下面的子程序来读取namespaceArray

def get_namespace_array(self):
        ns_node = self.get_node(ua.NodeId(ua.ObjectIds.Server_NamespaceArray))
        return ns_node.get_value()

打印返回的namespace

['http://opcfoundation.org/UA/', 'urn:freeopcua:python:server', 'http://www.maxim.org/pac/', 'http://www.maxim.org/fbs/', 'http://www.maxim.org/app/']

从上可见,在python-opcua 中,增加了一个URI 为'urn:freeopcua:python:server' 的命名空间。

一个完整的代码

import sys
sys.path.insert(0, "..")
import time
from opcua import ua, Server
def get_namespace_array(self):

        ns_node = self.get_node(ua.NodeId(ua.ObjectIds.Server_NamespaceArray))
        return ns_node.get_value()
if __name__ == "__main__":

    # setup our server
    server = Server()
    
    server.set_endpoint("opc.tcp://localhost:48400/freeopcua/server/")     
    server.application_uri = "urn:freeopcua:python:server"     
    nodes=server.import_xml("E:/yao2023/Model1/pac.NodeSet2.xml")
    nodes=server.import_xml("E:/yao2023/Model1/OpcUaLib.NodeSet2.xml") 
    nodes=server.import_xml("E:/yao2023/Model1/app.NodeSet2.xml") 
    print(get_namespace_array(server))
    uri = "http://www.maxim.org/app/"
    idx = server.register_namespace(uri)
    # get Objects node, this is where we should put our nodes
    objects = server.get_objects_node()
    # populating our address space
    myobj = objects.add_object(idx, "MyObject")
    myvar = myobj.add_variable(idx, "MyVariable", 6.7)
    myvar.set_writable()    # Set MyVariable to be writable by clients
    
    # starting!
    server.start()
  
    try:
        count = 0
        while True:
            time.sleep(1)
            count += 0.1
            myvar.set_value(count)
    finally:
        #close connection, remove subcsriptions, etc
        server.stop()

你可能感兴趣的:(python,OPCUA)