sensor-sdk 0.0.16__tar.gz → 0.0.27__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: sensor-sdk
3
- Version: 0.0.16
3
+ Version: 0.0.27
4
4
  Summary: Python sdk for Synchroni
5
5
  Home-page: https://github.com/oymotion/SynchroniSDKPython
6
6
  Author: Martin Ye
@@ -92,10 +92,10 @@ isScanning = SensorControllerInstance.isScanning
92
92
 
93
93
  ### 5. Check if bluetooth is enabled
94
94
 
95
- Use `property isEnabled: bool` to check if bluetooth is enabled
95
+ Use `property isEnable: bool` to check if bluetooth is enable
96
96
 
97
97
  ```python
98
- isEnabled = SensorControllerInstance.isEnabled
98
+ isEnable = SensorControllerInstance.isEnable
99
99
  ```
100
100
 
101
101
  ### 6. Create SensorProfile
@@ -81,10 +81,10 @@ isScanning = SensorControllerInstance.isScanning
81
81
 
82
82
  ### 5. Check if bluetooth is enabled
83
83
 
84
- Use `property isEnabled: bool` to check if bluetooth is enabled
84
+ Use `property isEnable: bool` to check if bluetooth is enable
85
85
 
86
86
  ```python
87
- isEnabled = SensorControllerInstance.isEnabled
87
+ isEnable = SensorControllerInstance.isEnable
88
88
  ```
89
89
 
90
90
  ### 6. Create SensorProfile
@@ -16,7 +16,7 @@ from bleak import (
16
16
  BleakGATTCharacteristic,
17
17
  )
18
18
 
19
- from sensor import utils
19
+ from sensor import sensor_utils
20
20
 
21
21
 
22
22
  @dataclass
@@ -377,6 +377,7 @@ class GForce:
377
377
  self.client = None
378
378
  self.cmd_char = cmd_char
379
379
  self.data_char = data_char
380
+ self.current_request: Request = None
380
381
  self.responses: Dict[Command, Queue] = {}
381
382
  self.resolution = SampleResolution.BITS_8
382
383
  self._num_channels = 8
@@ -393,7 +394,7 @@ class GForce:
393
394
  self._raw_data_buf = buf
394
395
 
395
396
  try:
396
- await asyncio.wait_for(client.connect(), utils._TIMEOUT)
397
+ await asyncio.wait_for(client.connect(), sensor_utils._TIMEOUT)
397
398
  except Exception as e:
398
399
  return
399
400
 
@@ -404,12 +405,12 @@ class GForce:
404
405
  if not self._is_universal_stream:
405
406
  await asyncio.wait_for(
406
407
  client.start_notify(self.cmd_char, self._on_cmd_response),
407
- utils._TIMEOUT,
408
+ sensor_utils._TIMEOUT,
408
409
  )
409
410
  else:
410
411
  await asyncio.wait_for(
411
412
  client.start_notify(self.data_char, self._on_universal_response),
412
- utils._TIMEOUT,
413
+ sensor_utils._TIMEOUT,
413
414
  )
414
415
  except Exception as e:
415
416
  return
@@ -565,11 +566,14 @@ class GForce:
565
566
 
566
567
  def _on_cmd_response(self, _: BleakGATTCharacteristic, bs: bytearray):
567
568
  try:
569
+ # print(bytes(bs))
568
570
  response = self._parse_response(bytes(bs))
569
- if response.cmd in self.responses:
571
+ if self.responses.get(response.cmd) != None:
570
572
  self.responses[response.cmd].put_nowait(
571
573
  response.data,
572
574
  )
575
+ else:
576
+ print("invalid response:" + bytes(bs))
573
577
  except Exception as e:
574
578
  raise Exception("Failed to parse response: %s" % e)
575
579
 
@@ -859,17 +863,17 @@ class GForce:
859
863
  self.data_char,
860
864
  lambda _, data: self._on_data_response(q, data),
861
865
  ),
862
- utils._TIMEOUT,
866
+ sensor_utils._TIMEOUT,
863
867
  )
864
868
 
865
869
  async def stop_streaming(self):
866
870
  exceptions = []
867
871
  # try:
868
- # await asyncio.wait_for(self.set_subscription(DataSubscription.OFF), utils._TIMEOUT)
872
+ # await asyncio.wait_for(self.set_subscription(DataSubscription.OFF), sensor_utils._TIMEOUT)
869
873
  # except Exception as e:
