libosdp 3.0.8__tar.gz → 3.2.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.
- {libosdp-3.0.8/libosdp.egg-info → libosdp-3.2.0}/PKG-INFO +35 -3
- libosdp-3.0.8/PKG-INFO → libosdp-3.2.0/README.md +25 -14
- libosdp-3.0.8/README.md → libosdp-3.2.0/libosdp.egg-info/PKG-INFO +46 -1
- {libosdp-3.0.8 → libosdp-3.2.0}/libosdp.egg-info/SOURCES.txt +3 -2
- {libosdp-3.0.8 → libosdp-3.2.0}/osdp/__init__.py +2 -2
- {libosdp-3.0.8 → libosdp-3.2.0}/osdp/constants.py +8 -1
- {libosdp-3.0.8 → libosdp-3.2.0}/osdp/control_panel.py +93 -47
- {libosdp-3.0.8 → libosdp-3.2.0}/osdp/helpers.py +1 -1
- {libosdp-3.0.8 → libosdp-3.2.0}/osdp/key_store.py +1 -1
- {libosdp-3.0.8 → libosdp-3.2.0}/osdp/peripheral_device.py +49 -26
- {libosdp-3.0.8 → libosdp-3.2.0}/setup.py +60 -24
- {libosdp-3.0.8 → libosdp-3.2.0}/vendor/include/osdp.h +249 -37
- libosdp-3.2.0/vendor/include/osdp_export.h +76 -0
- {libosdp-3.0.8 → libosdp-3.2.0}/vendor/python/osdp_sys/base.c +31 -18
- {libosdp-3.0.8 → libosdp-3.2.0}/vendor/python/osdp_sys/cp.c +308 -45
- {libosdp-3.0.8 → libosdp-3.2.0}/vendor/python/osdp_sys/data.c +33 -45
- {libosdp-3.0.8 → libosdp-3.2.0}/vendor/python/osdp_sys/module.c +10 -2
- {libosdp-3.0.8 → libosdp-3.2.0}/vendor/python/osdp_sys/module.h +21 -2
- {libosdp-3.0.8 → libosdp-3.2.0}/vendor/python/osdp_sys/pd.c +171 -19
- {libosdp-3.0.8 → libosdp-3.2.0}/vendor/python/osdp_sys/utils.c +152 -7
- {libosdp-3.0.8 → libosdp-3.2.0}/vendor/src/crypto/tinyaes.c +2 -2
- {libosdp-3.0.8 → libosdp-3.2.0}/vendor/src/osdp_common.c +7 -23
- {libosdp-3.0.8 → libosdp-3.2.0}/vendor/src/osdp_common.h +190 -74
- libosdp-3.2.0/vendor/src/osdp_config.h +102 -0
- {libosdp-3.0.8 → libosdp-3.2.0}/vendor/src/osdp_cp.c +536 -247
- {libosdp-3.0.8 → libosdp-3.2.0}/vendor/src/osdp_diag.c +1 -1
- {libosdp-3.0.8 → libosdp-3.2.0}/vendor/src/osdp_diag.h +2 -2
- {libosdp-3.0.8 → libosdp-3.2.0}/vendor/src/osdp_file.c +20 -21
- {libosdp-3.0.8 → libosdp-3.2.0}/vendor/src/osdp_file.h +1 -1
- {libosdp-3.0.8 → libosdp-3.2.0}/vendor/src/osdp_pd.c +329 -147
- {libosdp-3.0.8 → libosdp-3.2.0}/vendor/src/osdp_phy.c +275 -104
- {libosdp-3.0.8 → libosdp-3.2.0}/vendor/src/osdp_sc.c +4 -8
- {libosdp-3.0.8 → libosdp-3.2.0}/vendor/utils/include/utils/assert.h +9 -1
- libosdp-3.2.0/vendor/utils/include/utils/crc16.h +25 -0
- {libosdp-3.0.8 → libosdp-3.2.0}/vendor/utils/include/utils/disjoint_set.h +1 -1
- {libosdp-3.0.8 → libosdp-3.2.0}/vendor/utils/include/utils/list.h +1 -1
- {libosdp-3.0.8 → libosdp-3.2.0}/vendor/utils/include/utils/logger.h +1 -1
- {libosdp-3.0.8 → libosdp-3.2.0}/vendor/utils/include/utils/pcap_gen.h +1 -1
- {libosdp-3.0.8 → libosdp-3.2.0}/vendor/utils/include/utils/queue.h +1 -1
- {libosdp-3.0.8 → libosdp-3.2.0}/vendor/utils/include/utils/slab.h +1 -1
- {libosdp-3.0.8 → libosdp-3.2.0}/vendor/utils/include/utils/utils.h +19 -5
- libosdp-3.2.0/vendor/utils/src/crc16.c +21 -0
- {libosdp-3.0.8 → libosdp-3.2.0}/vendor/utils/src/disjoint_set.c +1 -1
- {libosdp-3.0.8 → libosdp-3.2.0}/vendor/utils/src/list.c +1 -1
- {libosdp-3.0.8 → libosdp-3.2.0}/vendor/utils/src/logger.c +7 -2
- {libosdp-3.0.8 → libosdp-3.2.0}/vendor/utils/src/queue.c +1 -1
- {libosdp-3.0.8 → libosdp-3.2.0}/vendor/utils/src/utils.c +35 -1
- libosdp-3.0.8/vendor/src/osdp_config.h +0 -42
- libosdp-3.0.8/vendor/src/osdp_export.h +0 -1
- libosdp-3.0.8/vendor/utils/src/slab.c +0 -64
- {libosdp-3.0.8 → libosdp-3.2.0}/MANIFEST.in +0 -0
- {libosdp-3.0.8 → libosdp-3.2.0}/libosdp.egg-info/dependency_links.txt +0 -0
- {libosdp-3.0.8 → libosdp-3.2.0}/libosdp.egg-info/top_level.txt +0 -0
- {libosdp-3.0.8 → libosdp-3.2.0}/osdp/channel.py +0 -0
- {libosdp-3.0.8 → libosdp-3.2.0}/pyproject.toml +0 -0
- {libosdp-3.0.8 → libosdp-3.2.0}/setup.cfg +0 -0
- {libosdp-3.0.8 → libosdp-3.2.0}/vendor/src/crypto/tinyaes_src.c +0 -0
- {libosdp-3.0.8 → libosdp-3.2.0}/vendor/src/crypto/tinyaes_src.h +0 -0
- {libosdp-3.0.8 → libosdp-3.2.0}/vendor/utils/src/pcap_gen.c +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: libosdp
|
|
3
|
-
Version: 3.0
|
|
3
|
+
Version: 3.2.0
|
|
4
4
|
Summary: Library implementation of IEC 60839-11-5 OSDP (Open Supervised Device Protocol)
|
|
5
5
|
Home-page: https://github.com/goToMain/libosdp
|
|
6
6
|
Author: Siddharth Chandrasekaran
|
|
@@ -10,6 +10,14 @@ Classifier: License :: OSI Approved :: Apache Software License
|
|
|
10
10
|
Classifier: Operating System :: OS Independent
|
|
11
11
|
Requires-Python: >=3.8
|
|
12
12
|
Description-Content-Type: text/markdown
|
|
13
|
+
Dynamic: author
|
|
14
|
+
Dynamic: author-email
|
|
15
|
+
Dynamic: classifier
|
|
16
|
+
Dynamic: description
|
|
17
|
+
Dynamic: description-content-type
|
|
18
|
+
Dynamic: home-page
|
|
19
|
+
Dynamic: requires-python
|
|
20
|
+
Dynamic: summary
|
|
13
21
|
|
|
14
22
|
# LibOSDP for Python
|
|
15
23
|
|
|
@@ -77,6 +85,18 @@ while True:
|
|
|
77
85
|
|
|
78
86
|
see [examples/cp_app.py][2] for more details.
|
|
79
87
|
|
|
88
|
+
Optional command completion callback:
|
|
89
|
+
|
|
90
|
+
```python
|
|
91
|
+
from osdp import CompletionStatus
|
|
92
|
+
|
|
93
|
+
def on_command_complete(address, command, status):
|
|
94
|
+
if status == CompletionStatus.Ok:
|
|
95
|
+
print("command completed")
|
|
96
|
+
|
|
97
|
+
cp.set_command_completion_handler(on_command_complete)
|
|
98
|
+
```
|
|
99
|
+
|
|
80
100
|
### Peripheral Device mode:
|
|
81
101
|
|
|
82
102
|
```python
|
|
@@ -108,6 +128,18 @@ while True:
|
|
|
108
128
|
|
|
109
129
|
see [examples/pd_app.py][3] for more details.
|
|
110
130
|
|
|
111
|
-
|
|
131
|
+
Optional event completion callback:
|
|
132
|
+
|
|
133
|
+
```python
|
|
134
|
+
from osdp import CompletionStatus
|
|
135
|
+
|
|
136
|
+
def on_event_complete(event, status):
|
|
137
|
+
if status == CompletionStatus.Flushed:
|
|
138
|
+
print("event removed by flush")
|
|
139
|
+
|
|
140
|
+
pd.set_event_completion_handler(on_event_complete)
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
[1]: https://doc.osdp.dev/api/
|
|
112
144
|
[2]: https://github.com/goToMain/libosdp/blob/master/examples/python/cp_app.py
|
|
113
145
|
[3]: https://github.com/goToMain/libosdp/blob/master/examples/python/pd_app.py
|
|
@@ -1,16 +1,3 @@
|
|
|
1
|
-
Metadata-Version: 2.1
|
|
2
|
-
Name: libosdp
|
|
3
|
-
Version: 3.0.8
|
|
4
|
-
Summary: Library implementation of IEC 60839-11-5 OSDP (Open Supervised Device Protocol)
|
|
5
|
-
Home-page: https://github.com/goToMain/libosdp
|
|
6
|
-
Author: Siddharth Chandrasekaran
|
|
7
|
-
Author-email: sidcha.dev@gmail.com
|
|
8
|
-
Classifier: Programming Language :: Python :: 3
|
|
9
|
-
Classifier: License :: OSI Approved :: Apache Software License
|
|
10
|
-
Classifier: Operating System :: OS Independent
|
|
11
|
-
Requires-Python: >=3.8
|
|
12
|
-
Description-Content-Type: text/markdown
|
|
13
|
-
|
|
14
1
|
# LibOSDP for Python
|
|
15
2
|
|
|
16
3
|
This package exposes the C/C++ library for OSDP devices to python to enable rapid
|
|
@@ -77,6 +64,18 @@ while True:
|
|
|
77
64
|
|
|
78
65
|
see [examples/cp_app.py][2] for more details.
|
|
79
66
|
|
|
67
|
+
Optional command completion callback:
|
|
68
|
+
|
|
69
|
+
```python
|
|
70
|
+
from osdp import CompletionStatus
|
|
71
|
+
|
|
72
|
+
def on_command_complete(address, command, status):
|
|
73
|
+
if status == CompletionStatus.Ok:
|
|
74
|
+
print("command completed")
|
|
75
|
+
|
|
76
|
+
cp.set_command_completion_handler(on_command_complete)
|
|
77
|
+
```
|
|
78
|
+
|
|
80
79
|
### Peripheral Device mode:
|
|
81
80
|
|
|
82
81
|
```python
|
|
@@ -108,6 +107,18 @@ while True:
|
|
|
108
107
|
|
|
109
108
|
see [examples/pd_app.py][3] for more details.
|
|
110
109
|
|
|
111
|
-
|
|
110
|
+
Optional event completion callback:
|
|
111
|
+
|
|
112
|
+
```python
|
|
113
|
+
from osdp import CompletionStatus
|
|
114
|
+
|
|
115
|
+
def on_event_complete(event, status):
|
|
116
|
+
if status == CompletionStatus.Flushed:
|
|
117
|
+
print("event removed by flush")
|
|
118
|
+
|
|
119
|
+
pd.set_event_completion_handler(on_event_complete)
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
[1]: https://doc.osdp.dev/api/
|
|
112
123
|
[2]: https://github.com/goToMain/libosdp/blob/master/examples/python/cp_app.py
|
|
113
124
|
[3]: https://github.com/goToMain/libosdp/blob/master/examples/python/pd_app.py
|
|
@@ -1,3 +1,24 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: libosdp
|
|
3
|
+
Version: 3.2.0
|
|
4
|
+
Summary: Library implementation of IEC 60839-11-5 OSDP (Open Supervised Device Protocol)
|
|
5
|
+
Home-page: https://github.com/goToMain/libosdp
|
|
6
|
+
Author: Siddharth Chandrasekaran
|
|
7
|
+
Author-email: sidcha.dev@gmail.com
|
|
8
|
+
Classifier: Programming Language :: Python :: 3
|
|
9
|
+
Classifier: License :: OSI Approved :: Apache Software License
|
|
10
|
+
Classifier: Operating System :: OS Independent
|
|
11
|
+
Requires-Python: >=3.8
|
|
12
|
+
Description-Content-Type: text/markdown
|
|
13
|
+
Dynamic: author
|
|
14
|
+
Dynamic: author-email
|
|
15
|
+
Dynamic: classifier
|
|
16
|
+
Dynamic: description
|
|
17
|
+
Dynamic: description-content-type
|
|
18
|
+
Dynamic: home-page
|
|
19
|
+
Dynamic: requires-python
|
|
20
|
+
Dynamic: summary
|
|
21
|
+
|
|
1
22
|
# LibOSDP for Python
|
|
2
23
|
|
|
3
24
|
This package exposes the C/C++ library for OSDP devices to python to enable rapid
|
|
@@ -64,6 +85,18 @@ while True:
|
|
|
64
85
|
|
|
65
86
|
see [examples/cp_app.py][2] for more details.
|
|
66
87
|
|
|
88
|
+
Optional command completion callback:
|
|
89
|
+
|
|
90
|
+
```python
|
|
91
|
+
from osdp import CompletionStatus
|
|
92
|
+
|
|
93
|
+
def on_command_complete(address, command, status):
|
|
94
|
+
if status == CompletionStatus.Ok:
|
|
95
|
+
print("command completed")
|
|
96
|
+
|
|
97
|
+
cp.set_command_completion_handler(on_command_complete)
|
|
98
|
+
```
|
|
99
|
+
|
|
67
100
|
### Peripheral Device mode:
|
|
68
101
|
|
|
69
102
|
```python
|
|
@@ -95,6 +128,18 @@ while True:
|
|
|
95
128
|
|
|
96
129
|
see [examples/pd_app.py][3] for more details.
|
|
97
130
|
|
|
98
|
-
|
|
131
|
+
Optional event completion callback:
|
|
132
|
+
|
|
133
|
+
```python
|
|
134
|
+
from osdp import CompletionStatus
|
|
135
|
+
|
|
136
|
+
def on_event_complete(event, status):
|
|
137
|
+
if status == CompletionStatus.Flushed:
|
|
138
|
+
print("event removed by flush")
|
|
139
|
+
|
|
140
|
+
pd.set_event_completion_handler(on_event_complete)
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
[1]: https://doc.osdp.dev/api/
|
|
99
144
|
[2]: https://github.com/goToMain/libosdp/blob/master/examples/python/cp_app.py
|
|
100
145
|
[3]: https://github.com/goToMain/libosdp/blob/master/examples/python/pd_app.py
|
|
@@ -14,6 +14,7 @@ osdp/helpers.py
|
|
|
14
14
|
osdp/key_store.py
|
|
15
15
|
osdp/peripheral_device.py
|
|
16
16
|
vendor/include/osdp.h
|
|
17
|
+
vendor/include/osdp_export.h
|
|
17
18
|
vendor/python/osdp_sys/base.c
|
|
18
19
|
vendor/python/osdp_sys/cp.c
|
|
19
20
|
vendor/python/osdp_sys/data.c
|
|
@@ -27,7 +28,6 @@ vendor/src/osdp_config.h
|
|
|
27
28
|
vendor/src/osdp_cp.c
|
|
28
29
|
vendor/src/osdp_diag.c
|
|
29
30
|
vendor/src/osdp_diag.h
|
|
30
|
-
vendor/src/osdp_export.h
|
|
31
31
|
vendor/src/osdp_file.c
|
|
32
32
|
vendor/src/osdp_file.h
|
|
33
33
|
vendor/src/osdp_pd.c
|
|
@@ -37,6 +37,7 @@ vendor/src/crypto/tinyaes.c
|
|
|
37
37
|
vendor/src/crypto/tinyaes_src.c
|
|
38
38
|
vendor/src/crypto/tinyaes_src.h
|
|
39
39
|
vendor/utils/include/utils/assert.h
|
|
40
|
+
vendor/utils/include/utils/crc16.h
|
|
40
41
|
vendor/utils/include/utils/disjoint_set.h
|
|
41
42
|
vendor/utils/include/utils/list.h
|
|
42
43
|
vendor/utils/include/utils/logger.h
|
|
@@ -44,10 +45,10 @@ vendor/utils/include/utils/pcap_gen.h
|
|
|
44
45
|
vendor/utils/include/utils/queue.h
|
|
45
46
|
vendor/utils/include/utils/slab.h
|
|
46
47
|
vendor/utils/include/utils/utils.h
|
|
48
|
+
vendor/utils/src/crc16.c
|
|
47
49
|
vendor/utils/src/disjoint_set.c
|
|
48
50
|
vendor/utils/src/list.c
|
|
49
51
|
vendor/utils/src/logger.c
|
|
50
52
|
vendor/utils/src/pcap_gen.c
|
|
51
53
|
vendor/utils/src/queue.c
|
|
52
|
-
vendor/utils/src/slab.c
|
|
53
54
|
vendor/utils/src/utils.c
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#
|
|
2
|
-
# Copyright (c) 2021-
|
|
2
|
+
# Copyright (c) 2021-2026 Siddharth Chandrasekaran <sidcha.dev@gmail.com>
|
|
3
3
|
#
|
|
4
4
|
# SPDX-License-Identifier: Apache-2.0
|
|
5
5
|
#
|
|
@@ -9,7 +9,7 @@ from .peripheral_device import PeripheralDevice
|
|
|
9
9
|
from .key_store import KeyStore
|
|
10
10
|
from .constants import (
|
|
11
11
|
LibFlag, Command, CommandLEDColor, CommandFileTxFlags, Event, EventNotification,
|
|
12
|
-
CardFormat, Capability, LogLevel, StatusReportType
|
|
12
|
+
CardFormat, Capability, LogLevel, StatusReportType, CompletionStatus
|
|
13
13
|
)
|
|
14
14
|
from .helpers import PdId, PDInfo, PDCapabilities
|
|
15
15
|
from .channel import Channel
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#
|
|
2
|
-
# Copyright (c) 2021-
|
|
2
|
+
# Copyright (c) 2021-2026 Siddharth Chandrasekaran <sidcha.dev@gmail.com>
|
|
3
3
|
#
|
|
4
4
|
# SPDX-License-Identifier: Apache-2.0
|
|
5
5
|
#
|
|
@@ -35,6 +35,7 @@ class Command:
|
|
|
35
35
|
Buzzer = osdp_sys.CMD_BUZZER
|
|
36
36
|
LED = osdp_sys.CMD_LED
|
|
37
37
|
Comset = osdp_sys.CMD_COMSET
|
|
38
|
+
ComsetDone = osdp_sys.CMD_COMSET_DONE
|
|
38
39
|
Text = osdp_sys.CMD_TEXT
|
|
39
40
|
Manufacturer = osdp_sys.CMD_MFG
|
|
40
41
|
Keyset = osdp_sys.CMD_KEYSET
|
|
@@ -59,6 +60,12 @@ class EventNotification:
|
|
|
59
60
|
SecureChannelStatus = osdp_sys.EVENT_NOTIFICATION_SC_STATUS
|
|
60
61
|
PeripheralDeviceStatus = osdp_sys.EVENT_NOTIFICATION_PD_STATUS
|
|
61
62
|
|
|
63
|
+
class CompletionStatus:
|
|
64
|
+
Ok = getattr(osdp_sys, "COMPLETION_OK", 0)
|
|
65
|
+
Failed = getattr(osdp_sys, "COMPLETION_FAILED", 1)
|
|
66
|
+
Flushed = getattr(osdp_sys, "COMPLETION_FLUSHED", 2)
|
|
67
|
+
Aborted = getattr(osdp_sys, "COMPLETION_ABORTED", 3)
|
|
68
|
+
|
|
62
69
|
class Event:
|
|
63
70
|
CardRead = osdp_sys.EVENT_CARDREAD
|
|
64
71
|
KeyPress = osdp_sys.EVENT_KEYPRESS
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#
|
|
2
|
-
# Copyright (c) 2021-
|
|
2
|
+
# Copyright (c) 2021-2026 Siddharth Chandrasekaran <sidcha.dev@gmail.com>
|
|
3
3
|
#
|
|
4
4
|
# SPDX-License-Identifier: Apache-2.0
|
|
5
5
|
#
|
|
@@ -17,7 +17,8 @@ class ControlPanel():
|
|
|
17
17
|
self,
|
|
18
18
|
pd_info_list: list[PDInfo],
|
|
19
19
|
log_level: LogLevel=LogLevel.Info,
|
|
20
|
-
event_handler: Callable[[int, dict], int]=None
|
|
20
|
+
event_handler: Callable[[int, dict], int]=None,
|
|
21
|
+
command_completion_handler: Callable[[int, dict, int], None]=None
|
|
21
22
|
) -> None:
|
|
22
23
|
self.pd_addr = []
|
|
23
24
|
info_list = []
|
|
@@ -26,9 +27,18 @@ class ControlPanel():
|
|
|
26
27
|
self.pd_addr.append(pd_info.address)
|
|
27
28
|
info_list.append(pd_info.get())
|
|
28
29
|
self.event_queue = [ queue.Queue() for i in self.pd_addr ]
|
|
30
|
+
self.user_event_handler = None
|
|
31
|
+
self.user_command_completion_handler = None
|
|
29
32
|
osdp_sys.set_loglevel(log_level)
|
|
30
33
|
self.ctx = osdp_sys.ControlPanel(info_list)
|
|
34
|
+
# Always use our internal handler to ensure queue functionality
|
|
35
|
+
self.ctx.set_event_callback(self._internal_event_handler)
|
|
36
|
+
if hasattr(self.ctx, "set_command_completion_callback"):
|
|
37
|
+
self.ctx.set_command_completion_callback(
|
|
38
|
+
self._internal_command_completion_handler
|
|
39
|
+
)
|
|
31
40
|
self.set_event_handler(event_handler)
|
|
41
|
+
self.set_command_completion_handler(command_completion_handler)
|
|
32
42
|
self.event = None
|
|
33
43
|
self.lock = None
|
|
34
44
|
self.thread = None
|
|
@@ -36,21 +46,42 @@ class ControlPanel():
|
|
|
36
46
|
@staticmethod
|
|
37
47
|
def refresh(event, lock, ctx):
|
|
38
48
|
while not event.is_set():
|
|
39
|
-
lock
|
|
40
|
-
|
|
41
|
-
lock.release()
|
|
49
|
+
with lock:
|
|
50
|
+
ctx.refresh()
|
|
42
51
|
time.sleep(0.020) #sleep for 20ms
|
|
43
52
|
|
|
44
53
|
def set_event_handler(self, handler: Callable[[int, dict], int]):
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
54
|
+
"""Set user event handler while maintaining queue functionality"""
|
|
55
|
+
self.user_event_handler = handler
|
|
56
|
+
|
|
57
|
+
def set_command_completion_handler(
|
|
58
|
+
self, handler: Callable[[int, dict, int], None]):
|
|
59
|
+
self.user_command_completion_handler = handler
|
|
49
60
|
|
|
50
|
-
def
|
|
61
|
+
def _internal_event_handler(self, pd, event) -> int:
|
|
62
|
+
"""Internal handler that manages both queue and user callback"""
|
|
63
|
+
# Always put event in queue for get_event() compatibility
|
|
51
64
|
self.event_queue[pd].put(event)
|
|
65
|
+
|
|
66
|
+
# If user has set a custom handler, call it too
|
|
67
|
+
if self.user_event_handler:
|
|
68
|
+
try:
|
|
69
|
+
return self.user_event_handler(pd, event)
|
|
70
|
+
except Exception as e:
|
|
71
|
+
print(f"Error in user event handler: {e}")
|
|
72
|
+
return -1
|
|
73
|
+
|
|
52
74
|
return 0
|
|
53
75
|
|
|
76
|
+
def _internal_command_completion_handler(self, pd, command, status) -> None:
|
|
77
|
+
if self.user_command_completion_handler:
|
|
78
|
+
try:
|
|
79
|
+
self.user_command_completion_handler(
|
|
80
|
+
self.pd_addr[pd], command, status
|
|
81
|
+
)
|
|
82
|
+
except Exception as e:
|
|
83
|
+
print(f"Error in user command completion handler: {e}")
|
|
84
|
+
|
|
54
85
|
def get_event(self, address, timeout: int=5):
|
|
55
86
|
pd = self.pd_addr.index(address)
|
|
56
87
|
block = timeout >= 0
|
|
@@ -61,10 +92,8 @@ class ControlPanel():
|
|
|
61
92
|
return event
|
|
62
93
|
|
|
63
94
|
def status(self):
|
|
64
|
-
self.lock
|
|
65
|
-
|
|
66
|
-
self.lock.release()
|
|
67
|
-
return bitmask
|
|
95
|
+
with self.lock:
|
|
96
|
+
return self.ctx.status()
|
|
68
97
|
|
|
69
98
|
def is_online(self, address):
|
|
70
99
|
pd = self.pd_addr.index(address)
|
|
@@ -72,9 +101,8 @@ class ControlPanel():
|
|
|
72
101
|
|
|
73
102
|
def get_pd_id(self, address: int) -> PdId:
|
|
74
103
|
pd = self.pd_addr.index(address)
|
|
75
|
-
self.lock
|
|
76
|
-
|
|
77
|
-
self.lock.release()
|
|
104
|
+
with self.lock:
|
|
105
|
+
pd_id_dict = self.ctx.get_pd_id(pd)
|
|
78
106
|
if pd_id_dict:
|
|
79
107
|
# version: int, model: int, vendor_code: int, serial_number: int, firmware_version: int
|
|
80
108
|
pd_id = PdId(
|
|
@@ -88,9 +116,8 @@ class ControlPanel():
|
|
|
88
116
|
|
|
89
117
|
def check_capability(self, address: int, cap: Capability) -> Tuple[int, int]:
|
|
90
118
|
pd = self.pd_addr.index(address)
|
|
91
|
-
self.lock
|
|
92
|
-
|
|
93
|
-
self.lock.release()
|
|
119
|
+
with self.lock:
|
|
120
|
+
compliance_level, num_items = self.ctx.check_capability(pd, cap)
|
|
94
121
|
return (compliance_level, num_items)
|
|
95
122
|
|
|
96
123
|
def get_num_online(self):
|
|
@@ -102,10 +129,8 @@ class ControlPanel():
|
|
|
102
129
|
return online
|
|
103
130
|
|
|
104
131
|
def sc_status(self):
|
|
105
|
-
self.lock
|
|
106
|
-
|
|
107
|
-
self.lock.release()
|
|
108
|
-
return bitmask
|
|
132
|
+
with self.lock:
|
|
133
|
+
return self.ctx.sc_status()
|
|
109
134
|
|
|
110
135
|
def is_sc_active(self, address):
|
|
111
136
|
pd = self.pd_addr.index(address)
|
|
@@ -119,40 +144,55 @@ class ControlPanel():
|
|
|
119
144
|
sc_active += 1
|
|
120
145
|
return sc_active
|
|
121
146
|
|
|
122
|
-
def
|
|
147
|
+
def submit_command(self, address, cmd):
|
|
123
148
|
pd = self.pd_addr.index(address)
|
|
124
|
-
self.lock
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
149
|
+
with self.lock:
|
|
150
|
+
return self.ctx.submit_command(pd, cmd)
|
|
151
|
+
|
|
152
|
+
def flush_commands(self, address):
|
|
153
|
+
pd = self.pd_addr.index(address)
|
|
154
|
+
with self.lock:
|
|
155
|
+
return self.ctx.flush_commands(pd)
|
|
156
|
+
|
|
157
|
+
def send_command(self, address, cmd):
|
|
158
|
+
from warnings import warn
|
|
159
|
+
warn("This method has been renamed to submit_command", DeprecationWarning, 2)
|
|
160
|
+
return self.submit_command(address, cmd)
|
|
128
161
|
|
|
129
162
|
def set_flag(self, address, flag: LibFlag):
|
|
130
163
|
pd = self.pd_addr.index(address)
|
|
131
|
-
self.lock
|
|
132
|
-
|
|
133
|
-
self.lock.release()
|
|
134
|
-
return ret
|
|
164
|
+
with self.lock:
|
|
165
|
+
return self.ctx.set_flag(pd, flag)
|
|
135
166
|
|
|
136
167
|
def clear_flag(self, address, flag: LibFlag):
|
|
137
168
|
pd = self.pd_addr.index(address)
|
|
138
|
-
self.lock
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
169
|
+
with self.lock:
|
|
170
|
+
return self.ctx.clear_flag(pd, flag)
|
|
171
|
+
|
|
172
|
+
def disable_pd(self, address: int) -> bool:
|
|
173
|
+
pd = self.pd_addr.index(address)
|
|
174
|
+
with self.lock:
|
|
175
|
+
return self.ctx.disable_pd(pd)
|
|
176
|
+
|
|
177
|
+
def enable_pd(self, address: int) -> bool:
|
|
178
|
+
pd = self.pd_addr.index(address)
|
|
179
|
+
with self.lock:
|
|
180
|
+
return self.ctx.enable_pd(pd)
|
|
181
|
+
|
|
182
|
+
def is_pd_enabled(self, address: int) -> bool:
|
|
183
|
+
pd = self.pd_addr.index(address)
|
|
184
|
+
with self.lock:
|
|
185
|
+
return self.ctx.is_pd_enabled(pd)
|
|
142
186
|
|
|
143
187
|
def register_file_ops(self, address, fops):
|
|
144
188
|
pd = self.pd_addr.index(address)
|
|
145
|
-
self.lock
|
|
146
|
-
|
|
147
|
-
self.lock.release()
|
|
148
|
-
return ret
|
|
189
|
+
with self.lock:
|
|
190
|
+
return self.ctx.register_file_ops(pd, fops)
|
|
149
191
|
|
|
150
192
|
def get_file_tx_status(self, address):
|
|
151
193
|
pd = self.pd_addr.index(address)
|
|
152
|
-
self.lock
|
|
153
|
-
|
|
154
|
-
self.lock.release()
|
|
155
|
-
return ret
|
|
194
|
+
with self.lock:
|
|
195
|
+
return self.ctx.get_file_tx_status(pd)
|
|
156
196
|
|
|
157
197
|
def start(self):
|
|
158
198
|
if self.thread:
|
|
@@ -197,8 +237,14 @@ class ControlPanel():
|
|
|
197
237
|
|
|
198
238
|
def offline_wait(self, address, timeout=8):
|
|
199
239
|
count = 0
|
|
200
|
-
|
|
201
|
-
|
|
240
|
+
res = False
|
|
241
|
+
while count < timeout * 2:
|
|
242
|
+
time.sleep(0.5)
|
|
243
|
+
if not self.is_online(address):
|
|
244
|
+
res = True
|
|
245
|
+
break
|
|
246
|
+
count += 1
|
|
247
|
+
return res
|
|
202
248
|
|
|
203
249
|
def sc_wait(self, address, timeout=5):
|
|
204
250
|
count = 0
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#
|
|
2
|
-
# Copyright (c) 2021-
|
|
2
|
+
# Copyright (c) 2021-2026 Siddharth Chandrasekaran <sidcha.dev@gmail.com>
|
|
3
3
|
#
|
|
4
4
|
# SPDX-License-Identifier: Apache-2.0
|
|
5
5
|
#
|
|
@@ -16,16 +16,22 @@ from .constants import LogLevel
|
|
|
16
16
|
class PeripheralDevice():
|
|
17
17
|
def __init__(self, pd_info: PDInfo, pd_cap: PDCapabilities,
|
|
18
18
|
log_level: LogLevel=LogLevel.Info,
|
|
19
|
-
command_handler: Callable[[dict], Tuple[int, dict]]=None
|
|
19
|
+
command_handler: Callable[[dict], Tuple[int, dict]]=None,
|
|
20
|
+
event_completion_handler: Callable[[dict, int], None]=None):
|
|
20
21
|
self.command_queue = queue.Queue()
|
|
21
22
|
self.address = pd_info.address
|
|
23
|
+
self.user_command_handler = None
|
|
24
|
+
self.user_event_completion_handler = None
|
|
22
25
|
osdp_sys.set_loglevel(log_level)
|
|
23
26
|
self.ctx = osdp_sys.PeripheralDevice(pd_info.get(), capabilities=pd_cap.get())
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
self.ctx.
|
|
27
|
+
# Always use our internal handler to ensure queue functionality
|
|
28
|
+
self.ctx.set_command_callback(self._internal_command_handler)
|
|
29
|
+
if hasattr(self.ctx, "set_event_completion_callback"):
|
|
30
|
+
self.ctx.set_event_completion_callback(
|
|
31
|
+
self._internal_event_completion_handler
|
|
32
|
+
)
|
|
28
33
|
self.set_command_handler(command_handler)
|
|
34
|
+
self.set_event_completion_handler(event_completion_handler)
|
|
29
35
|
self.event = None
|
|
30
36
|
self.lock = None
|
|
31
37
|
self.thread = None
|
|
@@ -33,20 +39,38 @@ class PeripheralDevice():
|
|
|
33
39
|
@staticmethod
|
|
34
40
|
def refresh(event, lock, ctx):
|
|
35
41
|
while not event.is_set():
|
|
36
|
-
lock
|
|
37
|
-
|
|
38
|
-
lock.release()
|
|
42
|
+
with lock:
|
|
43
|
+
ctx.refresh()
|
|
39
44
|
time.sleep(0.020) #sleep for 20ms
|
|
40
45
|
|
|
41
|
-
def
|
|
46
|
+
def _internal_command_handler(self, command) -> Tuple[int, dict]:
|
|
47
|
+
"""Internal handler that manages both queue and user callback"""
|
|
48
|
+
# Always put command in queue for get_command() compatibility
|
|
42
49
|
self.command_queue.put(command)
|
|
50
|
+
|
|
51
|
+
# If user has set a custom handler, call it too
|
|
52
|
+
if self.user_command_handler:
|
|
53
|
+
try:
|
|
54
|
+
return self.user_command_handler(command)
|
|
55
|
+
except Exception as e:
|
|
56
|
+
print(f"Error in user command handler: {e}")
|
|
57
|
+
return -1, None
|
|
58
|
+
|
|
43
59
|
return 0, None
|
|
44
60
|
|
|
45
61
|
def set_command_handler(self, handler: Callable[[dict], Tuple[int, dict]]):
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
62
|
+
"""Set user command handler while maintaining queue functionality"""
|
|
63
|
+
self.user_command_handler = handler
|
|
64
|
+
|
|
65
|
+
def set_event_completion_handler(self, handler: Callable[[dict, int], None]):
|
|
66
|
+
self.user_event_completion_handler = handler
|
|
67
|
+
|
|
68
|
+
def _internal_event_completion_handler(self, event, status) -> None:
|
|
69
|
+
if self.user_event_completion_handler:
|
|
70
|
+
try:
|
|
71
|
+
self.user_event_completion_handler(event, status)
|
|
72
|
+
except Exception as e:
|
|
73
|
+
print(f"Error in user event completion handler: {e}")
|
|
50
74
|
|
|
51
75
|
def get_command(self, timeout: int=5):
|
|
52
76
|
block = timeout >= 0
|
|
@@ -56,17 +80,18 @@ class PeripheralDevice():
|
|
|
56
80
|
return None
|
|
57
81
|
return cmd
|
|
58
82
|
|
|
83
|
+
def submit_event(self, event):
|
|
84
|
+
with self.lock:
|
|
85
|
+
return self.ctx.submit_event(event)
|
|
86
|
+
|
|
59
87
|
def notify_event(self, event):
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
self.
|
|
63
|
-
return ret
|
|
88
|
+
from warnings import warn
|
|
89
|
+
warn("This method has been renamed to submit_event", DeprecationWarning, 2)
|
|
90
|
+
return self.submit_event(event)
|
|
64
91
|
|
|
65
92
|
def register_file_ops(self, fops):
|
|
66
|
-
self.lock
|
|
67
|
-
|
|
68
|
-
self.lock.release()
|
|
69
|
-
return ret
|
|
93
|
+
with self.lock:
|
|
94
|
+
return self.ctx.register_file_ops(0, fops)
|
|
70
95
|
|
|
71
96
|
def is_sc_active(self):
|
|
72
97
|
return self.ctx.is_sc_active()
|
|
@@ -95,10 +120,8 @@ class PeripheralDevice():
|
|
|
95
120
|
self.thread.start()
|
|
96
121
|
|
|
97
122
|
def get_file_tx_status(self):
|
|
98
|
-
self.lock
|
|
99
|
-
|
|
100
|
-
self.lock.release()
|
|
101
|
-
return ret
|
|
123
|
+
with self.lock:
|
|
124
|
+
return self.ctx.get_file_tx_status(0)
|
|
102
125
|
|
|
103
126
|
def stop(self):
|
|
104
127
|
if not self.thread:
|