Completed
Push — master ( 7a4bf2...905d1f )
by Olivier
53s
created

UaClient   A

Complexity

Total Complexity 26

Size/Duplication

Total Lines 116
Duplicated Lines 0 %

Importance

Changes 21
Bugs 0 Features 3
Metric Value
c 21
b 0
f 3
dl 0
loc 116
rs 10
wmc 26

13 Methods

Rating   Name   Duplication   Size   Complexity  
A load_security_settings() 0 15 3
A unsubscribe_datachange() 0 2 1
A save_security_settings() 0 9 2
A get_node() 0 2 1
A get_children() 0 5 2
A get_node_attrs() 0 5 3
A unsubscribe_events() 0 2 1
A get_endpoints() 0 10 3
A subscribe_datachange() 0 6 2
A disconnect() 0 8 2
A connect() 0 14 3
A __init__() 0 12 1
A subscribe_events() 0 7 2
1
import logging
2
3
from PyQt5.QtCore import QSettings
4
5
from opcua import ua
6
from opcua import Client
7
from opcua import Node
8
from opcua import crypto
9
from opcua.tools import endpoint_to_strings
10
11
12
logger = logging.getLogger(__name__)
13
14
15
class UaClient(object):
16
    """
17
    OPC-Ua client specialized for the need of GUI client
18
    return exactly what GUI needs, no customization possible
19
    """
20
21
    def __init__(self):
22
        self.settings = QSettings()
23
        self.client = None
24
        self._connected = False
25
        self._datachange_sub = None
26
        self._event_sub = None
27
        self._subs_dc = {}
28
        self._subs_ev = {}
29
        self.security_mode = None
30
        self.security_policy = None
31
        self.certificate_path = None
32
        self.private_key_path = None
33
34
    def get_endpoints(self, uri):
35
        client = Client(uri, timeout=2)
36
        client.connect_and_get_server_endpoints()
37
        edps = client.connect_and_get_server_endpoints()
38
        for i, ep in enumerate(edps, start=1):
39
            logger.info('Endpoint %s:', i)
40
            for (n, v) in endpoint_to_strings(ep):
41
                logger.info('  %s: %s', n, v)
42
            logger.info('')
43
        return 
44
45
46
    def load_security_settings(self, uri):
47
        self.security_mode = None
48
        self.security_policy = None
49
        self.certificate_path = None
50
        self.private_key_path = None
51
52
        mysettings = self.settings.value("security_settings", None)
53
        if mysettings is None:
54
            return
55
        if uri in mysettings:
56
            mode, policy, cert, key = mysettings[uri]
57
            self.security_mode = mode
58
            self.security_policy = policy
59
            self.certificate_path = cert
60
            self.private_key_path = key
61
62
    def save_security_settings(self, uri):
63
        mysettings = self.settings.value("security_settings", None)
64
        if mysettings is None:
65
            mysettings = {}
66
        mysettings[uri] = [self.security_mode,
67
                           self.security_policy,
68
                           self.certificate_path,
69
                           self.private_key_path]
70
        self.settings.setValue("security_settings", mysettings)
71
72
    def get_node(self, nodeid):
73
        return self.client.get_node(nodeid)
74
    
75
    def connect(self, uri):
76
        self.disconnect()
77
        logger.info("Connecting to %s with parameters %s, %s, %s, %s", uri, self.security_mode, self.security_policy, self.certificate_path, self.private_key_path)
78
        self.client = Client(uri)
79
        if self.security_mode is not None and self.security_policy is not None:
80
            self.client.set_security(
81
                getattr(crypto.security_policies, 'SecurityPolicy' + self.security_policy),
82
                self.certificate_path,
83
                self.private_key_path,
84
                mode=getattr(ua.MessageSecurityMode, self.security_mode)
85
            )
86
        self.client.connect()
87
        self._connected = True
88
        self.save_security_settings(uri)
89
90
    def disconnect(self):
91
        if self._connected:
92
            print("Disconnecting from server")
93
            self._subs_dc = {}
94
            self._subs_ev = {}
95
            self._connected = False
96
            self.client.disconnect()
97
            self.client = None
98
99
    def subscribe_datachange(self, node, handler):
100
        if not self._datachange_sub:
101
            self._datachange_sub = self.client.create_subscription(500, handler)
102
        handle = self._datachange_sub.subscribe_data_change(node)
103
        self._subs_dc[node.nodeid] = handle
104
        return handle
105
106
    def unsubscribe_datachange(self, node):
107
        self._datachange_sub.unsubscribe(self._subs_dc[node.nodeid])
108
109
    def subscribe_events(self, node, handler):
110
        if not self._event_sub:
111
            print("subscirbing with handler: ", handler, dir(handler))
112
            self._event_sub = self.client.create_subscription(500, handler)
113
        handle = self._event_sub.subscribe_events(node)
114
        self._subs_ev[node.nodeid] = handle
115
        return handle
116
117
    def unsubscribe_events(self, node):
118
        self._event_sub.unsubscribe(self._subs_ev[node.nodeid])
119
120
    def get_node_attrs(self, node):
121
        if not isinstance(node, Node):
122
            node = self.client.get_node(node)
123
        attrs = node.get_attributes([ua.AttributeIds.DisplayName, ua.AttributeIds.BrowseName, ua.AttributeIds.NodeId])
124
        return node, [attr.Value.Value.to_string() for attr in attrs]
125
126
    @staticmethod
127
    def get_children(node):
128
        descs = node.get_children_descriptions()
129
        descs.sort(key=lambda x: x.BrowseName)
130
        return descs
131
132