sensor-sdk 0.0.15__py3-none-any.whl → 0.0.18__py3-none-any.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.
Potentially problematic release.
This version of sensor-sdk might be problematic. Click here for more details.
- sensor/gforce.py +21 -10
- sensor/sensor_controller.py +7 -7
- sensor/sensor_data.py +1 -0
- sensor/sensor_data_context.py +64 -21
- sensor/sensor_profile.py +9 -9
- sensor/{utils.py → sensor_utils.py} +10 -1
- {sensor_sdk-0.0.15.dist-info → sensor_sdk-0.0.18.dist-info}/METADATA +4 -4
- sensor_sdk-0.0.18.dist-info/RECORD +14 -0
- sensor_sdk-0.0.15.dist-info/RECORD +0 -14
- {sensor_sdk-0.0.15.dist-info → sensor_sdk-0.0.18.dist-info}/LICENSE.txt +0 -0
- {sensor_sdk-0.0.15.dist-info → sensor_sdk-0.0.18.dist-info}/WHEEL +0 -0
- {sensor_sdk-0.0.15.dist-info → sensor_sdk-0.0.18.dist-info}/top_level.txt +0 -0
- {sensor_sdk-0.0.15.dist-info → sensor_sdk-0.0.18.dist-info}/zip-safe +0 -0
sensor/gforce.py
CHANGED
|
@@ -16,7 +16,7 @@ from bleak import (
|
|
|
16
16
|
BleakGATTCharacteristic,
|
|
17
17
|
)
|
|
18
18
|
|
|
19
|
-
from sensor import
|
|
19
|
+
from sensor import sensor_utils
|
|
20
20
|
|
|
21
21
|
|
|
22
22
|
@dataclass
|
|
@@ -393,7 +393,7 @@ class GForce:
|
|
|
393
393
|
self._raw_data_buf = buf
|
|
394
394
|
|
|
395
395
|
try:
|
|
396
|
-
await asyncio.wait_for(client.connect(),
|
|
396
|
+
await asyncio.wait_for(client.connect(), sensor_utils._TIMEOUT)
|
|
397
397
|
except Exception as e:
|
|
398
398
|
return
|
|
399
399
|
|
|
@@ -404,12 +404,12 @@ class GForce:
|
|
|
404
404
|
if not self._is_universal_stream:
|
|
405
405
|
await asyncio.wait_for(
|
|
406
406
|
client.start_notify(self.cmd_char, self._on_cmd_response),
|
|
407
|
-
|
|
407
|
+
sensor_utils._TIMEOUT,
|
|
408
408
|
)
|
|
409
409
|
else:
|
|
410
410
|
await asyncio.wait_for(
|
|
411
411
|
client.start_notify(self.data_char, self._on_universal_response),
|
|
412
|
-
|
|
412
|
+
sensor_utils._TIMEOUT,
|
|
413
413
|
)
|
|
414
414
|
except Exception as e:
|
|
415
415
|
return
|
|
@@ -728,6 +728,17 @@ class GForce:
|
|
|
728
728
|
)
|
|
729
729
|
)
|
|
730
730
|
|
|
731
|
+
async def set_package_id(self, switchStatus):
|
|
732
|
+
body = [switchStatus == True]
|
|
733
|
+
body = bytes(body)
|
|
734
|
+
ret = await self._send_request(
|
|
735
|
+
Request(
|
|
736
|
+
cmd=Command.PACKAGE_ID_CONTROL,
|
|
737
|
+
body=body,
|
|
738
|
+
has_res=True,
|
|
739
|
+
)
|
|
740
|
+
)
|
|
741
|
+
|
|
731
742
|
async def set_log_level(self, logLevel):
|
|
732
743
|
body = [0xFF & logLevel]
|
|
733
744
|
body = bytes(body)
|
|
@@ -848,17 +859,17 @@ class GForce:
|
|
|
848
859
|
self.data_char,
|
|
849
860
|
lambda _, data: self._on_data_response(q, data),
|
|
850
861
|
),
|
|
851
|
-
|
|
862
|
+
sensor_utils._TIMEOUT,
|
|
852
863
|
)
|
|
853
864
|
|
|
854
865
|
async def stop_streaming(self):
|
|
855
866
|
exceptions = []
|
|
856
867
|
# try:
|
|
857
|
-
# await asyncio.wait_for(self.set_subscription(DataSubscription.OFF),
|
|
868
|
+
# await asyncio.wait_for(self.set_subscription(DataSubscription.OFF), sensor_utils._TIMEOUT)
|
|
858
869
|
# except Exception as e:
|
|
859
870
|
# exceptions.append(e)
|
|
860
871
|
try:
|
|
861
|
-
await asyncio.wait_for(self.client.stop_notify(self.data_char),
|
|
872
|
+
await asyncio.wait_for(self.client.stop_notify(self.data_char), sensor_utils._TIMEOUT)
|
|
862
873
|
except Exception as e:
|
|
863
874
|
exceptions.append(e)
|
|
864
875
|
|
|
@@ -868,7 +879,7 @@ class GForce:
|
|
|
868
879
|
async def disconnect(self):
|
|
869
880
|
with suppress(asyncio.CancelledError):
|
|
870
881
|
try:
|
|
871
|
-
await asyncio.wait_for(self.client.disconnect(),
|
|
882
|
+
await asyncio.wait_for(self.client.disconnect(), sensor_utils._TIMEOUT)
|
|
872
883
|
except Exception as e:
|
|
873
884
|
pass
|
|
874
885
|
|
|
@@ -885,12 +896,12 @@ class GForce:
|
|
|
885
896
|
bs = bytes([req.cmd])
|
|
886
897
|
if req.body is not None:
|
|
887
898
|
bs += req.body
|
|
888
|
-
await asyncio.wait_for(self.client.write_gatt_char(self.cmd_char, bs),
|
|
899
|
+
await asyncio.wait_for(self.client.write_gatt_char(self.cmd_char, bs), sensor_utils._TIMEOUT)
|
|
889
900
|
|
|
890
901
|
if not req.has_res:
|
|
891
902
|
return None
|
|
892
903
|
|
|
893
904
|
try:
|
|
894
|
-
return await asyncio.wait_for(q.get(),
|
|
905
|
+
return await asyncio.wait_for(q.get(), sensor_utils._TIMEOUT)
|
|
895
906
|
except Exception as e:
|
|
896
907
|
return None
|
sensor/sensor_controller.py
CHANGED
|
@@ -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
|
|
9
|
+
from sensor import sensor_utils
|
|
10
10
|
from sensor.sensor_profile import DeviceStateEx, SensorProfile
|
|
11
11
|
|
|
12
|
-
from sensor.
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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:
|
sensor/sensor_data.py
CHANGED
|
@@ -38,6 +38,7 @@ class Sample:
|
|
|
38
38
|
class DataType(IntEnum):
|
|
39
39
|
NTF_ACC = 0x1 # 加速度,用于标识加速度传感器采集的数据
|
|
40
40
|
NTF_GYRO = 0x2 # 陀螺仪,用于标识陀螺仪传感器采集的数据
|
|
41
|
+
NTF_EMG = 0x8 # EMG,用于标识肌电传感器采集的数据
|
|
41
42
|
NTF_EEG = 0x10 # EEG,用于标识脑电传感器采集的数据
|
|
42
43
|
NTF_ECG = 0x11 # ECG,用于标识心电传感器采集的数据
|
|
43
44
|
NTF_IMPEDANCE = (0x12,) # 阻抗数据
|
sensor/sensor_data_context.py
CHANGED
|
@@ -7,8 +7,8 @@ import struct
|
|
|
7
7
|
from typing import Deque, List
|
|
8
8
|
from concurrent.futures import ThreadPoolExecutor
|
|
9
9
|
import csv
|
|
10
|
-
from sensor import
|
|
11
|
-
from sensor.gforce import DataSubscription, GForce
|
|
10
|
+
from sensor import sensor_utils
|
|
11
|
+
from sensor.gforce import DataSubscription, GForce, SamplingRate
|
|
12
12
|
from sensor.sensor_data import DataType, Sample, SensorData
|
|
13
13
|
|
|
14
14
|
from enum import Enum, IntEnum
|
|
@@ -22,7 +22,8 @@ class SensorDataType(IntEnum):
|
|
|
22
22
|
DATA_TYPE_ACC = 2
|
|
23
23
|
DATA_TYPE_GYRO = 3
|
|
24
24
|
DATA_TYPE_BRTH = 4
|
|
25
|
-
|
|
25
|
+
DATA_TYPE_EMG = 5
|
|
26
|
+
DATA_TYPE_COUNT = 6
|
|
26
27
|
|
|
27
28
|
|
|
28
29
|
# 枚举 FeatureMaps 的 Python 实现
|
|
@@ -114,6 +115,31 @@ class SensorProfileDataCtx:
|
|
|
114
115
|
def hasConcatBLE(self):
|
|
115
116
|
return (self.featureMap & FeatureMaps.GFD_FEAT_CONCAT_BLE.value) != 0
|
|
116
117
|
|
|
118
|
+
async def initEMG(self, packageCount: int) -> int:
|
|
119
|
+
config = await self.gForce.get_emg_raw_data_config()
|
|
120
|
+
data = SensorData()
|
|
121
|
+
data.deviceMac = self.deviceMac
|
|
122
|
+
data.dataType = DataType.NTF_EMG
|
|
123
|
+
data.sampleRate = 500
|
|
124
|
+
data.resolutionBits = 0
|
|
125
|
+
data.channelCount = 8
|
|
126
|
+
data.channelMask = config.channel_mask
|
|
127
|
+
data.minPackageSampleCount = packageCount
|
|
128
|
+
data.packageSampleCount = 8
|
|
129
|
+
data.K = 4000000.0 / 8388607.0
|
|
130
|
+
data.clear()
|
|
131
|
+
self.sensorDatas[SensorDataType.DATA_TYPE_EMG] = data
|
|
132
|
+
self.notifyDataFlag |= DataSubscription.EMG_RAW
|
|
133
|
+
|
|
134
|
+
config.fs = SamplingRate.HZ_500
|
|
135
|
+
config.channel_mask = 255
|
|
136
|
+
config.resolution = 8
|
|
137
|
+
config.batch_len = 128
|
|
138
|
+
await self.gForce.set_emg_raw_data_config(config)
|
|
139
|
+
|
|
140
|
+
await self.gForce.set_package_id(True)
|
|
141
|
+
return data.channelCount
|
|
142
|
+
|
|
117
143
|
async def initEEG(self, packageCount: int) -> int:
|
|
118
144
|
config = await self.gForce.get_eeg_raw_data_config()
|
|
119
145
|
cap = await self.gForce.get_eeg_raw_data_cap()
|
|
@@ -234,23 +260,23 @@ class SensorProfileDataCtx:
|
|
|
234
260
|
if self.hasImpedance():
|
|
235
261
|
self.notifyDataFlag |= DataSubscription.DNF_IMPEDANCE
|
|
236
262
|
|
|
237
|
-
if self.
|
|
238
|
-
|
|
263
|
+
if self.hasEMG() and (self.init_map["NTF_EMG"] == "ON"):
|
|
264
|
+
info.EmgChannelCount = await self.initEMG(packageCount)
|
|
265
|
+
info.EmgSampleRate = self.sensorDatas[SensorDataType.DATA_TYPE_EMG].sampleRate
|
|
266
|
+
|
|
267
|
+
if self.hasEEG() and (self.init_map["NTF_EEG"] == "ON"):
|
|
239
268
|
info.EegChannelCount = await self.initEEG(packageCount)
|
|
240
269
|
info.EegSampleRate = self.sensorDatas[SensorDataType.DATA_TYPE_EEG].sampleRate
|
|
241
270
|
|
|
242
|
-
if self.hasECG()
|
|
243
|
-
# print("initECG")
|
|
271
|
+
if self.hasECG() and (self.init_map["NTF_ECG"] == "ON"):
|
|
244
272
|
info.EcgChannelCount = await self.initECG(packageCount)
|
|
245
273
|
info.EcgSampleRate = self.sensorDatas[SensorDataType.DATA_TYPE_ECG].sampleRate
|
|
246
274
|
|
|
247
|
-
if self.hasBrth()
|
|
248
|
-
# print("initBrth")
|
|
275
|
+
if self.hasBrth() and (self.init_map["NTF_BRTH"] == "ON"):
|
|
249
276
|
info.BrthChannelCount = await self.initBrth(packageCount)
|
|
250
277
|
info.BrthSampleRate = self.sensorDatas[SensorDataType.DATA_TYPE_BRTH].sampleRate
|
|
251
278
|
|
|
252
|
-
if self.hasIMU()
|
|
253
|
-
# print("initIMU")
|
|
279
|
+
if self.hasIMU() and (self.init_map["NTF_IMU"] == "ON"):
|
|
254
280
|
imuChannelCount = await self.initIMU(packageCount)
|
|
255
281
|
info.AccChannelCount = imuChannelCount
|
|
256
282
|
info.GyroChannelCount = imuChannelCount
|
|
@@ -365,7 +391,7 @@ class SensorProfileDataCtx:
|
|
|
365
391
|
sensorData = buf.get_nowait()
|
|
366
392
|
except Exception as e:
|
|
367
393
|
break
|
|
368
|
-
if sensorData != None and callback != None:
|
|
394
|
+
if not sensor_utils._terminated and sensorData != None and callback != None:
|
|
369
395
|
try:
|
|
370
396
|
asyncio.get_event_loop().run_in_executor(self.dataPool, callback, sensor, sensorData)
|
|
371
397
|
except Exception as e:
|
|
@@ -374,7 +400,7 @@ class SensorProfileDataCtx:
|
|
|
374
400
|
buf.task_done()
|
|
375
401
|
|
|
376
402
|
def _processDataPackage(self, data: bytes, buf: Queue[SensorData], sensor):
|
|
377
|
-
v = data[0]
|
|
403
|
+
v = data[0] & 0x7F
|
|
378
404
|
if v == DataType.NTF_IMPEDANCE:
|
|
379
405
|
offset = 1
|
|
380
406
|
# packageIndex = ((data[offset + 1] & 0xff) << 8) | (data[offset] & 0xff)
|
|
@@ -397,7 +423,10 @@ class SensorProfileDataCtx:
|
|
|
397
423
|
|
|
398
424
|
self.impedanceData = impedanceData
|
|
399
425
|
self.saturationData = saturationData
|
|
400
|
-
|
|
426
|
+
elif v == DataType.NTF_EMG:
|
|
427
|
+
sensor_data = self.sensorDatas[SensorDataType.DATA_TYPE_EMG]
|
|
428
|
+
if self.checkReadSamples(sensor, data, sensor_data, 3, 0):
|
|
429
|
+
self.sendSensorData(sensor_data, buf)
|
|
401
430
|
elif v == DataType.NTF_EEG:
|
|
402
431
|
sensor_data = self.sensorDatas[SensorDataType.DATA_TYPE_EEG]
|
|
403
432
|
if self.checkReadSamples(sensor, data, sensor_data, 3, 0):
|
|
@@ -421,7 +450,7 @@ class SensorProfileDataCtx:
|
|
|
421
450
|
|
|
422
451
|
def checkReadSamples(self, sensor, data: bytes, sensorData: SensorData, dataOffset: int, dataGap: int):
|
|
423
452
|
offset = 1
|
|
424
|
-
|
|
453
|
+
|
|
425
454
|
if not self._is_data_transfering:
|
|
426
455
|
return False
|
|
427
456
|
try:
|
|
@@ -430,6 +459,8 @@ class SensorProfileDataCtx:
|
|
|
430
459
|
offset += 2
|
|
431
460
|
newPackageIndex = packageIndex
|
|
432
461
|
lastPackageIndex = sensorData.lastPackageIndex
|
|
462
|
+
if sensorData.lastPackageCounter == 0 and sensorData.lastPackageIndex == 0 and packageIndex > 1:
|
|
463
|
+
return False
|
|
433
464
|
|
|
434
465
|
if packageIndex < lastPackageIndex:
|
|
435
466
|
packageIndex += 65536 # 包索引是 U16 类型
|
|
@@ -448,13 +479,14 @@ class SensorProfileDataCtx:
|
|
|
448
479
|
+ str(lostSampleCount)
|
|
449
480
|
)
|
|
450
481
|
# print(lostLog)
|
|
451
|
-
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:
|
|
452
483
|
try:
|
|
453
484
|
asyncio.get_event_loop().run_in_executor(None, sensor._on_error_callback, sensor, lostLog)
|
|
454
485
|
except Exception as e:
|
|
455
486
|
pass
|
|
487
|
+
if lostSampleCount < 100:
|
|
488
|
+
self.readSamples(data, sensorData, 0, dataGap, lostSampleCount)
|
|
456
489
|
|
|
457
|
-
self.readSamples(data, sensorData, 0, dataGap, lostSampleCount)
|
|
458
490
|
if newPackageIndex == 0:
|
|
459
491
|
sensorData.lastPackageIndex = 65535
|
|
460
492
|
else:
|
|
@@ -469,6 +501,12 @@ class SensorProfileDataCtx:
|
|
|
469
501
|
return False
|
|
470
502
|
return True
|
|
471
503
|
|
|
504
|
+
def transTrainData(self, data: int):
|
|
505
|
+
xout = data >> 4
|
|
506
|
+
exp = data & 0x0000000F
|
|
507
|
+
xout = xout << exp
|
|
508
|
+
return xout
|
|
509
|
+
|
|
472
510
|
def readSamples(
|
|
473
511
|
self,
|
|
474
512
|
data: bytes,
|
|
@@ -536,6 +574,10 @@ class SensorProfileDataCtx:
|
|
|
536
574
|
rawData = (data[offset] << 16) | (data[offset + 1] << 8) | data[offset + 2]
|
|
537
575
|
rawData -= 8388608
|
|
538
576
|
offset += 3
|
|
577
|
+
elif sensorData.resolutionBits == 0:
|
|
578
|
+
rawData = struct.unpack_from("<h", data, offset)[0]
|
|
579
|
+
offset += 2
|
|
580
|
+
rawData = self.transTrainData(rawData)
|
|
539
581
|
|
|
540
582
|
converted = rawData * K
|
|
541
583
|
dataItem.rawData = rawData
|
|
@@ -659,7 +701,7 @@ class SensorProfileDataCtx:
|
|
|
659
701
|
index += 1
|
|
660
702
|
continue
|
|
661
703
|
crc = self._concatDataBuffer[index + 1 + n + 1]
|
|
662
|
-
calc_crc =
|
|
704
|
+
calc_crc = sensor_utils.calc_crc8(self._concatDataBuffer[index + 2 : index + 2 + n])
|
|
663
705
|
if crc != calc_crc:
|
|
664
706
|
index += 1
|
|
665
707
|
continue
|
|
@@ -672,7 +714,7 @@ class SensorProfileDataCtx:
|
|
|
672
714
|
sensorData = buf.get_nowait()
|
|
673
715
|
except Exception as e:
|
|
674
716
|
break
|
|
675
|
-
if sensorData != None and callback != None:
|
|
717
|
+
if not sensor_utils._terminated and sensorData != None and callback != None:
|
|
676
718
|
try:
|
|
677
719
|
asyncio.get_event_loop().run_in_executor(self.dataPool, callback, sensor, sensorData)
|
|
678
720
|
except Exception as e:
|
|
@@ -690,12 +732,13 @@ class SensorProfileDataCtx:
|
|
|
690
732
|
index += 1
|
|
691
733
|
continue
|
|
692
734
|
crc = self._concatDataBuffer[index + 1 + n + 1]
|
|
693
|
-
calc_crc =
|
|
735
|
+
calc_crc = sensor_utils.calc_crc8(self._concatDataBuffer[index + 2 : index + 2 + n])
|
|
694
736
|
if crc != calc_crc:
|
|
695
737
|
index += 1
|
|
696
738
|
continue
|
|
697
739
|
data_package = bytes(self._concatDataBuffer[index + 2 : index + 2 + n])
|
|
698
|
-
|
|
740
|
+
if not sensor_utils._terminated:
|
|
741
|
+
asyncio.get_event_loop().run_in_executor(None, self.gForce._on_cmd_response, None, data_package)
|
|
699
742
|
last_cut = index = index + 2 + n
|
|
700
743
|
|
|
701
744
|
else:
|
sensor/sensor_profile.py
CHANGED
|
@@ -10,7 +10,7 @@ from bleak import (
|
|
|
10
10
|
BleakClient,
|
|
11
11
|
)
|
|
12
12
|
|
|
13
|
-
from sensor import
|
|
13
|
+
from sensor import sensor_utils
|
|
14
14
|
from sensor.gforce import GForce
|
|
15
15
|
from sensor.sensor_data import SensorData
|
|
16
16
|
import asyncio
|
|
@@ -18,7 +18,7 @@ import asyncio
|
|
|
18
18
|
|
|
19
19
|
from sensor.sensor_data_context import SensorProfileDataCtx
|
|
20
20
|
from sensor.sensor_device import BLEDevice, DeviceInfo, DeviceStateEx
|
|
21
|
-
from sensor.
|
|
21
|
+
from sensor.sensor_utils import async_call, sync_call, async_exec
|
|
22
22
|
|
|
23
23
|
SERVICE_GUID = "0000ffd0-0000-1000-8000-00805f9b34fb"
|
|
24
24
|
OYM_CMD_NOTIFY_CHAR_UUID = "f000ffe1-0451-4000-b000-000000000000"
|
|
@@ -212,7 +212,7 @@ class SensorProfile:
|
|
|
212
212
|
self._on_power_changed = callback
|
|
213
213
|
|
|
214
214
|
async def _connect(self) -> bool:
|
|
215
|
-
if
|
|
215
|
+
if sensor_utils._terminated:
|
|
216
216
|
return False
|
|
217
217
|
|
|
218
218
|
if self._event_loop == None:
|
|
@@ -292,7 +292,7 @@ class SensorProfile:
|
|
|
292
292
|
return await async_call(self._connect())
|
|
293
293
|
|
|
294
294
|
async def _waitForDisconnect(self) -> bool:
|
|
295
|
-
while not
|
|
295
|
+
while not sensor_utils._terminated and self.deviceState != DeviceStateEx.Disconnected:
|
|
296
296
|
await asyncio.sleep(1)
|
|
297
297
|
return True
|
|
298
298
|
|
|
@@ -303,7 +303,7 @@ class SensorProfile:
|
|
|
303
303
|
return False
|
|
304
304
|
self._set_device_state(DeviceStateEx.Disconnecting)
|
|
305
305
|
await self._gforce.disconnect()
|
|
306
|
-
await asyncio.wait_for(self._waitForDisconnect(),
|
|
306
|
+
await asyncio.wait_for(self._waitForDisconnect(), sensor_utils._TIMEOUT)
|
|
307
307
|
|
|
308
308
|
return True
|
|
309
309
|
|
|
@@ -393,7 +393,7 @@ class SensorProfile:
|
|
|
393
393
|
|
|
394
394
|
result = await self._data_ctx.stop_streaming()
|
|
395
395
|
self._is_starting = False
|
|
396
|
-
return
|
|
396
|
+
return result
|
|
397
397
|
|
|
398
398
|
def stopDataNotification(self) -> bool:
|
|
399
399
|
"""
|
|
@@ -422,12 +422,12 @@ class SensorProfile:
|
|
|
422
422
|
return await async_call(self._stopDataNotification())
|
|
423
423
|
|
|
424
424
|
async def _refresh_power(self):
|
|
425
|
-
while not
|
|
425
|
+
while not sensor_utils._terminated and self.deviceState == DeviceStateEx.Ready:
|
|
426
426
|
await asyncio.sleep(self._power_interval / 1000)
|
|
427
427
|
|
|
428
428
|
self._power = await self._gforce.get_battery_level()
|
|
429
429
|
|
|
430
|
-
if self._event_loop != None and self._on_power_changed != None:
|
|
430
|
+
if not sensor_utils._terminated and self._event_loop != None and self._on_power_changed != None:
|
|
431
431
|
try:
|
|
432
432
|
asyncio.get_event_loop().run_in_executor(None, self._on_power_changed, self, self._power)
|
|
433
433
|
except Exception as e:
|
|
@@ -443,7 +443,7 @@ class SensorProfile:
|
|
|
443
443
|
|
|
444
444
|
if await self._data_ctx.init(packageSampleCount):
|
|
445
445
|
self._power_interval = powerRefreshInterval
|
|
446
|
-
|
|
446
|
+
sensor_utils.async_exec(self._refresh_power())
|
|
447
447
|
|
|
448
448
|
return self._data_ctx.hasInit()
|
|
449
449
|
|
|
@@ -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()
|
|
@@ -85,6 +93,7 @@ async def async_call(function, _timeout=_TIMEOUT) -> any:
|
|
|
85
93
|
|
|
86
94
|
|
|
87
95
|
def start_loop(loop: asyncio.BaseEventLoop):
|
|
96
|
+
# asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
|
|
88
97
|
asyncio.set_event_loop(loop)
|
|
89
98
|
loop.run_forever()
|
|
90
99
|
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: sensor-sdk
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.18
|
|
4
4
|
Summary: Python sdk for Synchroni
|
|
5
5
|
Home-page: https://github.com/oymotion/SynchroniSDKPython
|
|
6
6
|
Author: Martin Ye
|
|
7
7
|
Author-email: yecq_82@hotmail.com
|
|
8
|
-
Requires-Python: >=3.
|
|
8
|
+
Requires-Python: >=3.9.0
|
|
9
9
|
Description-Content-Type: text/markdown
|
|
10
10
|
License-File: LICENSE.txt
|
|
11
11
|
Requires-Dist: numpy
|
|
@@ -95,10 +95,10 @@ isScanning = SensorControllerInstance.isScanning
|
|
|
95
95
|
|
|
96
96
|
### 5. Check if bluetooth is enabled
|
|
97
97
|
|
|
98
|
-
Use `property
|
|
98
|
+
Use `property isEnable: bool` to check if bluetooth is enable
|
|
99
99
|
|
|
100
100
|
```python
|
|
101
|
-
|
|
101
|
+
isEnable = SensorControllerInstance.isEnable
|
|
102
102
|
```
|
|
103
103
|
|
|
104
104
|
### 6. Create SensorProfile
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
sensor/__init__.py,sha256=L1VyAP0EDEnJIMeMTzp4iXHSRUUHyHScF_GIl3iYKRI,123
|
|
2
|
+
sensor/gforce.py,sha256=aWE4qFSnr5fLqsXE0uNg4t-sp0QVNreKQIEfjk2vVgs,26148
|
|
3
|
+
sensor/sensor_controller.py,sha256=cjVOcGaU9_8_eWFamtOpXsqSZMzD7lGU24gC_rsm2FQ,9546
|
|
4
|
+
sensor/sensor_data.py,sha256=vKreLHZs7WbQcnfqHiLLfHQ3cCmvD1K2xl2WUQg8vv0,4005
|
|
5
|
+
sensor/sensor_data_context.py,sha256=5I8AZ6e-qlnCLRydbW9MXLJTpNpI0uzPLqflVFzpVeA,30878
|
|
6
|
+
sensor/sensor_device.py,sha256=eO1vaqjxCc2UCPBoKXqlk6o498uRyWt6IYs7r7wXSD0,3042
|
|
7
|
+
sensor/sensor_profile.py,sha256=xe9QT3_lbrwS8pcVUVvVQavXZrRFKLl4Dj9eUs5hsFk,19747
|
|
8
|
+
sensor/sensor_utils.py,sha256=TkAY6tv3hWEsTbMipI7DCelVYZUpRuILLQ-b2IxFIC4,6771
|
|
9
|
+
sensor_sdk-0.0.18.dist-info/LICENSE.txt,sha256=8CSivOpub3IuXODTyqBRI91AxouJZk02YrcKuOAkWu8,1111
|
|
10
|
+
sensor_sdk-0.0.18.dist-info/METADATA,sha256=JYfyaSXzq8L1C9xbsZk66ny4sDFl2ut7Ed6gG8LaiI8,9821
|
|
11
|
+
sensor_sdk-0.0.18.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
|
|
12
|
+
sensor_sdk-0.0.18.dist-info/top_level.txt,sha256=Ftq49B6bH0Ffdc7c8LkcyakHo6lsg_snlBbpEUoILSk,7
|
|
13
|
+
sensor_sdk-0.0.18.dist-info/zip-safe,sha256=frcCV1k9oG9oKj3dpUqdJg1PxRT2RSN_XKdLCPjaYaY,2
|
|
14
|
+
sensor_sdk-0.0.18.dist-info/RECORD,,
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
sensor/__init__.py,sha256=L1VyAP0EDEnJIMeMTzp4iXHSRUUHyHScF_GIl3iYKRI,123
|
|
2
|
-
sensor/gforce.py,sha256=wZ4aEFtrgeR8LsL7tm6VSsjvIVcWbfQhwAVfADveNkg,25761
|
|
3
|
-
sensor/sensor_controller.py,sha256=qnM9mVwpJn9PCnxlvbgWFeaLktqVnmaquZgasYGEHqs,9451
|
|
4
|
-
sensor/sensor_data.py,sha256=Hu7Ql0LgQ7V24xYZhaLrKPwU4KWZeWE655v8Gy8xphY,3934
|
|
5
|
-
sensor/sensor_data_context.py,sha256=rxttt7f1BQOM2lUFys_po4BICdVl-NmIHKfnqGKs5XE,28815
|
|
6
|
-
sensor/sensor_device.py,sha256=eO1vaqjxCc2UCPBoKXqlk6o498uRyWt6IYs7r7wXSD0,3042
|
|
7
|
-
sensor/sensor_profile.py,sha256=NJsPr9l4VB9zAjfkaD28chGnJiSCnYAGFdkkN9Wyky0,19669
|
|
8
|
-
sensor/utils.py,sha256=BudTD083ucGxcTXfmksF-2gLRi_i-k7tMytruLUUKJc,6503
|
|
9
|
-
sensor_sdk-0.0.15.dist-info/LICENSE.txt,sha256=8CSivOpub3IuXODTyqBRI91AxouJZk02YrcKuOAkWu8,1111
|
|
10
|
-
sensor_sdk-0.0.15.dist-info/METADATA,sha256=D2Zk6zQPs3XrYYVdt_ROBT-PNZaIi_EhCgFZ9iqtwb4,9825
|
|
11
|
-
sensor_sdk-0.0.15.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
|
|
12
|
-
sensor_sdk-0.0.15.dist-info/top_level.txt,sha256=Ftq49B6bH0Ffdc7c8LkcyakHo6lsg_snlBbpEUoILSk,7
|
|
13
|
-
sensor_sdk-0.0.15.dist-info/zip-safe,sha256=frcCV1k9oG9oKj3dpUqdJg1PxRT2RSN_XKdLCPjaYaY,2
|
|
14
|
-
sensor_sdk-0.0.15.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|