Python 3.x freeOPCUA Python多个订阅

Python 3.x freeOPCUA Python多个订阅,python-3.x,opc-ua,Python 3.x,Opc Ua,我使用的是python opcua github的最小示例客户机和服务器,我似乎不知道如何以不同的间隔订阅多个变量。我想做的是以较高的频率更新某些值,而以较低的频率更新其他值 我成功地将列表传递给了 handle = sub.subscribe_data_change(monitoredNodes) monitoredNodes是节点ID的列表 但是,只要列表中的任何变量发生变化,if就会在子句柄中触发数据更改事件,我将使用if语句来确定哪个变量发生了变化。如果我想订阅1000个变量,那么为每

我使用的是python opcua github的最小示例客户机和服务器,我似乎不知道如何以不同的间隔订阅多个变量。我想做的是以较高的频率更新某些值,而以较低的频率更新其他值

我成功地将列表传递给了

handle = sub.subscribe_data_change(monitoredNodes)
monitoredNodes是节点ID的列表

但是,只要列表中的任何变量发生变化,if就会在子句柄中触发数据更改事件,我将使用if语句来确定哪个变量发生了变化。如果我想订阅1000个变量,那么为每个事件运行100个If语句似乎既麻烦又低效

如果有人有这方面的经验,我想在这里谈谈如何妥善处理这一问题。下面是我稍微修改过的示例客户端的代码

import sys
sys.path.insert(0, "..")
import re
from IPython import embed


from opcua import Client

def getChildren(node):
 children = extractName(root.get_child(node).get_children_descriptions())
 return children

def extractName(description):
 qualifiedNames = re.findall(r"QualifiedName\(.*?\)", str(description))
 nodeNames = re.findall("\d:[a-z,A-Z_]*", str(qualifiedNames))
 return nodeNames

class SubHandler(object):

def datachange_notification(self, node, val, data):
    pass
    #print("Python: New data change event", node, val)

def event_notification(self, event):
    print("Python: New event", event)


if __name__ == "__main__":

client = Client("opc.tcp://0.0.0.0:4840/freeopcua/server/")
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.get_browse_name())

    # 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())

    rootNode = extractName(str(root.get_children_descriptions()))
    print(rootNode)
    print('''
    The following nodes are found on root.
    Press enter the corresponding number to go deeper.
    ''')
    path = ['0:Objects']
    children=[]

    while True:
        for node in enumerate(getChildren(path)):
            print(node[0], ": ", node[1])
        print("Enter 99 to exit or 88 to go back to top")
        sel = int(input('Please make a selection\n' ))
        if sel == 99:
            break
        elif sel == 88:
            path = []
            children = []
        elif sel == 11:
            print(path)
            print(root.get_child(path).get_value())
            print(root.get_child(path))
        else:
            if path == []:
                path.append(rootNode[sel])
                #print(path)
                #print(getChildren(path))
            else:
                children = getChildren(path)
                path.append(children[sel])
                #print(getChildren(path))

    # 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.get_value())

    # subscribing to a variable node
    handler = SubHandler()
    sub = client.create_subscription(500, handler)
    handle = sub.subscribe_data_change(myvar)

    embed()
finally:
    client.disconnect()

好的,所以对于任何试图做我想做的事情并且有问题的人来说。我认为对只想更新特定间隔的变量使用订阅不是正确的方法。似乎通过订阅一个变量,您将获得该变量的所有更改。如果您的订阅期长于其更改速率,则更改事件将触发多次,其中包含自上次更新以来的所有历史更改。这不是我想要的


相反,我建议使用类似于python的apscheduler模块中的计时器任务,并定期读取变量。这似乎正是我想要的。

更新:我通过将所有内容加倍,成功订阅了2份。我创建了一个新的子句柄类、第二个句柄对象、第二个子对象和第二个句柄对象。这似乎比使用一长串if语句进行单个订阅更糟糕。从根本上说,我是不是搞错了?我建议重新检查规范,因为实现可能总是不完整的/有缺陷的/等等。订阅时,对于整个订阅,您有发布间隔,对于给定节点,您有采样间隔。因此,您不可能获得比采样要求更密集的(时间)值。更重要的是,OPC服务器应该保证您没有虚假的更改,例如,假设您在某个节点中有值5,然后在服务器被告知写入“5”(相同的值)后,应该拒绝此类更改,并且您不会在订阅中看到它(理论上)。