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() ESP8266=self.server.get_node("ns=0;i=20005") print("ESP8266: ") print(ESP8266) #death_button=ESP8266.get_children() watering_status=ESP8266.get_value() print(watering_status) switch_method=self.server.get_node("ns=0;i=20006") 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(switch_method, switch_mtd) # 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()
def runTest(self): tmpfile = NamedTemporaryFile() path = tmpfile.name tmpfile.close() #create cache file server = Server(cacheFile = path) #modify cache content id = ua.NodeId(ua.ObjectIds.Server_ServerStatus_SecondsTillShutdown) s = shelve.open(path, "w", writeback = True) s[id.to_string()].attributes[ua.AttributeIds.Value].value = ua.DataValue(123) s.close() #ensure that we are actually loading from the cache server = Server(cacheFile = path) self.assertEqual(server.get_node(id).get_value(), 123) os.remove(path)
class ServerPython(object): def __init__(self): self._server = None self.nodes = None self.get_node = None self.get_namespace_array = None def start_server(self, endpoint): logger.info("Starting python-opcua server") self._server = Server() self._server.set_endpoint(endpoint) self._server.set_server_name("OpcUa Modeler Server") self.nodes = self._server.nodes self.get_node = self._server.get_node self.get_namespace_array = self._server.get_namespace_array self.load_type_definitions = self._server.load_type_definitions self.load_enums = self._server.load_enums # now remove freeopcua namespace, not necessary when modeling and # ensures correct idx for exported nodesets ns_node = self._server.get_node( ua.NodeId(ua.ObjectIds.Server_NamespaceArray)) nss = ns_node.get_value() ns_node.set_value(nss[:1]) self._server.start() def stop_server(self): if self._server is not None: self._server.stop() self._server = None self.get_node = None self.get_namespace_array = None def import_xml(self, path): return self._server.import_xml(path) def export_xml(self, nodes, uris, path): exp = XmlExporter(self._server) exp.build_etree(nodes, uris=uris) exp.write_xml(path)
class ServerPython(object): def __init__(self): self._server = None self.nodes = None self.get_node = None self.get_namespace_array = None def start_server(self, endpoint): logger.info("Starting python-opcua server") self._server = Server() self._server.set_endpoint(endpoint) self._server.set_server_name("OpcUa Modeler Server") self.nodes = self._server.nodes self.get_node = self._server.get_node self.get_namespace_array = self._server.get_namespace_array self.load_type_definitions = self._server.load_type_definitions self.load_enums = self._server.load_enums # now remove freeopcua namespace, not necessary when modeling and # ensures correct idx for exported nodesets ns_node = self._server.get_node(ua.NodeId(ua.ObjectIds.Server_NamespaceArray)) nss = ns_node.get_value() ns_node.set_value(nss[:1]) self._server.start() def stop_server(self): if self._server is not None: self._server.stop() self._server = None self.get_node = None self.get_namespace_array = None def import_xml(self, path): return self._server.import_xml(path) def export_xml(self, nodes, uris, path): exp = XmlExporter(self._server) exp.build_etree(nodes, uris=uris) exp.write_xml(path)
class UaModeler(QMainWindow): def __init__(self): QMainWindow.__init__(self) self.ui = Ui_UaModeler() self.ui.setupUi(self) self.setWindowIcon(QIcon(":/network.svg")) # we only show statusbar in case of errors self.ui.statusBar.hide() # load settings, seconds arg is default self.settings = QSettings("FreeOpcUa", "OpcUaModeler") self.server = Server() self.server.set_endpoint( "opc.tcp://0.0.0.0:48400/freeopcua/uamodeler/") self.server.set_server_name("OpcUa Modeler Server") self._new_nodes = [] # the added nodes we will save self.tree_ui = TreeWidget(self.ui.treeView) self.tree_ui.error.connect(self.show_error) self.refs_ui = RefsWidget(self.ui.refView) self.refs_ui.error.connect(self.show_error) self.attrs_ui = AttrsWidget(self.ui.attrView) self.attrs_ui.error.connect(self.show_error) self.idx_ui = NamespaceWidget(self.ui.namespaceView) self.ui.treeView.activated.connect(self.show_refs) self.ui.treeView.clicked.connect(self.show_refs) self.ui.treeView.activated.connect(self.show_attrs) self.ui.treeView.clicked.connect(self.show_attrs) self.resize(int(self.settings.value("main_window_width", 800)), int(self.settings.value("main_window_height", 600))) #self.restoreState(self.settings.value("main_window_state", b"", type="QByteArray")) self.restoreState(self.settings.value("main_window_state", b"")) self.ui.splitterLeft.restoreState( self.settings.value("splitter_left", b"")) self.ui.splitterRight.restoreState( self.settings.value("splitter_right", b"")) self.ui.splitterCenter.restoreState( self.settings.value("splitter_center", b"")) self.server.start() self.tree_ui.set_root_node(self.server.get_root_node()) self.idx_ui.set_node( self.server.get_node(ua.ObjectIds.Server_NamespaceArray)) # fix icon stuff self.ui.actionAddFolder.setIcon(QIcon(":/folder.svg")) self.ui.actionAddObject.setIcon(QIcon(":/object.svg")) self.ui.actionAddObjectType.setIcon(QIcon(":/object_type.svg")) self.ui.actionAddProperty.setIcon(QIcon(":/property.svg")) self.ui.actionAddVariable.setIcon(QIcon(":/variable.svg")) self.ui.actionAddVariableType.setIcon(QIcon(":/variable_type.svg")) # menu self.ui.treeView.addAction(self.ui.actionAddFolder) self.ui.treeView.addAction(self.ui.actionAddObject) self.ui.treeView.addAction(self.ui.actionAddVariable) self.ui.treeView.addAction(self.ui.actionAddProperty) self.ui.treeView.addAction(self.ui.actionAddObjectType) self.ui.treeView.addAction(self.ui.actionAddVariableType) self.ui.treeView.addAction(self.ui.actionAddDataType) # actions self.ui.actionOpen.triggered.connect(self._open) self.ui.actionSave.triggered.connect(self._save) self.ui.actionAddObjectType.triggered.connect(self._add_object_type) self.ui.actionAddObject.triggered.connect(self._add_object) self.ui.actionAddDataType.triggered.connect(self._add_data_type) self.ui.actionAddVariable.triggered.connect(self._add_variable) self.ui.actionAddProperty.triggered.connect(self._add_property) def _open(self): path = QFileDialog.getOpenFileName(self) f = open(path[0], 'r') xml = f.read() print("should read", xml) def _save(self): raise NotImplementedError def _add_node(self, func_name, node_type=None, default_value=None): node = self.tree_ui.get_current_node() if not node: self.show_error("No node selected") raise RuntimeError("No node selected") args, ok = NewNodeDialog.getArgs(self, func_name, self.server, node_type=node_type, default_value=default_value) print("ARGS are", args) if ok: new_node = getattr(node, func_name)(*args) self._new_nodes.append(new_node) self.tree_ui.reload_current() self.show_refs() def _add_object_type(self): return self._add_node("add_object_type") def _add_object(self): return self._add_node("add_object", node_type=self.server.get_node( ua.ObjectIds.BaseObjectType)) def _add_data_type(self): return self._add_node("add_data_type") def _add_variable(self): return self._add_node("add_variable", default_value=9.99) def _add_property(self): return self._add_node("add_property", default_value=1.11) def show_refs(self, idx=None): node = self.get_current_node(idx) if node: self.refs_ui.show_refs(node) def show_attrs(self, idx=None): if not isinstance(idx, QModelIndex): idx = None node = self.get_current_node(idx) if node: self.attrs_ui.show_attrs(node) def show_error(self, msg, level=1): print("showing error: ", msg, level) self.ui.statusBar.show() self.ui.statusBar.setStyleSheet( "QStatusBar { background-color : red; color : black; }") self.ui.statusBar.showMessage(str(msg)) QTimer.singleShot(1500, self.ui.statusBar.hide) def get_current_node(self, idx=None): return self.tree_ui.get_current_node(idx) def closeEvent(self, event): self.settings.setValue("main_window_width", self.size().width()) self.settings.setValue("main_window_height", self.size().height()) self.settings.setValue("main_window_state", self.saveState()) self.settings.setValue("splitter_left", self.ui.splitterLeft.saveState()) self.settings.setValue("splitter_right", self.ui.splitterRight.saveState()) self.settings.setValue("splitter_center", self.ui.splitterCenter.saveState()) self.server.stop() event.accept()
server.load_certificate(certificate_path + "server_certificate.der") server.load_private_key(certificate_path + "server_private_key.pem") # Setup our namespace uri = "http://Aggregation.Server.opcua" #Getting the index of our nasmespace idx = server.register_namespace(uri) # get Objects node. This is where we should put our custom stuff objects = server.get_objects_node() # populate our namespace with the aggreagated element and their variables aggregator = objects.add_folder(idx, "Aggregated Servers") # definition of our custom object type -> AggregatedServer types = server.get_node(ua.ObjectIds.BaseObjectType) mycustomobj_type = types.add_object_type(idx, "AggregatedServerType") mycustomobj_type.set_modelling_rule(True) # each element of the node_ids list contains the node ids of the nodes that we want to monitor on a single sample server #This list is useful when populating object tree c_handles = [[] for i in range(len(aggr_servers))] node_ids = [[] for i in range(len(aggr_servers))] for i in range(len(aggr_servers)): for j in range(len(aggr_servers[i]["monitoring_info"])): node_ids[i].append( aggr_servers[i]["monitoring_info"][j]["nodeTomonitor"]) if (aggr_servers[i]["monitoring_info"][j]["monitoringMode"] == "monitored_item"): c_handles[i].append( aggr_servers[i]["monitoring_info"][j]["client_handle"])
idx = server.register_namespace(uri) # Import customobject type server.import_xml('customobject.xml') # get Objects node, this is where we should put our custom stuff objects = server.get_objects_node() # get nodeid of custom object type by : # 1) Use node ID # 2) Or Full path # 3) Or As child from parent nodeid_a = ua.NodeId.from_string('ns=1;i=1002') nodeid_b = server.get_root_node().get_child(["0:Types", "0:ObjectTypes", "0:BaseObjectType", "1:MyObjectType"]).nodeid nodeid_c = server.get_node(ua.ObjectIds.BaseObjectType).get_child(["1:MyObjectType"]).nodeid myobject_type_nodeid = nodeid_a # populating our address space myobj = objects.add_object(idx, "MyObject",) myobj = objects.add_object(idx, "MyCustomObject", myobject_type_nodeid) # starting! server.start() try: while True: time.sleep(1) finally:
class TestServer(unittest.TestCase, CommonTests, SubscriptionTests): ''' Run common tests on server side Tests that can only be run on server side must be defined here ''' @classmethod def setUpClass(self): self.srv = Server() self.srv.set_endpoint('opc.tcp://localhost:%d' % port_num) add_server_methods(self.srv) self.srv.start() self.opc = self.srv self.discovery = Server() self.discovery.set_application_uri("urn:freeopcua:python:discovery") self.discovery.set_endpoint('opc.tcp://localhost:%d' % port_discovery) self.discovery.start() @classmethod def tearDownClass(self): self.srv.stop() self.discovery.stop() def test_discovery(self): client = Client(self.discovery.endpoint.geturl()) client.connect() try: servers = client.find_servers() new_app_uri = "urn:freeopcua:python:server:test_discovery" self.srv.application_uri = new_app_uri self.srv.register_to_discovery(self.discovery.endpoint.geturl(), 0) time.sleep(0.1) # let server register registration new_servers = client.find_servers() self.assertEqual(len(new_servers) - len(servers) , 1) self.assertFalse(new_app_uri in [s.ApplicationUri for s in servers]) self.assertTrue(new_app_uri in [s.ApplicationUri for s in new_servers]) finally: client.disconnect() def test_find_servers2(self): client = Client(self.discovery.endpoint.geturl()) client.connect() try: servers = client.find_servers() new_app_uri1 = "urn:freeopcua:python:server:test_discovery1" self.srv.application_uri = new_app_uri1 self.srv.register_to_discovery(self.discovery.endpoint.geturl(), period=0) new_app_uri2 = "urn:freeopcua:python:test_discovery2" self.srv.application_uri = new_app_uri2 self.srv.register_to_discovery(self.discovery.endpoint.geturl(), period=0) time.sleep(0.1) # let server register registration new_servers = client.find_servers() self.assertEqual(len(new_servers) - len(servers) , 2) self.assertFalse(new_app_uri1 in [s.ApplicationUri for s in servers]) self.assertFalse(new_app_uri2 in [s.ApplicationUri for s in servers]) self.assertTrue(new_app_uri1 in [s.ApplicationUri for s in new_servers]) self.assertTrue(new_app_uri2 in [s.ApplicationUri for s in new_servers]) # now do a query with filer new_servers = client.find_servers(["urn:freeopcua:python:server"]) self.assertEqual(len(new_servers) - len(servers) , 0) self.assertTrue(new_app_uri1 in [s.ApplicationUri for s in new_servers]) self.assertFalse(new_app_uri2 in [s.ApplicationUri for s in new_servers]) # now do a query with filer new_servers = client.find_servers(["urn:freeopcua:python"]) self.assertEqual(len(new_servers) - len(servers) , 2) self.assertTrue(new_app_uri1 in [s.ApplicationUri for s in new_servers]) self.assertTrue(new_app_uri2 in [s.ApplicationUri for s in new_servers]) finally: client.disconnect() """ # not sure if this test is necessary, and there is a lot repetition with previous test def test_discovery_server_side(self): servers = self.discovery.find_servers() self.assertEqual(len(servers), 1) self.srv.register_to_discovery(self.discovery.endpoint.geturl(), 1) time.sleep(1) # let server register registration servers = self.discovery.find_servers() print("SERVERS 2", servers) self.assertEqual(len(servers), 2) """ #def test_register_server2(self): #servers = self.opc.register_server() def test_register_namespace(self): uri = 'http://mycustom.Namespace.com' idx1 = self.opc.register_namespace(uri) idx2 = self.opc.get_namespace_index(uri) self.assertEqual(idx1, idx2) def test_register_use_namespace(self): uri = 'http://my_very_custom.Namespace.com' idx = self.opc.register_namespace(uri) root = self.opc.get_root_node() myvar = root.add_variable(idx, 'var_in_custom_namespace', [5]) myid = myvar.nodeid self.assertEqual(idx, myid.NamespaceIndex) def test_server_method(self): def func(parent, variant): variant.Value *= 2 return [variant] o = self.opc.get_objects_node() v = o.add_method(3, 'Method1', func, [ua.VariantType.Int64], [ua.VariantType.Int64]) result = o.call_method(v, ua.Variant(2.1)) self.assertEqual(result, 4.2) def test_xml_import(self): self.srv.import_xml("tests/custom_nodes.xml") o = self.opc.get_objects_node() v = o.get_child(["MyXMLFolder", "MyXMLObject", "MyXMLVariable"]) val = v.get_value() self.assertEqual(val, "StringValue") def test_historize_variable(self): o = self.opc.get_objects_node() var = o.add_variable(3, "test_hist", 1.0) self.srv.iserver.enable_history_data_change(var, timedelta(days=1)) time.sleep(1) var.set_value(2.0) var.set_value(3.0) self.srv.iserver.disable_history_data_change(var) def test_historize_events(self): srv_node = self.srv.get_node(ua.ObjectIds.Server) srvevgen = self.srv.get_event_generator() self.srv.iserver.enable_history_event(srv_node, period=None) srvevgen.trigger(message="Message") self.srv.iserver.disable_history_event(srv_node) def test_references_for_added_nodes_method(self): objects = self.opc.get_objects_node() o = objects.add_object(3, 'MyObject') nodes = objects.get_referenced_nodes(refs=ua.ObjectIds.Organizes, direction=ua.BrowseDirection.Forward, includesubtypes=False) self.assertTrue(o in nodes) nodes = o.get_referenced_nodes(refs=ua.ObjectIds.Organizes, direction=ua.BrowseDirection.Inverse, includesubtypes=False) self.assertTrue(objects in nodes) self.assertEqual(o.get_parent(), objects) self.assertEqual(o.get_type_definition(), ua.ObjectIds.BaseObjectType) @uamethod def callback(parent): return m = o.add_method(3, 'MyMethod', callback) nodes = o.get_referenced_nodes(refs=ua.ObjectIds.HasComponent, direction=ua.BrowseDirection.Forward, includesubtypes=False) self.assertTrue(m in nodes) nodes = m.get_referenced_nodes(refs=ua.ObjectIds.HasComponent, direction=ua.BrowseDirection.Inverse, includesubtypes=False) self.assertTrue(o in nodes) self.assertEqual(m.get_parent(), o) # This should work for following BaseEvent tests to work (maybe to write it a bit differentlly since they are not independent) def test_get_event_from_type_node_BaseEvent(self): ev = opcua.server.event.get_event_from_type_node(opcua.Node(self.opc.iserver.isession, ua.NodeId(ua.ObjectIds.BaseEventType))) check_base_event(self, ev) def test_get_event_from_type_node_Inhereted_AuditEvent(self): ev = opcua.server.event.get_event_from_type_node(opcua.Node(self.opc.iserver.isession, ua.NodeId(ua.ObjectIds.AuditEventType))) self.assertIsNot(ev, None) # we did not receive event self.assertIsInstance(ev, ua.BaseEvent) self.assertIsInstance(ev, ua.AuditEvent) self.assertEqual(ev.EventType, ua.NodeId(ua.ObjectIds.AuditEventType)) self.assertEqual(ev.Severity, ua.Variant(1, ua.VariantType.UInt16)) self.assertEqual(ev.ActionTimeStamp, None) self.assertEqual(ev.Status, False) self.assertEqual(ev.ServerId, None) self.assertEqual(ev.ClientAuditEntryId, None) self.assertEqual(ev.ClientUserId, None) self.assertEqual(ev._freeze, True) def test_eventgenerator_default(self): evgen = self.opc.get_event_generator() check_eventgenerator_BaseEvent(self, evgen) check_eventgenerator_SourceServer(self, evgen) def test_eventgenerator_BaseEvent_object(self): evgen = self.opc.get_event_generator(ua.BaseEvent()) check_eventgenerator_BaseEvent(self, evgen) check_eventgenerator_SourceServer(self, evgen) def test_eventgenerator_BaseEvent_Node(self): evgen = self.opc.get_event_generator(opcua.Node(self.opc.iserver.isession, ua.NodeId(ua.ObjectIds.BaseEventType))) check_eventgenerator_BaseEvent(self, evgen) check_eventgenerator_SourceServer(self, evgen) def test_eventgenerator_BaseEvent_NodeId(self): evgen = self.opc.get_event_generator(ua.NodeId(ua.ObjectIds.BaseEventType)) check_eventgenerator_BaseEvent(self, evgen) check_eventgenerator_SourceServer(self, evgen) def test_eventgenerator_BaseEvent_ObjectIds(self): evgen = self.opc.get_event_generator(ua.ObjectIds.BaseEventType) check_eventgenerator_BaseEvent(self, evgen) check_eventgenerator_SourceServer(self, evgen) def test_eventgenerator_BaseEvent_Identifier(self): evgen = self.opc.get_event_generator(2041) check_eventgenerator_BaseEvent(self, evgen) check_eventgenerator_SourceServer(self, evgen) def test_eventgenerator_sourceServer_Node(self): evgen = self.opc.get_event_generator(source=opcua.Node(self.opc.iserver.isession, ua.NodeId(ua.ObjectIds.Server))) check_eventgenerator_BaseEvent(self, evgen) check_eventgenerator_SourceServer(self, evgen) def test_eventgenerator_sourceServer_NodeId(self): evgen = self.opc.get_event_generator(source=ua.NodeId(ua.ObjectIds.Server)) check_eventgenerator_BaseEvent(self, evgen) check_eventgenerator_SourceServer(self, evgen) def test_eventgenerator_sourceServer_ObjectIds(self): evgen = self.opc.get_event_generator(source=ua.ObjectIds.Server) check_eventgenerator_BaseEvent(self, evgen) check_eventgenerator_SourceServer(self, evgen) def test_eventgenerator_sourceMyObject(self): objects = self.opc.get_objects_node() o = objects.add_object(3, 'MyObject') evgen = self.opc.get_event_generator(source=o) check_eventgenerator_BaseEvent(self, evgen) check_event_generator_object(self, evgen, o) def test_eventgenerator_source_collision(self): objects = self.opc.get_objects_node() o = objects.add_object(3, 'MyObject') event = ua.BaseEvent(sourcenode=o.nodeid) evgen = self.opc.get_event_generator(event, ua.ObjectIds.Server) check_eventgenerator_BaseEvent(self, evgen) check_event_generator_object(self, evgen, o) def test_eventgenerator_InheritedEvent(self): evgen = self.opc.get_event_generator(ua.ObjectIds.AuditEventType) check_eventgenerator_SourceServer(self, evgen) ev = evgen.event self.assertIsNot(ev, None) # we did not receive event self.assertIsInstance(ev, ua.BaseEvent) self.assertIsInstance(ev, ua.AuditEvent) self.assertEqual(ev.EventType, ua.NodeId(ua.ObjectIds.AuditEventType)) self.assertEqual(ev.Severity, ua.Variant(1, ua.VariantType.UInt16)) self.assertEqual(ev.ActionTimeStamp, None) self.assertEqual(ev.Status, False) self.assertEqual(ev.ServerId, None) self.assertEqual(ev.ClientAuditEntryId, None) self.assertEqual(ev.ClientUserId, None) self.assertEqual(ev._freeze, True) def test_create_custom_event_type_ObjectId(self): etype = self.opc.create_custom_event_type(2, 'MyEvent', ua.ObjectIds.BaseEventType, [('PropertyNum', ua.VariantType.Float), ('PropertyString', ua.VariantType.String)]) check_custom_event_type(self, etype) def test_create_custom_event_type_NodeId(self): etype = self.opc.create_custom_event_type(2, 'MyEvent', ua.NodeId(ua.ObjectIds.BaseEventType), [('PropertyNum', ua.VariantType.Float), ('PropertyString', ua.VariantType.String)]) check_custom_event_type(self, etype) def test_create_custom_event_type_Node(self): etype = self.opc.create_custom_event_type(2, 'MyEvent', opcua.Node(self.opc.iserver.isession, ua.NodeId(ua.ObjectIds.BaseEventType)), [('PropertyNum', ua.VariantType.Float), ('PropertyString', ua.VariantType.String)]) check_custom_event_type(self, etype) def test_get_event_from_type_node_CustomEvent(self): etype = self.opc.create_custom_event_type(2, 'MyEvent', ua.ObjectIds.BaseEventType, [('PropertyNum', ua.VariantType.Float), ('PropertyString', ua.VariantType.String)]) ev = opcua.server.event.get_event_from_type_node(etype) check_custom_event(self, ev, etype) self.assertEqual(ev.PropertyNum, None) self.assertEqual(ev.PropertyString, None) def test_eventgenerator_customEvent(self): etype = self.opc.create_custom_event_type(2, 'MyEvent', ua.ObjectIds.BaseEventType, [('PropertyNum', ua.VariantType.Float), ('PropertyString', ua.VariantType.String)]) evgen = self.opc.get_event_generator(etype, ua.ObjectIds.Server) check_eventgenerator_CustomEvent(self, evgen, etype) check_eventgenerator_SourceServer(self, evgen) self.assertEqual(evgen.event.PropertyNum, None) self.assertEqual(evgen.event.PropertyString, None) def test_eventgenerator_double_customEvent(self): event1 = self.opc.create_custom_event_type(3, 'MyEvent1', ua.ObjectIds.BaseEventType, [('PropertyNum', ua.VariantType.Float), ('PropertyString', ua.VariantType.String)]) event2 = self.opc.create_custom_event_type(4, 'MyEvent2', event1, [('PropertyBool', ua.VariantType.Boolean), ('PropertyInt', ua.VariantType.Int32)]) evgen = self.opc.get_event_generator(event2, ua.ObjectIds.Server) check_eventgenerator_CustomEvent(self, evgen, event2) check_eventgenerator_SourceServer(self, evgen) # Properties from MyEvent1 self.assertEqual(evgen.event.PropertyNum, None) self.assertEqual(evgen.event.PropertyString, None) # Properties from MyEvent2 self.assertEqual(evgen.event.PropertyBool, None) self.assertEqual(evgen.event.PropertyInt, None) def test_eventgenerator_customEvent_MyObject(self): objects = self.opc.get_objects_node() o = objects.add_object(3, 'MyObject') etype = self.opc.create_custom_event_type(2, 'MyEvent', ua.ObjectIds.BaseEventType, [('PropertyNum', ua.VariantType.Float), ('PropertyString', ua.VariantType.String)]) evgen = self.opc.get_event_generator(etype, o) check_eventgenerator_CustomEvent(self, evgen, etype) check_event_generator_object(self, evgen, o) self.assertEqual(evgen.event.PropertyNum, None) self.assertEqual(evgen.event.PropertyString, None)
class TestServer(unittest.TestCase, CommonTests, SubscriptionTests): ''' Run common tests on server side Tests that can only be run on server side must be defined here ''' @classmethod def setUpClass(self): self.srv = Server() self.srv.set_endpoint('opc.tcp://localhost:%d' % port_num) add_server_methods(self.srv) self.srv.start() self.opc = self.srv self.discovery = Server() self.discovery.set_application_uri("urn:freeopcua:python:discovery") self.discovery.set_endpoint('opc.tcp://localhost:%d' % port_discovery) self.discovery.start() @classmethod def tearDownClass(self): self.srv.stop() self.discovery.stop() def test_discovery(self): client = Client(self.discovery.endpoint.geturl()) client.connect() try: servers = client.find_servers() new_app_uri = "urn:freeopcua:python:server:test_discovery" self.srv.application_uri = new_app_uri self.srv.register_to_discovery(self.discovery.endpoint.geturl(), 0) time.sleep(0.1) # let server register registration new_servers = client.find_servers() self.assertEqual(len(new_servers) - len(servers) , 1) self.assertFalse(new_app_uri in [s.ApplicationUri for s in servers]) self.assertTrue(new_app_uri in [s.ApplicationUri for s in new_servers]) finally: client.disconnect() def test_find_servers2(self): client = Client(self.discovery.endpoint.geturl()) client.connect() try: servers = client.find_servers() new_app_uri1 = "urn:freeopcua:python:server:test_discovery1" self.srv.application_uri = new_app_uri1 self.srv.register_to_discovery(self.discovery.endpoint.geturl(), period=0) new_app_uri2 = "urn:freeopcua:python:test_discovery2" self.srv.application_uri = new_app_uri2 self.srv.register_to_discovery(self.discovery.endpoint.geturl(), period=0) time.sleep(0.1) # let server register registration new_servers = client.find_servers() self.assertEqual(len(new_servers) - len(servers) , 2) self.assertFalse(new_app_uri1 in [s.ApplicationUri for s in servers]) self.assertFalse(new_app_uri2 in [s.ApplicationUri for s in servers]) self.assertTrue(new_app_uri1 in [s.ApplicationUri for s in new_servers]) self.assertTrue(new_app_uri2 in [s.ApplicationUri for s in new_servers]) # now do a query with filer new_servers = client.find_servers(["urn:freeopcua:python:server"]) self.assertEqual(len(new_servers) - len(servers) , 0) self.assertTrue(new_app_uri1 in [s.ApplicationUri for s in new_servers]) self.assertFalse(new_app_uri2 in [s.ApplicationUri for s in new_servers]) # now do a query with filer new_servers = client.find_servers(["urn:freeopcua:python"]) self.assertEqual(len(new_servers) - len(servers) , 2) self.assertTrue(new_app_uri1 in [s.ApplicationUri for s in new_servers]) self.assertTrue(new_app_uri2 in [s.ApplicationUri for s in new_servers]) finally: client.disconnect() """ # not sure if this test is necessary, and there is a lot repetition with previous test def test_discovery_server_side(self): servers = self.discovery.find_servers() self.assertEqual(len(servers), 1) self.srv.register_to_discovery(self.discovery.endpoint.geturl(), 1) time.sleep(1) # let server register registration servers = self.discovery.find_servers() print("SERVERS 2", servers) self.assertEqual(len(servers), 2) """ #def test_register_server2(self): #servers = self.opc.register_server() def test_register_namespace(self): uri = 'http://mycustom.Namespace.com' idx1 = self.opc.register_namespace(uri) idx2 = self.opc.get_namespace_index(uri) self.assertEqual(idx1, idx2) def test_register_use_namespace(self): uri = 'http://my_very_custom.Namespace.com' idx = self.opc.register_namespace(uri) root = self.opc.get_root_node() myvar = root.add_variable(idx, 'var_in_custom_namespace', [5]) myid = myvar.nodeid self.assertEqual(idx, myid.NamespaceIndex) def test_server_method(self): def func(parent, variant): variant.Value *= 2 return [variant] o = self.opc.get_objects_node() v = o.add_method(3, 'Method1', func, [ua.VariantType.Int64], [ua.VariantType.Int64]) result = o.call_method(v, ua.Variant(2.1)) self.assertEqual(result, 4.2) def test_xml_import(self): self.srv.import_xml("tests/custom_nodes.xml") o = self.opc.get_objects_node() v = o.get_child(["MyXMLFolder", "MyXMLObject", "MyXMLVariable"]) val = v.get_value() self.assertEqual(val, "StringValue") def test_historize_variable(self): o = self.opc.get_objects_node() var = o.add_variable(3, "test_hist", 1.0) self.srv.iserver.enable_history_data_change(var, timedelta(days=1)) time.sleep(1) var.set_value(2.0) var.set_value(3.0) self.srv.iserver.disable_history_data_change(var) def test_historize_events(self): srv_node = self.srv.get_node(ua.ObjectIds.Server) srvevgen = self.srv.get_event_generator() self.srv.iserver.enable_history_event(srv_node, period=None) srvevgen.trigger(message="Message") self.srv.iserver.disable_history_event(srv_node) def test_references_for_added_nodes_method(self): objects = self.opc.get_objects_node() o = objects.add_object(3, 'MyObject') nodes = objects.get_referenced_nodes(refs=ua.ObjectIds.Organizes, direction=ua.BrowseDirection.Forward, includesubtypes=False) self.assertTrue(o in nodes) nodes = o.get_referenced_nodes(refs=ua.ObjectIds.Organizes, direction=ua.BrowseDirection.Inverse, includesubtypes=False) self.assertTrue(objects in nodes) self.assertEqual(o.get_parent(), objects) self.assertEqual(o.get_type_definition(), ua.ObjectIds.BaseObjectType) @uamethod def callback(parent): return m = o.add_method(3, 'MyMethod', callback) nodes = o.get_referenced_nodes(refs=ua.ObjectIds.HasComponent, direction=ua.BrowseDirection.Forward, includesubtypes=False) self.assertTrue(m in nodes) nodes = m.get_referenced_nodes(refs=ua.ObjectIds.HasComponent, direction=ua.BrowseDirection.Inverse, includesubtypes=False) self.assertTrue(o in nodes) self.assertEqual(m.get_parent(), o) # This should work for following BaseEvent tests to work (maybe to write it a bit differentlly since they are not independent) def test_get_event_from_type_node_BaseEvent(self): ev = opcua.common.events.get_event_obj_from_type_node(opcua.Node(self.opc.iserver.isession, ua.NodeId(ua.ObjectIds.BaseEventType))) check_base_event(self, ev) def test_get_event_from_type_node_Inhereted_AuditEvent(self): ev = opcua.common.events.get_event_obj_from_type_node(opcua.Node(self.opc.iserver.isession, ua.NodeId(ua.ObjectIds.AuditEventType))) self.assertIsNot(ev, None) # we did not receive event self.assertIsInstance(ev, BaseEvent) self.assertIsInstance(ev, AuditEvent) self.assertEqual(ev.EventType, ua.NodeId(ua.ObjectIds.AuditEventType)) self.assertEqual(ev.Severity, 1) self.assertEqual(ev.ActionTimeStamp, None) self.assertEqual(ev.Status, False) self.assertEqual(ev.ServerId, None) self.assertEqual(ev.ClientAuditEntryId, None) self.assertEqual(ev.ClientUserId, None) def test_eventgenerator_default(self): evgen = self.opc.get_event_generator() check_eventgenerator_BaseEvent(self, evgen) check_eventgenerator_SourceServer(self, evgen) def test_eventgenerator_BaseEvent_object(self): evgen = self.opc.get_event_generator(BaseEvent()) check_eventgenerator_BaseEvent(self, evgen) check_eventgenerator_SourceServer(self, evgen) def test_eventgenerator_BaseEvent_Node(self): evgen = self.opc.get_event_generator(opcua.Node(self.opc.iserver.isession, ua.NodeId(ua.ObjectIds.BaseEventType))) check_eventgenerator_BaseEvent(self, evgen) check_eventgenerator_SourceServer(self, evgen) def test_eventgenerator_BaseEvent_NodeId(self): evgen = self.opc.get_event_generator(ua.NodeId(ua.ObjectIds.BaseEventType)) check_eventgenerator_BaseEvent(self, evgen) check_eventgenerator_SourceServer(self, evgen) def test_eventgenerator_BaseEvent_ObjectIds(self): evgen = self.opc.get_event_generator(ua.ObjectIds.BaseEventType) check_eventgenerator_BaseEvent(self, evgen) check_eventgenerator_SourceServer(self, evgen) def test_eventgenerator_BaseEvent_Identifier(self): evgen = self.opc.get_event_generator(2041) check_eventgenerator_BaseEvent(self, evgen) check_eventgenerator_SourceServer(self, evgen) def test_eventgenerator_sourceServer_Node(self): evgen = self.opc.get_event_generator(source=opcua.Node(self.opc.iserver.isession, ua.NodeId(ua.ObjectIds.Server))) check_eventgenerator_BaseEvent(self, evgen) check_eventgenerator_SourceServer(self, evgen) def test_eventgenerator_sourceServer_NodeId(self): evgen = self.opc.get_event_generator(source=ua.NodeId(ua.ObjectIds.Server)) check_eventgenerator_BaseEvent(self, evgen) check_eventgenerator_SourceServer(self, evgen) def test_eventgenerator_sourceServer_ObjectIds(self): evgen = self.opc.get_event_generator(source=ua.ObjectIds.Server) check_eventgenerator_BaseEvent(self, evgen) check_eventgenerator_SourceServer(self, evgen) def test_eventgenerator_sourceMyObject(self): objects = self.opc.get_objects_node() o = objects.add_object(3, 'MyObject') evgen = self.opc.get_event_generator(source=o) check_eventgenerator_BaseEvent(self, evgen) check_event_generator_object(self, evgen, o) def test_eventgenerator_source_collision(self): objects = self.opc.get_objects_node() o = objects.add_object(3, 'MyObject') event = BaseEvent(sourcenode=o.nodeid) evgen = self.opc.get_event_generator(event, ua.ObjectIds.Server) check_eventgenerator_BaseEvent(self, evgen) check_event_generator_object(self, evgen, o) def test_eventgenerator_InheritedEvent(self): evgen = self.opc.get_event_generator(ua.ObjectIds.AuditEventType) check_eventgenerator_SourceServer(self, evgen) ev = evgen.event self.assertIsNot(ev, None) # we did not receive event self.assertIsInstance(ev, BaseEvent) self.assertIsInstance(ev, AuditEvent) self.assertEqual(ev.EventType, ua.NodeId(ua.ObjectIds.AuditEventType)) self.assertEqual(ev.Severity, 1) self.assertEqual(ev.ActionTimeStamp, None) self.assertEqual(ev.Status, False) self.assertEqual(ev.ServerId, None) self.assertEqual(ev.ClientAuditEntryId, None) self.assertEqual(ev.ClientUserId, None) def test_create_custom_event_type_ObjectId(self): etype = self.opc.create_custom_event_type(2, 'MyEvent', ua.ObjectIds.BaseEventType, [('PropertyNum', ua.VariantType.Float), ('PropertyString', ua.VariantType.String)]) check_custom_event_type(self, etype) def test_create_custom_event_type_NodeId(self): etype = self.opc.create_custom_event_type(2, 'MyEvent', ua.NodeId(ua.ObjectIds.BaseEventType), [('PropertyNum', ua.VariantType.Float), ('PropertyString', ua.VariantType.String)]) check_custom_event_type(self, etype) def test_create_custom_event_type_Node(self): etype = self.opc.create_custom_event_type(2, 'MyEvent', opcua.Node(self.opc.iserver.isession, ua.NodeId(ua.ObjectIds.BaseEventType)), [('PropertyNum', ua.VariantType.Float), ('PropertyString', ua.VariantType.String)]) check_custom_event_type(self, etype) def test_get_event_from_type_node_CustomEvent(self): etype = self.opc.create_custom_event_type(2, 'MyEvent', ua.ObjectIds.BaseEventType, [('PropertyNum', ua.VariantType.Float), ('PropertyString', ua.VariantType.String)]) ev = opcua.common.events.get_event_obj_from_type_node(etype) check_custom_event(self, ev, etype) self.assertEqual(ev.PropertyNum, None) self.assertEqual(ev.PropertyString, None) def test_eventgenerator_customEvent(self): etype = self.opc.create_custom_event_type(2, 'MyEvent', ua.ObjectIds.BaseEventType, [('PropertyNum', ua.VariantType.Float), ('PropertyString', ua.VariantType.String)]) evgen = self.opc.get_event_generator(etype, ua.ObjectIds.Server) check_eventgenerator_CustomEvent(self, evgen, etype) check_eventgenerator_SourceServer(self, evgen) self.assertEqual(evgen.event.PropertyNum, None) self.assertEqual(evgen.event.PropertyString, None) def test_eventgenerator_double_customEvent(self): event1 = self.opc.create_custom_event_type(3, 'MyEvent1', ua.ObjectIds.BaseEventType, [('PropertyNum', ua.VariantType.Float), ('PropertyString', ua.VariantType.String)]) event2 = self.opc.create_custom_event_type(4, 'MyEvent2', event1, [('PropertyBool', ua.VariantType.Boolean), ('PropertyInt', ua.VariantType.Int32)]) evgen = self.opc.get_event_generator(event2, ua.ObjectIds.Server) check_eventgenerator_CustomEvent(self, evgen, event2) check_eventgenerator_SourceServer(self, evgen) # Properties from MyEvent1 self.assertEqual(evgen.event.PropertyNum, None) self.assertEqual(evgen.event.PropertyString, None) # Properties from MyEvent2 self.assertEqual(evgen.event.PropertyBool, None) self.assertEqual(evgen.event.PropertyInt, None) def test_eventgenerator_customEvent_MyObject(self): objects = self.opc.get_objects_node() o = objects.add_object(3, 'MyObject') etype = self.opc.create_custom_event_type(2, 'MyEvent', ua.ObjectIds.BaseEventType, [('PropertyNum', ua.VariantType.Float), ('PropertyString', ua.VariantType.String)]) evgen = self.opc.get_event_generator(etype, o) check_eventgenerator_CustomEvent(self, evgen, etype) check_event_generator_object(self, evgen, o) self.assertEqual(evgen.event.PropertyNum, None) self.assertEqual(evgen.event.PropertyString, None)
class TestAttrsWidget(unittest.TestCase): def setUp(self): self.server = Server() self.server.set_endpoint("opc.tcp://0.0.0.0:4840/freeopcua/server/") self.server.start() self.widget = AttrsWidget(QTreeView()) def tearDown(self): self.server.stop() def find_item(self, text): idxlist = self.widget.model.match(self.widget.model.index(0, 0), Qt.DisplayRole, text, 1, Qt.MatchExactly | Qt.MatchRecursive) idx = idxlist[0] return idx def modify_item(self, text, val, match_to_use=0): """ modify the current item and set its displayed value to 'val' """ idxlist = self.widget.model.match(self.widget.model.index(0, 0), Qt.DisplayRole, text, match_to_use + 1, Qt.MatchExactly | Qt.MatchRecursive) if not idxlist: raise RuntimeError("Item with text '{}' not found".format(text)) idx = idxlist[match_to_use] self.widget.view.setCurrentIndex(idx) idx = idx.sibling(idx.row(), 1) self.widget.view.edit(idx) editor = self.widget.view.focusWidget() if not editor: print(app.focusWidget()) print("NO EDITOR WIDGET") #QTest.keyClick(self.widget.view, Qt.Key_Return) from IPython import embed embed() raise RuntimeError("Could not get editor widget!, it does not have the focus") if hasattr(editor, "_current_node"): editor._current_node = val elif hasattr(editor, "setCurrentText"): editor.setCurrentText(val) else: editor.setText(val) self.widget.view.commitData(editor) self.widget.view.closeEditor(editor, QAbstractItemDelegate.NoHint) self.widget.view.reset() def modify_value(self, val): self.modify_item("Value", val, 1) def test_display_objects_node(self): objects = self.server.nodes.objects self.widget.show_attrs(objects) self.modify_item("BrowseName", "5:titi") self.assertEqual(objects.get_browse_name().to_string(), "5:titi") self.modify_item("BrowseName", "0:Objects") # restore states for other tests def test_display_var_double(self): objects = self.server.nodes.objects myvar = objects.add_variable(1, "myvar1", 9.99, ua.VariantType.Double) self.widget.show_attrs(myvar) self.modify_value("8.45") self.assertEqual(myvar.get_value(), 8.45) def test_display_var_bytes(self): objects = self.server.nodes.objects myvar = objects.add_variable(1, "myvar_bytes", b"jkl", ua.VariantType.ByteString) self.widget.show_attrs(myvar) self.modify_value("titi") self.assertEqual(myvar.get_value(), b"titi") def test_change_data_type(self): objects = self.server.nodes.objects myvar = objects.add_variable(1, "myvar1", 9.99, ua.VariantType.Double) self.widget.show_attrs(myvar) dtype = myvar.get_data_type() self.assertEqual(dtype, ua.NodeId(ua.ObjectIds.Double)) new_dtype = ua.NodeId(ua.ObjectIds.String) self.modify_item("DataType", self.server.get_node(new_dtype)) self.assertEqual(myvar.get_data_type(), new_dtype) # now try to write a value which is a string self.modify_value("mystring") self.assertEqual(myvar.get_value(), "mystring") def test_change_value_rank(self): # need to find a way to modify combo box with QTest objects = self.server.nodes.objects myvar = objects.add_variable(1, "myvar1", 9.99, ua.VariantType.Double) self.widget.show_attrs(myvar) rank = myvar.get_value_rank() self.modify_item("ValueRank", "ThreeDimensions") self.assertEqual(myvar.get_value_rank(), ua.ValueRank.ThreeDimensions)
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'])
class TestAttrsWidget(unittest.TestCase): def setUp(self): self.server = Server() self.server.set_endpoint("opc.tcp://0.0.0.0:4840/freeopcua/server/") self.server.start() self.widget = AttrsWidget(QTreeView()) def tearDown(self): self.server.stop() def find_item(self, text): idxlist = self.widget.model.match(self.widget.model.index(0, 0), Qt.DisplayRole, text, 1, Qt.MatchExactly | Qt.MatchRecursive) idx = idxlist[0] return idx def modify_item(self, text, val, match_to_use=0): """ modify the current item and set its displayed value to 'val' """ idxlist = self.widget.model.match(self.widget.model.index(0, 0), Qt.DisplayRole, text, match_to_use + 1, Qt.MatchExactly | Qt.MatchRecursive) if not idxlist: raise RuntimeError("Item with text '{}' not found".format(text)) idx = idxlist[match_to_use] self.widget.view.setCurrentIndex(idx) idx = idx.sibling(idx.row(), 1) self.widget.view.edit(idx) editor = self.widget.view.focusWidget() if not editor: print(app.focusWidget()) print("NO EDITOR WIDGET") #QTest.keyClick(self.widget.view, Qt.Key_Return) from IPython import embed embed() raise RuntimeError( "Could not get editor widget!, it does not have the focus") if hasattr(editor, "current_node"): editor.current_node = val elif hasattr(editor, "setCurrentText"): editor.setCurrentText(val) else: editor.setText(val) self.widget.view.commitData(editor) self.widget.view.closeEditor(editor, QAbstractItemDelegate.NoHint) self.widget.view.reset() def modify_value(self, val): self.modify_item("Value", val, 1) def test_display_objects_node(self): objects = self.server.nodes.objects self.widget.show_attrs(objects) self.modify_item("BrowseName", "5:titi") self.assertEqual(objects.get_browse_name().to_string(), "5:titi") self.modify_item("BrowseName", "0:Objects") # restore states for other tests def test_display_var_double(self): objects = self.server.nodes.objects myvar = objects.add_variable(1, "myvar1", 9.99, ua.VariantType.Double) self.widget.show_attrs(myvar) self.modify_value("8.45") self.assertEqual(myvar.get_value(), 8.45) def test_display_var_bytes(self): objects = self.server.nodes.objects myvar = objects.add_variable(1, "myvar_bytes", b"jkl", ua.VariantType.ByteString) self.widget.show_attrs(myvar) self.modify_value("titi") self.assertEqual(myvar.get_value(), b"titi") def test_change_data_type(self): objects = self.server.nodes.objects myvar = objects.add_variable(1, "myvar1", 9.99, ua.VariantType.Double) self.widget.show_attrs(myvar) dtype = myvar.get_data_type() self.assertEqual(dtype, ua.NodeId(ua.ObjectIds.Double)) new_dtype = ua.NodeId(ua.ObjectIds.String) self.modify_item("DataType", self.server.get_node(new_dtype)) self.assertEqual(myvar.get_data_type(), new_dtype) # now try to write a value which is a string self.modify_value("mystring") self.assertEqual(myvar.get_value(), "mystring") def test_change_value_rank( self): # need to find a way to modify combo box with QTest objects = self.server.nodes.objects myvar = objects.add_variable(1, "myvar1", 9.99, ua.VariantType.Double) self.widget.show_attrs(myvar) rank = myvar.get_value_rank() self.modify_item("ValueRank", "ThreeDimensions") self.assertEqual(myvar.get_value_rank(), ua.ValueRank.ThreeDimensions)
class TestServer(unittest.TestCase, CommonTests, SubscriptionTests): ''' Run common tests on server side Tests that can only be run on server side must be defined here ''' @classmethod def setUpClass(self): self.srv = Server() self.srv.set_endpoint('opc.tcp://localhost:%d' % port_num) add_server_methods(self.srv) self.srv.start() self.opc = self.srv self.discovery = Server() self.discovery.set_application_uri("urn:freeopcua:python:discovery") self.discovery.set_endpoint('opc.tcp://localhost:%d' % port_discovery) self.discovery.start() @classmethod def tearDownClass(self): self.srv.stop() self.discovery.stop() def test_discovery(self): client = Client(self.discovery.endpoint.geturl()) client.connect() try: servers = client.find_servers() new_app_uri = "urn:freeopcua:python:server:test_discovery" self.srv.application_uri = new_app_uri self.srv.register_to_discovery(self.discovery.endpoint.geturl(), 0) time.sleep(0.1) # let server register registration new_servers = client.find_servers() self.assertEqual(len(new_servers) - len(servers) , 1) self.assertFalse(new_app_uri in [s.ApplicationUri for s in servers]) self.assertTrue(new_app_uri in [s.ApplicationUri for s in new_servers]) finally: client.disconnect() def test_find_servers2(self): client = Client(self.discovery.endpoint.geturl()) client.connect() try: servers = client.find_servers() new_app_uri1 = "urn:freeopcua:python:server:test_discovery1" self.srv.application_uri = new_app_uri1 self.srv.register_to_discovery(self.discovery.endpoint.geturl(), period=0) new_app_uri2 = "urn:freeopcua:python:test_discovery2" self.srv.application_uri = new_app_uri2 self.srv.register_to_discovery(self.discovery.endpoint.geturl(), period=0) time.sleep(0.1) # let server register registration new_servers = client.find_servers() self.assertEqual(len(new_servers) - len(servers) , 2) self.assertFalse(new_app_uri1 in [s.ApplicationUri for s in servers]) self.assertFalse(new_app_uri2 in [s.ApplicationUri for s in servers]) self.assertTrue(new_app_uri1 in [s.ApplicationUri for s in new_servers]) self.assertTrue(new_app_uri2 in [s.ApplicationUri for s in new_servers]) # now do a query with filer new_servers = client.find_servers(["urn:freeopcua:python:server"]) self.assertEqual(len(new_servers) - len(servers) , 0) self.assertTrue(new_app_uri1 in [s.ApplicationUri for s in new_servers]) self.assertFalse(new_app_uri2 in [s.ApplicationUri for s in new_servers]) # now do a query with filer new_servers = client.find_servers(["urn:freeopcua:python"]) self.assertEqual(len(new_servers) - len(servers) , 2) self.assertTrue(new_app_uri1 in [s.ApplicationUri for s in new_servers]) self.assertTrue(new_app_uri2 in [s.ApplicationUri for s in new_servers]) finally: client.disconnect() """ # not sure if this test is necessary, and there is a lot repetition with previous test def test_discovery_server_side(self): servers = self.discovery.find_servers() self.assertEqual(len(servers), 1) self.srv.register_to_discovery(self.discovery.endpoint.geturl(), 1) time.sleep(1) # let server register registration servers = self.discovery.find_servers() print("SERVERS 2", servers) self.assertEqual(len(servers), 2) """ #def test_register_server2(self): #servers = self.opc.register_server() def test_register_namespace(self): uri = 'http://mycustom.Namespace.com' idx1 = self.opc.register_namespace(uri) idx2 = self.opc.get_namespace_index(uri) self.assertEqual(idx1, idx2) def test_register_existing_namespace(self): uri = 'http://mycustom.Namespace.com' idx1 = self.opc.register_namespace(uri) idx2 = self.opc.register_namespace(uri) idx3 = self.opc.get_namespace_index(uri) self.assertEqual(idx1, idx2) self.assertEqual(idx1, idx3) def test_register_use_namespace(self): uri = 'http://my_very_custom.Namespace.com' idx = self.opc.register_namespace(uri) root = self.opc.get_root_node() myvar = root.add_variable(idx, 'var_in_custom_namespace', [5]) myid = myvar.nodeid self.assertEqual(idx, myid.NamespaceIndex) def test_server_method(self): def func(parent, variant): variant.Value *= 2 return [variant] o = self.opc.get_objects_node() v = o.add_method(3, 'Method1', func, [ua.VariantType.Int64], [ua.VariantType.Int64]) result = o.call_method(v, ua.Variant(2.1)) self.assertEqual(result, 4.2) def test_xml_import(self): self.srv.import_xml("tests/custom_nodes.xml") o = self.opc.get_objects_node() v = o.get_child(["MyXMLFolder", "MyXMLObject", "MyXMLVariable"]) val = v.get_value() self.assertEqual(val, "StringValue") node_path = ["Types", "DataTypes", "BaseDataType", "Enumeration", "1:MyEnum", "0:EnumStrings"] o = self.opc.get_root_node().get_child(node_path) self.assertEqual(len(o.get_value()), 3) # Check if method is imported node_path = ["Types", "ObjectTypes", "BaseObjectType", "1:MyObjectType", "1:MyMethod"] o = self.opc.get_root_node().get_child(node_path) self.assertEqual(len(o.get_referenced_nodes()), 4) # Check if InputArgs are imported and can be read node_path = ["Types", "ObjectTypes", "BaseObjectType", "1:MyObjectType", "1:MyMethod", "InputArguments"] o = self.opc.get_root_node().get_child(node_path) input_arg = o.get_data_value().Value.Value[0] self.assertEqual(input_arg.Name, 'Context') def test_historize_variable(self): o = self.opc.get_objects_node() var = o.add_variable(3, "test_hist", 1.0) self.srv.iserver.enable_history_data_change(var, timedelta(days=1)) time.sleep(1) var.set_value(2.0) var.set_value(3.0) self.srv.iserver.disable_history_data_change(var) def test_historize_events(self): srv_node = self.srv.get_node(ua.ObjectIds.Server) srvevgen = self.srv.get_event_generator() self.srv.iserver.enable_history_event(srv_node, period=None) srvevgen.trigger(message="Message") self.srv.iserver.disable_history_event(srv_node) def test_references_for_added_nodes_method(self): objects = self.opc.get_objects_node() o = objects.add_object(3, 'MyObject') nodes = objects.get_referenced_nodes(refs=ua.ObjectIds.Organizes, direction=ua.BrowseDirection.Forward, includesubtypes=False) self.assertTrue(o in nodes) nodes = o.get_referenced_nodes(refs=ua.ObjectIds.Organizes, direction=ua.BrowseDirection.Inverse, includesubtypes=False) self.assertTrue(objects in nodes) self.assertEqual(o.get_parent(), objects) self.assertEqual(o.get_type_definition().Identifier, ua.ObjectIds.BaseObjectType) @uamethod def callback(parent): return m = o.add_method(3, 'MyMethod', callback) nodes = o.get_referenced_nodes(refs=ua.ObjectIds.HasComponent, direction=ua.BrowseDirection.Forward, includesubtypes=False) self.assertTrue(m in nodes) nodes = m.get_referenced_nodes(refs=ua.ObjectIds.HasComponent, direction=ua.BrowseDirection.Inverse, includesubtypes=False) self.assertTrue(o in nodes) self.assertEqual(m.get_parent(), o) # This should work for following BaseEvent tests to work (maybe to write it a bit differentlly since they are not independent) def test_get_event_from_type_node_BaseEvent(self): ev = opcua.common.events.get_event_obj_from_type_node(opcua.Node(self.opc.iserver.isession, ua.NodeId(ua.ObjectIds.BaseEventType))) check_base_event(self, ev) def test_get_event_from_type_node_Inhereted_AuditEvent(self): ev = opcua.common.events.get_event_obj_from_type_node(opcua.Node(self.opc.iserver.isession, ua.NodeId(ua.ObjectIds.AuditEventType))) self.assertIsNot(ev, None) # we did not receive event self.assertIsInstance(ev, BaseEvent) self.assertIsInstance(ev, AuditEvent) self.assertEqual(ev.EventType, ua.NodeId(ua.ObjectIds.AuditEventType)) self.assertEqual(ev.Severity, 1) self.assertEqual(ev.ActionTimeStamp, None) self.assertEqual(ev.Status, False) self.assertEqual(ev.ServerId, None) self.assertEqual(ev.ClientAuditEntryId, None) self.assertEqual(ev.ClientUserId, None) def test_eventgenerator_default(self): evgen = self.opc.get_event_generator() check_eventgenerator_BaseEvent(self, evgen) check_eventgenerator_SourceServer(self, evgen) def test_eventgenerator_BaseEvent_object(self): evgen = self.opc.get_event_generator(BaseEvent()) check_eventgenerator_BaseEvent(self, evgen) check_eventgenerator_SourceServer(self, evgen) def test_eventgenerator_BaseEvent_Node(self): evgen = self.opc.get_event_generator(opcua.Node(self.opc.iserver.isession, ua.NodeId(ua.ObjectIds.BaseEventType))) check_eventgenerator_BaseEvent(self, evgen) check_eventgenerator_SourceServer(self, evgen) def test_eventgenerator_BaseEvent_NodeId(self): evgen = self.opc.get_event_generator(ua.NodeId(ua.ObjectIds.BaseEventType)) check_eventgenerator_BaseEvent(self, evgen) check_eventgenerator_SourceServer(self, evgen) def test_eventgenerator_BaseEvent_ObjectIds(self): evgen = self.opc.get_event_generator(ua.ObjectIds.BaseEventType) check_eventgenerator_BaseEvent(self, evgen) check_eventgenerator_SourceServer(self, evgen) def test_eventgenerator_BaseEvent_Identifier(self): evgen = self.opc.get_event_generator(2041) check_eventgenerator_BaseEvent(self, evgen) check_eventgenerator_SourceServer(self, evgen) def test_eventgenerator_sourceServer_Node(self): evgen = self.opc.get_event_generator(source=opcua.Node(self.opc.iserver.isession, ua.NodeId(ua.ObjectIds.Server))) check_eventgenerator_BaseEvent(self, evgen) check_eventgenerator_SourceServer(self, evgen) def test_eventgenerator_sourceServer_NodeId(self): evgen = self.opc.get_event_generator(source=ua.NodeId(ua.ObjectIds.Server)) check_eventgenerator_BaseEvent(self, evgen) check_eventgenerator_SourceServer(self, evgen) def test_eventgenerator_sourceServer_ObjectIds(self): evgen = self.opc.get_event_generator(source=ua.ObjectIds.Server) check_eventgenerator_BaseEvent(self, evgen) check_eventgenerator_SourceServer(self, evgen) def test_eventgenerator_sourceMyObject(self): objects = self.opc.get_objects_node() o = objects.add_object(3, 'MyObject') evgen = self.opc.get_event_generator(source=o) check_eventgenerator_BaseEvent(self, evgen) check_event_generator_object(self, evgen, o) def test_eventgenerator_source_collision(self): objects = self.opc.get_objects_node() o = objects.add_object(3, 'MyObject') event = BaseEvent(sourcenode=o.nodeid) evgen = self.opc.get_event_generator(event, ua.ObjectIds.Server) check_eventgenerator_BaseEvent(self, evgen) check_event_generator_object(self, evgen, o) def test_eventgenerator_InheritedEvent(self): evgen = self.opc.get_event_generator(ua.ObjectIds.AuditEventType) check_eventgenerator_SourceServer(self, evgen) ev = evgen.event self.assertIsNot(ev, None) # we did not receive event self.assertIsInstance(ev, BaseEvent) self.assertIsInstance(ev, AuditEvent) self.assertEqual(ev.EventType, ua.NodeId(ua.ObjectIds.AuditEventType)) self.assertEqual(ev.Severity, 1) self.assertEqual(ev.ActionTimeStamp, None) self.assertEqual(ev.Status, False) self.assertEqual(ev.ServerId, None) self.assertEqual(ev.ClientAuditEntryId, None) self.assertEqual(ev.ClientUserId, None) # For the custom events all posibilites are tested. For other custom types only one test case is done since they are using the same code def test_create_custom_data_type_ObjectId(self): type = self.opc.create_custom_data_type(2, 'MyDataType', ua.ObjectIds.BaseDataType, [('PropertyNum', ua.VariantType.Int32), ('PropertyString', ua.VariantType.String)]) check_custom_type(self, type, ua.ObjectIds.BaseDataType) def test_create_custom_event_type_ObjectId(self): type = self.opc.create_custom_event_type(2, 'MyEvent', ua.ObjectIds.BaseEventType, [('PropertyNum', ua.VariantType.Int32), ('PropertyString', ua.VariantType.String)]) check_custom_type(self, type, ua.ObjectIds.BaseEventType) def test_create_custom_object_type_ObjectId(self): def func(parent, variant): return [ua.Variant(ret, ua.VariantType.Boolean)] properties = [('PropertyNum', ua.VariantType.Int32), ('PropertyString', ua.VariantType.String)] variables = [('VariableString', ua.VariantType.String), ('MyEnumVar', ua.VariantType.Int32, ua.NodeId(ua.ObjectIds.ApplicationType))] methods = [('MyMethod', func, [ua.VariantType.Int64], [ua.VariantType.Boolean])] node_type = self.opc.create_custom_object_type(2, 'MyObjectType', ua.ObjectIds.BaseObjectType, properties, variables, methods) check_custom_type(self, node_type, ua.ObjectIds.BaseObjectType) variables = node_type.get_variables() self.assertTrue(node_type.get_child("2:VariableString") in variables) self.assertEqual(node_type.get_child("2:VariableString").get_data_value().Value.VariantType, ua.VariantType.String) self.assertTrue(node_type.get_child("2:MyEnumVar") in variables) self.assertEqual(node_type.get_child("2:MyEnumVar").get_data_value().Value.VariantType, ua.VariantType.Int32) self.assertEqual(node_type.get_child("2:MyEnumVar").get_data_type(), ua.NodeId(ua.ObjectIds.ApplicationType)) methods = node_type.get_methods() self.assertTrue(node_type.get_child("2:MyMethod") in methods) #def test_create_custom_refrence_type_ObjectId(self): #type = self.opc.create_custom_reference_type(2, 'MyEvent', ua.ObjectIds.Base, [('PropertyNum', ua.VariantType.Int32), ('PropertyString', ua.VariantType.String)]) #check_custom_type(self, type, ua.ObjectIds.BaseObjectType) def test_create_custom_variable_type_ObjectId(self): type = self.opc.create_custom_variable_type(2, 'MyVariableType', ua.ObjectIds.BaseVariableType, [('PropertyNum', ua.VariantType.Int32), ('PropertyString', ua.VariantType.String)]) check_custom_type(self, type, ua.ObjectIds.BaseVariableType) def test_create_custom_event_type_NodeId(self): etype = self.opc.create_custom_event_type(2, 'MyEvent', ua.NodeId(ua.ObjectIds.BaseEventType), [('PropertyNum', ua.VariantType.Int32), ('PropertyString', ua.VariantType.String)]) check_custom_type(self, etype, ua.ObjectIds.BaseEventType) def test_create_custom_event_type_Node(self): etype = self.opc.create_custom_event_type(2, 'MyEvent', opcua.Node(self.opc.iserver.isession, ua.NodeId(ua.ObjectIds.BaseEventType)), [('PropertyNum', ua.VariantType.Int32), ('PropertyString', ua.VariantType.String)]) check_custom_type(self, etype, ua.ObjectIds.BaseEventType) def test_get_event_from_type_node_CustomEvent(self): etype = self.opc.create_custom_event_type(2, 'MyEvent', ua.ObjectIds.BaseEventType, [('PropertyNum', ua.VariantType.Int32), ('PropertyString', ua.VariantType.String)]) ev = opcua.common.events.get_event_obj_from_type_node(etype) check_custom_event(self, ev, etype) self.assertEqual(ev.PropertyNum, None) self.assertEqual(ev.PropertyString, None) def test_eventgenerator_customEvent(self): etype = self.opc.create_custom_event_type(2, 'MyEvent', ua.ObjectIds.BaseEventType, [('PropertyNum', ua.VariantType.Int32), ('PropertyString', ua.VariantType.String)]) evgen = self.opc.get_event_generator(etype, ua.ObjectIds.Server) check_eventgenerator_CustomEvent(self, evgen, etype) check_eventgenerator_SourceServer(self, evgen) self.assertEqual(evgen.event.PropertyNum, None) self.assertEqual(evgen.event.PropertyString, None) def test_eventgenerator_double_customEvent(self): event1 = self.opc.create_custom_event_type(3, 'MyEvent1', ua.ObjectIds.BaseEventType, [('PropertyNum', ua.VariantType.Int32), ('PropertyString', ua.VariantType.String)]) event2 = self.opc.create_custom_event_type(4, 'MyEvent2', event1, [('PropertyBool', ua.VariantType.Boolean), ('PropertyInt', ua.VariantType.Int32)]) evgen = self.opc.get_event_generator(event2, ua.ObjectIds.Server) check_eventgenerator_CustomEvent(self, evgen, event2) check_eventgenerator_SourceServer(self, evgen) # Properties from MyEvent1 self.assertEqual(evgen.event.PropertyNum, None) self.assertEqual(evgen.event.PropertyString, None) # Properties from MyEvent2 self.assertEqual(evgen.event.PropertyBool, None) self.assertEqual(evgen.event.PropertyInt, None) def test_eventgenerator_customEvent_MyObject(self): objects = self.opc.get_objects_node() o = objects.add_object(3, 'MyObject') etype = self.opc.create_custom_event_type(2, 'MyEvent', ua.ObjectIds.BaseEventType, [('PropertyNum', ua.VariantType.Int32), ('PropertyString', ua.VariantType.String)]) evgen = self.opc.get_event_generator(etype, o) check_eventgenerator_CustomEvent(self, evgen, etype) check_event_generator_object(self, evgen, o) self.assertEqual(evgen.event.PropertyNum, None) self.assertEqual(evgen.event.PropertyString, None) def test_context_manager(self): """ Context manager calls start() and stop() """ state = [0] 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 with server: # test if server started self.assertEqual(state[0], 1) # test if server stopped self.assertEqual(state[0], 2)
# 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 custom stuff objects = server.get_objects_node() # Example 1 - create a basic object #------------------------------------------------------------------------------- myobj = objects.add_object(idx, "MyObject") #------------------------------------------------------------------------------- # Example 2 - create a new object type and a instance of the new object type #------------------------------------------------------------------------------- types = server.get_node(ua.ObjectIds.BaseObjectType) object_type_to_derive_from = server.get_root_node().get_child( ["0:Types", "0:ObjectTypes", "0:BaseObjectType"]) mycustomobj_type = types.add_object_type(idx, "MyCustomObject") mycustomobj_type.add_variable(0, "var_should_be_there_after_instantiate", 1.0) # demonstrates instantiate myobj = objects.add_object(idx, "MyCustomObjectA", mycustomobj_type.nodeid) #------------------------------------------------------------------------------- # Example 3 - import a new object from xml address space and create a instance of the new object type #------------------------------------------------------------------------------- # Import customobject type server.import_xml('customobject.xml')
# 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 custom stuff objects = server.get_objects_node() # Example 1 - create a basic object #------------------------------------------------------------------------------- myobj = objects.add_object(idx, "MyObject") #------------------------------------------------------------------------------- # Example 2 - create a new object type and a instance of the new object type #------------------------------------------------------------------------------- types = server.get_node(ua.ObjectIds.BaseObjectType) object_type_to_derive_from = server.get_root_node().get_child(["0:Types", "0:ObjectTypes", "0:BaseObjectType"]) mycustomobj_type = types.add_object_type(idx, "MyCustomObjectType") var = mycustomobj_type.add_variable(0, "var_should_be_there_after_instantiate", 1.0) # demonstrates instantiate var.set_modelling_rule(True) #if false it would not be instantiated myobj = objects.add_object(idx, "MyCustomObjectA", mycustomobj_type.nodeid) #------------------------------------------------------------------------------- # Example 3 - import a new object from xml address space and create a instance of the new object type #------------------------------------------------------------------------------- # Import customobject type server.import_xml('customobject.xml')
Temp = Param.add_variable(addspace, "Temperature", 0) Press = Param.add_variable(addspace, "Pressure", 0) Time = Param.add_variable(addspace, "Time", 0) OnOff = Param.add_variable(addspace, "OnOff", 0) Temp.set_writable() Press.set_writable() Time.set_writable() OnOff.set_writable() server.start() print("Server started at {}".format(url)) # Read OnOff node var = server.get_node("ns=2;i=5") while True: Temperature = randint(10, 50) Pressure = randint(200, 999) TIME = datetime.datetime.now() # print(Temp.get_value(),Press.get_value(),Time.get_value(), var.get_value()) Temp.set_value(Temperature) Press.set_value(Pressure) Time.set_value(TIME) # print(Temp.get_value(),Press.get_value(),Time.get_value(), var.get_value()) time.sleep(0.1)
server.set_server_name("Proyecto Industria 4.0") # load server certificate and private key. This enables endpoints # with signing and encryption. # server.load_certificate("certificate-example.der") # server.load_private_key("private-key-example.pem") ns = server.get_namespace_array() uax = str(ns.index("http://opcfoundation.org/UA/")) dix = str(ns.index("http://opcfoundation.org/UA/DI/")) fdix = str(ns.index("http://fdi-cooperation.com/OPCUA/FDI5/")) i4ox = str(ns.index("http://juandavid.univalle/i4o/")) m1x = str(ns.index("http://juandavid.univalle/i4o/Mixer1/")) m2x = str(ns.index("http://juandavid.univalle/i4o/Mixer2/")) server.link_method( server.get_node("ns=" + i4ox + ";s=D.ST.O.AS.InvokeAction"), Methods.execute) server.link_method( server.get_node("ns=" + m1x + ";s=D.Mx1.O.AS.InvokeAction"), Methods.execute) server.link_method( server.get_node("ns=" + m2x + ";s=D.Mx2.O.AS.InvokeAction"), Methods.execute) Modules.ns_printer(ns) # Server conf for using sqlite for history # server.iserver.history_manager.set_storage(HistorySQLite("my_datavalue_history.sql")) # starting! server.start()
# populating our address space myobj = objects.add_object(idx, "MyObject") # Creating a custom event: Approach 1 # The custom event object automatically will have members from its parent (BaseEventType) etype = server.create_custom_event_type( 2, 'MyFirstEvent', ua.ObjectIds.BaseEventType, [('MyNumericProperty', ua.VariantType.Float), ('MyStringProperty', ua.VariantType.String)]) myevgen = server.get_event_generator(etype, myobj) myevgen.event.Severity = 500 # Creating a custom event: Approach 2 base_etype = server.get_node(ua.ObjectIds.BaseEventType) custom_etype = base_etype.add_subtype(2, 'MySecondEvent') custom_etype.add_property(2, 'MyIntProperty', ua.Variant(None, ua.VariantType.Int32)) custom_etype.add_property(2, 'MyBoolProperty', ua.Variant(None, ua.VariantType.Boolean)) mysecondevgen = server.get_event_generator(custom_etype, myobj) # starting! server.start() try: # time.sleep is here just because we want to see events in UaExpert import time count = 0
print(datetime.now(), "bulk datachange") await asyncio.sleep(random.randint(1, 100) / 10) async def status_updater(status_node): while True: status_node.set_value( ua.DataValue( ua.Variant(ua.ServerState.Running, ua.VariantType.Int32))) await asyncio.sleep(10) status_node.set_value( ua.DataValue( ua.Variant(ua.ServerState.Suspended, ua.VariantType.Int32))) await asyncio.sleep(10) loop = asyncio.get_event_loop() asyncio.ensure_future(servicelevel_updater(server.get_node("ns=0;i=2267"))) asyncio.ensure_future(random_updater(random_node)) asyncio.ensure_future(event_gen(myevgen)) asyncio.ensure_future(status_updater(server.get_node("ns=0;i=2259"))) asyncio.ensure_future(vars_updater(var_list)) if __name__ == "__main__": try: server.start() loop.run_forever() except KeyboardInterrupt: loop.close() server.stop()
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) servicelevel_node = server.get_node("ns=0;i=2267") #Service-Level Node servicelevel_value = 255 #0-255 [Byte] servicelevel_dv = ua.DataValue( ua.Variant(servicelevel_value, ua.VariantType.Byte)) servicelevel_node.set_value(servicelevel_dv) parameter_obj = server.nodes.objects.add_object(address_space, "Parameter") token_node = parameter_obj.add_variable( address_space, "token", ua.Variant(0, ua.VariantType.UInt32)) token_node.set_writable() #if clients should be able to write myobj = server.nodes.objects.add_object(address_space, "Methods") multiply_node = myobj.add_method( address_space, "myMethod", myMethod,
# 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 custom stuff objects = server.get_objects_node() # Example 1 - create a basic object #------------------------------------------------------------------------------- myobj = objects.add_object(idx, "MyObject") #------------------------------------------------------------------------------- # Example 2 - create a new object type and a instance of the new object type #------------------------------------------------------------------------------- types = server.get_node(ua.ObjectIds.BaseObjectType) object_type_to_derive_from = server.get_root_node().get_child(["0:Types", "0:ObjectTypes", "0:BaseObjectType"]) mycustomobj_type = types.add_object_type(idx, "MyCustomObjectType") mycustomobj_type.add_variable(0, "var_should_be_there_after_instantiate", 1.0) # demonstrates instantiate myobj = objects.add_object(idx, "MyCustomObjectA", mycustomobj_type.nodeid) #------------------------------------------------------------------------------- # Example 3 - import a new object from xml address space and create a instance of the new object type #------------------------------------------------------------------------------- # Import customobject type server.import_xml('customobject.xml')
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)
serverevgen = server.get_event_generator() serverevgen.event.Severity = 111 # Configure server to use sqlite as history database (default is a simple in memory dict) server.iserver.history_manager.set_storage( HistorySQLite("my_event_history.sql")) # starting! server.start() # enable history for myobj events server.iserver.enable_history_event(myobj, period=None) # enable history for server events server_node = server.get_node(ua.ObjectIds.Server) server.iserver.enable_history_event(server_node, period=None) try: count = 0 while True: time.sleep(1) count += 0.1 myevgen.trigger(message="This is MyFirstEvent " + str(count)) myevgen2.trigger(message="This is MySecondEvent " + str(count)) serverevgen.trigger(message="Server Event Message") finally: # close connection, remove subscriptions, etc server.stop()
myobj = objects.add_object(idx, "MyObject") # Creating a custom event: Approach 1 # The custom event object automatically will have members from its parent (BaseEventType) etype = server.create_custom_event_type( 2, "MyFirstEvent", ua.ObjectIds.BaseEventType, [("MyNumericProperty", ua.VariantType.Float), ("MyStringProperty", ua.VariantType.String)], ) myevgen = server.get_event_generator(etype, myobj) myevgen.event.Severity = 500 # Creating a custom event: Approach 2 base_etype = server.get_node(ua.ObjectIds.BaseEventType) custom_etype = base_etype.add_subtype(2, "MySecondEvent") custom_etype.add_property(2, "MyIntProperty", ua.Variant(None, ua.VariantType.Int32)) custom_etype.add_property(2, "MyBoolProperty", ua.Variant(None, ua.VariantType.Boolean)) mysecondevgen = server.get_event_generator(custom_etype, myobj) # starting! server.start() try: # time.sleep is here just because we want to see events in UaExpert import time for i in range(1, 10): time.sleep(10)
if __name__ == "__main__": # setup our server server = Server() server.set_endpoint("opc.tcp://127.0.0.1:7040/") # 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", 7) myvar.set_writable() # Set MyVariable to be writable by clients # starting! server.start() root = server.get_root_node() try: count = 0 while True: #time.sleep(1) # count += 0.1 #myvar.set_value(count) print(server.get_node(myvar).get_value()) finally: # close connection, remove subcsriptions, etc server.stop()
serverevgen.event.Severity = 111 # Configure server to use sqlite as history database (default is a simple in memory dict) server.iserver.history_manager.set_storage(HistorySQLite(":memory:")) # starting! server.start() # enable history for this particular node, must be called after start since it uses subscription server.iserver.enable_history_data_change(myvar, period=None, count=100) # enable history for myobj events server.iserver.enable_history_event(myobj, period=None) # enable history for server events server_node = server.get_node(ua.ObjectIds.Server) server.iserver.enable_history_event(server_node, period=None) try: count = 0 while True: time.sleep(1) count += 0.1 myvar.set_value(math.sin(count)) myevgen.trigger(message="This is MyFirstEvent with MyNumericProperty and MyStringProperty.") myevgen2.trigger(message="This is MySecondEvent with MyOtherProperty.") serverevgen.trigger(message="Server Event Message") finally: # close connection, remove subscriptions, etc server.stop()
# Import customobject type server.import_xml('customobject.xml') # get Objects node, this is where we should put our custom stuff objects = server.get_objects_node() # get nodeid of custom object type by : # 1) Use node ID # 2) Or Full path # 3) Or As child from parent nodeid_a = ua.NodeId.from_string('ns=1;i=1002') nodeid_b = server.get_root_node().get_child( ["0:Types", "0:ObjectTypes", "0:BaseObjectType", "1:MyObjectType"]).nodeid nodeid_c = server.get_node(ua.ObjectIds.BaseObjectType).get_child( ["1:MyObjectType"]).nodeid myobject_type_nodeid = nodeid_a # populating our address space myobj = objects.add_object( idx, "MyObject", ) myobj = objects.add_object(idx, "MyCustomObject", myobject_type_nodeid) # starting! server.start() try: while True: