ServerManager   A
last analyzed

Complexity

Total Complexity 12

Size/Duplication

Total Lines 50
Duplicated Lines 0 %

Importance

Changes 2
Bugs 1 Features 0
Metric Value
wmc 12
c 2
b 1
f 0
dl 0
loc 50
rs 10

9 Methods

Rating   Name   Duplication   Size   Complexity  
A start_server() 0 3 1
A import_xml() 0 2 1
A get_namespace_array() 0 2 1
A _toggle_use_open62541() 0 7 2
A stop_server() 0 5 2
A export_xml() 0 2 1
A __init__() 0 15 2
A nodes() 0 3 1
A get_node() 0 2 1
1
import time
2
import logging
3
from threading import Thread
4
5
from PyQt5.QtCore import QSettings
6
7
from opcua import ua
8
from opcua import Server
9
from opcua import Client
10
from opcua.common.xmlexporter import XmlExporter
11
12
logger = logging.getLogger(__name__)
13
14
OPEN62541 = True
15
try:
16
    import open62541
17
except ImportError as ex:
18
    logger.info("Could not import open62541 python wrapper: %s ", ex)
19
    OPEN62541 = False
20
21
22
class ServerManager(object):
23
    def __init__(self, action):
24
        self._backend = ServerPython()
25
        self._action = action
26
        self._settings = QSettings()
27
28
        if OPEN62541:
29
            use_open62541 = int(self._settings.value("use_open62541_server", 0))
30
            logger.info("Using open62541: %s", open62541)
31
            self._action.setChecked(use_open62541)
32
            self._action.toggled.connect(self._toggle_use_open62541)
33
            self._toggle_use_open62541(use_open62541)  # init state
34
        else:
35
            logger.info("Open62541 python wrappers not available, disabling action")
36
            self._action.setChecked(False)
37
            self._action.setEnabled(False)
38
39
    def _toggle_use_open62541(self, val):
40
        if val:
41
            logger.info("Set use of open62451 backend")
42
            self._backend = ServerC()
43
        else:
44
            logger.info("Set use of python-opcua backend")
45
            self._backend = ServerPython()
46
47
    @property
48
    def nodes(self):
49
        return self._backend.nodes
50
51
    def get_node(self, node):
52
        return self._backend.get_node(node)
53
54
    def get_namespace_array(self):
55
        return self._backend.get_namespace_array()
56
57
    def start_server(self, endpoint):
58
        self._action.setEnabled(False)
59
        self._backend.start_server(endpoint)
60
61
    def stop_server(self):
62
        self._backend.stop_server()
63
        self._action.setEnabled(True)
64
        if OPEN62541:
65
            self._settings.setValue("use_open62541_server", int(self._action.isChecked()))
66
67
    def import_xml(self, path):
68
        return self._backend.import_xml(path)
69
70
    def export_xml(self, nodes, uris, path):
71
        return self._backend.export_xml(nodes, uris, path)
72
73
74
class ServerPython(object):
75
    def __init__(self):
76
        self._server = None
77
        self.nodes = None
78
        self.get_node = None
79
        self.get_namespace_array = None
80
81
    def start_server(self, endpoint):
82
        logger.info("Starting python-opcua server")
83
        self._server = Server()
84
        self._server.set_endpoint(endpoint)
85
        self._server.set_server_name("OpcUa Modeler Server")
86
        self.nodes = self._server.nodes
87
        self.get_node = self._server.get_node
88
        self.get_namespace_array = self._server.get_namespace_array
89
        # now remove freeopcua namespace, not necessary when modeling and
90
        # ensures correct idx for exported nodesets
91
        ns_node = self._server.get_node(ua.NodeId(ua.ObjectIds.Server_NamespaceArray))
92
        nss = ns_node.get_value()
93
        ns_node.set_value(nss[:1])
94
        self._server.start()
95
96
    def stop_server(self):
97
        if self._server is not None:
98
            self._server.stop()
99
            self._server = None
100
            self.get_node = None
101
            self.get_namespace_array = None
102
103
    def import_xml(self, path):
104
        return self._server.import_xml(path)
105
106
    def export_xml(self, nodes, uris, path):
107
        exp = XmlExporter(self._server)
108
        exp.build_etree(nodes, uris=uris)
109
        exp.write_xml(path)
110
111
112
class UAServer(Thread):
113
    def __init__(self):
114
        Thread.__init__(self)
115
        self.server = open62541.Server()
116
        self.status = None
117
        self.endpoint = None
118
119
    def run(self):
120
        logger.info("Starting open62451 server")
121
        self.status = self.server.run(self.endpoint)
122
        logger.info("open62451 server stopped")
123
124
    def stop(self):
125
        logger.info("trying to stop open62451 server")
126
        self.server.stop()
127
128
129
class ServerC(object):
130
    def __init__(self):
131
        self._server = None
132
        self._client = None
133
        self.nodes = None
134
        self.get_node = None
135
        self.get_namespace_array = None
136
137
    def start_server(self, endpoint):
138
        self._server = UAServer()
139
        self._server.endpoint = 48400  # enpoint not supported yet
140
        #self._server.endpoint = endpoint
141
        self._server.start()
142
        #self._server.set_server_name("OpcUa Modeler Server")
143
        time.sleep(0.2)
144
        self._client = Client(endpoint)
145
        self._client.connect()
146
147
        self.nodes = self._client.nodes
148
        self.get_node = self._client.get_node
149
        self.get_namespace_array = self._client.get_namespace_array
150
        # now remove freeopcua namespace, not necessary when modeling and
151
        # ensures correct idx for exported nodesets
152
        ns_node = self._client.get_node(ua.NodeId(ua.ObjectIds.Server_NamespaceArray))
153
        nss = ns_node.get_value()
154
        #ns_node.set_value(nss[1:])
155
156
    def stop_server(self):
157
        if self._server is not None:
158
            self._client.disconnect()
159
            self._client = None
160
            self._server.stop()
161
            time.sleep(0.2)
162
            self._server = None
163
            self.get_node = None
164
            self.get_namespace_array = None
165
166
    def import_xml(self, path):
167
        return self._client.import_xml(path)
168
169
    def export_xml(self, nodes, uris, path):
170
        exp = XmlExporter(self._client)
171
        exp.build_etree(nodes, uris=uris)
172
        exp.write_xml(path)
173
174