def start(): mServer = Server() mServer.set_endpoint(URL) mServer.set_security_policy([ ua.SecurityPolicyType.NoSecurity, ua.SecurityPolicyType.Basic256Sha256_SignAndEncrypt, ua.SecurityPolicyType.Basic256Sha256_Sign ]) address_space = mServer.register_namespace(NAMESPACE_NAME) root_node = mServer.get_objects_node() params = root_node.add_object(address_space, "Parameters") start_time = params.add_variable(address_space, "start_time", start_timestamp) data = root_node.add_object(address_space, "data") pump = data.add_object(address_space, "Pump") temperature = 20 + random.randint(0, 10) pump_temp_var = pump.add_variable(address_space, "temperature", temperature) pump_temp_vup = VarUpdater( pump_temp_var) # just a dummy class update a variable pump_temp_unit = pump.add_variable(address_space, "unit", "°C") pump_status = pump.add_variable(address_space, "status", False) pump_status.set_writable() level = 12 pump_level = pump.add_variable(address_space, "level", level) pump_level.set_writable() sleep_period = 0.5 # Start the server mServer.start() print("Server started at {}".format(URL)) print("root_node: " + root_node.__str__()) print("params: " + params.__str__()) print("pump: " + pump.__str__()) # print(""+pump) # enable following if you want to subscribe to nodes on server side handler = SubHandler() sub = mServer.create_subscription(500, handler) handle = sub.subscribe_data_change(pump_level) # IMPORTANT: This should be started after the mServer.start() pump_temp_vup.start() try: while True: time.sleep(sleep_period) finally: # close connection, remove subscriptions, etc pump_temp_vup.stop() # should be stopped mServer.stop()
def main(): # logging.basicConfig(level=logging.ERROR) # logger=logging.getLogger("opcua.server.internal_subscription") # logger.setLevel(logging.ERROR) read = open('config.txt', 'r') configs = read.readlines() read.close() server = Server() endpoint = configs[0].split('@')[1].rstrip('\n') servername = configs[1].split('@')[1].rstrip('\n') kafkaservers = configs[2].split('@')[1].replace("'", "").replace( "\"", "").rstrip('\n') kafkaserver = kafkaservers[1:-1].split(',') kafkatopic = configs[3].split('@')[1].rstrip('\n') eventname = configs[4].split('@')[1].rstrip('\n') # auto_offset_reset='earlist' consumer = KafkaConsumer(kafkatopic, bootstrap_servers=kafkaserver) server.set_endpoint(endpoint) server.set_server_name(servername) print("Program running......") print("Please do not close this page") # 证书 # server.load_certificate("certificate-example.der") # server.load_private_key("private-key-example.pem") # 安全策略 server.set_security_policy([ ua.SecurityPolicyType.NoSecurity, # ua.SecurityPolicyType.Basic256Sha256_SignAndEncrypt, # ua.SecurityPolicyType.Basic256Sha256_Sign ]) uri = "http://taiji.com.cn" idx = server.register_namespace(uri) objs = server.get_objects_node() myobj = objs.add_object(idx, "MyObject") # 节点 taglists = readFile("node.csv") for taglist in taglists: # myobj.add_variable(idx, taglist, 6.7).set_writable() myobj.add_variable(idx, taglist, random.random()).set_writable() # myobj.add_variable(idx, taglist, 6.7) attrs = readFile("ae_attr.csv") custom_etype = server.nodes.base_event_type.add_object_type(idx, eventname) for attr in attrs: custom_etype.add_property(2, attr, ua.Variant("", ua.VariantType.String)) myevent = server.get_event_generator(custom_etype, myobj) server.start() try: rootnode = server.get_root_node().get_child( ["0:Objects", "{}:MyObject".format(idx)]) rootnodes = rootnode.get_variables() nodeAll = {} for i in range(len(rootnodes)): nodeId = rootnodes[i] nodeName = rootnodes[i].get_browse_name().Name nodeAll.update({nodeName: nodeId}) for message in consumer: recv = message.value.decode("utf8") # print("recvevent=",recv) if recv[0] == '{' and recv[-1] == '}': nodeKafka = json.loads(recv) # print("nodeKafka=", nodeKafka) comName = nodeKafka.keys() & nodeAll.keys() for row in comName: rootnode.get_child(["2:{}".format(row) ]).set_value(nodeKafka[row]) else: recv = recv.replace('\n', '').replace('\r', '') datas = recv.split("|")[1:] # print("datas=", datas) if len(datas) == 9: for i in range(len(attrs)): # exec("myevent.event.{}='{}'".format(attrs[i], datas[i].replace('\n', '').replace('\r', ''))) exec("myevent.event.{}='{}'".format( attrs[i], datas[i])) myevent.trigger() else: # continue f = open('ErrorAE.bak', 'a', encoding='utf8') f.write(recv) f.write('\n') f.close # print("mysecondevgen=",mysecondevgen) # print("mysecondevgen=", myevent.event) except Exception as e: print(e) finally: server.stop()
print("device has been stopped") if __name__ == "__main__": logger = logging.getLogger() logger.setLevel(logging.WARNING) logging.basicConfig(stream=sys.stdout) server = Server() server.set_endpoint("opc.tcp://0.0.0.0:4840/freeopcua/server/") server.set_server_name("FreeOpcUa Example Server") # set all possible endpoint policies for clients to connect through server.set_security_policy([ ua.SecurityPolicyType.Basic256Sha256_Sign, ua.SecurityPolicyType.Basic256Sha256_SignAndEncrypt, ]) server.load_certificate("cert.pem") server.load_private_key("key.pem") server.user_manager.user_manager = lambda session, username, password: username == "testuser" and password == "testpass2" # setup our own namespace uri = "http://examples.freeopcua.github.io" idx = server.register_namespace(uri) # direct directly some objects and variables device = server.nodes.objects.add_object(idx, "device") device_switch = device.add_variable(idx, "switch", True)
ua.Variant(db_value, ua.VariantType.UInt64) #Value from database ) if __name__ == "__main__": """ OPC-UA-Server Setup """ server = Server() server.set_endpoint("opc.tcp://127.0.0.1:4840") server.set_server_name("PythonOpcUaServer") security_policy = [ ua.SecurityPolicyType.NoSecurity, #ua.SecurityPolicyType.Basic256Sha256_SignAndEncrypt, #ua.SecurityPolicyType.Basic256Sha256_Sign ] server.set_security_policy(security_policy) policyIDs = [ "Anonymous", "Basic256Sha256", "Username" ] server.set_security_IDs(policyIDs) address_space = server.register_namespace("http://andreas-heine.net/UA") """ OPC-UA-Modeling """ root_node = server.get_root_node() object_node = server.get_objects_node() server_node = server.get_server_node() #S7-1500 Checks frequently the service level so make sure it has a value (http://documentation.unified-automation.com/uasdkcpp/1.5.3/html/L2ServerRedundancy.html) servicelevel_node = server.get_node("ns=0;i=2267") #Service-Level Node
class StationUAServer: def __init__(self, pick_by_light): self._pbl = pick_by_light self._setup_nodes() self._generate_tags() self.ua_server.start() self._generate_subscriptions() Thread(target=self._var_updater, daemon=True).start() def _setup_nodes(self): # Create server instance self.ua_server = Server('./opcua_cache') self.ua_server.set_endpoint('opc.tcp://0.0.0.0:4840/UA/PickByLight') self.ua_server.set_server_name("Pick By Light Server") # idx name will be used later for creating the xml used in data type dictionary # setup our own namespace, not really necessary but should as spec idx_name = 'http://examples.freeopcua.github.io' self.idx = self.ua_server.register_namespace(idx_name) # Set all possible endpoint policies for clients to connect through self.ua_server.set_security_policy([ ua.SecurityPolicyType.NoSecurity, ua.SecurityPolicyType.Basic128Rsa15_SignAndEncrypt, ua.SecurityPolicyType.Basic128Rsa15_Sign, ua.SecurityPolicyType.Basic256_SignAndEncrypt, ua.SecurityPolicyType.Basic256_Sign ]) # get Objects node, this is where we should put our custom stuff objects = self.ua_server.get_objects_node() # Create objects for the pack tags using the above created packMLBasedObjectType self.Status = objects.add_folder('ns=2;s=Status', "Status") self.Command = objects.add_folder('ns=2;s=Command', "Command") self.Command.add_method('ns=2;s=Command.SelectPort', "SelectPort", self._select_method, [ua.VariantType.Int32, ua.VariantType.String], [ua.VariantType.Boolean]) self.Command.add_method('ns=2;s=Command.DeselectPort', "DeselectPort", self._deselect_method, [ua.VariantType.Int32], [ua.VariantType.Boolean]) self.Command.add_method('ns=2;s=Command.DeselectAllPorts', "DeselectAllPorts", self._deselect_all_method, [], [ua.VariantType.Boolean]) root = self.ua_server.get_root_node() DummyFestoObj = root.add_object( "ns=2;s=|var|CECC-LK.Application.Flexstation_globalVariables", "DummyFesto") DummyFestoObj.add_variable( "ns=2;s=|var|CECC-LK.Application.Flexstation_globalVariables.FlexStationStatus", "FlexStationStatus", val=0).set_writable() DummyFestoObj.add_variable( "ns=2;s=|var|CECC-LK.Application.FBs.stpStopper1.stAppControl.uiOpNo", "uiOpNo", val=0).set_writable() DummyFestoObj.add_variable( "ns=2;s=ns=2;s=|var|CECC-LK.Application.AppModul.stRcvData.sOderDes", "sOderDes", val="").set_writable() def _generate_tags(self): # for all ports generate tags for port_number, port in self._pbl.get_ports(): # Make a folder with the port_number as the name b_obj = self.Status.add_object( 'ns=2;s=Status.Port_{}'.format(port_number), "Port_{}".format(port_number)) content = self._pbl.get_content(port_number) b_obj.add_variable( "ns=2;s=Status.Port_{}.Selected".format(port_number), "Selected", bool()) b_obj.add_variable( "ns=2;s=Status.Port_{}.WorkFinished".format(port_number), "WorkFinished", bool()) b_obj.add_variable( "ns=2;s=Status.Port_{}.Instructions".format(port_number), "Instructions", "") b_obj.add_variable( "ns=2;s=Status.Port_{}.Activity".format(port_number), "Activity", bool()) b_obj.add_variable( "ns=2;s=Status.Port_{}.ActivityTimestamp".format(port_number), "ActivityTimestamp", datetime.fromtimestamp(0)) b_obj.add_variable( "ns=2;s=Status.Port_{}.LightState".format(port_number), "LightState", 0) b_obj.add_variable( "ns=2;s=Status.Port_{}.ContentDisplayName".format(port_number), "ContentDisplayName", content['display_name']) b_obj.add_variable( "ns=2;s=Status.Port_{}.ContentName".format(port_number), "ContentName", content['name']) b_obj.add_variable( "ns=2;s=Status.Port_{}.ContentDescription".format(port_number), "ContentDescription", content['description']) b_obj.add_variable( "ns=2;s=Status.Port_{}.ContentImagePath".format(port_number), "ContentImagePath", content['image_path']) ''' create command tags for clients that does not support ua methods. ''' b_obj = self.Command.add_object( 'ns=2;s=Command.Port_{}'.format(port_number), "Port_{}".format(port_number)) b_obj.add_variable( "ns=2;s=Command.Port_{}.Select".format(port_number), "Select", bool()).set_writable() b_obj.add_variable( "ns=2;s=Command.Port_{}.Deselect".format(port_number), "Deselect", bool()).set_writable() b_obj.add_variable( "ns=2;s=Command.Port_{}.Instructions".format(port_number), "Instructions", "").set_writable() b_obj.add_variable( "ns=2;s=Command.Port_{}.ContentDisplayName".format( port_number), "ContentDisplayName", content['display_name']).set_writable() b_obj.add_variable( "ns=2;s=Command.Port_{}.ContentName".format(port_number), "ContentName", content['name']).set_writable() b_obj.add_variable( "ns=2;s=Command.Port_{}.ContentDescription".format( port_number), "ContentDescription", content['description']).set_writable() b_obj.add_variable( "ns=2;s=Command.Port_{}.ContentImagePath".format(port_number), "ContentImagePath", content['image_path']).set_writable() ''' Generate some common commands ''' # Make a folder for the commons b_obj = self.Command.add_object('ns=2;s=Command.ByContent', 'ByContent') b_obj.add_variable("ns=2;s=Command.ByContent.Select", "Select", bool()).set_writable() b_obj.add_variable("ns=2;s=Command.ByContent.Deselect", "Deselect", bool()).set_writable() b_obj.add_variable("ns=2;s=Command.ByContent.Name", "Name", "").set_writable() b_obj.add_variable("ns=2;s=Command.ByContent.Instructions", "Instructions", "").set_writable() b_obj.add_variable("ns=2;s=Command.ByContent.Result", "Result", -1).set_writable() def _generate_subscriptions(self): # Create UA subscriber node for the box. Set self as handler. sub = self.ua_server.create_subscription(100, self) # Subscribe to the Select tag and all the content tags for port_number, port in self._pbl.get_ports(): ac = self.ua_server.get_node( "ns=2;s=Command.Port_{}.Select".format(port_number)) sub.subscribe_data_change(ac) ac = self.ua_server.get_node( "ns=2;s=Command.Port_{}.Deselect".format(port_number)) sub.subscribe_data_change(ac) b = self.ua_server.get_node( "ns=2;s=Command.Port_{}.ContentDisplayName".format( port_number)) sub.subscribe_data_change(b) c = self.ua_server.get_node( "ns=2;s=Command.Port_{}.ContentName".format(port_number)) sub.subscribe_data_change(c) d = self.ua_server.get_node( "ns=2;s=Command.Port_{}.ContentDescription".format( port_number)) sub.subscribe_data_change(d) e = self.ua_server.get_node( "ns=2;s=Command.Port_{}.ContentImagePath".format(port_number)) sub.subscribe_data_change(e) a = self.ua_server.get_node("ns=2;s=Command.ByContent.Select") sub.subscribe_data_change(a) a = self.ua_server.get_node("ns=2;s=Command.ByContent.Deselect") sub.subscribe_data_change(a) a = self.ua_server.get_node("ns=2;s=Command.ByContent.Name") sub.subscribe_data_change(a) a = self.ua_server.get_node( "ns=2;s=Command.ByContent.Instructions") sub.subscribe_data_change(a) def _event_notification(self, event): logger.warning( "Python: New event. No function implemented. {}".format(event)) def _select_method(self, parrent, port_number, instructions): r = self._pbl.select_port(port_number.Value, instructions=instructions.Value) return [ua.Variant(value=r, varianttype=ua.VariantType.Boolean)] def _deselect_method(self, parrent, port_number): r = self._pbl.deselect_port(port_number.Value) return [ua.Variant(value=r, varianttype=ua.VariantType.Boolean)] def _deselect_all_method(self, parrent): r = self._pbl.deselect_all() return [ua.Variant(value=r, varianttype=ua.VariantType.Boolean)] def datachange_notification(self, node, val, data): """UA server callback on data change notifications Arguments: node {Node} -- [description] val {[type]} -- [description] data {[type]} -- [description] """ logger.debug("New data change event. node:{}, value:{}".format( node, val)) # Sorry about these lines of code, but I don't see any nicer way of determining the port number than from # the identifier string. Then splitting it up to isolate the port number. # Example "Status.Port_2.Selected" is split into ['Status', 'Port_2', 'Selected'] then 'Port_2' is split into # ['Port', '2'] and then the '2' is turned into an intiger. path_list = str(node.nodeid.Identifier).split(".") # We can safely assume that the last term is the tag that updated. tag = path_list[-1] # Figure out the port number port_number = None if 'Port' in path_list[1]: port_number = int(path_list[1].split("_")[-1]) """ Switch for each possible tag""" # If the command tag "Select" changes go select that port with the instructions saved in the command tag. if tag == 'Select' and port_number: if val == True: node = self.ua_server.get_node( "ns=2;s=Command.Port_{}.Instructions".format(port_number)) instructions = node.get_value() self._pbl.select_port(port_number, instructions=instructions) # Reset the select flag node = self.ua_server.get_node( "ns=2;s=Command.Port_{}.Select".format(port_number)) node.set_value(False) elif tag == 'Deselect' and port_number: if val == True: self._pbl.deselect_port(port_number, work_finished=True) # Reset the select flag node = self.ua_server.get_node( "ns=2;s=Command.Port_{}.Deselect".format(port_number)) node.set_value(False) elif tag == 'ContentDisplayName' and port_number: self._pbl.set_content_key(port_number, 'display_name', str(val)) elif tag == 'ContentName' and port_number: self._pbl.set_content_key(port_number, 'name', str(val)) elif tag == 'ContentDescription' and port_number: self._pbl.set_content_key(port_number, 'description', str(val)) elif tag == 'ContentImagePath' and port_number: self._pbl.set_content_key(port_number, 'image_path', str(val)) elif tag == 'Select' and 'ByContent' in path_list[1]: if val == True: instructions = self.ua_server.get_node( "ns=2;s=Command.ByContent.Instructions").get_value() name = self.ua_server.get_node( "ns=2;s=Command.ByContent.Name").get_value() _, selected_port = self._pbl.select_content( name=name, instructions=instructions) # Reset the select flag node = self.ua_server.get_node( "ns=2;s=Command.ByContent.Select") node.set_value(False) node = self.ua_server.get_node( "ns=2;s=Command.ByContent.Result") node.set_value(selected_port) elif tag == 'Deselect' and 'ByContent' in path_list[1]: if val == True: name = self.ua_server.get_node( "ns=2;s=Command.ByContent.Name").get_value() self._pbl.deselect_content(name=name, work_finished=True) # Reset the select flag node = self.ua_server.get_node( "ns=2;s=Command.ByContent.Deselect") node.set_value(False) def _var_updater(self): while True: sleep(0.1) # for all boxes update tags for port_number, port in self._pbl.get_ports(): # get the object in the packml status object using our unique idx node = self.ua_server.get_node( "ns=2;s=Status.Port_{}.Activity".format(port_number)) node.set_value(port.activity) node = self.ua_server.get_node( "ns=2;s=Status.Port_{}.ActivityTimestamp".format( port_number)) node.set_value(port.activity_timestamp) node = self.ua_server.get_node( "ns=2;s=Status.Port_{}.LightState".format(port_number)) node.set_value(port.get_light()) state = self._pbl.get_port_state(port_number) node = self.ua_server.get_node( "ns=2;s=Status.Port_{}.Selected".format(port_number)) node.set_value(state.selected) node = self.ua_server.get_node( "ns=2;s=Status.Port_{}.WorkFinished".format(port_number)) node.set_value(state.work_finished) node = self.ua_server.get_node( "ns=2;s=Status.Port_{}.Instructions".format(port_number)) node.set_value(state.select_instructions) content = self._pbl.get_content(port_number) node = self.ua_server.get_node( "ns=2;s=Status.Port_{}.ContentDisplayName".format( port_number)) node.set_value(content['display_name']) node = self.ua_server.get_node( "ns=2;s=Status.Port_{}.ContentName".format(port_number)) node.set_value(content['name']) node = self.ua_server.get_node( "ns=2;s=Status.Port_{}.ContentDescription".format( port_number)) node.set_value(content['description']) node = self.ua_server.get_node( "ns=2;s=Status.Port_{}.ContentImagePath".format( port_number)) node.set_value(content['image_path'])
def __init__(self, name, shared): super().__init__(name, shared) self.logger = logging.getLogger(self.name) self.logger.info("init") self.shared.config.set_hidden_value(self.name, "user") self.shared.config.set_hidden_value(self.name, "password") self.shared.config.set_hidden_value(self.name, "password_hash") def config(key, val): return self.shared.config.config(self.name, key, val) endpoint = config("endpoint", "no_endpoint") certificate = config("certificate", "") private_key = config("private_key", "") uri = config("uri", "http://examples.freeopcua.github.io") root_object_name = config("root_object_name", "TEST") separator = config("separator", ".") namespace = config("namespace", 2) self.oldnew = config("oldnew_comparision", 0) admin_username = config("user", "admin") admin_password = config("password", "admin") admin_password_hash = config("password_hash", "").replace("$$", "$") security_ids = [] anonymous_on = config("anonymous_on", 0) username_on = config("username_on", 1) certificate_on = config("certificate_basic256sha256_on", 0) if anonymous_on: security_ids.append("Anonymous") if username_on: security_ids.append("Username") if certificate_on: security_ids.append("Basic256Sha256") security_policy = [] if config("nosecurity_on", 1): security_policy.append(ua.SecurityPolicyType.NoSecurity) if config("basic128rsa15_sign_on", 0): security_policy.append(ua.SecurityPolicyType.Basic128Rsa15_Sign) if config("basic128rsa15_signandencrypt_on", 0): security_policy.append( ua.SecurityPolicyType.Basic128Rsa15_SignAndEncrypt) if config("basic256_sign_on", 0): security_policy.append(ua.SecurityPolicyType.Basic256_Sign) if config("basic256_signandencrypt_on", 0): security_policy.append( ua.SecurityPolicyType.Basic256_SignAndEncrypt) if config("basic256sha256_sign_on", 1): security_policy.append(ua.SecurityPolicyType.Basic256Sha256_Sign) if config("basic256sha256_signandencrypt_on", 1): security_policy.append( ua.SecurityPolicyType.Basic256Sha256_SignAndEncrypt) initial_values_is_quality_good = config( "initial_values_is_quality_good", 0) if anonymous_on: server = Server() else: server = Server(iserver=CustomInternalServer()) server.iserver.set_parent(server) server.set_endpoint(endpoint) server.allow_remote_admin(False) if certificate and private_key: server.load_certificate(str(certificate)) server.load_private_key(str(private_key)) if security_ids: server.set_security_IDs(security_ids) if security_policy: server.set_security_policy(security_policy) def custom_user_manager(isession, userName, password): if userName != admin_username: return False if admin_password_hash: if werkzeug.security.check_password_hash( admin_password_hash, password): return True else: # fallback to plaintext if password == admin_password: return True return False if username_on: server.user_manager.set_user_manager(custom_user_manager) idx = server.register_namespace(uri) objects = server.get_objects_node() root = objects.add_object(idx, root_object_name) self.server = server self.objects = objects self.root = root self.sep = separator self.ns = namespace self.items = [] if initial_values_is_quality_good: self.initial_status_code = ua.StatusCodes.Good else: self.initial_status_code = ua.StatusCodes.BadWaitingForInitialData
#logger = logging.getLogger("opcua.internal_server") # logger.setLevel(logging.DEBUG) #logger = logging.getLogger("opcua.binary_server_asyncio") # logger.setLevel(logging.DEBUG) #logger = logging.getLogger("opcua.uaprocessor") # logger.setLevel(logging.DEBUG) # now setup our server server = Server() #server.disable_clock() #server.set_endpoint("opc.tcp://localhost:4840/freeopcua/server/") server.set_endpoint("opc.tcp://0.0.0.0:4840/freeopcua/server/") server.set_server_name("FreeOpcUa Example Server") # set possible endpoint policies for clients to connect through server.set_security_policy([ "None", "Basic128Rsa15_Sign", "Basic128Rsa15_SignAndEncrypt", "Basic256_Sign", "Basic256_SignAndEncrypt" ]) # setup our own namespace uri = "http://examples.freeopcua.github.io" idx = server.register_namespace(uri) # create a new node type we can instantiate in our address space dev = server.nodes.base_object_type.add_object_type(0, "MyDevice") dev.add_variable(0, "sensor1", 1.0).set_modelling_rule(True) dev.add_property(0, "device_id", "0340").set_modelling_rule(True) ctrl = dev.add_object(0, "controller") ctrl.set_modelling_rule(True) ctrl.add_property(0, "state", "Idle").set_modelling_rule(True) # populating our address space
class ServerOPC(): def __init__(self, sensori): self.keys=c_gpio.led_dict.keys() self.sensori=sensori self.__led=c_gpio.led_dict self.init_server() def init_server(self): print("inizio settaggio server") self.server=Server() #self.server.set_endpoint("opc.tcp://192.168.1.250:4840") self.server.set_endpoint("opc.tcp://0.0.0.0:4840") self.server.set_server_name("DomoticProject") #carico il certificato e la chiave privata global base_path file_path_cert=(base_path / "../config/certificati/my_cert.der").resolve() file_path_key=(base_path / "../config/certificati/my_private_key.pem").resolve() self.server.load_certificate(file_path_cert) self.server.load_private_key(file_path_key) self.server.set_security_policy([ ua.SecurityPolicyType.NoSecurity, ua.SecurityPolicyType.Basic256Sha256_SignAndEncrypt, ua.SecurityPolicyType.Basic256Sha256_Sign ]) #setup namespace uri="Domotic" self.idx=self.server.register_namespace(uri) self.objects=self.server.get_objects_node() #per contenere le info dei sensori self.sensors_o=self.objects.add_object(self.idx, "Sensori") self.temperatura_s=self.sensors_o.add_variable(self.idx, "Temperatura", 0.00) self.counterbagno_s=self.sensors_o.add_variable(self.idx, "Counter Bagno", 0) self.countersalotto_s=self.sensors_o.add_variable(self.idx, "Counter Salotto", 0) #per contenere le info dei led self.luci_o=self.objects.add_object(self.idx, "Luci") self.luci_o_dict={} for x in self.keys: self.luci_o_dict[x]=self.luci_o.add_variable(self.idx, "Luce "+x, False) self.luci_o_dict[x].set_writable() #per contenere i metodi self.method_o=self.objects.add_object(self.idx, "Metodi") inarg=ua.Argument() inarg.Name="stanza" inarg.DataType=ua.NodeId(ua.ObjectIds.String) inarg.ValueRank=-1 inarg.ArrayDimensions=[] inarg.Description=ua.LocalizedText("stanza su cui applicare il metodo ['salotto', 'camera', 'bagno', 'ingresso']") self.mymethod1=self.method_o.add_method(self.idx, "Accendi luce", self.accendi_luce, [inarg]) self.mymethod2=self.method_o.add_method(self.idx, "Spegni luce", self.spegni_luce, [inarg]) print("server settato") def run(self): print("start server") self.server.start() try: while True: val=ua.Variant(self.sensori["temperatura"], ua.VariantType.Float) val=ua.DataValue(val) val.SourceTimestamp=datetime.utcnow() val.ServerTimestamp=datetime.utcnow() self.temperatura_s.set_data_value(val) val2=ua.Variant(self.sensori["counter_bagno"], ua.VariantType.UInt16) val2=ua.DataValue(val2) val2.SourceTimestamp=datetime.utcnow() val2.ServerTimestamp=datetime.utcnow() self.counterbagno_s.set_data_value(val2) val3=ua.Variant(self.sensori["counter_salotto"], ua.VariantType.UInt16) val3=ua.DataValue(val3) val3.SourceTimestamp=datetime.utcnow() val3.ServerTimestamp=datetime.utcnow() self.countersalotto_s.set_data_value(val3) for x in self.keys: pin=self.__led[x] status=gpio.input(pin) var=ua.Variant(status, ua.VariantType.Boolean) s=ua.DataValue(var) s.SourceTimestamp=datetime.utcnow() s.ServerTimestamp=datetime.utcnow() self.luci_o_dict[x].set_value(s) time.sleep(1) finally: self.server.stop() @uamethod def accendi_luce(self, parent, stanza): pin=self.__led[stanza] if stanza=="salotto": s=gpio.input(2) gpio.output(2, 1) gpio.output(pin, 0) else: gpio.output(pin, 1) @uamethod def spegni_luce(self, parent, stanza): pin=self.__led[stanza] if stanza=="salotto": s=gpio.input(2) gpio.output(2, 0) gpio.output(pin, 1) else: gpio.output(pin, 0)
out_extobj.EURange.High = in_extobj.EURange.High out_extobj.Title = in_extobj.Title out_extobj.AxisScaleType = in_extobj.AxisScaleType out_extobj.AxisSteps = in_extobj.AxisSteps axis_info.set_value(out_extobj) #write values to variable ret = (ua.Variant(out_extobj, ua.VariantType.ExtensionObject), ua.Variant("test", ua.VariantType.String)) return ret server = Server() server.set_endpoint("opc.tcp://0.0.0.0:4840/freeopcua/server/") server.set_security_policy([ua.SecurityPolicyType.NoSecurity]) obj = server.get_objects_node() idx = server.register_namespace("http://examples.freeopcua.github.io") server.load_type_definitions() inarg_extobj = ua.Argument() inarg_extobj.Name = "In" inarg_extobj.DataType = ua.NodeId(12079, 0) inarg_extobj.ValueRank = -1 inarg_extobj.ArrayDimensions = [] inarg_extobj.Description = ua.LocalizedText("Wanted AxisInformation") outarg_extobj = ua.Argument() outarg_extobj.Name = "Out"
class IbaToUaServer(): """The Server will discover the iba files and prepare the Opc Server accordingly.""" def __init__(self): """Default constructor. Not magic here since everything is hard coded atm. Todo: Use config parser to configure the server a little bit """ # init super class constructors super().__init__() # list of path to iba files self.iba_files = list() # dictionary containing the channels of the iba files sorted by sample rate self.iba_info = dict() # dictionary of loaded iba data sorted by sample rate self.iba_data = dict() # handle to the actual opc ua server self._server = None # dictionary of threads for each unique sample rate self._value_updater = dict() def start(self): """The actual run function called by the Thread super class. All the magic happens here. 1. discover the iba files in the dat sub folder 2. get channels from the iba files 3. build the opc ua server 4. read the data 5. start the updating of the data :return: """ # discover iba files print('finding iba files ...') self.iba_files = self.discover_iba_files() # get channels from first iba file print('receiving channel info ...') self.iba_info = self.get_file_info(self.iba_files[0]) # build the opc server print('building opc server ...') self.init_opc() # start the server print('starting opc server ...') self._server.start() # create the value updater self._write_values() def discover_iba_files(self): """Call to get a list of iba files in the dat sub directory. :return: list of paths to iba files :raises: FileNotFoundError """ # where shall i search for files? iba_path = os.path.join(os.getcwd(), 'dat') # get the list of iba files file_list = getSortedIbaFiles(iba_path, scan_sub_folders=False) # check if any files have been found if not file_list: raise FileNotFoundError('Could not find any files at ' '{}' '.'.format(file_list)) # TODO: check if all iba files have the same channel configuration. If not this will create problems! return file_list def get_file_info(self, iba_file): """Returns a dict containing all modules defined in the iba file as well as the dictionary with channels group by their sample rate. :param iba_file: (madatory, string) path to a iba files :return: dict with keys: modules (dict), channel (dict) """ # get the actual info channel_info = get_channel_info(iba_file) # loop over the file to store the info modules = dict() channels = dict() for name, chan in channel_info.items(): # ignore text channel if chan['type'] == 'text' or '$PDA_Tbase' not in chan.keys(): continue # add fields to the channel dict for later use chan['opc_obj'] = None chan['opc_value'] = None # get module full_module = '{0} {1}'.format(chan['module_no'], chan['module']) if full_module not in modules.keys(): modules[full_module] = list() modules[full_module].append(chan) # sort channel cur_tbase = chan['$PDA_Tbase'] if cur_tbase not in channels.keys(): channels[cur_tbase] = list() channels[cur_tbase].append(chan) return {'modules': modules, 'channels': channels} def init_opc(self): """Initializes the actual OPC Server and creates all folder, nodes, etc. :return: None """ self._server = Server() self._server.set_endpoint( "opc.tcp://localhost:4840/sms-digital/iba-playback/") self._server.set_server_name("iba Files Playback OPC UA Server") # set all possible endpoint policies for clients to connect through self._server.set_security_policy([ ua.SecurityPolicyType.NoSecurity, ua.SecurityPolicyType.Basic256Sha256_SignAndEncrypt, ua.SecurityPolicyType.Basic256Sha256_Sign ]) # setup our own namespace uri = "http://iba-playback.sms-digital.io" idx = self._server.register_namespace(uri) # add modules folder modules = self._server.nodes.objects.add_folder(idx, "Modules") for module, channel in self.iba_info['modules'].items(): print('\tModule: {} ...'.format(module)) # create a new folder for the module module_folder = modules.add_folder(idx, module) # create a folder for analog and digital signals analog_folder = module_folder.add_folder(idx, 'Analog') digital_folder = module_folder.add_folder(idx, 'Digital') # add the channel for chan in channel: # create channel if chan['type'] == 'analog': opc_channel = analog_folder.add_object(idx, chan['name']) val = 0.0 else: opc_channel = digital_folder.add_object(idx, chan['name']) val = False # define the channel object value_var = opc_channel.add_variable(idx, "value", val) value_var.set_writable(True) for key, val in chan.items(): opc_channel.add_variable(idx, key, val).set_writable(False) # store the handles to the value variable and the opc_channel in the channel dict chan['opc_obj'] = opc_channel chan['opc_value'] = value_var def _write_values(self): """Spawn a thread for each sample rate :return: """ for sampleRate, channel in self.iba_info['channels'].items(): # read the data channels = list() for chan in channel: channels.append(chan['id']) # TODO: Deal with multiple files data = readIbaFile(self.iba_files[0], channels=channels, names=channels) # todo: split large files with many channel with the same samplerate into multiple threads # create variable update VariableUpdater(server=self._server, channel=channel, period=float(sampleRate), data=data).start()
class CustomServer(object): def __init__(self): self.SERVER_ENDPOINT = os.environ.get("SERVER_ENDPOINT") self.NAMESPACE = os.environ.get("NAMESPACE") self.SERVER_NAME = os.environ.get("SERVER_NAME") self.ENABLE_CERTIFICATE = bool( strtobool(os.environ.get("ENABLE_CERTIFICATE"))) # setup our server self.server = Server() self.server.set_endpoint(self.SERVER_ENDPOINT) self.server.set_server_name(self.SERVER_NAME) # set the security endpoints for identification of clients if self.ENABLE_CERTIFICATE: # load server certificate and private key. This enables endpoints with signing and encryption. self.CERTIFICATE_PATH_SERVER_CERT = os.path.dirname( os.getcwd()) + os.environ.get("CERTIFICATE_PATH_SERVER_CERT") self.CERTIFICATE_PATH_SERVER_PRIVATE_KEY = os.path.dirname( os.getcwd()) + os.environ.get( "CERTIFICATE_PATH_SERVER_PRIVATE_KEY") self.server.load_certificate(self.CERTIFICATE_PATH_SERVER_CERT) self.server.load_private_key( self.CERTIFICATE_PATH_SERVER_PRIVATE_KEY) # set all possible endpoint policies for clients to connect through self.server.set_security_policy([ # ua.SecurityPolicyType.NoSecurity, ua.SecurityPolicyType.Basic256Sha256_SignAndEncrypt, # ua.SecurityPolicyType.Basic256Sha256_Sign, ]) self.server.set_security_IDs(["Username", "Basic256Sha256"]) else: self.server.set_security_policy([ua.SecurityPolicyType.NoSecurity]) self.server.set_security_IDs(["Anonymous", "Username"]) # set the user_manager function self.server.user_manager.set_user_manager(user_manager) # setup our own namespace, not really necessary but should as spec uri = self.NAMESPACE self.idx = self.server.register_namespace(uri) # get important nodes self.root = self.server.get_root_node() self.obj = self.server.get_objects_node() self.init_methods() def init_methods(self): # method: ADD_OBJECTS_DIR inarg1 = ua.Argument() inarg1.Name = "objects folder" inarg1.DataType = ua.NodeId(ua.ObjectIds.String) # String inarg1.ValueRank = -1 inarg1.ArrayDimensions = [] inarg1.Description = ua.LocalizedText("Name the new objects folder") method_node = self.obj.add_method(self.idx, "ADD_NEW_OBJECTS_FOLDER", self.add_objects_subfolder, [inarg1]) # method: ADD_OPC_TAG inarg1 = ua.Argument() inarg1.Name = "opctag" inarg1.DataType = ua.NodeId(ua.ObjectIds.String) # String inarg1.ValueRank = -1 inarg1.ArrayDimensions = [] inarg1.Description = ua.LocalizedText("Name new OPC variable") inarg2 = ua.Argument() inarg2.Name = "variant_type" inarg2.DataType = ua.NodeId(ua.ObjectIds.String) # String inarg2.ValueRank = -1 inarg2.ArrayDimensions = [] inarg2.Description = ua.LocalizedText("Type of variable") inarg3 = ua.Argument() inarg3.Name = "parent_node" inarg3.DataType = ua.NodeId(ua.ObjectIds.String) # String inarg3.ValueRank = -1 inarg3.ArrayDimensions = [] inarg3.Description = ua.LocalizedText( "Type in the name of the parent node the new variable should assigned to" ) method_node = self.obj.add_method(self.idx, "ADD_OPC_TAG", self.register_opc_tag, [inarg1, inarg2, inarg3]) # method: SET_PV_LIMIT inarg1 = ua.Argument() inarg1.Name = "active_power_setpoint" inarg1.DataType = ua.NodeId(ua.ObjectIds.Int32) # Integer inarg1.ValueRank = -1 inarg1.ArrayDimensions = [] inarg1.Description = ua.LocalizedText( "Type in active power setpoint in percent [0 ... 100]") inarg2 = ua.Argument() inarg2.Name = "parent_node" inarg2.DataType = ua.NodeId(ua.ObjectIds.String) # String inarg2.ValueRank = -1 inarg2.ArrayDimensions = [] inarg2.Description = ua.LocalizedText( "Type in the name of the parent node") method_node = self.obj.add_method(self.idx, "SET_PV_LIMIT", self.set_pv_active_power_setpoint, [inarg1, inarg2]) # method: RUN_ONLINE_GRID_PROTECTION inarg1 = ua.Argument() inarg1.Name = "On/Off" inarg1.DataType = ua.NodeId(ua.ObjectIds.Int32) # Integer inarg1.ValueRank = -1 inarg1.ArrayDimensions = [] inarg1.Description = ua.LocalizedText( "Type in 1 to RUN or 0 to STOP ONLINE_GRID_PROTECTION") inarg2 = ua.Argument() inarg2.Name = "parent_node" inarg2.DataType = ua.NodeId(ua.ObjectIds.String) # String inarg2.ValueRank = -1 inarg2.ArrayDimensions = [] inarg2.Description = ua.LocalizedText( "Type in the name of the parent node") method_node = self.obj.add_method(self.idx, "RUN_ONLINE_GRID_PROTECTION", self.run_online_grid_protection, [inarg1, inarg2]) @uamethod def add_objects_subfolder(self, parent, dir_name): # check if old dir with dir_name exists. if so then delete this dir first try: obj = self.root.get_child( ["0:Objects", ("{}:" + dir_name).format(self.idx)]) self.server.delete_nodes([obj], True) except BadNoMatch: print(DateHelper.get_local_datetime(), "There is no old folder with the name: " + dir_name) folder = self.obj.add_folder(self.idx, dir_name) print(DateHelper.get_local_datetime(), "Add subfolder: " + dir_name) @uamethod def register_opc_tag(self, parent, opctag, variant_type="Float", parent_node=""): # Object "parent_node": try: obj = self.root.get_child( ["0:Objects", ("{}:" + parent_node).format(self.idx)]) except BadNoMatch: print( DateHelper.get_local_datetime(), "register_opc_tag(): OPCUA_server_dir the variables should be assigned to, doesn't exists." ) raise var = ua.Variant(0, strings_to_vartyps(variant_type)) mvar = obj.add_variable(self.idx, opctag.strip(), var) mvar.set_writable() print( DateHelper.get_local_datetime(), "Add variable: " + opctag + " of type " + variant_type + " @node " + parent_node) @uamethod def set_pv_active_power_setpoint(self, parent, setpoint, parent_node=""): try: obj = self.root.get_child( ["0:Objects", ("{}:" + parent_node).format(self.idx)]) except BadNoMatch: print( DateHelper.get_local_datetime(), "set_pv_active_power_setpoint(): assign new value to node failed." ) raise for mvar in obj.get_variables(): if "PV" and "CTRL" in mvar.get_browse_name().Name: variant_type = mvar.get_data_value().Value.VariantType mvar.set_value(clamp(setpoint, 0, 100), variant_type) print( DateHelper.get_local_datetime(), "Set Value of node " + mvar.get_browse_name().Name + " to " + str(clamp(setpoint, 0, 100))) @uamethod def run_online_grid_protection(self, parent, setpoint, parent_node=""): try: obj = self.root.get_child( ["0:Objects", ("{}:" + parent_node).format(self.idx)]) except BadNoMatch: print(DateHelper.get_local_datetime(), "run_online_grid_protection(): Change in On/Off failed.") raise for mvar in obj.get_variables(): if "RUN_ONLINE_GRID_PROTECTION" in mvar.get_browse_name().Name: variant_type = mvar.get_data_value().Value.VariantType mvar.set_value(clamp(setpoint, 0, 1), variant_type) print( DateHelper.get_local_datetime(), "Change status of online grid protection to " + str(clamp(setpoint, 0, 1))) def start(self): self.server.start() print(DateHelper.get_local_datetime(), self.__class__.__name__, " successful started") def stop(self): self.server.stop() print(DateHelper.get_local_datetime(), self.__class__.__name__, " successful stopped")
class UAServer: def __init__(self,rack : rack_controller): self.rack = rack self._setup_nodes() self._generate_tags() self.ua_server.start() self._generate_subscriptions() Thread(target=self._var_updater, daemon=True).start() def _setup_nodes(self): # Create server instance self.ua_server = Server('./opcua_cache') self.ua_server.set_endpoint('opc.tcp://0.0.0.0:4840/UA/PickByLight') self.ua_server.set_server_name("Pick By Light Server") # idx name will be used later for creating the xml used in data type dictionary # setup our own namespace, not really necessary but should as spec idx_name = 'http://examples.freeopcua.github.io' self.idx = self.ua_server.register_namespace(idx_name) # Set all possible endpoint policies for clients to connect through self.ua_server.set_security_policy([ ua.SecurityPolicyType.NoSecurity, ua.SecurityPolicyType.Basic128Rsa15_SignAndEncrypt, ua.SecurityPolicyType.Basic128Rsa15_Sign, ua.SecurityPolicyType.Basic256_SignAndEncrypt, ua.SecurityPolicyType.Basic256_Sign]) # get Objects node, this is where we should put our custom stuff objects = self.ua_server.get_objects_node() # add a PackMLObjects folder pml_folder = objects.add_folder(self.idx, "PackMLObjects") # Get the base type object types = self.ua_server.get_node(ua.ObjectIds.BaseObjectType) # Create a new type for PackMLObjects PackMLBaseObjectType = types.add_object_type(self.idx, "PackMLBaseObjectType") # Create objects for the pack tags using the above created packMLBasedObjectType self.Admin = pml_folder.add_object('ns=2;s=Admin', "Admin", PackMLBaseObjectType.nodeid) self.Status = pml_folder.add_object('ns=2;s=Status', "Status", PackMLBaseObjectType.nodeid) self.Command = pml_folder.add_object('ns=2;s=Command', "Command", PackMLBaseObjectType.nodeid) # Create an object container for the rack self.RackStatus = self.Status.add_object('ns=2;s=Status.Rack', 'Rack') #BoxesCommonStatus = BoxesStatus.add_object('ns=2;s=Status.Boxes.Common', 'Common') root = self.ua_server.get_root_node() DummyFestoObj = root.add_object("ns=2;s=|var|CECC-LK.Application.Flexstation_globalVariables", "DummyFesto") DummyFestoObj.add_variable("ns=2;s=|var|CECC-LK.Application.Flexstation_globalVariables.FlexStationStatus", "FlexStationStatus", val=0).set_writable() DummyFestoObj.add_variable("ns=2;s=|var|CECC-LK.Application.FBs.stpStopper1.stAppControl.uiOpNo","uiOpNo", val=0).set_writable() def _generate_tags(self): # for all ports generate tags for port_number in self.rack.ports: # Make a folder with the port_number as the name b_obj = self.RackStatus.add_object('ns=2;s=Status.Rack.{}'.format(port_number), str(port_number)) b_obj.add_variable("ns=2;s=Status.Rack.{}.Selected".format(port_number) ,"Selected" , bool()) b_obj.add_variable("ns=2;s=Status.Rack.{}.Activity".format(port_number) ,"Activity" , bool()) b_obj.add_variable("ns=2;s=Status.Rack.{}.ActivityTimestamp".format(port_number) ,"ActivityTimestamp", datetime.fromtimestamp(0)) b_obj.add_variable("ns=2;s=Status.Rack.{}.PickTimestamp".format(port_number) ,"PickTimestamp" , datetime.fromtimestamp(0)) b_obj.add_variable("ns=2;s=Status.Rack.{}.LightState".format(port_number) ,"LightState" , bool()) b_obj.add_variable("ns=2;s=Status.Rack.{}.BoxId".format(port_number) ,"BoxId" , str()) b_obj.add_variable("ns=2;s=Status.Rack.{}.ContentId".format(port_number) ,"ContentId" , str()) b_obj.add_variable("ns=2;s=Status.Rack.{}.ContentCount".format(port_number) ,"ContentCount" , int()) ''' create command tags for clients that does not support ua methods. ''' # create an object in the packml Command object called rack for all the commands. b_obj = self.Command.add_object("ns=2;s=Command.Rack", 'Rack') # Create command tag for triggering the selection b_obj.add_variable("ns=2;s=Command.Rack.Select", 'Select', -1, ua.VariantType.Int16).set_writable() b_obj.add_variable("ns=2;s=Command.Rack.DeSelect", 'DeSelect', -1, ua.VariantType.Int16).set_writable() def _generate_subscriptions(self): # Create UA subscriber node for the box. Set self as handler. sub = self.ua_server.create_subscription(100, self) # Subscribe to the Select tag n = self.ua_server.get_node("ns=2;s=Command.Rack.Select") sub.subscribe_data_change(n) # Subscribe to the Deselect tag n = self.ua_server.get_node("ns=2;s=Command.Rack.DeSelect") sub.subscribe_data_change(n) pass def event_notification(self, event): print("Python: New event. No function implemented", event) def datachange_notification(self, node, val, data): """UA server callback on data change notifications This is a workaround for kepware that does not support UA methods, so instead is has "trigger tags" that when set to true it works like calling a method. TODO make this more dynamic instead of hard coding the attributes. Arguments: node {Node} -- [description] val {[type]} -- [description] data {[type]} -- [description] """ # avoid triggereing it all again when resetting the tags to -1 if val != -1 : # Print info print("New data change event", node, val) # get the node browse name. node_id = node.get_browse_name().Name # If the trigger tag changes to true go in and update the status tag and set the trigger back to false. # Also read description above. if node_id == "Select" : self.rack.select_port(val) node.set_value(-1) elif node_id == "Deselect" : self.rack.select_port(val) node.set_value(-1) def _var_updater(self): while True: sleep(0.1) # for all boxes update tags for port_number, port in self.rack.ports.items(): # get the object in the packml status object using our unique idx node = self.ua_server.get_node("ns=2;s=Status.Rack.{}.Activity".format(port_number)) node.set_value(port.activity) node = self.ua_server.get_node("ns=2;s=Status.Rack.{}.ActivityTimestamp".format(port_number)) node.set_value(port.activity_timestamp) node = self.ua_server.get_node("ns=2;s=Status.Rack.{}.LightState".format(port_number)) node.set_value(port.get_light()) for port_number, box in self.rack.boxes.items(): node = self.ua_server.get_node("ns=2;s=Status.Rack.{}.BoxId".format(port_number)) node.set_value(box.box_id) node = self.ua_server.get_node("ns=2;s=Status.Rack.{}.ContentId".format(port_number)) node.set_value(box.content_id) node = self.ua_server.get_node("ns=2;s=Status.Rack.{}.ContentCount".format(port_number)) node.set_value(box.content_count) for port_number, select_state in self.rack.ports_select_state.items(): node = self.ua_server.get_node("ns=2;s=Status.Rack.{}.Selected".format(port_number)) node.set_value(select_state.selected) node = self.ua_server.get_node("ns=2;s=Status.Rack.{}.PickTimestamp".format(port_number)) node.set_value(select_state.pick_timestamp)
class OPCUAServer: """An OPC UA server which reads variables from a csv file and exposes it. Args: endpoint (:obj:`str`): OPC UA server endpoint. Defaults to 'opc.tcp://0.0.0.0:4840/intry4.0/server/'. server_name (:obj:`str`): OPC UA server name. Defaults to 'InTry 4.0 OPC UA Server'. security_policy (:obj:`list`): Array which contains `opcua.ua.SecurityPolicyType` available in the server. Defaults to [ ua.SecurityPolicyType.NoSecurity, ua.SecurityPolicyType.Basic256Sha256_Sign, ua.SecurityPolicyType.Basic256Sha256_SignAndEncrypt, ] ns_uri(:obj:`str`): the namespace URI where all the variables will be added. Defaults to 'urn:intry4.0:server'. object_name(:obj:`str`): name of the OPC UA object that will be created to hold all variables. Defaults to 'variables'. last_row_file (:obj:`str`): name of the file in which the last row published by the server will be saved. certificate (:obj:`str`): path of the certificate file used by the server. Defaults to '/var/intry-opcua-server/cert.der'. private_key (:obj:`str`): path of the certificate file used by the server. Defaults to '/var/intry-opcua-server/key.pem'. min_time(:obj:`int`): min time elapsed between variable updates. Defaults to 30. logger(:obj:`logging.Logger`): logger to be used. Defaults to None. Attributes: _server (opcua.Server): the OPC UA server. endpoint (str): OPC UA server endpoint. _ns_index (): the namespace index where all the variables will be added. _object () last_row (:obj:`dict`): last row that has been used by the server. For example: { "file": "csv1.csv", "row": "2019-10-02 23:55" } _stop (bool): flag variable that controls the infinite loop of variable updating. """ def __init__( self, endpoint: str = "opc.tcp://0.0.0.0:4840/intry4.0/server/", server_name: str = "InTry 4.0 - OPC UA Server", security_policy: List[ua.SecurityPolicyType] = None, ns_uri: str = "urn:intry:opcua:server", object_name: str = "variables", last_row_file: str = "/var/intry-opcua-server/last_row.log", certificate: str = "/var/intry-opcua-server/cert.der", private_key: str = "/var/intry-opcua-server/key.pem", min_time: int = 30, logger=None, ): if security_policy is None: _security_policy = [ ua.SecurityPolicyType.NoSecurity, ua.SecurityPolicyType.Basic256Sha256_Sign, ua.SecurityPolicyType.Basic256Sha256_SignAndEncrypt, ] self._server = Server() self.endpoint = endpoint self._server.set_endpoint(self.endpoint) self._server.set_security_policy(_security_policy) self._server.load_certificate(certificate) self._server.load_private_key(private_key) self._ns_index = self._server.register_namespace(ns_uri) self._object = self._server.nodes.objects.add_object( self._ns_index, object_name ) self._last_row_file = last_row_file self._logger = logger or logging.getLogger(__name__) self.last_row = {} self._stop = False self.min_time = min_time def _add_variable(self, name, value): """Adds a variable to the OPC UA server. Args: name (:obj:`str`): name of the variable. value (int or float): initial value of the variable. Returns: opcua.common.node.Node: the created variable in the OPC UA server. """ return self._object.add_variable(self._ns_index, name, value) def _get_csvs(self, csv_dir): """Get the CSV files stored in the specified directory and filter the CSV which are not required to start publishing new values from the last row that was published. Args: csv_dir (:obj:`str`): path of the directory containing CSVs. """ self._read_last_row() csvs = get_csvs_in_dir(csv_dir) self._logger.debug(f"CSV files inside {csv_dir}: {len(csvs)}") if not self.last_row: df = pd.read_csv(csvs[0], index_col="date") self.last_row = {"file": csvs[0], "row": df.index[0]} file_index = csvs.index(self.last_row["file"]) return csvs[file_index:] def variable_values_from_csvs(self, csv_dir): """Creates variables inside the OPC UA server from the CSVs contained in the specified directory. Then, each row of the provided CSVs will be read to update the value of each variable. csv_dir (str): path of the directory containing CSVs. """ csvs = self._get_csvs(csv_dir) len_csvs = len(csvs) if len_csvs > 0: variable_name_node = {} for (index, csv) in enumerate(csvs): if self._stop: break self._logger.info(f"Reading file {csv}") df = pd.read_csv(csv, index_col="date") self.last_row["file"] = csv # If first CSV, create variables in the OPC UA Server if index == 0: self._logger.debug( f"First csv readed: {csv}. Creating {len(df.columns)} OPC UA variables from it..." ) df = df[self.last_row["row"] :] for column in df.columns: first_value = df[column].iloc[0] self._logger.debug( f"Adding variable [{column}] with initial value <{first_value}>" ) variable_name_node[column] = self._add_variable( column, first_value ) # remove the first row because its going used for initial value df = df.iloc[1:] # iterate over the rows in the dataframe for updating the value of each variable time_between_update = 0 last_index = None for (index, row) in df.iterrows(): if self._stop: break self.last_row["row"] = index # Calculate the time to sleep between each update with the date of the # last row and this row. if last_index is not None: time_between_update = ( str_to_date(index) - str_to_date(last_index) ).total_seconds() if time_between_update > 60: self._logger.info( "Time between update too high. Setting it to 60 secs..." ) time_between_update = 60.0 elif time_between_update < self.min_time: self._logger.info( f"Time between update was negative or too low. Setting it to {self.min_time} secs..." ) time_between_update = self.min_time self._logger.info(f"Starting sleep of {time_between_update}...") time.sleep(time_between_update) self._logger.info( f"Time of {time_between_update} elapsed. Updating variable values..." ) for (column, node) in variable_name_node.items(): node.set_value(row[column]) last_index = index def _write_last_row(self): """Writes the last row published to a file in JSON format.""" create_path_if_not_exists(self._last_row_file) with open(self._last_row_file, "w+") as f: f.write(json.dumps(self.last_row)) def _read_last_row(self): """Reads the last row published from a JSON file.""" if file_exists(self._last_row_file): self._logger.info(f"Reading last row file {self._last_row_file}") with open(self._last_row_file, "r") as f: self.last_row = json.loads(f.read()) else: self._logger.info(f"File {self._last_row_file} does not exist") self.last_row = {} def start(self): """Starts the OPC UA server execution.""" self._logger.info(f"Starting OPC UA server. Listening on {self.endpoint}") self._server.start() def stop(self): """Stops the OPC UA server execution.""" self._write_last_row() self._logger.info("Stopping OPC UA server...") self._stop = True self._server.stop()
class ServerClass: def define_server(self): """ Function for setting up the OPC UA Server. """ # Instanciation of OPC-UA Server self.server = Server() self.server.set_endpoint("opc.tcp://0.0.0.0:4840/") self.server.set_server_name('Opc UA Valve Test Server') # set all possible endpoint policies for clients to connect through self.server.set_security_policy([ ua.SecurityPolicyType.NoSecurity, ua.SecurityPolicyType.Basic256Sha256_SignAndEncrypt, ua.SecurityPolicyType.Basic256Sha256_Sign]) # setup our own namespace self.uri = "http://test.valve.iit" self.idx = self.server.register_namespace(self.uri) # Create a new node type we can instantiate in address space self.dev = self.server.nodes.base_object_type.add_object_type(self.idx, "Test Server") self.valve01 = self.server.nodes.objects.add_object(self.idx, 'Valve01') # Definition of the pickle file with open('pickles/valve01.p', 'rb') as handle: self.valve_prop = pickle.load(handle) # Definition of the OPC UA classes and variables self.typ_valve01 = self.valve01.add_property(self.idx, "ValveType", self.valve_prop['typ'], ua.VariantType.String) self.medium_valve01 = self.valve01.add_property(self.idx, "Medium", self.valve_prop['medium'], ua.VariantType.String) self.status_valve01 = self.valve01.add_variable(self.idx, "Status", self.valve_prop['status'], ua.VariantType.String) self.status_valve01.set_writable() self.accuracy_valve01 = self.valve01.add_variable(self.idx, "Accuracy", self.valve_prop['accuracy'], ua.VariantType.Double) self.accuracy_valve01.set_writable() self.status_update_valve01 = self.valve01.add_variable(self.idx, "LastUpdate", self.valve_prop['updated'], ua.VariantType.DateTime) self.status_update_valve01.set_writable() self.cycles_valve01 = self.valve01.add_variable(self.idx, 'TotalCycles', self.valve_prop['cycles'], ua.VariantType.Int64) self.cycles_valve01.set_writable() self.server.start() def use_server(self, status, updated, accuracy, cycles): """ Function for updating the OPC UA Server. """ self.status_valve01.set_value(status) self.status_update_valve01.set_value(updated) self.accuracy_valve01.set_value(accuracy) self.cycles_valve01.set_value(cycles) def stop_server(self): """ Function for stopping the OPC UA Server. """ self.server.stop()
#logger = logging.getLogger("opcua.binary_server_asyncio") # logger.setLevel(logging.DEBUG) #logger = logging.getLogger("opcua.uaprocessor") # logger.setLevel(logging.DEBUG) # now setup our server server = Server() #server.disable_clock() #server.set_endpoint("opc.tcp://localhost:4840/freeopcua/server/") server.set_endpoint("opc.tcp://0.0.0.0:4840/freeopcua/server/") server.set_server_name("FreeOpcUa Example Server") # set all possible endpoint policies for clients to connect through server.set_security_policy([ ua.SecurityPolicyType.NoSecurity, ua.SecurityPolicyType.Basic128Rsa15_SignAndEncrypt, ua.SecurityPolicyType.Basic128Rsa15_Sign, ua.SecurityPolicyType.Basic256_SignAndEncrypt, ua.SecurityPolicyType.Basic256_Sign ]) # setup our own namespace uri = "http://examples.freeopcua.github.io" idx = server.register_namespace(uri) # create a new node type we can instantiate in our address space dev = server.nodes.base_object_type.add_object_type(0, "MyDevice") dev.add_variable(0, "sensor1", 1.0).set_modelling_rule(True) dev.add_property(0, "device_id", "0340").set_modelling_rule(True) ctrl = dev.add_object(0, "controller") ctrl.set_modelling_rule(True) ctrl.add_property(0, "state", "Idle").set_modelling_rule(True)
# logger.setLevel(logging.DEBUG) #logger = logging.getLogger("opcua.binary_server_asyncio") # logger.setLevel(logging.DEBUG) #logger = logging.getLogger("opcua.uaprocessor") # logger.setLevel(logging.DEBUG) # now setup our server server = Server() #server.disable_clock() #server.set_endpoint("opc.tcp://localhost:4840/freeopcua/server/") server.set_endpoint("opc.tcp://0.0.0.0:4840/freeopcua/server/") server.set_server_name("FreeOpcUa Example Server") # set all possible endpoint policies for clients to connect through server.set_security_policy([ ua.SecurityPolicyType.NoSecurity, ua.SecurityPolicyType.Basic128Rsa15_SignAndEncrypt, ua.SecurityPolicyType.Basic128Rsa15_Sign, ua.SecurityPolicyType.Basic256_SignAndEncrypt, ua.SecurityPolicyType.Basic256_Sign]) # setup our own namespace uri = "http://examples.freeopcua.github.io" idx = server.register_namespace(uri) # create a new node type we can instantiate in our address space dev = server.nodes.base_object_type.add_object_type(0, "MyDevice") dev.add_variable(0, "sensor1", 1.0).set_modelling_rule(True) dev.add_property(0, "device_id", "0340").set_modelling_rule(True) ctrl = dev.add_object(0, "controller") ctrl.set_modelling_rule(True) ctrl.add_property(0, "state", "Idle").set_modelling_rule(True)
class OpcUaConnectorGeneralTest(ConnectorTestBase): def test_number_one(self): self._create_connector("connection_test.json") self.assertTrue(self.connector is not None) self.check_or_create_server() self.connector.open() def check_or_create_server(self): if not hasattr(self, "test_server"): self.test_server = Server() self.__server_thread = Thread(target=self.__server_run, name="Test OPC UA server", args=(self.test_server,)) self.assertTrue(self.test_server is not None) def __server_run(self, test_server): self.test_server = test_server class SubHandler(object): def datachange_notification(self, node, val, data): print("Python: New data change event", node, val) def event_notification(self, event): print("Python: New event", event) @uamethod def multiply(parent, x, y): return x * y self.test_server.set_endpoint("opc.tcp://0.0.0.0:4840/freeopcua/server/") self.test_server.set_server_name("Test Server") self.test_server.set_security_policy([ ua.SecurityPolicyType.NoSecurity, ua.SecurityPolicyType.Basic256Sha256_SignAndEncrypt, ua.SecurityPolicyType.Basic256Sha256_Sign]) uri = "http://127.0.0.1" idx = self.test_server.register_namespace(uri) device = self.test_server.nodes.objects.add_object(idx, "Device1") name = self.test_server.nodes.objects.add_variable(idx, "serialNumber", "TEST") name.set_writable() temperature_and_humidity = device.add_object(idx, "TemperatureAndHumiditySensor") temperature = temperature_and_humidity.add_variable(idx, "Temperature", 56.7) humidity = temperature_and_humidity.add_variable(idx, "Humidity", 68.7) battery = device.add_object(idx, "Battery") battery_level = battery.add_variable(idx, "batteryLevel", 24) device.add_method(idx, "multiply", multiply, [ua.VariantType.Int64, ua.VariantType.Int64], [ua.VariantType.Int64]) self.test_server.start() try: while self.server_running: sleep(.1) finally: self.test_server.stop() def stop_test_server(self): self.server_running = False def tearDown(self): super().tearDown() self.stop_test_server()
class UA_Object(object): def __init__(self, url, spaceName, security_num): self.server = Server() self.endPoint = self.server.set_endpoint(url) self.security_num = security_num self.spaceName = self.server.register_namespace(spaceName) self.node_obj = self.server.get_objects_node() # root_id def set_security(self): security = [ ua.SecurityPolicyType.NoSecurity, ua.SecurityPolicyType.Basic256Sha256_SignAndEncrypt, ua.SecurityPolicyType.Basic256Sha256_Sign ] self.server.set_security_policy([security[self.security_num]]) def read_json(self, jsonPath): with open(jsonPath, 'r') as f: data = f.read() return json.loads(data) def get_server_tagName(self, jsonDict): s_server_tag = UAStack() for k, v in jsonDict.items(): for i, j in v.items(): s_server_tag.push({k: i}) return s_server_tag def add_serverName(self, s_tags): temp = list() for k in s_tags.keys(): serverObj = self.node_obj.add_object(self.spaceName, str(k)) temp.append(serverObj) return temp def get_browse_name(self, tagNameObj): temp = list() for nodeObj in tagNameObj: tag_TagName = nodeObj.get_browse_name().Name temp.append(tag_TagName) return temp def add_tagName(self, s_tags, serverObj): tagNameObj = list() for val in s_tags: for q, w in val.items(): for i in serverObj: serverName = i.get_browse_name().Name if serverName == q: tag = i.add_variable(self.spaceName, w, None) tag.set_writable() tagNameObj.append(tag) return tagNameObj def change_node(self, res_stack, tagNodeObj): for tagObj in tagNodeObj: b_name = tagObj.get_browse_name().Name for values in res_stack: if b_name in values: tagObj.set_value(values[b_name]) break