单功能块应用研究(2)

为了进一步研究单功能块应用,我编写了一个演示程序。在这个演示中,包含了两个单功能应用

  • ECycle_1
  • FunctionBlock

        ECycle_1 定时产生一个输出事件EO,触发FunctionBlock 的输入事件EI。触发内部的算法EI_Algorithem。 两个功能块通过Opcua 的Client/Server 协议交换数据和事件。

单功能块应用研究(2)_第1张图片

 Cycle_1 Server代码

import sys
sys.path.insert(0, "..")
import time
from opcua import ua, Server
from ThreadClient import ThreadClient
class InputEventHandler(object):
   def datachange_notification(self, node, val, data):
       EventName=node.get_browse_name().Name
       print(EventName+" Trigged")
       if EventName=="EI":
           self.EI_Algorithm()
   def EI_Algorithm(self):
       print("EI_Algorithm in pocessing")
if __name__ == "__main__":

    # setup Aggregation server
    server = Server()    
    server.set_endpoint("opc.tcp://localhost:48400/freeopcua/server/")     
    server.application_uri = "urn:freeopcua:python:server"     
    #server.import_xml("OpcUaModbus.NodeSet2.xml") 
    # Create aggregation information model
    uri = "http://www.maxim.org/OpcUaAggregation/"
    idx = server.register_namespace(uri)
    objects = server.get_objects_node() 
    #Create 
    FunctionBlock=objects.add_folder(idx, "ECycle_1")
    InputEvents=FunctionBlock.add_folder(idx,"InputEvents")
    OutputEvents=FunctionBlock.add_folder(idx,"OutputEvents")
    InputVars=FunctionBlock.add_folder(idx,"InputVars")
    OutputVars=FunctionBlock.add_folder(idx,"OutputVars")
    Event_EI=InputEvents.add_variable(idx,"EI",ua.Variant(False, ua.VariantType.Boolean))
    Event_EO=OutputEvents.add_variable(idx,"EO",ua.Variant(False, ua.VariantType.Boolean))
    
    server.start()
    handler = InputEventHandler()
    sub = server.create_subscription(100, handler)
    sub.subscribe_data_change(Event_EI)
    ThreadClient=ThreadClient("Client")
    ThreadClient.start()
    # main Loop
    try:
        Event_state = True
        while True:
            time.sleep(5)
            Event_state=not Event_state
            Event_EO.set_data_value(Event_state)
            ThreadClient.Notify_Event("2:EI",Event_state)

    finally:
        #close connection, remove subcsriptions, etc
        server.stop()
        ThreadClient.stop()

Cycle_1 Client 代码

import threading
from opcua import ua , Client
import time
#from Common import get_variables,get_Node_Path,get_Node_By_Name
class ThreadClient(threading.Thread):
    def __init__(self,Name):
        threading.Thread.__init__(self)  
        self._stopper = threading.Event()
        self.Name=Name
        self.client = Client("opc.tcp://localhost:48410/freeopcua/server/")
        
    def stop(self): 
       self._stopper.set()  
  
    def stopped(self): 
        return self._stopper.isSet()  
    def Notify_Event(self,TargetEvent,val):
        Path=["0:Objects","2:FunctionBlock","2:InputEvents",TargetEvent]
        #print(Path)
        root = self.client.get_root_node()
        node=root.get_child(Path)
        #print(node)
        self.client.set_values([node],[val])
    def run(self):
        #Start
        try:
            self.client.connect()
            root = self.client.get_root_node()
            print("Objects node is: ", root)
            while True:
                #print("Client")
                time.sleep(2)                
        finally:
            self.client.disconnection()
                         

FunctionBlock Server 代码

import sys
sys.path.insert(0, "..")
import time
from opcua import ua, Server
from ThreadClient import ThreadClient
class InputEventHandler(object):
     def datachange_notification(self, node, val, data):
         EventName=node.get_browse_name().Name
         print(EventName+" Trigged")
         if EventName=="EI":
             self.EI_Algorithm()
     def EI_Algorithm(self):
         print("EI_Algorithm in pocessing")
if __name__ == "__main__":

    # setup Aggregation server
    server = Server()    
    server.set_endpoint("opc.tcp://localhost:48410/freeopcua/server/")     
    server.application_uri = "urn:freeopcua:python:server"     
    #server.import_xml("OpcUaModbus.NodeSet2.xml") 
    # Create aggregation information model
    uri = "http://www.maxim.org/OpcUaAggregation/"
    idx = server.register_namespace(uri)
    objects = server.get_objects_node() 
    #Create 
    FunctionBlock=objects.add_folder(idx, "FunctionBlock")
    InputEvents=FunctionBlock.add_folder(idx,"InputEvents")
    OutputEvents=FunctionBlock.add_folder(idx,"OutputEvents")
    InputVars=FunctionBlock.add_folder(idx,"InputVars")
    OutputVars=FunctionBlock.add_folder(idx,"OutputVars")
    Event_EI=InputEvents.add_variable(idx,"EI",ua.Variant(False, ua.VariantType.Boolean))
    Event_EO=OutputEvents.add_variable(idx,"EO",ua.Variant(False, ua.VariantType.Boolean))
    Event_EI.set_writable()
    Event_EO.set_writable()
    server.start()
    handler = InputEventHandler()
    sub = server.create_subscription(100, handler)
    sub.subscribe_data_change(Event_EI)
    #ThreadClient=ThreadClient("Client")
    #ThreadClient.start()
    # main Loop
    try:
        Event_state = True
        while True:
            time.sleep(5)
            #Event_state=not Event_state
            #Event_EO.set_data_value(Event_state)
            #ThreadClient.Notify_Event("EO",Event_state)
         
    finally:
        #close connection, remove subcsriptions, etc
        server.stop()
        #ThreadClient.stop()

 进一步的完善

       上面的例子仅仅是一个演示程序,从它可以看出一个单一功能块如何在没有Runtime 的情形下独立运行。在云端,能够将该应用程序在Docker 中运行。由于不需要runtime,使编程变得异常简单。可以使用Golang,C#,C++,javascript 等各种语言简单实现。

进一步地完善包括

1 每个单功能块需要有一个JSON 格式的Configuration 配置文档。

2 当功能块网络生成时,要将EventConnection 和DataConnection 的信息添加到信息模型中,比较好的方法是将OutputEvent 中包含Target URI 信息,Client 能够将事件输出注入目标功能块。OutputData 是通过目标功能块的Client 来读取数据的。也可以采取源功能块注入的方法。

3 进一步设计多种语言的单应用程序的标准模板

你可能感兴趣的:(网络)