870
874
  # exceptions.append(e)
871
875
  try:
872
- await asyncio.wait_for(self.client.stop_notify(self.data_char), utils._TIMEOUT)
876
+ await asyncio.wait_for(self.client.stop_notify(self.data_char), sensor_utils._TIMEOUT)
873
877
  except Exception as e:
874
878
  exceptions.append(e)
875
879
 
@@ -879,29 +883,49 @@ class GForce:
879
883
  async def disconnect(self):
880
884
  with suppress(asyncio.CancelledError):
881
885
  try:
882
- await asyncio.wait_for(self.client.disconnect(), utils._TIMEOUT)
886
+ await asyncio.wait_for(self.client.disconnect(), sensor_utils._TIMEOUT)
883
887
  except Exception as e:
884
888
  pass
885
889
 
886
890
  def _get_response_channel(self, cmd: Command) -> Queue:
891
+ if self.responses.get(cmd) != None:
892
+ return None
893
+
887
894
  q = Queue()
888
895
  self.responses[cmd] = q
889
896
  return q
890
897
 
891
898
  async def _send_request(self, req: Request) -> Optional[bytes]:
899
+
892
900
  q = None
893
901
  if req.has_res:
894
902
  q = self._get_response_channel(req.cmd)
903
+ if q == None:
904
+ # print("duplicate")
905
+ return None
906
+
907
+ while self.current_request != None:
908
+ # print("wait")
909
+ await asyncio.sleep(0.1)
895
910
 
911
+ self.current_request = req
896
912
  bs = bytes([req.cmd])
897
913
  if req.body is not None:
898
914
  bs += req.body
899
- await asyncio.wait_for(self.client.write_gatt_char(self.cmd_char, bs), utils._TIMEOUT)
915
+
916
+ # print(str(req.cmd) + str(req.body))
917
+ await asyncio.wait_for(self.client.write_gatt_char(self.cmd_char, bs, response=False), 0.1)
900
918
 
901
919
  if not req.has_res:
920
+ self.current_request = None
902
921
  return None
903
922
 
904
923
  try:
905
- return await asyncio.wait_for(q.get(), utils._TIMEOUT)
924
+ ret = await asyncio.wait_for(q.get(), 0.5)
925
+ self.current_request = None
926
+ self.responses[req.cmd] = None
927
+ return ret
906
928
  except Exception as e:
929
+ self.current_request = None
930
+ self.responses[req.cmd] = None
907
931
  return None
@@ -6,10 +6,10 @@ from typing import Callable, Dict, List, Optional, Tuple
6
6
  import bleak
7
7
 
8
8
  from sensor import sensor_profile
9
- from sensor import utils
9
+ from sensor import sensor_utils
10
10
  from sensor.sensor_profile import DeviceStateEx, SensorProfile
11
11
 
