2017-10-05 434 views
1

我使用python opcua github的最小示例客戶端和服務器,我似乎無法弄清楚如何以不同的時間間隔訂閱多個變量。我想要做的是將某些數值以較高的頻率更新,而其他的以較低的頻率更新。freeOPCUA Python多訂閱

我傳遞一個列表成功的

handle = sub.subscribe_data_change(monitoredNodes) 

monitoredNodes作爲nodeIDs的列表。

然而,任何時候,如果在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類,第二個處理程序對象,第二個子對象和第二個處理對象。這看起來比使用if語句很長的單個訂閱更糟糕。我從根本上解決這個問題嗎? – uprightcarrion

回答

0

好的,以便任何人試圖做我想做的事情和有問題。我認爲使用訂閱的變量,你只想更新一個特定的時間間隔是不正確的。看起來,通過訂閱一個變量,您將獲得該變量的每一個變化。如果您的訂閱期限長於其更改的速率,那麼更改事件將使用自上次更新以來的所有歷史更改進行多次啓動。這不是我想要的。

相反,我會建議在apscheduler模塊中使用類似python的計時器任務,並定期對變量執行讀操作。這似乎是做我想要的。

+0

我會建議重新檢查規範,因爲執行可能總是不完整/馬車/等。訂閱時,每個訂閱都有發佈時間間隔,並且您有給定節點的採樣時間間隔。所以你應該沒有機會獲得比採樣指令更密集(及時)的值。更重要的是,OPC服務器應該保證你沒有假的變化,也就是說你在某個節點有價值5,然後在服務器被告知寫入「5」(相同的值)之後,這樣的變化應該被拒絕並且你不會在訂閱中看到它(理論上)。 – astrowalker