【问题标题】:freeOPCUA Python multiple subscriptions免费OPCUA Python多订阅
【发布时间】:2018-03-17 00:28:36
【问题描述】:

我正在为 python opcua github 使用最小的示例客户端和服务器,我似乎无法弄清楚如何以不同的时间间隔订阅多个变量。我想做的是以高频率更新某些值,而以低得多的频率更新其他值。

我通过将列表传递给成功

handle = sub.subscribe_data_change(monitoredNodes)

monitoredNodes 是 nodeID 的列表。

但是,如果在 subHandler 中触发数据更改事件,则列表中的任何变量都会发生更改,并且我正在使用 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()

【问题讨论】:

  • 更新:我设法通过加倍订阅了 2 次。我创建了一个新的 SubHandler 类、第二个处理程序对象、第二个子对象和第二个句柄对象。这似乎比使用一长串 if 语句进行单个订阅更糟糕。我是否从根本上解决了这个错误?

标签: python-3.x opc-ua


【解决方案1】:

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

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

【讨论】:

  • 我建议重新检查规范,因为实现可能总是不完整/错误/等等。订阅时,您有每个整个订阅的发布间隔,并且您有给定节点的采样间隔。因此,您应该不可能获得比采样要求的更密集(及时)的值。更重要的是,OPC 服务器应该保证你没有虚假的更改,即假设你在某个节点有值 5,然后在小时后服务器被告知写“5”(相同的值),这样的更改应该被拒绝并且您不会在订阅中看到它(理论上)。
猜你喜欢
  • 2018-09-19
  • 2010-10-25
  • 1970-01-01
  • 2017-03-03
  • 2018-06-09
  • 2022-11-05
  • 2014-02-01
  • 1970-01-01
  • 2018-12-01
相关资源
最近更新 更多