12
- from sensor.utils import async_call, sync_call, async_exec
12
+ from sensor.sensor_utils import async_call, sync_call, async_exec
13
13
  from bleak import (
14
14
  BleakScanner,
15
15
  AdvertisementData,
@@ -52,13 +52,13 @@ class SensorController:
52
52
  """
53
53
 
54
54
  def terminate(self):
55
- utils._terminated = True
55
+ sensor_utils._terminated = True
56
56
 
57
57
  for sensor in self._sensor_profiles.values():
58
58
  if sensor.deviceState == DeviceStateEx.Connected or sensor.deviceState == DeviceStateEx.Ready:
59
59
  sensor._destroy()
60
60
 
61
- utils.Terminate()
61
+ sensor_utils.Terminate()
62
62
 
63
63
  def _match_device(self, _device: bleak.BLEDevice, adv: AdvertisementData):
64
64
  if _device.name == None:
@@ -71,7 +71,7 @@ class SensorController:
71
71
  return False
72
72
 
73
73
  @property
74
- def isScaning(self) -> bool:
74
+ def isScanning(self) -> bool:
75
75
  """
76
76
  检查是否正在扫描。
77
77
 
@@ -181,13 +181,13 @@ class SensorController:
181
181
  return await async_call(self._async_scan(period))
182
182
 
183
183
  async def _device_scan_callback(self, devices: List[sensor_profile.BLEDevice]):
184
- if self._device_callback:
184
+ if not sensor_utils._terminated and self._device_callback:
185
185
  try:
186
186
  asyncio.get_event_loop().run_in_executor(None, self._device_callback, devices)
187
187
  except Exception as e:
188
188
  print(e)
189
189
 
190
- if self._is_scanning:
190
+ if not sensor_utils._terminated and self._is_scanning:
191
191
  async_exec(self._startScan())
192
192
 
193
193
  async def _startScan(self) -> bool:
@@ -7,7 +7,7 @@ import struct
7
7
  from typing import Deque, List
8
8
  from concurrent.futures import ThreadPoolExecutor
9
9
  import csv
10
- from sensor import utils
10
+ from sensor import sensor_utils
11
11
  from sensor.gforce import DataSubscription, GForce, SamplingRate
12
12
  from sensor.sensor_data import DataType, Sample, SensorData
13
13
 
@@ -351,7 +351,7 @@ class SensorProfileDataCtx:
351
351
  switch |= 8
352
352
  try:
353
353
  await self.gForce.set_firmware_filter_switch(switch)
354
- await asyncio.sleep(0.1)
354
+ # await asyncio.sleep(0.1)
355
355
  return "OK"
356
356
  except Exception as e:
357
357
  return "ERROR: " + str(e)
@@ -391,7 +391,7 @@ class SensorProfileDataCtx:
391
391
  sensorData = buf.get_nowait()
392
392
  except Exception as e:
393
393
  break
394
- if sensorData != None and callback != None:
394
+ if not sensor_utils._terminated and sensorData != None and callback != None:
395
395
  try:
396
396
  asyncio.get_event_loop().run_in_executor(self.dataPool, callback, sensor, sensorData)
397
397
  except Exception as e:
@@ -459,6 +459,8 @@ class SensorProfileDataCtx:
459
459
  offset += 2
460
460
  newPackageIndex = packageIndex
461
461
  lastPackageIndex = sensorData.lastPackageIndex
462
+ if sensorData.lastPackageCounter == 0 and sensorData.lastPackageIndex == 0 and packageIndex > 1:
463
+ return False
462
464
 
463
465
  if packageIndex < lastPackageIndex:
464
466
  packageIndex += 65536 # 包索引是 U16 类型
@@ -477,7 +479,7 @@ class SensorProfileDataCtx:
477
479
  + str(lostSampleCount)
478
480
  )
479
481
  # print(lostLog)
480
- if sensor._event_loop != None and sensor._on_error_callback != None:
482
+ if not sensor_utils._terminated and sensor._event_loop != None and sensor._on_error_callback != None:
481
483
  try:
482
484
  asyncio.get_event_loop().run_in_executor(None, sensor._on_error_callback, sensor, lostLog)
483
485
  except Exception as e:
@@ -699,7 +701,7 @@ class SensorProfileDataCtx:
699
701
  index += 1
700
702
  continue
701
703
  crc = self._concatDataBuffer[index + 1 + n + 1]
702
- calc_crc = utils.calc_crc8(self._concatDataBuffer[index + 2 : index + 2 + n])
704
+ calc_crc = sensor_utils.calc_crc8(self._concatDataBuffer[index + 2 : index + 2 + n])
703
705
  if crc != calc_crc:
704
706
  index += 1
705
707
  continue
@@ -712,7 +714,7 @@ class SensorProfileDataCtx:
712
714
  sensorData = buf.get_nowait()
713
715
  except Exception as e:
714
716
  break
715
- if sensorData != None and callback != None:
717
+ if not sensor_utils._terminated and sensorData != None and callback != None:
716
718
  try:
717
719
  asyncio.get_event_loop().run_in_executor(self.dataPool, callback, sensor, sensorData)
718
720
  except Exception as e:
@@ -730,12 +732,13 @@ class SensorProfileDataCtx:
730
732
  index += 1
731
733
  continue
732
734
  crc = self._concatDataBuffer[index + 1 + n + 1]
733
- calc_crc = utils.calc_crc8(self._concatDataBuffer[index + 2 : index + 2 + n])
735
+ calc_crc = sensor_utils.calc_crc8(self._concatDataBuffer[index + 2 : index + 2 + n])
734
736
  if crc != calc_crc:
735
737
  index += 1
736
738
  continue
737
739
  data_package = bytes(self._concatDataBuffer[index + 2 : index + 2 + n])
