2017-10-05 16 views
1

私はpython opcua githubのための最小限のサンプルクライアントとサーバーを使用しています。異なる間隔で複数の変数をサブスクライブする方法を理解できないようです。私がやりたいことは、特定の値を高い頻度で更新し、他の値をはるかに低い頻度で更新することです。freeOPCUA Python複数のサブスクリプション

私は

handle = sub.subscribe_data_change(monitoredNodes) 

monitoredNodesは、ノード識別子のリストであることにリストを渡すことに成功しました。

しかし、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() 
+0

更新:私はすべてを倍増させて2つのサブスクリプションを作りました。私は新しいSubHandlerクラス、2番目のハンドラオブジェクト、2番目のサブオブジェクト、2番目のハンドルオブジェクトを作成しました。これは、if文の長いリストで単一のサブスクリプションを行うよりも悪いようです。私は根本的にこれについて間違っていますか? – uprightcarrion

答えて

0

私がやろうとしていることや問題がある人は、私はあなたが特定の間隔を更新するだけの正しい方法ではない変数のサブスクリプションを使用すると思います。変数を購読すれば、その変数のすべての変更が得られるようです。サブスクリプション期間が変更されたレートよりも長い場合、変更イベントは最後の更新以降のすべての履歴変更で複数回発生します。これは私が望んでいたものではありません。

代わりに、私はPython用のapschedulerモジュールのようなタイマータスクを使用し、定期的な間隔で変数の読み取りを実行することをお勧めします。これは私がしたいことをするようです。

+0

実装が常に不完全/バグ/などである可能性があるので、私は仕様を再確認することを提案します。サブスクリプション時には、サブスクリプション全体のパブリッシュ間隔があり、指定されたノードのサンプリング間隔があります。だから、サンプリングの指示よりも(時間的に)より高密度になる可能性はないはずです。さらに、OPCサーバーでは、偽の変更がないことを保証する必要があります。つまり、ノード5に値5があり、サーバーに「5」(同じ値)を書き込むように指示された後、その変更は拒否されます。あなたはサブスクリプション(理論上)でそれを見ることはできません。 – astrowalker

関連する問題