sensor-sdk 0.2.2__tar.gz → 0.2.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.2.2/sensor_sdk.egg-info → sensor_sdk-0.2.4}/PKG-INFO +1 -1
- {sensor_sdk-0.2.2 → sensor_sdk-0.2.4}/sensor/bleak_process.py +4 -26
- {sensor_sdk-0.2.2 → sensor_sdk-0.2.4}/sensor/sensor_data_context.py +18 -6
- {sensor_sdk-0.2.2 → sensor_sdk-0.2.4}/sensor/sensor_profile.py +1 -34
- {sensor_sdk-0.2.2 → sensor_sdk-0.2.4/sensor_sdk.egg-info}/PKG-INFO +1 -1
- {sensor_sdk-0.2.2 → sensor_sdk-0.2.4}/setup.py +1 -1
- {sensor_sdk-0.2.2 → sensor_sdk-0.2.4}/LICENSE.txt +0 -0
- {sensor_sdk-0.2.2 → sensor_sdk-0.2.4}/README.md +0 -0
- {sensor_sdk-0.2.2 → sensor_sdk-0.2.4}/sensor/__init__.py +0 -0
- {sensor_sdk-0.2.2 → sensor_sdk-0.2.4}/sensor/bleak_host.py +0 -0
- {sensor_sdk-0.2.2 → sensor_sdk-0.2.4}/sensor/bleak_no_ack_patch.py +0 -0
- {sensor_sdk-0.2.2 → sensor_sdk-0.2.4}/sensor/fb/DataType.py +0 -0
- {sensor_sdk-0.2.2 → sensor_sdk-0.2.4}/sensor/fb/Sample.py +0 -0
- {sensor_sdk-0.2.2 → sensor_sdk-0.2.4}/sensor/fb/SensorData.py +0 -0
- {sensor_sdk-0.2.2 → sensor_sdk-0.2.4}/sensor/fb/__init__.py +0 -0
- {sensor_sdk-0.2.2 → sensor_sdk-0.2.4}/sensor/gforce.py +0 -0
- {sensor_sdk-0.2.2 → sensor_sdk-0.2.4}/sensor/sdk_log.py +0 -0
- {sensor_sdk-0.2.2 → sensor_sdk-0.2.4}/sensor/sensor_controller.py +0 -0
- {sensor_sdk-0.2.2 → sensor_sdk-0.2.4}/sensor/sensor_data.py +0 -0
- {sensor_sdk-0.2.2 → sensor_sdk-0.2.4}/sensor/sensor_data_pool.py +0 -0
- {sensor_sdk-0.2.2 → sensor_sdk-0.2.4}/sensor/sensor_device.py +0 -0
- {sensor_sdk-0.2.2 → sensor_sdk-0.2.4}/sensor/sensor_utils.py +0 -0
- {sensor_sdk-0.2.2 → sensor_sdk-0.2.4}/sensor/winrt_high_throughput.py +0 -0
- {sensor_sdk-0.2.2 → sensor_sdk-0.2.4}/sensor_sdk.egg-info/SOURCES.txt +0 -0
- {sensor_sdk-0.2.2 → sensor_sdk-0.2.4}/sensor_sdk.egg-info/dependency_links.txt +0 -0
- {sensor_sdk-0.2.2 → sensor_sdk-0.2.4}/sensor_sdk.egg-info/requires.txt +0 -0
- {sensor_sdk-0.2.2 → sensor_sdk-0.2.4}/sensor_sdk.egg-info/top_level.txt +0 -0
- {sensor_sdk-0.2.2 → sensor_sdk-0.2.4}/sensor_sdk.egg-info/zip-safe +0 -0
- {sensor_sdk-0.2.2 → sensor_sdk-0.2.4}/setup.cfg +0 -0
|
@@ -30,16 +30,6 @@ _MAX_RECONNECT_ATTEMPTS = 5
|
|
|
30
30
|
_RECONNECT_DELAY_SECONDS = 1.0
|
|
31
31
|
|
|
32
32
|
|
|
33
|
-
def _is_core_bluetooth(client) -> bool:
|
|
34
|
-
"""判断 bleak 当前是否使用 macOS CoreBluetooth 后端。"""
|
|
35
|
-
if client is None:
|
|
36
|
-
return False
|
|
37
|
-
backend = getattr(client, "_backend", None)
|
|
38
|
-
if backend is None:
|
|
39
|
-
return False
|
|
40
|
-
return "corebluetooth" in type(backend).__module__.lower()
|
|
41
|
-
|
|
42
|
-
|
|
43
33
|
def _extract_mac(_device: bleak.BLEDevice, adv: AdvertisementData) -> str:
|
|
44
34
|
|
|
45
35
|
mac = None
|
|
@@ -108,7 +98,6 @@ class BleakProcess(multiprocessing.Process):
|
|
|
108
98
|
self._data_tasks: dict = {} # mac -> asyncio.Task
|
|
109
99
|
self._battery_tasks: dict = {} # mac -> asyncio.Task
|
|
110
100
|
self._reconnect_info: dict = {} # mac -> {cmd, attempts, task, normal_disconnect}
|
|
111
|
-
self._restore_info: dict = {} # mac -> {package_sample_count, power_refresh_interval, streaming}
|
|
112
101
|
self._main_event_loop = None # BleakProcess 主事件循环
|
|
113
102
|
|
|
114
103
|
# Per-device event loops and threads
|
|
@@ -1352,26 +1341,15 @@ class BleakProcess(multiprocessing.Process):
|
|
|
1352
1341
|
|
|
1353
1342
|
if needs_restart or oym_needs_subscribe:
|
|
1354
1343
|
try:
|
|
1355
|
-
|
|
1356
|
-
# macOS CoreBluetooth 在流传输中 stop_notify 容易导致设备断开,
|
|
1357
|
-
# 因此 OYM 设备在 CoreBluetooth 后端上直接更新订阅掩码,不启停通知。
|
|
1358
|
-
oym_skip_stop_start = is_oym and _is_core_bluetooth(ctx.gForce.client)
|
|
1359
|
-
if oym_skip_stop_start:
|
|
1360
|
-
SdkLog.d(_TAG, f"OYM CoreBluetooth: skip stop/start, set subscription directly for {device_mac}")
|
|
1361
|
-
if was_streaming and not oym_skip_stop_start:
|
|
1344
|
+
if was_streaming:
|
|
1362
1345
|
await ctx.stop_streaming()
|
|
1363
|
-
if oym_needs_subscribe and
|
|
1346
|
+
if oym_needs_subscribe and ctx.getChipType() == BLEChipType.OYM:
|
|
1364
1347
|
await ctx.gForce.set_subscription(ctx.notifyDataFlag)
|
|
1365
|
-
if was_streaming
|
|
1348
|
+
if was_streaming:
|
|
1366
1349
|
await ctx.start_streaming()
|
|
1367
1350
|
except Exception as e:
|
|
1368
|
-
err_msg = str(e)
|
|
1369
1351
|
SdkLog.exception(_TAG, f"_do_set_param restart stream failed: {device_mac}")
|
|
1370
|
-
result = "ERROR: restart stream fail: " +
|
|
1371
|
-
# 如果是因为设备已经断开,直接触发自动重连
|
|
1372
|
-
if "disconnected" in err_msg.lower() or "not connected" in err_msg.lower():
|
|
1373
|
-
SdkLog.w(_TAG, f"Device disconnected during setParam restart, scheduling reconnect for {device_mac}")
|
|
1374
|
-
self._schedule_reconnect(device_mac)
|
|
1352
|
+
result = "ERROR: restart stream fail: " + str(e)
|
|
1375
1353
|
|
|
1376
1354
|
if key == "DEBUG_LOG_PATH":
|
|
1377
1355
|
try:
|
|
@@ -714,8 +714,10 @@ class SensorProfileDataCtx:
|
|
|
714
714
|
data.clear()
|
|
715
715
|
self.sensorDatas[SensorDataType.DATA_TYPE_EULER] = data
|
|
716
716
|
|
|
717
|
-
# EEG + OYM 设备默认不订阅 IMU
|
|
718
|
-
if not (self._chip_type == BLEChipType.OYM
|
|
717
|
+
# EEG + OYM 设备默认不订阅 IMU;带 PPG 的设备保留
|
|
718
|
+
if not (self._chip_type == BLEChipType.OYM
|
|
719
|
+
and self.hasEEG()
|
|
720
|
+
and not self.hasPPG()):
|
|
719
721
|
self.notifyDataFlag |= DataSubscription.DNF_IMU
|
|
720
722
|
if self._device_info is not None:
|
|
721
723
|
self._device_info.AccChannelCount = 3
|
|
@@ -872,8 +874,10 @@ class SensorProfileDataCtx:
|
|
|
872
874
|
self._device_info = info
|
|
873
875
|
await self.initDataTransfer(True)
|
|
874
876
|
|
|
875
|
-
# EEG + OYM 设备默认关闭 IMU
|
|
876
|
-
if self._chip_type == BLEChipType.OYM
|
|
877
|
+
# EEG + OYM 设备默认关闭 IMU;带 PPG 的设备保留 IMU 默认开启
|
|
878
|
+
if (self._chip_type == BLEChipType.OYM
|
|
879
|
+
and self.hasEEG()
|
|
880
|
+
and not self.hasPPG()):
|
|
877
881
|
self.notify_map["NTF_IMU"] = "OFF"
|
|
878
882
|
self.notify_map["NTF_GFORCE_ACC"] = "OFF"
|
|
879
883
|
self.notify_map["NTF_GFORCE_GYRO"] = "OFF"
|
|
@@ -1292,7 +1296,11 @@ class SensorProfileDataCtx:
|
|
|
1292
1296
|
if sensor_data is None or sensor_data.sampleRate <= 0:
|
|
1293
1297
|
return True
|
|
1294
1298
|
|
|
1295
|
-
self.checkReadSamples(data, sensor_data, 0, -1)
|
|
1299
|
+
res = self.checkReadSamples(data, sensor_data, 0, -1, on_error_callback)
|
|
1300
|
+
if res == ReadSamplesResult.Error:
|
|
1301
|
+
return False
|
|
1302
|
+
if res == ReadSamplesResult.Repeated:
|
|
1303
|
+
return True
|
|
1296
1304
|
sampleInterval = 1000.0 / sensor_data.sampleRate
|
|
1297
1305
|
lastSampleIndex = sensor_data.lastPackageCounter * sensor_data.packageSampleCount
|
|
1298
1306
|
sensor_data.channelSamples = []
|
|
@@ -1345,7 +1353,11 @@ class SensorProfileDataCtx:
|
|
|
1345
1353
|
return False
|
|
1346
1354
|
|
|
1347
1355
|
sensor_data = self.sensorDatas[SensorDataType.DATA_TYPE_IMPEDANCE]
|
|
1348
|
-
self.checkReadSamples(data, sensor_data, 0, -1, on_error_callback)
|
|
1356
|
+
res = self.checkReadSamples(data, sensor_data, 0, -1, on_error_callback)
|
|
1357
|
+
if res == ReadSamplesResult.Error:
|
|
1358
|
+
return False
|
|
1359
|
+
if res == ReadSamplesResult.Repeated:
|
|
1360
|
+
return True
|
|
1349
1361
|
sampleInterval = 1000.0 / sensor_data.sampleRate if sensor_data.sampleRate > 0 else 0
|
|
1350
1362
|
|
|
1351
1363
|
for index in range(channelCount):
|
|
@@ -93,11 +93,6 @@ class SensorProfile:
|
|
|
93
93
|
self._device_info: Optional[DeviceInfo] = None
|
|
94
94
|
self._chip_type: BLEChipType = BLEChipType.Unknown
|
|
95
95
|
|
|
96
|
-
# 异常断开后自动恢复流状态所需信息
|
|
97
|
-
self._last_init_args: Optional[tuple] = None # (packageSampleCount, powerRefreshInterval)
|
|
98
|
-
self._was_streaming_before_disconnect = False
|
|
99
|
-
self._auto_restoring = False
|
|
100
|
-
|
|
101
96
|
# 用于在独立线程中执行用户回调,避免阻塞 BLE/数据解析线程
|
|
102
97
|
# onDataCallback 使用单线程池,保证数据回调严格按到达顺序执行
|
|
103
98
|
self._callback_executor = ThreadPoolExecutor(max_workers=4)
|
|
@@ -227,8 +222,7 @@ class SensorProfile:
|
|
|
227
222
|
return self._device_state
|
|
228
223
|
|
|
229
224
|
def _set_device_state(self, newState: DeviceStateEx):
|
|
230
|
-
|
|
231
|
-
if old_state != newState:
|
|
225
|
+
if self._device_state != newState:
|
|
232
226
|
self._device_state = newState
|
|
233
227
|
if newState == DeviceStateEx.Disconnected:
|
|
234
228
|
self._has_inited = False
|
|
@@ -241,33 +235,6 @@ class SensorProfile:
|
|
|
241
235
|
SdkLog.e(_TAG, f"Error occurred while processing state change: {e}")
|
|
242
236
|
raise RuntimeError("Set device state %s fail: %s" % (self.BLEDevice.Name , e))
|
|
243
237
|
|
|
244
|
-
# 异常断开后重连成功,自动恢复 init + 数据流
|
|
245
|
-
if (newState == DeviceStateEx.Connected
|
|
246
|
-
and old_state == DeviceStateEx.Disconnected
|
|
247
|
-
and self._last_init_args is not None
|
|
248
|
-
and self._was_streaming_before_disconnect
|
|
249
|
-
and not self._auto_restoring):
|
|
250
|
-
SdkLog.i(_TAG, f"Auto-restoring stream state for {self._device_mac}")
|
|
251
|
-
threading.Thread(target=self._auto_restore, daemon=True).start()
|
|
252
|
-
|
|
253
|
-
def _auto_restore(self):
|
|
254
|
-
"""在异常断开后自动恢复 init 和数据流。"""
|
|
255
|
-
if self._auto_restoring:
|
|
256
|
-
return
|
|
257
|
-
self._auto_restoring = True
|
|
258
|
-
try:
|
|
259
|
-
package_sample_count, power_refresh_interval = self._last_init_args
|
|
260
|
-
SdkLog.i(_TAG, f"Auto-restore init for {self._device_mac}")
|
|
261
|
-
if self.init(package_sample_count, power_refresh_interval):
|
|
262
|
-
SdkLog.i(_TAG, f"Auto-restore start data notification for {self._device_mac}")
|
|
263
|
-
self.startDataNotification()
|
|
264
|
-
else:
|
|
265
|
-
SdkLog.w(_TAG, f"Auto-restore init failed for {self._device_mac}")
|
|
266
|
-
except Exception as e:
|
|
267
|
-
SdkLog.exception(_TAG, f"Auto-restore failed for {self._device_mac}: {e}")
|
|
268
|
-
finally:
|
|
269
|
-
self._auto_restoring = False
|
|
270
|
-
|
|
271
238
|
@property
|
|
272
239
|
def hasInited(self) -> bool:
|
|
273
240
|
|
|
@@ -8,7 +8,7 @@ with open(os.path.join(this_directory, "README.md"), "r", encoding="utf-8") as f
|
|
|
8
8
|
|
|
9
9
|
setup(
|
|
10
10
|
name="sensor-sdk",
|
|
11
|
-
version="0.2.
|
|
11
|
+
version="0.2.4",
|
|
12
12
|
description="Python sdk for Synchroni",
|
|
13
13
|
long_description=long_description,
|
|
14
14
|
long_description_content_type="text/markdown",
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|