738
- asyncio.get_event_loop().run_in_executor(None, self.gForce._on_cmd_response, None, data_package)
740
+ if not sensor_utils._terminated:
741
+ self.gForce._on_cmd_response(None, data_package)
739
742
  last_cut = index = index + 2 + n
740
743
 
741
744
  else:
@@ -2,6 +2,7 @@
2
2
  # 该枚举类定义了设备的各种状态,用于表示设备在不同操作阶段的状态信息
3
3
  from enum import Enum, IntEnum
4
4
  from queue import Queue
5
+ import threading
5
6
  import time
6
7
  from typing import Callable, Optional
7
8
 
@@ -10,7 +11,7 @@ from bleak import (
10
11
  BleakClient,
11
12
  )
12
13
 
13
- from sensor import utils
14
+ from sensor import sensor_utils
14
15
  from sensor.gforce import GForce
15
16
  from sensor.sensor_data import SensorData
16
17
  import asyncio
@@ -18,7 +19,7 @@ import asyncio
18
19
 
19
20
  from sensor.sensor_data_context import SensorProfileDataCtx
20
21
  from sensor.sensor_device import BLEDevice, DeviceInfo, DeviceStateEx
21
- from sensor.utils import async_call, sync_call, async_exec
22
+ from sensor.sensor_utils import async_call, sync_call, async_exec
22
23
 
23
24
  SERVICE_GUID = "0000ffd0-0000-1000-8000-00805f9b34fb"
24
25
  OYM_CMD_NOTIFY_CHAR_UUID = "f000ffe1-0451-4000-b000-000000000000"
@@ -60,7 +61,9 @@ class SensorProfile:
60
61
  self._data_ctx: SensorProfileDataCtx = None
61
62
  self._gforce: GForce = None
62
63
  self._data_event_loop: asyncio.AbstractEventLoop = None
64
+ self._data_event_thread: threading.Thread = None
63
65
  self._event_loop: asyncio.AbstractEventLoop = None
66
+ self._event_thread: threading.Thread = None
64
67
  self._is_starting = False
65
68
  self._is_setting_param = False
66
69
 
