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_profile.py
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
1
|
# 设备状态枚举
|
|
4
2
|
# 该枚举类定义了设备的各种状态,用于表示设备在不同操作阶段的状态信息
|
|
5
3
|
from enum import Enum, IntEnum
|
|
@@ -15,6 +13,7 @@ from bleak import (
|
|
|
15
13
|
)
|
|
16
14
|
|
|
17
15
|
import sensor
|
|
16
|
+
from sensor import utils
|
|
18
17
|
from sensor.gforce import GForce
|
|
19
18
|
from sensor.sensor_data import DataType, Sample, SensorData
|
|
20
19
|
import asyncio
|
|
@@ -22,7 +21,7 @@ import threading
|
|
|
22
21
|
|
|
23
22
|
from sensor.sensor_data_context import SensorProfileDataCtx
|
|
24
23
|
from sensor.sensor_device import BLEDevice, DeviceInfo, DeviceStateEx
|
|
25
|
-
from sensor.utils import start_loop, sync_timer, timer
|
|
24
|
+
from sensor.utils import async_timer, start_loop, sync_timer, timer
|
|
26
25
|
from contextlib import suppress
|
|
27
26
|
from dataclasses import dataclass
|
|
28
27
|
|
|
@@ -42,27 +41,33 @@ class SensorProfile:
|
|
|
42
41
|
包含回调函数,用于处理传感器的状态变化、错误、数据接收和电量变化等事件。
|
|
43
42
|
"""
|
|
44
43
|
|
|
45
|
-
def __init__(
|
|
44
|
+
def __init__(
|
|
45
|
+
self,
|
|
46
|
+
device: bleak.BLEDevice,
|
|
47
|
+
adv: bleak.AdvertisementData,
|
|
48
|
+
mac: str,
|
|
49
|
+
gforce_event_loop: asyncio.AbstractEventLoop,
|
|
50
|
+
):
|
|
46
51
|
"""
|
|
47
52
|
初始化 SensorProfile 类的实例。
|
|
48
53
|
|
|
49
54
|
:param device (BLEDevice): 蓝牙设备对象,包含设备的名称、地址和信号强度等信息。
|
|
50
55
|
"""
|
|
51
56
|
self._detail_device = device
|
|
52
|
-
self._device = BLEDevice(device.name,
|
|
57
|
+
self._device = BLEDevice(device.name, mac, adv.rssi)
|
|
53
58
|
self._device_state = DeviceStateEx.Disconnected
|
|
54
|
-
self._on_state_changed: Callable[[
|
|
55
|
-
self._on_error_callback: Callable[[
|
|
56
|
-
self._on_data_callback: Callable[[
|
|
57
|
-
self._on_power_changed: Callable[[
|
|
59
|
+
self._on_state_changed: Callable[["SensorProfile", DeviceStateEx], None] = None
|
|
60
|
+
self._on_error_callback: Callable[["SensorProfile", str], None] = None
|
|
61
|
+
self._on_data_callback: Callable[["SensorProfile", SensorData], None] = None
|
|
62
|
+
self._on_power_changed: Callable[["SensorProfile", int], None] = None
|
|
58
63
|
self._power = -1
|
|
59
64
|
self._power_interval = 0
|
|
60
65
|
self._adv = adv
|
|
61
66
|
self._data_ctx: SensorProfileDataCtx = None
|
|
62
67
|
self._gforce: GForce = None
|
|
63
|
-
self._data_event_loop:asyncio.AbstractEventLoop = None
|
|
64
|
-
self._gforce_event_loop:asyncio.AbstractEventLoop = gforce_event_loop
|
|
65
|
-
self._event_loop:asyncio.AbstractEventLoop = None
|
|
68
|
+
self._data_event_loop: asyncio.AbstractEventLoop = None
|
|
69
|
+
self._gforce_event_loop: asyncio.AbstractEventLoop = gforce_event_loop
|
|
70
|
+
self._event_loop: asyncio.AbstractEventLoop = None
|
|
66
71
|
self._event_thread = None
|
|
67
72
|
|
|
68
73
|
def __del__(self) -> None:
|
|
@@ -73,23 +78,28 @@ class SensorProfile:
|
|
|
73
78
|
self._destroy()
|
|
74
79
|
|
|
75
80
|
def _destroy(self):
|
|
76
|
-
if
|
|
81
|
+
if (
|
|
82
|
+
self._device_state == DeviceStateEx.Connected
|
|
83
|
+
or self._device_state == DeviceStateEx.Ready
|
|
84
|
+
):
|
|
77
85
|
self.disconnect()
|
|
78
|
-
if
|
|
86
|
+
if self._data_event_loop != None:
|
|
79
87
|
try:
|
|
80
88
|
self._data_event_loop.stop()
|
|
81
89
|
self._data_event_loop.close()
|
|
90
|
+
self._data_event_loop = None
|
|
82
91
|
self._data_event_thread.join()
|
|
83
92
|
except Exception as e:
|
|
84
93
|
pass
|
|
85
|
-
if
|
|
94
|
+
if self._event_loop != None:
|
|
86
95
|
try:
|
|
87
96
|
self._event_loop.stop()
|
|
88
97
|
self._event_loop.close()
|
|
98
|
+
self._event_loop = None
|
|
89
99
|
self._event_thread.join()
|
|
90
100
|
except Exception as e:
|
|
91
101
|
pass
|
|
92
|
-
|
|
102
|
+
|
|
93
103
|
@property
|
|
94
104
|
def deviceState(self) -> DeviceStateEx:
|
|
95
105
|
"""
|
|
@@ -102,9 +112,11 @@ class SensorProfile:
|
|
|
102
112
|
def _set_device_state(self, newState: DeviceStateEx):
|
|
103
113
|
if self._device_state != newState:
|
|
104
114
|
self._device_state = newState
|
|
105
|
-
if self._on_state_changed != None:
|
|
115
|
+
if self._event_loop != None and self._on_state_changed != None:
|
|
106
116
|
try:
|
|
107
|
-
self._event_loop.call_soon_threadsafe(
|
|
117
|
+
self._event_loop.call_soon_threadsafe(
|
|
118
|
+
self._on_state_changed, self, newState
|
|
119
|
+
)
|
|
108
120
|
except Exception as e:
|
|
109
121
|
print(e)
|
|
110
122
|
pass
|
|
@@ -141,7 +153,7 @@ class SensorProfile:
|
|
|
141
153
|
return self._device
|
|
142
154
|
|
|
143
155
|
@property
|
|
144
|
-
def onStateChanged(self) -> Callable[[
|
|
156
|
+
def onStateChanged(self) -> Callable[["SensorProfile", DeviceStateEx], None]:
|
|
145
157
|
"""
|
|
146
158
|
获取状态变化的回调函数。
|
|
147
159
|
|
|
@@ -150,7 +162,9 @@ class SensorProfile:
|
|
|
150
162
|
return self._on_state_changed
|
|
151
163
|
|
|
152
164
|
@onStateChanged.setter
|
|
153
|
-
def onStateChanged(
|
|
165
|
+
def onStateChanged(
|
|
166
|
+
self, callback: Callable[["SensorProfile", DeviceStateEx], None]
|
|
167
|
+
):
|
|
154
168
|
"""
|
|
155
169
|
设置状态变化的回调函数。
|
|
156
170
|
|
|
@@ -159,7 +173,7 @@ class SensorProfile:
|
|
|
159
173
|
self._on_state_changed = callback
|
|
160
174
|
|
|
161
175
|
@property
|
|
162
|
-
def onErrorCallback(self) -> Callable[[
|
|
176
|
+
def onErrorCallback(self) -> Callable[["SensorProfile", str], None]:
|
|
163
177
|
"""
|
|
164
178
|
获取错误回调函数。
|
|
165
179
|
|
|
@@ -168,7 +182,7 @@ class SensorProfile:
|
|
|
168
182
|
return self._on_error_callback
|
|
169
183
|
|
|
170
184
|
@onErrorCallback.setter
|
|
171
|
-
def onErrorCallback(self, callback: Callable[[
|
|
185
|
+
def onErrorCallback(self, callback: Callable[["SensorProfile", str], None]):
|
|
172
186
|
"""
|
|
173
187
|
设置错误回调函数。
|
|
174
188
|
|
|
@@ -177,7 +191,7 @@ class SensorProfile:
|
|
|
177
191
|
self._on_error_callback = callback
|
|
178
192
|
|
|
179
193
|
@property
|
|
180
|
-
def onDataCallback(self) -> Callable[[
|
|
194
|
+
def onDataCallback(self) -> Callable[["SensorProfile", SensorData], None]:
|
|
181
195
|
"""
|
|
182
196
|
获取数据接收的回调函数。
|
|
183
197
|
|
|
@@ -186,7 +200,7 @@ class SensorProfile:
|
|
|
186
200
|
return self._on_data_callback
|
|
187
201
|
|
|
188
202
|
@onDataCallback.setter
|
|
189
|
-
def onDataCallback(self, callback: Callable[[
|
|
203
|
+
def onDataCallback(self, callback: Callable[["SensorProfile", SensorData], None]):
|
|
190
204
|
"""
|
|
191
205
|
设置数据接收的回调函数。
|
|
192
206
|
|
|
@@ -195,7 +209,7 @@ class SensorProfile:
|
|
|
195
209
|
self._on_data_callback = callback
|
|
196
210
|
|
|
197
211
|
@property
|
|
198
|
-
def onPowerChanged(self) -> Callable[[
|
|
212
|
+
def onPowerChanged(self) -> Callable[["SensorProfile", int], None]:
|
|
199
213
|
"""
|
|
200
214
|
获取电量变化的回调函数。
|
|
201
215
|
|
|
@@ -204,21 +218,72 @@ class SensorProfile:
|
|
|
204
218
|
return self._on_power_changed
|
|
205
219
|
|
|
206
220
|
@onPowerChanged.setter
|
|
207
|
-
def onPowerChanged(self, callback: Callable[[
|
|
221
|
+
def onPowerChanged(self, callback: Callable[["SensorProfile", int], None]):
|
|
208
222
|
"""
|
|
209
223
|
设置电量变化的回调函数。
|
|
210
224
|
|
|
211
225
|
:param callback (Callable[['SensorProfile', int], None]): 电量变化的回调函数。
|
|
212
226
|
"""
|
|
213
227
|
self._on_power_changed = callback
|
|
228
|
+
|
|
214
229
|
async def _connect(self) -> bool:
|
|
215
|
-
if self.
|
|
230
|
+
if self._event_thread == None:
|
|
231
|
+
self._event_loop = asyncio.new_event_loop()
|
|
232
|
+
self._event_thread = threading.Thread(
|
|
233
|
+
target=start_loop, args=(self._event_loop,)
|
|
234
|
+
)
|
|
235
|
+
self._event_thread.daemon = True
|
|
236
|
+
self._event_thread.name = self._device.Name + " event"
|
|
237
|
+
self._event_thread.start()
|
|
238
|
+
self._data_buffer: Queue[SensorData] = Queue()
|
|
239
|
+
self._raw_data_buf: Queue[bytes] = Queue()
|
|
240
|
+
|
|
241
|
+
if self._gforce == None:
|
|
242
|
+
if self._adv.service_data.get(SERVICE_GUID) != None:
|
|
243
|
+
# print("OYM_SERVICE:" + self._detail_device.name)
|
|
244
|
+
self._gforce = GForce(
|
|
245
|
+
self._detail_device,
|
|
246
|
+
OYM_CMD_NOTIFY_CHAR_UUID,
|
|
247
|
+
OYM_DATA_NOTIFY_CHAR_UUID,
|
|
248
|
+
False,
|
|
249
|
+
)
|
|
250
|
+
elif self._adv.service_data.get(RFSTAR_SERVICE_GUID) != None:
|
|
251
|
+
# print("RFSTAR_SERVICE:" + self._detail_device.name)
|
|
252
|
+
self._gforce = GForce(
|
|
253
|
+
self._detail_device, RFSTAR_CMD_UUID, RFSTAR_DATA_UUID, True
|
|
254
|
+
)
|
|
255
|
+
self._data_event_loop = asyncio.new_event_loop()
|
|
256
|
+
self._data_event_thread = threading.Thread(
|
|
257
|
+
target=start_loop, args=(self._data_event_loop,)
|
|
258
|
+
)
|
|
259
|
+
self._data_event_thread.daemon = True
|
|
260
|
+
self._data_event_thread.name = self._detail_device.name + " data"
|
|
261
|
+
self._data_event_thread.start()
|
|
262
|
+
else:
|
|
263
|
+
print(
|
|
264
|
+
"Invalid device service uuid:"
|
|
265
|
+
+ self._detail_device.name
|
|
266
|
+
+ str(self._adv)
|
|
267
|
+
)
|
|
268
|
+
return False
|
|
269
|
+
|
|
270
|
+
if self._data_ctx == None and self._gforce != None:
|
|
271
|
+
self._data_ctx = SensorProfileDataCtx(
|
|
272
|
+
self._gforce, self._device.Address, self._raw_data_buf
|
|
273
|
+
)
|
|
274
|
+
if self._data_ctx.isUniversalStream:
|
|
275
|
+
timer(self._data_event_loop, 0, self._process_universal_data())
|
|
276
|
+
|
|
277
|
+
if (
|
|
278
|
+
self.deviceState == DeviceStateEx.Connected
|
|
279
|
+
or self.deviceState == DeviceStateEx.Ready
|
|
280
|
+
):
|
|
216
281
|
return True
|
|
217
282
|
self._set_device_state(DeviceStateEx.Connecting)
|
|
283
|
+
|
|
218
284
|
def handle_disconnect(_: BleakClient):
|
|
219
|
-
self.stopDataNotification()
|
|
220
285
|
self._data_ctx.close()
|
|
221
|
-
time.sleep(1)
|
|
286
|
+
time.sleep(0.1)
|
|
222
287
|
self._data_buffer.queue.clear()
|
|
223
288
|
self._data_ctx = None
|
|
224
289
|
self._gforce = None
|
|
@@ -227,16 +292,18 @@ class SensorProfile:
|
|
|
227
292
|
|
|
228
293
|
await self._gforce.connect(handle_disconnect, self._raw_data_buf)
|
|
229
294
|
|
|
230
|
-
if
|
|
295
|
+
if self._gforce.client.is_connected:
|
|
231
296
|
self._set_device_state(DeviceStateEx.Connected)
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
297
|
+
self._set_device_state(DeviceStateEx.Ready)
|
|
298
|
+
# if self._gforce.client.mtu_size >= 80:
|
|
299
|
+
# self._set_device_state(DeviceStateEx.Ready)
|
|
300
|
+
# else:
|
|
301
|
+
# self.disconnect()
|
|
236
302
|
else:
|
|
237
303
|
self._set_device_state(DeviceStateEx.Disconnected)
|
|
238
|
-
|
|
304
|
+
|
|
239
305
|
return True
|
|
306
|
+
|
|
240
307
|
def connect(self) -> bool:
|
|
241
308
|
"""
|
|
242
309
|
连接传感器。
|
|
@@ -244,54 +311,36 @@ class SensorProfile:
|
|
|
244
311
|
:return: bool: 如果连接成功,返回 True;否则返回 False。
|
|
245
312
|
|
|
246
313
|
"""
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
self._event_thread = threading.Thread(target=start_loop, args=(self._event_loop,))
|
|
250
|
-
self._event_thread.daemon = True
|
|
251
|
-
self._event_thread.name = self._device.Name + " event"
|
|
252
|
-
self._event_thread.start()
|
|
253
|
-
self._data_buffer: Queue[SensorData] = Queue()
|
|
254
|
-
self._raw_data_buf: Queue[bytes] = Queue()
|
|
314
|
+
result = sync_timer(self._gforce_event_loop, 0, self._connect())
|
|
315
|
+
return result
|
|
255
316
|
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
self._gforce = GForce(self._detail_device, OYM_CMD_NOTIFY_CHAR_UUID, OYM_DATA_NOTIFY_CHAR_UUID, False)
|
|
260
|
-
elif (self._adv.service_data.get(RFSTAR_SERVICE_GUID) != None):
|
|
261
|
-
# print("RFSTAR_SERVICE:" + self._detail_device.name)
|
|
262
|
-
self._gforce = GForce(self._detail_device, RFSTAR_CMD_UUID, RFSTAR_DATA_UUID, True)
|
|
263
|
-
self._data_event_loop = asyncio.new_event_loop()
|
|
264
|
-
self._data_event_thread = threading.Thread(target=start_loop, args=(self._data_event_loop,))
|
|
265
|
-
self._data_event_thread.daemon = True
|
|
266
|
-
self._data_event_thread.name = self._detail_device.name + " data"
|
|
267
|
-
self._data_event_thread.start()
|
|
268
|
-
else:
|
|
269
|
-
print("Invalid device service uuid:" + self._detail_device.name + str(self._adv))
|
|
270
|
-
return False
|
|
317
|
+
async def asyncConnect(self) -> bool:
|
|
318
|
+
"""
|
|
319
|
+
连接传感器。
|
|
271
320
|
|
|
272
|
-
|
|
273
|
-
if (self._data_ctx == None and self._gforce != None):
|
|
274
|
-
self._data_ctx = SensorProfileDataCtx(self._gforce, self._device.Address, self._raw_data_buf)
|
|
275
|
-
if (self._data_ctx.isUniversalStream):
|
|
276
|
-
timer(self._data_event_loop, 0, self._process_universal_data())
|
|
321
|
+
:return: bool: 如果连接成功,返回 True;否则返回 False。
|
|
277
322
|
|
|
278
|
-
|
|
279
|
-
return
|
|
323
|
+
"""
|
|
324
|
+
return await async_timer(self._gforce_event_loop, 0, self._connect())
|
|
280
325
|
|
|
281
326
|
async def _waitForDisconnect(self) -> bool:
|
|
282
|
-
while
|
|
327
|
+
while self.deviceState != DeviceStateEx.Disconnected:
|
|
283
328
|
asyncio.sleep(1)
|
|
284
329
|
return True
|
|
285
330
|
|
|
286
331
|
async def _disconnect(self) -> bool:
|
|
287
|
-
if
|
|
332
|
+
if (
|
|
333
|
+
self.deviceState != DeviceStateEx.Connected
|
|
334
|
+
and self.deviceState != DeviceStateEx.Ready
|
|
335
|
+
):
|
|
288
336
|
return True
|
|
289
337
|
if self._data_ctx == None:
|
|
290
338
|
return False
|
|
291
339
|
self._set_device_state(DeviceStateEx.Disconnecting)
|
|
292
340
|
await self._gforce.disconnect()
|
|
293
|
-
await asyncio.wait_for(self._waitForDisconnect(),
|
|
341
|
+
await asyncio.wait_for(self._waitForDisconnect(), utils._TIMEOUT)
|
|
294
342
|
return True
|
|
343
|
+
|
|
295
344
|
def disconnect(self) -> bool:
|
|
296
345
|
"""
|
|
297
346
|
断开传感器连接。
|
|
@@ -301,30 +350,66 @@ class SensorProfile:
|
|
|
301
350
|
"""
|
|
302
351
|
return sync_timer(self._gforce_event_loop, 0, self._disconnect())
|
|
303
352
|
|
|
353
|
+
async def asyncDisconnect(self) -> bool:
|
|
354
|
+
"""
|
|
355
|
+
断开传感器连接。
|
|
356
|
+
|
|
357
|
+
:return: bool: 如果断开连接成功,返回 True;否则返回 False。
|
|
358
|
+
|
|
359
|
+
"""
|
|
360
|
+
return await async_timer(self._gforce_event_loop, 0, self._disconnect())
|
|
361
|
+
|
|
304
362
|
async def _process_data(self):
|
|
305
|
-
while
|
|
306
|
-
self._data_ctx.process_data(self._data_buffer)
|
|
307
|
-
while
|
|
363
|
+
while self._data_ctx._is_running and self._data_ctx.isDataTransfering:
|
|
364
|
+
self._data_ctx.process_data(self._data_buffer, self)
|
|
365
|
+
while self._data_ctx._is_running and self._data_ctx.isDataTransfering:
|
|
308
366
|
sensorData: SensorData = None
|
|
309
367
|
try:
|
|
310
368
|
sensorData = self._data_buffer.get_nowait()
|
|
311
369
|
except Exception as e:
|
|
312
370
|
break
|
|
313
|
-
if (
|
|
371
|
+
if (
|
|
372
|
+
self._event_loop != None
|
|
373
|
+
and sensorData != None
|
|
374
|
+
and self._on_data_callback != None
|
|
375
|
+
):
|
|
314
376
|
try:
|
|
315
|
-
self._event_loop.call_soon_threadsafe(
|
|
377
|
+
self._event_loop.call_soon_threadsafe(
|
|
378
|
+
self._on_data_callback, self, sensorData
|
|
379
|
+
)
|
|
316
380
|
except Exception as e:
|
|
317
381
|
print(e)
|
|
318
382
|
self._data_buffer.task_done()
|
|
319
383
|
|
|
320
384
|
async def _process_universal_data(self):
|
|
321
|
-
self._data_ctx.processUniversalData(
|
|
385
|
+
self._data_ctx.processUniversalData(
|
|
386
|
+
self._data_buffer, self._event_loop, self, self._on_data_callback
|
|
387
|
+
)
|
|
322
388
|
|
|
323
389
|
async def _startDataNotification(self) -> bool:
|
|
390
|
+
if self.deviceState != DeviceStateEx.Ready:
|
|
391
|
+
return False
|
|
392
|
+
if self._data_ctx == None:
|
|
393
|
+
return False
|
|
394
|
+
if not self._data_ctx.hasInit():
|
|
395
|
+
return False
|
|
396
|
+
|
|
397
|
+
if self._data_ctx.isDataTransfering:
|
|
398
|
+
return True
|
|
399
|
+
|
|
400
|
+
if self._data_event_loop == None:
|
|
401
|
+
self._data_event_loop = asyncio.new_event_loop()
|
|
402
|
+
self._data_event_thread = threading.Thread(
|
|
403
|
+
target=start_loop, args=(self._data_event_loop,)
|
|
404
|
+
)
|
|
405
|
+
self._data_event_thread.daemon = True
|
|
406
|
+
self._data_event_thread.name = self.BLEDevice.Name + " data"
|
|
407
|
+
self._data_event_thread.start()
|
|
408
|
+
|
|
324
409
|
result = await self._data_ctx.start_streaming()
|
|
325
410
|
self._data_buffer.queue.clear()
|
|
326
411
|
self._data_ctx.clear()
|
|
327
|
-
if
|
|
412
|
+
if not self._data_ctx.isUniversalStream:
|
|
328
413
|
timer(self._data_event_loop, 0, self._process_data())
|
|
329
414
|
return result
|
|
330
415
|
|
|
@@ -335,26 +420,29 @@ class SensorProfile:
|
|
|
335
420
|
:return: bool: 如果开始数据通知成功,返回 True;否则返回 False。
|
|
336
421
|
|
|
337
422
|
"""
|
|
423
|
+
return sync_timer(self._gforce_event_loop, 0, self._startDataNotification())
|
|
424
|
+
|
|
425
|
+
async def asyncStartDataNotification(self) -> bool:
|
|
426
|
+
"""
|
|
427
|
+
开始数据通知。
|
|
428
|
+
|
|
429
|
+
:return: bool: 如果开始数据通知成功,返回 True;否则返回 False。
|
|
430
|
+
|
|
431
|
+
"""
|
|
432
|
+
return await async_timer(
|
|
433
|
+
self._gforce_event_loop, 0, self._startDataNotification()
|
|
434
|
+
)
|
|
435
|
+
|
|
436
|
+
async def _stopDataNotification(self) -> bool:
|
|
338
437
|
if self.deviceState != DeviceStateEx.Ready:
|
|
339
438
|
return False
|
|
340
439
|
if self._data_ctx == None:
|
|
341
440
|
return False
|
|
342
441
|
if not self._data_ctx.hasInit():
|
|
343
442
|
return False
|
|
344
|
-
|
|
345
|
-
if self._data_ctx.isDataTransfering:
|
|
346
|
-
return True
|
|
347
|
-
|
|
348
|
-
if (self._data_event_loop == None):
|
|
349
|
-
self._data_event_loop = asyncio.new_event_loop()
|
|
350
|
-
self._data_event_thread = threading.Thread(target=start_loop, args=(self._data_event_loop,))
|
|
351
|
-
self._data_event_thread.daemon = True
|
|
352
|
-
self._data_event_thread.name = self.BLEDevice.Name + " data"
|
|
353
|
-
self._data_event_thread.start()
|
|
354
|
-
|
|
355
|
-
return sync_timer(self._gforce_event_loop, 0, self._startDataNotification())
|
|
356
443
|
|
|
357
|
-
|
|
444
|
+
if not self._data_ctx.isDataTransfering:
|
|
445
|
+
return True
|
|
358
446
|
|
|
359
447
|
return not await self._data_ctx.stop_streaming()
|
|
360
448
|
|
|
@@ -365,29 +453,36 @@ class SensorProfile:
|
|
|
365
453
|
:return: bool: 如果停止数据通知成功,返回 True;否则返回 False。
|
|
366
454
|
|
|
367
455
|
"""
|
|
368
|
-
if self.deviceState != DeviceStateEx.Ready:
|
|
369
|
-
return False
|
|
370
|
-
if self._data_ctx == None:
|
|
371
|
-
return False
|
|
372
|
-
if not self._data_ctx.hasInit():
|
|
373
|
-
return False
|
|
374
|
-
|
|
375
|
-
if not self._data_ctx.isDataTransfering:
|
|
376
|
-
return True
|
|
377
|
-
|
|
378
456
|
return sync_timer(self._gforce_event_loop, 0, self._stopDataNotification())
|
|
379
457
|
|
|
458
|
+
async def asyncStopDataNotification(self) -> bool:
|
|
459
|
+
"""
|
|
460
|
+
停止数据通知。
|
|
461
|
+
|
|
462
|
+
:return: bool: 如果停止数据通知成功,返回 True;否则返回 False。
|
|
463
|
+
|
|
464
|
+
"""
|
|
465
|
+
return await async_timer(
|
|
466
|
+
self._gforce_event_loop, 0, self._stopDataNotification()
|
|
467
|
+
)
|
|
468
|
+
|
|
380
469
|
async def _refresh_power(self):
|
|
381
470
|
self._power = await self._gforce.get_battery_level()
|
|
382
471
|
|
|
383
|
-
if self._on_power_changed != None:
|
|
472
|
+
if self._event_loop != None and self._on_power_changed != None:
|
|
384
473
|
try:
|
|
385
|
-
self._event_loop.call_soon_threadsafe(
|
|
474
|
+
self._event_loop.call_soon_threadsafe(
|
|
475
|
+
self._on_power_changed, self, self._power
|
|
476
|
+
)
|
|
386
477
|
except Exception as e:
|
|
387
478
|
print(e)
|
|
388
|
-
|
|
479
|
+
|
|
389
480
|
if self.deviceState == DeviceStateEx.Ready:
|
|
390
|
-
timer(
|
|
481
|
+
timer(
|
|
482
|
+
self._gforce_event_loop,
|
|
483
|
+
self._power_interval / 1000,
|
|
484
|
+
self._refresh_power(),
|
|
485
|
+
)
|
|
391
486
|
|
|
392
487
|
async def _init(self, packageSampleCount: int, powerRefreshInterval: int) -> bool:
|
|
393
488
|
if self.deviceState != DeviceStateEx.Ready:
|
|
@@ -396,12 +491,17 @@ class SensorProfile:
|
|
|
396
491
|
return False
|
|
397
492
|
if self._data_ctx.hasInit():
|
|
398
493
|
return True
|
|
399
|
-
|
|
400
|
-
if
|
|
494
|
+
|
|
495
|
+
if await self._data_ctx.init(packageSampleCount):
|
|
401
496
|
self._power_interval = powerRefreshInterval
|
|
402
|
-
timer(
|
|
497
|
+
timer(
|
|
498
|
+
self._gforce_event_loop,
|
|
499
|
+
self._power_interval / 1000,
|
|
500
|
+
self._refresh_power(),
|
|
501
|
+
)
|
|
403
502
|
|
|
404
503
|
return self._data_ctx.hasInit()
|
|
504
|
+
|
|
405
505
|
def init(self, packageSampleCount: int, powerRefreshInterval: int) -> bool:
|
|
406
506
|
"""
|
|
407
507
|
初始化数据采集。
|
|
@@ -412,7 +512,31 @@ class SensorProfile:
|
|
|
412
512
|
:return: bool: 初始化结果。True 表示成功,False 表示失败。
|
|
413
513
|
|
|
414
514
|
"""
|
|
415
|
-
return sync_timer(
|
|
515
|
+
return sync_timer(
|
|
516
|
+
self._gforce_event_loop,
|
|
517
|
+
0,
|
|
518
|
+
self._init(packageSampleCount, powerRefreshInterval),
|
|
519
|
+
120,
|
|
520
|
+
)
|
|
521
|
+
|
|
522
|
+
async def asyncInit(
|
|
523
|
+
self, packageSampleCount: int, powerRefreshInterval: int
|
|
524
|
+
) -> bool:
|
|
525
|
+
"""
|
|
526
|
+
初始化数据采集。
|
|
527
|
+
|
|
528
|
+
:param packageSampleCount (int): 数据包中的样本数量。
|
|
529
|
+
:param powerRefreshInterval (int): 电量刷新间隔。
|
|
530
|
+
|
|
531
|
+
:return: bool: 初始化结果。True 表示成功,False 表示失败。
|
|
532
|
+
|
|
533
|
+
"""
|
|
534
|
+
return await async_timer(
|
|
535
|
+
self._gforce_event_loop,
|
|
536
|
+
0,
|
|
537
|
+
self._init(packageSampleCount, powerRefreshInterval),
|
|
538
|
+
120,
|
|
539
|
+
)
|
|
416
540
|
|
|
417
541
|
def getBatteryLevel(self) -> int:
|
|
418
542
|
"""
|
|
@@ -423,7 +547,6 @@ class SensorProfile:
|
|
|
423
547
|
"""
|
|
424
548
|
return self._power
|
|
425
549
|
|
|
426
|
-
|
|
427
550
|
def getDeviceInfo(self) -> Optional[DeviceInfo]:
|
|
428
551
|
"""
|
|
429
552
|
获取传感器的设备信息。
|
|
@@ -431,11 +554,10 @@ class SensorProfile:
|
|
|
431
554
|
:return: DeviceInfo: 传感器的设备信息。
|
|
432
555
|
|
|
433
556
|
"""
|
|
434
|
-
if
|
|
557
|
+
if self.hasInited:
|
|
435
558
|
return self._data_ctx._device_info
|
|
436
559
|
return None
|
|
437
560
|
|
|
438
|
-
|
|
439
561
|
def setParam(self, key: str, value: str) -> str:
|
|
440
562
|
"""
|
|
441
563
|
设置传感器的参数。
|
|
@@ -447,3 +569,15 @@ class SensorProfile:
|
|
|
447
569
|
|
|
448
570
|
"""
|
|
449
571
|
return ""
|
|
572
|
+
|
|
573
|
+
async def AsyncSetParam(self, key: str, value: str) -> str:
|
|
574
|
+
"""
|
|
575
|
+
设置传感器的参数。
|
|
576
|
+
|
|
577
|
+
:param key (str): 参数的键。
|
|
578
|
+
:param value (str): 参数的值。
|
|
579
|
+
|
|
580
|
+
:return: str: 设置参数的结果。
|
|
581
|
+
|
|
582
|
+
"""
|
|
583
|
+
return ""
|
sensor/utils.py
CHANGED
|
@@ -1,28 +1,72 @@
|
|
|
1
1
|
import asyncio
|
|
2
|
+
import platform
|
|
3
|
+
import queue
|
|
2
4
|
import signal
|
|
5
|
+
import time
|
|
3
6
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
+
_terminated = False
|
|
8
|
+
_TIMEOUT = 10
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
async def delay(_time: float, function) -> any:
|
|
12
|
+
if _time > 0:
|
|
13
|
+
await asyncio.sleep(_time)
|
|
7
14
|
return await function
|
|
8
15
|
|
|
9
|
-
|
|
16
|
+
|
|
17
|
+
def timer(_loop: asyncio.AbstractEventLoop, _delay: float, function):
|
|
18
|
+
if _loop == None:
|
|
19
|
+
return
|
|
10
20
|
try:
|
|
11
|
-
asyncio.run_coroutine_threadsafe(delay(
|
|
21
|
+
asyncio.run_coroutine_threadsafe(delay(_delay, function), _loop)
|
|
12
22
|
except Exception as e:
|
|
13
23
|
print(e)
|
|
14
24
|
pass
|
|
15
|
-
|
|
16
25
|
|
|
17
|
-
|
|
26
|
+
|
|
27
|
+
def sync_timer(
|
|
28
|
+
_loop: asyncio.AbstractEventLoop, _delay: float, function, _timeout=_TIMEOUT
|
|
29
|
+
) -> any:
|
|
30
|
+
if _loop == None:
|
|
31
|
+
return
|
|
32
|
+
|
|
18
33
|
try:
|
|
19
|
-
f = asyncio.run_coroutine_threadsafe(
|
|
20
|
-
|
|
34
|
+
f = asyncio.run_coroutine_threadsafe(
|
|
35
|
+
asyncio.wait_for(delay(_delay, function), _delay + _timeout), _loop
|
|
36
|
+
)
|
|
37
|
+
return f.result(timeout=_timeout)
|
|
21
38
|
except Exception as e:
|
|
22
39
|
print(e)
|
|
23
40
|
pass
|
|
24
41
|
|
|
42
|
+
|
|
43
|
+
async def async_timer(
|
|
44
|
+
_loop: asyncio.AbstractEventLoop, _delay: float, function, _timeout=_TIMEOUT
|
|
45
|
+
) -> any:
|
|
46
|
+
if _loop == None:
|
|
47
|
+
return
|
|
48
|
+
|
|
49
|
+
try:
|
|
50
|
+
f = asyncio.run_coroutine_threadsafe(
|
|
51
|
+
asyncio.wait_for(delay(_delay, function), _delay + _timeout), _loop
|
|
52
|
+
)
|
|
53
|
+
except Exception as e:
|
|
54
|
+
print(e)
|
|
55
|
+
pass
|
|
56
|
+
|
|
57
|
+
while not _terminated and not f.done():
|
|
58
|
+
await asyncio.sleep(0.1)
|
|
59
|
+
|
|
60
|
+
try:
|
|
61
|
+
if not f.cancelled():
|
|
62
|
+
return f.result()
|
|
63
|
+
except Exception as e:
|
|
64
|
+
print(e)
|
|
65
|
+
return
|
|
66
|
+
|
|
67
|
+
|
|
25
68
|
def start_loop(loop: asyncio.BaseEventLoop):
|
|
69
|
+
if platform.system() == "Darwin":
|
|
70
|
+
asyncio.get_running_loop = asyncio.get_event_loop
|
|
26
71
|
asyncio.set_event_loop(loop)
|
|
27
72
|
loop.run_forever()
|
|
28
|
-
|