sensor-sdk 0.0.11__py3-none-any.whl → 0.0.15__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 +15 -4
- sensor/sensor_data_context.py +111 -27
- sensor/sensor_profile.py +80 -11
- sensor/utils.py +0 -24
- {sensor_sdk-0.0.11.dist-info → sensor_sdk-0.0.15.dist-info}/METADATA +41 -2
- sensor_sdk-0.0.15.dist-info/RECORD +14 -0
- sensor_sdk-0.0.11.dist-info/RECORD +0 -14
- {sensor_sdk-0.0.11.dist-info → sensor_sdk-0.0.15.dist-info}/LICENSE.txt +0 -0
- {sensor_sdk-0.0.11.dist-info → sensor_sdk-0.0.15.dist-info}/WHEEL +0 -0
- {sensor_sdk-0.0.11.dist-info → sensor_sdk-0.0.15.dist-info}/top_level.txt +0 -0
- {sensor_sdk-0.0.11.dist-info → sensor_sdk-0.0.15.dist-info}/zip-safe +0 -0
sensor/gforce.py
CHANGED
|
@@ -103,6 +103,8 @@ class Command(IntEnum):
|
|
|
103
103
|
CMD_GET_BLE_MTU_INFO = (0xAE,)
|
|
104
104
|
CMD_GET_BRT_CONFIG = (0xB3,)
|
|
105
105
|
|
|
106
|
+
CMD_SET_FRIMWARE_FILTER_SWITCH = (0xAA,)
|
|
107
|
+
CMD_GET_FRIMWARE_FILTER_SWITCH = (0xA9,)
|
|
106
108
|
# Partial command packet, format: [CMD_PARTIAL_DATA, packet number in reverse order, packet content]
|
|
107
109
|
MD_PARTIAL_DATA = 0xFF
|
|
108
110
|
|
|
@@ -737,6 +739,15 @@ class GForce:
|
|
|
737
739
|
)
|
|
738
740
|
)
|
|
739
741
|
|
|
742
|
+
async def set_firmware_filter_switch(self, switchStatus: int):
|
|
743
|
+
body = [0xFF & switchStatus]
|
|
744
|
+
body = bytes(body)
|
|
745
|
+
await self._send_request(Request(cmd=Command.CMD_SET_FRIMWARE_FILTER_SWITCH, body=body, has_res=True))
|
|
746
|
+
|
|
747
|
+
async def get_firmware_filter_switch(self):
|
|
748
|
+
buf = await self._send_request(Request(cmd=Command.CMD_GET_FRIMWARE_FILTER_SWITCH, has_res=True))
|
|
749
|
+
return buf[0]
|
|
750
|
+
|
|
740
751
|
async def set_emg_raw_data_config(self, cfg=EmgRawDataConfig()):
|
|
741
752
|
body = cfg.to_bytes()
|
|
742
753
|
await self._send_request(
|
|
@@ -842,10 +853,10 @@ class GForce:
|
|
|
842
853
|
|
|
843
854
|
async def stop_streaming(self):
|
|
844
855
|
exceptions = []
|
|
845
|
-
try:
|
|
846
|
-
|
|
847
|
-
except Exception as e:
|
|
848
|
-
|
|
856
|
+
# try:
|
|
857
|
+
# await asyncio.wait_for(self.set_subscription(DataSubscription.OFF), utils._TIMEOUT)
|
|
858
|
+
# except Exception as e:
|
|
859
|
+
# exceptions.append(e)
|
|
849
860
|
try:
|
|
850
861
|
await asyncio.wait_for(self.client.stop_notify(self.data_char), utils._TIMEOUT)
|
|
851
862
|
except Exception as e:
|
sensor/sensor_data_context.py
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import asyncio
|
|
2
2
|
from collections import deque
|
|
3
|
+
import os
|
|
3
4
|
import platform
|
|
4
5
|
from queue import Queue
|
|
5
6
|
import struct
|
|
6
7
|
from typing import Deque, List
|
|
7
8
|
from concurrent.futures import ThreadPoolExecutor
|
|
8
|
-
|
|
9
|
+
import csv
|
|
9
10
|
from sensor import utils
|
|
10
11
|
from sensor.gforce import DataSubscription, GForce
|
|
11
12
|
from sensor.sensor_data import DataType, Sample, SensorData
|
|
@@ -58,9 +59,15 @@ class SensorProfileDataCtx:
|
|
|
58
59
|
self.impedanceData: List[float] = list()
|
|
59
60
|
self.saturationData: List[float] = list()
|
|
60
61
|
self.dataPool = ThreadPoolExecutor(1, "data")
|
|
62
|
+
self.init_map = {"NTF_EMG": "ON", "NTF_EEG": "ON", "NTF_ECG": "ON", "NTF_IMU": "ON", "NTF_BRTH": "ON"}
|
|
63
|
+
self.filter_map = {"FILTER_50Hz": "ON", "FILTER_60Hz": "ON", "FILTER_HPF": "ON", "FILTER_LPF": "ON"}
|
|
64
|
+
self.debugCSVWriter = None
|
|
65
|
+
self.debugCSVPath = None
|
|
61
66
|
|
|
62
67
|
def close(self):
|
|
63
68
|
self._is_running = False
|
|
69
|
+
if self.debugCSVWriter != None:
|
|
70
|
+
self.debugCSVWriter = None
|
|
64
71
|
|
|
65
72
|
def clear(self):
|
|
66
73
|
for sensorData in self.sensorDatas:
|
|
@@ -227,22 +234,22 @@ class SensorProfileDataCtx:
|
|
|
227
234
|
if self.hasImpedance():
|
|
228
235
|
self.notifyDataFlag |= DataSubscription.DNF_IMPEDANCE
|
|
229
236
|
|
|
230
|
-
if self.hasEEG():
|
|
237
|
+
if self.hasEEG() & (self.init_map["NTF_EEG"] == "ON"):
|
|
231
238
|
# print("initEEG")
|
|
232
239
|
info.EegChannelCount = await self.initEEG(packageCount)
|
|
233
240
|
info.EegSampleRate = self.sensorDatas[SensorDataType.DATA_TYPE_EEG].sampleRate
|
|
234
241
|
|
|
235
|
-
if self.hasECG():
|
|
242
|
+
if self.hasECG() & (self.init_map["NTF_ECG"] == "ON"):
|
|
236
243
|
# print("initECG")
|
|
237
244
|
info.EcgChannelCount = await self.initECG(packageCount)
|
|
238
245
|
info.EcgSampleRate = self.sensorDatas[SensorDataType.DATA_TYPE_ECG].sampleRate
|
|
239
246
|
|
|
240
|
-
if self.hasBrth():
|
|
247
|
+
if self.hasBrth() & (self.init_map["NTF_BRTH"] == "ON"):
|
|
241
248
|
# print("initBrth")
|
|
242
249
|
info.BrthChannelCount = await self.initBrth(packageCount)
|
|
243
250
|
info.BrthSampleRate = self.sensorDatas[SensorDataType.DATA_TYPE_BRTH].sampleRate
|
|
244
251
|
|
|
245
|
-
if self.hasIMU():
|
|
252
|
+
if self.hasIMU() & (self.init_map["NTF_IMU"] == "ON"):
|
|
246
253
|
# print("initIMU")
|
|
247
254
|
imuChannelCount = await self.initIMU(packageCount)
|
|
248
255
|
info.AccChannelCount = imuChannelCount
|
|
@@ -267,12 +274,15 @@ class SensorProfileDataCtx:
|
|
|
267
274
|
return True
|
|
268
275
|
self._is_data_transfering = True
|
|
269
276
|
self._rawDataBuffer.queue.clear()
|
|
277
|
+
self._concatDataBuffer.clear()
|
|
278
|
+
self.clear()
|
|
279
|
+
|
|
270
280
|
if not self.isUniversalStream:
|
|
271
281
|
await self.gForce.start_streaming(self._rawDataBuffer)
|
|
272
|
-
return True
|
|
273
282
|
else:
|
|
274
283
|
await self.gForce.set_subscription(self.notifyDataFlag)
|
|
275
|
-
|
|
284
|
+
|
|
285
|
+
return True
|
|
276
286
|
|
|
277
287
|
async def stop_streaming(self) -> bool:
|
|
278
288
|
if not self._is_data_transfering:
|
|
@@ -280,16 +290,64 @@ class SensorProfileDataCtx:
|
|
|
280
290
|
|
|
281
291
|
self._is_data_transfering = False
|
|
282
292
|
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
293
|
+
try:
|
|
294
|
+
|
|
295
|
+
if not self.isUniversalStream:
|
|
296
|
+
await self.gForce.stop_streaming()
|
|
297
|
+
else:
|
|
298
|
+
await self.gForce.set_subscription(0)
|
|
299
|
+
|
|
300
|
+
while self._is_running and not self._rawDataBuffer.empty():
|
|
301
|
+
await asyncio.sleep(0.1)
|
|
302
|
+
|
|
303
|
+
except Exception as e:
|
|
304
|
+
print(e)
|
|
305
|
+
return False
|
|
306
|
+
|
|
307
|
+
return True
|
|
308
|
+
|
|
309
|
+
async def setFilter(self, filter: str, value: str) -> str:
|
|
310
|
+
self.filter_map[filter] = value
|
|
311
|
+
switch = 0
|
|
312
|
+
for filter in self.filter_map.keys():
|
|
313
|
+
value = self.filter_map[filter]
|
|
314
|
+
if filter == "FILTER_50Hz":
|
|
315
|
+
if value == "ON":
|
|
316
|
+
switch |= 1
|
|
317
|
+
elif filter == "FILTER_60Hz":
|
|
318
|
+
if value == "ON":
|
|
319
|
+
switch |= 2
|
|
320
|
+
elif filter == "FILTER_HPF":
|
|
321
|
+
if value == "ON":
|
|
322
|
+
switch |= 4
|
|
323
|
+
elif filter == "FILTER_LPF":
|
|
324
|
+
if value == "ON":
|
|
325
|
+
switch |= 8
|
|
326
|
+
try:
|
|
327
|
+
await self.gForce.set_firmware_filter_switch(switch)
|
|
328
|
+
await asyncio.sleep(0.1)
|
|
329
|
+
return "OK"
|
|
330
|
+
except Exception as e:
|
|
331
|
+
return "ERROR: " + str(e)
|
|
332
|
+
|
|
333
|
+
async def setDebugCSV(self, debugFilePath) -> str:
|
|
334
|
+
if self.debugCSVWriter != None:
|
|
335
|
+
self.debugCSVWriter = None
|
|
336
|
+
if debugFilePath != None:
|
|
337
|
+
self.debugCSVPath = debugFilePath
|
|
338
|
+
try:
|
|
339
|
+
if self.debugCSVPath != "":
|
|
340
|
+
CSVWriter = csv.writer(open(self.debugCSVPath, "w", newline=""), delimiter=",")
|
|
341
|
+
CSVWriter = None
|
|
342
|
+
except Exception as e:
|
|
343
|
+
return "ERROR: " + str(e)
|
|
344
|
+
return "OK"
|
|
345
|
+
|
|
346
|
+
####################################################################################
|
|
289
347
|
|
|
290
348
|
async def process_data(self, buf: Queue[SensorData], sensor, callback):
|
|
291
349
|
while self._is_running and self._rawDataBuffer.empty():
|
|
292
|
-
await asyncio.sleep(0.
|
|
350
|
+
await asyncio.sleep(0.1)
|
|
293
351
|
|
|
294
352
|
while self._is_running and not self._rawDataBuffer.empty():
|
|
295
353
|
try:
|
|
@@ -297,22 +355,23 @@ class SensorProfileDataCtx:
|
|
|
297
355
|
except Exception as e:
|
|
298
356
|
continue
|
|
299
357
|
|
|
300
|
-
self.
|
|
358
|
+
if self.isDataTransfering:
|
|
359
|
+
self._processDataPackage(data, buf, sensor)
|
|
301
360
|
self._rawDataBuffer.task_done()
|
|
302
361
|
|
|
303
|
-
|
|
304
|
-
|
|
362
|
+
while self._is_running and self.isDataTransfering and not buf.empty():
|
|
363
|
+
sensorData: SensorData = None
|
|
364
|
+
try:
|
|
365
|
+
sensorData = buf.get_nowait()
|
|
366
|
+
except Exception as e:
|
|
367
|
+
break
|
|
368
|
+
if sensorData != None and callback != None:
|
|
305
369
|
try:
|
|
306
|
-
|
|
370
|
+
asyncio.get_event_loop().run_in_executor(self.dataPool, callback, sensor, sensorData)
|
|
307
371
|
except Exception as e:
|
|
308
|
-
|
|
309
|
-
if sensorData != None and callback != None:
|
|
310
|
-
try:
|
|
311
|
-
asyncio.get_event_loop().run_in_executor(self.dataPool, callback, sensor, sensorData)
|
|
312
|
-
except Exception as e:
|
|
313
|
-
print(e)
|
|
372
|
+
print(e)
|
|
314
373
|
|
|
315
|
-
|
|
374
|
+
buf.task_done()
|
|
316
375
|
|
|
317
376
|
def _processDataPackage(self, data: bytes, buf: Queue[SensorData], sensor):
|
|
318
377
|
v = data[0]
|
|
@@ -527,6 +586,31 @@ class SensorProfileDataCtx:
|
|
|
527
586
|
sensorDataResult.minPackageSampleCount = sensorData.minPackageSampleCount
|
|
528
587
|
sensorDataList.append(sensorDataResult)
|
|
529
588
|
|
|
589
|
+
if self.debugCSVPath != None and self.debugCSVPath != "" and self.debugCSVWriter == None:
|
|
590
|
+
try:
|
|
591
|
+
self.debugCSVWriter = csv.writer(open(self.debugCSVPath, "w", newline="", encoding="utf-8"))
|
|
592
|
+
header_append_keys = ["dataType", "sampleRate"]
|
|
593
|
+
channel_samples_header = list(vars(sensorDataResult.channelSamples[0][0]).keys())
|
|
594
|
+
for key_item in header_append_keys:
|
|
595
|
+
channel_samples_header.append(key_item)
|
|
596
|
+
self.debugCSVWriter.writerow(channel_samples_header)
|
|
597
|
+
except Exception as e:
|
|
598
|
+
print(e)
|
|
599
|
+
|
|
600
|
+
if self.debugCSVWriter != None:
|
|
601
|
+
try:
|
|
602
|
+
for i, channel_sample_list in enumerate(sensorDataResult.channelSamples):
|
|
603
|
+
for channel_sample in channel_sample_list:
|
|
604
|
+
row_data = []
|
|
605
|
+
|
|
606
|
+
for key in vars(channel_sample).keys():
|
|
607
|
+
row_data.append(getattr(channel_sample, key))
|
|
608
|
+
row_data.append(sensorDataResult.dataType)
|
|
609
|
+
row_data.append(sensorDataResult.sampleRate)
|
|
610
|
+
self.debugCSVWriter.writerow(row_data)
|
|
611
|
+
except Exception as e:
|
|
612
|
+
print(e)
|
|
613
|
+
|
|
530
614
|
startIndex += sensorData.minPackageSampleCount
|
|
531
615
|
|
|
532
616
|
leftChannelSamples = []
|
|
@@ -547,7 +631,7 @@ class SensorProfileDataCtx:
|
|
|
547
631
|
|
|
548
632
|
while self._is_running:
|
|
549
633
|
while self._is_running and self._rawDataBuffer.empty():
|
|
550
|
-
await asyncio.sleep(0.
|
|
634
|
+
await asyncio.sleep(0.1)
|
|
551
635
|
continue
|
|
552
636
|
|
|
553
637
|
try:
|
|
@@ -611,7 +695,7 @@ class SensorProfileDataCtx:
|
|
|
611
695
|
index += 1
|
|
612
696
|
continue
|
|
613
697
|
data_package = bytes(self._concatDataBuffer[index + 2 : index + 2 + n])
|
|
614
|
-
asyncio.get_event_loop().run_in_executor(
|
|
698
|
+
asyncio.get_event_loop().run_in_executor(None, self.gForce._on_cmd_response, None, data_package)
|
|
615
699
|
last_cut = index = index + 2 + n
|
|
616
700
|
|
|
617
701
|
else:
|
sensor/sensor_profile.py
CHANGED
|
@@ -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.utils import async_call, sync_call, async_exec
|
|
21
|
+
from 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"
|
|
@@ -61,6 +61,8 @@ class SensorProfile:
|
|
|
61
61
|
self._gforce: GForce = None
|
|
62
62
|
self._data_event_loop: asyncio.AbstractEventLoop = None
|
|
63
63
|
self._event_loop: asyncio.AbstractEventLoop = None
|
|
64
|
+
self._is_starting = False
|
|
65
|
+
self._is_setting_param = False
|
|
64
66
|
|
|
65
67
|
def __del__(self) -> None:
|
|
66
68
|
"""
|
|
@@ -239,6 +241,8 @@ class SensorProfile:
|
|
|
239
241
|
self._data_ctx = SensorProfileDataCtx(self._gforce, self._device.Address, self._raw_data_buf)
|
|
240
242
|
if self._data_ctx.isUniversalStream:
|
|
241
243
|
async_exec(self._process_universal_data())
|
|
244
|
+
else:
|
|
245
|
+
async_exec(self._process_data())
|
|
242
246
|
|
|
243
247
|
if self.deviceState == DeviceStateEx.Connected or self.deviceState == DeviceStateEx.Ready:
|
|
244
248
|
return True
|
|
@@ -288,8 +292,8 @@ class SensorProfile:
|
|
|
288
292
|
return await async_call(self._connect())
|
|
289
293
|
|
|
290
294
|
async def _waitForDisconnect(self) -> bool:
|
|
291
|
-
while self.deviceState != DeviceStateEx.Disconnected:
|
|
292
|
-
asyncio.sleep(1)
|
|
295
|
+
while not utils._terminated and self.deviceState != DeviceStateEx.Disconnected:
|
|
296
|
+
await asyncio.sleep(1)
|
|
293
297
|
return True
|
|
294
298
|
|
|
295
299
|
async def _disconnect(self) -> bool:
|
|
@@ -341,11 +345,13 @@ class SensorProfile:
|
|
|
341
345
|
if self._data_event_loop == None:
|
|
342
346
|
self._data_event_loop = asyncio.new_event_loop()
|
|
343
347
|
|
|
344
|
-
|
|
348
|
+
self._raw_data_buf.queue.clear()
|
|
345
349
|
self._data_buffer.queue.clear()
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
350
|
+
|
|
351
|
+
result = await self._data_ctx.start_streaming()
|
|
352
|
+
await asyncio.sleep(0.2)
|
|
353
|
+
|
|
354
|
+
self._is_starting = False
|
|
349
355
|
return result
|
|
350
356
|
|
|
351
357
|
def startDataNotification(self) -> bool:
|
|
@@ -355,6 +361,10 @@ class SensorProfile:
|
|
|
355
361
|
:return: bool: 如果开始数据通知成功,返回 True;否则返回 False。
|
|
356
362
|
|
|
357
363
|
"""
|
|
364
|
+
if self._is_starting:
|
|
365
|
+
return False
|
|
366
|
+
|
|
367
|
+
self._is_starting = True
|
|
358
368
|
return sync_call(self._startDataNotification())
|
|
359
369
|
|
|
360
370
|
async def asyncStartDataNotification(self) -> bool:
|
|
@@ -364,6 +374,10 @@ class SensorProfile:
|
|
|
364
374
|
:return: bool: 如果开始数据通知成功,返回 True;否则返回 False。
|
|
365
375
|
|
|
366
376
|
"""
|
|
377
|
+
if self._is_starting:
|
|
378
|
+
return False
|
|
379
|
+
|
|
380
|
+
self._is_starting = True
|
|
367
381
|
return await async_call(self._startDataNotification())
|
|
368
382
|
|
|
369
383
|
async def _stopDataNotification(self) -> bool:
|
|
@@ -377,7 +391,9 @@ class SensorProfile:
|
|
|
377
391
|
if not self._data_ctx.isDataTransfering:
|
|
378
392
|
return True
|
|
379
393
|
|
|
380
|
-
|
|
394
|
+
result = await self._data_ctx.stop_streaming()
|
|
395
|
+
self._is_starting = False
|
|
396
|
+
return not result
|
|
381
397
|
|
|
382
398
|
def stopDataNotification(self) -> bool:
|
|
383
399
|
"""
|
|
@@ -386,6 +402,10 @@ class SensorProfile:
|
|
|
386
402
|
:return: bool: 如果停止数据通知成功,返回 True;否则返回 False。
|
|
387
403
|
|
|
388
404
|
"""
|
|
405
|
+
if self._is_starting:
|
|
406
|
+
return False
|
|
407
|
+
|
|
408
|
+
self._is_starting = True
|
|
389
409
|
return sync_call(self._stopDataNotification())
|
|
390
410
|
|
|
391
411
|
async def asyncStopDataNotification(self) -> bool:
|
|
@@ -395,6 +415,10 @@ class SensorProfile:
|
|
|
395
415
|
:return: bool: 如果停止数据通知成功,返回 True;否则返回 False。
|
|
396
416
|
|
|
397
417
|
"""
|
|
418
|
+
if self._is_starting:
|
|
419
|
+
return False
|
|
420
|
+
|
|
421
|
+
self._is_starting = True
|
|
398
422
|
return await async_call(self._stopDataNotification())
|
|
399
423
|
|
|
400
424
|
async def _refresh_power(self):
|
|
@@ -473,6 +497,37 @@ class SensorProfile:
|
|
|
473
497
|
return self._data_ctx._device_info
|
|
474
498
|
return None
|
|
475
499
|
|
|
500
|
+
async def _setParam(self, key: str, value: str) -> str:
|
|
501
|
+
result = "Error: Not supported"
|
|
502
|
+
if self.deviceState != DeviceStateEx.Ready:
|
|
503
|
+
result = "Error: Please connect first"
|
|
504
|
+
|
|
505
|
+
if key in ["NTF_EMG", "NTF_EEG", "NTF_ECG", "NTF_IMU", "NTF_BRTH"]:
|
|
506
|
+
if value in ["ON", "OFF"]:
|
|
507
|
+
self._data_ctx.init_map[key] = value
|
|
508
|
+
result = "OK"
|
|
509
|
+
|
|
510
|
+
if key in ["FILTER_50Hz", "FILTER_60Hz", "FILTER_HPF", "FILTER_LPF"]:
|
|
511
|
+
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
|
+
result = await self._data_ctx.setFilter(key, value)
|
|
521
|
+
if needPauseTransfer:
|
|
522
|
+
self._is_starting = True
|
|
523
|
+
await self._startDataNotification()
|
|
524
|
+
|
|
525
|
+
if key == "DEBUG_BLE_DATA_PATH":
|
|
526
|
+
result = await self._data_ctx.setDebugCSV(value)
|
|
527
|
+
|
|
528
|
+
self._is_setting_param = False
|
|
529
|
+
return result
|
|
530
|
+
|
|
476
531
|
def setParam(self, key: str, value: str) -> str:
|
|
477
532
|
"""
|
|
478
533
|
设置传感器的参数。
|
|
@@ -483,9 +538,16 @@ class SensorProfile:
|
|
|
483
538
|
:return: str: 设置参数的结果。
|
|
484
539
|
|
|
485
540
|
"""
|
|
486
|
-
|
|
541
|
+
if self._is_setting_param:
|
|
542
|
+
return "Error: Please wait for the previous operation to complete"
|
|
487
543
|
|
|
488
|
-
|
|
544
|
+
self._is_setting_param = True
|
|
545
|
+
return sync_call(
|
|
546
|
+
self._setParam(key, value),
|
|
547
|
+
20,
|
|
548
|
+
)
|
|
549
|
+
|
|
550
|
+
async def asyncSetParam(self, key: str, value: str) -> str:
|
|
489
551
|
"""
|
|
490
552
|
设置传感器的参数。
|
|
491
553
|
|
|
@@ -495,4 +557,11 @@ class SensorProfile:
|
|
|
495
557
|
:return: str: 设置参数的结果。
|
|
496
558
|
|
|
497
559
|
"""
|
|
498
|
-
|
|
560
|
+
if self._is_setting_param:
|
|
561
|
+
return "Error: Please wait for the previous operation to complete"
|
|
562
|
+
|
|
563
|
+
self._is_setting_param = True
|
|
564
|
+
return await async_call(
|
|
565
|
+
self._setParam(key, value),
|
|
566
|
+
20,
|
|
567
|
+
)
|
sensor/utils.py
CHANGED
|
@@ -37,30 +37,6 @@ def Terminate():
|
|
|
37
37
|
pass
|
|
38
38
|
|
|
39
39
|
|
|
40
|
-
async def delay(_time: float, function) -> any:
|
|
41
|
-
try:
|
|
42
|
-
await asyncio.sleep(_time)
|
|
43
|
-
except Exception as e:
|
|
44
|
-
pass
|
|
45
|
-
|
|
46
|
-
try:
|
|
47
|
-
return await function
|
|
48
|
-
except Exception as e:
|
|
49
|
-
pass
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
def timer(_delay: float, function):
|
|
53
|
-
checkRunLoop()
|
|
54
|
-
task: asyncio.Future = None
|
|
55
|
-
try:
|
|
56
|
-
task = asyncio.run_coroutine_threadsafe(delay(_delay, function), _runloop)
|
|
57
|
-
running_tasks.add(task)
|
|
58
|
-
task.add_done_callback(lambda t: running_tasks.remove(t))
|
|
59
|
-
except Exception as e:
|
|
60
|
-
print(e)
|
|
61
|
-
pass
|
|
62
|
-
|
|
63
|
-
|
|
64
40
|
def async_exec(function):
|
|
65
41
|
checkRunLoop()
|
|
66
42
|
task: asyncio.Future = None
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: sensor-sdk
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.15
|
|
4
4
|
Summary: Python sdk for Synchroni
|
|
5
5
|
Home-page: https://github.com/oymotion/SynchroniSDKPython
|
|
6
6
|
Author: Martin Ye
|
|
@@ -350,8 +350,47 @@ batteryPower = sensorProfile.getBatteryLevel()
|
|
|
350
350
|
|
|
351
351
|
Please check console.py in examples directory
|
|
352
352
|
|
|
353
|
-
|
|
353
|
+
### Async methods
|
|
354
354
|
|
|
355
355
|
all methods start with async is async methods, they has same params and return result as sync methods.
|
|
356
356
|
|
|
357
357
|
Please check async_console.py in examples directory
|
|
358
|
+
|
|
359
|
+
### setParam method
|
|
360
|
+
|
|
361
|
+
Use `def setParam(self, key: str, value: str) -> str` to set parameter of sensor profile. Please call after device in 'Ready' state.
|
|
362
|
+
|
|
363
|
+
Below is available key and value:
|
|
364
|
+
|
|
365
|
+
```python
|
|
366
|
+
result = sensorProfile.setParam("NTF_EMG", "ON")
|
|
367
|
+
# set EMG data to ON or OFF, result is "OK" if succeed
|
|
368
|
+
|
|
369
|
+
result = sensorProfile.setParam("NTF_EEG", "ON")
|
|
370
|
+
# set EEG data to ON or OFF, result is "OK" if succeed
|
|
371
|
+
|
|
372
|
+
result = sensorProfile.setParam("NTF_ECG", "ON")
|
|
373
|
+
# set ECG data to ON or OFF, result is "OK" if succeed
|
|
374
|
+
|
|
375
|
+
result = sensorProfile.setParam("NTF_IMU", "ON")
|
|
376
|
+
# set IMU data to ON or OFF, result is "OK" if succeed
|
|
377
|
+
|
|
378
|
+
result = sensorProfile.setParam("NTF_BRTH", "ON")
|
|
379
|
+
# set BRTH data to ON or OFF, result is "OK" if succeed
|
|
380
|
+
|
|
381
|
+
result = sensorProfile.setParam("FILTER_50Hz", "ON")
|
|
382
|
+
# set 50Hz notch filter to ON or OFF, result is "OK" if succeed
|
|
383
|
+
|
|
384
|
+
result = sensorProfile.setParam("FILTER_60Hz", "ON")
|
|
385
|
+
# set 60Hz notch filter to ON or OFF, result is "OK" if succeed
|
|
386
|
+
|
|
387
|
+
result = sensorProfile.setParam("FILTER_HPF", "ON")
|
|
388
|
+
# set 0.5Hz hpf filter to ON or OFF, result is "OK" if succeed
|
|
389
|
+
|
|
390
|
+
result = sensorProfile.setParam("FILTER_LPF", "ON")
|
|
391
|
+
# set 80Hz lpf filter to ON or OFF, result is "OK" if succeed
|
|
392
|
+
|
|
393
|
+
result = sensorProfile.setParam("DEBUG_BLE_DATA_PATH", "d:/temp/test.csv")
|
|
394
|
+
# set debug ble data path, result is "OK" if succeed
|
|
395
|
+
# please give an absolute path and make sure it is valid and writeable by yourself
|
|
396
|
+
```
|
|
@@ -0,0 +1,14 @@
|
|
|
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,,
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
sensor/__init__.py,sha256=L1VyAP0EDEnJIMeMTzp4iXHSRUUHyHScF_GIl3iYKRI,123
|
|
2
|
-
sensor/gforce.py,sha256=mTw0VVQSxPiTzZmjK7I9knTlTkEeu4PISQdlAkMU6WE,25232
|
|
3
|
-
sensor/sensor_controller.py,sha256=qnM9mVwpJn9PCnxlvbgWFeaLktqVnmaquZgasYGEHqs,9451
|
|
4
|
-
sensor/sensor_data.py,sha256=Hu7Ql0LgQ7V24xYZhaLrKPwU4KWZeWE655v8Gy8xphY,3934
|
|
5
|
-
sensor/sensor_data_context.py,sha256=Mlq0Bflnf6Lmj9cf7ccXYnjKldKD4pM9_x1GcgFynEs,25166
|
|
6
|
-
sensor/sensor_device.py,sha256=eO1vaqjxCc2UCPBoKXqlk6o498uRyWt6IYs7r7wXSD0,3042
|
|
7
|
-
sensor/sensor_profile.py,sha256=64MFNyLJajX6HeGS_tmN9R9wfEW1qjsP_MjH3ZRPq4s,17322
|
|
8
|
-
sensor/utils.py,sha256=FuBEChpJYbXnUaDvlta3aT6dYGAK2fQdGbIB7BYMQp4,7077
|
|
9
|
-
sensor_sdk-0.0.11.dist-info/LICENSE.txt,sha256=8CSivOpub3IuXODTyqBRI91AxouJZk02YrcKuOAkWu8,1111
|
|
10
|
-
sensor_sdk-0.0.11.dist-info/METADATA,sha256=VMpmAjRXMlk8u-UnHu_QrXULi0-YMxSdRSGDwPmCdPs,8375
|
|
11
|
-
sensor_sdk-0.0.11.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
|
|
12
|
-
sensor_sdk-0.0.11.dist-info/top_level.txt,sha256=Ftq49B6bH0Ffdc7c8LkcyakHo6lsg_snlBbpEUoILSk,7
|
|
13
|
-
sensor_sdk-0.0.11.dist-info/zip-safe,sha256=frcCV1k9oG9oKj3dpUqdJg1PxRT2RSN_XKdLCPjaYaY,2
|
|
14
|
-
sensor_sdk-0.0.11.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|