qlsdk2 0.2.0__py3-none-any.whl → 0.3.0a1__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.
qlsdk/sdk/hub.py ADDED
@@ -0,0 +1,51 @@
1
+ from qlsdk.sdk.ar4sdk import AR4SDK, LMDevice
2
+
3
+
4
+ from time import sleep, time
5
+ from threading import Lock, Timer
6
+ from loguru import logger
7
+
8
+ class Hub(object):
9
+ def __init__(self):
10
+ self._lock = Lock()
11
+ self._search_timer = None
12
+ self._search_running = False
13
+ self._devices: dict[str, LMDevice] = {}
14
+
15
+ @property
16
+ def devices(self):
17
+ return self._devices
18
+
19
+ def search(self):
20
+ if not self._search_running:
21
+ self._search_running = True
22
+ self._search()
23
+
24
+ def _search(self):
25
+ if self._search_running:
26
+
27
+ self._search_timer = Timer(2, self._search_device)
28
+ self._search_timer.daemon = True
29
+ self._search_timer.start()
30
+
31
+
32
+ def _search_device(self):
33
+ try:
34
+ devices = AR4SDK.enum_devices()
35
+ # logger.debug(f"_search_ar4 devices size: {len(devices)}")
36
+ for dev in devices:
37
+ self.add_device(hex(dev.mac))
38
+ except Exception as e:
39
+ logger.error(f"_search_device 异常: {str(e)}")
40
+ finally:
41
+ self._search()
42
+
43
+ def add_device(self, mac: str):
44
+ if mac in list(self._devices.keys()):
45
+ self._devices[mac].update_info()
46
+ logger.info(f"update device mac: {mac}")
47
+ else:
48
+ dev = LMDevice(mac)
49
+ if dev.init():
50
+ self._devices[mac] = dev
51
+ logger.info(f"add device mac: {dev}")
qlsdk/x8/__init__.py ADDED
@@ -0,0 +1,128 @@
1
+ from multiprocessing import Queue
2
+ from typing import Literal
3
+ from loguru import logger
4
+ from qlsdk.sdk import LMDevice, LMPacket
5
+ import numpy as np
6
+ from qlsdk.persist import EdfHandler
7
+ import time
8
+
9
+ # 设备对象
10
+ class X8(LMDevice):
11
+ def __init__(self, box_mac:str, is_persist:bool=True, storage_path:str=None):
12
+ # 是否持久化-保存为文件
13
+ self._is_persist = is_persist
14
+ self._storage_path = storage_path
15
+ self._edf_handler = None
16
+
17
+ self._recording = False
18
+ self._record_start_time = None
19
+
20
+ self._acq_info = {}
21
+ # 订阅者列表,数值为数字信号值
22
+ self._dig_subscriber: dict[str, Queue] = {}
23
+ # 订阅者列表,数值为物理信号值
24
+ self._phy_subscriber: dict[str, Queue] = {}
25
+
26
+ super().__init__(box_mac)
27
+
28
+ def set_storage_path(self, storage_path):
29
+ self._storage_path = storage_path
30
+
31
+ @property
32
+ def device_type(self):
33
+ return "x8"
34
+
35
+
36
+ def eeg_accept(self, packet):
37
+ if len(self._dig_subscriber) > 0 or len(self._phy_subscriber) > 0:
38
+ for consumer in self._dig_subscriber.values():
39
+ consumer.put(packet)
40
+
41
+ if len(self._phy_subscriber) > 0:
42
+ logger.info(f"dig data eeg: {packet.eeg}")
43
+ logger.info(f"dig data acc: {packet.acc}")
44
+ packet.eeg = self.eeg2phy(np.array(packet.eeg))
45
+ packet.acc = self.acc2phy(np.array(packet.acc))
46
+ logger.info(f"phy data eeg: {packet.eeg}")
47
+ logger.info(f"phy data acc: {packet.acc}")
48
+ for consumer2 in self._phy_subscriber.values():
49
+ consumer2.put(packet)
50
+
51
+ if self._is_persist:
52
+ if self._edf_handler is None:
53
+ self.start_record()
54
+ self._recording = True
55
+ self._record_start_time = packet.time_stamp
56
+ logger.info(f"开始记录数据: {self.box_mac}")
57
+
58
+ # 处理数据包
59
+ self._edf_handler.append(packet)
60
+
61
+ def start_record(self):
62
+ if self._is_persist:
63
+ if self._edf_handler is None:
64
+ self._edf_handler = EdfHandler(self.sample_frequency, self.eeg_phy_max, self.eeg_phy_min, self.eeg_dig_max, self.eeg_dig_min, storage_path=self._storage_path)
65
+ self._edf_handler.set_device_type(self.device_type)
66
+ self._edf_handler.set_storage_path(self._storage_path)
67
+
68
+ def stop_record(self):
69
+ if self._edf_handler:
70
+ # 等待设备端数据传输完成
71
+ time.sleep(0.5)
72
+ # 添加结束标识
73
+ self._edf_handler.append(None)
74
+ self._edf_handler = None
75
+ self._recording = False
76
+ logger.info(f"停止记录数据: {self.box_mac}")
77
+
78
+ # 订阅推送消息
79
+ def subscribe(self, topic: str = None, q: Queue = Queue(), value_type: Literal['phy', 'dig'] = 'phy') -> tuple[str, Queue]:
80
+ if topic is None:
81
+ topic = f"msg_{self.box_mac}"
82
+
83
+ if value_type == 'dig':
84
+ if topic in list(self._dig_subscriber.keys()):
85
+ logger.warning(f"ar4 {self.box_mac} 订阅主题已存在: {topic}")
86
+ return topic, self._dig_subscriber[topic]
87
+ self._dig_subscriber[topic] = q
88
+ else:
89
+ if topic in list(self._phy_subscriber.keys()):
90
+ logger.warning(f"ar4 {self.box_mac} 订阅主题已存在: {topic}")
91
+ return topic, self._phy_subscriber[topic]
92
+ self._phy_subscriber[topic] = q
93
+
94
+ return topic, q
95
+
96
+ def eeg2phy(self, digtal):
97
+ # 向量化计算(自动支持广播)
98
+ return super().eeg2phy(digtal)
99
+
100
+ def acc2phy(self, digtal):
101
+ return super().eeg2phy(digtal)
102
+
103
+ class X8Packet(LMPacket):
104
+ def __init__(self, data: bytes):
105
+ super().__init__(data)
106
+ self._data = data
107
+ self._head = None
108
+ self._body = None
109
+
110
+ @property
111
+ def head(self):
112
+ return self._head
113
+
114
+ @property
115
+ def body(self):
116
+ return self._body
117
+
118
+ def parse(self):
119
+ # 解析数据包头部和数据体
120
+ if len(self._data) < 4:
121
+ logger.error(f"数据包长度不足: {len(self._data)}")
122
+ return False
123
+
124
+ # 解析头部和数据体
125
+ self._head = self._data[:4]
126
+ self._body = self._data[4:]
127
+
128
+ return True
qlsdk/x8m/__init__.py ADDED
@@ -0,0 +1,21 @@
1
+ from qlsdk.sdk import Hub
2
+ from qlsdk.x8 import X8
3
+ from loguru import logger
4
+
5
+
6
+ class X8M(Hub):
7
+ def __init__(self):
8
+ super().__init__()
9
+ self._devices: dict[str, X8] = {}
10
+ self._search_running = False
11
+ self._search_timer = None
12
+
13
+ def add_device(self, mac: str):
14
+ if mac in list(self._devices.keys()):
15
+ self._devices[mac].update_info()
16
+ logger.debug(f"update x8 device mac: {mac}")
17
+ else:
18
+ dev = X8(mac)
19
+ if dev.connected:
20
+ self._devices[mac] = dev
21
+ logger.info(f"add x8 device mac: {dev}")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: qlsdk2
3
- Version: 0.2.0
3
+ Version: 0.3.0a1
4
4
  Summary: SDK for quanlan device
