async def test_add_string_array_variable(opc): objects = opc.opc.nodes.objects v = await objects.add_variable('ns=3;s=stringarrayid;', '9:stringarray', ['l', 'b']) nid = ua.NodeId('stringarrayid', 3) qn = ua.QualifiedName('stringarray', 9) assert nid == v.nodeid assert qn == await v.read_browse_name() val = await v.read_value() assert ['l', 'b'] == val await opc.opc.delete_nodes([v])
async def test_data_type_dict_add_dictionary(srv): add_dictionary = getattr(srv.dict_builder, '_add_dictionary') dict_name = 'TestDict' dict_node = srv.srv.get_node(await add_dictionary(dict_name)) assert await dict_node.get_browse_name() == ua.QualifiedName(dict_name, srv.idx) assert await dict_node.get_node_class() == ua.NodeClass.Variable assert (await dict_node.get_parent()).nodeid == ua.NodeId(ua.ObjectIds.OPCBinarySchema_TypeSystem, 0) assert ua.NodeId(ua.ObjectIds.HasComponent, 0) == (await dict_node.get_references(refs=ua.ObjectIds.HasComponent))[0].ReferenceTypeId assert await dict_node.get_type_definition() == ua.NodeId(ua.ObjectIds.DataTypeDictionaryType, 0) assert await dict_node.get_display_name() == ua.LocalizedText(dict_name) assert await dict_node.get_data_type() == ua.NodeId(ua.ObjectIds.ByteString) assert await dict_node.read_value_rank() == -1
async def test_utf8(opc): objects = opc.opc.get_objects_node() utf_string = "æøå@%&" bn = ua.QualifiedName(utf_string, 3) nid = ua.NodeId("æølå", 3) val = "æøå" v = await objects.add_variable(nid, bn, val) assert nid == v.nodeid val2 = await v.get_value() assert val == val2 bn2 = await v.get_browse_name() assert bn == bn2
async def load_type_definitions(server, nodes=None): """ Download xml from given variable node defining custom structures. If no node is given, attemps to import variables from all nodes under "0:OPC Binary" the code is generated and imported on the fly. If you know the structures are not going to be modified it might be interresting to copy the generated files and include them in you code """ if nodes is None: nodes = [] for desc in await server.nodes.opc_binary.get_children_descriptions(): if desc.BrowseName != ua.QualifiedName("Opc.Ua"): nodes.append(server.get_node(desc.NodeId)) structs_dict = {} generators = [] for node in nodes: xml = await node.get_value() xml = xml.decode("utf-8") generator = StructGenerator() generators.append(generator) generator.make_model_from_string(xml) # generate and execute new code on the fly generator.get_python_classes(structs_dict) # same but using a file that is imported. This can be usefull for debugging library # name = node.get_browse_name().Name # Make sure structure names do not contain charaters that cannot be used in Python class file names # name = _clean_name(name) # name = "structures_" + node.get_browse_name().Name # generator.save_and_import(name + ".py", append_to=structs_dict) # register classes # every children of our node should represent a class for ndesc in await node.get_children_descriptions(): ndesc_node = server.get_node(ndesc.NodeId) ref_desc_list = await ndesc_node.get_references(refs=ua.ObjectIds.HasDescription, direction=ua.BrowseDirection.Inverse) if ref_desc_list: # some server put extra things here name = _clean_name(ndesc.BrowseName.Name) if not name in structs_dict: _logger.warning("%s is found as child of binary definition node but is not found in xml", name) continue nodeid = ref_desc_list[0].NodeId ua.register_extension_object(name, nodeid, structs_dict[name]) # save the typeid if user want to create static file for type definitnion generator.set_typeid(name, nodeid.to_string()) for key, val in structs_dict.items(): if isinstance(val, EnumMeta) and key is not "IntEnum": setattr(ua, key, val) return generators, structs_dict
def _parse_qualifed_name(self, el): name = None ns = 0 nval = el.find("uax:Name", self.ns) if nval is not None: name = nval.text nsval = el.find("uax:NamespaceIndex", self.ns) if nsval is not None: ns = string_to_val(nsval.text, ua.VariantType.UInt16) v = ua.QualifiedName(name, ns) self.logger.error(f"qn: {v}") return v
async def _create_method(parent, nodeid, qname, callback, inputs, outputs): addnode = ua.AddNodesItem() addnode.RequestedNewNodeId = nodeid addnode.BrowseName = qname addnode.NodeClass = ua.NodeClass.Method addnode.ParentNodeId = parent.nodeid addnode.ReferenceTypeId = ua.NodeId(ua.ObjectIds.HasComponent) # node.TypeDefinition = ua.NodeId(ua.ObjectIds.BaseObjectType) attrs = ua.MethodAttributes() attrs.Description = ua.LocalizedText(qname.Name) attrs.DisplayName = ua.LocalizedText(qname.Name) attrs.WriteMask = 0 attrs.UserWriteMask = 0 attrs.Executable = True attrs.UserExecutable = True addnode.NodeAttributes = attrs results = await parent.server.add_nodes([addnode]) results[0].StatusCode.check() method = make_node(parent.server, results[0].AddedNodeId) if inputs: await create_property( method, ua.NodeId(namespaceidx=method.nodeid.NamespaceIndex), ua.QualifiedName("InputArguments", 0), [_vtype_to_argument(vtype) for vtype in inputs], varianttype=ua.VariantType.ExtensionObject, datatype=ua.ObjectIds.Argument ) if outputs: await create_property( method, ua.NodeId(namespaceidx=method.nodeid.NamespaceIndex), ua.QualifiedName("OutputArguments", 0), [_vtype_to_argument(vtype) for vtype in outputs], varianttype=ua.VariantType.ExtensionObject, datatype=ua.ObjectIds.Argument ) if hasattr(parent.server, "add_method_callback"): parent.server.add_method_callback(method.nodeid, callback) return results[0].AddedNodeId
async def test_enum_string_identifier_and_spaces(opc): idx = 4 nodeid = ua.NodeId("My Identifier", idx) qname = ua.QualifiedName("My Enum", idx) await new_enum(opc.opc, nodeid, qname, [ "my name with hole", "toto", "tutu", ]) await opc.opc.load_data_type_definitions() var = await opc.opc.nodes.objects.add_variable(idx, "my enum", ua.My_Enum.my_name_with_hole) val = await var.read_value() assert val == 0
def _migrate_ns(self, obj: Union[ua.NodeId, ua.QualifiedName]) -> Union[ua.NodeId, ua.QualifiedName]: """ Check if the index of nodeid or browsename given in the xml model file must be converted to a already existing namespace id based on the files namespace uri :returns: NodeId (str) """ if isinstance(obj, ua.NodeId): if obj.NamespaceIndex in self.namespaces: obj = ua.NodeId(Identifier=obj.Identifier, NamespaceIndex=self.namespaces[obj.NamespaceIndex], NodeIdType=obj.NodeIdType) if isinstance(obj, ua.QualifiedName): if obj.NamespaceIndex in self.namespaces: obj = ua.QualifiedName(Name=obj.Name, NamespaceIndex=self.namespaces[obj.NamespaceIndex]) return obj
def test_where_clause(): cf = ua.ContentFilter() el = ua.ContentFilterElement() op = ua.SimpleAttributeOperand() op.BrowsePath.append(ua.QualifiedName("property", 2)) el.FilterOperands.append(op) for i in range(10): op = ua.LiteralOperand() op.Value = ua.Variant(i) el.FilterOperands.append(op) el.FilterOperator = ua.FilterOperator.InList cf.Elements.append(el) wce = WhereClauseEvaluator(logging.getLogger(__name__), None, cf) ev = BaseEvent() ev._freeze = False ev.property = 3 assert wce.eval(ev)
async def test_custom_struct_of_struct_with_spaces(opc): idx = 6 nodeid = ua.NodeId("toto.My Identifier", idx) qname = ua.QualifiedName("My Sub Struct 1", idx) dtype, encs = await new_struct(opc.opc, nodeid, qname, [ new_struct_field("My Bool", ua.VariantType.Boolean), new_struct_field("My UInt32", ua.VariantType.UInt32), ]) await new_struct(opc.opc, idx, "My Mother Struct", [ new_struct_field("My Bool", ua.VariantType.Boolean), new_struct_field("My Sub Struct", dtype), ]) await opc.opc.load_data_type_definitions() mystruct = ua.My_Mother_Struct() mystruct.My_Sub_Struct = ua.My_Sub_Struct_1() mystruct.My_Sub_Struct.My_UInt32 = 78 var = await opc.opc.nodes.objects.add_variable(idx, "my mother struct", mystruct) val = await var.read_value() assert val.My_Sub_Struct.My_UInt32 == 78
def test_qualified_name(): qn = ua.QualifiedName('qname', 2) assert qn.NamespaceIndex == 2 assert qn.Name == 'qname' assert qn.to_string() == '2:qname'
def test_string_to_variant_qname(): string = "2:name" obj = ua.QualifiedName("name", 2) assert obj == string_to_val(string, ua.VariantType.QualifiedName) assert string == val_to_string(obj)
async def test_objects(opc): objects = opc.opc.get_objects_node() assert ua.QualifiedName('Objects', 0) == await objects.get_browse_name() nid = ua.NodeId(85, 0) assert nid == objects.nodeid
async def test_root(opc): root = opc.opc.get_root_node() assert ua.QualifiedName('Root', 0) == await root.get_browse_name() assert ua.LocalizedText('Root') == await root.get_display_name() nid = ua.NodeId(84, 0) assert nid == root.nodeid
async def test_server_node(opc): node = opc.opc.nodes.server assert ua.QualifiedName('Server', 0) == await node.read_browse_name()
def test_browsepathtonodeid(self, client): root = client.nodes.root node = root.get_child(["0:Objects", "0:Server", "0:ServerArray"]) self.assertEqual(node.read_browse_name(), ua.QualifiedName("ServerArray", 0))
async def test_xml_qualifiedname(opc, tmpdir): o = await opc.opc.nodes.objects.add_variable(2, "xmlltext", ua.QualifiedName("mytext", 5)) await _test_xml_var_type(opc, tmpdir, o, "qualified_name") await opc.opc.delete_nodes([o])
def test_get_root(self, client): root = client.get_root_node() self.assertEqual(root.get_browse_name(), ua.QualifiedName("Root", 0))
def test_bname(): qn = ua.QualifiedName("TOTO", 2) d = struct_to_binary(qn) qn2 = struct_from_binary(ua.QualifiedName, ua.utils.Buffer(d)) assert qn == qn2
async def _create_data_type(self, type_name, nodeid=None, init=True): #name = _to_camel_case(type_name) name = type_name if nodeid is None: # create data type node dt_node = ua.AddNodesItem() dt_node.RequestedNewNodeId = ua.NodeId(0, self._idx) dt_node.BrowseName = ua.QualifiedName(name, self._idx) dt_node.NodeClass = ua.NodeClass.DataType dt_node.ParentNodeId = ua.NodeId(ua.ObjectIds.Structure, 0) dt_node.ReferenceTypeId = ua.NodeId(ua.ObjectIds.HasSubtype, 0) dt_attributes = ua.DataTypeAttributes() dt_attributes.DisplayName = ua.LocalizedText(type_name) dt_node.NodeAttributes = dt_attributes res = await self._session_server.add_nodes([dt_node]) data_type_node_id = res[0].AddedNodeId else: data_type_node_id = nodeid added = [data_type_node_id] if init: # create description node desc_node = ua.AddNodesItem() desc_node.RequestedNewNodeId = ua.NodeId(0, self._idx) desc_node.BrowseName = ua.QualifiedName(name, self._idx) desc_node.NodeClass = ua.NodeClass.Variable desc_node.ParentNodeId = self.dict_id desc_node.ReferenceTypeId = ua.NodeId(ua.ObjectIds.HasComponent, 0) desc_node.TypeDefinition = ua.NodeId( ua.ObjectIds.DataTypeDescriptionType, 0) desc_attributes = ua.VariableAttributes() desc_attributes.DisplayName = ua.LocalizedText(type_name) desc_attributes.DataType = ua.NodeId(ua.ObjectIds.String) desc_attributes.Value = ua.Variant(name, ua.VariantType.String) desc_attributes.ValueRank = -1 desc_node.NodeAttributes = desc_attributes res = await self._session_server.add_nodes([desc_node]) description_node_id = res[0].AddedNodeId added.append(description_node_id) # create object node which the loaded python class should link to obj_node = ua.AddNodesItem() obj_node.RequestedNewNodeId = ua.NodeId(0, self._idx) obj_node.BrowseName = ua.QualifiedName('Default Binary', 0) obj_node.NodeClass = ua.NodeClass.Object obj_node.ParentNodeId = data_type_node_id obj_node.ReferenceTypeId = ua.NodeId(ua.ObjectIds.HasEncoding, 0) obj_node.TypeDefinition = ua.NodeId( ua.ObjectIds.DataTypeEncodingType, 0) obj_attributes = ua.ObjectAttributes() obj_attributes.DisplayName = ua.LocalizedText('Default Binary') obj_attributes.EventNotifier = 0 obj_node.NodeAttributes = obj_attributes res = await self._session_server.add_nodes([obj_node]) bind_obj_node_id = res[0].AddedNodeId added.append(bind_obj_node_id) await self._link_nodes(bind_obj_node_id, data_type_node_id, description_node_id) self._type_dictionary.append_struct(type_name) return StructNode(self, data_type_node_id, type_name, added)
def test_get_root(self, client): root = client.nodes.root self.assertEqual(root.read_browse_name(), ua.QualifiedName("Root", 0))
async def test_server_node(opc): node = opc.opc.get_server_node() assert ua.QualifiedName('Server', 0) == await node.get_browse_name()
async def main(): # setup our server server = Server() await server.init() server.default_timeout = 60 # server.set_endpoint('opc.tcp://0.0.0.0:4840/freeopcua/server/') server.set_endpoint('opc.tcp://192.168.100.170:4840/') # setup our own namespace, not really necessary but should as spec # 设置加密和密钥后 prosys可以连接 await server.load_certificate("certificate-example.der") await server.load_private_key("private-key-example.pem") # set all possible endpoint policies for clients to connect through server.set_security_policy([ ua.SecurityPolicyType.NoSecurity, ua.SecurityPolicyType.Basic256Sha256_SignAndEncrypt, ua.SecurityPolicyType.Basic256Sha256_Sign ]) uri = 'http://examples.freeopcua.github.io' idx = await server.register_namespace(uri) # await server.import_xml('device.xml') # # get Objects node, this is where we should put our nodes objects = server.get_objects_node() suobj = await objects.add_object(idx, 'ROCKWELLObj') suvar = [] device = Rockwell_AB_PLC device.IP = '192.168.100.200' device.tag_list = [ 'Program:MainProgram.run', 'Program:MainProgram.start', 'Program:MainProgram.EMG', 'Local:1:O.Data.0', 'Local:1:O.Data.1', 'Local:1:O.Data.2', 'Local:1:O.Data.3', 'Local:1:O.Data.4', 'Local:1:O.Data.5', 'Local:1:O.Data.6', 'Local:1:O.Data.7', 'Program:MainProgram.EP_Timer.PRE', 'Program:MainProgram.EP_Timer.ACC', 'Program:MainProgram.EP_Timer.EN', 'Program:MainProgram.EP_Timer.TT', 'Program:MainProgram.EP_Timer.DN' ] # 初始化 创建 opc ua变量 a = 0 for i in device.tag_list: suvar.append(i) nodeid = (f'ns={idx};s={i}') # print(nodeid,type(nodeid)) # i=i.replace(':','-') # 添加变量,add_variable(NodeId(xxxx), QualifiedName(xxxx), DataValue(xxx)) # 加QualifiedName()否则直接写字符串":"会分割字符串 报错 suvar[a] = await suobj.add_variable(ua.NodeId(nodeid), ua.QualifiedName(i), True) # fixme 初始化需不需要特殊操作? 暂时都写0 最好和后续变量类型一致 await suvar[a].set_writable() a += 1 # await objects.add_method( # ua.NodeId('ServerMethod', 2), ua.QualifiedName('ServerMethod', 2), # func, [ua.VariantType.Int64], [ua.VariantType.Int64] # ) # _logger.info('Starting server!') async with server: count = 0 while True: await asyncio.sleep(1) # 数据更新周期 # print(device.IP,device.tag_list) aa, bb = rockwellread(device.IP, device.tag_list) # print(cc.Value) # print(aa,bb) # count += 0.1 # _logger.info(aa, bb) # await myvar.write_value(count) a = 0 for i in bb: await suvar[a].write_value(i) a += 1
async def add_server_methods(srv): @uamethod def func(parent, value): return value * 2 o = srv.get_objects_node() await o.add_method(ua.NodeId("ServerMethod", 2), ua.QualifiedName('ServerMethod', 2), func, [ua.VariantType.Int64], [ua.VariantType.Int64]) @uamethod def func2(parent, methodname, value): if methodname == "panic": return ua.StatusCode(ua.StatusCodes.BadOutOfMemory) if methodname != "sin": res = ua.CallMethodResult() res.StatusCode = ua.StatusCode(ua.StatusCodes.BadInvalidArgument) res.InputArgumentResults = [ ua.StatusCode(ua.StatusCodes.BadNotSupported), ua.StatusCode() ] return res return math.sin(value) o = srv.get_objects_node() await o.add_method(ua.NodeId("ServerMethodArray", 2), ua.QualifiedName('ServerMethodArray', 2), func2, [ua.VariantType.String, ua.VariantType.Int64], [ua.VariantType.Int64]) @uamethod def func3(parent, mylist): return [i * 2 for i in mylist] o = srv.get_objects_node() await o.add_method(ua.NodeId("ServerMethodArray2", 2), ua.QualifiedName('ServerMethodArray2', 2), func3, [ua.VariantType.Int64], [ua.VariantType.Int64]) @uamethod def func4(parent): return None base_otype = srv.get_node(ua.ObjectIds.BaseObjectType) custom_otype = await base_otype.add_object_type(2, 'ObjectWithMethodsType') await custom_otype.add_method(2, 'ServerMethodDefault', func4) await (await custom_otype.add_method(2, 'ServerMethodMandatory', func4)).set_modelling_rule(True) await (await custom_otype.add_method(2, 'ServerMethodOptional', func4)).set_modelling_rule(False) await (await custom_otype.add_method(2, 'ServerMethodNone', func4)).set_modelling_rule(None) await o.add_object(2, 'ObjectWithMethods', custom_otype) @uamethod def func5(parent): return 1, 2, 3 o = srv.get_objects_node() await o.add_method( ua.NodeId("ServerMethodTuple", 2), ua.QualifiedName('ServerMethodTuple', 2), func5, [], [ua.VariantType.Int64, ua.VariantType.Int64, ua.VariantType.Int64]) @uamethod async def func6(parent): await asyncio.sleep(0) o = srv.get_objects_node() await o.add_method(ua.NodeId("ServerMethodAsync", 2), ua.QualifiedName('ServerMethodAsync', 2), func6, [], [])
async def test_data_type_dict_create_data_type(srv): type_name = 'CustomizedStruct2' created_type = await srv.dict_builder.create_data_type(type_name) assert isinstance(created_type, StructNode) # Test data type node type_node = srv.srv.get_node(created_type.data_type) assert await type_node.read_browse_name() == ua.QualifiedName( type_name, srv.idx) assert await type_node.read_node_class() == ua.NodeClass.DataType assert (await type_node.get_parent()).nodeid == ua.NodeId( ua.ObjectIds.Structure, 0) assert ua.NodeId( ua.ObjectIds.HasSubtype, 0) == (await type_node.get_references(refs=ua.ObjectIds.HasSubtype ))[0].ReferenceTypeId assert await type_node.read_display_name() == ua.LocalizedText(type_name) # Test description node n = srv.srv.get_node(srv.dict_builder.dict_id) desc_node = await n.get_child(f"{srv.dict_builder._idx}:{type_name}") assert await desc_node.read_browse_name() == ua.QualifiedName( type_name, srv.idx) assert await desc_node.read_node_class() == ua.NodeClass.Variable assert (await desc_node.get_parent()).nodeid == srv.dict_builder.dict_id assert ua.NodeId( ua.ObjectIds.HasComponent, 0) == (await desc_node.get_references(refs=ua.ObjectIds.HasComponent ))[0].ReferenceTypeId assert await desc_node.read_type_definition() == ua.NodeId( ua.ObjectIds.DataTypeDescriptionType, 0) assert await desc_node.read_display_name() == ua.LocalizedText(type_name) assert await desc_node.read_data_type() == ua.NodeId(ua.ObjectIds.String) assert await desc_node.read_value() == type_name assert await desc_node.read_value_rank() == -1 # Test object node obj_node = (await type_node.get_children(refs=ua.ObjectIds.HasEncoding))[0] assert await obj_node.read_browse_name() == ua.QualifiedName( 'Default Binary', 0) assert await obj_node.read_node_class() == ua.NodeClass.Object assert (await obj_node.get_references(refs=ua.ObjectIds.HasEncoding ))[0].NodeId == type_node.nodeid assert ua.NodeId( ua.ObjectIds.HasEncoding, 0) == (await obj_node.get_references(refs=ua.ObjectIds.HasEncoding ))[0].ReferenceTypeId assert await obj_node.read_type_definition() == ua.NodeId( ua.ObjectIds.DataTypeEncodingType, 0) assert await obj_node.read_display_name() == ua.LocalizedText( 'Default Binary') assert len(await obj_node.read_event_notifier()) == 0 # Test links, three were tested above struct_node = srv.srv.get_node(ua.NodeId(ua.ObjectIds.Structure, 0)) struct_children = await struct_node.get_children( refs=ua.ObjectIds.HasSubtype) assert type_node in struct_children dict_node = srv.srv.get_node(srv.dict_builder.dict_id) dict_children = await dict_node.get_children(refs=ua.ObjectIds.HasComponent ) assert desc_node in dict_children assert obj_node in await type_node.get_children(ua.ObjectIds.HasEncoding) assert desc_node in await obj_node.get_children( refs=ua.ObjectIds.HasDescription) assert obj_node.nodeid == (await desc_node.get_references( refs=ua.ObjectIds.HasDescription, direction=ua.BrowseDirection.Inverse))[0].NodeId
def test_get_server_node(self, client): srv = client.nodes.server self.assertEqual(srv.read_browse_name(), ua.QualifiedName("Server", 0))
def _bname_to_string(self, bname): if bname.NamespaceIndex in self._addr_idx_to_xml_idx: bname = ua.QualifiedName( Name=bname.Name, NamespaceIndex=self._addr_idx_to_xml_idx[bname.NamespaceIndex]) return bname.to_string()