libosdp 3.1.0__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.1.0 → libosdp-3.2.0}/PKG-INFO +26 -2
- {libosdp-3.1.0 → libosdp-3.2.0}/README.md +25 -1
- {libosdp-3.1.0 → libosdp-3.2.0}/libosdp.egg-info/PKG-INFO +26 -2
- {libosdp-3.1.0 → libosdp-3.2.0}/libosdp.egg-info/SOURCES.txt +0 -1
- {libosdp-3.1.0 → libosdp-3.2.0}/osdp/__init__.py +2 -2
- {libosdp-3.1.0 → libosdp-3.2.0}/osdp/constants.py +7 -1
- {libosdp-3.1.0 → libosdp-3.2.0}/osdp/control_panel.py +53 -51
- {libosdp-3.1.0 → libosdp-3.2.0}/osdp/helpers.py +1 -1
- {libosdp-3.1.0 → libosdp-3.2.0}/osdp/key_store.py +1 -1
- {libosdp-3.1.0 → libosdp-3.2.0}/osdp/peripheral_device.py +27 -17
- {libosdp-3.1.0 → libosdp-3.2.0}/setup.py +55 -19
- {libosdp-3.1.0 → libosdp-3.2.0}/vendor/include/osdp.h +95 -1
- {libosdp-3.1.0 → libosdp-3.2.0}/vendor/include/osdp_export.h +3 -3
- {libosdp-3.1.0 → libosdp-3.2.0}/vendor/python/osdp_sys/base.c +24 -13
- {libosdp-3.1.0 → libosdp-3.2.0}/vendor/python/osdp_sys/cp.c +202 -24
- {libosdp-3.1.0 → libosdp-3.2.0}/vendor/python/osdp_sys/data.c +2 -13
- {libosdp-3.1.0 → libosdp-3.2.0}/vendor/python/osdp_sys/module.c +8 -1
- {libosdp-3.1.0 → libosdp-3.2.0}/vendor/python/osdp_sys/module.h +18 -1
- {libosdp-3.1.0 → libosdp-3.2.0}/vendor/python/osdp_sys/pd.c +154 -7
- {libosdp-3.1.0 → libosdp-3.2.0}/vendor/python/osdp_sys/utils.c +115 -2
- {libosdp-3.1.0 → libosdp-3.2.0}/vendor/src/crypto/tinyaes.c +1 -1
- {libosdp-3.1.0 → libosdp-3.2.0}/vendor/src/osdp_common.c +1 -1
- {libosdp-3.1.0 → libosdp-3.2.0}/vendor/src/osdp_common.h +177 -65
- libosdp-3.2.0/vendor/src/osdp_config.h +102 -0
- {libosdp-3.1.0 → libosdp-3.2.0}/vendor/src/osdp_cp.c +253 -141
- {libosdp-3.1.0 → libosdp-3.2.0}/vendor/src/osdp_diag.c +1 -1
- {libosdp-3.1.0 → libosdp-3.2.0}/vendor/src/osdp_diag.h +1 -1
- {libosdp-3.1.0 → libosdp-3.2.0}/vendor/src/osdp_file.c +18 -19
- {libosdp-3.1.0 → libosdp-3.2.0}/vendor/src/osdp_file.h +1 -1
- {libosdp-3.1.0 → libosdp-3.2.0}/vendor/src/osdp_pd.c +217 -91
- {libosdp-3.1.0 → libosdp-3.2.0}/vendor/src/osdp_phy.c +156 -55
- {libosdp-3.1.0 → libosdp-3.2.0}/vendor/src/osdp_sc.c +4 -8
- {libosdp-3.1.0 → libosdp-3.2.0}/vendor/utils/include/utils/assert.h +1 -1
- {libosdp-3.1.0 → libosdp-3.2.0}/vendor/utils/include/utils/disjoint_set.h +1 -1
- {libosdp-3.1.0 → libosdp-3.2.0}/vendor/utils/include/utils/list.h +1 -1
- {libosdp-3.1.0 → libosdp-3.2.0}/vendor/utils/include/utils/logger.h +1 -1
- {libosdp-3.1.0 → libosdp-3.2.0}/vendor/utils/include/utils/pcap_gen.h +1 -1
- {libosdp-3.1.0 → libosdp-3.2.0}/vendor/utils/include/utils/queue.h +1 -1
- {libosdp-3.1.0 → libosdp-3.2.0}/vendor/utils/include/utils/slab.h +1 -1
- {libosdp-3.1.0 → libosdp-3.2.0}/vendor/utils/include/utils/utils.h +5 -5
- {libosdp-3.1.0 → libosdp-3.2.0}/vendor/utils/src/crc16.c +1 -1
- {libosdp-3.1.0 → libosdp-3.2.0}/vendor/utils/src/disjoint_set.c +1 -1
- {libosdp-3.1.0 → libosdp-3.2.0}/vendor/utils/src/list.c +1 -1
- {libosdp-3.1.0 → libosdp-3.2.0}/vendor/utils/src/logger.c +1 -1
- {libosdp-3.1.0 → libosdp-3.2.0}/vendor/utils/src/queue.c +1 -1
- {libosdp-3.1.0 → libosdp-3.2.0}/vendor/utils/src/utils.c +35 -1
- libosdp-3.1.0/vendor/src/osdp_config.h +0 -43
- libosdp-3.1.0/vendor/utils/src/slab.c +0 -64
- {libosdp-3.1.0 → libosdp-3.2.0}/MANIFEST.in +0 -0
- {libosdp-3.1.0 → libosdp-3.2.0}/libosdp.egg-info/dependency_links.txt +0 -0
- {libosdp-3.1.0 → libosdp-3.2.0}/libosdp.egg-info/top_level.txt +0 -0
- {libosdp-3.1.0 → libosdp-3.2.0}/osdp/channel.py +0 -0
- {libosdp-3.1.0 → libosdp-3.2.0}/pyproject.toml +0 -0
- {libosdp-3.1.0 → libosdp-3.2.0}/setup.cfg +0 -0
- {libosdp-3.1.0 → libosdp-3.2.0}/vendor/src/crypto/tinyaes_src.c +0 -0
- {libosdp-3.1.0 → libosdp-3.2.0}/vendor/src/crypto/tinyaes_src.h +0 -0
- {libosdp-3.1.0 → libosdp-3.2.0}/vendor/utils/include/utils/crc16.h +0 -0
- {libosdp-3.1.0 → libosdp-3.2.0}/vendor/utils/src/pcap_gen.c +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: libosdp
|
|
3
|
-
Version: 3.
|
|
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
|
|
@@ -85,6 +85,18 @@ while True:
|
|
|
85
85
|
|
|
86
86
|
see [examples/cp_app.py][2] for more details.
|
|
87
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
|
+
|
|
88
100
|
### Peripheral Device mode:
|
|
89
101
|
|
|
90
102
|
```python
|
|
@@ -116,6 +128,18 @@ while True:
|
|
|
116
128
|
|
|
117
129
|
see [examples/pd_app.py][3] for more details.
|
|
118
130
|
|
|
119
|
-
|
|
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/
|
|
120
144
|
[2]: https://github.com/goToMain/libosdp/blob/master/examples/python/cp_app.py
|
|
121
145
|
[3]: https://github.com/goToMain/libosdp/blob/master/examples/python/pd_app.py
|
|
@@ -64,6 +64,18 @@ while True:
|
|
|
64
64
|
|
|
65
65
|
see [examples/cp_app.py][2] for more details.
|
|
66
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
|
+
|
|
67
79
|
### Peripheral Device mode:
|
|
68
80
|
|
|
69
81
|
```python
|
|
@@ -95,6 +107,18 @@ while True:
|
|
|
95
107
|
|
|
96
108
|
see [examples/pd_app.py][3] for more details.
|
|
97
109
|
|
|
98
|
-
|
|
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/
|
|
99
123
|
[2]: https://github.com/goToMain/libosdp/blob/master/examples/python/cp_app.py
|
|
100
124
|
[3]: https://github.com/goToMain/libosdp/blob/master/examples/python/pd_app.py
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: libosdp
|
|
3
|
-
Version: 3.
|
|
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
|
|
@@ -85,6 +85,18 @@ while True:
|
|
|
85
85
|
|
|
86
86
|
see [examples/cp_app.py][2] for more details.
|
|
87
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
|
+
|
|
88
100
|
### Peripheral Device mode:
|
|
89
101
|
|
|
90
102
|
```python
|
|
@@ -116,6 +128,18 @@ while True:
|
|
|
116
128
|
|
|
117
129
|
see [examples/pd_app.py][3] for more details.
|
|
118
130
|
|
|
119
|
-
|
|
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/
|
|
120
144
|
[2]: https://github.com/goToMain/libosdp/blob/master/examples/python/cp_app.py
|
|
121
145
|
[3]: https://github.com/goToMain/libosdp/blob/master/examples/python/pd_app.py
|
|
@@ -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
|
#
|
|
@@ -60,6 +60,12 @@ class EventNotification:
|
|
|
60
60
|
SecureChannelStatus = osdp_sys.EVENT_NOTIFICATION_SC_STATUS
|
|
61
61
|
PeripheralDeviceStatus = osdp_sys.EVENT_NOTIFICATION_PD_STATUS
|
|
62
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
|
+
|
|
63
69
|
class Event:
|
|
64
70
|
CardRead = osdp_sys.EVENT_CARDREAD
|
|
65
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 = []
|
|
@@ -27,11 +28,17 @@ class ControlPanel():
|
|
|
27
28
|
info_list.append(pd_info.get())
|
|
28
29
|
self.event_queue = [ queue.Queue() for i in self.pd_addr ]
|
|
29
30
|
self.user_event_handler = None
|
|
31
|
+
self.user_command_completion_handler = None
|
|
30
32
|
osdp_sys.set_loglevel(log_level)
|
|
31
33
|
self.ctx = osdp_sys.ControlPanel(info_list)
|
|
32
34
|
# Always use our internal handler to ensure queue functionality
|
|
33
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
|
+
)
|
|
34
40
|
self.set_event_handler(event_handler)
|
|
41
|
+
self.set_command_completion_handler(command_completion_handler)
|
|
35
42
|
self.event = None
|
|
36
43
|
self.lock = None
|
|
37
44
|
self.thread = None
|
|
@@ -39,15 +46,18 @@ class ControlPanel():
|
|
|
39
46
|
@staticmethod
|
|
40
47
|
def refresh(event, lock, ctx):
|
|
41
48
|
while not event.is_set():
|
|
42
|
-
lock
|
|
43
|
-
|
|
44
|
-
lock.release()
|
|
49
|
+
with lock:
|
|
50
|
+
ctx.refresh()
|
|
45
51
|
time.sleep(0.020) #sleep for 20ms
|
|
46
52
|
|
|
47
53
|
def set_event_handler(self, handler: Callable[[int, dict], int]):
|
|
48
54
|
"""Set user event handler while maintaining queue functionality"""
|
|
49
55
|
self.user_event_handler = handler
|
|
50
56
|
|
|
57
|
+
def set_command_completion_handler(
|
|
58
|
+
self, handler: Callable[[int, dict, int], None]):
|
|
59
|
+
self.user_command_completion_handler = handler
|
|
60
|
+
|
|
51
61
|
def _internal_event_handler(self, pd, event) -> int:
|
|
52
62
|
"""Internal handler that manages both queue and user callback"""
|
|
53
63
|
# Always put event in queue for get_event() compatibility
|
|
@@ -63,6 +73,15 @@ class ControlPanel():
|
|
|
63
73
|
|
|
64
74
|
return 0
|
|
65
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
|
+
|
|
66
85
|
def get_event(self, address, timeout: int=5):
|
|
67
86
|
pd = self.pd_addr.index(address)
|
|
68
87
|
block = timeout >= 0
|
|
@@ -73,10 +92,8 @@ class ControlPanel():
|
|
|
73
92
|
return event
|
|
74
93
|
|
|
75
94
|
def status(self):
|
|
76
|
-
self.lock
|
|
77
|
-
|
|
78
|
-
self.lock.release()
|
|
79
|
-
return bitmask
|
|
95
|
+
with self.lock:
|
|
96
|
+
return self.ctx.status()
|
|
80
97
|
|
|
81
98
|
def is_online(self, address):
|
|
82
99
|
pd = self.pd_addr.index(address)
|
|
@@ -84,9 +101,8 @@ class ControlPanel():
|
|
|
84
101
|
|
|
85
102
|
def get_pd_id(self, address: int) -> PdId:
|
|
86
103
|
pd = self.pd_addr.index(address)
|
|
87
|
-
self.lock
|
|
88
|
-
|
|
89
|
-
self.lock.release()
|
|
104
|
+
with self.lock:
|
|
105
|
+
pd_id_dict = self.ctx.get_pd_id(pd)
|
|
90
106
|
if pd_id_dict:
|
|
91
107
|
# version: int, model: int, vendor_code: int, serial_number: int, firmware_version: int
|
|
92
108
|
pd_id = PdId(
|
|
@@ -100,9 +116,8 @@ class ControlPanel():
|
|
|
100
116
|
|
|
101
117
|
def check_capability(self, address: int, cap: Capability) -> Tuple[int, int]:
|
|
102
118
|
pd = self.pd_addr.index(address)
|
|
103
|
-
self.lock
|
|
104
|
-
|
|
105
|
-
self.lock.release()
|
|
119
|
+
with self.lock:
|
|
120
|
+
compliance_level, num_items = self.ctx.check_capability(pd, cap)
|
|
106
121
|
return (compliance_level, num_items)
|
|
107
122
|
|
|
108
123
|
def get_num_online(self):
|
|
@@ -114,10 +129,8 @@ class ControlPanel():
|
|
|
114
129
|
return online
|
|
115
130
|
|
|
116
131
|
def sc_status(self):
|
|
117
|
-
self.lock
|
|
118
|
-
|
|
119
|
-
self.lock.release()
|
|
120
|
-
return bitmask
|
|
132
|
+
with self.lock:
|
|
133
|
+
return self.ctx.sc_status()
|
|
121
134
|
|
|
122
135
|
def is_sc_active(self, address):
|
|
123
136
|
pd = self.pd_addr.index(address)
|
|
@@ -133,10 +146,13 @@ class ControlPanel():
|
|
|
133
146
|
|
|
134
147
|
def submit_command(self, address, cmd):
|
|
135
148
|
pd = self.pd_addr.index(address)
|
|
136
|
-
self.lock
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
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)
|
|
140
156
|
|
|
141
157
|
def send_command(self, address, cmd):
|
|
142
158
|
from warnings import warn
|
|
@@ -145,52 +161,38 @@ class ControlPanel():
|
|
|
145
161
|
|
|
146
162
|
def set_flag(self, address, flag: LibFlag):
|
|
147
163
|
pd = self.pd_addr.index(address)
|
|
148
|
-
self.lock
|
|
149
|
-
|
|
150
|
-
self.lock.release()
|
|
151
|
-
return ret
|
|
164
|
+
with self.lock:
|
|
165
|
+
return self.ctx.set_flag(pd, flag)
|
|
152
166
|
|
|
153
167
|
def clear_flag(self, address, flag: LibFlag):
|
|
154
168
|
pd = self.pd_addr.index(address)
|
|
155
|
-
self.lock
|
|
156
|
-
|
|
157
|
-
self.lock.release()
|
|
158
|
-
return ret
|
|
169
|
+
with self.lock:
|
|
170
|
+
return self.ctx.clear_flag(pd, flag)
|
|
159
171
|
|
|
160
172
|
def disable_pd(self, address: int) -> bool:
|
|
161
173
|
pd = self.pd_addr.index(address)
|
|
162
|
-
self.lock
|
|
163
|
-
|
|
164
|
-
self.lock.release()
|
|
165
|
-
return ret
|
|
174
|
+
with self.lock:
|
|
175
|
+
return self.ctx.disable_pd(pd)
|
|
166
176
|
|
|
167
177
|
def enable_pd(self, address: int) -> bool:
|
|
168
178
|
pd = self.pd_addr.index(address)
|
|
169
|
-
self.lock
|
|
170
|
-
|
|
171
|
-
self.lock.release()
|
|
172
|
-
return ret
|
|
179
|
+
with self.lock:
|
|
180
|
+
return self.ctx.enable_pd(pd)
|
|
173
181
|
|
|
174
182
|
def is_pd_enabled(self, address: int) -> bool:
|
|
175
183
|
pd = self.pd_addr.index(address)
|
|
176
|
-
self.lock
|
|
177
|
-
|
|
178
|
-
self.lock.release()
|
|
179
|
-
return ret
|
|
184
|
+
with self.lock:
|
|
185
|
+
return self.ctx.is_pd_enabled(pd)
|
|
180
186
|
|
|
181
187
|
def register_file_ops(self, address, fops):
|
|
182
188
|
pd = self.pd_addr.index(address)
|
|
183
|
-
self.lock
|
|
184
|
-
|
|
185
|
-
self.lock.release()
|
|
186
|
-
return ret
|
|
189
|
+
with self.lock:
|
|
190
|
+
return self.ctx.register_file_ops(pd, fops)
|
|
187
191
|
|
|
188
192
|
def get_file_tx_status(self, address):
|
|
189
193
|
pd = self.pd_addr.index(address)
|
|
190
|
-
self.lock
|
|
191
|
-
|
|
192
|
-
self.lock.release()
|
|
193
|
-
return ret
|
|
194
|
+
with self.lock:
|
|
195
|
+
return self.ctx.get_file_tx_status(pd)
|
|
194
196
|
|
|
195
197
|
def start(self):
|
|
196
198
|
if self.thread:
|
|
@@ -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,15 +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
|
|
22
23
|
self.user_command_handler = None
|
|
24
|
+
self.user_event_completion_handler = None
|
|
23
25
|
osdp_sys.set_loglevel(log_level)
|
|
24
26
|
self.ctx = osdp_sys.PeripheralDevice(pd_info.get(), capabilities=pd_cap.get())
|
|
25
27
|
# Always use our internal handler to ensure queue functionality
|
|
26
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
|
+
)
|
|
27
33
|
self.set_command_handler(command_handler)
|
|
34
|
+
self.set_event_completion_handler(event_completion_handler)
|
|
28
35
|
self.event = None
|
|
29
36
|
self.lock = None
|
|
30
37
|
self.thread = None
|
|
@@ -32,9 +39,8 @@ class PeripheralDevice():
|
|
|
32
39
|
@staticmethod
|
|
33
40
|
def refresh(event, lock, ctx):
|
|
34
41
|
while not event.is_set():
|
|
35
|
-
lock
|
|
36
|
-
|
|
37
|
-
lock.release()
|
|
42
|
+
with lock:
|
|
43
|
+
ctx.refresh()
|
|
38
44
|
time.sleep(0.020) #sleep for 20ms
|
|
39
45
|
|
|
40
46
|
def _internal_command_handler(self, command) -> Tuple[int, dict]:
|
|
@@ -56,6 +62,16 @@ class PeripheralDevice():
|
|
|
56
62
|
"""Set user command handler while maintaining queue functionality"""
|
|
57
63
|
self.user_command_handler = handler
|
|
58
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}")
|
|
74
|
+
|
|
59
75
|
def get_command(self, timeout: int=5):
|
|
60
76
|
block = timeout >= 0
|
|
61
77
|
try:
|
|
@@ -65,10 +81,8 @@ class PeripheralDevice():
|
|
|
65
81
|
return cmd
|
|
66
82
|
|
|
67
83
|
def submit_event(self, event):
|
|
68
|
-
self.lock
|
|
69
|
-
|
|
70
|
-
self.lock.release()
|
|
71
|
-
return ret
|
|
84
|
+
with self.lock:
|
|
85
|
+
return self.ctx.submit_event(event)
|
|
72
86
|
|
|
73
87
|
def notify_event(self, event):
|
|
74
88
|
from warnings import warn
|
|
@@ -76,10 +90,8 @@ class PeripheralDevice():
|
|
|
76
90
|
return self.submit_event(event)
|
|
77
91
|
|
|
78
92
|
def register_file_ops(self, fops):
|
|
79
|
-
self.lock
|
|
80
|
-
|
|
81
|
-
self.lock.release()
|
|
82
|
-
return ret
|
|
93
|
+
with self.lock:
|
|
94
|
+
return self.ctx.register_file_ops(0, fops)
|
|
83
95
|
|
|
84
96
|
def is_sc_active(self):
|
|
85
97
|
return self.ctx.is_sc_active()
|
|
@@ -108,10 +120,8 @@ class PeripheralDevice():
|
|
|
108
120
|
self.thread.start()
|
|
109
121
|
|
|
110
122
|
def get_file_tx_status(self):
|
|
111
|
-
self.lock
|
|
112
|
-
|
|
113
|
-
self.lock.release()
|
|
114
|
-
return ret
|
|
123
|
+
with self.lock:
|
|
124
|
+
return self.ctx.get_file_tx_status(0)
|
|
115
125
|
|
|
116
126
|
def stop(self):
|
|
117
127
|
if not self.thread:
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#
|
|
2
|
-
# Copyright (c) 2020-
|
|
2
|
+
# Copyright (c) 2020-2026 Siddharth Chandrasekaran <sidcha.dev@gmail.com>
|
|
3
3
|
#
|
|
4
4
|
# SPDX-License-Identifier: Apache-2.0
|
|
5
5
|
#
|
|
@@ -11,7 +11,7 @@ import shutil
|
|
|
11
11
|
import subprocess
|
|
12
12
|
|
|
13
13
|
project_name = "libosdp"
|
|
14
|
-
project_version = "3.
|
|
14
|
+
project_version = "3.2.0"
|
|
15
15
|
current_dir = os.path.dirname(os.path.realpath(__file__))
|
|
16
16
|
repo_root = os.path.realpath(os.path.join(current_dir, ".."))
|
|
17
17
|
|
|
@@ -23,17 +23,47 @@ def add_prefix_to_path(src_list, path, check_files=True):
|
|
|
23
23
|
raise RuntimeError(f"Path '{path}' does not exist")
|
|
24
24
|
return paths
|
|
25
25
|
|
|
26
|
-
def exec_cmd(cmd):
|
|
27
|
-
r = subprocess.run(cmd, capture_output
|
|
28
|
-
return r.stdout.strip()
|
|
26
|
+
def exec_cmd(cmd, cwd=None):
|
|
27
|
+
r = subprocess.run(cmd, capture_output=True, text=True, cwd=cwd)
|
|
28
|
+
return r.returncode, r.stdout.strip()
|
|
29
29
|
|
|
30
30
|
def get_git_info():
|
|
31
|
-
d = {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
31
|
+
d = {
|
|
32
|
+
"branch": "None",
|
|
33
|
+
"tag": "",
|
|
34
|
+
"diff": "",
|
|
35
|
+
"rev": "",
|
|
36
|
+
"root": repo_root,
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
rc, _ = exec_cmd(["git", "rev-parse", "--is-inside-work-tree"], cwd=repo_root)
|
|
40
|
+
if rc != 0:
|
|
41
|
+
return d
|
|
42
|
+
|
|
43
|
+
rc, root = exec_cmd(["git", "rev-parse", "--show-toplevel"], cwd=repo_root)
|
|
44
|
+
if rc == 0 and root:
|
|
45
|
+
d["root"] = root
|
|
46
|
+
|
|
47
|
+
rc, branch = exec_cmd(["git", "symbolic-ref", "--short", "-q", "HEAD"], cwd=repo_root)
|
|
48
|
+
if rc == 0 and branch:
|
|
49
|
+
d["branch"] = branch
|
|
50
|
+
else:
|
|
51
|
+
d["branch"] = "detached"
|
|
52
|
+
|
|
53
|
+
rc, rev = exec_cmd(["git", "describe", "--tags", "--long", "--always", "--abbrev=7"], cwd=repo_root)
|
|
54
|
+
if rc == 0:
|
|
55
|
+
d["rev"] = rev
|
|
56
|
+
|
|
57
|
+
rc, tag = exec_cmd(["git", "describe", "--exact-match", "--tags", "HEAD"], cwd=repo_root)
|
|
58
|
+
if rc == 0 and tag:
|
|
59
|
+
d["tag"] = tag
|
|
60
|
+
|
|
61
|
+
rc, status = exec_cmd(["git", "status", "--porcelain", "--untracked-files=normal"], cwd=repo_root)
|
|
62
|
+
if rc == 0 and status:
|
|
63
|
+
d["diff"] = "+"
|
|
64
|
+
if d["tag"]:
|
|
65
|
+
d["tag"] = d["tag"] + "+"
|
|
66
|
+
|
|
37
67
|
return d
|
|
38
68
|
|
|
39
69
|
def configure_file(file, replacements):
|
|
@@ -78,7 +108,6 @@ def try_vendor_sources(src_dir, src_files, vendor_dir):
|
|
|
78
108
|
utils_sources = [
|
|
79
109
|
"utils/src/list.c",
|
|
80
110
|
"utils/src/queue.c",
|
|
81
|
-
"utils/src/slab.c",
|
|
82
111
|
"utils/src/utils.c",
|
|
83
112
|
"utils/src/logger.c",
|
|
84
113
|
"utils/src/disjoint_set.c",
|
|
@@ -138,6 +167,19 @@ other_files = [
|
|
|
138
167
|
"utils/src/pcap_gen.c",
|
|
139
168
|
]
|
|
140
169
|
|
|
170
|
+
definitions = [
|
|
171
|
+
"OPT_OSDP_PACKET_TRACE",
|
|
172
|
+
"OPT_OSDP_RX_ZERO_COPY",
|
|
173
|
+
# "OPT_OSDP_DATA_TRACE",
|
|
174
|
+
# "OPT_OSDP_SKIP_MARK_BYTE",
|
|
175
|
+
]
|
|
176
|
+
|
|
177
|
+
app_owned_queue_data = os.getenv("OPT_OSDP_APP_OWNED_QUEUE_DATA", "").lower()
|
|
178
|
+
if app_owned_queue_data in ("0", "false", "no", "off"):
|
|
179
|
+
utils_sources.append("utils/src/slab.c")
|
|
180
|
+
else:
|
|
181
|
+
definitions.append("OPT_OSDP_APP_OWNED_QUEUE_DATA")
|
|
182
|
+
|
|
141
183
|
source_files = utils_sources + lib_sources + osdp_sys_sources
|
|
142
184
|
|
|
143
185
|
try_vendor_sources(
|
|
@@ -146,12 +188,6 @@ try_vendor_sources(
|
|
|
146
188
|
"vendor"
|
|
147
189
|
)
|
|
148
190
|
|
|
149
|
-
definitions = [
|
|
150
|
-
"OPT_OSDP_PACKET_TRACE",
|
|
151
|
-
# "OPT_OSDP_DATA_TRACE",
|
|
152
|
-
# "OPT_OSDP_SKIP_MARK_BYTE",
|
|
153
|
-
]
|
|
154
|
-
|
|
155
191
|
if ("OPT_OSDP_PACKET_TRACE" in definitions or
|
|
156
192
|
"OPT_OSDP_DATA_TRACE" in definitions):
|
|
157
193
|
source_files += [
|
|
@@ -171,7 +207,7 @@ include_dirs = [
|
|
|
171
207
|
|
|
172
208
|
compile_args = (
|
|
173
209
|
[ "-I" + path for path in include_dirs ] +
|
|
174
|
-
[ "-D" + define for define in definitions ]
|
|
210
|
+
[ "-D" + define + "=1" for define in definitions ]
|
|
175
211
|
)
|
|
176
212
|
|
|
177
213
|
if os.path.exists("README.md"):
|