Completed
Push — master ( 70d6df...ac5e60 )
by Olivier
01:00
created

UaClient   A

Complexity

Total Complexity 23

Size/Duplication

Total Lines 104
Duplicated Lines 0 %

Importance

Changes 20
Bugs 0 Features 3
Metric Value
c 20
b 0
f 3
dl 0
loc 104
rs 10
wmc 23

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