sensor-sdk 0.0.13__tar.gz → 0.0.15__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.
Potentially problematic release.
This version of sensor-sdk might be problematic. Click here for more details.
- {sensor-sdk-0.0.13 → sensor-sdk-0.0.15}/PKG-INFO +1 -1
- {sensor-sdk-0.0.13 → sensor-sdk-0.0.15}/README.md +382 -382
- {sensor-sdk-0.0.13 → sensor-sdk-0.0.15}/sensor/gforce.py +4 -4
- {sensor-sdk-0.0.13 → sensor-sdk-0.0.15}/sensor/sensor_data_context.py +34 -20
- {sensor-sdk-0.0.13 → sensor-sdk-0.0.15}/sensor/sensor_profile.py +57 -11
- {sensor-sdk-0.0.13 → sensor-sdk-0.0.15}/sensor_sdk.egg-info/PKG-INFO +1 -1
- {sensor-sdk-0.0.13 → sensor-sdk-0.0.15}/setup.py +1 -1
- {sensor-sdk-0.0.13 → sensor-sdk-0.0.15}/LICENSE.txt +0 -0
- {sensor-sdk-0.0.13 → sensor-sdk-0.0.15}/sensor/__init__.py +0 -0
- {sensor-sdk-0.0.13 → sensor-sdk-0.0.15}/sensor/sensor_controller.py +0 -0
- {sensor-sdk-0.0.13 → sensor-sdk-0.0.15}/sensor/sensor_data.py +0 -0
- {sensor-sdk-0.0.13 → sensor-sdk-0.0.15}/sensor/sensor_device.py +0 -0
- {sensor-sdk-0.0.13 → sensor-sdk-0.0.15}/sensor/utils.py +0 -0
- {sensor-sdk-0.0.13 → sensor-sdk-0.0.15}/sensor_sdk.egg-info/SOURCES.txt +0 -0
- {sensor-sdk-0.0.13 → sensor-sdk-0.0.15}/sensor_sdk.egg-info/dependency_links.txt +0 -0
- {sensor-sdk-0.0.13 → sensor-sdk-0.0.15}/sensor_sdk.egg-info/requires.txt +0 -0
- {sensor-sdk-0.0.13 → sensor-sdk-0.0.15}/sensor_sdk.egg-info/top_level.txt +0 -0
- {sensor-sdk-0.0.13 → sensor-sdk-0.0.15}/sensor_sdk.egg-info/zip-safe +0 -0
- {sensor-sdk-0.0.13 → sensor-sdk-0.0.15}/setup.cfg +0 -0
|
@@ -1,382 +1,382 @@
|
|
|
1
|
-
# sensor-sdk
|
|
2
|
-
|
|
3
|
-
Synchroni sdk for Python
|
|
4
|
-
|
|
5
|
-
## Brief
|
|
6
|
-
|
|
7
|
-
Synchroni SDK is the software development kit for developers to access Synchroni products.
|
|
8
|
-
|
|
9
|
-
## Contributing
|
|
10
|
-
|
|
11
|
-
See the [contributing guide](CONTRIBUTING.md) to learn how to contribute to the repository and the development workflow.
|
|
12
|
-
|
|
13
|
-
## License
|
|
14
|
-
|
|
15
|
-
MIT
|
|
16
|
-
|
|
17
|
-
---
|
|
18
|
-
|
|
19
|
-
## Installation
|
|
20
|
-
|
|
21
|
-
```sh
|
|
22
|
-
pip install sensor-sdk
|
|
23
|
-
```
|
|
24
|
-
|
|
25
|
-
## 1. Permission
|
|
26
|
-
|
|
27
|
-
Application will obtain bluetooth permission by itself.
|
|
28
|
-
|
|
29
|
-
## 2. Import SDK
|
|
30
|
-
|
|
31
|
-
```python
|
|
32
|
-
from sensor import *
|
|
33
|
-
```
|
|
34
|
-
|
|
35
|
-
## SensorController methods
|
|
36
|
-
|
|
37
|
-
### 1. Initalize
|
|
38
|
-
|
|
39
|
-
```python
|
|
40
|
-
SensorControllerInstance = SensorController()
|
|
41
|
-
|
|
42
|
-
# register scan listener
|
|
43
|
-
if not SensorControllerInstance.hasDeviceFoundCallback:
|
|
44
|
-
def on_device_callback(deviceList: List[BLEDevice]):
|
|
45
|
-
# return all devices doesn't connected
|
|
46
|
-
pass
|
|
47
|
-
SensorControllerInstance.onDeviceFoundCallback = on_device_callback
|
|
48
|
-
```
|
|
49
|
-
|
|
50
|
-
### 2. Start scan
|
|
51
|
-
|
|
52
|
-
Use `def startScan(period_in_ms: int) -> bool` to start scan
|
|
53
|
-
|
|
54
|
-
```python
|
|
55
|
-
success = SensorControllerInstance.startScan(6000)
|
|
56
|
-
```
|
|
57
|
-
|
|
58
|
-
returns true if start scan success, periodInMS means onDeviceCallback will be called every periodInMS
|
|
59
|
-
|
|
60
|
-
Use `def scan(period_in_ms: int) -> list[BLEDevice]` to scan once time
|
|
61
|
-
|
|
62
|
-
```python
|
|
63
|
-
bleDevices = SensorControllerInstance.scan(6000)
|
|
64
|
-
```
|
|
65
|
-
|
|
66
|
-
### 3. Stop scan
|
|
67
|
-
|
|
68
|
-
Use `def stopScan() -> None` to stop scan
|
|
69
|
-
|
|
70
|
-
```python
|
|
71
|
-
SensorControllerInstance.stopScan()
|
|
72
|
-
```
|
|
73
|
-
|
|
74
|
-
### 4. Check scaning
|
|
75
|
-
|
|
76
|
-
Use `property isScanning: bool` to check scanning status
|
|
77
|
-
|
|
78
|
-
```python
|
|
79
|
-
isScanning = SensorControllerInstance.isScanning
|
|
80
|
-
```
|
|
81
|
-
|
|
82
|
-
### 5. Check if bluetooth is enabled
|
|
83
|
-
|
|
84
|
-
Use `property isEnabled: bool` to check if bluetooth is enabled
|
|
85
|
-
|
|
86
|
-
```python
|
|
87
|
-
isEnabled = SensorControllerInstance.isEnabled
|
|
88
|
-
```
|
|
89
|
-
|
|
90
|
-
### 6. Create SensorProfile
|
|
91
|
-
|
|
92
|
-
Use `def requireSensor(device: BLEDevice) -> SensorProfile | None` to create SensorProfile.
|
|
93
|
-
|
|
94
|
-
If bleDevice is invalid, result is None.
|
|
95
|
-
|
|
96
|
-
```python
|
|
97
|
-
sensorProfile = SensorControllerInstance.requireSensor(bleDevice)
|
|
98
|
-
```
|
|
99
|
-
|
|
100
|
-
### 7. Get SensorProfile
|
|
101
|
-
|
|
102
|
-
Use `def getSensor(device: BLEDevice) -> SensorProfile | None` to get SensorProfile.
|
|
103
|
-
|
|
104
|
-
If SensorProfile didn't created, result is None.
|
|
105
|
-
|
|
106
|
-
```python
|
|
107
|
-
sensorProfile = SensorControllerInstance.getSensor(bleDevice)
|
|
108
|
-
```
|
|
109
|
-
|
|
110
|
-
### 8. Get Connected SensorProfiles
|
|
111
|
-
|
|
112
|
-
Use `def getConnectedSensors() -> list[SensorProfile]` to get connected SensorProfiles.
|
|
113
|
-
|
|
114
|
-
```python
|
|
115
|
-
sensorProfiles = SensorControllerInstance.getConnectedSensors()
|
|
116
|
-
```
|
|
117
|
-
|
|
118
|
-
### 9. Get Connected BLE Devices
|
|
119
|
-
|
|
120
|
-
Use `def getConnectedDevices() -> list[BLEDevice]` to get connected BLE Devices.
|
|
121
|
-
|
|
122
|
-
```python
|
|
123
|
-
bleDevices = SensorControllerInstance.getConnectedDevices()
|
|
124
|
-
```
|
|
125
|
-
|
|
126
|
-
### 10. Terminate
|
|
127
|
-
|
|
128
|
-
Use `def terminate()` to terminate sdk
|
|
129
|
-
|
|
130
|
-
```python
|
|
131
|
-
|
|
132
|
-
def terminate():
|
|
133
|
-
SensorControllerInstance.terminate()
|
|
134
|
-
exit()
|
|
135
|
-
|
|
136
|
-
def main():
|
|
137
|
-
signal.signal(signal.SIGINT, lambda signal, frame: terminate())
|
|
138
|
-
time.sleep(30)
|
|
139
|
-
SensorControllerInstance.terminate()
|
|
140
|
-
|
|
141
|
-
Please MAKE SURE to call terminate when exit main() or press Ctrl+C
|
|
142
|
-
```
|
|
143
|
-
|
|
144
|
-
## SensorProfile methods
|
|
145
|
-
|
|
146
|
-
### 11. Initalize
|
|
147
|
-
|
|
148
|
-
Please register callbacks for SensorProfile
|
|
149
|
-
|
|
150
|
-
```python
|
|
151
|
-
sensorProfile = SensorControllerInstance.requireSensor(bleDevice)
|
|
152
|
-
|
|
153
|
-
# register callbacks
|
|
154
|
-
def on_state_changed(sensor, newState):
|
|
155
|
-
# please do logic when device disconnected unexpected
|
|
156
|
-
pass
|
|
157
|
-
|
|
158
|
-
def on_error_callback(sensor, reason):
|
|
159
|
-
# called when error occurs
|
|
160
|
-
pass
|
|
161
|
-
|
|
162
|
-
def on_power_changed(sensor, power):
|
|
163
|
-
# callback for get battery level of device, power from 0 - 100, -1 is invalid
|
|
164
|
-
pass
|
|
165
|
-
|
|
166
|
-
def on_data_callback(sensor, data):
|
|
167
|
-
# called after start data transfer
|
|
168
|
-
pass
|
|
169
|
-
|
|
170
|
-
sensorProfile.onStateChanged = on_state_changed
|
|
171
|
-
sensorProfile.onErrorCallback = on_error_callback
|
|
172
|
-
sensorProfile.onPowerChanged = on_power_changed
|
|
173
|
-
sensorProfile.onDataCallback = on_data_callback
|
|
174
|
-
```
|
|
175
|
-
|
|
176
|
-
### 12. Connect device
|
|
177
|
-
|
|
178
|
-
Use `def connect() -> bool` to connect.
|
|
179
|
-
|
|
180
|
-
```python
|
|
181
|
-
success = sensorProfile.connect()
|
|
182
|
-
```
|
|
183
|
-
|
|
184
|
-
### 13. Disconnect
|
|
185
|
-
|
|
186
|
-
Use `def disconnect() -> bool` to disconnect.
|
|
187
|
-
|
|
188
|
-
```python
|
|
189
|
-
success = sensorProfile.disconnect()
|
|
190
|
-
```
|
|
191
|
-
|
|
192
|
-
### 14. Get device status
|
|
193
|
-
|
|
194
|
-
Use `property deviceState: DeviceStateEx` to get device status.
|
|
195
|
-
|
|
196
|
-
Please send command in 'Ready' state, should be after connect() return True.
|
|
197
|
-
|
|
198
|
-
```python
|
|
199
|
-
deviceStateEx = sensorProfile.deviceState
|
|
200
|
-
|
|
201
|
-
# deviceStateEx has define:
|
|
202
|
-
# class DeviceStateEx(Enum):
|
|
203
|
-
# Disconnected = 0
|
|
204
|
-
# Connecting = 1
|
|
205
|
-
# Connected = 2
|
|
206
|
-
# Ready = 3
|
|
207
|
-
# Disconnecting = 4
|
|
208
|
-
# Invalid = 5
|
|
209
|
-
```
|
|
210
|
-
|
|
211
|
-
### 15. Get BLE device of SensorProfile
|
|
212
|
-
|
|
213
|
-
Use `property BLEDevice: BLEDevice` to get BLE device of SensorProfile.
|
|
214
|
-
|
|
215
|
-
```python
|
|
216
|
-
bleDevice = sensorProfile.BLEDevice
|
|
217
|
-
```
|
|
218
|
-
|
|
219
|
-
### 16. Get device info of SensorProfile
|
|
220
|
-
|
|
221
|
-
Use `def getDeviceInfo() -> dict | None` to get device info of SensorProfile.
|
|
222
|
-
|
|
223
|
-
Please call after device in 'Ready' state, return None if it's not connected.
|
|
224
|
-
|
|
225
|
-
```python
|
|
226
|
-
deviceInfo = sensorProfile.getDeviceInfo()
|
|
227
|
-
|
|
228
|
-
# deviceInfo has defines:
|
|
229
|
-
# deviceInfo = {
|
|
230
|
-
# "deviceName": str,
|
|
231
|
-
# "modelName": str,
|
|
232
|
-
# "hardwareVersion": str,
|
|
233
|
-
# "firmwareVersion": str,
|
|
234
|
-
# "emgChannelCount": int,
|
|
235
|
-
# "eegChannelCount": int,
|
|
236
|
-
# "ecgChannelCount": int,
|
|
237
|
-
# "accChannelCount": int,
|
|
238
|
-
# "gyroChannelCount": int,
|
|
239
|
-
# "brthChannelCount": int,
|
|
240
|
-
# "mtuSize": int
|
|
241
|
-
# }
|
|
242
|
-
```
|
|
243
|
-
|
|
244
|
-
### 17. Init data transfer
|
|
245
|
-
|
|
246
|
-
Use `def init(packageSampleCount: int, powerRefreshInterval: int) -> bool`.
|
|
247
|
-
|
|
248
|
-
Please call after device in 'Ready' state, return True if init succeed.
|
|
249
|
-
|
|
250
|
-
```python
|
|
251
|
-
success = sensorProfile.init(5, 60*1000)
|
|
252
|
-
```
|
|
253
|
-
|
|
254
|
-
packageSampleCount: set sample counts of SensorData.channelSamples in onDataCallback()
|
|
255
|
-
powerRefreshInterval: callback period for onPowerChanged()
|
|
256
|
-
|
|
257
|
-
### 18. Check if init data transfer succeed
|
|
258
|
-
|
|
259
|
-
Use `property hasInited: bool` to check if init data transfer succeed.
|
|
260
|
-
|
|
261
|
-
```python
|
|
262
|
-
hasInited = sensorProfile.hasInited
|
|
263
|
-
```
|
|
264
|
-
|
|
265
|
-
### 19. DataNotify
|
|
266
|
-
|
|
267
|
-
Use `def startDataNotification() -> bool` to start data notification.
|
|
268
|
-
|
|
269
|
-
Please call if hasInited return True
|
|
270
|
-
|
|
271
|
-
#### 19.1 Start data transfer
|
|
272
|
-
|
|
273
|
-
```python
|
|
274
|
-
success = sensorProfile.startDataNotification()
|
|
275
|
-
```
|
|
276
|
-
|
|
277
|
-
Data type list:
|
|
278
|
-
|
|
279
|
-
```python
|
|
280
|
-
class DataType(Enum):
|
|
281
|
-
NTF_ACC = 0x1 # unit is g
|
|
282
|
-
NTF_GYRO = 0x2 # unit is degree/s
|
|
283
|
-
NTF_EEG = 0x10 # unit is uV
|
|
284
|
-
NTF_ECG = 0x11 # unit is uV
|
|
285
|
-
NTF_BRTH = 0x15 # unit is uV
|
|
286
|
-
```
|
|
287
|
-
|
|
288
|
-
Process data in onDataCallback.
|
|
289
|
-
|
|
290
|
-
```python
|
|
291
|
-
def on_data_callback(sensor, data):
|
|
292
|
-
if data.dataType == DataType.NTF_EEG:
|
|
293
|
-
pass
|
|
294
|
-
elif data.dataType == DataType.NTF_ECG:
|
|
295
|
-
pass
|
|
296
|
-
|
|
297
|
-
# process data as you wish
|
|
298
|
-
for oneChannelSamples in data.channelSamples:
|
|
299
|
-
for sample in oneChannelSamples:
|
|
300
|
-
if sample.isLost:
|
|
301
|
-
# do some logic
|
|
302
|
-
pass
|
|
303
|
-
else:
|
|
304
|
-
# draw with sample.data & sample.channelIndex
|
|
305
|
-
# print(f"{sample.channelIndex} | {sample.sampleIndex} | {sample.data} | {sample.impedance}")
|
|
306
|
-
pass
|
|
307
|
-
|
|
308
|
-
sensorProfile.onDataCallback = on_data_callback
|
|
309
|
-
```
|
|
310
|
-
|
|
311
|
-
#### 19.2 Stop data transfer
|
|
312
|
-
|
|
313
|
-
Use `def stopDataNotification() -> bool` to stop data transfer.
|
|
314
|
-
|
|
315
|
-
```python
|
|
316
|
-
success = sensorProfile.stopDataNotification()
|
|
317
|
-
```
|
|
318
|
-
|
|
319
|
-
#### 19.3 Check if it's data transfering
|
|
320
|
-
|
|
321
|
-
Use `property isDataTransfering: bool` to check if it's data transfering.
|
|
322
|
-
|
|
323
|
-
```python
|
|
324
|
-
isDataTransfering = sensorProfile.isDataTransfering
|
|
325
|
-
```
|
|
326
|
-
|
|
327
|
-
### 20. Get battery level
|
|
328
|
-
|
|
329
|
-
Use `def getBatteryLevel() -> int` to get battery level. Please call after device in 'Ready' state.
|
|
330
|
-
|
|
331
|
-
```python
|
|
332
|
-
batteryPower = sensorProfile.getBatteryLevel()
|
|
333
|
-
|
|
334
|
-
# batteryPower is battery level returned, value ranges from 0 to 100, 0 means out of battery, while 100 means full.
|
|
335
|
-
```
|
|
336
|
-
|
|
337
|
-
Please check console.py in examples directory
|
|
338
|
-
|
|
339
|
-
### Async methods
|
|
340
|
-
|
|
341
|
-
all methods start with async is async methods, they has same params and return result as sync methods.
|
|
342
|
-
|
|
343
|
-
Please check async_console.py in examples directory
|
|
344
|
-
|
|
345
|
-
### setParam method
|
|
346
|
-
|
|
347
|
-
Use `def setParam(self, key: str, value: str) -> str` to set parameter of sensor profile. Please call after device in 'Ready' state.
|
|
348
|
-
|
|
349
|
-
Below is available key and value:
|
|
350
|
-
|
|
351
|
-
```python
|
|
352
|
-
result = sensorProfile.setParam("NTF_EMG", "ON")
|
|
353
|
-
# set EMG data to ON or OFF, result is "OK" if succeed
|
|
354
|
-
|
|
355
|
-
result = sensorProfile.setParam("NTF_EEG", "ON")
|
|
356
|
-
# set EEG data to ON or OFF, result is "OK" if succeed
|
|
357
|
-
|
|
358
|
-
result = sensorProfile.setParam("NTF_ECG", "ON")
|
|
359
|
-
# set ECG data to ON or OFF, result is "OK" if succeed
|
|
360
|
-
|
|
361
|
-
result = sensorProfile.setParam("NTF_IMU", "ON")
|
|
362
|
-
# set IMU data to ON or OFF, result is "OK" if succeed
|
|
363
|
-
|
|
364
|
-
result = sensorProfile.setParam("NTF_BRTH", "ON")
|
|
365
|
-
# set BRTH data to ON or OFF, result is "OK" if succeed
|
|
366
|
-
|
|
367
|
-
result = sensorProfile.setParam("FILTER_50Hz", "ON")
|
|
368
|
-
# set 50Hz notch filter to ON or OFF, result is "OK" if succeed
|
|
369
|
-
|
|
370
|
-
result = sensorProfile.setParam("FILTER_60Hz", "ON")
|
|
371
|
-
# set 60Hz notch filter to ON or OFF, result is "OK" if succeed
|
|
372
|
-
|
|
373
|
-
result = sensorProfile.setParam("FILTER_HPF", "ON")
|
|
374
|
-
# set 0.5Hz hpf filter to ON or OFF, result is "OK" if succeed
|
|
375
|
-
|
|
376
|
-
result = sensorProfile.setParam("FILTER_LPF", "ON")
|
|
377
|
-
# set 80Hz lpf filter to ON or OFF, result is "OK" if succeed
|
|
378
|
-
|
|
379
|
-
result = sensorProfile.setParam("DEBUG_BLE_DATA_PATH", "d:/temp/test.csv")
|
|
380
|
-
# set debug ble data path, result is "OK" if succeed
|
|
381
|
-
# please give an absolute path and make sure it is valid and writeable by yourself
|
|
382
|
-
```
|
|
1
|
+
# sensor-sdk
|
|
2
|
+
|
|
3
|
+
Synchroni sdk for Python
|
|
4
|
+
|
|
5
|
+
## Brief
|
|
6
|
+
|
|
7
|
+
Synchroni SDK is the software development kit for developers to access Synchroni products.
|
|
8
|
+
|
|
9
|
+
## Contributing
|
|
10
|
+
|
|
11
|
+
See the [contributing guide](CONTRIBUTING.md) to learn how to contribute to the repository and the development workflow.
|
|
12
|
+
|
|
13
|
+
## License
|
|
14
|
+
|
|
15
|
+
MIT
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## Installation
|
|
20
|
+
|
|
21
|
+
```sh
|
|
22
|
+
pip install sensor-sdk
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## 1. Permission
|
|
26
|
+
|
|
27
|
+
Application will obtain bluetooth permission by itself.
|
|
28
|
+
|
|
29
|
+
## 2. Import SDK
|
|
30
|
+
|
|
31
|
+
```python
|
|
32
|
+
from sensor import *
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## SensorController methods
|
|
36
|
+
|
|
37
|
+
### 1. Initalize
|
|
38
|
+
|
|
39
|
+
```python
|
|
40
|
+
SensorControllerInstance = SensorController()
|
|
41
|
+
|
|
42
|
+
# register scan listener
|
|
43
|
+
if not SensorControllerInstance.hasDeviceFoundCallback:
|
|
44
|
+
def on_device_callback(deviceList: List[BLEDevice]):
|
|
45
|
+
# return all devices doesn't connected
|
|
46
|
+
pass
|
|
47
|
+
SensorControllerInstance.onDeviceFoundCallback = on_device_callback
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### 2. Start scan
|
|
51
|
+
|
|
52
|
+
Use `def startScan(period_in_ms: int) -> bool` to start scan
|
|
53
|
+
|
|
54
|
+
```python
|
|
55
|
+
success = SensorControllerInstance.startScan(6000)
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
returns true if start scan success, periodInMS means onDeviceCallback will be called every periodInMS
|
|
59
|
+
|
|
60
|
+
Use `def scan(period_in_ms: int) -> list[BLEDevice]` to scan once time
|
|
61
|
+
|
|
62
|
+
```python
|
|
63
|
+
bleDevices = SensorControllerInstance.scan(6000)
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### 3. Stop scan
|
|
67
|
+
|
|
68
|
+
Use `def stopScan() -> None` to stop scan
|
|
69
|
+
|
|
70
|
+
```python
|
|
71
|
+
SensorControllerInstance.stopScan()
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### 4. Check scaning
|
|
75
|
+
|
|
76
|
+
Use `property isScanning: bool` to check scanning status
|
|
77
|
+
|
|
78
|
+
```python
|
|
79
|
+
isScanning = SensorControllerInstance.isScanning
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### 5. Check if bluetooth is enabled
|
|
83
|
+
|
|
84
|
+
Use `property isEnabled: bool` to check if bluetooth is enabled
|
|
85
|
+
|
|
86
|
+
```python
|
|
87
|
+
isEnabled = SensorControllerInstance.isEnabled
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### 6. Create SensorProfile
|
|
91
|
+
|
|
92
|
+
Use `def requireSensor(device: BLEDevice) -> SensorProfile | None` to create SensorProfile.
|
|
93
|
+
|
|
94
|
+
If bleDevice is invalid, result is None.
|
|
95
|
+
|
|
96
|
+
```python
|
|
97
|
+
sensorProfile = SensorControllerInstance.requireSensor(bleDevice)
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### 7. Get SensorProfile
|
|
101
|
+
|
|
102
|
+
Use `def getSensor(device: BLEDevice) -> SensorProfile | None` to get SensorProfile.
|
|
103
|
+
|
|
104
|
+
If SensorProfile didn't created, result is None.
|
|
105
|
+
|
|
106
|
+
```python
|
|
107
|
+
sensorProfile = SensorControllerInstance.getSensor(bleDevice)
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### 8. Get Connected SensorProfiles
|
|
111
|
+
|
|
112
|
+
Use `def getConnectedSensors() -> list[SensorProfile]` to get connected SensorProfiles.
|
|
113
|
+
|
|
114
|
+
```python
|
|
115
|
+
sensorProfiles = SensorControllerInstance.getConnectedSensors()
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### 9. Get Connected BLE Devices
|
|
119
|
+
|
|
120
|
+
Use `def getConnectedDevices() -> list[BLEDevice]` to get connected BLE Devices.
|
|
121
|
+
|
|
122
|
+
```python
|
|
123
|
+
bleDevices = SensorControllerInstance.getConnectedDevices()
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### 10. Terminate
|
|
127
|
+
|
|
128
|
+
Use `def terminate()` to terminate sdk
|
|
129
|
+
|
|
130
|
+
```python
|
|
131
|
+
|
|
132
|
+
def terminate():
|
|
133
|
+
SensorControllerInstance.terminate()
|
|
134
|
+
exit()
|
|
135
|
+
|
|
136
|
+
def main():
|
|
137
|
+
signal.signal(signal.SIGINT, lambda signal, frame: terminate())
|
|
138
|
+
time.sleep(30)
|
|
139
|
+
SensorControllerInstance.terminate()
|
|
140
|
+
|
|
141
|
+
Please MAKE SURE to call terminate when exit main() or press Ctrl+C
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
## SensorProfile methods
|
|
145
|
+
|
|
146
|
+
### 11. Initalize
|
|
147
|
+
|
|
148
|
+
Please register callbacks for SensorProfile
|
|
149
|
+
|
|
150
|
+
```python
|
|
151
|
+
sensorProfile = SensorControllerInstance.requireSensor(bleDevice)
|
|
152
|
+
|
|
153
|
+
# register callbacks
|
|
154
|
+
def on_state_changed(sensor, newState):
|
|
155
|
+
# please do logic when device disconnected unexpected
|
|
156
|
+
pass
|
|
157
|
+
|
|
158
|
+
def on_error_callback(sensor, reason):
|
|
159
|
+
# called when error occurs
|
|
160
|
+
pass
|
|
161
|
+
|
|
162
|
+
def on_power_changed(sensor, power):
|
|
163
|
+
# callback for get battery level of device, power from 0 - 100, -1 is invalid
|
|
164
|
+
pass
|
|
165
|
+
|
|
166
|
+
def on_data_callback(sensor, data):
|
|
167
|
+
# called after start data transfer
|
|
168
|
+
pass
|
|
169
|
+
|
|
170
|
+
sensorProfile.onStateChanged = on_state_changed
|
|
171
|
+
sensorProfile.onErrorCallback = on_error_callback
|
|
172
|
+
sensorProfile.onPowerChanged = on_power_changed
|
|
173
|
+
sensorProfile.onDataCallback = on_data_callback
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
### 12. Connect device
|
|
177
|
+
|
|
178
|
+
Use `def connect() -> bool` to connect.
|
|
179
|
+
|
|
180
|
+
```python
|
|
181
|
+
success = sensorProfile.connect()
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
### 13. Disconnect
|
|
185
|
+
|
|
186
|
+
Use `def disconnect() -> bool` to disconnect.
|
|
187
|
+
|
|
188
|
+
```python
|
|
189
|
+
success = sensorProfile.disconnect()
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
### 14. Get device status
|
|
193
|
+
|
|
194
|
+
Use `property deviceState: DeviceStateEx` to get device status.
|
|
195
|
+
|
|
196
|
+
Please send command in 'Ready' state, should be after connect() return True.
|
|
197
|
+
|
|
198
|
+
```python
|
|
199
|
+
deviceStateEx = sensorProfile.deviceState
|
|
200
|
+
|
|
201
|
+
# deviceStateEx has define:
|
|
202
|
+
# class DeviceStateEx(Enum):
|
|
203
|
+
# Disconnected = 0
|
|
204
|
+
# Connecting = 1
|
|
205
|
+
# Connected = 2
|
|
206
|
+
# Ready = 3
|
|
207
|
+
# Disconnecting = 4
|
|
208
|
+
# Invalid = 5
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
### 15. Get BLE device of SensorProfile
|
|
212
|
+
|
|
213
|
+
Use `property BLEDevice: BLEDevice` to get BLE device of SensorProfile.
|
|
214
|
+
|
|
215
|
+
```python
|
|
216
|
+
bleDevice = sensorProfile.BLEDevice
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
### 16. Get device info of SensorProfile
|
|
220
|
+
|
|
221
|
+
Use `def getDeviceInfo() -> dict | None` to get device info of SensorProfile.
|
|
222
|
+
|
|
223
|
+
Please call after device in 'Ready' state, return None if it's not connected.
|
|
224
|
+
|
|
225
|
+
```python
|
|
226
|
+
deviceInfo = sensorProfile.getDeviceInfo()
|
|
227
|
+
|
|
228
|
+
# deviceInfo has defines:
|
|
229
|
+
# deviceInfo = {
|
|
230
|
+
# "deviceName": str,
|
|
231
|
+
# "modelName": str,
|
|
232
|
+
# "hardwareVersion": str,
|
|
233
|
+
# "firmwareVersion": str,
|
|
234
|
+
# "emgChannelCount": int,
|
|
235
|
+
# "eegChannelCount": int,
|
|
236
|
+
# "ecgChannelCount": int,
|
|
237
|
+
# "accChannelCount": int,
|
|
238
|
+
# "gyroChannelCount": int,
|
|
239
|
+
# "brthChannelCount": int,
|
|
240
|
+
# "mtuSize": int
|
|
241
|
+
# }
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
### 17. Init data transfer
|
|
245
|
+
|
|
246
|
+
Use `def init(packageSampleCount: int, powerRefreshInterval: int) -> bool`.
|
|
247
|
+
|
|
248
|
+
Please call after device in 'Ready' state, return True if init succeed.
|
|
249
|
+
|
|
250
|
+
```python
|
|
251
|
+
success = sensorProfile.init(5, 60*1000)
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
packageSampleCount: set sample counts of SensorData.channelSamples in onDataCallback()
|
|
255
|
+
powerRefreshInterval: callback period for onPowerChanged()
|
|
256
|
+
|
|
257
|
+
### 18. Check if init data transfer succeed
|
|
258
|
+
|
|
259
|
+
Use `property hasInited: bool` to check if init data transfer succeed.
|
|
260
|
+
|
|
261
|
+
```python
|
|
262
|
+
hasInited = sensorProfile.hasInited
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
### 19. DataNotify
|
|
266
|
+
|
|
267
|
+
Use `def startDataNotification() -> bool` to start data notification.
|
|
268
|
+
|
|
269
|
+
Please call if hasInited return True
|
|
270
|
+
|
|
271
|
+
#### 19.1 Start data transfer
|
|
272
|
+
|
|
273
|
+
```python
|
|
274
|
+
success = sensorProfile.startDataNotification()
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
Data type list:
|
|
278
|
+
|
|
279
|
+
```python
|
|
280
|
+
class DataType(Enum):
|
|
281
|
+
NTF_ACC = 0x1 # unit is g
|
|
282
|
+
NTF_GYRO = 0x2 # unit is degree/s
|
|
283
|
+
NTF_EEG = 0x10 # unit is uV
|
|
284
|
+
NTF_ECG = 0x11 # unit is uV
|
|
285
|
+
NTF_BRTH = 0x15 # unit is uV
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
Process data in onDataCallback.
|
|
289
|
+
|
|
290
|
+
```python
|
|
291
|
+
def on_data_callback(sensor, data):
|
|
292
|
+
if data.dataType == DataType.NTF_EEG:
|
|
293
|
+
pass
|
|
294
|
+
elif data.dataType == DataType.NTF_ECG:
|
|
295
|
+
pass
|
|
296
|
+
|
|
297
|
+
# process data as you wish
|
|
298
|
+
for oneChannelSamples in data.channelSamples:
|
|
299
|
+
for sample in oneChannelSamples:
|
|
300
|
+
if sample.isLost:
|
|
301
|
+
# do some logic
|
|
302
|
+
pass
|
|
303
|
+
else:
|
|
304
|
+
# draw with sample.data & sample.channelIndex
|
|
305
|
+
# print(f"{sample.channelIndex} | {sample.sampleIndex} | {sample.data} | {sample.impedance}")
|
|
306
|
+
pass
|
|
307
|
+
|
|
308
|
+
sensorProfile.onDataCallback = on_data_callback
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
#### 19.2 Stop data transfer
|
|
312
|
+
|
|
313
|
+
Use `def stopDataNotification() -> bool` to stop data transfer.
|
|
314
|
+
|
|
315
|
+
```python
|
|
316
|
+
success = sensorProfile.stopDataNotification()
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
#### 19.3 Check if it's data transfering
|
|
320
|
+
|
|
321
|
+
Use `property isDataTransfering: bool` to check if it's data transfering.
|
|
322
|
+
|
|
323
|
+
```python
|
|
324
|
+
isDataTransfering = sensorProfile.isDataTransfering
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
### 20. Get battery level
|
|
328
|
+
|
|
329
|
+
Use `def getBatteryLevel() -> int` to get battery level. Please call after device in 'Ready' state.
|
|
330
|
+
|
|
331
|
+
```python
|
|
332
|
+
batteryPower = sensorProfile.getBatteryLevel()
|
|
333
|
+
|
|
334
|
+
# batteryPower is battery level returned, value ranges from 0 to 100, 0 means out of battery, while 100 means full.
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
Please check console.py in examples directory
|
|
338
|
+
|
|
339
|
+
### Async methods
|
|
340
|
+
|
|
341
|
+
all methods start with async is async methods, they has same params and return result as sync methods.
|
|
342
|
+
|
|
343
|
+
Please check async_console.py in examples directory
|
|
344
|
+
|
|
345
|
+
### setParam method
|
|
346
|
+
|
|
347
|
+
Use `def setParam(self, key: str, value: str) -> str` to set parameter of sensor profile. Please call after device in 'Ready' state.
|
|
348
|
+
|
|
349
|
+
Below is available key and value:
|
|
350
|
+
|
|
351
|
+
```python
|
|
352
|
+
result = sensorProfile.setParam("NTF_EMG", "ON")
|
|
353
|
+
# set EMG data to ON or OFF, result is "OK" if succeed
|
|
354
|
+
|
|
355
|
+
result = sensorProfile.setParam("NTF_EEG", "ON")
|
|
356
|
+
# set EEG data to ON or OFF, result is "OK" if succeed
|
|
357
|
+
|
|
358
|
+
result = sensorProfile.setParam("NTF_ECG", "ON")
|
|
359
|
+
# set ECG data to ON or OFF, result is "OK" if succeed
|
|
360
|
+
|
|
361
|
+
result = sensorProfile.setParam("NTF_IMU", "ON")
|
|
362
|
+
# set IMU data to ON or OFF, result is "OK" if succeed
|
|
363
|
+
|
|
364
|
+
result = sensorProfile.setParam("NTF_BRTH", "ON")
|
|
365
|
+
# set BRTH data to ON or OFF, result is "OK" if succeed
|
|
366
|
+
|
|
367
|
+
result = sensorProfile.setParam("FILTER_50Hz", "ON")
|
|
368
|
+
# set 50Hz notch filter to ON or OFF, result is "OK" if succeed
|
|
369
|
+
|
|
370
|
+
result = sensorProfile.setParam("FILTER_60Hz", "ON")
|
|
371
|
+
# set 60Hz notch filter to ON or OFF, result is "OK" if succeed
|
|
372
|
+
|
|
373
|
+
result = sensorProfile.setParam("FILTER_HPF", "ON")
|
|
374
|
+
# set 0.5Hz hpf filter to ON or OFF, result is "OK" if succeed
|
|
375
|
+
|
|
376
|
+
result = sensorProfile.setParam("FILTER_LPF", "ON")
|
|
377
|
+
# set 80Hz lpf filter to ON or OFF, result is "OK" if succeed
|
|
378
|
+
|
|
379
|
+
result = sensorProfile.setParam("DEBUG_BLE_DATA_PATH", "d:/temp/test.csv")
|
|
380
|
+
# set debug ble data path, result is "OK" if succeed
|
|
381
|
+
# please give an absolute path and make sure it is valid and writeable by yourself
|
|
382
|
+
```
|
|
@@ -853,10 +853,10 @@ class GForce:
|
|
|
853
853
|
|
|
854
854
|
async def stop_streaming(self):
|
|
855
855
|
exceptions = []
|
|
856
|
-
try:
|
|
857
|
-
|
|
858
|
-
except Exception as e:
|
|
859
|
-
|
|
856
|
+
# try:
|
|
857
|
+
# await asyncio.wait_for(self.set_subscription(DataSubscription.OFF), utils._TIMEOUT)
|
|
858
|
+
# except Exception as e:
|
|
859
|
+
# exceptions.append(e)
|
|
860
860
|
try:
|
|
861
861
|
await asyncio.wait_for(self.client.stop_notify(self.data_char), utils._TIMEOUT)
|
|
862
862
|
except Exception as e:
|
|
@@ -274,12 +274,15 @@ class SensorProfileDataCtx:
|
|
|
274
274
|
return True
|
|
275
275
|
self._is_data_transfering = True
|
|
276
276
|
self._rawDataBuffer.queue.clear()
|
|
277
|
+
self._concatDataBuffer.clear()
|
|
278
|
+
self.clear()
|
|
279
|
+
|
|
277
280
|
if not self.isUniversalStream:
|
|
278
281
|
await self.gForce.start_streaming(self._rawDataBuffer)
|
|
279
|
-
return True
|
|
280
282
|
else:
|
|
281
283
|
await self.gForce.set_subscription(self.notifyDataFlag)
|
|
282
|
-
|
|
284
|
+
|
|
285
|
+
return True
|
|
283
286
|
|
|
284
287
|
async def stop_streaming(self) -> bool:
|
|
285
288
|
if not self._is_data_transfering:
|
|
@@ -287,12 +290,21 @@ class SensorProfileDataCtx:
|
|
|
287
290
|
|
|
288
291
|
self._is_data_transfering = False
|
|
289
292
|
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
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
|
|
296
308
|
|
|
297
309
|
async def setFilter(self, filter: str, value: str) -> str:
|
|
298
310
|
self.filter_map[filter] = value
|
|
@@ -313,6 +325,7 @@ class SensorProfileDataCtx:
|
|
|
313
325
|
switch |= 8
|
|
314
326
|
try:
|
|
315
327
|
await self.gForce.set_firmware_filter_switch(switch)
|
|
328
|
+
await asyncio.sleep(0.1)
|
|
316
329
|
return "OK"
|
|
317
330
|
except Exception as e:
|
|
318
331
|
return "ERROR: " + str(e)
|
|
@@ -342,22 +355,23 @@ class SensorProfileDataCtx:
|
|
|
342
355
|
except Exception as e:
|
|
343
356
|
continue
|
|
344
357
|
|
|
345
|
-
self.
|
|
358
|
+
if self.isDataTransfering:
|
|
359
|
+
self._processDataPackage(data, buf, sensor)
|
|
346
360
|
self._rawDataBuffer.task_done()
|
|
347
361
|
|
|
348
|
-
|
|
349
|
-
|
|
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:
|
|
350
369
|
try:
|
|
351
|
-
|
|
370
|
+
asyncio.get_event_loop().run_in_executor(self.dataPool, callback, sensor, sensorData)
|
|
352
371
|
except Exception as e:
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
asyncio.get_event_loop().run_in_executor(self.dataPool, callback, sensor, sensorData)
|
|
357
|
-
except Exception as e:
|
|
358
|
-
print(e)
|
|
359
|
-
|
|
360
|
-
buf.task_done()
|
|
372
|
+
print(e)
|
|
373
|
+
|
|
374
|
+
buf.task_done()
|
|
361
375
|
|
|
362
376
|
def _processDataPackage(self, data: bytes, buf: Queue[SensorData], sensor):
|
|
363
377
|
v = data[0]
|
|
@@ -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,7 +292,7 @@ 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:
|
|
295
|
+
while not utils._terminated and self.deviceState != DeviceStateEx.Disconnected:
|
|
292
296
|
await asyncio.sleep(1)
|
|
293
297
|
return True
|
|
294
298
|
|
|
@@ -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):
|
|
@@ -474,21 +498,35 @@ class SensorProfile:
|
|
|
474
498
|
return None
|
|
475
499
|
|
|
476
500
|
async def _setParam(self, key: str, value: str) -> str:
|
|
501
|
+
result = "Error: Not supported"
|
|
477
502
|
if self.deviceState != DeviceStateEx.Ready:
|
|
478
|
-
|
|
503
|
+
result = "Error: Please connect first"
|
|
479
504
|
|
|
480
505
|
if key in ["NTF_EMG", "NTF_EEG", "NTF_ECG", "NTF_IMU", "NTF_BRTH"]:
|
|
481
506
|
if value in ["ON", "OFF"]:
|
|
482
507
|
self._data_ctx.init_map[key] = value
|
|
483
|
-
|
|
508
|
+
result = "OK"
|
|
484
509
|
|
|
485
510
|
if key in ["FILTER_50Hz", "FILTER_60Hz", "FILTER_HPF", "FILTER_LPF"]:
|
|
486
511
|
if value in ["ON", "OFF"]:
|
|
487
|
-
|
|
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()
|
|
488
524
|
|
|
489
525
|
if key == "DEBUG_BLE_DATA_PATH":
|
|
490
|
-
|
|
491
|
-
|
|
526
|
+
result = await self._data_ctx.setDebugCSV(value)
|
|
527
|
+
|
|
528
|
+
self._is_setting_param = False
|
|
529
|
+
return result
|
|
492
530
|
|
|
493
531
|
def setParam(self, key: str, value: str) -> str:
|
|
494
532
|
"""
|
|
@@ -500,6 +538,10 @@ class SensorProfile:
|
|
|
500
538
|
:return: str: 设置参数的结果。
|
|
501
539
|
|
|
502
540
|
"""
|
|
541
|
+
if self._is_setting_param:
|
|
542
|
+
return "Error: Please wait for the previous operation to complete"
|
|
543
|
+
|
|
544
|
+
self._is_setting_param = True
|
|
503
545
|
return sync_call(
|
|
504
546
|
self._setParam(key, value),
|
|
505
547
|
20,
|
|
@@ -515,6 +557,10 @@ class SensorProfile:
|
|
|
515
557
|
:return: str: 设置参数的结果。
|
|
516
558
|
|
|
517
559
|
"""
|
|
560
|
+
if self._is_setting_param:
|
|
561
|
+
return "Error: Please wait for the previous operation to complete"
|
|
562
|
+
|
|
563
|
+
self._is_setting_param = True
|
|
518
564
|
return await async_call(
|
|
519
565
|
self._setParam(key, value),
|
|
520
566
|
20,
|
|
@@ -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.
|
|
11
|
+
version="0.0.15",
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|