5
5
  Home-page: https://github.com/hehuajun/qlsdk
6
6
  Author: hehuajun
@@ -12,6 +12,7 @@ Requires-Python: >=3.9
12
12
  Description-Content-Type: text/markdown
13
13
  Requires-Dist: loguru>=0.6.0
14
14
  Requires-Dist: numpy>=1.23.5
15
+ Requires-Dist: pyedflib>=0.1.40
15
16
  Provides-Extra: dev
16
17
  Requires-Dist: pytest>=6.0; extra == "dev"
17
18
  Requires-Dist: twine>=3.0; extra == "dev"
@@ -0,0 +1,18 @@
1
+ qlsdk/__init__.py,sha256=w0UCnZJekAq4orDahQXRL8s5JJGrWMz0De5LVIf4X_c,426
2
+ qlsdk/ar4/__init__.py,sha256=iR0bFanDwqSxSEM1nCcge1l-GSIWjwnMeRQa47wGrds,4752
3
+ qlsdk/ar4m/__init__.py,sha256=Z13X53WKmKp6MW_fA1FUPdQgJxhxxuyzemJWPS_CEHA,639
4
+ qlsdk/ar4m/ar4sdk.py,sha256=OtmlvbO7XAgk5FNPFYIv_rXGj14maaWtgi2lQ7zQkvY,41418
5
+ qlsdk/ar4m/persist.py,sha256=YrISKVfY-r1m2GZOw-JLuqTbEajA5wYa31MejGlz14I,6696
6
+ qlsdk/ar4m/libs/libAr4SDK.dll,sha256=kZp9_DRwPdAJ5OgTFQSqS8tEETxUs7YmmETuBP2g60U,15402132
7
+ qlsdk/ar4m/libs/libwinpthread-1.dll,sha256=W77ySaDQDi0yxpnQu-ifcU6-uHKzmQpcvsyx2J9j5eg,52224
8
+ qlsdk/persist/__init__.py,sha256=UYaNL_RSczIZL_YrBWAifoAnNxpgZHEeSp-goHqyqv4,27
9
+ qlsdk/persist/edf.py,sha256=usgFjZJVcfAUwSy6cJtRdgjdqMgOS4viLCDGcwAGMZE,7106
10
+ qlsdk/sdk/__init__.py,sha256=v9LKP-5qXCqnAsCkiRE9LDb5Tagvl_Qd_fqrw7y9yd4,68
11
+ qlsdk/sdk/ar4sdk.py,sha256=ZILuUVgUZN7-LNQm4xdItxmZWGwvFt4oWUKGez1BCLI,27101
12
+ qlsdk/sdk/hub.py,sha256=uEOGZBZtMDCWlV8G2TZe6FAo6eTPcwHAW8zdqr1eq_0,1571
13
+ qlsdk/x8/__init__.py,sha256=XlQn3Af_HA7bGrxhv3RZKWMob_SnmissXiso7OH1UgI,4750
14
+ qlsdk/x8m/__init__.py,sha256=cLeUqEEj65qXw4Qa4REyxoLh6T24anSqPaKe9_lR340,634
15
+ qlsdk2-0.3.0a1.dist-info/METADATA,sha256=4VqeQbubQOwzp3fwRsmNXgVRiWjvDXE6bCe7lcOGlNk,7066
16
+ qlsdk2-0.3.0a1.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
17
+ qlsdk2-0.3.0a1.dist-info/top_level.txt,sha256=2CHzn0SY-NIBVyBl07Suh-Eo8oBAQfyNPtqQ_aDatBg,6
18
+ qlsdk2-0.3.0a1.dist-info/RECORD,,
@@ -1,9 +0,0 @@
1
- qlsdk/__init__.py,sha256=pHMMwFiz7AGYlWvxo-81Obd7gIkojhLAEUGe0yuiAJI,372
2
- qlsdk/ar4m/__init__.py,sha256=HCFv58t9vYoH2nNN9EiswwdRngiDmh_7h-uwhW-id1I,1784
3
- qlsdk/ar4m/ar4sdk.py,sha256=DlPCVF5eFA500wXGk-gRqcQXGnoCdUhHe1yoLsOGu7c,23847
4
- qlsdk/ar4m/libs/libAr4SDK.dll,sha256=kZp9_DRwPdAJ5OgTFQSqS8tEETxUs7YmmETuBP2g60U,15402132
5
- qlsdk/ar4m/libs/libwinpthread-1.dll,sha256=W77ySaDQDi0yxpnQu-ifcU6-uHKzmQpcvsyx2J9j5eg,52224
6
- qlsdk2-0.2.0.dist-info/METADATA,sha256=V6UWoXTs44Ulwtb_HvDLyv8A6o6ACgqDTr_dy2XFU6A,7031
7
- qlsdk2-0.2.0.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
8
- qlsdk2-0.2.0.dist-info/top_level.txt,sha256=2CHzn0SY-NIBVyBl07Suh-Eo8oBAQfyNPtqQ_aDatBg,6
9
- qlsdk2-0.2.0.dist-info/RECORD,,