address_space = server.register_namespace("http://andreas-heine.net/UA") uri = "urn:opcua:python:server" server.set_application_uri(uri) server.load_certificate("certificate.pem") server.load_private_key("key.pem") server.set_security_policy([ # ua.SecurityPolicyType.NoSecurity, # ua.SecurityPolicyType.Basic128Rsa15_Sign, # ua.SecurityPolicyType.Basic128Rsa15_SignAndEncrypt, # ua.SecurityPolicyType.Basic256Sha256_Sign, ua.SecurityPolicyType.Basic256Sha256_SignAndEncrypt ]) policyIDs = ["Username"] server.set_security_IDs(policyIDs) server.user_manager.set_user_manager(user_manager) """ OPC-UA-Modeling """ root_node = server.get_root_node() object_node = server.get_objects_node() server_node = server.get_server_node() try: server.import_xml("custom_nodes.xml") except FileNotFoundError: pass except Exception as e: print(e)
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
def serverLoop(self): self.log.Info(self.opcInfoList) # setup our server server = Server() server.set_endpoint("opc.tcp://" + self.get_local_ip("eth0") + ":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) server.user_manager.set_user_manager(self.user_manager) server.set_security_IDs("Username") # get Objects node, this is where we should put our nodes objects = server.get_objects_node() # populating our address space obj_modbusDevInfoList = objects.add_object(idx, "obj_modbusDevInfoList") obj_opcInfoList = objects.add_object(idx, "obj_opcInfoList") obj_lzbusIpInfoList = objects.add_object(idx, "obj_lzbusIpInfoList") obj_snmpInfoList = objects.add_object(idx, "obj_snmpInfoList") obj_dev1 = objects.add_object(idx, "obj_173_12_10_138") obj_dev2 = objects.add_object(idx, "obj_173_12_10_139") v_modbusDevInfoList = obj_modbusDevInfoList.add_variable( idx, "v_modbusDevInfoList", "") v_opcInfoList = obj_opcInfoList.add_variable(idx, "v_opcInfoList", "") v_lzbusIpInfoList = obj_lzbusIpInfoList.add_variable( idx, "v_lzbusIpInfoList", "") v_snmpInfoList = obj_snmpInfoList.add_variable(idx, "v_snmpInfoList", "") d1_ip = obj_dev1.add_variable(idx, "ID", "173.12.10.138") d1_type = obj_dev1.add_variable(idx, "TYPE", "1") d1_powerstatus = obj_dev1.add_variable(idx, "POWERSTAUS", "on") d1_netstatus = obj_dev1.add_variable(idx, "NETSTATUS", "on") d1_cpu1_per = obj_dev1.add_variable(idx, "CPU1_PER", "70") d1_cpu2_per = obj_dev1.add_variable(idx, "CPU2_PER", "50") d1_cpu3_per = obj_dev1.add_variable(idx, "CPU3_PER", "30") d1_cpu4_per = obj_dev1.add_variable(idx, "CPU4_PER", "10") d1_mem_total = obj_dev1.add_variable(idx, "MEM_TOTAL", "82300000") d1_disk_total = obj_dev1.add_variable(idx, "DISK_TOTAL", "70") d2_type = obj_dev2.add_variable(idx, "TYPE", "1") d2_powerstatus = obj_dev2.add_variable(idx, "POWERSTAUS", "on") d2_netstatus = obj_dev2.add_variable(idx, "NETSTATUS", "on") d2_cpu1_per = obj_dev2.add_variable(idx, "CPU1_PER", "70") d2_cpu2_per = obj_dev2.add_variable(idx, "CPU2_PER", "50") d2_cpu3_per = obj_dev2.add_variable(idx, "CPU3_PER", "30") d2_cpu4_per = obj_dev2.add_variable(idx, "CPU4_PER", "10") d2_mem_total = obj_dev2.add_variable(idx, "MEM_TOTAL", "82300000") d2_disk_total = obj_dev2.add_variable(idx, "DISK_TOTAL", "70") # starting! server.start() while True: dateInfo = datetime.datetime.now().strftime('%Y-%m-%d %H-%M-%S') v_modbusDevInfoList.set_value(json.dumps(self.modbusDevInfoList)) v_opcInfoList.set_value(json.dumps(self.opcInfoList)) v_lzbusIpInfoList.set_value(json.dumps(self.lzbusIpInfoList)) v_snmpInfoList.set_value(json.dumps(self.snmpInfoList)) d1_ip.set_value("173.12.10.138") d1_type.set_value("1") d1_powerstatus.set_value("on") d1_netstatus.set_value("on") d1_cpu1_per.set_value("70") d1_cpu2_per.set_value("50") d1_cpu3_per.set_value("30") d1_cpu4_per.set_value("10") d1_mem_total.set_value("82300000") d1_disk_total.set_value("70") d2_type.set_value("1") d2_powerstatus.set_value("on") d2_netstatus.set_value("on") d2_cpu1_per.set_value("70") d2_cpu2_per.set_value("50") d2_cpu3_per.set_value("30") d2_cpu4_per.set_value("10") d2_mem_total.set_value("82300000") d2_disk_total.set_value("70") time.sleep(60)
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")