sensor-sdk 0.1.1__tar.gz → 0.1.4__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.
- {sensor_sdk-0.1.1 → sensor_sdk-0.1.4}/PKG-INFO +2 -1
- sensor_sdk-0.1.4/sensor/__init__.py +20 -0
- {sensor_sdk-0.1.1 → sensor_sdk-0.1.4}/sensor/bleak_host.py +87 -27
- {sensor_sdk-0.1.1 → sensor_sdk-0.1.4}/sensor/bleak_process.py +55 -20
- sensor_sdk-0.1.4/sensor/fb/DataType.py +32 -0
- sensor_sdk-0.1.4/sensor/fb/Sample.py +49 -0
- sensor_sdk-0.1.4/sensor/fb/SensorData.py +296 -0
- sensor_sdk-0.1.4/sensor/fb/__init__.py +0 -0
- {sensor_sdk-0.1.1 → sensor_sdk-0.1.4}/sensor/gforce.py +40 -19
- {sensor_sdk-0.1.1 → sensor_sdk-0.1.4}/sensor/sdk_log.py +93 -5
- {sensor_sdk-0.1.1 → sensor_sdk-0.1.4}/sensor/sensor_controller.py +3 -0
- sensor_sdk-0.1.4/sensor/sensor_data.py +241 -0
- {sensor_sdk-0.1.1 → sensor_sdk-0.1.4}/sensor/sensor_data_context.py +296 -134
- sensor_sdk-0.1.4/sensor/sensor_data_pool.py +110 -0
- {sensor_sdk-0.1.1 → sensor_sdk-0.1.4}/sensor/sensor_utils.py +20 -3
- sensor_sdk-0.1.4/sensor/winrt_high_throughput.py +104 -0
- {sensor_sdk-0.1.1 → sensor_sdk-0.1.4}/sensor_sdk.egg-info/PKG-INFO +2 -1
- {sensor_sdk-0.1.1 → sensor_sdk-0.1.4}/sensor_sdk.egg-info/SOURCES.txt +6 -0
- {sensor_sdk-0.1.1 → sensor_sdk-0.1.4}/sensor_sdk.egg-info/requires.txt +1 -0
- {sensor_sdk-0.1.1 → sensor_sdk-0.1.4}/setup.py +2 -2
- sensor_sdk-0.1.1/sensor/__init__.py +0 -4
- sensor_sdk-0.1.1/sensor/sensor_data.py +0 -103
- {sensor_sdk-0.1.1 → sensor_sdk-0.1.4}/LICENSE.txt +0 -0
- {sensor_sdk-0.1.1 → sensor_sdk-0.1.4}/README.md +0 -0
- {sensor_sdk-0.1.1 → sensor_sdk-0.1.4}/sensor/sensor_device.py +0 -0
- {sensor_sdk-0.1.1 → sensor_sdk-0.1.4}/sensor/sensor_profile.py +0 -0
- {sensor_sdk-0.1.1 → sensor_sdk-0.1.4}/sensor_sdk.egg-info/dependency_links.txt +0 -0
- {sensor_sdk-0.1.1 → sensor_sdk-0.1.4}/sensor_sdk.egg-info/top_level.txt +0 -0
- {sensor_sdk-0.1.1 → sensor_sdk-0.1.4}/sensor_sdk.egg-info/zip-safe +0 -0
- {sensor_sdk-0.1.1 → sensor_sdk-0.1.4}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: sensor-sdk
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.4
|
|
4
4
|
Summary: Python sdk for Synchroni
|
|
5
5
|
Home-page: https://github.com/oymotion/SynchroniSDKPython
|
|
6
6
|
Author: Martin Ye
|
|
@@ -11,6 +11,7 @@ License-File: LICENSE.txt
|
|
|
11
11
|
Requires-Dist: numpy
|
|
12
12
|
Requires-Dist: setuptools
|
|
13
13
|
Requires-Dist: bleak>=3.0.2
|
|
14
|
+
Requires-Dist: flatbuffers>=25.0.0
|
|
14
15
|
Dynamic: author
|
|
15
16
|
Dynamic: author-email
|
|
16
17
|
Dynamic: description
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
from sensor.sensor_controller import SensorController, SensorControllerInstance
|
|
2
|
+
from sensor.sensor_profile import SensorProfile
|
|
3
|
+
from sensor.sensor_device import BLEDevice, DeviceInfo, DeviceStateEx
|
|
4
|
+
from sensor.sensor_data import DataType, Sample, SensorData
|
|
5
|
+
from sensor.winrt_high_throughput import apply as _apply_winrt_high_throughput_patch
|
|
6
|
+
|
|
7
|
+
# Windows 下尝试给 bleak WinRT backend 打高吞吐率连接参数补丁
|
|
8
|
+
_apply_winrt_high_throughput_patch()
|
|
9
|
+
|
|
10
|
+
__all__ = [
|
|
11
|
+
"SensorController",
|
|
12
|
+
"SensorControllerInstance",
|
|
13
|
+
"SensorProfile",
|
|
14
|
+
"BLEDevice",
|
|
15
|
+
"DeviceInfo",
|
|
16
|
+
"DeviceStateEx",
|
|
17
|
+
"DataType",
|
|
18
|
+
"Sample",
|
|
19
|
+
"SensorData",
|
|
20
|
+
]
|
|
@@ -17,7 +17,8 @@ class BleakHost:
|
|
|
17
17
|
def __init__(self):
|
|
18
18
|
self._cmd_queue = multiprocessing.Queue(maxsize=50)
|
|
19
19
|
self._result_queue = multiprocessing.Queue(maxsize=sensor_utils.BLEAK_RESULT_QUEUE_MAXSIZE)
|
|
20
|
-
self.
|
|
20
|
+
self._data_queue = multiprocessing.Queue(maxsize=sensor_utils.BLEAK_DATA_QUEUE_MAXSIZE)
|
|
21
|
+
self._bleak_process = BleakProcess(self._cmd_queue, self._result_queue, self._data_queue, SdkLog.get_log_path())
|
|
21
22
|
self._started = False
|
|
22
23
|
|
|
23
24
|
|
|
@@ -51,6 +52,7 @@ class BleakHost:
|
|
|
51
52
|
def stop(self):
|
|
52
53
|
if not self._started:
|
|
53
54
|
return
|
|
55
|
+
self._should_exit = True
|
|
54
56
|
try:
|
|
55
57
|
self._cmd_queue.put({"type": "terminate"})
|
|
56
58
|
except Exception as e:
|
|
@@ -60,9 +62,23 @@ class BleakHost:
|
|
|
60
62
|
self._bleak_process.join(timeout=5)
|
|
61
63
|
if self._bleak_process.is_alive():
|
|
62
64
|
self._bleak_process.terminate()
|
|
65
|
+
self._bleak_process.join(timeout=2)
|
|
63
66
|
|
|
64
67
|
self._stop_result_loop()
|
|
65
68
|
self._stop_cmd_loop()
|
|
69
|
+
|
|
70
|
+
try:
|
|
71
|
+
self._cmd_queue.close()
|
|
72
|
+
self._result_queue.close()
|
|
73
|
+
self._data_queue.close()
|
|
74
|
+
except Exception as e:
|
|
75
|
+
SdkLog.exception(_TAG, "Error closing queues")
|
|
76
|
+
|
|
77
|
+
try:
|
|
78
|
+
self._bleak_process.close()
|
|
79
|
+
except Exception as e:
|
|
80
|
+
SdkLog.exception(_TAG, "Error closing bleak process")
|
|
81
|
+
|
|
66
82
|
self._started = False
|
|
67
83
|
|
|
68
84
|
# ------------------------------------------------------------------
|
|
@@ -77,9 +93,23 @@ class BleakHost:
|
|
|
77
93
|
result_thread.start()
|
|
78
94
|
self._result_loop = result_loop
|
|
79
95
|
self._result_thread = result_thread
|
|
80
|
-
|
|
96
|
+
|
|
97
|
+
def _create_consume_task():
|
|
98
|
+
self._consume_task = result_loop.create_task(self._consume_results())
|
|
99
|
+
|
|
100
|
+
result_loop.call_soon_threadsafe(_create_consume_task)
|
|
81
101
|
|
|
82
102
|
def _stop_result_loop(self):
|
|
103
|
+
task = getattr(self, '_consume_task', None)
|
|
104
|
+
if task is not None:
|
|
105
|
+
try:
|
|
106
|
+
loop = task.get_loop()
|
|
107
|
+
if loop is not None and not loop.is_closed():
|
|
108
|
+
loop.call_soon_threadsafe(task.cancel)
|
|
109
|
+
except Exception as e:
|
|
110
|
+
SdkLog.exception(_TAG, "Unexpected error")
|
|
111
|
+
self._consume_task = None
|
|
112
|
+
|
|
83
113
|
loop = getattr(self, '_result_loop', None)
|
|
84
114
|
thread = getattr(self, '_result_thread', None)
|
|
85
115
|
if loop is not None and not loop.is_closed():
|
|
@@ -97,38 +127,68 @@ class BleakHost:
|
|
|
97
127
|
|
|
98
128
|
async def _consume_results(self):
|
|
99
129
|
|
|
100
|
-
|
|
130
|
+
def _try_get(q, timeout):
|
|
131
|
+
try:
|
|
132
|
+
return q.get(True, timeout)
|
|
133
|
+
except queue.Empty:
|
|
134
|
+
return None
|
|
135
|
+
|
|
136
|
+
while not getattr(self, '_should_exit', False):
|
|
101
137
|
try:
|
|
138
|
+
# Prioritize control/result messages; data messages are drained in batch below.
|
|
102
139
|
msg = await asyncio.get_event_loop().run_in_executor(
|
|
103
|
-
None, self._result_queue
|
|
140
|
+
None, _try_get, self._result_queue, 0.02
|
|
104
141
|
)
|
|
105
|
-
except queue.Empty:
|
|
106
|
-
continue
|
|
107
142
|
except Exception:
|
|
143
|
+
msg = None
|
|
144
|
+
|
|
145
|
+
if msg is None:
|
|
146
|
+
try:
|
|
147
|
+
msg = await asyncio.get_event_loop().run_in_executor(
|
|
148
|
+
None, _try_get, self._data_queue, 0.02
|
|
149
|
+
)
|
|
150
|
+
except Exception:
|
|
151
|
+
msg = None
|
|
152
|
+
|
|
153
|
+
if msg is None:
|
|
154
|
+
await asyncio.sleep(0.001)
|
|
108
155
|
continue
|
|
109
156
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
except Exception as e:
|
|
116
|
-
SdkLog.exception(_TAG, "Unexpected error")
|
|
117
|
-
elif msg_type == "devices":
|
|
118
|
-
if self.on_scan_result is not None:
|
|
119
|
-
try:
|
|
120
|
-
self.on_scan_result(msg)
|
|
121
|
-
except Exception as e:
|
|
122
|
-
SdkLog.exception(_TAG, "Unexpected error")
|
|
123
|
-
elif msg_type == "command_result":
|
|
124
|
-
self._handle_command_result(msg)
|
|
125
|
-
elif msg_type in ("state_changed", "power_changed", "sensor_data", "error"):
|
|
126
|
-
if self.on_device_message is not None:
|
|
127
|
-
device_mac = msg.get("device_mac")
|
|
157
|
+
self._dispatch_message(msg)
|
|
158
|
+
|
|
159
|
+
# Batch drain both queues to catch up quickly and reduce per-get overhead.
|
|
160
|
+
for q in (self._result_queue, self._data_queue):
|
|
161
|
+
while True:
|
|
128
162
|
try:
|
|
129
|
-
self.
|
|
130
|
-
except
|
|
131
|
-
|
|
163
|
+
self._dispatch_message(q.get_nowait())
|
|
164
|
+
except queue.Empty:
|
|
165
|
+
break
|
|
166
|
+
except Exception:
|
|
167
|
+
break
|
|
168
|
+
|
|
169
|
+
def _dispatch_message(self, msg):
|
|
170
|
+
msg_type = msg.get("type")
|
|
171
|
+
if msg_type == "scan_once_result":
|
|
172
|
+
if self.on_scan_once_result is not None:
|
|
173
|
+
try:
|
|
174
|
+
self.on_scan_once_result(msg)
|
|
175
|
+
except Exception as e:
|
|
176
|
+
SdkLog.exception(_TAG, "Unexpected error")
|
|
177
|
+
elif msg_type == "devices":
|
|
178
|
+
if self.on_scan_result is not None:
|
|
179
|
+
try:
|
|
180
|
+
self.on_scan_result(msg)
|
|
181
|
+
except Exception as e:
|
|
182
|
+
SdkLog.exception(_TAG, "Unexpected error")
|
|
183
|
+
elif msg_type == "command_result":
|
|
184
|
+
self._handle_command_result(msg)
|
|
185
|
+
elif msg_type in ("state_changed", "power_changed", "sensor_data", "error"):
|
|
186
|
+
if self.on_device_message is not None:
|
|
187
|
+
device_mac = msg.get("device_mac")
|
|
188
|
+
try:
|
|
189
|
+
self.on_device_message(device_mac, msg)
|
|
190
|
+
except Exception as e:
|
|
191
|
+
SdkLog.exception(_TAG, "Unexpected error")
|
|
132
192
|
|
|
133
193
|
def _handle_command_result(self, msg):
|
|
134
194
|
|
|
@@ -72,11 +72,13 @@ class BleakProcess(multiprocessing.Process):
|
|
|
72
72
|
self,
|
|
73
73
|
cmd_queue: multiprocessing.Queue,
|
|
74
74
|
result_queue: multiprocessing.Queue,
|
|
75
|
+
data_queue: multiprocessing.Queue,
|
|
75
76
|
log_path: str = None,
|
|
76
77
|
):
|
|
77
78
|
super().__init__(daemon=True)
|
|
78
79
|
self.cmd_queue = cmd_queue
|
|
79
80
|
self.result_queue = result_queue
|
|
81
|
+
self.data_queue = data_queue
|
|
80
82
|
self._log_path = log_path
|
|
81
83
|
self._scanner = None
|
|
82
84
|
self._is_scanning = False
|
|
@@ -141,15 +143,23 @@ class BleakProcess(multiprocessing.Process):
|
|
|
141
143
|
|
|
142
144
|
def _flush_msg_queue(self):
|
|
143
145
|
|
|
146
|
+
def _route_and_put(msg):
|
|
147
|
+
msg_type = msg.get("type")
|
|
148
|
+
if msg_type == "sensor_data":
|
|
149
|
+
try:
|
|
150
|
+
self.data_queue.put_nowait(msg)
|
|
151
|
+
except queue.Full:
|
|
152
|
+
pass
|
|
153
|
+
elif msg_type in self._DROPABLE_MSG_TYPES:
|
|
154
|
+
self.result_queue.put_nowait(msg)
|
|
155
|
+
else:
|
|
156
|
+
# Use a short timeout during shutdown so the child process can exit cleanly.
|
|
157
|
+
self.result_queue.put(msg, timeout=2.0)
|
|
158
|
+
|
|
144
159
|
while True:
|
|
145
160
|
try:
|
|
146
161
|
msg = self._msg_queue.get_nowait()
|
|
147
|
-
|
|
148
|
-
if msg_type in self._DROPABLE_MSG_TYPES:
|
|
149
|
-
self.result_queue.put_nowait(msg)
|
|
150
|
-
else:
|
|
151
|
-
# Use a short timeout during shutdown so the child process can exit cleanly.
|
|
152
|
-
self.result_queue.put(msg, timeout=2.0)
|
|
162
|
+
_route_and_put(msg)
|
|
153
163
|
except queue.Empty:
|
|
154
164
|
break
|
|
155
165
|
except queue.Full:
|
|
@@ -170,6 +180,7 @@ class BleakProcess(multiprocessing.Process):
|
|
|
170
180
|
async def _publisher_task(self):
|
|
171
181
|
# Throttle queue-full logs to avoid blocking stdout on Windows.
|
|
172
182
|
_last_queue_full_log = 0.0
|
|
183
|
+
_last_data_queue_full_log = 0.0
|
|
173
184
|
|
|
174
185
|
while True:
|
|
175
186
|
msg = None
|
|
@@ -177,7 +188,17 @@ class BleakProcess(multiprocessing.Process):
|
|
|
177
188
|
try:
|
|
178
189
|
msg = self._msg_queue.get_nowait()
|
|
179
190
|
msg_type = msg.get("type")
|
|
180
|
-
if msg_type
|
|
191
|
+
if msg_type == "sensor_data":
|
|
192
|
+
# High-frequency data: use a dedicated drop-capable queue so it cannot
|
|
193
|
+
# block control/result messages in the main result queue.
|
|
194
|
+
try:
|
|
195
|
+
self.data_queue.put_nowait(msg)
|
|
196
|
+
except queue.Full:
|
|
197
|
+
now = time.time()
|
|
198
|
+
if now - _last_data_queue_full_log >= 2.0:
|
|
199
|
+
_last_data_queue_full_log = now
|
|
200
|
+
SdkLog.w(_TAG, "Data queue is full, dropping sensor_data")
|
|
201
|
+
elif msg_type in self._DROPABLE_MSG_TYPES:
|
|
181
202
|
self.result_queue.put_nowait(msg)
|
|
182
203
|
else:
|
|
183
204
|
# Use a short timeout for important messages so the publisher does not stall.
|
|
@@ -261,6 +282,17 @@ class BleakProcess(multiprocessing.Process):
|
|
|
261
282
|
|
|
262
283
|
def _stop_device_loops(self, device_mac: str):
|
|
263
284
|
|
|
285
|
+
# Cancel battery task if still running in event_loop
|
|
286
|
+
if device_mac in self._battery_tasks:
|
|
287
|
+
task = self._battery_tasks.pop(device_mac, None)
|
|
288
|
+
if task:
|
|
289
|
+
try:
|
|
290
|
+
loop = self._event_loops.get(device_mac)
|
|
291
|
+
if loop and not loop.is_closed():
|
|
292
|
+
loop.call_soon_threadsafe(task.cancel)
|
|
293
|
+
except Exception as e:
|
|
294
|
+
SdkLog.exception(_TAG, "Unexpected error")
|
|
295
|
+
|
|
264
296
|
# Cancel data task first if still running in data_event_loop
|
|
265
297
|
if device_mac in self._data_tasks:
|
|
266
298
|
task = self._data_tasks.pop(device_mac, None)
|
|
@@ -684,7 +716,12 @@ class BleakProcess(multiprocessing.Process):
|
|
|
684
716
|
|
|
685
717
|
# Cancel battery task
|
|
686
718
|
if device_mac in self._battery_tasks:
|
|
687
|
-
self._battery_tasks.pop(device_mac, None)
|
|
719
|
+
task = self._battery_tasks.pop(device_mac, None)
|
|
720
|
+
if task is not None:
|
|
721
|
+
try:
|
|
722
|
+
task.cancel()
|
|
723
|
+
except Exception as e:
|
|
724
|
+
SdkLog.exception(_TAG, "Unexpected error")
|
|
688
725
|
|
|
689
726
|
# Stop streaming and optionally disconnect client
|
|
690
727
|
if disconnect_client and device_mac in self._gforces:
|
|
@@ -829,9 +866,9 @@ class BleakProcess(multiprocessing.Process):
|
|
|
829
866
|
|
|
830
867
|
try:
|
|
831
868
|
if ctx.isUniversalStream:
|
|
832
|
-
await ctx.
|
|
869
|
+
await ctx._processUniversalData(local_buf, on_data, on_error)
|
|
833
870
|
else:
|
|
834
|
-
await ctx.
|
|
871
|
+
await ctx._process_data(local_buf, on_data, on_error)
|
|
835
872
|
except asyncio.CancelledError as e:
|
|
836
873
|
SdkLog.exception(_TAG, "Data loop cancelled")
|
|
837
874
|
except Exception as e:
|
|
@@ -1119,10 +1156,12 @@ class BleakProcess(multiprocessing.Process):
|
|
|
1119
1156
|
if key == "NTF_PPG_RAW":
|
|
1120
1157
|
map_key = "NTF_PPG"
|
|
1121
1158
|
|
|
1122
|
-
# 老版本 EMG 设备上 Gesture 与 EMG
|
|
1159
|
+
# 老版本 EMG 设备上 Gesture 与 EMG 互斥,自动切换
|
|
1123
1160
|
if not ctx.isNewEMG:
|
|
1124
1161
|
if map_key == "NTF_GEST" and value == "ON" and ctx.notify_map.get("NTF_EMG") == "ON":
|
|
1125
|
-
|
|
1162
|
+
ctx.notify_map["NTF_EMG"] = "OFF"
|
|
1163
|
+
ctx.notify_map[map_key] = value
|
|
1164
|
+
result = "OK"
|
|
1126
1165
|
elif map_key == "NTF_EMG" and value == "ON" and ctx.notify_map.get("NTF_GEST") == "ON":
|
|
1127
1166
|
ctx.notify_map["NTF_GEST"] = "OFF"
|
|
1128
1167
|
ctx.notify_map[map_key] = value
|
|
@@ -1165,14 +1204,12 @@ class BleakProcess(multiprocessing.Process):
|
|
|
1165
1204
|
try:
|
|
1166
1205
|
if value == "False" or value == "":
|
|
1167
1206
|
SdkLog.set_log_path("")
|
|
1168
|
-
result = "OK"
|
|
1169
1207
|
elif value == "True":
|
|
1170
1208
|
path = SdkLog.get_default_log_path()
|
|
1171
1209
|
SdkLog.set_log_path(path)
|
|
1172
|
-
result = path
|
|
1173
1210
|
else:
|
|
1174
1211
|
SdkLog.set_log_path(value)
|
|
1175
|
-
|
|
1212
|
+
result = "OK"
|
|
1176
1213
|
except Exception as e:
|
|
1177
1214
|
SdkLog.exception(_TAG, f"_do_set_param DEBUG_LOG_PATH failed: {e}")
|
|
1178
1215
|
result = "ERROR: " + str(e)
|
|
@@ -1182,16 +1219,14 @@ class BleakProcess(multiprocessing.Process):
|
|
|
1182
1219
|
if value == "False" or value == "":
|
|
1183
1220
|
SdkLog.set_data_log_enabled(False)
|
|
1184
1221
|
await ctx.setDebugCSV("")
|
|
1185
|
-
result = "OK"
|
|
1186
1222
|
elif value == "True":
|
|
1187
1223
|
SdkLog.set_data_log_enabled(True)
|
|
1188
1224
|
path = SdkLog.get_default_data_log_path()
|
|
1189
|
-
|
|
1190
|
-
result = path if csv_result == "OK" else csv_result
|
|
1225
|
+
await ctx.setDebugCSV(path)
|
|
1191
1226
|
else:
|
|
1192
1227
|
SdkLog.set_data_log_enabled(True)
|
|
1193
|
-
|
|
1194
|
-
|
|
1228
|
+
await ctx.setDebugCSV(value)
|
|
1229
|
+
result = "OK"
|
|
1195
1230
|
except Exception as e:
|
|
1196
1231
|
SdkLog.exception(_TAG, f"_do_set_param setDebugCSV failed: {device_mac} path={value}")
|
|
1197
1232
|
result = "ERROR: " + str(e)
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# automatically generated by the FlatBuffers compiler, do not modify
|
|
2
|
+
|
|
3
|
+
# namespace: fb
|
|
4
|
+
|
|
5
|
+
# BLE 数据通知类型,与 SensorSDKCXX src/SensorProfileImpl.h 中的 NotifyDataType 保持一致
|
|
6
|
+
class DataType(object):
|
|
7
|
+
NONE = 0
|
|
8
|
+
NTF_ACC_DATA = 1
|
|
9
|
+
NTF_GYO_DATA = 2
|
|
10
|
+
NTF_MAG_DATA = 3
|
|
11
|
+
NTF_EULER_DATA = 4
|
|
12
|
+
NTF_QUAT_FLOAT_DATA = 5
|
|
13
|
+
NTF_ROTA_DATA = 6
|
|
14
|
+
NTF_EMG_GEST_DATA = 7
|
|
15
|
+
NTF_EMG_ADC_DATA = 8
|
|
16
|
+
NTF_HID_MOUSE = 9
|
|
17
|
+
NTF_HID_JOYSTICK = 10
|
|
18
|
+
NTF_DEV_STATUS = 11
|
|
19
|
+
NTF_LOG_DATA = 12
|
|
20
|
+
NTF_MAG_ANGLE_DATA = 13
|
|
21
|
+
NTF_MOT_CURRENT_DATA = 14
|
|
22
|
+
NTF_NEUCIR_STATUS = 15
|
|
23
|
+
NTF_EEG = 16
|
|
24
|
+
NTF_ECG = 17
|
|
25
|
+
NTF_IMPEDANCE = 18
|
|
26
|
+
NTF_IMU = 19
|
|
27
|
+
NTF_ADS = 20
|
|
28
|
+
NTF_BRTH = 21
|
|
29
|
+
NTF_IMPEDANCE_EXT = 22
|
|
30
|
+
NTF_SPO2 = 23
|
|
31
|
+
NTF_PPG = 24
|
|
32
|
+
NTF_PARTIAL_DATA = 255
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# automatically generated by the FlatBuffers compiler, do not modify
|
|
2
|
+
|
|
3
|
+
# namespace: fb
|
|
4
|
+
|
|
5
|
+
import flatbuffers
|
|
6
|
+
from flatbuffers.compat import import_numpy
|
|
7
|
+
np = import_numpy()
|
|
8
|
+
|
|
9
|
+
# 单个采样点,内存紧凑的 struct
|
|
10
|
+
class Sample(object):
|
|
11
|
+
__slots__ = ['_tab']
|
|
12
|
+
|
|
13
|
+
@classmethod
|
|
14
|
+
def SizeOf(cls):
|
|
15
|
+
return 32
|
|
16
|
+
|
|
17
|
+
# Sample
|
|
18
|
+
def Init(self, buf, pos):
|
|
19
|
+
self._tab = flatbuffers.table.Table(buf, pos)
|
|
20
|
+
|
|
21
|
+
# Sample
|
|
22
|
+
def TimeStampInMs(self): return self._tab.Get(flatbuffers.number_types.Int32Flags, self._tab.Pos + flatbuffers.number_types.UOffsetTFlags.py_type(0))
|
|
23
|
+
# Sample
|
|
24
|
+
def ChannelIndex(self): return self._tab.Get(flatbuffers.number_types.Int32Flags, self._tab.Pos + flatbuffers.number_types.UOffsetTFlags.py_type(4))
|
|
25
|
+
# Sample
|
|
26
|
+
def SampleIndex(self): return self._tab.Get(flatbuffers.number_types.Int32Flags, self._tab.Pos + flatbuffers.number_types.UOffsetTFlags.py_type(8))
|
|
27
|
+
# Sample
|
|
28
|
+
def RawData(self): return self._tab.Get(flatbuffers.number_types.Int32Flags, self._tab.Pos + flatbuffers.number_types.UOffsetTFlags.py_type(12))
|
|
29
|
+
# Sample
|
|
30
|
+
def Data(self): return self._tab.Get(flatbuffers.number_types.Float32Flags, self._tab.Pos + flatbuffers.number_types.UOffsetTFlags.py_type(16))
|
|
31
|
+
# Sample
|
|
32
|
+
def Impedance(self): return self._tab.Get(flatbuffers.number_types.Float32Flags, self._tab.Pos + flatbuffers.number_types.UOffsetTFlags.py_type(20))
|
|
33
|
+
# Sample
|
|
34
|
+
def Saturation(self): return self._tab.Get(flatbuffers.number_types.Float32Flags, self._tab.Pos + flatbuffers.number_types.UOffsetTFlags.py_type(24))
|
|
35
|
+
# Sample
|
|
36
|
+
def IsLost(self): return self._tab.Get(flatbuffers.number_types.BoolFlags, self._tab.Pos + flatbuffers.number_types.UOffsetTFlags.py_type(28))
|
|
37
|
+
|
|
38
|
+
def CreateSample(builder, timeStampInMs, channelIndex, sampleIndex, rawData, data, impedance, saturation, isLost):
|
|
39
|
+
builder.Prep(4, 32)
|
|
40
|
+
builder.Pad(3)
|
|
41
|
+
builder.PrependBool(isLost)
|
|
42
|
+
builder.PrependFloat32(saturation)
|
|
43
|
+
builder.PrependFloat32(impedance)
|
|
44
|
+
builder.PrependFloat32(data)
|
|
45
|
+
builder.PrependInt32(rawData)
|
|
46
|
+
builder.PrependInt32(sampleIndex)
|
|
47
|
+
builder.PrependInt32(channelIndex)
|
|
48
|
+
builder.PrependInt32(timeStampInMs)
|
|
49
|
+
return builder.Offset()
|