@@ -211,15 +214,7 @@ class SensorProfile:
211
214
  """
212
215
  self._on_power_changed = callback
213
216
 
214
- async def _connect(self) -> bool:
215
- if utils._terminated:
216
- return False
217
-
218
- if self._event_loop == None:
219
- self._event_loop = asyncio.new_event_loop()
220
- self._data_buffer: Queue[SensorData] = Queue()
221
- self._raw_data_buf: Queue[bytes] = Queue()
222
-
217
+ async def _initGforce(self):
223
218
  if self._gforce == None:
224
219
  if self._adv.service_data.get(SERVICE_GUID) != None:
225
220
  # print("OYM_SERVICE:" + self._detail_device.name)
@@ -240,25 +235,41 @@ class SensorProfile:
240
235
  if self._data_ctx == None and self._gforce != None:
241
236
  self._data_ctx = SensorProfileDataCtx(self._gforce, self._device.Address, self._raw_data_buf)
242
237
  if self._data_ctx.isUniversalStream:
243
- async_exec(self._process_universal_data())
238
+ async_exec(self._process_universal_data(), self._event_loop)
244
239
  else:
245
- async_exec(self._process_data())
240
+ async_exec(self._process_data(), self._event_loop)
241
+
242
+ async def _connect(self) -> bool:
243
+ if sensor_utils._terminated:
244
+ return False
245
+
246
+ if self._event_loop == None:
247
+ self._event_loop = asyncio.new_event_loop()
248
+ self._event_thread = threading.Thread(target=sensor_utils.start_loop, args=(self._event_loop,))
249
+ self._event_thread.daemon = True
250
+ self._event_thread.name = self._detail_device.name + "event"
251
+ self._event_thread.start()
252
+ self._data_buffer: Queue[SensorData] = Queue()
253
+ self._raw_data_buf: Queue[bytes] = Queue()
246
254
 
247
255
  if self.deviceState == DeviceStateEx.Connected or self.deviceState == DeviceStateEx.Ready:
248
256
  return True
257
+
249
258
  self._set_device_state(DeviceStateEx.Connecting)
250
259
 
260
+ await async_call(self._initGforce(), runloop=self._event_loop)
261
+
251
262
  def handle_disconnect(_: BleakClient):
252
263
  if self._data_ctx != None:
253
264
  self._data_ctx.close()
254
- time.sleep(1)
265
+ time.sleep(0.2)
255
266
  self._data_buffer.queue.clear()
256
267
  self._data_ctx = None
257
268
  self._gforce = None
258
269
  self._set_device_state(DeviceStateEx.Disconnected)
259
270
  pass
260
271
 
261
- await self._gforce.connect(handle_disconnect, self._raw_data_buf)
272
+ await async_call(self._gforce.connect(handle_disconnect, self._raw_data_buf), runloop=self._event_loop)
262
273
 
263
274
  if self._gforce != None and self._gforce.client.is_connected:
264
275
  self._set_device_state(DeviceStateEx.Connected)
@@ -292,8 +303,8 @@ class SensorProfile:
292
303
  return await async_call(self._connect())
293
304
 
294
305
  async def _waitForDisconnect(self) -> bool:
295
- while not utils._terminated and self.deviceState != DeviceStateEx.Disconnected:
296
- await asyncio.sleep(1)
306
+ while not sensor_utils._terminated and self.deviceState != DeviceStateEx.Disconnected:
307
+ await asyncio.sleep(0.1)
297
308
  return True
298
309
 
299
310
  async def _disconnect(self) -> bool:
@@ -302,8 +313,8 @@ class SensorProfile:
302
313
  if self._data_ctx == None:
303
314
  return False
304
315
  self._set_device_state(DeviceStateEx.Disconnecting)
305
- await self._gforce.disconnect()
306
- await asyncio.wait_for(self._waitForDisconnect(), utils._TIMEOUT)
316
+ async_exec(self._gforce.disconnect(), self._event_loop)
317
+ await asyncio.wait_for(self._waitForDisconnect(), sensor_utils._TIMEOUT)
307
318
 
308
319
  return True
309
320
 
@@ -348,10 +359,9 @@ class SensorProfile:
348
359
  self._raw_data_buf.queue.clear()
349
360
  self._data_buffer.queue.clear()
350
361
 
351
- result = await self._data_ctx.start_streaming()
362
+ result = await async_call(self._data_ctx.start_streaming(), runloop=self._event_loop)
352
363
  await asyncio.sleep(0.2)
353
364
 
354
- self._is_starting = False
355
365
  return result
356
366
 
357
367
  def startDataNotification(self) -> bool:
@@ -364,8 +374,14 @@ class SensorProfile:
364
374
  if self._is_starting:
365
375
  return False
366
376
 
367
- self._is_starting = True
368
- return sync_call(self._startDataNotification())
377
+ try:
378
+ self._is_starting = True
379
+ ret = sync_call(self._startDataNotification())
380
+ self._is_starting = False
381
+ return ret
382
+ except Exception as e:
383
+ self._is_starting = False
384
+ print(e)
369
385
 
370
386
  async def asyncStartDataNotification(self) -> bool:
371
387
  """
@@ -377,8 +393,14 @@ class SensorProfile:
377
393
  if self._is_starting:
378
394
  return False
379
395
 
380
- self._is_starting = True
381
- return await async_call(self._startDataNotification())
396
+ try:
397
+ self._is_starting = True
398
+ ret = await async_call(self._startDataNotification())
399
+ self._is_starting = False
400
+ return ret
401
+ except Exception as e:
402
+ self._is_starting = False
403
+ print(e)
382
404
 
383
405
  async def _stopDataNotification(self) -> bool:
384
406
  if self.deviceState != DeviceStateEx.Ready:
@@ -391,9 +413,8 @@ class SensorProfile:
391
413
  if not self._data_ctx.isDataTransfering:
392
414
  return True
393
415
 
394
- result = await self._data_ctx.stop_streaming()
395
- self._is_starting = False
396
- return not result
416
+ result = await async_call(self._data_ctx.stop_streaming(), runloop=self._event_loop)
417
+ return result
397
418
 
398
419
  def stopDataNotification(self) -> bool:
399
420
  """
@@ -405,8 +426,14 @@ class SensorProfile:
405
426
  if self._is_starting:
406
427
  return False
407
428
 
408
- self._is_starting = True
409
- return sync_call(self._stopDataNotification())
429
+ try:
430
+ self._is_starting = True
431
+ ret = sync_call(self._stopDataNotification())
432
+ self._is_starting = False
433
+ return ret
434
+ except Exception as e:
435
+ self._is_starting = False
436
+ print(e)
410
437
 
411
438
  async def asyncStopDataNotification(self) -> bool:
412
439
  """
