class HelloServer: def __init__(self, endpoint, name, model_filepath): self.server = Server() # This need to be imported at the start or else it will overwrite the data self.server.import_xml(model_filepath) self.server.set_endpoint(endpoint) self.server.set_server_name(name) objects = self.server.get_objects_node() freeopcua_namespace = self.server.get_namespace_index( "urn:freeopcua:python:server") hellower = objects.get_child("0:Hellower") hellower_say_hello = hellower.get_child("0:SayHello") self.server.link_method(hellower_say_hello, say_hello_xml) hellower.add_method(freeopcua_namespace, "SayHello2", say_hello, [ua.VariantType.Boolean], [ua.VariantType.String]) hellower.add_method(freeopcua_namespace, "SayHelloArray", say_hello_array, [ua.VariantType.Boolean], [ua.VariantType.String]) def __enter__(self): self.server.start() return self.server def __exit__(self, exc_type, exc_val, exc_tb): self.server.stop()
class DemoServer: def __init__(self): self.server = Server() self.server.set_endpoint('opc.tcp://0.0.0.0:51210/UA/SampleServer') self.server.set_server_name('Custom structure demo server') # idx name will be used later for creating the xml used in data type dictionary self._idx_name = 'http://examples.freeopcua.github.io' self.idx = self.server.register_namespace(self._idx_name) self.dict_builder = DataTypeDictionaryBuilder(self.server, self.idx, self._idx_name, 'MyDictionary') def __enter__(self): return self def __exit__(self, exc_type, exc_val, exc_tb): quit() def start_server(self): self.server.start() def create_structure(self, name): # save the created data type return self.dict_builder.create_data_type(name) def complete_creation(self): self.dict_builder.set_dict_byte_string()
def mymain(): # setup our server server = Server() server.set_endpoint("opc.tcp://0.0.0.0:4840/freeopcua/server/") # setup our own namespace, not really necessary but should as spec uri = "http://examples.freeopcua.github.io" idx = server.register_namespace(uri) # get Objects node, this is where we should put our nodes objects = server.get_objects_node() # populating our address space myobj = objects.add_object(idx, "MyObject") myvar = myobj.add_variable(idx, "MyVariable", 6.7) myvar.set_writable() # Set MyVariable to be writable by clients # starting! server.start() server.stop()
async def test_context_manager(): # Context manager calls start() and stop() state = [0] async def increment_state(self, *args, **kwargs): state[0] += 1 # create server and replace instance methods with dummy methods server = Server() server.start = increment_state.__get__(server) server.stop = increment_state.__get__(server) assert state[0] == 0 async with server: # test if server started assert 1 == state[0] # test if server stopped assert 2 == state[0]
#------------------------------------------------------------------------------- # Import customobject type server.import_xml('customobject.xml') # get nodeid of custom object type by one of the following 3 ways: # 1) Use node ID # 2) Or Full path # 3) Or As child from parent myobject1_type_nodeid = ua.NodeId.from_string('ns=%d;i=2' % idx) myobject2_type_nodeid = server.get_root_node().get_child([ "0:Types", "0:ObjectTypes", "0:BaseObjectType", "%d:MyCustomObjectType" % idx ]).nodeid myobject3_type_nodeid = server.get_node( ua.ObjectIds.BaseObjectType).get_child(["%d:MyCustomObjectType" % idx ]).nodeid # populating our address space myobj = objects.add_object(idx, "MyCustomObjectB", myobject3_type_nodeid) #------------------------------------------------------------------------------- # starting! server.start() try: while True: time.sleep(1) finally: # close connection, remove subcsriptions, etc server.stop()
async def start(self): node_obj = {} variable_obj = {} # Data Type Mappings (OPCUA Datatypes to IoT Central Datatypes) variant_type = VariantType(self.logger) # OPCUA Server Setup # Here we setup the Server and add discovery try: # configure the endpoint opc_url = self.config["ServerUrlPattern"].format(ip = self.config["IPAddress"], port = self.config["Port"]) if not self.whatif: # init the server opc_server = Server() await opc_server.init() # set the endpoint and name opc_server.set_endpoint(opc_url) opc_server.set_server_name(self.config["ServerDiscoveryName"]) # set discovery await opc_server.set_application_uri(self.config["ApplicationUri"]) log_msg = "[SERVER CONFIG] ENDPOINT: {ep} APPLICATION URI: {au} APPLICATION NAME: {an}" self.logger.info(log_msg.format(ep = opc_url, au = self.config["ApplicationUri"], an = self.config["ServerDiscoveryName"])) # Setup root for Map Telemetry self.map_telemetry = self.create_map_telemetry(self.config["NameSpace"], self.config["DeviceCapabilityModelId"]) except Exception as ex: self.logger.error("[ERROR] %s" % ex) self.logger.error("[TERMINATING] We encountered an error in OPCUA Server Setup" ) return # OPCUA Server Setup Nodes # Here we setup the Nodes and Variables try: # Set NameSpace namespace = self.config["NameSpace"] self.logger.info("[NAMESPACE] %s" % namespace) if not self.whatif: id_namespace = await opc_server.register_namespace(namespace) node_count = 0 # Create our Nodes and Parameters for node in self.nodes: # Add Node and Begin Populating our Address Space if not self.whatif: # Create Node node_obj[node["Name"]] = await opc_server.nodes.objects.add_object(id_namespace, node["Name"]) self.logger.info("[NODE ID] %s" % node_obj[node["Name"]]) # Setup nodes for Map Telemetry self.map_telemetry["Nodes"].append(self.create_map_telemetry_node(node["Name"], str(node_obj[node["Name"]]), node["InterfacelId"], node["InterfaceInstanceName"])) for variable in node["Variables"]: variable_name = variable["DisplayName"] telemetry_name = variable["TelemetryName"] range_value = variable["RangeValues"][0] opc_variant_type = variant_type.map_variant_type(variable["IoTCDataType"]) log_msg = "[SETUP VARIABLE] NODE NAME: {nn} DISPLAY NAME: {dn} TELEMETRY NAME: {tn} RANGE VALUE: {rv} " \ "IoTC TYPE: {it} OPC VARIANT TYPE {ovt} OPC DATA TYPE {odt}" self.logger.info(log_msg.format(nn = node["Name"], dn = variable["DisplayName"], vn = variable["TelemetryName"], \ tn = variable["TelemetryName"], rv = variable["RangeValues"][0], it = variable["IoTCDataType"], \ ovt = opc_variant_type, odt = opc_variant_type)) if not self.whatif: # Create Node Variable nodeObject = await node_obj[node["Name"]].add_variable(id_namespace, telemetry_name, range_value) await nodeObject.set_writable() variable_obj[telemetry_name] = nodeObject self.map_telemetry_nodes_variables.append(self.create_map_telemetry_variable(variable_name, telemetry_name, str(variable_obj[telemetry_name]), variable["IoTCDataType"])) if not self.whatif: self.map_telemetry["Nodes"][node_count]["Variables"] = copy.copy(self.map_telemetry_nodes_variables) self.logger.info("[MAP] %s" % self.map_telemetry) self.map_telemetry_nodes_variables = [] node_count += 1 if not self.whatif: self.update_map_telemetry() except Exception as ex: self.logger.error("[ERROR] %s" % ex) self.logger.error("[TERMINATING] We encountered an error in OPCUA Server Setup for the Nodes and Variables" ) return # Start the server and save the address space try: if not self.whatif and self.cache_addr_space == "save": filename = Path(self.config["CacheAddrSpaceFileName"]) opc_server.start() opc_server.iserver.dump_address_space(filename) opc_server.stop() self.logger.info("[CACHE ADDRESS SPACE] Saved and Server Terminated. Now run with -c load") return except Exception as ex: self.logger.error("[ERROR] %s" % ex) self.logger.error("[TERMINATING] We encountered an error in OPCUA Server Setup for the Nodes and Variables" ) return # We start the server loop if we are not in WhatIf and the CacheAddrSpace # is null (not set) or load. If it was load, we pulled it from the cache on # server init()... if not self.whatif and (self.cache_addr_space == None or self.cache_addr_space == "load"): self.logger.info("[STARTING SERVER] %s" % opc_url) if self.cache_addr_space == "load": filename = Path(self.config["CacheAddrSpaceFileName"]) opc_server.iserver.load_address_space(filename) self.logger.info("[CACHE ADDRESS SPACE] Loaded Address Space Cache from %s" % filename) opc_server.start() async with opc_server: while True: await asyncio.sleep(self.config["ServerFrequencyInSeconds"]) for node in self.nodes: temp_dict = self.nodes_dict[node["Name"]] temp_dict_counter = self.nodes_dict_counter[node["Name"]] for variable in node["Variables"]: count = temp_dict_counter[variable["TelemetryName"]] sequence_count = temp_dict[variable["TelemetryName"]] if count > (sequence_count - 1): count = 0 # Choose the next value in the telemetry sequence for the variable self.nodes_dict_counter[node["Name"]][variable["TelemetryName"]] = (count + 1) value = variable["RangeValues"][count] if not self.whatif: await variable_obj[variable["TelemetryName"]].write_value(value) log_msg = "[LOOP] {nn} {tn} {vw} {tc} SEQ({sc}) CUR({cc})" self.logger.info(log_msg.format(nn = node["Name"], tn = variable["TelemetryName"], vw = value, tc = count, sc = temp_dict[variable["TelemetryName"]], cc = temp_dict_counter[variable["TelemetryName"]])) else: while True: await asyncio.sleep(self.config["ServerFrequencyInSeconds"]) for node in self.nodes: temp_dict = self.nodes_dict[node["Name"]] temp_dict_counter = self.nodes_dict_counter[node["Name"]] for variable in node["Variables"]: count = temp_dict_counter[variable["TelemetryName"]] sequence_count = temp_dict[variable["TelemetryName"]] if count > (sequence_count - 1): count = 0 # Choose the next value in the telemetry sequence for the variable self.nodes_dict_counter[node["Name"]][variable["TelemetryName"]] = (count + 1) value = variable["RangeValues"][count] log_msg = "[LOOP] {nn} {tn} {vw} {tc} SEQ({sc}) CUR({cc})" self.logger.info(log_msg.format(nn = node["Name"], tn = variable["TelemetryName"], vw = value, tc = count, sc = temp_dict[variable["TelemetryName"]], cc = temp_dict_counter[variable["TelemetryName"]])) return