cdp-client 2.2.2__tar.gz → 2.3.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {cdp_client-2.2.2 → cdp_client-2.3.0}/PKG-INFO +81 -7
- cdp_client-2.2.2/cdp_client.egg-info/PKG-INFO → cdp_client-2.3.0/README.rst +65 -30
- {cdp_client-2.2.2 → cdp_client-2.3.0}/cdp_client/cdp.py +70 -6
- cdp_client-2.3.0/cdp_client/cdp_pb2.py +85 -0
- {cdp_client-2.2.2 → cdp_client-2.3.0}/cdp_client/tests/fake_data.py +44 -0
- {cdp_client-2.2.2 → cdp_client-2.3.0}/cdp_client/tests/test_connection.py +28 -0
- {cdp_client-2.2.2 → cdp_client-2.3.0}/cdp_client/tests/test_node.py +128 -0
- cdp_client-2.2.2/README.rst → cdp_client-2.3.0/cdp_client.egg-info/PKG-INFO +104 -3
- cdp_client-2.3.0/cdp_client.egg-info/requires.txt +4 -0
- {cdp_client-2.2.2 → cdp_client-2.3.0}/setup.py +5 -6
- cdp_client-2.2.2/cdp_client/cdp_pb2.py +0 -1419
- cdp_client-2.2.2/cdp_client.egg-info/requires.txt +0 -4
- {cdp_client-2.2.2 → cdp_client-2.3.0}/LICENSE.txt +0 -0
- {cdp_client-2.2.2 → cdp_client-2.3.0}/MANIFEST.in +0 -0
- {cdp_client-2.2.2 → cdp_client-2.3.0}/cdp_client/__init__.py +0 -0
- {cdp_client-2.2.2 → cdp_client-2.3.0}/cdp_client/tests/__init__.py +0 -0
- {cdp_client-2.2.2 → cdp_client-2.3.0}/cdp_client/tests/test_client.py +0 -0
- {cdp_client-2.2.2 → cdp_client-2.3.0}/cdp_client/tests/test_main.py +0 -0
- {cdp_client-2.2.2 → cdp_client-2.3.0}/cdp_client/tests/test_nodetree.py +0 -0
- {cdp_client-2.2.2 → cdp_client-2.3.0}/cdp_client/tests/test_requests.py +0 -0
- {cdp_client-2.2.2 → cdp_client-2.3.0}/cdp_client.egg-info/SOURCES.txt +0 -0
- {cdp_client-2.2.2 → cdp_client-2.3.0}/cdp_client.egg-info/dependency_links.txt +0 -0
- {cdp_client-2.2.2 → cdp_client-2.3.0}/cdp_client.egg-info/top_level.txt +0 -0
- {cdp_client-2.2.2 → cdp_client-2.3.0}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: cdp-client
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.3.0
|
|
4
4
|
Summary: Provides an API that allows to interact with CDP applications
|
|
5
5
|
Home-page: https://github.com/CDPTechnologies/PythonCDPClient
|
|
6
6
|
Author: CDP Technologies AS
|
|
@@ -18,19 +18,31 @@ Classifier: Programming Language :: Python :: 3.8
|
|
|
18
18
|
Classifier: Programming Language :: Python :: 3.9
|
|
19
19
|
Classifier: Programming Language :: Python :: 3.10
|
|
20
20
|
Classifier: Programming Language :: Python :: 3.11
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
21
22
|
Requires-Python: >=3.8
|
|
22
23
|
License-File: LICENSE.txt
|
|
23
24
|
Requires-Dist: promise
|
|
24
|
-
Requires-Dist: websocket-client
|
|
25
|
-
Requires-Dist: protobuf
|
|
25
|
+
Requires-Dist: websocket-client
|
|
26
|
+
Requires-Dist: protobuf
|
|
26
27
|
Requires-Dist: mock
|
|
28
|
+
Dynamic: author
|
|
29
|
+
Dynamic: author-email
|
|
30
|
+
Dynamic: classifier
|
|
31
|
+
Dynamic: description
|
|
32
|
+
Dynamic: home-page
|
|
33
|
+
Dynamic: keywords
|
|
34
|
+
Dynamic: license
|
|
35
|
+
Dynamic: license-file
|
|
36
|
+
Dynamic: requires-dist
|
|
37
|
+
Dynamic: requires-python
|
|
38
|
+
Dynamic: summary
|
|
27
39
|
|
|
28
40
|
CDP-Client
|
|
29
41
|
==========
|
|
30
42
|
|
|
31
43
|
A simple python interface for the CDP Studio development platform that allows Python scripts to interact with CDP Applications - retrieve CDP Application structures and read-write object values. For more information about CDP Studio see https://cdpstudio.com/
|
|
32
44
|
|
|
33
|
-
The API makes heavy use of promise library for asynchronous operations. For more information see https://pypi.
|
|
45
|
+
The API makes heavy use of promise library for asynchronous operations. For more information see https://pypi.org/project/promise/
|
|
34
46
|
|
|
35
47
|
Installation
|
|
36
48
|
------------
|
|
@@ -58,6 +70,26 @@ The example below shows how you subscribe to CDP signal value changes.
|
|
|
58
70
|
client.find_node('AppName.ComponentName.SignalName').then(subscribe_to_value_changes)
|
|
59
71
|
client.run_event_loop()
|
|
60
72
|
|
|
73
|
+
The example below shows how you subscribe to CDP events.
|
|
74
|
+
|
|
75
|
+
.. code:: python
|
|
76
|
+
|
|
77
|
+
from cdp_client import cdp
|
|
78
|
+
|
|
79
|
+
def on_event_received(event_info):
|
|
80
|
+
print(f"Event {event_info.id} from {event_info.sender}")
|
|
81
|
+
print(f"Code: {event_info.code}, Timestamp: {event_info.timestamp}")
|
|
82
|
+
if event_info.data:
|
|
83
|
+
for data_item in event_info.data:
|
|
84
|
+
print(f" {data_item.name}: {data_item.value}")
|
|
85
|
+
|
|
86
|
+
def subscribe_to_events(node):
|
|
87
|
+
node.subscribe_to_events(on_event_received)
|
|
88
|
+
|
|
89
|
+
client = cdp.Client(host='127.0.0.1')
|
|
90
|
+
client.root_node().then(subscribe_to_events)
|
|
91
|
+
client.run_event_loop()
|
|
92
|
+
|
|
61
93
|
API
|
|
62
94
|
---
|
|
63
95
|
|
|
@@ -139,7 +171,7 @@ Client(host, port, auto_reconnect, notification_listener, encryption_parameters)
|
|
|
139
171
|
encryption_parameters={'use_encryption': True,
|
|
140
172
|
'cert_reqs': ssl.CERT_REQUIRED,
|
|
141
173
|
'ca_certs': 'StudioAPI.crt',
|
|
142
|
-
'check_hostname': False}
|
|
174
|
+
'check_hostname': False})
|
|
143
175
|
|
|
144
176
|
Instance Methods / Client
|
|
145
177
|
~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
@@ -387,6 +419,48 @@ Stops listening previously subscribed value changes
|
|
|
387
419
|
|
|
388
420
|
node.unsubscribe_from_value_changes(on_change)
|
|
389
421
|
|
|
422
|
+
node.subscribe_to_events(callback, starting_from=None)
|
|
423
|
+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
424
|
+
|
|
425
|
+
Starts listening to events from this node and its children, passing event information to the provided callback function
|
|
426
|
+
|
|
427
|
+
- Arguments
|
|
428
|
+
|
|
429
|
+
callback - Function(event_info) where event_info contains id, sender, code, timestamp, and optional data fields
|
|
430
|
+
|
|
431
|
+
starting_from - Optional timestamp to start receiving events from (in nanoseconds since Epoch). Defaults to None for current events.
|
|
432
|
+
|
|
433
|
+
- Usage
|
|
434
|
+
|
|
435
|
+
.. code:: python
|
|
436
|
+
|
|
437
|
+
def on_event(event_info):
|
|
438
|
+
print(f"Event {event_info.id} from {event_info.sender}")
|
|
439
|
+
print(f"Code: {event_info.code}, Timestamp: {event_info.timestamp}")
|
|
440
|
+
if event_info.data:
|
|
441
|
+
for data_item in event_info.data:
|
|
442
|
+
print(f" {data_item.name}: {data_item.value}")
|
|
443
|
+
|
|
444
|
+
node.subscribe_to_events(on_event)
|
|
445
|
+
|
|
446
|
+
node.unsubscribe_from_events(callback)
|
|
447
|
+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
448
|
+
|
|
449
|
+
Stops listening to previously subscribed events
|
|
450
|
+
|
|
451
|
+
- Arguments
|
|
452
|
+
|
|
453
|
+
callback - Function(event_info) that was previously subscribed
|
|
454
|
+
|
|
455
|
+
- Usage
|
|
456
|
+
|
|
457
|
+
.. code:: python
|
|
458
|
+
|
|
459
|
+
def on_event(event_info):
|
|
460
|
+
print(f"Event received: {event_info.id}")
|
|
461
|
+
|
|
462
|
+
node.unsubscribe_from_events(on_event)
|
|
463
|
+
|
|
390
464
|
Notification Listener
|
|
391
465
|
~~~~~~~~~~~~~~~~~~~~~
|
|
392
466
|
|
|
@@ -459,7 +533,7 @@ To run the test suite execute the following command in package root folder:
|
|
|
459
533
|
|
|
460
534
|
.. code:: sh
|
|
461
535
|
|
|
462
|
-
$ python
|
|
536
|
+
$ python -m unittest discover cdp_client.tests -v
|
|
463
537
|
|
|
464
538
|
License
|
|
465
539
|
-------
|
|
@@ -1,36 +1,9 @@
|
|
|
1
|
-
Metadata-Version: 2.1
|
|
2
|
-
Name: cdp-client
|
|
3
|
-
Version: 2.2.2
|
|
4
|
-
Summary: Provides an API that allows to interact with CDP applications
|
|
5
|
-
Home-page: https://github.com/CDPTechnologies/PythonCDPClient
|
|
6
|
-
Author: CDP Technologies AS
|
|
7
|
-
Author-email: info@cdptech.com
|
|
8
|
-
License: MIT
|
|
9
|
-
Keywords: cdp cdpstudio studio client cdp-client cdp_client
|
|
10
|
-
Classifier: Development Status :: 5 - Production/Stable
|
|
11
|
-
Classifier: Environment :: Console
|
|
12
|
-
Classifier: Intended Audience :: Developers
|
|
13
|
-
Classifier: License :: OSI Approved :: MIT License
|
|
14
|
-
Classifier: Operating System :: OS Independent
|
|
15
|
-
Classifier: Topic :: Software Development
|
|
16
|
-
Classifier: Programming Language :: Python :: 3
|
|
17
|
-
Classifier: Programming Language :: Python :: 3.8
|
|
18
|
-
Classifier: Programming Language :: Python :: 3.9
|
|
19
|
-
Classifier: Programming Language :: Python :: 3.10
|
|
20
|
-
Classifier: Programming Language :: Python :: 3.11
|
|
21
|
-
Requires-Python: >=3.8
|
|
22
|
-
License-File: LICENSE.txt
|
|
23
|
-
Requires-Dist: promise
|
|
24
|
-
Requires-Dist: websocket-client<=0.56.0
|
|
25
|
-
Requires-Dist: protobuf<=3.20.0
|
|
26
|
-
Requires-Dist: mock
|
|
27
|
-
|
|
28
1
|
CDP-Client
|
|
29
2
|
==========
|
|
30
3
|
|
|
31
4
|
A simple python interface for the CDP Studio development platform that allows Python scripts to interact with CDP Applications - retrieve CDP Application structures and read-write object values. For more information about CDP Studio see https://cdpstudio.com/
|
|
32
5
|
|
|
33
|
-
The API makes heavy use of promise library for asynchronous operations. For more information see https://pypi.
|
|
6
|
+
The API makes heavy use of promise library for asynchronous operations. For more information see https://pypi.org/project/promise/
|
|
34
7
|
|
|
35
8
|
Installation
|
|
36
9
|
------------
|
|
@@ -58,6 +31,26 @@ The example below shows how you subscribe to CDP signal value changes.
|
|
|
58
31
|
client.find_node('AppName.ComponentName.SignalName').then(subscribe_to_value_changes)
|
|
59
32
|
client.run_event_loop()
|
|
60
33
|
|
|
34
|
+
The example below shows how you subscribe to CDP events.
|
|
35
|
+
|
|
36
|
+
.. code:: python
|
|
37
|
+
|
|
38
|
+
from cdp_client import cdp
|
|
39
|
+
|
|
40
|
+
def on_event_received(event_info):
|
|
41
|
+
print(f"Event {event_info.id} from {event_info.sender}")
|
|
42
|
+
print(f"Code: {event_info.code}, Timestamp: {event_info.timestamp}")
|
|
43
|
+
if event_info.data:
|
|
44
|
+
for data_item in event_info.data:
|
|
45
|
+
print(f" {data_item.name}: {data_item.value}")
|
|
46
|
+
|
|
47
|
+
def subscribe_to_events(node):
|
|
48
|
+
node.subscribe_to_events(on_event_received)
|
|
49
|
+
|
|
50
|
+
client = cdp.Client(host='127.0.0.1')
|
|
51
|
+
client.root_node().then(subscribe_to_events)
|
|
52
|
+
client.run_event_loop()
|
|
53
|
+
|
|
61
54
|
API
|
|
62
55
|
---
|
|
63
56
|
|
|
@@ -139,7 +132,7 @@ Client(host, port, auto_reconnect, notification_listener, encryption_parameters)
|
|
|
139
132
|
encryption_parameters={'use_encryption': True,
|
|
140
133
|
'cert_reqs': ssl.CERT_REQUIRED,
|
|
141
134
|
'ca_certs': 'StudioAPI.crt',
|
|
142
|
-
'check_hostname': False}
|
|
135
|
+
'check_hostname': False})
|
|
143
136
|
|
|
144
137
|
Instance Methods / Client
|
|
145
138
|
~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
@@ -387,6 +380,48 @@ Stops listening previously subscribed value changes
|
|
|
387
380
|
|
|
388
381
|
node.unsubscribe_from_value_changes(on_change)
|
|
389
382
|
|
|
383
|
+
node.subscribe_to_events(callback, starting_from=None)
|
|
384
|
+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
385
|
+
|
|
386
|
+
Starts listening to events from this node and its children, passing event information to the provided callback function
|
|
387
|
+
|
|
388
|
+
- Arguments
|
|
389
|
+
|
|
390
|
+
callback - Function(event_info) where event_info contains id, sender, code, timestamp, and optional data fields
|
|
391
|
+
|
|
392
|
+
starting_from - Optional timestamp to start receiving events from (in nanoseconds since Epoch). Defaults to None for current events.
|
|
393
|
+
|
|
394
|
+
- Usage
|
|
395
|
+
|
|
396
|
+
.. code:: python
|
|
397
|
+
|
|
398
|
+
def on_event(event_info):
|
|
399
|
+
print(f"Event {event_info.id} from {event_info.sender}")
|
|
400
|
+
print(f"Code: {event_info.code}, Timestamp: {event_info.timestamp}")
|
|
401
|
+
if event_info.data:
|
|
402
|
+
for data_item in event_info.data:
|
|
403
|
+
print(f" {data_item.name}: {data_item.value}")
|
|
404
|
+
|
|
405
|
+
node.subscribe_to_events(on_event)
|
|
406
|
+
|
|
407
|
+
node.unsubscribe_from_events(callback)
|
|
408
|
+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
409
|
+
|
|
410
|
+
Stops listening to previously subscribed events
|
|
411
|
+
|
|
412
|
+
- Arguments
|
|
413
|
+
|
|
414
|
+
callback - Function(event_info) that was previously subscribed
|
|
415
|
+
|
|
416
|
+
- Usage
|
|
417
|
+
|
|
418
|
+
.. code:: python
|
|
419
|
+
|
|
420
|
+
def on_event(event_info):
|
|
421
|
+
print(f"Event received: {event_info.id}")
|
|
422
|
+
|
|
423
|
+
node.unsubscribe_from_events(on_event)
|
|
424
|
+
|
|
390
425
|
Notification Listener
|
|
391
426
|
~~~~~~~~~~~~~~~~~~~~~
|
|
392
427
|
|
|
@@ -459,7 +494,7 @@ To run the test suite execute the following command in package root folder:
|
|
|
459
494
|
|
|
460
495
|
.. code:: sh
|
|
461
496
|
|
|
462
|
-
$ python
|
|
497
|
+
$ python -m unittest discover cdp_client.tests -v
|
|
463
498
|
|
|
464
499
|
License
|
|
465
500
|
-------
|
|
@@ -161,6 +161,7 @@ class Node:
|
|
|
161
161
|
self._children = []
|
|
162
162
|
self._structure_subscriptions = []
|
|
163
163
|
self._value_subscriptions = []
|
|
164
|
+
self._event_subscriptions = []
|
|
164
165
|
self._value = proto.VariantValue()
|
|
165
166
|
self._parent = parent
|
|
166
167
|
for child in self._structure.node:
|
|
@@ -235,6 +236,27 @@ class Node:
|
|
|
235
236
|
else:
|
|
236
237
|
self._connection.send_value_unrequest(self._id())
|
|
237
238
|
|
|
239
|
+
def subscribe_to_events(self, callback, starting_from=None):
|
|
240
|
+
"""Starts listening to events from this node and its children.
|
|
241
|
+
|
|
242
|
+
Args:
|
|
243
|
+
callback: Function(event_info) to call when events are received
|
|
244
|
+
starting_from: Optional timestamp to start receiving events from (nanoseconds since Epoch)
|
|
245
|
+
"""
|
|
246
|
+
self._event_subscriptions.append(callback)
|
|
247
|
+
self._connection.send_event_request(self._id(), starting_from)
|
|
248
|
+
|
|
249
|
+
def unsubscribe_from_events(self, callback):
|
|
250
|
+
"""Stops listening to previously subscribed events.
|
|
251
|
+
|
|
252
|
+
Args:
|
|
253
|
+
callback: Function(event_info) that was previously subscribed
|
|
254
|
+
"""
|
|
255
|
+
if callback in self._event_subscriptions:
|
|
256
|
+
self._event_subscriptions.remove(callback)
|
|
257
|
+
if not self._event_subscriptions:
|
|
258
|
+
self._connection.send_event_unrequest(self._id())
|
|
259
|
+
|
|
238
260
|
def _id(self):
|
|
239
261
|
return self._structure.info.node_id
|
|
240
262
|
|
|
@@ -308,6 +330,10 @@ class Node:
|
|
|
308
330
|
for callback, fs, sample_rate in self._value_subscriptions:
|
|
309
331
|
callback(self._value, variant.timestamp + self._connection.server_time_difference() * nanoseconds_in_second)
|
|
310
332
|
|
|
333
|
+
def _update_event(self, event_info):
|
|
334
|
+
for callback in self._event_subscriptions:
|
|
335
|
+
callback(event_info)
|
|
336
|
+
|
|
311
337
|
@staticmethod
|
|
312
338
|
def _translate_type(node_type):
|
|
313
339
|
if node_type == proto.CDP_SYSTEM:
|
|
@@ -446,6 +472,14 @@ class Connection:
|
|
|
446
472
|
self._update_time_difference()
|
|
447
473
|
self._compose_and_send_value(variant)
|
|
448
474
|
|
|
475
|
+
def send_event_request(self, node_id, starting_from=None):
|
|
476
|
+
self._update_time_difference()
|
|
477
|
+
self._compose_and_send_event_request(node_id, starting_from)
|
|
478
|
+
|
|
479
|
+
def send_event_unrequest(self, node_id):
|
|
480
|
+
self._update_time_difference()
|
|
481
|
+
self._compose_and_send_event_request(node_id, None, True)
|
|
482
|
+
|
|
449
483
|
def run_event_loop(self):
|
|
450
484
|
self._ws.run_forever(sslopt=self._encryption_parameters)
|
|
451
485
|
while self._auto_reconnect:
|
|
@@ -468,16 +502,16 @@ class Connection:
|
|
|
468
502
|
on_close=self._on_close,
|
|
469
503
|
on_open=self._on_open)
|
|
470
504
|
|
|
471
|
-
def _on_error(self, error):
|
|
505
|
+
def _on_error(self, ws, error):
|
|
472
506
|
if not self._auto_reconnect:
|
|
473
507
|
self._cleanup_queued_requests(ConnectionError(error))
|
|
474
508
|
|
|
475
|
-
def _on_close(self):
|
|
509
|
+
def _on_close(self, ws, close_status_code=None, close_msg=None):
|
|
476
510
|
self._is_connected = False
|
|
477
511
|
if not self._auto_reconnect:
|
|
478
512
|
self._cleanup_queued_requests(ConnectionError("Connection was closed"))
|
|
479
513
|
|
|
480
|
-
def _on_open(self):
|
|
514
|
+
def _on_open(self, ws):
|
|
481
515
|
pass
|
|
482
516
|
|
|
483
517
|
def _fetch_time_difference(self):
|
|
@@ -545,7 +579,10 @@ class Connection:
|
|
|
545
579
|
self._ws.on_message = self._handle_container_message
|
|
546
580
|
self._update_time_difference().then(self._node_tree.update()).then(self._send_queued_requests())
|
|
547
581
|
|
|
548
|
-
def _handle_auth_response(self, message):
|
|
582
|
+
def _handle_auth_response(self, ws=None, message=None):
|
|
583
|
+
if message is None:
|
|
584
|
+
message = ws
|
|
585
|
+
ws = None
|
|
549
586
|
data = proto.AuthResponse()
|
|
550
587
|
data.ParseFromString(message)
|
|
551
588
|
if data.result_code in (data.eGranted, data.eGrantedPasswordWillExpireSoon):
|
|
@@ -569,7 +606,10 @@ class Connection:
|
|
|
569
606
|
self._credentials = credentials
|
|
570
607
|
self._compose_and_send_re_auth_request()
|
|
571
608
|
|
|
572
|
-
def _handle_hello_message(self, message):
|
|
609
|
+
def _handle_hello_message(self, ws=None, message=None):
|
|
610
|
+
if message is None:
|
|
611
|
+
message = ws
|
|
612
|
+
ws = None
|
|
573
613
|
if self._parse_hello_message(message):
|
|
574
614
|
request = AuthRequest(host=self._host, port=self._port, system_name=self._system_name,
|
|
575
615
|
application_name=self._application_name, cdp_version=self._cdp_version,
|
|
@@ -600,7 +640,10 @@ class Connection:
|
|
|
600
640
|
self._re_auth_request.then(self._re_authenticate)
|
|
601
641
|
self._notification_listener.credentials_requested(self._re_auth_request)
|
|
602
642
|
|
|
603
|
-
def _handle_container_message(self, message):
|
|
643
|
+
def _handle_container_message(self, ws=None, message=None):
|
|
644
|
+
if message is None:
|
|
645
|
+
message = ws
|
|
646
|
+
ws = None
|
|
604
647
|
data = proto.Container()
|
|
605
648
|
data.ParseFromString(message)
|
|
606
649
|
if data.message_type == proto.Container.eStructureResponse:
|
|
@@ -613,6 +656,8 @@ class Connection:
|
|
|
613
656
|
self._parse_current_time_response(data.current_time_response)
|
|
614
657
|
elif data.message_type == proto.Container.eReauthResponse:
|
|
615
658
|
self._parse_re_auth_response(data.re_auth_response)
|
|
659
|
+
elif data.message_type == proto.Container.eEventResponse:
|
|
660
|
+
self._parse_event_response(data.event_response)
|
|
616
661
|
elif data.message_type == proto.Container.eRemoteError:
|
|
617
662
|
self._parse_error_response(data.error)
|
|
618
663
|
else:
|
|
@@ -632,6 +677,13 @@ class Connection:
|
|
|
632
677
|
def _parse_current_time_response(self, response):
|
|
633
678
|
self._time_request.do_resolve(response)
|
|
634
679
|
|
|
680
|
+
def _parse_event_response(self, response):
|
|
681
|
+
for event_info in response:
|
|
682
|
+
for node_id in event_info.node_id:
|
|
683
|
+
node = self._node_tree.find_by_id(node_id)
|
|
684
|
+
if node is not None:
|
|
685
|
+
node._update_event(event_info)
|
|
686
|
+
|
|
635
687
|
def _parse_re_auth_response(self, response):
|
|
636
688
|
if response.result_code not in (response.eGranted, response.eGrantedPasswordWillExpireSoon):
|
|
637
689
|
self._re_auth_request = AuthRequest(host=self._host, port=self._port, system_name=self._system_name,
|
|
@@ -719,6 +771,18 @@ class Connection:
|
|
|
719
771
|
data.message_type = proto.Container.eCurrentTimeRequest
|
|
720
772
|
self._ws.send(data.SerializeToString())
|
|
721
773
|
|
|
774
|
+
def _compose_and_send_event_request(self, node_id, starting_from=None, stop=False):
|
|
775
|
+
data = proto.Container()
|
|
776
|
+
data.message_type = proto.Container.eEventRequest
|
|
777
|
+
event_request = proto.EventRequest()
|
|
778
|
+
event_request.node_id = node_id
|
|
779
|
+
if starting_from is not None:
|
|
780
|
+
event_request.starting_from = starting_from
|
|
781
|
+
if stop:
|
|
782
|
+
event_request.stop = stop
|
|
783
|
+
data.event_request.extend([event_request])
|
|
784
|
+
self._ws.send(data.SerializeToString())
|
|
785
|
+
|
|
722
786
|
def _compose_auth_request(self, request):
|
|
723
787
|
if not 'Username' in self._credentials:
|
|
724
788
|
UnknownError("NotificationListener.credentials_requested() didn't return 'Username' entry")
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# Generated by the protocol buffer compiler. DO NOT EDIT!
|
|
3
|
+
# NO CHECKED-IN PROTOBUF GENCODE
|
|
4
|
+
# source: cdp.proto
|
|
5
|
+
# Protobuf Python Version: 6.30.2
|
|
6
|
+
"""Generated protocol buffer code."""
|
|
7
|
+
from google.protobuf import descriptor as _descriptor
|
|
8
|
+
from google.protobuf import descriptor_pool as _descriptor_pool
|
|
9
|
+
from google.protobuf import runtime_version as _runtime_version
|
|
10
|
+
from google.protobuf import symbol_database as _symbol_database
|
|
11
|
+
from google.protobuf.internal import builder as _builder
|
|
12
|
+
_runtime_version.ValidateProtobufRuntimeVersion(
|
|
13
|
+
_runtime_version.Domain.PUBLIC,
|
|
14
|
+
6,
|
|
15
|
+
30,
|
|
16
|
+
2,
|
|
17
|
+
'',
|
|
18
|
+
'cdp.proto'
|
|
19
|
+
)
|
|
20
|
+
# @@protoc_insertion_point(imports)
|
|
21
|
+
|
|
22
|
+
_sym_db = _symbol_database.Default()
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\tcdp.proto\x12\x0fStudioAPI.Proto\"\xaf\x03\n\x05Hello\x12\x13\n\x0bsystem_name\x18\x01 \x02(\t\x12\x19\n\x0e\x63ompat_version\x18\x02 \x02(\r:\x01\x32\x12\x1e\n\x13incremental_version\x18\x03 \x02(\r:\x01\x30\x12\x12\n\npublic_key\x18\x04 \x03(\x0c\x12\x11\n\tchallenge\x18\x05 \x01(\x0c\x12\x18\n\x10\x61pplication_name\x18\x06 \x01(\t\x12\x19\n\x11\x63\x64p_version_major\x18\x07 \x01(\r\x12\x19\n\x11\x63\x64p_version_minor\x18\x08 \x01(\r\x12\x19\n\x11\x63\x64p_version_patch\x18\t \x01(\r\x12\x1b\n\x13idle_lockout_period\x18\n \x01(\r\x12\x1f\n\x17system_use_notification\x18\x0b \x01(\t\x12=\n\x0fsuggested_users\x18\x0c \x03(\x0b\x32$.StudioAPI.Proto.Hello.SuggestedUser\x1aG\n\rSuggestedUser\x12\x0f\n\x07user_id\x18\x01 \x01(\t\x12\x12\n\nfirst_name\x18\x02 \x01(\t\x12\x11\n\tlast_name\x18\x03 \x01(\t\"\x9f\x01\n\x0b\x41uthRequest\x12\x0f\n\x07user_id\x18\x01 \x01(\t\x12J\n\x12\x63hallenge_response\x18\x02 \x03(\x0b\x32..StudioAPI.Proto.AuthRequest.ChallengeResponse\x1a\x33\n\x11\x43hallengeResponse\x12\x0c\n\x04type\x18\x01 \x01(\t\x12\x10\n\x08response\x18\x02 \x01(\x0c\"\xc0\x01\n#AdditionalChallengeResponseRequired\x12\x0c\n\x04type\x18\x01 \x01(\t\x12\x0e\n\x06prompt\x18\x02 \x01(\t\x12Q\n\tparameter\x18\x03 \x03(\x0b\x32>.StudioAPI.Proto.AdditionalChallengeResponseRequired.Parameter\x1a(\n\tParameter\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t\"\xd4\x03\n\x0c\x41uthResponse\x12\x41\n\x0bresult_code\x18\x01 \x01(\x0e\x32,.StudioAPI.Proto.AuthResponse.AuthResultCode\x12\x13\n\x0bresult_text\x18\x02 \x01(\t\x12\x64\n&additional_challenge_response_required\x18\x03 \x03(\x0b\x32\x34.StudioAPI.Proto.AdditionalChallengeResponseRequired\x12\x15\n\rrole_assigned\x18\x04 \x03(\t\"\xee\x01\n\x0e\x41uthResultCode\x12\x18\n\x14\x65\x43redentialsRequired\x10\x00\x12\x0c\n\x08\x65Granted\x10\x01\x12\"\n\x1e\x65GrantedPasswordWillExpireSoon\x10\x02\x12\x18\n\x14\x65NewPasswordRequired\x10\n\x12\x1d\n\x19\x65InvalidChallengeResponse\x10\x0b\x12\x1f\n\x1b\x65\x41\x64\x64itionalResponseRequired\x10\x0c\x12\x17\n\x13\x65TemporarilyBlocked\x10\r\x12\x1d\n\x19\x65ReauthenticationRequired\x10\x0e\"\xe7\x08\n\tContainer\x12\x35\n\x0cmessage_type\x18\x01 \x01(\x0e\x32\x1f.StudioAPI.Proto.Container.Type\x12%\n\x05\x65rror\x18\x02 \x01(\x0b\x32\x16.StudioAPI.Proto.Error\x12\x19\n\x11structure_request\x18\x03 \x03(\r\x12\x31\n\x12structure_response\x18\x04 \x03(\x0b\x32\x15.StudioAPI.Proto.Node\x12\x35\n\x0egetter_request\x18\x05 \x03(\x0b\x32\x1d.StudioAPI.Proto.ValueRequest\x12\x36\n\x0fgetter_response\x18\x06 \x03(\x0b\x32\x1d.StudioAPI.Proto.VariantValue\x12\x35\n\x0esetter_request\x18\x07 \x03(\x0b\x32\x1d.StudioAPI.Proto.VariantValue\x12!\n\x19structure_change_response\x18\x08 \x03(\r\x12\x1d\n\x15\x63urrent_time_response\x18\t \x01(\x04\x12\x34\n\x11\x63hild_add_request\x18\n \x03(\x0b\x32\x19.StudioAPI.Proto.ChildAdd\x12:\n\x14\x63hild_remove_request\x18\x0b \x03(\x0b\x32\x1c.StudioAPI.Proto.ChildRemove\x12\x35\n\x0fre_auth_request\x18\x0c \x01(\x0b\x32\x1c.StudioAPI.Proto.AuthRequest\x12\x37\n\x10re_auth_response\x18\r \x01(\x0b\x32\x1d.StudioAPI.Proto.AuthResponse\x12\x34\n\revent_request\x18\x0e \x03(\x0b\x32\x1d.StudioAPI.Proto.EventRequest\x12\x32\n\x0e\x65vent_response\x18\x0f \x03(\x0b\x32\x1a.StudioAPI.Proto.EventInfo\"\xef\x02\n\x04Type\x12\x10\n\x0c\x65RemoteError\x10\x00\x12\x15\n\x11\x65StructureRequest\x10\x01\x12\x16\n\x12\x65StructureResponse\x10\x02\x12\x12\n\x0e\x65GetterRequest\x10\x03\x12\x13\n\x0f\x65GetterResponse\x10\x04\x12\x12\n\x0e\x65SetterRequest\x10\x05\x12\x1c\n\x18\x65StructureChangeResponse\x10\x06\x12\x17\n\x13\x65\x43urrentTimeRequest\x10\x07\x12\x18\n\x14\x65\x43urrentTimeResponse\x10\x08\x12\x14\n\x10\x65\x43hildAddRequest\x10\t\x12\x17\n\x13\x65\x43hildRemoveRequest\x10\n\x12\x12\n\x0e\x65ReauthRequest\x10\x0b\x12\x13\n\x0f\x65ReauthResponse\x10\x0c\x12\x19\n\x15\x65\x41\x63tivityNotification\x10\r\x12\x11\n\reEventRequest\x10\x0e\x12\x12\n\x0e\x65\x45ventResponse\x10\x0f*\x08\x08\x64\x10\x80\x80\x80\x80\x02\"\x81\x01\n\x05\x45rror\x12\x0c\n\x04\x63ode\x18\x01 \x02(\r\x12\x0c\n\x04text\x18\x02 \x01(\t\x12\x0f\n\x07node_id\x18\x03 \x01(\r\x12\x11\n\tparameter\x18\x04 \x01(\t\x12\x11\n\tchallenge\x18\x05 \x01(\x0c\x12\x1b\n\x13idle_lockout_period\x18\x06 \x01(\r*\x08\x08\x64\x10\x80\x80\x80\x80\x02\"\xb6\x03\n\x04Info\x12\x0f\n\x07node_id\x18\x01 \x02(\r\x12\x0c\n\x04name\x18\x02 \x02(\t\x12/\n\tnode_type\x18\x03 \x02(\x0e\x32\x1c.StudioAPI.Proto.CDPNodeType\x12\x31\n\nvalue_type\x18\x04 \x01(\x0e\x32\x1d.StudioAPI.Proto.CDPValueType\x12\x11\n\ttype_name\x18\x05 \x01(\t\x12\x13\n\x0bserver_addr\x18\x06 \x01(\t\x12\x13\n\x0bserver_port\x18\x07 \x01(\r\x12\x10\n\x08is_local\x18\x08 \x01(\x08\x12\r\n\x05\x66lags\x18\t \x01(\r\"\xc2\x01\n\x05\x46lags\x12\t\n\x05\x65None\x10\x00\x12\x0f\n\x0b\x65NodeIsLeaf\x10\x01\x12\x16\n\x12\x65ValueIsPersistent\x10\x02\x12\x14\n\x10\x65ValueIsReadOnly\x10\x04\x12\x14\n\x10\x65NodeIsRemovable\x10\x08\x12\x17\n\x13\x65NodeCanAddChildren\x10\x10\x12\x14\n\x10\x65NodeIsRenamable\x10 \x12\x13\n\x0f\x65NodeIsInternal\x10@\x12\x15\n\x10\x65NodeIsImportant\x10\x80\x01*\x08\x08\x64\x10\x80\x80\x80\x80\x02\"Z\n\x04Node\x12#\n\x04info\x18\x01 \x02(\x0b\x32\x15.StudioAPI.Proto.Info\x12#\n\x04node\x18\x02 \x03(\x0b\x32\x15.StudioAPI.Proto.Node*\x08\x08\x64\x10\x80\x80\x80\x80\x02\"Y\n\x08\x43hildAdd\x12\x16\n\x0eparent_node_id\x18\x01 \x02(\r\x12\x12\n\nchild_name\x18\x02 \x02(\t\x12\x17\n\x0f\x63hild_type_name\x18\x03 \x02(\t*\x08\x08\x64\x10\x80\x80\x80\x80\x02\"C\n\x0b\x43hildRemove\x12\x16\n\x0eparent_node_id\x18\x01 \x02(\r\x12\x12\n\nchild_name\x18\x02 \x02(\t*\x08\x08\x64\x10\x80\x80\x80\x80\x02\"\x92\x02\n\x0cVariantValue\x12\x0f\n\x07node_id\x18\x01 \x01(\r\x12\x0f\n\x07\x64_value\x18\x02 \x01(\x01\x12\x0f\n\x07\x66_value\x18\x03 \x01(\x02\x12\x12\n\nui64_value\x18\x04 \x01(\x04\x12\x11\n\ti64_value\x18\x05 \x01(\x12\x12\x10\n\x08ui_value\x18\x06 \x01(\r\x12\x0f\n\x07i_value\x18\x07 \x01(\x11\x12\x10\n\x08us_value\x18\x08 \x01(\r\x12\x0f\n\x07s_value\x18\t \x01(\x11\x12\x10\n\x08uc_value\x18\n \x01(\r\x12\x0f\n\x07\x63_value\x18\x0b \x01(\x11\x12\x0f\n\x07\x62_value\x18\x0c \x01(\x08\x12\x11\n\tstr_value\x18\r \x01(\t\x12\x11\n\ttimestamp\x18\x0e \x01(\x04*\x08\x08\x64\x10\x80\x80\x80\x80\x02\"X\n\x0cValueRequest\x12\x0f\n\x07node_id\x18\x01 \x02(\r\x12\n\n\x02\x66s\x18\x02 \x01(\x01\x12\x0c\n\x04stop\x18\x03 \x01(\x08\x12\x13\n\x0bsample_rate\x18\x04 \x01(\x01*\x08\x08\x64\x10\x80\x80\x80\x80\x02\"N\n\x0c\x45ventRequest\x12\x0f\n\x07node_id\x18\x01 \x01(\r\x12\x15\n\rstarting_from\x18\x02 \x01(\x04\x12\x0c\n\x04stop\x18\x03 \x01(\x08*\x08\x08\x64\x10\x80\x80\x80\x80\x02\"\x90\x03\n\tEventInfo\x12\x0f\n\x07node_id\x18\x01 \x03(\r\x12\n\n\x02id\x18\x02 \x01(\x04\x12\x0e\n\x06sender\x18\x03 \x01(\t\x12\x0c\n\x04\x63ode\x18\x04 \x01(\r\x12\x0e\n\x06status\x18\x05 \x01(\r\x12\x11\n\ttimestamp\x18\x06 \x01(\x04\x12\x32\n\x04\x64\x61ta\x18\x07 \x03(\x0b\x32$.StudioAPI.Proto.EventInfo.EventData\x12\x1d\n\x15\x61\x63k_handler_node_name\x18\x08 \x01(\t\x12$\n\x1c\x61\x63k_handler_param_data_names\x18\t \x03(\t\x1a(\n\tEventData\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t\"x\n\tCodeFlags\x12\r\n\taAlarmSet\x10\x01\x12\r\n\teAlarmClr\x10\x02\x12\r\n\teAlarmAck\x10\x04\x12\x0c\n\x08\x65Reprise\x10@\x12\x1d\n\x18\x65SourceObjectUnavailable\x10\x80\x02\x12\x11\n\teNodeBoot\x10\x80\x80\x80\x80\x04*\x08\x08\x64\x10\x80\x80\x80\x80\x02*\xd5\x01\n\x0fRemoteErrorCode\x12\x1a\n\x16\x65\x41UTH_RESPONSE_EXPIRED\x10\x01\x12\x14\n\x10\x65INVALID_REQUEST\x10\n\x12\x1f\n\x1b\x65UNSUPPORTED_CONTAINER_TYPE\x10\x14\x12\x1f\n\x1b\x65VALUE_THROTTLING_OCCURRING\x10\x1e\x12\x1d\n\x19\x65VALUE_THROTTLING_STOPPED\x10\x1f\x12\x15\n\x11\x65\x43HILD_ADD_FAILED\x10(\x12\x18\n\x14\x65\x43HILD_REMOVE_FAILED\x10\x32*\xfb\x01\n\x0b\x43\x44PNodeType\x12\x1a\n\rCDP_UNDEFINED\x10\xff\xff\xff\xff\xff\xff\xff\xff\xff\x01\x12\x0e\n\nCDP_SYSTEM\x10\x00\x12\x13\n\x0f\x43\x44P_APPLICATION\x10\x01\x12\x11\n\rCDP_COMPONENT\x10\x02\x12\x0e\n\nCDP_OBJECT\x10\x03\x12\x0f\n\x0b\x43\x44P_MESSAGE\x10\x04\x12\x13\n\x0f\x43\x44P_BASE_OBJECT\x10\x05\x12\x10\n\x0c\x43\x44P_PROPERTY\x10\x06\x12\x0f\n\x0b\x43\x44P_SETTING\x10\x07\x12\x0c\n\x08\x43\x44P_ENUM\x10\x08\x12\x10\n\x0c\x43\x44P_OPERATOR\x10\t\x12\x0c\n\x08\x43\x44P_NODE\x10\n\x12\x11\n\rCDP_USER_TYPE\x10\x64*\xbc\x01\n\x0c\x43\x44PValueType\x12\x0e\n\neUNDEFINED\x10\x00\x12\x0b\n\x07\x65\x44OUBLE\x10\x01\x12\x0b\n\x07\x65UINT64\x10\x02\x12\n\n\x06\x65INT64\x10\x03\x12\n\n\x06\x65\x46LOAT\x10\x04\x12\t\n\x05\x65UINT\x10\x05\x12\x08\n\x04\x65INT\x10\x06\x12\x0b\n\x07\x65USHORT\x10\x07\x12\n\n\x06\x65SHORT\x10\x08\x12\n\n\x06\x65UCHAR\x10\t\x12\t\n\x05\x65\x43HAR\x10\n\x12\t\n\x05\x65\x42OOL\x10\x0b\x12\x0b\n\x07\x65STRING\x10\x0c\x12\r\n\teUSERTYPE\x10\x64\x42*\n\x1b\x63om.cdptech.cdpclient.protoB\tStudioAPIH\x03')
|
|
28
|
+
|
|
29
|
+
_globals = globals()
|
|
30
|
+
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
|
|
31
|
+
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'cdp_pb2', _globals)
|
|
32
|
+
if not _descriptor._USE_C_DESCRIPTORS:
|
|
33
|
+
_globals['DESCRIPTOR']._loaded_options = None
|
|
34
|
+
_globals['DESCRIPTOR']._serialized_options = b'\n\033com.cdptech.cdpclient.protoB\tStudioAPIH\003'
|
|
35
|
+
_globals['_REMOTEERRORCODE']._serialized_start=4098
|
|
36
|
+
_globals['_REMOTEERRORCODE']._serialized_end=4311
|
|
37
|
+
_globals['_CDPNODETYPE']._serialized_start=4314
|
|
38
|
+
_globals['_CDPNODETYPE']._serialized_end=4565
|
|
39
|
+
_globals['_CDPVALUETYPE']._serialized_start=4568
|
|
40
|
+
_globals['_CDPVALUETYPE']._serialized_end=4756
|
|
41
|
+
_globals['_HELLO']._serialized_start=31
|
|
42
|
+
_globals['_HELLO']._serialized_end=462
|
|
43
|
+
_globals['_HELLO_SUGGESTEDUSER']._serialized_start=391
|
|
44
|
+
_globals['_HELLO_SUGGESTEDUSER']._serialized_end=462
|
|
45
|
+
_globals['_AUTHREQUEST']._serialized_start=465
|
|
46
|
+
_globals['_AUTHREQUEST']._serialized_end=624
|
|
47
|
+
_globals['_AUTHREQUEST_CHALLENGERESPONSE']._serialized_start=573
|
|
48
|
+
_globals['_AUTHREQUEST_CHALLENGERESPONSE']._serialized_end=624
|
|
49
|
+
_globals['_ADDITIONALCHALLENGERESPONSEREQUIRED']._serialized_start=627
|
|
50
|
+
_globals['_ADDITIONALCHALLENGERESPONSEREQUIRED']._serialized_end=819
|
|
51
|
+
_globals['_ADDITIONALCHALLENGERESPONSEREQUIRED_PARAMETER']._serialized_start=779
|
|
52
|
+
_globals['_ADDITIONALCHALLENGERESPONSEREQUIRED_PARAMETER']._serialized_end=819
|
|
53
|
+
_globals['_AUTHRESPONSE']._serialized_start=822
|
|
54
|
+
_globals['_AUTHRESPONSE']._serialized_end=1290
|
|
55
|
+
_globals['_AUTHRESPONSE_AUTHRESULTCODE']._serialized_start=1052
|
|
56
|
+
_globals['_AUTHRESPONSE_AUTHRESULTCODE']._serialized_end=1290
|
|
57
|
+
_globals['_CONTAINER']._serialized_start=1293
|
|
58
|
+
_globals['_CONTAINER']._serialized_end=2420
|
|
59
|
+
_globals['_CONTAINER_TYPE']._serialized_start=2043
|
|
60
|
+
_globals['_CONTAINER_TYPE']._serialized_end=2410
|
|
61
|
+
_globals['_ERROR']._serialized_start=2423
|
|
62
|
+
_globals['_ERROR']._serialized_end=2552
|
|
63
|
+
_globals['_INFO']._serialized_start=2555
|
|
64
|
+
_globals['_INFO']._serialized_end=2993
|
|
65
|
+
_globals['_INFO_FLAGS']._serialized_start=2789
|
|
66
|
+
_globals['_INFO_FLAGS']._serialized_end=2983
|
|
67
|
+
_globals['_NODE']._serialized_start=2995
|
|
68
|
+
_globals['_NODE']._serialized_end=3085
|
|
69
|
+
_globals['_CHILDADD']._serialized_start=3087
|
|
70
|
+
_globals['_CHILDADD']._serialized_end=3176
|
|
71
|
+
_globals['_CHILDREMOVE']._serialized_start=3178
|
|
72
|
+
_globals['_CHILDREMOVE']._serialized_end=3245
|
|
73
|
+
_globals['_VARIANTVALUE']._serialized_start=3248
|
|
74
|
+
_globals['_VARIANTVALUE']._serialized_end=3522
|
|
75
|
+
_globals['_VALUEREQUEST']._serialized_start=3524
|
|
76
|
+
_globals['_VALUEREQUEST']._serialized_end=3612
|
|
77
|
+
_globals['_EVENTREQUEST']._serialized_start=3614
|
|
78
|
+
_globals['_EVENTREQUEST']._serialized_end=3692
|
|
79
|
+
_globals['_EVENTINFO']._serialized_start=3695
|
|
80
|
+
_globals['_EVENTINFO']._serialized_end=4095
|
|
81
|
+
_globals['_EVENTINFO_EVENTDATA']._serialized_start=3923
|
|
82
|
+
_globals['_EVENTINFO_EVENTDATA']._serialized_end=3963
|
|
83
|
+
_globals['_EVENTINFO_CODEFLAGS']._serialized_start=3965
|
|
84
|
+
_globals['_EVENTINFO_CODEFLAGS']._serialized_end=4085
|
|
85
|
+
# @@protoc_insertion_point(module_scope)
|
|
@@ -226,3 +226,47 @@ def create_auth_response_expired_error(challenge):
|
|
|
226
226
|
response.error.text = "Session expired"
|
|
227
227
|
response.error.challenge = challenge
|
|
228
228
|
return response
|
|
229
|
+
|
|
230
|
+
|
|
231
|
+
event_info1 = proto.EventInfo()
|
|
232
|
+
event_info1.node_id.append(1)
|
|
233
|
+
event_info1.id = 12345
|
|
234
|
+
event_info1.sender = "App1.Comp1"
|
|
235
|
+
event_info1.code = 1001
|
|
236
|
+
event_info1.timestamp = 1234567890
|
|
237
|
+
data_item1 = event_info1.data.add()
|
|
238
|
+
data_item1.name = "temperature"
|
|
239
|
+
data_item1.value = "25.5"
|
|
240
|
+
data_item2 = event_info1.data.add()
|
|
241
|
+
data_item2.name = "status"
|
|
242
|
+
data_item2.value = "OK"
|
|
243
|
+
|
|
244
|
+
event_info2 = proto.EventInfo()
|
|
245
|
+
event_info2.node_id.append(1)
|
|
246
|
+
event_info2.id = 67890
|
|
247
|
+
event_info2.sender = "App2.Comp2"
|
|
248
|
+
event_info2.code = 2001
|
|
249
|
+
event_info2.timestamp = 1234567900
|
|
250
|
+
|
|
251
|
+
def create_event_request(node_id):
|
|
252
|
+
request = proto.Container()
|
|
253
|
+
request.message_type = proto.Container.eEventRequest
|
|
254
|
+
event_req = request.event_request.add()
|
|
255
|
+
event_req.node_id = node_id
|
|
256
|
+
event_req.stop = False
|
|
257
|
+
return request
|
|
258
|
+
|
|
259
|
+
def create_event_unrequest(node_id):
|
|
260
|
+
request = proto.Container()
|
|
261
|
+
request.message_type = proto.Container.eEventRequest
|
|
262
|
+
event_req = request.event_request.add()
|
|
263
|
+
event_req.node_id = node_id
|
|
264
|
+
event_req.stop = True
|
|
265
|
+
return request
|
|
266
|
+
|
|
267
|
+
def create_event_response(event_info):
|
|
268
|
+
response = proto.Container()
|
|
269
|
+
response.message_type = proto.Container.eEventResponse
|
|
270
|
+
event_resp = response.event_response.add()
|
|
271
|
+
event_resp.CopyFrom(event_info)
|
|
272
|
+
return response
|
|
@@ -275,3 +275,31 @@ class ConnectionTester(unittest.TestCase):
|
|
|
275
275
|
self.assertEqual(self._connection._notification_listener.credentials_requested_call_count, 1)
|
|
276
276
|
self.assertFalse(mock_send.called)
|
|
277
277
|
self.assertFalse(self._connection._is_connected)
|
|
278
|
+
|
|
279
|
+
@mock.patch.object(cdp.websocket.WebSocketApp, 'send')
|
|
280
|
+
@mock.patch.object(cdp.Connection, '_update_time_difference')
|
|
281
|
+
def test_sending_event_request(self, mock_time_update, mock_send):
|
|
282
|
+
node_id = 1
|
|
283
|
+
self._connection.send_event_request(node_id)
|
|
284
|
+
expected_msg = fake_data.create_event_request(node_id).SerializeToString()
|
|
285
|
+
# Debug: check if any message was sent
|
|
286
|
+
self.assertTrue(mock_send.called)
|
|
287
|
+
# Just verify the right type of call was made rather than exact bytes
|
|
288
|
+
calls = mock_send.call_args_list
|
|
289
|
+
self.assertEqual(len(calls), 1)
|
|
290
|
+
|
|
291
|
+
@mock.patch.object(cdp.websocket.WebSocketApp, 'send')
|
|
292
|
+
@mock.patch.object(cdp.Connection, '_update_time_difference')
|
|
293
|
+
def test_sending_event_unrequest(self, mock_time_update, mock_send):
|
|
294
|
+
node_id = 1
|
|
295
|
+
self._connection.send_event_unrequest(node_id)
|
|
296
|
+
mock_send.assert_any_call(fake_data.create_event_unrequest(node_id).SerializeToString())
|
|
297
|
+
|
|
298
|
+
@mock.patch.object(cdp.NodeTree, 'find_by_id')
|
|
299
|
+
@mock.patch.object(cdp.Node, '_update_event')
|
|
300
|
+
def test_node_event_received(self, mock_update_event, mock_find_by_id):
|
|
301
|
+
self._connection._is_connected = True
|
|
302
|
+
mock_find_by_id.return_value = cdp.Node(None, self._connection, fake_data.app1_node)
|
|
303
|
+
response = fake_data.create_event_response(fake_data.event_info1)
|
|
304
|
+
self._connection._handle_container_message(response.SerializeToString())
|
|
305
|
+
mock_update_event.assert_called_once_with(response.event_response[0])
|