sensor-sdk 0.0.1__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/__init__.py +4 -0
- sensor/gforce.py +864 -0
- sensor/sensor_controller.py +223 -0
- sensor/sensor_data.py +91 -0
- sensor/sensor_data_context.py +569 -0
- sensor/sensor_device.py +75 -0
- sensor/sensor_profile.py +449 -0
- sensor/utils.py +28 -0
- sensor_sdk-0.0.1.dist-info/LICENSE.txt +21 -0
- sensor_sdk-0.0.1.dist-info/METADATA +300 -0
- sensor_sdk-0.0.1.dist-info/RECORD +14 -0
- sensor_sdk-0.0.1.dist-info/WHEEL +5 -0
- sensor_sdk-0.0.1.dist-info/top_level.txt +1 -0
- sensor_sdk-0.0.1.dist-info/zip-safe +1 -0
sensor/sensor_profile.py
ADDED
|
@@ -0,0 +1,449 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
# 设备状态枚举
|
|
4
|
+
# 该枚举类定义了设备的各种状态,用于表示设备在不同操作阶段的状态信息
|
|
5
|
+
from enum import Enum, IntEnum
|
|
6
|
+
from queue import Queue
|
|
7
|
+
import struct
|
|
8
|
+
import time
|
|
9
|
+
from typing import Callable, Dict, List, Optional
|
|
10
|
+
|
|
11
|
+
import bleak
|
|
12
|
+
from bleak import (
|
|
13
|
+
BleakClient,
|
|
14
|
+
BleakGATTCharacteristic,
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
import sensor
|
|
18
|
+
from sensor.gforce import GForce
|
|
19
|
+
from sensor.sensor_data import DataType, Sample, SensorData
|
|
20
|
+
import asyncio
|
|
21
|
+
import threading
|
|
22
|
+
|
|
23
|
+
from sensor.sensor_data_context import SensorProfileDataCtx
|
|
24
|
+
from sensor.sensor_device import BLEDevice, DeviceInfo, DeviceStateEx
|
|
25
|
+
from sensor.utils import start_loop, sync_timer, timer
|
|
26
|
+
from contextlib import suppress
|
|
27
|
+
from dataclasses import dataclass
|
|
28
|
+
|
|
29
|
+
SERVICE_GUID = "0000ffd0-0000-1000-8000-00805f9b34fb"
|
|
30
|
+
OYM_CMD_NOTIFY_CHAR_UUID = "f000ffe1-0451-4000-b000-000000000000"
|
|
31
|
+
OYM_DATA_NOTIFY_CHAR_UUID = "f000ffe2-0451-4000-b000-000000000000"
|
|
32
|
+
|
|
33
|
+
RFSTAR_SERVICE_GUID = "00001812-0000-1000-8000-00805f9b34fb"
|
|
34
|
+
RFSTAR_CMD_UUID = "00000002-0000-1000-8000-00805f9b34fb"
|
|
35
|
+
RFSTAR_DATA_UUID = "00000003-0000-1000-8000-00805f9b34fb"
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class SensorProfile:
|
|
39
|
+
"""
|
|
40
|
+
SensorProfile 类用于蓝牙设备的连接,获取详细设备信息,初始化,数据接收。
|
|
41
|
+
|
|
42
|
+
包含回调函数,用于处理传感器的状态变化、错误、数据接收和电量变化等事件。
|
|
43
|
+
"""
|
|
44
|
+
|
|
45
|
+
def __init__(self, device: bleak.BLEDevice, adv: bleak.AdvertisementData, gforce_event_loop: asyncio.AbstractEventLoop):
|
|
46
|
+
"""
|
|
47
|
+
初始化 SensorProfile 类的实例。
|
|
48
|
+
|
|
49
|
+
:param device (BLEDevice): 蓝牙设备对象,包含设备的名称、地址和信号强度等信息。
|
|
50
|
+
"""
|
|
51
|
+
self._detail_device = device
|
|
52
|
+
self._device = BLEDevice(device.name, device.address, adv.rssi)
|
|
53
|
+
self._device_state = DeviceStateEx.Disconnected
|
|
54
|
+
self._on_state_changed: Callable[['SensorProfile', DeviceStateEx], None] = None
|
|
55
|
+
self._on_error_callback: Callable[['SensorProfile', str], None] = None
|
|
56
|
+
self._on_data_callback: Callable[['SensorProfile', SensorData], None] = None
|
|
57
|
+
self._on_power_changed: Callable[['SensorProfile', int], None] = None
|
|
58
|
+
self._power = -1
|
|
59
|
+
self._power_interval = 0
|
|
60
|
+
self._adv = adv
|
|
61
|
+
self._data_ctx: SensorProfileDataCtx = None
|
|
62
|
+
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
|
|
66
|
+
self._event_thread = None
|
|
67
|
+
|
|
68
|
+
def __del__(self) -> None:
|
|
69
|
+
"""
|
|
70
|
+
反初始化 SensorProfile 类的实例。
|
|
71
|
+
|
|
72
|
+
"""
|
|
73
|
+
self.destroy()
|
|
74
|
+
|
|
75
|
+
def destroy(self):
|
|
76
|
+
if self._device_state == DeviceStateEx.Connected or self._device_state == DeviceStateEx.Ready:
|
|
77
|
+
self.disconnect()
|
|
78
|
+
if (self._data_event_loop != None):
|
|
79
|
+
try:
|
|
80
|
+
self._data_event_loop.stop()
|
|
81
|
+
self._data_event_loop.close()
|
|
82
|
+
self._data_event_thread.join()
|
|
83
|
+
except Exception as e:
|
|
84
|
+
pass
|
|
85
|
+
if (self._event_loop != None):
|
|
86
|
+
try:
|
|
87
|
+
self._event_loop.stop()
|
|
88
|
+
self._event_loop.close()
|
|
89
|
+
self._event_thread.join()
|
|
90
|
+
except Exception as e:
|
|
91
|
+
pass
|
|
92
|
+
|
|
93
|
+
@property
|
|
94
|
+
def deviceState(self) -> DeviceStateEx:
|
|
95
|
+
"""
|
|
96
|
+
获取蓝牙连接状态。
|
|
97
|
+
|
|
98
|
+
:return: DeviceStateEx: 设备的状态,如 Disconnected、Connecting、Connected 等。
|
|
99
|
+
"""
|
|
100
|
+
return self._device_state
|
|
101
|
+
|
|
102
|
+
def _set_device_state(self, newState: DeviceStateEx):
|
|
103
|
+
if self._device_state != newState:
|
|
104
|
+
self._device_state = newState
|
|
105
|
+
if self._on_state_changed != None:
|
|
106
|
+
try:
|
|
107
|
+
self._event_loop.call_soon_threadsafe(self._on_state_changed,self, newState)
|
|
108
|
+
except Exception as e:
|
|
109
|
+
print(e)
|
|
110
|
+
pass
|
|
111
|
+
|
|
112
|
+
@property
|
|
113
|
+
def hasInited(self) -> bool:
|
|
114
|
+
"""
|
|
115
|
+
检查传感器是否已经初始化。
|
|
116
|
+
|
|
117
|
+
:return: bool: 如果传感器已经初始化,返回 True;否则返回 False。
|
|
118
|
+
"""
|
|
119
|
+
if self._data_ctx == None:
|
|
120
|
+
return False
|
|
121
|
+
return self._data_ctx.hasInit()
|
|
122
|
+
|
|
123
|
+
@property
|
|
124
|
+
def isDataTransfering(self) -> bool:
|
|
125
|
+
"""
|
|
126
|
+
检查传感器是否正在进行数据传输。
|
|
127
|
+
|
|
128
|
+
:return: bool: 如果传感器正在进行数据传输,返回 True;否则返回 False。
|
|
129
|
+
"""
|
|
130
|
+
if self._data_ctx == None:
|
|
131
|
+
return False
|
|
132
|
+
return self._data_ctx.isDataTransfering
|
|
133
|
+
|
|
134
|
+
@property
|
|
135
|
+
def BLEDevice(self) -> BLEDevice:
|
|
136
|
+
"""
|
|
137
|
+
获取传感器的蓝牙设备信息。
|
|
138
|
+
|
|
139
|
+
:return: BLEDevice: 蓝牙设备对象,包含设备的名称、地址和信号强度等信息。
|
|
140
|
+
"""
|
|
141
|
+
return self._device
|
|
142
|
+
|
|
143
|
+
@property
|
|
144
|
+
def onStateChanged(self) -> Callable[['SensorProfile', DeviceStateEx], None]:
|
|
145
|
+
"""
|
|
146
|
+
获取状态变化的回调函数。
|
|
147
|
+
|
|
148
|
+
:return: Callable[['SensorProfile', DeviceStateEx], None]: 状态变化的回调函数。
|
|
149
|
+
"""
|
|
150
|
+
return self._on_state_changed
|
|
151
|
+
|
|
152
|
+
@onStateChanged.setter
|
|
153
|
+
def onStateChanged(self, callback: Callable[['SensorProfile', DeviceStateEx], None]):
|
|
154
|
+
"""
|
|
155
|
+
设置状态变化的回调函数。
|
|
156
|
+
|
|
157
|
+
:param callback (Callable[['SensorProfile', DeviceStateEx], None]): 状态变化的回调函数。
|
|
158
|
+
"""
|
|
159
|
+
self._on_state_changed = callback
|
|
160
|
+
|
|
161
|
+
@property
|
|
162
|
+
def onErrorCallback(self) -> Callable[['SensorProfile', str], None]:
|
|
163
|
+
"""
|
|
164
|
+
获取错误回调函数。
|
|
165
|
+
|
|
166
|
+
:return: Callable[['SensorProfile', str], None]: 错误回调函数。
|
|
167
|
+
"""
|
|
168
|
+
return self._on_error_callback
|
|
169
|
+
|
|
170
|
+
@onErrorCallback.setter
|
|
171
|
+
def onErrorCallback(self, callback: Callable[['SensorProfile', str], None]):
|
|
172
|
+
"""
|
|
173
|
+
设置错误回调函数。
|
|
174
|
+
|
|
175
|
+
:param callback (Callable[['SensorProfile', str], None]): 错误回调函数。
|
|
176
|
+
"""
|
|
177
|
+
self._on_error_callback = callback
|
|
178
|
+
|
|
179
|
+
@property
|
|
180
|
+
def onDataCallback(self) -> Callable[['SensorProfile', SensorData], None]:
|
|
181
|
+
"""
|
|
182
|
+
获取数据接收的回调函数。
|
|
183
|
+
|
|
184
|
+
:return: Callable[['SensorProfile', SensorData], None]: 数据接收的回调函数。
|
|
185
|
+
"""
|
|
186
|
+
return self._on_data_callback
|
|
187
|
+
|
|
188
|
+
@onDataCallback.setter
|
|
189
|
+
def onDataCallback(self, callback: Callable[['SensorProfile', SensorData], None]):
|
|
190
|
+
"""
|
|
191
|
+
设置数据接收的回调函数。
|
|
192
|
+
|
|
193
|
+
:param callback (Callable[['SensorProfile', SensorData], None]): 数据接收的回调函数。
|
|
194
|
+
"""
|
|
195
|
+
self._on_data_callback = callback
|
|
196
|
+
|
|
197
|
+
@property
|
|
198
|
+
def onPowerChanged(self) -> Callable[['SensorProfile', int], None]:
|
|
199
|
+
"""
|
|
200
|
+
获取电量变化的回调函数。
|
|
201
|
+
|
|
202
|
+
:return: Callable[['SensorProfile', int], None]: 电量变化的回调函数。
|
|
203
|
+
"""
|
|
204
|
+
return self._on_power_changed
|
|
205
|
+
|
|
206
|
+
@onPowerChanged.setter
|
|
207
|
+
def onPowerChanged(self, callback: Callable[['SensorProfile', int], None]):
|
|
208
|
+
"""
|
|
209
|
+
设置电量变化的回调函数。
|
|
210
|
+
|
|
211
|
+
:param callback (Callable[['SensorProfile', int], None]): 电量变化的回调函数。
|
|
212
|
+
"""
|
|
213
|
+
self._on_power_changed = callback
|
|
214
|
+
async def _connect(self) -> bool:
|
|
215
|
+
if self.deviceState == DeviceStateEx.Connected or self.deviceState == DeviceStateEx.Ready:
|
|
216
|
+
return True
|
|
217
|
+
self._set_device_state(DeviceStateEx.Connecting)
|
|
218
|
+
def handle_disconnect(_: BleakClient):
|
|
219
|
+
self.stopDataNotification()
|
|
220
|
+
self._data_ctx.close()
|
|
221
|
+
time.sleep(1)
|
|
222
|
+
self._data_buffer.queue.clear()
|
|
223
|
+
self._data_ctx = None
|
|
224
|
+
self._gforce = None
|
|
225
|
+
self._set_device_state(DeviceStateEx.Disconnected)
|
|
226
|
+
pass
|
|
227
|
+
|
|
228
|
+
await self._gforce.connect(handle_disconnect, self._raw_data_buf)
|
|
229
|
+
|
|
230
|
+
if (self._gforce.client.is_connected):
|
|
231
|
+
self._set_device_state(DeviceStateEx.Connected)
|
|
232
|
+
if (self._gforce.client.mtu_size >= 80):
|
|
233
|
+
self._set_device_state(DeviceStateEx.Ready)
|
|
234
|
+
else:
|
|
235
|
+
self.disconnect()
|
|
236
|
+
else:
|
|
237
|
+
self._set_device_state(DeviceStateEx.Disconnected)
|
|
238
|
+
|
|
239
|
+
return True
|
|
240
|
+
def connect(self) -> bool:
|
|
241
|
+
"""
|
|
242
|
+
连接传感器。
|
|
243
|
+
|
|
244
|
+
:return: bool: 如果连接成功,返回 True;否则返回 False。
|
|
245
|
+
|
|
246
|
+
"""
|
|
247
|
+
if (self._event_thread == None):
|
|
248
|
+
self._event_loop = asyncio.new_event_loop()
|
|
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()
|
|
255
|
+
|
|
256
|
+
if (self._gforce == None):
|
|
257
|
+
if (self._adv.service_data.get(SERVICE_GUID) != None):
|
|
258
|
+
# print("OYM_SERVICE:" + self._detail_device.name)
|
|
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
|
|
271
|
+
|
|
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())
|
|
277
|
+
|
|
278
|
+
result = sync_timer(self._gforce_event_loop, 0, self._connect())
|
|
279
|
+
return result
|
|
280
|
+
|
|
281
|
+
async def _waitForDisconnect(self) -> bool:
|
|
282
|
+
while(self.deviceState != DeviceStateEx.Disconnected):
|
|
283
|
+
asyncio.sleep(1)
|
|
284
|
+
return True
|
|
285
|
+
|
|
286
|
+
async def _disconnect(self) -> bool:
|
|
287
|
+
if self.deviceState != DeviceStateEx.Connected and self.deviceState != DeviceStateEx.Ready:
|
|
288
|
+
return True
|
|
289
|
+
if self._data_ctx == None:
|
|
290
|
+
return False
|
|
291
|
+
self._set_device_state(DeviceStateEx.Disconnecting)
|
|
292
|
+
await self._gforce.disconnect()
|
|
293
|
+
await asyncio.wait_for(self._waitForDisconnect(), 5)
|
|
294
|
+
return True
|
|
295
|
+
def disconnect(self) -> bool:
|
|
296
|
+
"""
|
|
297
|
+
断开传感器连接。
|
|
298
|
+
|
|
299
|
+
:return: bool: 如果断开连接成功,返回 True;否则返回 False。
|
|
300
|
+
|
|
301
|
+
"""
|
|
302
|
+
return sync_timer(self._gforce_event_loop, 0, self._disconnect())
|
|
303
|
+
|
|
304
|
+
async def _process_data(self):
|
|
305
|
+
while(self._data_ctx._is_running and self._data_ctx.isDataTransfering):
|
|
306
|
+
self._data_ctx.process_data(self._data_buffer)
|
|
307
|
+
while(self._data_ctx._is_running and self._data_ctx.isDataTransfering):
|
|
308
|
+
sensorData: SensorData = None
|
|
309
|
+
try:
|
|
310
|
+
sensorData = self._data_buffer.get_nowait()
|
|
311
|
+
except Exception as e:
|
|
312
|
+
break
|
|
313
|
+
if (sensorData != None and self._on_data_callback != None):
|
|
314
|
+
try:
|
|
315
|
+
self._event_loop.call_soon_threadsafe(self._on_data_callback,self, sensorData)
|
|
316
|
+
except Exception as e:
|
|
317
|
+
print(e)
|
|
318
|
+
self._data_buffer.task_done()
|
|
319
|
+
|
|
320
|
+
async def _process_universal_data(self):
|
|
321
|
+
self._data_ctx.processUniversalData(self._data_buffer, self._event_loop, self, self._on_data_callback)
|
|
322
|
+
|
|
323
|
+
async def _startDataNotification(self) -> bool:
|
|
324
|
+
result = await self._data_ctx.start_streaming()
|
|
325
|
+
self._data_buffer.queue.clear()
|
|
326
|
+
self._data_ctx.clear()
|
|
327
|
+
if (not self._data_ctx.isUniversalStream):
|
|
328
|
+
timer(self._data_event_loop, 0, self._process_data())
|
|
329
|
+
return result
|
|
330
|
+
|
|
331
|
+
def startDataNotification(self) -> bool:
|
|
332
|
+
"""
|
|
333
|
+
开始数据通知。
|
|
334
|
+
|
|
335
|
+
:return: bool: 如果开始数据通知成功,返回 True;否则返回 False。
|
|
336
|
+
|
|
337
|
+
"""
|
|
338
|
+
if self.deviceState != DeviceStateEx.Ready:
|
|
339
|
+
return False
|
|
340
|
+
if self._data_ctx == None:
|
|
341
|
+
return False
|
|
342
|
+
if not self._data_ctx.hasInit():
|
|
343
|
+
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
|
+
|
|
357
|
+
async def _stopDataNotification(self) -> bool:
|
|
358
|
+
|
|
359
|
+
return not await self._data_ctx.stop_streaming()
|
|
360
|
+
|
|
361
|
+
def stopDataNotification(self) -> bool:
|
|
362
|
+
"""
|
|
363
|
+
停止数据通知。
|
|
364
|
+
|
|
365
|
+
:return: bool: 如果停止数据通知成功,返回 True;否则返回 False。
|
|
366
|
+
|
|
367
|
+
"""
|
|
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
|
+
return sync_timer(self._gforce_event_loop, 0, self._stopDataNotification())
|
|
379
|
+
|
|
380
|
+
async def _refresh_power(self):
|
|
381
|
+
self._power = await self._gforce.get_battery_level()
|
|
382
|
+
|
|
383
|
+
if self._on_power_changed != None:
|
|
384
|
+
try:
|
|
385
|
+
self._event_loop.call_soon_threadsafe(self._on_power_changed, self, self._power)
|
|
386
|
+
except Exception as e:
|
|
387
|
+
print(e)
|
|
388
|
+
|
|
389
|
+
if self.deviceState == DeviceStateEx.Ready:
|
|
390
|
+
timer(self._gforce_event_loop, self._power_interval / 1000, self._refresh_power())
|
|
391
|
+
|
|
392
|
+
async def _init(self, packageSampleCount: int, powerRefreshInterval: int) -> bool:
|
|
393
|
+
if self.deviceState != DeviceStateEx.Ready:
|
|
394
|
+
return False
|
|
395
|
+
if self._data_ctx == None:
|
|
396
|
+
return False
|
|
397
|
+
if self._data_ctx.hasInit():
|
|
398
|
+
return True
|
|
399
|
+
|
|
400
|
+
if (await self._data_ctx.init(packageSampleCount)):
|
|
401
|
+
self._power_interval = powerRefreshInterval
|
|
402
|
+
timer(self._gforce_event_loop, self._power_interval / 1000, self._refresh_power())
|
|
403
|
+
|
|
404
|
+
return self._data_ctx.hasInit()
|
|
405
|
+
def init(self, packageSampleCount: int, powerRefreshInterval: int) -> bool:
|
|
406
|
+
"""
|
|
407
|
+
初始化数据采集。
|
|
408
|
+
|
|
409
|
+
:param packageSampleCount (int): 数据包中的样本数量。
|
|
410
|
+
:param powerRefreshInterval (int): 电量刷新间隔。
|
|
411
|
+
|
|
412
|
+
:return: bool: 初始化结果。True 表示成功,False 表示失败。
|
|
413
|
+
|
|
414
|
+
"""
|
|
415
|
+
return sync_timer(self._gforce_event_loop, 0, self._init(packageSampleCount, powerRefreshInterval))
|
|
416
|
+
|
|
417
|
+
def getBatteryLevel(self) -> int:
|
|
418
|
+
"""
|
|
419
|
+
获取传感器的电池电量。
|
|
420
|
+
|
|
421
|
+
:return: int: 传感器的电池电量。 正常0-100,-1为未知。
|
|
422
|
+
|
|
423
|
+
"""
|
|
424
|
+
return self._power
|
|
425
|
+
|
|
426
|
+
|
|
427
|
+
def getDeviceInfo(self) -> Optional[DeviceInfo]:
|
|
428
|
+
"""
|
|
429
|
+
获取传感器的设备信息。
|
|
430
|
+
|
|
431
|
+
:return: DeviceInfo: 传感器的设备信息。
|
|
432
|
+
|
|
433
|
+
"""
|
|
434
|
+
if (self.hasInited):
|
|
435
|
+
return self._data_ctx._device_info
|
|
436
|
+
return None
|
|
437
|
+
|
|
438
|
+
|
|
439
|
+
def setParam(self, key: str, value: str) -> str:
|
|
440
|
+
"""
|
|
441
|
+
设置传感器的参数。
|
|
442
|
+
|
|
443
|
+
:param key (str): 参数的键。
|
|
444
|
+
:param value (str): 参数的值。
|
|
445
|
+
|
|
446
|
+
:return: str: 设置参数的结果。
|
|
447
|
+
|
|
448
|
+
"""
|
|
449
|
+
return ""
|
sensor/utils.py
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
import signal
|
|
3
|
+
|
|
4
|
+
async def delay(time:float, function)->any:
|
|
5
|
+
if (time > 0):
|
|
6
|
+
await asyncio.sleep(time)
|
|
7
|
+
return await function
|
|
8
|
+
|
|
9
|
+
def timer(_loop: asyncio.AbstractEventLoop, time: float, function):
|
|
10
|
+
try:
|
|
11
|
+
asyncio.run_coroutine_threadsafe(delay(time, function), _loop)
|
|
12
|
+
except Exception as e:
|
|
13
|
+
print(e)
|
|
14
|
+
pass
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def sync_timer(_loop: asyncio.AbstractEventLoop, time: float, function)->any:
|
|
18
|
+
try:
|
|
19
|
+
f = asyncio.run_coroutine_threadsafe(delay(time, function), _loop)
|
|
20
|
+
return f.result()
|
|
21
|
+
except Exception as e:
|
|
22
|
+
print(e)
|
|
23
|
+
pass
|
|
24
|
+
|
|
25
|
+
def start_loop(loop: asyncio.BaseEventLoop):
|
|
26
|
+
asyncio.set_event_loop(loop)
|
|
27
|
+
loop.run_forever()
|
|
28
|
+
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 OYMotion Technologies Co., Ltd..
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|