sensor-sdk 1.3.3__py3-none-win_amd64.whl

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.
@@ -0,0 +1,674 @@
1
+ import asyncio
2
+ import ctypes
3
+ import inspect
4
+ import threading
5
+ import traceback
6
+ from typing import Callable, Optional
7
+
8
+ from . import _dll
9
+ from . import _sync
10
+ from .sensor_data import SensorData
11
+ from .sensor_device import BLEDevice, DeviceInfo, DeviceStateEx
12
+
13
+ _sdk_thread_ids = set()
14
+ _sdk_thread_ids_lock = threading.Lock()
15
+
16
+ def _mark_sdk_thread():
17
+ with _sdk_thread_ids_lock:
18
+ _sdk_thread_ids.add(threading.get_ident())
19
+
20
+ def _is_sdk_thread() -> bool:
21
+ with _sdk_thread_ids_lock:
22
+ return threading.get_ident() in _sdk_thread_ids
23
+
24
+ def _raise_on_sdk_thread():
25
+ if _is_sdk_thread():
26
+ raise RuntimeError("blocking sync call from an SDK callback thread")
27
+
28
+ def _decode_str(raw) -> str:
29
+ if not raw:
30
+ return ""
31
+ return raw.decode("utf-8", errors="replace") if isinstance(raw, bytes) else str(raw)
32
+
33
+ def _resolve_future(loop, fut, value):
34
+ def _set():
35
+ if not fut.done():
36
+ fut.set_result(value)
37
+ try:
38
+ loop.call_soon_threadsafe(_set)
39
+ except Exception:
40
+ pass
41
+
42
+ def _ctx_self(ctx) -> "SensorProfile":
43
+ return ctypes.cast(ctx, ctypes.POINTER(ctypes.py_object)).contents.value
44
+
45
+ def _wrap_auto_reconnect_callback(callback):
46
+ if callback is None:
47
+ return None
48
+ try:
49
+ argc = len(inspect.signature(callback).parameters)
50
+ except (TypeError, ValueError):
51
+ argc = 3
52
+ if argc == 2:
53
+ def _wrapped(sensor, has_last_session, answer):
54
+ answer(bool(callback(sensor, has_last_session)))
55
+ return _wrapped
56
+ return callback
57
+
58
+ class SensorProfile:
59
+ def __init__(self, controller, handle):
60
+ self._controller = controller
61
+ self._handle = handle
62
+
63
+ self._on_error_callback: Optional[Callable[["SensorProfile", str], None]] = None
64
+ self._on_state_change: Optional[Callable[["SensorProfile", DeviceStateEx], None]] = None
65
+ self._on_sensor_notify_data: Optional[Callable[["SensorProfile", list], None]] = None
66
+ self._on_auto_reconnect: Optional[Callable[["SensorProfile", bool, Callable[[bool], None]], None]] = None
67
+ self._on_auto_reconnect_orig: Optional[Callable] = None
68
+ self._on_power_changed: Optional[Callable[["SensorProfile", int], None]] = None
69
+ self._on_device_info_update: Optional[Callable[["SensorProfile", DeviceInfo], None]] = None
70
+ self._on_data_transfer_state_change: Optional[Callable[["SensorProfile", bool], None]] = None
71
+
72
+ self._power = -1
73
+ self._auto_reconnect = False
74
+ self._device_info: Optional[DeviceInfo] = None
75
+ self._ble_device: Optional[BLEDevice] = None
76
+ self._pending_cbs = []
77
+
78
+ self._ctx = ctypes.py_object(self)
79
+ self._ctx_ptr = ctypes.cast(ctypes.pointer(self._ctx), ctypes.c_void_p)
80
+ self._c_on_data = _dll._sen_data_cb(SensorProfile._c_data)
81
+ self._c_on_state = _dll._sen_state_cb(SensorProfile._c_state)
82
+ self._c_on_error = _dll._sen_error_cb(SensorProfile._c_error)
83
+ self._c_on_power = _dll._sen_power_cb(SensorProfile._c_power)
84
+ self._c_on_auto_reconnect = _dll._sen_auto_reconnect_cb(SensorProfile._c_auto_reconnect)
85
+ self._c_on_device_info_update = _dll._sen_device_info_update_cb(SensorProfile._c_device_info_update)
86
+ self._c_on_data_transfer_state_change = _dll._sen_data_transfer_state_cb(SensorProfile._c_data_transfer_state_change)
87
+ self._cbs = _dll.sen_profile_cbs_t()
88
+ self._cbs.structSize = ctypes.sizeof(self._cbs)
89
+ self._cbs.onData = self._c_on_data
90
+ self._cbs.onStateChange = self._c_on_state
91
+ self._cbs.onError = self._c_on_error
92
+ self._cbs.onPowerChange = self._c_on_power
93
+ self._cbs.onAutoReconnect = self._c_on_auto_reconnect
94
+ self._cbs.onDeviceInfoUpdate = self._c_on_device_info_update
95
+ self._cbs.onDataTransferStateChange = self._c_on_data_transfer_state_change
96
+ _dll.load_dll().sen_profile_set_callbacks(
97
+ self._handle, ctypes.byref(self._cbs), self._ctx_ptr)
98
+
99
+ @staticmethod
100
+ def _c_data(ctx, profile, views, view_count):
101
+ _mark_sdk_thread()
102
+ try:
103
+ self = _ctx_self(ctx)
104
+ cb = self._on_sensor_notify_data
105
+ if cb is None or view_count == 0:
106
+ return
107
+ data_list = [SensorProfile._copy_view(views[i]) for i in range(view_count)]
108
+ cb(self, data_list)
109
+ except Exception:
110
+ traceback.print_exc()
111
+
112
+ @staticmethod
113
+ def _c_state(ctx, profile, new_state):
114
+ _mark_sdk_thread()
115
+ try:
116
+ self = _ctx_self(ctx)
117
+ if new_state == DeviceStateEx.Disconnected.value:
118
+ self._device_info = None
119
+ self._ble_device = None
120
+ self._power = -1
121
+ cb = self._on_state_change
122
+ if cb is not None:
123
+ cb(self, DeviceStateEx(new_state))
124
+ except Exception:
125
+ traceback.print_exc()
126
+
127
+ @staticmethod
128
+ def _c_error(ctx, profile, error_msg):
129
+ _mark_sdk_thread()
130
+ try:
131
+ self = _ctx_self(ctx)
132
+ cb = self._on_error_callback
133
+ if cb is not None:
134
+ cb(self, _decode_str(error_msg))
135
+ except Exception:
136
+ traceback.print_exc()
137
+
138
+ @staticmethod
139
+ def _c_power(ctx, profile, power):
140
+ _mark_sdk_thread()
141
+ try:
142
+ self = _ctx_self(ctx)
143
+ if power >= 0:
144
+ self._power = power
145
+ cb = self._on_power_changed
146
+ if cb is not None:
147
+ cb(self, power)
148
+ except Exception:
149
+ traceback.print_exc()
150
+
151
+ @staticmethod
152
+ def _c_auto_reconnect(ctx, profile, has_last_session, answer, answer_ctx):
153
+ _mark_sdk_thread()
154
+ answered = False
155
+
156
+ def _answer(handled: bool):
157
+ nonlocal answered
158
+ if answered:
159
+ return
160
+ answered = True
161
+ answer(answer_ctx, 1 if handled else 0)
162
+
163
+ try:
164
+ self = _ctx_self(ctx)
165
+ cb = self._on_auto_reconnect
166
+ if cb is None:
167
+ _answer(False)
168
+ return
169
+ cb(self, has_last_session != 0, _answer)
170
+ except Exception:
171
+ traceback.print_exc()
172
+ try:
173
+ _answer(False)
174
+ except Exception:
175
+ traceback.print_exc()
176
+
177
+ @staticmethod
178
+ def _c_device_info_update(ctx, profile, info):
179
+ _mark_sdk_thread()
180
+ try:
181
+ self = _ctx_self(ctx)
182
+ if info:
183
+ self._device_info = DeviceInfo._from_c(info.contents)
184
+ cb = self._on_device_info_update
185
+ if cb is not None and self._device_info is not None:
186
+ cb(self, self._device_info)
187
+ except Exception:
188
+ traceback.print_exc()
189
+
190
+ @staticmethod
191
+ def _c_data_transfer_state_change(ctx, profile, is_transferring):
192
+ _mark_sdk_thread()
193
+ try:
194
+ self = _ctx_self(ctx)
195
+ cb = self._on_data_transfer_state_change
196
+ if cb is not None:
197
+ cb(self, is_transferring != 0)
198
+ except Exception:
199
+ traceback.print_exc()
200
+
201
+ @staticmethod
202
+ def _copy_view(view) -> SensorData:
203
+ sd = SensorData()
204
+ info_addr = ctypes.cast(view.info, ctypes.c_void_p).value
205
+ sd._info = ctypes.cast(info_addr, ctypes.POINTER(_dll.sen_data_info_t)) if info_addr else None
206
+ sd._startSampleIndex = view.startSampleIndex
207
+ sd._view_start_time_stamp = view.startTimeStamp
208
+ samples_addr = ctypes.cast(view.samples, ctypes.c_void_p).value
209
+ if samples_addr and view.samplesBytes > 0:
210
+ sd._buf = (ctypes.c_char * view.samplesBytes).from_address(samples_addr)
211
+ return sd
212
+
213
+ @property
214
+ def on_error_callback(self):
215
+ return self._on_error_callback
216
+
217
+ @on_error_callback.setter
218
+ def on_error_callback(self, callback):
219
+ self._on_error_callback = callback
220
+
221
+ @property
222
+ def on_state_change(self):
223
+ return self._on_state_change
224
+
225
+ @on_state_change.setter
226
+ def on_state_change(self, callback):
227
+ self._on_state_change = callback
228
+
229
+ @property
230
+ def on_sensor_notify_data(self):
231
+ return self._on_sensor_notify_data
232
+
233
+ @on_sensor_notify_data.setter
234
+ def on_sensor_notify_data(self, callback):
235
+ self._on_sensor_notify_data = callback
236
+
237
+ @property
238
+ def on_auto_reconnect(self):
239
+ return self._on_auto_reconnect_orig
240
+
241
+ @on_auto_reconnect.setter
242
+ def on_auto_reconnect(self, callback):
243
+ self._on_auto_reconnect_orig = callback
244
+ self._on_auto_reconnect = _wrap_auto_reconnect_callback(callback)
245
+
246
+ @property
247
+ def onAutoReconnect(self):
248
+ return self._on_auto_reconnect_orig
249
+
250
+ @onAutoReconnect.setter
251
+ def onAutoReconnect(self, callback):
252
+ self._on_auto_reconnect_orig = callback
253
+ self._on_auto_reconnect = _wrap_auto_reconnect_callback(callback)
254
+
255
+ @property
256
+ def on_power_changed(self):
257
+ return self._on_power_changed
258
+
259
+ @on_power_changed.setter
260
+ def on_power_changed(self, callback):
261
+ self._on_power_changed = callback
262
+
263
+ @property
264
+ def on_device_info_update(self):
265
+ return self._on_device_info_update
266
+
267
+ @on_device_info_update.setter
268
+ def on_device_info_update(self, callback):
269
+ self._on_device_info_update = callback
270
+
271
+ @property
272
+ def on_data_transfer_state_change(self):
273
+ return self._on_data_transfer_state_change
274
+
275
+ @on_data_transfer_state_change.setter
276
+ def on_data_transfer_state_change(self, callback):
277
+ self._on_data_transfer_state_change = callback
278
+
279
+ @property
280
+ def onStateChanged(self):
281
+ return self._on_state_change
282
+
283
+ @onStateChanged.setter
284
+ def onStateChanged(self, callback):
285
+ self._on_state_change = callback
286
+
287
+ @property
288
+ def onErrorCallback(self):
289
+ return self._on_error_callback
290
+
291
+ @onErrorCallback.setter
292
+ def onErrorCallback(self, callback):
293
+ self._on_error_callback = callback
294
+
295
+ @property
296
+ def onDataCallback(self):
297
+ return self._on_sensor_notify_data
298
+
299
+ @onDataCallback.setter
300
+ def onDataCallback(self, callback):
301
+ self._on_sensor_notify_data = callback
302
+
303
+ @property
304
+ def onPowerChanged(self):
305
+ return self._on_power_changed
306
+
307
+ @onPowerChanged.setter
308
+ def onPowerChanged(self, callback):
309
+ self._on_power_changed = callback
310
+
311
+ @property
312
+ def onDeviceInfoUpdate(self):
313
+ return self._on_device_info_update
314
+
315
+ @onDeviceInfoUpdate.setter
316
+ def onDeviceInfoUpdate(self, callback):
317
+ self._on_device_info_update = callback
318
+
319
+ @property
320
+ def onDataTransferStateChange(self):
321
+ return self._on_data_transfer_state_change
322
+
323
+ @onDataTransferStateChange.setter
324
+ def onDataTransferStateChange(self, callback):
325
+ self._on_data_transfer_state_change = callback
326
+
327
+ @property
328
+ def autoReconnect(self) -> bool:
329
+ return self._auto_reconnect
330
+
331
+ @autoReconnect.setter
332
+ def autoReconnect(self, enabled: bool):
333
+ self.setAutoReconnect(enabled)
334
+ self._auto_reconnect = bool(enabled)
335
+
336
+ @property
337
+ def BLEDevice(self) -> BLEDevice:
338
+ if self._ble_device is None:
339
+ dev = _dll.sen_ble_device_t()
340
+ _dll.load_dll().sen_profile_get_device(self._handle, ctypes.byref(dev))
341
+ self._ble_device = BLEDevice._from_c(dev)
342
+ return self._ble_device
343
+
344
+ @property
345
+ def deviceState(self) -> DeviceStateEx:
346
+ return DeviceStateEx(_dll.load_dll().sen_profile_get_state(self._handle))
347
+
348
+ @property
349
+ def isReady(self) -> bool:
350
+ return self.deviceState == DeviceStateEx.Ready
351
+
352
+ @property
353
+ def hasInited(self) -> bool:
354
+ return _dll.load_dll().sen_profile_has_init(self._handle) != 0
355
+
356
+ @property
357
+ def isDataTransfering(self) -> bool:
358
+ return _dll.load_dll().sen_profile_has_start_data_notification(self._handle) != 0
359
+
360
+ def _track(self, cb_obj):
361
+ self._pending_cbs.append(cb_obj)
362
+ return cb_obj
363
+
364
+ def _discard(self, cb_obj):
365
+ try:
366
+ self._pending_cbs.remove(cb_obj)
367
+ except ValueError:
368
+ pass
369
+
370
+ def _connect(self, cb: Optional[Callable[[bool, str], None]] = None):
371
+ @_dll._sen_completion_cb
372
+ def _cb(ctx, result, errorMsg):
373
+ _mark_sdk_thread()
374
+ try:
375
+ if cb is not None:
376
+ cb(result != 0, _decode_str(errorMsg))
377
+ finally:
378
+ self._discard(_cb)
379
+ self._track(_cb)
380
+ _dll.load_dll().sen_profile_connect(self._handle, _cb, None)
381
+
382
+ def _disconnect(self, cb: Optional[Callable[[bool, str], None]] = None):
383
+ @_dll._sen_completion_cb
384
+ def _cb(ctx, result, errorMsg):
385
+ _mark_sdk_thread()
386
+ try:
387
+ if cb is not None:
388
+ cb(result != 0, _decode_str(errorMsg))
389
+ finally:
390
+ self._discard(_cb)
391
+ self._track(_cb)
392
+ _dll.load_dll().sen_profile_disconnect(self._handle, _cb, None)
393
+
394
+ def setAutoReconnect(self, enabled: bool):
395
+ _dll.load_dll().sen_profile_set_auto_reconnect(self._handle, 1 if enabled else 0)
396
+
397
+ def _init(self, packageSampleCount: int, powerRefreshInterval: int,
398
+ timeoutInMS: int, cb: Callable[[bool, str], None]):
399
+ @_dll._sen_completion_cb
400
+ def _cb(ctx, result, errorMsg):
401
+ _mark_sdk_thread()
402
+ try:
403
+ if cb is not None:
404
+ cb(result != 0, _decode_str(errorMsg))
405
+ finally:
406
+ self._discard(_cb)
407
+ self._track(_cb)
408
+ _dll.load_dll().sen_profile_init(
409
+ self._handle, packageSampleCount, timeoutInMS, powerRefreshInterval, _cb, None)
410
+
411
+ def _startDataNotification(self, timeoutInMS: int, cb: Callable[[bool, str], None]):
412
+ @_dll._sen_completion_cb
413
+ def _cb(ctx, result, errorMsg):
414
+ _mark_sdk_thread()
415
+ try:
416
+ if cb is not None:
417
+ cb(result != 0, _decode_str(errorMsg))
418
+ finally:
419
+ self._discard(_cb)
420
+ self._track(_cb)
421
+ _dll.load_dll().sen_profile_start_data(self._handle, timeoutInMS, _cb, None)
422
+
423
+ def _stopDataNotification(self, timeoutInMS: int, cb: Callable[[bool, str], None]):
424
+ @_dll._sen_completion_cb
425
+ def _cb(ctx, result, errorMsg):
426
+ _mark_sdk_thread()
427
+ try:
428
+ if cb is not None:
429
+ cb(result != 0, _decode_str(errorMsg))
430
+ finally:
431
+ self._discard(_cb)
432
+ self._track(_cb)
433
+ _dll.load_dll().sen_profile_stop_data(self._handle, timeoutInMS, _cb, None)
434
+
435
+ def _setParam(self, timeoutInMS: int, key: str, value: str,
436
+ cb: Callable[[str, str], None]):
437
+ @_dll._sen_param_cb
438
+ def _cb(ctx, result, errorMsg):
439
+ _mark_sdk_thread()
440
+ try:
441
+ if cb is not None:
442
+ cb(_decode_str(result), _decode_str(errorMsg))
443
+ finally:
444
+ self._discard(_cb)
445
+ self._track(_cb)
446
+ _dll.load_dll().sen_profile_set_param(
447
+ self._handle, timeoutInMS, key.encode(), value.encode(), _cb, None)
448
+
449
+ def _getParam(self, timeoutInMS: int, key: str, cb: Callable[[str, str], None]):
450
+ @_dll._sen_param_cb
451
+ def _cb(ctx, result, errorMsg):
452
+ _mark_sdk_thread()
453
+ try:
454
+ if cb is not None:
455
+ cb(_decode_str(result), _decode_str(errorMsg))
456
+ finally:
457
+ self._discard(_cb)
458
+ self._track(_cb)
459
+ _dll.load_dll().sen_profile_get_param(
460
+ self._handle, timeoutInMS, key.encode(), _cb, None)
461
+
462
+ def _getBatteryLevel(self, timeoutInMS: int, cb: Callable[[int, str], None]):
463
+ @_dll._sen_battery_cb
464
+ def _cb(ctx, result, errorMsg):
465
+ _mark_sdk_thread()
466
+ try:
467
+ if result >= 0:
468
+ self._power = result
469
+ if cb is not None:
470
+ cb(result, _decode_str(errorMsg))
471
+ finally:
472
+ self._discard(_cb)
473
+ self._track(_cb)
474
+ _dll.load_dll().sen_profile_get_battery_level(self._handle, timeoutInMS, _cb, None)
475
+
476
+ def _fetchDeviceInfo(self, timeoutInMS: int,
477
+ cb: Callable[[Optional[DeviceInfo], str], None]):
478
+ @_dll._sen_info_cb
479
+ def _cb(ctx, info, errorMsg):
480
+ _mark_sdk_thread()
481
+ try:
482
+ if cb is not None:
483
+ out = DeviceInfo._from_c(info.contents) if info else None
484
+ if out is not None:
485
+ self._device_info = out
486
+ cb(out, _decode_str(errorMsg))
487
+ finally:
488
+ self._discard(_cb)
489
+ self._track(_cb)
490
+ _dll.load_dll().sen_profile_fetch_device_info(self._handle, timeoutInMS, _cb, None)
491
+
492
+ def connect(self):
493
+ _raise_on_sdk_thread()
494
+ try:
495
+ return _sync.run_sync(self.asyncConnect(), 40.0)
496
+ except _sync.FuturesTimeoutError:
497
+ return False
498
+
499
+ def disconnect(self):
500
+ _raise_on_sdk_thread()
501
+ try:
502
+ return _sync.run_sync(self.asyncDisconnect(), 25.0)
503
+ except _sync.FuturesTimeoutError:
504
+ return None
505
+
506
+ def init(self, packageSampleCount: int, powerRefreshInterval: int,
507
+ timeoutInMS: int = 0):
508
+ _raise_on_sdk_thread()
509
+ try:
510
+ return _sync.run_sync(
511
+ self.asyncInit(packageSampleCount, powerRefreshInterval, timeoutInMS),
512
+ _sync.effective_timeout_ms(timeoutInMS) / 1000.0 + 15.0)
513
+ except _sync.FuturesTimeoutError:
514
+ return None
515
+
516
+ def startDataNotification(self, timeoutInMS: int = 0):
517
+ _raise_on_sdk_thread()
518
+ try:
519
+ return _sync.run_sync(self.asyncStartDataNotification(timeoutInMS),
520
+ _sync.effective_timeout_ms(timeoutInMS) / 1000.0 + 15.0)
521
+ except _sync.FuturesTimeoutError:
522
+ return None
523
+
524
+ def stopDataNotification(self, timeoutInMS: int = 0):
525
+ _raise_on_sdk_thread()
526
+ try:
527
+ return _sync.run_sync(self.asyncStopDataNotification(timeoutInMS),
528
+ _sync.effective_timeout_ms(timeoutInMS) / 1000.0 + 15.0)
529
+ except _sync.FuturesTimeoutError:
530
+ return None
531
+
532
+ def setParam(self, key: str, value, timeoutInMS: int = 0) -> str:
533
+ _raise_on_sdk_thread()
534
+ try:
535
+ return _sync.run_sync(self.asyncSetParam(key, value, timeoutInMS),
536
+ _sync.effective_timeout_ms(timeoutInMS) / 1000.0 + 15.0)
537
+ except _sync.FuturesTimeoutError:
538
+ return "Error: Timeout"
539
+
540
+ def getParam(self, key: str, timeoutInMS: int = 0) -> str:
541
+ _raise_on_sdk_thread()
542
+ try:
543
+ return _sync.run_sync(self.asyncGetParam(key, timeoutInMS),
544
+ _sync.effective_timeout_ms(timeoutInMS) / 1000.0 + 15.0)
545
+ except _sync.FuturesTimeoutError:
546
+ return "Error: Timeout"
547
+
548
+ def getBatteryLevel(self) -> int:
549
+ if self._power >= 0:
550
+ return self._power
551
+ _raise_on_sdk_thread()
552
+ try:
553
+ return _sync.run_sync(self.asyncGetBatteryLevel(),
554
+ _sync.effective_timeout_ms(0) / 1000.0 + 17.0)
555
+ except _sync.FuturesTimeoutError:
556
+ return -1
557
+
558
+ def fetchDeviceInfo(self, timeoutInMS: int = 0) -> Optional[DeviceInfo]:
559
+ _raise_on_sdk_thread()
560
+ try:
561
+ return _sync.run_sync(self.asyncFetchDeviceInfo(timeoutInMS),
562
+ _sync.effective_timeout_ms(timeoutInMS) / 1000.0 + 15.0)
563
+ except _sync.FuturesTimeoutError:
564
+ return None
565
+
566
+ def getDeviceInfo(self) -> Optional[DeviceInfo]:
567
+ if self._device_info is not None:
568
+ return self._device_info
569
+ info = _dll.sen_device_info_t()
570
+ info.structSize = ctypes.sizeof(info)
571
+ _dll.load_dll().sen_profile_get_device_info(self._handle, ctypes.byref(info))
572
+ out = DeviceInfo._from_c(info)
573
+ if not (out.DeviceName or out.ModelName):
574
+ return None
575
+ self._device_info = out
576
+ return out
577
+
578
+ def log(self, message: str, level: str = "I"):
579
+ try:
580
+ _dll.load_dll().sen_profile_log(
581
+ self._handle, str(message).encode(), str(level).encode())
582
+ except Exception:
583
+ traceback.print_exc()
584
+
585
+ async def asyncConnect(self) -> bool:
586
+ loop = asyncio.get_running_loop()
587
+ fut = loop.create_future()
588
+ self._connect(cb=lambda ok, err: _resolve_future(loop, fut, ok))
589
+ try:
590
+ return await asyncio.wait_for(fut, 30.0)
591
+ except asyncio.TimeoutError:
592
+ return False
593
+
594
+ async def asyncDisconnect(self) -> bool:
595
+ loop = asyncio.get_running_loop()
596
+ fut = loop.create_future()
597
+ self._disconnect(cb=lambda ok, err: _resolve_future(loop, fut, ok))
598
+ try:
599
+ return await asyncio.wait_for(fut, 15.0)
600
+ except asyncio.TimeoutError:
601
+ return False
602
+
603
+ async def asyncInit(self, packageSampleCount: int, powerRefreshInterval: int,
604
+ timeoutInMS: int = 0) -> bool:
605
+ loop = asyncio.get_running_loop()
606
+ fut = loop.create_future()
607
+ self._init(packageSampleCount, powerRefreshInterval, timeoutInMS,
608
+ cb=lambda ok, err: _resolve_future(loop, fut, ok))
609
+ try:
610
+ return await asyncio.wait_for(
611
+ fut, _sync.effective_timeout_ms(timeoutInMS) / 1000.0 + 5.0)
612
+ except asyncio.TimeoutError:
613
+ return False
614
+
615
+ async def asyncStartDataNotification(self, timeoutInMS: int = 0) -> bool:
616
+ loop = asyncio.get_running_loop()
617
+ fut = loop.create_future()
618
+ self._startDataNotification(timeoutInMS, cb=lambda ok, err: _resolve_future(loop, fut, ok))
619
+ try:
620
+ return await asyncio.wait_for(
621
+ fut, _sync.effective_timeout_ms(timeoutInMS) / 1000.0 + 5.0)
622
+ except asyncio.TimeoutError:
623
+ return False
624
+
625
+ async def asyncStopDataNotification(self, timeoutInMS: int = 0) -> bool:
626
+ loop = asyncio.get_running_loop()
627
+ fut = loop.create_future()
628
+ self._stopDataNotification(timeoutInMS, cb=lambda ok, err: _resolve_future(loop, fut, ok))
629
+ try:
630
+ return await asyncio.wait_for(
631
+ fut, _sync.effective_timeout_ms(timeoutInMS) / 1000.0 + 5.0)
632
+ except asyncio.TimeoutError:
633
+ return False
634
+
635
+ async def asyncGetBatteryLevel(self) -> int:
636
+ loop = asyncio.get_running_loop()
637
+ fut = loop.create_future()
638
+ self._getBatteryLevel(0, cb=lambda level, err: _resolve_future(loop, fut, level))
639
+ try:
640
+ return await asyncio.wait_for(
641
+ fut, _sync.effective_timeout_ms(0) / 1000.0 + 2.0)
642
+ except asyncio.TimeoutError:
643
+ return -1
644
+
645
+ async def asyncSetParam(self, key: str, value, timeoutInMS: int = 0) -> str:
646
+ loop = asyncio.get_running_loop()
647
+ fut = loop.create_future()
648
+ self._setParam(timeoutInMS, key, str(value),
649
+ cb=lambda res, err: _resolve_future(loop, fut, err if err and res in ('', 'Error') else res))
650
+ try:
651
+ return await asyncio.wait_for(
652
+ fut, _sync.effective_timeout_ms(timeoutInMS) / 1000.0 + 2.0)
653
+ except asyncio.TimeoutError:
654
+ return "Error: Timeout"
655
+
656
+ async def asyncGetParam(self, key: str, timeoutInMS: int = 0) -> str:
657
+ loop = asyncio.get_running_loop()
658
+ fut = loop.create_future()
659
+ self._getParam(timeoutInMS, key, cb=lambda res, err: _resolve_future(loop, fut, err if err and res in ('', 'Error') else res))
660
+ try:
661
+ return await asyncio.wait_for(
662
+ fut, _sync.effective_timeout_ms(timeoutInMS) / 1000.0 + 2.0)
663
+ except asyncio.TimeoutError:
664
+ return "Error: Timeout"
665
+
666
+ async def asyncFetchDeviceInfo(self, timeoutInMS: int = 0) -> Optional[DeviceInfo]:
667
+ loop = asyncio.get_running_loop()
668
+ fut = loop.create_future()
669
+ self._fetchDeviceInfo(timeoutInMS, cb=lambda info, err: _resolve_future(loop, fut, info))
670
+ try:
671
+ return await asyncio.wait_for(
672
+ fut, _sync.effective_timeout_ms(timeoutInMS) / 1000.0 + 5.0)
673
+ except asyncio.TimeoutError:
674
+ return None
@@ -0,0 +1,23 @@
1
+ Metadata-Version: 2.4
2
+ Name: sensor-sdk
3
+ Version: 1.3.3
4
+ Summary: Python sdk for Synchroni
5
+ Home-page: https://github.com/oymotion/SynchroniSDKPython
6
+ Author: Martin Ye
7
+ Author-email: yecq_82@hotmail.com
8
+ License: MIT
9
+ Classifier: Programming Language :: Python :: 3
10
+ Classifier: Operating System :: Microsoft :: Windows
11
+ Requires-Python: >=3.10
12
+ Requires-Dist: numpy
13
+ Dynamic: author
14
+ Dynamic: author-email
15
+ Dynamic: classifier
16
+ Dynamic: description
17
+ Dynamic: home-page
18
+ Dynamic: license
19
+ Dynamic: requires-dist
20
+ Dynamic: requires-python
21
+ Dynamic: summary
22
+
23
+ Pure-ctypes Python bindings over the SensorSDKCXX flat C API (drop-in replacement for the SensorSDKPython package), bundling the native sensor library and the frozen BLE helper (USB dongle backend).