@@ -418,16 +445,22 @@ class SensorProfile:
418
445
  if self._is_starting:
419
446
  return False
420
447
 
421
- self._is_starting = True
422
- return await async_call(self._stopDataNotification())
448
+ try:
449
+ self._is_starting = True
450
+ ret = await async_call(self._stopDataNotification())
451
+ self._is_starting = False
452
+ return ret
453
+ except Exception as e:
454
+ self._is_starting = False
455
+ print(e)
423
456
 
424
457
  async def _refresh_power(self):
425
- while not utils._terminated and self.deviceState == DeviceStateEx.Ready:
458
+ while not sensor_utils._terminated and self.deviceState == DeviceStateEx.Ready:
426
459
  await asyncio.sleep(self._power_interval / 1000)
427
460
 
428
461
  self._power = await self._gforce.get_battery_level()
429
462
 
430
- if self._event_loop != None and self._on_power_changed != None:
463
+ if not sensor_utils._terminated and self._event_loop != None and self._on_power_changed != None:
431
464
  try:
432
465
  asyncio.get_event_loop().run_in_executor(None, self._on_power_changed, self, self._power)
433
466
  except Exception as e:
@@ -443,7 +476,8 @@ class SensorProfile:
443
476
 
444
477
  if await self._data_ctx.init(packageSampleCount):
445
478
  self._power_interval = powerRefreshInterval
446
- utils.async_exec(self._refresh_power())
479
+ self._power = await self._gforce.get_battery_level()
480
+ sensor_utils.async_exec(self._refresh_power())
447
481
 
448
482
  return self._data_ctx.hasInit()
449
483
 
@@ -477,6 +511,23 @@ class SensorProfile:
477
511
  20,
478
512
  )
479
513
 
514
+ async def _asyncGetBatteryLevel(self) -> int:
515
+ if self.deviceState != DeviceStateEx.Ready:
516
+ return -1
517
+ if self._data_ctx == None:
518
+ return -1
519
+ self._power = await self._gforce.get_battery_level()
520
+ return self._power
521
+
522
+ async def asyncGetBatteryLevel(self) -> int:
523
+ """
524
+ 获取传感器的电池电量。
525
+
526
+ :return: int: 传感器的电池电量。 正常0-100,-1为未知。
527
+
528
+ """
529
+ return await async_call(self._asyncGetBatteryLevel())
530
+
480
531
  def getBatteryLevel(self) -> int:
