sensor-sdk 0.0.3__py3-none-any.whl → 0.0.5__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 +73 -46
- sensor/sensor_controller.py +114 -38
- sensor/sensor_data.py +44 -41
- sensor/sensor_data_context.py +428 -107
- sensor/sensor_device.py +34 -34
- sensor/sensor_profile.py +243 -109
- sensor/utils.py +54 -10
- {sensor_sdk-0.0.3.dist-info → sensor_sdk-0.0.5.dist-info}/METADATA +14 -2
- sensor_sdk-0.0.5.dist-info/RECORD +14 -0
- sensor_sdk-0.0.3.dist-info/RECORD +0 -14
- {sensor_sdk-0.0.3.dist-info → sensor_sdk-0.0.5.dist-info}/LICENSE.txt +0 -0
- {sensor_sdk-0.0.3.dist-info → sensor_sdk-0.0.5.dist-info}/WHEEL +0 -0
- {sensor_sdk-0.0.3.dist-info → sensor_sdk-0.0.5.dist-info}/top_level.txt +0 -0
- {sensor_sdk-0.0.3.dist-info → sensor_sdk-0.0.5.dist-info}/zip-safe +0 -0
sensor/sensor_data_context.py
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import asyncio
|
|
2
2
|
from collections import deque
|
|
3
|
+
import platform
|
|
3
4
|
from queue import Queue
|
|
5
|
+
import struct
|
|
4
6
|
from typing import Deque, List
|
|
5
7
|
|
|
6
8
|
from sensor.gforce import DataSubscription, GForce
|
|
@@ -11,6 +13,7 @@ from enum import Enum, IntEnum
|
|
|
11
13
|
from sensor.sensor_device import DeviceInfo
|
|
12
14
|
from sensor.utils import timer
|
|
13
15
|
|
|
16
|
+
|
|
14
17
|
class SensorDataType(IntEnum):
|
|
15
18
|
DATA_TYPE_EEG = 0
|
|
16
19
|
DATA_TYPE_ECG = 1
|
|
@@ -19,6 +22,7 @@ class SensorDataType(IntEnum):
|
|
|
19
22
|
DATA_TYPE_BRTH = 4
|
|
20
23
|
DATA_TYPE_COUNT = 5
|
|
21
24
|
|
|
25
|
+
|
|
22
26
|
# 枚举 FeatureMaps 的 Python 实现
|
|
23
27
|
class FeatureMaps(Enum):
|
|
24
28
|
GFD_FEAT_EMG = 0x000002000
|
|
@@ -34,12 +38,13 @@ class FeatureMaps(Enum):
|
|
|
34
38
|
class SensorProfileDataCtx:
|
|
35
39
|
def __init__(self, gForce: GForce, deviceMac: str, buf: Queue[bytes]):
|
|
36
40
|
self.featureMap = 0
|
|
37
|
-
self.notifyDataFlag:DataSubscription = 0
|
|
38
|
-
|
|
41
|
+
self.notifyDataFlag: DataSubscription = 0
|
|
42
|
+
|
|
39
43
|
self.gForce = gForce
|
|
40
44
|
self.deviceMac = deviceMac
|
|
41
45
|
self._device_info: DeviceInfo = None
|
|
42
46
|
|
|
47
|
+
self._is_initing = False
|
|
43
48
|
self._is_running = True
|
|
44
49
|
self._is_data_transfering = False
|
|
45
50
|
self.isUniversalStream: bool = gForce._is_universal_stream
|
|
@@ -75,30 +80,34 @@ class SensorProfileDataCtx:
|
|
|
75
80
|
:return: bool: 如果传感器正在进行数据传输,返回 True;否则返回 False。
|
|
76
81
|
"""
|
|
77
82
|
return self._is_data_transfering
|
|
83
|
+
|
|
78
84
|
def hasInit(self):
|
|
79
|
-
return
|
|
85
|
+
return (
|
|
86
|
+
not self._is_initing and self.featureMap != 0 and self.notifyDataFlag != 0
|
|
87
|
+
)
|
|
88
|
+
|
|
80
89
|
def hasEMG(self):
|
|
81
90
|
return (self.featureMap & FeatureMaps.GFD_FEAT_EMG.value) != 0
|
|
82
91
|
|
|
83
92
|
def hasEEG(self):
|
|
84
93
|
return (self.featureMap & FeatureMaps.GFD_FEAT_EEG.value) != 0
|
|
85
|
-
|
|
94
|
+
|
|
86
95
|
def hasECG(self):
|
|
87
96
|
return (self.featureMap & FeatureMaps.GFD_FEAT_ECG.value) != 0
|
|
88
97
|
|
|
89
98
|
def hasImpedance(self):
|
|
90
99
|
return (self.featureMap & FeatureMaps.GFD_FEAT_IMPEDANCE.value) != 0
|
|
91
|
-
|
|
100
|
+
|
|
92
101
|
def hasIMU(self):
|
|
93
102
|
return (self.featureMap & FeatureMaps.GFD_FEAT_IMU.value) != 0
|
|
94
|
-
|
|
103
|
+
|
|
95
104
|
def hasBrth(self):
|
|
96
105
|
return (self.featureMap & FeatureMaps.GFD_FEAT_BRTH.value) != 0
|
|
97
106
|
|
|
98
107
|
def hasConcatBLE(self):
|
|
99
108
|
return (self.featureMap & FeatureMaps.GFD_FEAT_CONCAT_BLE.value) != 0
|
|
100
|
-
|
|
101
|
-
async def initEEG(self,packageCount:int)-> int:
|
|
109
|
+
|
|
110
|
+
async def initEEG(self, packageCount: int) -> int:
|
|
102
111
|
config = await self.gForce.get_eeg_raw_data_config()
|
|
103
112
|
cap = await self.gForce.get_eeg_raw_data_cap()
|
|
104
113
|
data = SensorData()
|
|
@@ -115,8 +124,8 @@ class SensorProfileDataCtx:
|
|
|
115
124
|
self.sensorDatas[SensorDataType.DATA_TYPE_EEG] = data
|
|
116
125
|
self.notifyDataFlag |= DataSubscription.DNF_EEG
|
|
117
126
|
return data.channelCount
|
|
118
|
-
|
|
119
|
-
async def initECG(self,packageCount:int)-> int:
|
|
127
|
+
|
|
128
|
+
async def initECG(self, packageCount: int) -> int:
|
|
120
129
|
config = await self.gForce.get_ecg_raw_data_config()
|
|
121
130
|
data = SensorData()
|
|
122
131
|
data.deviceMac = self.deviceMac
|
|
@@ -131,9 +140,9 @@ class SensorProfileDataCtx:
|
|
|
131
140
|
data.clear()
|
|
132
141
|
self.sensorDatas[SensorDataType.DATA_TYPE_ECG] = data
|
|
133
142
|
self.notifyDataFlag |= DataSubscription.DNF_ECG
|
|
134
|
-
return data.channelCount
|
|
135
|
-
|
|
136
|
-
async def initIMU(self,packageCount:int)-> int:
|
|
143
|
+
return data.channelCount
|
|
144
|
+
|
|
145
|
+
async def initIMU(self, packageCount: int) -> int:
|
|
137
146
|
config = await self.gForce.get_imu_raw_data_config()
|
|
138
147
|
data = SensorData()
|
|
139
148
|
data.deviceMac = self.deviceMac
|
|
@@ -163,9 +172,9 @@ class SensorProfileDataCtx:
|
|
|
163
172
|
|
|
164
173
|
self.notifyDataFlag |= DataSubscription.DNF_IMU
|
|
165
174
|
|
|
166
|
-
return data.channelCount
|
|
175
|
+
return data.channelCount
|
|
167
176
|
|
|
168
|
-
async def initBrth(self,packageCount:int)-> int:
|
|
177
|
+
async def initBrth(self, packageCount: int) -> int:
|
|
169
178
|
config = await self.gForce.get_brth_raw_data_config()
|
|
170
179
|
data = SensorData()
|
|
171
180
|
data.deviceMac = self.deviceMac
|
|
@@ -180,66 +189,80 @@ class SensorProfileDataCtx:
|
|
|
180
189
|
data.clear()
|
|
181
190
|
self.sensorDatas[SensorDataType.DATA_TYPE_BRTH] = data
|
|
182
191
|
self.notifyDataFlag |= DataSubscription.DNF_ECG
|
|
183
|
-
return data.channelCount
|
|
184
|
-
|
|
185
|
-
async def initDataTransfer(self,isGetFeature:bool)-> int:
|
|
186
|
-
if
|
|
187
|
-
self.featureMap =
|
|
188
|
-
if
|
|
192
|
+
return data.channelCount
|
|
193
|
+
|
|
194
|
+
async def initDataTransfer(self, isGetFeature: bool) -> int:
|
|
195
|
+
if isGetFeature:
|
|
196
|
+
self.featureMap = await self.gForce.get_feature_map()
|
|
197
|
+
if self.hasImpedance():
|
|
189
198
|
self.notifyDataFlag |= DataSubscription.DNF_IMPEDANCE
|
|
190
199
|
return self.featureMap
|
|
191
200
|
else:
|
|
192
201
|
await self.gForce.set_subscription(self.notifyDataFlag)
|
|
193
202
|
return self.notifyDataFlag
|
|
194
|
-
|
|
195
|
-
async def fetchDeviceInfo(self)->DeviceInfo:
|
|
203
|
+
|
|
204
|
+
async def fetchDeviceInfo(self) -> DeviceInfo:
|
|
196
205
|
info = DeviceInfo()
|
|
197
|
-
|
|
206
|
+
if platform.system() != "Linux":
|
|
207
|
+
info.MTUSize = self.gForce.client.mtu_size
|
|
208
|
+
else:
|
|
209
|
+
info.MTUSize = 0
|
|
210
|
+
print("get_device_name")
|
|
198
211
|
info.DeviceName = await self.gForce.get_device_name()
|
|
212
|
+
print("get_model_number")
|
|
199
213
|
info.ModelName = await self.gForce.get_model_number()
|
|
214
|
+
print("get_hardware_revision")
|
|
200
215
|
info.HardwareVersion = await self.gForce.get_hardware_revision()
|
|
216
|
+
print("get_firmware_revision")
|
|
201
217
|
info.FirmwareVersion = await self.gForce.get_firmware_revision()
|
|
202
218
|
return info
|
|
203
|
-
|
|
204
|
-
async def init(self, packageCount:int)->bool:
|
|
219
|
+
|
|
220
|
+
async def init(self, packageCount: int) -> bool:
|
|
221
|
+
if self._is_initing:
|
|
222
|
+
return False
|
|
205
223
|
try:
|
|
224
|
+
self._is_initing = True
|
|
206
225
|
info = await self.fetchDeviceInfo()
|
|
207
|
-
|
|
208
226
|
await self.initDataTransfer(True)
|
|
209
|
-
|
|
210
|
-
if (self.hasImpedance()):
|
|
227
|
+
if self.hasImpedance():
|
|
211
228
|
self.notifyDataFlag |= DataSubscription.DNF_IMPEDANCE
|
|
212
229
|
|
|
213
|
-
if
|
|
214
|
-
|
|
230
|
+
if self.hasEEG():
|
|
231
|
+
print("initEEG")
|
|
232
|
+
info.EegChannelCount = await self.initEEG(packageCount)
|
|
215
233
|
|
|
216
|
-
if
|
|
217
|
-
|
|
234
|
+
if self.hasECG():
|
|
235
|
+
print("initECG")
|
|
236
|
+
info.EcgChannelCount = await self.initECG(packageCount)
|
|
218
237
|
|
|
219
|
-
if
|
|
220
|
-
|
|
238
|
+
if self.hasBrth():
|
|
239
|
+
print("initBrth")
|
|
240
|
+
info.BrthChannelCount = await self.initBrth(packageCount)
|
|
221
241
|
|
|
222
|
-
if
|
|
242
|
+
if self.hasIMU():
|
|
243
|
+
print("initIMU")
|
|
223
244
|
imuChannelCount = await self.initIMU(packageCount)
|
|
224
245
|
info.AccChannelCount = imuChannelCount
|
|
225
246
|
info.GyroChannelCount = imuChannelCount
|
|
226
247
|
|
|
227
248
|
self._device_info = info
|
|
228
249
|
|
|
229
|
-
if
|
|
250
|
+
if not self.isUniversalStream:
|
|
230
251
|
await self.initDataTransfer(False)
|
|
231
252
|
|
|
253
|
+
self._is_initing = False
|
|
232
254
|
return True
|
|
233
255
|
except Exception as e:
|
|
234
256
|
print(e)
|
|
257
|
+
self._is_initing = False
|
|
235
258
|
return False
|
|
236
|
-
|
|
259
|
+
|
|
237
260
|
async def start_streaming(self) -> bool:
|
|
238
|
-
if
|
|
261
|
+
if self._is_data_transfering:
|
|
239
262
|
return True
|
|
240
263
|
self._is_data_transfering = True
|
|
241
264
|
self._rawDataBuffer.queue.clear()
|
|
242
|
-
if
|
|
265
|
+
if not self.isUniversalStream:
|
|
243
266
|
await self.gForce.start_streaming(self._rawDataBuffer)
|
|
244
267
|
return True
|
|
245
268
|
else:
|
|
@@ -247,28 +270,28 @@ class SensorProfileDataCtx:
|
|
|
247
270
|
return True
|
|
248
271
|
|
|
249
272
|
async def stop_streaming(self) -> bool:
|
|
250
|
-
if
|
|
273
|
+
if not self._is_data_transfering:
|
|
251
274
|
return True
|
|
252
|
-
|
|
275
|
+
|
|
253
276
|
self._is_data_transfering = False
|
|
254
277
|
|
|
255
|
-
if
|
|
278
|
+
if not self.isUniversalStream:
|
|
256
279
|
await self.gForce.stop_streaming()
|
|
257
280
|
return True
|
|
258
281
|
else:
|
|
259
282
|
await self.gForce.set_subscription(0)
|
|
260
283
|
return True
|
|
261
284
|
|
|
262
|
-
def process_data(self, buf: Queue[SensorData]):
|
|
285
|
+
def process_data(self, buf: Queue[SensorData], sensor):
|
|
263
286
|
try:
|
|
264
287
|
data: bytes = self._rawDataBuffer.get_nowait()
|
|
265
288
|
except Exception as e:
|
|
266
289
|
return
|
|
267
290
|
|
|
268
|
-
self._processDataPackage(data, buf)
|
|
291
|
+
self._processDataPackage(data, buf, sensor)
|
|
269
292
|
self._rawDataBuffer.task_done()
|
|
270
293
|
|
|
271
|
-
def _processDataPackage(self,data: bytes, buf: Queue[SensorData]):
|
|
294
|
+
def _processDataPackage(self, data: bytes, buf: Queue[SensorData], sensor):
|
|
272
295
|
v = data[0]
|
|
273
296
|
if v == DataType.NTF_IMPEDANCE:
|
|
274
297
|
offset = 1
|
|
@@ -279,15 +302,14 @@ class SensorProfileDataCtx:
|
|
|
279
302
|
saturationData = []
|
|
280
303
|
|
|
281
304
|
dataCount = (len(data) - 3) // 4 // 2
|
|
305
|
+
|
|
282
306
|
for index in range(dataCount):
|
|
283
|
-
|
|
284
|
-
impedance = int.from_bytes(impedance_bytes, byteorder='little')
|
|
307
|
+
impedance = struct.unpack_from("<f", data, offset)[0]
|
|
285
308
|
offset += 4
|
|
286
309
|
impedanceData.append(impedance)
|
|
287
310
|
|
|
288
311
|
for index in range(dataCount):
|
|
289
|
-
|
|
290
|
-
saturation = int.from_bytes(saturation_bytes, byteorder='little')
|
|
312
|
+
saturation = struct.unpack_from("<f", data, offset)[0]
|
|
291
313
|
offset += 4
|
|
292
314
|
saturationData.append(saturation / 10) # firmware value range 0 - 1000
|
|
293
315
|
|
|
@@ -295,34 +317,36 @@ class SensorProfileDataCtx:
|
|
|
295
317
|
self.saturationData = saturationData
|
|
296
318
|
|
|
297
319
|
elif v == DataType.NTF_EEG:
|
|
298
|
-
sensor_data = self.sensorDatas[SensorDataType.DATA_TYPE_EEG]
|
|
299
|
-
if self.checkReadSamples(data, sensor_data, 3, 0):
|
|
320
|
+
sensor_data = self.sensorDatas[SensorDataType.DATA_TYPE_EEG]
|
|
321
|
+
if self.checkReadSamples(sensor, data, sensor_data, 3, 0):
|
|
300
322
|
self.sendSensorData(sensor_data, buf)
|
|
301
323
|
elif v == DataType.NTF_ECG:
|
|
302
|
-
sensor_data = self.sensorDatas[SensorDataType.DATA_TYPE_ECG]
|
|
303
|
-
if self.checkReadSamples(data, sensor_data, 3, 0):
|
|
324
|
+
sensor_data = self.sensorDatas[SensorDataType.DATA_TYPE_ECG]
|
|
325
|
+
if self.checkReadSamples(sensor, data, sensor_data, 3, 0):
|
|
304
326
|
self.sendSensorData(sensor_data, buf)
|
|
305
327
|
elif v == DataType.NTF_BRTH:
|
|
306
|
-
sensor_data = self.sensorDatas[SensorDataType.DATA_TYPE_BRTH]
|
|
307
|
-
if self.checkReadSamples(data, sensor_data, 3, 0):
|
|
328
|
+
sensor_data = self.sensorDatas[SensorDataType.DATA_TYPE_BRTH]
|
|
329
|
+
if self.checkReadSamples(sensor, data, sensor_data, 3, 0):
|
|
308
330
|
self.sendSensorData(sensor_data, buf)
|
|
309
331
|
elif v == DataType.NTF_IMU:
|
|
310
|
-
sensor_data_acc = self.sensorDatas[SensorDataType.DATA_TYPE_ACC]
|
|
311
|
-
if self.checkReadSamples(data, sensor_data_acc, 3, 6):
|
|
332
|
+
sensor_data_acc = self.sensorDatas[SensorDataType.DATA_TYPE_ACC]
|
|
333
|
+
if self.checkReadSamples(sensor, data, sensor_data_acc, 3, 6):
|
|
312
334
|
self.sendSensorData(sensor_data_acc, buf)
|
|
313
335
|
|
|
314
|
-
sensor_data_gyro = self.sensorDatas[SensorDataType.DATA_TYPE_GYRO]
|
|
315
|
-
if self.checkReadSamples(data, sensor_data_gyro, 9, 6):
|
|
336
|
+
sensor_data_gyro = self.sensorDatas[SensorDataType.DATA_TYPE_GYRO]
|
|
337
|
+
if self.checkReadSamples(sensor, data, sensor_data_gyro, 9, 6):
|
|
316
338
|
self.sendSensorData(sensor_data_gyro, buf)
|
|
317
339
|
|
|
318
|
-
def checkReadSamples(
|
|
340
|
+
def checkReadSamples(
|
|
341
|
+
self, sensor, data: bytes, sensorData: SensorData, dataOffset: int, dataGap: int
|
|
342
|
+
):
|
|
319
343
|
offset = 1
|
|
320
344
|
v = data[0]
|
|
321
345
|
if not self._is_data_transfering:
|
|
322
346
|
return False
|
|
323
347
|
try:
|
|
324
348
|
|
|
325
|
-
packageIndex = ((data[offset + 1] &
|
|
349
|
+
packageIndex = ((data[offset + 1] & 0xFF) << 8) | (data[offset] & 0xFF)
|
|
326
350
|
offset += 2
|
|
327
351
|
newPackageIndex = packageIndex
|
|
328
352
|
lastPackageIndex = sensorData.lastPackageIndex
|
|
@@ -334,23 +358,49 @@ class SensorProfileDataCtx:
|
|
|
334
358
|
|
|
335
359
|
deltaPackageIndex = packageIndex - lastPackageIndex
|
|
336
360
|
if deltaPackageIndex > 1:
|
|
337
|
-
lostSampleCount = sensorData.packageSampleCount * (
|
|
338
|
-
|
|
361
|
+
lostSampleCount = sensorData.packageSampleCount * (
|
|
362
|
+
deltaPackageIndex - 1
|
|
363
|
+
)
|
|
364
|
+
lostLog = (
|
|
365
|
+
"MSG|LOST SAMPLE|MAC|"
|
|
366
|
+
+ str(sensorData.deviceMac)
|
|
367
|
+
+ "|TYPE|"
|
|
368
|
+
+ str(sensorData.dataType)
|
|
369
|
+
+ "|COUNT|"
|
|
370
|
+
+ str(lostSampleCount)
|
|
371
|
+
)
|
|
372
|
+
# print(lostLog)
|
|
373
|
+
if sensor._event_loop != None and sensor._on_error_callback != None:
|
|
374
|
+
try:
|
|
375
|
+
sensor._event_loop.call_soon_threadsafe(
|
|
376
|
+
sensor._on_error_callback, sensor, lostLog
|
|
377
|
+
)
|
|
378
|
+
except Exception as e:
|
|
379
|
+
pass
|
|
380
|
+
|
|
339
381
|
self.readSamples(data, sensorData, 0, dataGap, lostSampleCount)
|
|
340
382
|
if newPackageIndex == 0:
|
|
341
383
|
sensorData.lastPackageIndex = 65535
|
|
342
384
|
else:
|
|
343
385
|
sensorData.lastPackageIndex = newPackageIndex - 1
|
|
344
|
-
sensorData.lastPackageCounter +=
|
|
386
|
+
sensorData.lastPackageCounter += deltaPackageIndex - 1
|
|
345
387
|
|
|
346
388
|
self.readSamples(data, sensorData, dataOffset, dataGap, 0)
|
|
347
389
|
sensorData.lastPackageIndex = newPackageIndex
|
|
348
390
|
sensorData.lastPackageCounter += 1
|
|
349
|
-
except Exception:
|
|
391
|
+
except Exception as e:
|
|
392
|
+
print(e)
|
|
350
393
|
return False
|
|
351
394
|
return True
|
|
352
|
-
|
|
353
|
-
def readSamples(
|
|
395
|
+
|
|
396
|
+
def readSamples(
|
|
397
|
+
self,
|
|
398
|
+
data: bytes,
|
|
399
|
+
sensorData: SensorData,
|
|
400
|
+
offset: int,
|
|
401
|
+
dataGap: int,
|
|
402
|
+
lostSampleCount: int,
|
|
403
|
+
):
|
|
354
404
|
sampleCount = sensorData.packageSampleCount
|
|
355
405
|
sampleInterval = 1000 // sensorData.sampleRate
|
|
356
406
|
if lostSampleCount > 0:
|
|
@@ -368,15 +418,23 @@ class SensorProfileDataCtx:
|
|
|
368
418
|
channelSamples.append([])
|
|
369
419
|
|
|
370
420
|
for sampleIndex in range(sampleCount):
|
|
371
|
-
for channelIndex, impedanceChannelIndex in enumerate(
|
|
421
|
+
for channelIndex, impedanceChannelIndex in enumerate(
|
|
422
|
+
range(sensorData.channelCount)
|
|
423
|
+
):
|
|
372
424
|
if (sensorData.channelMask & (1 << channelIndex)) != 0:
|
|
373
425
|
samples = channelSamples[channelIndex]
|
|
374
426
|
impedance = 0.0
|
|
375
427
|
saturation = 0.0
|
|
428
|
+
|
|
376
429
|
if sensorData.dataType == DataType.NTF_ECG:
|
|
377
|
-
impedanceChannelIndex = self.sensorDatas[
|
|
378
|
-
|
|
379
|
-
|
|
430
|
+
impedanceChannelIndex = self.sensorDatas[
|
|
431
|
+
SensorDataType.DATA_TYPE_EEG
|
|
432
|
+
].channelCount
|
|
433
|
+
|
|
434
|
+
if impedanceChannelIndex < len(_impedanceData):
|
|
435
|
+
impedance = _impedanceData[impedanceChannelIndex]
|
|
436
|
+
saturation = _saturationData[impedanceChannelIndex]
|
|
437
|
+
|
|
380
438
|
impedanceChannelIndex += 1
|
|
381
439
|
|
|
382
440
|
dataItem = Sample()
|
|
@@ -396,10 +454,18 @@ class SensorProfileDataCtx:
|
|
|
396
454
|
rawData -= 128
|
|
397
455
|
offset += 1
|
|
398
456
|
elif sensorData.resolutionBits == 16:
|
|
399
|
-
rawData = int.from_bytes(
|
|
457
|
+
rawData = int.from_bytes(
|
|
458
|
+
data[offset : offset + 2],
|
|
459
|
+
byteorder="little",
|
|
460
|
+
signed=True,
|
|
461
|
+
)
|
|
400
462
|
offset += 2
|
|
401
463
|
elif sensorData.resolutionBits == 24:
|
|
402
|
-
rawData = (
|
|
464
|
+
rawData = (
|
|
465
|
+
(data[offset] << 16)
|
|
466
|
+
| (data[offset + 1] << 8)
|
|
467
|
+
| data[offset + 2]
|
|
468
|
+
)
|
|
403
469
|
rawData -= 8388608
|
|
404
470
|
offset += 3
|
|
405
471
|
|
|
@@ -428,7 +494,7 @@ class SensorProfileDataCtx:
|
|
|
428
494
|
if realSampleCount < sensorData.minPackageSampleCount:
|
|
429
495
|
return
|
|
430
496
|
|
|
431
|
-
sensorData.channelSamples = []
|
|
497
|
+
sensorData.channelSamples = []
|
|
432
498
|
batchCount = realSampleCount // sensorData.minPackageSampleCount
|
|
433
499
|
# leftSampleSize = realSampleCount - sensorData.minPackageSampleCount * batchCount
|
|
434
500
|
|
|
@@ -468,25 +534,264 @@ class SensorProfileDataCtx:
|
|
|
468
534
|
for sensorDataResult in sensorDataList:
|
|
469
535
|
buf.put(sensorDataResult)
|
|
470
536
|
|
|
471
|
-
|
|
472
|
-
def calc_crc8(self,data):
|
|
537
|
+
def calc_crc8(self, data):
|
|
473
538
|
crc8Table = [
|
|
474
|
-
0x00,
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
539
|
+
0x00,
|
|
540
|
+
0x07,
|
|
541
|
+
0x0E,
|
|
542
|
+
0x09,
|
|
543
|
+
0x1C,
|
|
544
|
+
0x1B,
|
|
545
|
+
0x12,
|
|
546
|
+
0x15,
|
|
547
|
+
0x38,
|
|
548
|
+
0x3F,
|
|
549
|
+
0x36,
|
|
550
|
+
0x31,
|
|
551
|
+
0x24,
|
|
552
|
+
0x23,
|
|
553
|
+
0x2A,
|
|
554
|
+
0x2D,
|
|
555
|
+
0x70,
|
|
556
|
+
0x77,
|
|
557
|
+
0x7E,
|
|
558
|
+
0x79,
|
|
559
|
+
0x6C,
|
|
560
|
+
0x6B,
|
|
561
|
+
0x62,
|
|
562
|
+
0x65,
|
|
563
|
+
0x48,
|
|
564
|
+
0x4F,
|
|
565
|
+
0x46,
|
|
566
|
+
0x41,
|
|
567
|
+
0x54,
|
|
568
|
+
0x53,
|
|
569
|
+
0x5A,
|
|
570
|
+
0x5D,
|
|
571
|
+
0xE0,
|
|
572
|
+
0xE7,
|
|
573
|
+
0xEE,
|
|
574
|
+
0xE9,
|
|
575
|
+
0xFC,
|
|
576
|
+
0xFB,
|
|
577
|
+
0xF2,
|
|
578
|
+
0xF5,
|
|
579
|
+
0xD8,
|
|
580
|
+
0xDF,
|
|
581
|
+
0xD6,
|
|
582
|
+
0xD1,
|
|
583
|
+
0xC4,
|
|
584
|
+
0xC3,
|
|
585
|
+
0xCA,
|
|
586
|
+
0xCD,
|
|
587
|
+
0x90,
|
|
588
|
+
0x97,
|
|
589
|
+
0x9E,
|
|
590
|
+
0x99,
|
|
591
|
+
0x8C,
|
|
592
|
+
0x8B,
|
|
593
|
+
0x82,
|
|
594
|
+
0x85,
|
|
595
|
+
0xA8,
|
|
596
|
+
0xAF,
|
|
597
|
+
0xA6,
|
|
598
|
+
0xA1,
|
|
599
|
+
0xB4,
|
|
600
|
+
0xB3,
|
|
601
|
+
0xBA,
|
|
602
|
+
0xBD,
|
|
603
|
+
0xC7,
|
|
604
|
+
0xC0,
|
|
605
|
+
0xC9,
|
|
606
|
+
0xCE,
|
|
607
|
+
0xDB,
|
|
608
|
+
0xDC,
|
|
609
|
+
0xD5,
|
|
610
|
+
0xD2,
|
|
611
|
+
0xFF,
|
|
612
|
+
0xF8,
|
|
613
|
+
0xF1,
|
|
614
|
+
0xF6,
|
|
615
|
+
0xE3,
|
|
616
|
+
0xE4,
|
|
617
|
+
0xED,
|
|
618
|
+
0xEA,
|
|
619
|
+
0xB7,
|
|
620
|
+
0xB0,
|
|
621
|
+
0xB9,
|
|
622
|
+
0xBE,
|
|
623
|
+
0xAB,
|
|
624
|
+
0xAC,
|
|
625
|
+
0xA5,
|
|
626
|
+
0xA2,
|
|
627
|
+
0x8F,
|
|
628
|
+
0x88,
|
|
629
|
+
0x81,
|
|
630
|
+
0x86,
|
|
631
|
+
0x93,
|
|
632
|
+
0x94,
|
|
633
|
+
0x9D,
|
|
634
|
+
0x9A,
|
|
635
|
+
0x27,
|
|
636
|
+
0x20,
|
|
637
|
+
0x29,
|
|
638
|
+
0x2E,
|
|
639
|
+
0x3B,
|
|
640
|
+
0x3C,
|
|
641
|
+
0x35,
|
|
642
|
+
0x32,
|
|
643
|
+
0x1F,
|
|
644
|
+
0x18,
|
|
645
|
+
0x11,
|
|
646
|
+
0x16,
|
|
647
|
+
0x03,
|
|
648
|
+
0x04,
|
|
649
|
+
0x0D,
|
|
650
|
+
0x0A,
|
|
651
|
+
0x57,
|
|
652
|
+
0x50,
|
|
653
|
+
0x59,
|
|
654
|
+
0x5E,
|
|
655
|
+
0x4B,
|
|
656
|
+
0x4C,
|
|
657
|
+
0x45,
|
|
658
|
+
0x42,
|
|
659
|
+
0x6F,
|
|
660
|
+
0x68,
|
|
661
|
+
0x61,
|
|
662
|
+
0x66,
|
|
663
|
+
0x73,
|
|
664
|
+
0x74,
|
|
665
|
+
0x7D,
|
|
666
|
+
0x7A,
|
|
667
|
+
0x89,
|
|
668
|
+
0x8E,
|
|
669
|
+
0x87,
|
|
670
|
+
0x80,
|
|
671
|
+
0x95,
|
|
672
|
+
0x92,
|
|
673
|
+
0x9B,
|
|
674
|
+
0x9C,
|
|
675
|
+
0xB1,
|
|
676
|
+
0xB6,
|
|
677
|
+
0xBF,
|
|
678
|
+
0xB8,
|
|
679
|
+
0xAD,
|
|
680
|
+
0xAA,
|
|
681
|
+
0xA3,
|
|
682
|
+
0xA4,
|
|
683
|
+
0xF9,
|
|
684
|
+
0xFE,
|
|
685
|
+
0xF7,
|
|
686
|
+
0xF0,
|
|
687
|
+
0xE5,
|
|
688
|
+
0xE2,
|
|
689
|
+
0xEB,
|
|
690
|
+
0xEC,
|
|
691
|
+
0xC1,
|
|
692
|
+
0xC6,
|
|
693
|
+
0xCF,
|
|
694
|
+
0xC8,
|
|
695
|
+
0xDD,
|
|
696
|
+
0xDA,
|
|
697
|
+
0xD3,
|
|
698
|
+
0xD4,
|
|
699
|
+
0x69,
|
|
700
|
+
0x6E,
|
|
701
|
+
0x67,
|
|
702
|
+
0x60,
|
|
703
|
+
0x75,
|
|
704
|
+
0x72,
|
|
705
|
+
0x7B,
|
|
706
|
+
0x7C,
|
|
707
|
+
0x51,
|
|
708
|
+
0x56,
|
|
709
|
+
0x5F,
|
|
710
|
+
0x58,
|
|
711
|
+
0x4D,
|
|
712
|
+
0x4A,
|
|
713
|
+
0x43,
|
|
714
|
+
0x44,
|
|
715
|
+
0x19,
|
|
716
|
+
0x1E,
|
|
717
|
+
0x17,
|
|
718
|
+
0x10,
|
|
719
|
+
0x05,
|
|
720
|
+
0x02,
|
|
721
|
+
0x0B,
|
|
722
|
+
0x0C,
|
|
723
|
+
0x21,
|
|
724
|
+
0x26,
|
|
725
|
+
0x2F,
|
|
726
|
+
0x28,
|
|
727
|
+
0x3D,
|
|
728
|
+
0x3A,
|
|
729
|
+
0x33,
|
|
730
|
+
0x34,
|
|
731
|
+
0x4E,
|
|
732
|
+
0x49,
|
|
733
|
+
0x40,
|
|
734
|
+
0x47,
|
|
735
|
+
0x52,
|
|
736
|
+
0x55,
|
|
737
|
+
0x5C,
|
|
738
|
+
0x5B,
|
|
739
|
+
0x76,
|
|
740
|
+
0x71,
|
|
741
|
+
0x78,
|
|
742
|
+
0x7F,
|
|
743
|
+
0x6A,
|
|
744
|
+
0x6D,
|
|
745
|
+
0x64,
|
|
746
|
+
0x63,
|
|
747
|
+
0x3E,
|
|
748
|
+
0x39,
|
|
749
|
+
0x30,
|
|
750
|
+
0x37,
|
|
751
|
+
0x22,
|
|
752
|
+
0x25,
|
|
753
|
+
0x2C,
|
|
754
|
+
0x2B,
|
|
755
|
+
0x06,
|
|
756
|
+
0x01,
|
|
757
|
+
0x08,
|
|
758
|
+
0x0F,
|
|
759
|
+
0x1A,
|
|
760
|
+
0x1D,
|
|
761
|
+
0x14,
|
|
762
|
+
0x13,
|
|
763
|
+
0xAE,
|
|
764
|
+
0xA9,
|
|
765
|
+
0xA0,
|
|
766
|
+
0xA7,
|
|
767
|
+
0xB2,
|
|
768
|
+
0xB5,
|
|
769
|
+
0xBC,
|
|
770
|
+
0xBB,
|
|
771
|
+
0x96,
|
|
772
|
+
0x91,
|
|
773
|
+
0x98,
|
|
774
|
+
0x9F,
|
|
775
|
+
0x8A,
|
|
776
|
+
0x8D,
|
|
777
|
+
0x84,
|
|
778
|
+
0x83,
|
|
779
|
+
0xDE,
|
|
780
|
+
0xD9,
|
|
781
|
+
0xD0,
|
|
782
|
+
0xD7,
|
|
783
|
+
0xC2,
|
|
784
|
+
0xC5,
|
|
785
|
+
0xCC,
|
|
786
|
+
0xCB,
|
|
787
|
+
0xE6,
|
|
788
|
+
0xE1,
|
|
789
|
+
0xE8,
|
|
790
|
+
0xEF,
|
|
791
|
+
0xFA,
|
|
792
|
+
0xFD,
|
|
793
|
+
0xF4,
|
|
794
|
+
0xF3,
|
|
490
795
|
]
|
|
491
796
|
crc8 = 0
|
|
492
797
|
len_data = len(data)
|
|
@@ -496,11 +801,14 @@ class SensorProfileDataCtx:
|
|
|
496
801
|
crc8 = crc8Table[crc8]
|
|
497
802
|
|
|
498
803
|
return crc8
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
804
|
+
|
|
805
|
+
def processUniversalData(
|
|
806
|
+
self, buf: Queue[SensorData], loop: asyncio.AbstractEventLoop, sensor, callback
|
|
807
|
+
):
|
|
808
|
+
|
|
809
|
+
while self._is_running:
|
|
502
810
|
try:
|
|
503
|
-
while
|
|
811
|
+
while self._is_running and not self._rawDataBuffer.empty():
|
|
504
812
|
data = self._rawDataBuffer.get_nowait()
|
|
505
813
|
self._concatDataBuffer.extend(data)
|
|
506
814
|
self._rawDataBuffer.task_done()
|
|
@@ -524,22 +832,28 @@ class SensorProfileDataCtx:
|
|
|
524
832
|
index += 1
|
|
525
833
|
continue
|
|
526
834
|
crc = self._concatDataBuffer[index + 1 + n + 1]
|
|
527
|
-
calc_crc = self.calc_crc8(
|
|
835
|
+
calc_crc = self.calc_crc8(
|
|
836
|
+
self._concatDataBuffer[index + 2 : index + 2 + n]
|
|
837
|
+
)
|
|
528
838
|
if crc != calc_crc:
|
|
529
839
|
index += 1
|
|
530
840
|
continue
|
|
531
841
|
if self._is_data_transfering:
|
|
532
|
-
data_package = bytes(
|
|
533
|
-
|
|
534
|
-
|
|
842
|
+
data_package = bytes(
|
|
843
|
+
self._concatDataBuffer[index + 2 : index + 2 + n]
|
|
844
|
+
)
|
|
845
|
+
self._processDataPackage(data_package, buf, sensor)
|
|
846
|
+
while self._is_running and self.isDataTransfering:
|
|
535
847
|
sensorData: SensorData = None
|
|
536
848
|
try:
|
|
537
849
|
sensorData = buf.get_nowait()
|
|
538
850
|
except Exception as e:
|
|
539
851
|
break
|
|
540
|
-
if
|
|
852
|
+
if loop != None and sensorData != None and callback != None:
|
|
541
853
|
try:
|
|
542
|
-
loop.call_soon_threadsafe(
|
|
854
|
+
loop.call_soon_threadsafe(
|
|
855
|
+
callback, sensor, sensorData
|
|
856
|
+
)
|
|
543
857
|
except Exception as e:
|
|
544
858
|
print(e)
|
|
545
859
|
|
|
@@ -555,15 +869,22 @@ class SensorProfileDataCtx:
|
|
|
555
869
|
index += 1
|
|
556
870
|
continue
|
|
557
871
|
crc = self._concatDataBuffer[index + 1 + n + 1]
|
|
558
|
-
calc_crc = self.calc_crc8(
|
|
872
|
+
calc_crc = self.calc_crc8(
|
|
873
|
+
self._concatDataBuffer[index + 2 : index + 2 + n]
|
|
874
|
+
)
|
|
559
875
|
if crc != calc_crc:
|
|
560
876
|
index += 1
|
|
561
877
|
continue
|
|
562
|
-
data_package = bytes(
|
|
563
|
-
|
|
878
|
+
data_package = bytes(
|
|
879
|
+
self._concatDataBuffer[index + 2 : index + 2 + n]
|
|
880
|
+
)
|
|
881
|
+
if loop != None:
|
|
882
|
+
loop.call_soon_threadsafe(
|
|
883
|
+
self.gForce._on_cmd_response, None, data_package
|
|
884
|
+
)
|
|
564
885
|
last_cut = index = index + 2 + n
|
|
565
886
|
else:
|
|
566
887
|
index += 1
|
|
567
888
|
|
|
568
889
|
if last_cut > 0:
|
|
569
|
-
self._concatDataBuffer = self._concatDataBuffer[last_cut + 1:]
|
|
890
|
+
self._concatDataBuffer = self._concatDataBuffer[last_cut + 1 :]
|