sensor-sdk 0.0.69__tar.gz → 0.0.71__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.0.69/sensor_sdk.egg-info → sensor_sdk-0.0.71}/PKG-INFO +1 -1
- {sensor_sdk-0.0.69 → sensor_sdk-0.0.71}/sensor/bleak_process.py +12 -12
- {sensor_sdk-0.0.69 → sensor_sdk-0.0.71}/sensor/gforce.py +5 -3
- {sensor_sdk-0.0.69 → sensor_sdk-0.0.71}/sensor/sensor_data.py +103 -105
- {sensor_sdk-0.0.69 → sensor_sdk-0.0.71}/sensor/sensor_data_context.py +1488 -1409
- {sensor_sdk-0.0.69 → sensor_sdk-0.0.71/sensor_sdk.egg-info}/PKG-INFO +1 -1
- {sensor_sdk-0.0.69 → sensor_sdk-0.0.71}/setup.py +1 -1
- {sensor_sdk-0.0.69 → sensor_sdk-0.0.71}/LICENSE.txt +0 -0
- {sensor_sdk-0.0.69 → sensor_sdk-0.0.71}/README.md +0 -0
- {sensor_sdk-0.0.69 → sensor_sdk-0.0.71}/sensor/__init__.py +0 -0
- {sensor_sdk-0.0.69 → sensor_sdk-0.0.71}/sensor/bleak_host.py +0 -0
- {sensor_sdk-0.0.69 → sensor_sdk-0.0.71}/sensor/sensor_controller.py +0 -0
- {sensor_sdk-0.0.69 → sensor_sdk-0.0.71}/sensor/sensor_device.py +0 -0
- {sensor_sdk-0.0.69 → sensor_sdk-0.0.71}/sensor/sensor_profile.py +0 -0
- {sensor_sdk-0.0.69 → sensor_sdk-0.0.71}/sensor/sensor_utils.py +0 -0
- {sensor_sdk-0.0.69 → sensor_sdk-0.0.71}/sensor_sdk.egg-info/SOURCES.txt +0 -0
- {sensor_sdk-0.0.69 → sensor_sdk-0.0.71}/sensor_sdk.egg-info/dependency_links.txt +0 -0
- {sensor_sdk-0.0.69 → sensor_sdk-0.0.71}/sensor_sdk.egg-info/requires.txt +0 -0
- {sensor_sdk-0.0.69 → sensor_sdk-0.0.71}/sensor_sdk.egg-info/top_level.txt +0 -0
- {sensor_sdk-0.0.69 → sensor_sdk-0.0.71}/sensor_sdk.egg-info/zip-safe +0 -0
- {sensor_sdk-0.0.69 → sensor_sdk-0.0.71}/setup.cfg +0 -0
|
@@ -96,7 +96,7 @@ class BleakProcess(multiprocessing.Process):
|
|
|
96
96
|
self._gforce_event_loop = None
|
|
97
97
|
self._gforce_event_thread = None
|
|
98
98
|
|
|
99
|
-
#
|
|
99
|
+
# Message types that can be dropped when the result queue is full.
|
|
100
100
|
_DROPABLE_MSG_TYPES = ("sensor_data", "devices", "scan_once_result", "error")
|
|
101
101
|
|
|
102
102
|
def _publish(self, msg_type: str, **kwargs):
|
|
@@ -104,16 +104,16 @@ class BleakProcess(multiprocessing.Process):
|
|
|
104
104
|
try:
|
|
105
105
|
msg = {"type": msg_type, **kwargs}
|
|
106
106
|
|
|
107
|
-
#
|
|
107
|
+
# Memory guard: prevent the internal message queue from growing without bound.
|
|
108
108
|
if self._msg_queue.qsize() > sensor_utils.BLEAK_RESULT_QUEUE_MAXSIZE:
|
|
109
109
|
if msg_type in self._DROPABLE_MSG_TYPES:
|
|
110
110
|
return
|
|
111
|
-
#
|
|
111
|
+
# For non-droppable messages, try to evict one old droppable message.
|
|
112
112
|
try:
|
|
113
113
|
old_msg = self._msg_queue.get_nowait()
|
|
114
114
|
old_type = old_msg.get("type")
|
|
115
115
|
if old_type not in self._DROPABLE_MSG_TYPES:
|
|
116
|
-
#
|
|
116
|
+
# If the oldest message is also non-droppable, put it back.
|
|
117
117
|
self._msg_queue.put_nowait(old_msg)
|
|
118
118
|
except queue.Empty:
|
|
119
119
|
pass
|
|
@@ -123,7 +123,7 @@ class BleakProcess(multiprocessing.Process):
|
|
|
123
123
|
try:
|
|
124
124
|
self._msg_queue.put_nowait(msg)
|
|
125
125
|
except queue.Full:
|
|
126
|
-
#
|
|
126
|
+
# If still full, use a short blocking put for important messages.
|
|
127
127
|
if msg_type not in self._DROPABLE_MSG_TYPES:
|
|
128
128
|
try:
|
|
129
129
|
self._msg_queue.put(msg, timeout=1.0)
|
|
@@ -142,12 +142,12 @@ class BleakProcess(multiprocessing.Process):
|
|
|
142
142
|
if msg_type in self._DROPABLE_MSG_TYPES:
|
|
143
143
|
self.result_queue.put_nowait(msg)
|
|
144
144
|
else:
|
|
145
|
-
#
|
|
145
|
+
# Use a short timeout during shutdown so the child process can exit cleanly.
|
|
146
146
|
self.result_queue.put(msg, timeout=2.0)
|
|
147
147
|
except queue.Empty:
|
|
148
148
|
break
|
|
149
149
|
except queue.Full:
|
|
150
|
-
#
|
|
150
|
+
# Drop one old droppable message to make room for important messages.
|
|
151
151
|
try:
|
|
152
152
|
old_msg = self._msg_queue.get_nowait()
|
|
153
153
|
old_type = old_msg.get("type")
|
|
@@ -161,7 +161,7 @@ class BleakProcess(multiprocessing.Process):
|
|
|
161
161
|
break
|
|
162
162
|
|
|
163
163
|
async def _publisher_task(self):
|
|
164
|
-
#
|
|
164
|
+
# Throttle queue-full logs to avoid blocking stdout on Windows.
|
|
165
165
|
_last_queue_full_log = 0.0
|
|
166
166
|
|
|
167
167
|
while True:
|
|
@@ -173,7 +173,7 @@ class BleakProcess(multiprocessing.Process):
|
|
|
173
173
|
if msg_type in self._DROPABLE_MSG_TYPES:
|
|
174
174
|
self.result_queue.put_nowait(msg)
|
|
175
175
|
else:
|
|
176
|
-
#
|
|
176
|
+
# Use a short timeout for important messages so the publisher does not stall.
|
|
177
177
|
self.result_queue.put(msg, timeout=2.0)
|
|
178
178
|
except queue.Empty:
|
|
179
179
|
if self._should_exit:
|
|
@@ -182,15 +182,15 @@ class BleakProcess(multiprocessing.Process):
|
|
|
182
182
|
except queue.Full as e:
|
|
183
183
|
if msg is not None:
|
|
184
184
|
if msg_type not in self._DROPABLE_MSG_TYPES:
|
|
185
|
-
#
|
|
185
|
+
# Put important messages back so they can be retried later.
|
|
186
186
|
try:
|
|
187
187
|
self._msg_queue.put_nowait(msg)
|
|
188
188
|
except queue.Full:
|
|
189
189
|
pass
|
|
190
190
|
else:
|
|
191
|
-
#
|
|
191
|
+
# Droppable messages are discarded to avoid unbounded memory growth.
|
|
192
192
|
pass
|
|
193
|
-
#
|
|
193
|
+
# Log at most once every 2 seconds to prevent stdout flooding.
|
|
194
194
|
now = time.time()
|
|
195
195
|
if now - _last_queue_full_log >= 2.0:
|
|
196
196
|
_last_queue_full_log = now
|
|
@@ -157,6 +157,8 @@ class DataSubscription(IntEnum):
|
|
|
157
157
|
# Device Log On
|
|
158
158
|
LOG = (0x00000800,)
|
|
159
159
|
|
|
160
|
+
DNF_TYPE_GEST_EXT = (0x00001000,)
|
|
161
|
+
|
|
160
162
|
DNF_MAG_ANGLE_EXT = (0x00002000,)
|
|
161
163
|
|
|
162
164
|
DNF_EEG = (0x00010000,)
|
|
@@ -505,8 +507,8 @@ class GForce:
|
|
|
505
507
|
try:
|
|
506
508
|
q.put_nowait(bytes(bs))
|
|
507
509
|
except queue.Full:
|
|
508
|
-
#
|
|
509
|
-
#
|
|
510
|
+
# Drop only a few oldest items instead of clearing the whole queue
|
|
511
|
+
# to avoid losing too many raw data packets at once.
|
|
510
512
|
dropped = 0
|
|
511
513
|
while dropped < 16 and not q.empty():
|
|
512
514
|
try:
|
|
@@ -579,7 +581,7 @@ class GForce:
|
|
|
579
581
|
try:
|
|
580
582
|
q.put_nowait(bytes(bs))
|
|
581
583
|
except queue.Full:
|
|
582
|
-
#
|
|
584
|
+
# Drop only a few oldest items instead of clearing the whole queue.
|
|
583
585
|
dropped = 0
|
|
584
586
|
while dropped < 16 and not q.empty():
|
|
585
587
|
try:
|
|
@@ -1,105 +1,103 @@
|
|
|
1
|
-
from enum import Enum, IntEnum
|
|
2
|
-
from typing import Dict, List
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
class Sample:
|
|
8
|
-
# """
|
|
9
|
-
# Initialize a Sample instance.
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
# """
|
|
17
|
-
# def __init__(self, data: int, impedance: int, saturation: int, sample_index: int, is_lost: bool):
|
|
18
|
-
# self.data = data
|
|
19
|
-
# self.impedance = impedance
|
|
20
|
-
# self.saturation = saturation
|
|
21
|
-
# self.sampleIndex = sample_index
|
|
22
|
-
# self.isLost = is_lost
|
|
23
|
-
|
|
24
|
-
def __init__(self):
|
|
25
|
-
self.rawData = 0
|
|
26
|
-
self.data = 0
|
|
27
|
-
self.impedance = 0
|
|
28
|
-
self.saturation = 0
|
|
29
|
-
self.sampleIndex = 0
|
|
30
|
-
self.isLost = False
|
|
31
|
-
self.timeStampInMs = 0
|
|
32
|
-
self.channelIndex = 0
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
class DataType(IntEnum):
|
|
38
|
-
NTF_ACC = 0x1
|
|
39
|
-
NTF_GYRO = 0x2
|
|
40
|
-
NTF_EULER_DATA = 0x4
|
|
41
|
-
NTF_QUATERNION = 0x5
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
NTF_SPO2 = 0x17
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
#
|
|
61
|
-
|
|
62
|
-
# :param
|
|
63
|
-
# :param
|
|
64
|
-
# :param
|
|
65
|
-
# :param
|
|
66
|
-
#
|
|
67
|
-
#
|
|
68
|
-
#
|
|
69
|
-
#
|
|
70
|
-
#
|
|
71
|
-
# self.
|
|
72
|
-
# self.
|
|
73
|
-
# self.
|
|
74
|
-
# self.
|
|
75
|
-
# self.
|
|
76
|
-
# self.
|
|
77
|
-
# self.
|
|
78
|
-
# self.
|
|
79
|
-
# self.
|
|
80
|
-
# self.
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
self.
|
|
86
|
-
self.
|
|
87
|
-
self.
|
|
88
|
-
self.
|
|
89
|
-
self.
|
|
90
|
-
self.
|
|
91
|
-
self.
|
|
92
|
-
self.
|
|
93
|
-
self.
|
|
94
|
-
self.
|
|
95
|
-
self.
|
|
96
|
-
self.
|
|
97
|
-
self.
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
self.
|
|
103
|
-
self.
|
|
104
|
-
self.lastPackageIndex = 0
|
|
105
|
-
self.lostPackageCount = 0
|
|
1
|
+
from enum import Enum, IntEnum
|
|
2
|
+
from typing import Dict, List
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class Sample:
|
|
8
|
+
# """
|
|
9
|
+
# Initialize a Sample instance.
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
# """
|
|
17
|
+
# def __init__(self, data: int, impedance: int, saturation: int, sample_index: int, is_lost: bool):
|
|
18
|
+
# self.data = data
|
|
19
|
+
# self.impedance = impedance
|
|
20
|
+
# self.saturation = saturation
|
|
21
|
+
# self.sampleIndex = sample_index
|
|
22
|
+
# self.isLost = is_lost
|
|
23
|
+
|
|
24
|
+
def __init__(self):
|
|
25
|
+
self.rawData = 0
|
|
26
|
+
self.data = 0
|
|
27
|
+
self.impedance = 0
|
|
28
|
+
self.saturation = 0
|
|
29
|
+
self.sampleIndex = 0
|
|
30
|
+
self.isLost = False
|
|
31
|
+
self.timeStampInMs = 0
|
|
32
|
+
self.channelIndex = 0
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class DataType(IntEnum):
|
|
38
|
+
NTF_ACC = 0x1
|
|
39
|
+
NTF_GYRO = 0x2
|
|
40
|
+
NTF_EULER_DATA = 0x4
|
|
41
|
+
NTF_QUATERNION = 0x5
|
|
42
|
+
NTF_GEST = 0x07
|
|
43
|
+
NTF_EMG = 0x8
|
|
44
|
+
NTF_MAG_ANGLE_DATA = 0x0D
|
|
45
|
+
NTF_EEG = 0x10
|
|
46
|
+
NTF_ECG = 0x11
|
|
47
|
+
NTF_IMPEDANCE = 0x12
|
|
48
|
+
NTF_IMU = 0x13
|
|
49
|
+
NTF_ADS = 0x14
|
|
50
|
+
NTF_BRTH = 0x15
|
|
51
|
+
NTF_IMPEDANCE_EXT = 0x16
|
|
52
|
+
NTF_SPO2 = 0x17
|
|
53
|
+
NTF_PPG = 0x18
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
class SensorData:
|
|
57
|
+
# """
|
|
58
|
+
# Initialize a SensorData instance.
|
|
59
|
+
|
|
60
|
+
# :param device_mac: The MAC address of the device.
|
|
61
|
+
# :param data_type: The type of data being collected.
|
|
62
|
+
# :param sample_rate: The rate at which samples are collected.
|
|
63
|
+
# :param channel_count: The number of channels in the data.
|
|
64
|
+
# :param package_sample_count: The number of samples in the package.
|
|
65
|
+
# :param channel_samples: A list of lists containing the sample data for each channel.
|
|
66
|
+
# """
|
|
67
|
+
# def __init__(self, device_mac: str, data_type: DataType, sample_rate: int, channel_count: int,
|
|
68
|
+
# package_sample_count: int, channel_samples: List[List[Sample]]):
|
|
69
|
+
# self.deviceMac = device_mac
|
|
70
|
+
# self.dataType = data_type
|
|
71
|
+
# self.sampleRate = sample_rate
|
|
72
|
+
# self.channelCount = channel_count
|
|
73
|
+
# self.packageSampleCount = package_sample_count
|
|
74
|
+
# self.channelSamples = channel_samples
|
|
75
|
+
# self.lastPackageCounter = 0
|
|
76
|
+
# self.lastPackageIndex = 0
|
|
77
|
+
# self.resolutionBits = 0
|
|
78
|
+
# self.channelMask = 0
|
|
79
|
+
# self.minPackageSampleCount = 0
|
|
80
|
+
# self.K = 0
|
|
81
|
+
|
|
82
|
+
def __init__(self):
|
|
83
|
+
self.deviceMac = ""
|
|
84
|
+
self.dataType = DataType.NTF_EEG
|
|
85
|
+
self.sampleRate = 0
|
|
86
|
+
self.channelCount = 0
|
|
87
|
+
self.packageSampleCount = 0
|
|
88
|
+
self.packageIndexLength = 2
|
|
89
|
+
self.channelSamples: List[List[Sample]] = list()
|
|
90
|
+
self.lastPackageCounter = 0
|
|
91
|
+
self.lastPackageIndex = 0
|
|
92
|
+
self.lostPackageCount = 0
|
|
93
|
+
self.resolutionBits = 0
|
|
94
|
+
self.resolutionSigned = 0
|
|
95
|
+
self.channelMask = 0
|
|
96
|
+
self.minPackageSampleCount = 0
|
|
97
|
+
self.K = 0
|
|
98
|
+
|
|
99
|
+
def clear(self):
|
|
100
|
+
self.channelSamples.clear()
|
|
101
|
+
self.lastPackageCounter = -1
|
|
102
|
+
self.lastPackageIndex = 0
|
|
103
|
+
self.lostPackageCount = 0
|