481
532
  """
482
533
  获取传感器的电池电量。
@@ -509,18 +560,7 @@ class SensorProfile:
509
560
 
510
561
  if key in ["FILTER_50Hz", "FILTER_60Hz", "FILTER_HPF", "FILTER_LPF"]:
511
562
  if value in ["ON", "OFF"]:
512
- needPauseTransfer = self.isDataTransfering
513
- if needPauseTransfer:
514
- if self._is_starting:
515
- self._is_setting_param = False
516
- return "Error: Please pause data transfer first"
517
-
518
- self._is_starting = True
519
- await self._stopDataNotification()
520
563
  result = await self._data_ctx.setFilter(key, value)
521
- if needPauseTransfer:
522
- self._is_starting = True
523
- await self._startDataNotification()
524
564
 
525
565
  if key == "DEBUG_BLE_DATA_PATH":
526
566
  result = await self._data_ctx.setDebugCSV(value)
@@ -15,7 +15,7 @@ _needCloseRunloop = False
15
15
 
16
16
  def checkRunLoop():
17
17
  global _runloop, _needCloseRunloop, _event_thread
18
- if _runloop == None:
18
+ if _runloop == None or not _runloop.is_running():
19
19
  try:
20
20
  _runloop = asyncio.get_running_loop()
21
21
  except Exception as e:
@@ -25,10 +25,18 @@ def checkRunLoop():
25
25
  _event_thread.daemon = True
26
26
  _event_thread.name = "SensorController event"
27
27
  _event_thread.start()
28
+ time.sleep(0.1)
28
29
 
29
30
 
30
31
  def Terminate():
31
- global _runloop, _needCloseRunloop, _event_thread
32
+ global _runloop, _needCloseRunloop, _event_thread, _terminated
33
+ _terminated = True
34
+ try:
35
+ for task in asyncio.all_tasks():
36
+ task.cancel()
37
+ except Exception as e:
38
+ pass
39
+
32
40
  if _needCloseRunloop:
33
41
  try:
34
42
  _runloop.stop()
@@ -37,11 +45,13 @@ def Terminate():
37
45
  pass
38
46
 
39
47
 
40
- def async_exec(function):
48
+ def async_exec(function, runloop=None):
41
49
  checkRunLoop()
50
+ if runloop == None:
51
+ runloop = _runloop
42
52
  task: asyncio.Future = None
43
53
  try:
44
- task = asyncio.run_coroutine_threadsafe(function, _runloop)
54
+ task = asyncio.run_coroutine_threadsafe(function, runloop)
45
55
  running_tasks.add(task)
46
56
  task.add_done_callback(lambda t: running_tasks.remove(t))
47
57
  except Exception as e:
@@ -49,11 +59,13 @@ def async_exec(function):
49
59
  pass
50
60
 
51
61
 
52
- def sync_call(function, _timeout=_TIMEOUT) -> any:
62
+ def sync_call(function, _timeout=_TIMEOUT, runloop=None) -> any:
53
63
  checkRunLoop()
54
64
  task: asyncio.Future = None
65
+ if runloop == None:
66
+ runloop = _runloop
55
67
  try:
56
- task = asyncio.run_coroutine_threadsafe(asyncio.wait_for(function, _timeout), _runloop)
68
+ task = asyncio.run_coroutine_threadsafe(asyncio.wait_for(function, _timeout), runloop)
57
69
  running_tasks.add(task)
58
70
  task.add_done_callback(lambda t: running_tasks.remove(t))
59
71
  return task.result(timeout=_timeout)
@@ -62,11 +74,13 @@ def sync_call(function, _timeout=_TIMEOUT) -> any:
62
74
  pass
63
75
 
64
76
 
65
- async def async_call(function, _timeout=_TIMEOUT) -> any:
77
+ async def async_call(function, _timeout=_TIMEOUT, runloop=None) -> any:
66
78
  checkRunLoop()
67
79
  task: asyncio.Future = None
80
+ if runloop == None:
81
+ runloop = _runloop
68
82
  try:
69
- task = asyncio.run_coroutine_threadsafe(asyncio.wait_for(function, _timeout), _runloop)
83
+ task = asyncio.run_coroutine_threadsafe(asyncio.wait_for(function, _timeout), runloop)
70
84
  running_tasks.add(task)
71
85
  task.add_done_callback(lambda t: running_tasks.remove(t))
72
86
  except Exception as e:
@@ -85,6 +99,7 @@ async def async_call(function, _timeout=_TIMEOUT) -> any:
85
99
 
86
100
 
87
101
  def start_loop(loop: asyncio.BaseEventLoop):
102
+ # asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
88
103
  asyncio.set_event_loop(loop)
89
104
  loop.run_forever()
90
105
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: sensor-sdk
3
- Version: 0.0.16
3
+ Version: 0.0.27
4
4
  Summary: Python sdk for Synchroni
5
5
  Home-page: https://github.com/oymotion/SynchroniSDKPython
6
6
  Author: Martin Ye
@@ -92,10 +92,10 @@ isScanning = SensorControllerInstance.isScanning
92
92
 
93
93
  ### 5. Check if bluetooth is enabled
94
94
 
95
- Use `property isEnabled: bool` to check if bluetooth is enabled
95
+ Use `property isEnable: bool` to check if bluetooth is enable
96
96
 
97
97
  ```python
98
- isEnabled = SensorControllerInstance.isEnabled
98
+ isEnable = SensorControllerInstance.isEnable
99
99
  ```
100
100
 
101
101
  ### 6. Create SensorProfile
@@ -8,7 +8,7 @@ sensor/sensor_data.py
8
8
  sensor/sensor_data_context.py
9
9
  sensor/sensor_device.py
10
10
  sensor/sensor_profile.py
11
- sensor/utils.py
11
+ sensor/sensor_utils.py
12
12
  sensor_sdk.egg-info/PKG-INFO
13
13
  sensor_sdk.egg-info/SOURCES.txt
14
14
  sensor_sdk.egg-info/dependency_links.txt
@@ -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.0.16",
11
+ version="0.0.27",
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