qlsdk2 0.5.1__py3-none-any.whl → 0.6.0__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/core/entity/__init__.py +175 -42
- qlsdk/core/message/udp.py +9 -1
- qlsdk/entity/__init__.py +0 -0
- qlsdk/entity/message.py +0 -0
- qlsdk/entity/signal.py +0 -0
- qlsdk/interface/__init__.py +10 -0
- qlsdk/interface/analyzer.py +2 -0
- qlsdk/interface/collector.py +10 -0
- qlsdk/interface/device.py +2 -0
- qlsdk/interface/parser.py +13 -0
- qlsdk/interface/stimulator.py +2 -0
- qlsdk/interface/store.py +2 -0
- qlsdk/persist/ars_edf.py +80 -101
- qlsdk/persist/rsc_edf.py +23 -13
- qlsdk/rsc/command/__init__.py +30 -16
- qlsdk/rsc/device/__init__.py +2 -1
- qlsdk/rsc/device/arskindling.py +248 -310
- qlsdk/rsc/device/base.py +214 -105
- qlsdk/rsc/device/c16_rs.py +1 -5
- qlsdk/rsc/device/c256_rs.py +17 -338
- qlsdk/rsc/device/c64_rs.py +2 -332
- qlsdk/rsc/device/c64s1.py +4 -340
- qlsdk/rsc/device/device_factory.py +1 -0
- qlsdk/rsc/interface/device.py +38 -80
- qlsdk/rsc/interface/parser.py +6 -0
- qlsdk/rsc/manager/container.py +10 -2
- qlsdk/rsc/network/discover.py +2 -0
- qlsdk/rsc/paradigm.py +127 -6
- qlsdk/rsc/parser/__init__.py +2 -1
- qlsdk/rsc/parser/base.py +11 -6
- qlsdk/rsc/parser/rsc.py +130 -0
- {qlsdk2-0.5.1.dist-info → qlsdk2-0.6.0.dist-info}/METADATA +25 -15
- {qlsdk2-0.5.1.dist-info → qlsdk2-0.6.0.dist-info}/RECORD +35 -24
- {qlsdk2-0.5.1.dist-info → qlsdk2-0.6.0.dist-info}/WHEEL +0 -0
- {qlsdk2-0.5.1.dist-info → qlsdk2-0.6.0.dist-info}/top_level.txt +0 -0
qlsdk/rsc/paradigm.py
CHANGED
|
@@ -61,6 +61,22 @@ class StimulationChannel(ABC):
|
|
|
61
61
|
|
|
62
62
|
return result
|
|
63
63
|
|
|
64
|
+
def to_bytes_c256(self):
|
|
65
|
+
result = self.channel_id.to_bytes(1, 'little')
|
|
66
|
+
result += self.wave_form.to_bytes(1, 'little')
|
|
67
|
+
|
|
68
|
+
result += self._to_bytes_c256()
|
|
69
|
+
|
|
70
|
+
result += int(self.delay_time).to_bytes(4, 'little')
|
|
71
|
+
result += int(self.ramp_up * 1000).to_bytes(4, 'little')
|
|
72
|
+
result += int((self.duration + self.ramp_up) * 1000).to_bytes(4, 'little')
|
|
73
|
+
result += int(self.ramp_down * 1000).to_bytes(4, 'little')
|
|
74
|
+
|
|
75
|
+
return result
|
|
76
|
+
|
|
77
|
+
def _to_bytes_c256(self):
|
|
78
|
+
return bytes.fromhex("00000000000000000000000000000000000000000000000000000000")
|
|
79
|
+
|
|
64
80
|
def _ext_bytes(self):
|
|
65
81
|
return bytes.fromhex("00000000000000000000000000000000")
|
|
66
82
|
|
|
@@ -99,6 +115,9 @@ class DCStimulation(StimulationChannel):
|
|
|
99
115
|
"delay_time": self.delay_time
|
|
100
116
|
}
|
|
101
117
|
|
|
118
|
+
def _to_bytes_c256(self):
|
|
119
|
+
return int(self.current_max * 1000 ).to_bytes(2, 'little') + bytes.fromhex("0000000000000000000000000000000000000000000000000000")
|
|
120
|
+
|
|
102
121
|
def from_json(self, param):
|
|
103
122
|
pass
|
|
104
123
|
def __str__(self):
|
|
@@ -140,9 +159,19 @@ class SquareWaveStimulation(StimulationChannel):
|
|
|
140
159
|
result += int((self.duration + self.ramp_up) * 1000).to_bytes(4, 'little')
|
|
141
160
|
result += int(self.ramp_down * 1000).to_bytes(4, 'little')
|
|
142
161
|
|
|
143
|
-
return result
|
|
144
|
-
|
|
145
|
-
|
|
162
|
+
return result
|
|
163
|
+
|
|
164
|
+
def _to_bytes_c256(self):
|
|
165
|
+
result = int(self.current_max * 1000000 ).to_bytes(4, 'little')
|
|
166
|
+
result += int(self.frequency).to_bytes(2, 'little')
|
|
167
|
+
result += bytes.fromhex("0000")
|
|
168
|
+
result += struct.pack('<f', self.duty_cycle)
|
|
169
|
+
result = int(self.current_min * 1000000 ).to_bytes(4, 'little')
|
|
170
|
+
result += self._ext_bytes()
|
|
171
|
+
return result
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
# 刺激模式-正弦
|
|
146
175
|
class ACStimulation(StimulationChannel):
|
|
147
176
|
'''
|
|
148
177
|
channel_id: int, 通道编号,从0开始
|
|
@@ -162,7 +191,8 @@ class ACStimulation(StimulationChannel):
|
|
|
162
191
|
self.frequency = frequency
|
|
163
192
|
# self.frequency = frequency
|
|
164
193
|
self.phase_position = phase_position
|
|
165
|
-
|
|
194
|
+
if current < 0:
|
|
195
|
+
self.phase_position = (phase_position + 180) % 360
|
|
166
196
|
def to_json(self):
|
|
167
197
|
return {
|
|
168
198
|
"channel_id": self.channel_id,
|
|
@@ -177,6 +207,15 @@ class ACStimulation(StimulationChannel):
|
|
|
177
207
|
|
|
178
208
|
def from_json(self, param):
|
|
179
209
|
pass
|
|
210
|
+
|
|
211
|
+
def _to_bytes_c256(self):
|
|
212
|
+
result = int(self.current_max * 1000 ).to_bytes(2, 'little')
|
|
213
|
+
result += bytes.fromhex("0000")
|
|
214
|
+
result += struct.pack('<f', self.frequency)
|
|
215
|
+
result += struct.pack('<f', self.phase_position)
|
|
216
|
+
result += self._ext_bytes()
|
|
217
|
+
return result
|
|
218
|
+
|
|
180
219
|
def __str__(self):
|
|
181
220
|
return f"ACStimulation(channel_id={self.channel_id}, waveform={self.waveform}, current={self.current_max}, duration={self.duration}, ramp_up={self.ramp_up}, ramp_down={self.ramp_down}, frequency={self.frequency}, phase_position={self.phase_position}, duration_delay={self.duration_delay})"
|
|
182
221
|
|
|
@@ -230,6 +269,15 @@ class PulseStimulation(StimulationChannel):
|
|
|
230
269
|
|
|
231
270
|
return result
|
|
232
271
|
|
|
272
|
+
def _to_bytes_c256(self):
|
|
273
|
+
result = int(self.current_max * 1000000 ).to_bytes(4, 'little')
|
|
274
|
+
result += int(self.frequency).to_bytes(2, 'little')
|
|
275
|
+
result += bytes.fromhex("0000")
|
|
276
|
+
result += struct.pack('<f', self.duty_cycle)
|
|
277
|
+
result = int(self.current_min * 1000000 ).to_bytes(4, 'little')
|
|
278
|
+
result += self._ext_bytes()
|
|
279
|
+
return result
|
|
280
|
+
|
|
233
281
|
def to_json(self):
|
|
234
282
|
return {
|
|
235
283
|
"channel_id": self.channel_id,
|
|
@@ -254,7 +302,7 @@ class StimulationParadigm(object):
|
|
|
254
302
|
def __init__(self):
|
|
255
303
|
self.channels = None
|
|
256
304
|
self.duration = None
|
|
257
|
-
self.interval_time =
|
|
305
|
+
self.interval_time = 25000
|
|
258
306
|
self.characteristic = 1
|
|
259
307
|
self.mode = 0
|
|
260
308
|
self.repeats = 0
|
|
@@ -287,6 +335,17 @@ class StimulationParadigm(object):
|
|
|
287
335
|
result += channel.to_bytes()
|
|
288
336
|
return result
|
|
289
337
|
|
|
338
|
+
def to_bytes_c256(self):
|
|
339
|
+
result = to_bytes(list(self.channels.keys()), 256)
|
|
340
|
+
result += int(self.duration * 1000).to_bytes(4, 'little')
|
|
341
|
+
result += int(self.interval_time).to_bytes(4, 'little')
|
|
342
|
+
result += int(self.characteristic).to_bytes(4, 'little')
|
|
343
|
+
result += int(self.mode).to_bytes(1, 'little')
|
|
344
|
+
result += int(self.repeats).to_bytes(4, 'little')
|
|
345
|
+
for channel in self.channels.values():
|
|
346
|
+
result += channel.to_bytes()
|
|
347
|
+
return result
|
|
348
|
+
|
|
290
349
|
def to_json(self):
|
|
291
350
|
# Convert the object to JSON for transmission
|
|
292
351
|
return {
|
|
@@ -306,8 +365,70 @@ class StimulationParadigm(object):
|
|
|
306
365
|
def clear(self):
|
|
307
366
|
self.channels = None
|
|
308
367
|
self.duration = None
|
|
309
|
-
self.interval_time =
|
|
368
|
+
self.interval_time = 25000
|
|
310
369
|
self.characteristic = 1
|
|
311
370
|
self.mode = 0
|
|
312
371
|
self.repeats = 0
|
|
313
372
|
|
|
373
|
+
|
|
374
|
+
# 刺激范式
|
|
375
|
+
class C256StimulationParadigm(object):
|
|
376
|
+
def __init__(self):
|
|
377
|
+
self.channels = None
|
|
378
|
+
self.duration = None
|
|
379
|
+
self.interval_time = 0
|
|
380
|
+
self.characteristic = 1
|
|
381
|
+
self.mode = 0
|
|
382
|
+
self.repeats = 0
|
|
383
|
+
|
|
384
|
+
def add_channel(self, channel: StimulationChannel, update=False):
|
|
385
|
+
if self.channels is None:
|
|
386
|
+
self.channels = {}
|
|
387
|
+
channel_id = channel.channel_id + 1
|
|
388
|
+
if channel_id in self.channels.keys():
|
|
389
|
+
logger.warning(f"Channel {channel_id} already exists")
|
|
390
|
+
if update:
|
|
391
|
+
self.channels[channel_id] = channel
|
|
392
|
+
else:
|
|
393
|
+
self.channels[channel_id] = channel
|
|
394
|
+
|
|
395
|
+
# 计算刺激时间
|
|
396
|
+
duration = channel.duration + channel.ramp_up + channel.ramp_down
|
|
397
|
+
if self.duration is None or duration > self.duration:
|
|
398
|
+
self.duration = duration
|
|
399
|
+
|
|
400
|
+
|
|
401
|
+
def to_bytes(self):
|
|
402
|
+
result = to_bytes(list(self.channels.keys()), 64)
|
|
403
|
+
result += int(self.duration * 1000).to_bytes(4, 'little')
|
|
404
|
+
result += int(self.interval_time).to_bytes(4, 'little')
|
|
405
|
+
result += int(self.characteristic).to_bytes(4, 'little')
|
|
406
|
+
result += int(self.mode).to_bytes(1, 'little')
|
|
407
|
+
result += int(self.repeats).to_bytes(4, 'little')
|
|
408
|
+
for channel in self.channels.values():
|
|
409
|
+
result += channel.to_bytes()
|
|
410
|
+
return result
|
|
411
|
+
|
|
412
|
+
def to_json(self):
|
|
413
|
+
# Convert the object to JSON for transmission
|
|
414
|
+
return {
|
|
415
|
+
"channels": list(self.channels.keys()),
|
|
416
|
+
"duration": self.duration,
|
|
417
|
+
"interval_time": self.interval_time,
|
|
418
|
+
"characteristic": self.characteristic,
|
|
419
|
+
"mode": self.mode,
|
|
420
|
+
"repeats": self.repeats,
|
|
421
|
+
"stim": [channel.to_json() for channel in self.channels.values()]
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
# @staticmethod
|
|
425
|
+
# def from_json(param: Dict[str, Any]):
|
|
426
|
+
# pass
|
|
427
|
+
|
|
428
|
+
def clear(self):
|
|
429
|
+
self.channels = None
|
|
430
|
+
self.duration = None
|
|
431
|
+
self.interval_time = 0
|
|
432
|
+
self.characteristic = 1
|
|
433
|
+
self.mode = 0
|
|
434
|
+
self.repeats = 0
|
qlsdk/rsc/parser/__init__.py
CHANGED
|
@@ -1 +1,2 @@
|
|
|
1
|
-
from .base import TcpMessageParser
|
|
1
|
+
from .base import TcpMessageParser
|
|
2
|
+
from .rsc import RSCMessageParser
|
qlsdk/rsc/parser/base.py
CHANGED
|
@@ -53,7 +53,7 @@ class TcpMessageParser(IParser):
|
|
|
53
53
|
buf_len = get_len(self.buffer)
|
|
54
54
|
|
|
55
55
|
if buf_len < self.header_len:
|
|
56
|
-
logger.trace(f"
|
|
56
|
+
# logger.trace(f"等待数据中...: expect: {self.header_len}, actual: {buf_len}")
|
|
57
57
|
if not self.__fill_from_cache():
|
|
58
58
|
time.sleep(0.1)
|
|
59
59
|
continue
|
|
@@ -64,7 +64,7 @@ class TcpMessageParser(IParser):
|
|
|
64
64
|
start_pos = self.buffer.tell()
|
|
65
65
|
head = self.buffer.read(2)
|
|
66
66
|
if head != self.header:
|
|
67
|
-
logger.
|
|
67
|
+
# logger.trace(f"数据包头部不匹配: {head.hex()}, 期望: {self.header.hex()},继续查找...")
|
|
68
68
|
self.buffer.seek(start_pos + 1) # 移动到下一个字节
|
|
69
69
|
continue
|
|
70
70
|
|
|
@@ -131,10 +131,15 @@ class TcpMessageParser(IParser):
|
|
|
131
131
|
|
|
132
132
|
def unpack(self, packet):
|
|
133
133
|
# 提取指令码
|
|
134
|
-
cmd_code =
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
134
|
+
cmd_code = None
|
|
135
|
+
try:
|
|
136
|
+
cmd_code = int.from_bytes(packet[self.cmd_pos : self.cmd_pos + 2], 'little')
|
|
137
|
+
cmd_class = CommandFactory.create_command(cmd_code)
|
|
138
|
+
instance = cmd_class(self.device)
|
|
139
|
+
instance.parse_body(packet[self.header_len:-2])
|
|
140
|
+
except Exception as e:
|
|
141
|
+
logger.error(f"指令[{cmd_code}]数据包[len={len(packet)}]解析异常: {e}")
|
|
142
|
+
|
|
138
143
|
return instance
|
|
139
144
|
|
|
140
145
|
def start(self):
|
qlsdk/rsc/parser/rsc.py
ADDED
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
from multiprocessing import Lock
|
|
2
|
+
from qlsdk.rsc.interface import IDevice, IParser
|
|
3
|
+
|
|
4
|
+
from loguru import logger
|
|
5
|
+
from threading import Thread
|
|
6
|
+
from time import time_ns
|
|
7
|
+
from qlsdk.rsc.command import CommandFactory
|
|
8
|
+
|
|
9
|
+
class RSCMessageParser(IParser):
|
|
10
|
+
def __init__(self, device : IDevice):
|
|
11
|
+
# 待解析的数据来源于该设备
|
|
12
|
+
self.device = device
|
|
13
|
+
self.running = False
|
|
14
|
+
|
|
15
|
+
# 缓冲区-用于处理数据
|
|
16
|
+
self.buffer:bytearray = bytearray()
|
|
17
|
+
# 读写锁-用于临时缓冲区(避免读写冲突)
|
|
18
|
+
self._lock = Lock()
|
|
19
|
+
|
|
20
|
+
@property
|
|
21
|
+
def header(self):
|
|
22
|
+
return b'\x5A\xA5'
|
|
23
|
+
|
|
24
|
+
@property
|
|
25
|
+
def header_len(self):
|
|
26
|
+
return 14
|
|
27
|
+
|
|
28
|
+
@property
|
|
29
|
+
def cmd_pos(self):
|
|
30
|
+
return 12
|
|
31
|
+
|
|
32
|
+
def set_device(self, device):
|
|
33
|
+
self.device = device
|
|
34
|
+
|
|
35
|
+
def append(self, value):
|
|
36
|
+
print(f"append value len: {len(value)}")
|
|
37
|
+
def __parser__(self):
|
|
38
|
+
logger.info("数据解析开始")
|
|
39
|
+
|
|
40
|
+
try:
|
|
41
|
+
while self.running:
|
|
42
|
+
|
|
43
|
+
# 查找消息头
|
|
44
|
+
while len(self.buffer) < len(self.header):
|
|
45
|
+
read_data = self.device.read_msg(1)
|
|
46
|
+
if read_data is None:
|
|
47
|
+
if self.running:
|
|
48
|
+
continue
|
|
49
|
+
else:
|
|
50
|
+
break
|
|
51
|
+
if read_data[0] == self.header[len(self.buffer)]:
|
|
52
|
+
self.buffer.extend(read_data)
|
|
53
|
+
else:
|
|
54
|
+
self.buffer.clear()
|
|
55
|
+
break
|
|
56
|
+
|
|
57
|
+
if len(self.buffer) < len(self.header):
|
|
58
|
+
continue
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
# 判断消息头
|
|
62
|
+
while len(self.buffer) < self.header_len:
|
|
63
|
+
read_data = self.device.read_msg(self.header_len - len(self.buffer))
|
|
64
|
+
if read_data is None:
|
|
65
|
+
if self.running:
|
|
66
|
+
continue
|
|
67
|
+
else:
|
|
68
|
+
break
|
|
69
|
+
self.buffer.extend(read_data)
|
|
70
|
+
|
|
71
|
+
# # 移动下标(指向包长度的位置)
|
|
72
|
+
# self.buffer.seek(self.start_pos + 8)
|
|
73
|
+
# 包总长度
|
|
74
|
+
pkg_len = int.from_bytes(self.buffer[8:12], 'little')
|
|
75
|
+
# 256*32K = 8388608
|
|
76
|
+
# 太长2M
|
|
77
|
+
if pkg_len > 2048000:
|
|
78
|
+
print(f"error message pkg_len={pkg_len} > 1000000")
|
|
79
|
+
self.buffer.clear()
|
|
80
|
+
continue
|
|
81
|
+
# 太短
|
|
82
|
+
if pkg_len < self.header_len:
|
|
83
|
+
print(f"error message pkg_len={pkg_len} < {self.header_len}")
|
|
84
|
+
self.buffer.clear()
|
|
85
|
+
continue
|
|
86
|
+
|
|
87
|
+
# 读取消息体
|
|
88
|
+
while len(self.buffer) < pkg_len:
|
|
89
|
+
read_data = self.device.read_msg(pkg_len - len(self.buffer))
|
|
90
|
+
if read_data is None:
|
|
91
|
+
if self.running:
|
|
92
|
+
continue
|
|
93
|
+
else:
|
|
94
|
+
break
|
|
95
|
+
self.buffer.extend(read_data)
|
|
96
|
+
|
|
97
|
+
if len(self.buffer) < pkg_len:
|
|
98
|
+
continue
|
|
99
|
+
|
|
100
|
+
# msg_crc = self.buffer[-2:]
|
|
101
|
+
# cal_crc = (bytes_buffer, len(bytes_buffer) - 2)
|
|
102
|
+
# if cal_crc != msg_crc:
|
|
103
|
+
# print(f'crc fail {cal_crc} {msg_crc}')
|
|
104
|
+
# if cal_crc != msg_crc:
|
|
105
|
+
# print(f'crc fail {cal_crc} {msg_crc}')
|
|
106
|
+
|
|
107
|
+
self.unpack(self.buffer)
|
|
108
|
+
self.buffer.clear()
|
|
109
|
+
|
|
110
|
+
except Exception as e:
|
|
111
|
+
logger.error(f"数据解析异常: {e}")
|
|
112
|
+
|
|
113
|
+
logger.info(f"数据解析结束:{self.running}")
|
|
114
|
+
|
|
115
|
+
def unpack(self, packet):
|
|
116
|
+
# 提取指令码
|
|
117
|
+
cmd_code = int.from_bytes(packet[self.cmd_pos : self.cmd_pos + 2], 'little')
|
|
118
|
+
cmd_class = CommandFactory.create_command(cmd_code)
|
|
119
|
+
instance = cmd_class(self.device)
|
|
120
|
+
instance.parse_body(packet[self.header_len:-2])
|
|
121
|
+
return instance
|
|
122
|
+
|
|
123
|
+
def start(self):
|
|
124
|
+
self.running = True
|
|
125
|
+
parser = Thread(target=self.__parser__, daemon=True)
|
|
126
|
+
parser.start()
|
|
127
|
+
|
|
128
|
+
def stop(self):
|
|
129
|
+
self.running = False
|
|
130
|
+
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: qlsdk2
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.6.0
|
|
4
4
|
Summary: SDK for quanlan device
|
|
5
5
|
Home-page: https://github.com/hehuajun/qlsdk
|
|
6
6
|
Author: hehuajun
|
|
@@ -17,41 +17,51 @@ Provides-Extra: dev
|
|
|
17
17
|
Requires-Dist: pytest >=6.0 ; extra == 'dev'
|
|
18
18
|
Requires-Dist: twine >=3.0 ; extra == 'dev'
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
## **v0.6.0 (2025-xx-xx)
|
|
21
|
+
#### 新设备
|
|
22
|
+
- C256RS设备
|
|
21
23
|
|
|
22
|
-
## ⚙️ 优化
|
|
23
|
-
#### 修复C16R通道映射的问题
|
|
24
24
|
|
|
25
|
-
|
|
25
|
+
## **v0.5.1.1** (2025-08-24)
|
|
26
|
+
#### 🐛 Bug Fixed
|
|
27
|
+
- 修复仅选择一个通道时,自动保存功能异常的问题
|
|
26
28
|
|
|
27
|
-
#### 订阅队列满的时候,丢弃最早的数据
|
|
28
29
|
|
|
30
|
+
## **v0.5.1** (2025-08-04)
|
|
29
31
|
|
|
30
|
-
|
|
32
|
+
#### ⚙️ Changed
|
|
33
|
+
- C16R通道映射调整为按老的脑电帽位点映射(固件端做了映射)
|
|
31
34
|
|
|
32
|
-
|
|
35
|
+
- 开放底层参数,支持EDF/BDF文件中存储大量事件(>1个/秒)
|
|
33
36
|
|
|
34
|
-
|
|
37
|
+
- 优化实时信号数据订阅(发布/订阅模式),在调用者使用不规范时,多个订阅者之间不会互相干扰
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
## **v0.5.0** (2025-07-29)
|
|
41
|
+
|
|
42
|
+
#### 🚀 Added
|
|
43
|
+
|
|
44
|
+
- *新增C16R搜索与连接*
|
|
35
45
|
支持C16R类型设备的搜索与连接
|
|
36
46
|
|
|
37
|
-
|
|
47
|
+
- *C16R信号采集/停止控制*
|
|
38
48
|
支持信号采集的参数配置
|
|
39
49
|
支持信号采集的启动与停止控制
|
|
40
50
|
|
|
41
|
-
|
|
51
|
+
- *C16R数据自动记录*
|
|
42
52
|
采集到的信号数据自动保存为bdf文件
|
|
43
53
|
|
|
44
|
-
|
|
54
|
+
- *C16R采集通道设置*
|
|
45
55
|
- 支持数字模式通道配置
|
|
46
56
|
- 支持名称模式通道配置
|
|
47
57
|
- 支持两种模式混合使用
|
|
48
58
|
|
|
49
|
-
|
|
59
|
+
#### ⚙️ Changed
|
|
50
60
|
|
|
51
|
-
|
|
61
|
+
- *性能提升*
|
|
52
62
|
- 信号接收效率优化
|
|
53
63
|
- 指令拆包方式优化
|
|
54
64
|
|
|
55
|
-
|
|
65
|
+
- *日志系统改进*
|
|
56
66
|
- 日志级别精细化调整,减少不必要的日志信息
|
|
57
67
|
- 日志文案清晰化
|
|
@@ -8,50 +8,61 @@ qlsdk/core/local.py,sha256=vbison4XZtS4SNYLJ9CqBhetEcukdviTWmvtdA1efkQ,811
|
|
|
8
8
|
qlsdk/core/utils.py,sha256=yfCiLpufO96I68MLs6Drc6IECRjcQ-If8sXn7RaRHrk,4241
|
|
9
9
|
qlsdk/core/crc/__init__.py,sha256=kaYSr6KN5g4U49xlxAvT2lnEeGtwX4Dz1ArwKDvUIIY,143
|
|
10
10
|
qlsdk/core/crc/crctools.py,sha256=sDeE6CMccQX2cRAyMQK0SZUk1fa50XMuwqXau5UX5C8,4242
|
|
11
|
-
qlsdk/core/entity/__init__.py,sha256=
|
|
11
|
+
qlsdk/core/entity/__init__.py,sha256=5Uoywn4WkCj9SJc4rm1AypC-92zc34ztGMyam8FQ6VY,9026
|
|
12
12
|
qlsdk/core/filter/__init__.py,sha256=YIWIzDUKN30mq2JTr53ZGblggZfC_rLUp2FSRrsQFgU,36
|
|
13
13
|
qlsdk/core/filter/norch.py,sha256=5RdIBX5eqs5w5nmVAnCB3ESSuAT_vVBZ2g-dg6HMZdY,1858
|
|
14
14
|
qlsdk/core/message/__init__.py,sha256=sHuavOyHf4bhH6VdDpTA1EsCh7Q-XsPHcFiItpVz3Rs,51
|
|
15
15
|
qlsdk/core/message/command.py,sha256=94AyM6qmgVHQ8qzNLczdL8iY6N-2uEP5oBU6kD6pOG8,12102
|
|
16
16
|
qlsdk/core/message/tcp.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
17
|
-
qlsdk/core/message/udp.py,sha256=
|
|
17
|
+
qlsdk/core/message/udp.py,sha256=e_w35NSlgmhptzlMNGee7rE7KVgeLDO2WhE6FEnuy-0,3387
|
|
18
18
|
qlsdk/core/network/__init__.py,sha256=9Ww0cGgBEU_TVrwmgiDz20zA2fMFgepI_kOF4ggHcS0,1111
|
|
19
19
|
qlsdk/core/network/monitor.py,sha256=QqjjPwSr1kgqDTTySp5bpalZmsBQTaAWSxrfPLdROZo,1810
|
|
20
|
+
qlsdk/entity/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
21
|
+
qlsdk/entity/message.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
22
|
+
qlsdk/entity/signal.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
23
|
+
qlsdk/interface/__init__.py,sha256=zvXbyjbMWlPBt7AhD7fF4JwTrDqwkdyH8rH2xkmslGE,123
|
|
24
|
+
qlsdk/interface/analyzer.py,sha256=-muX0wWUn2e-PvUJicSstCGXHJZw2yP7Er1soJsWybw,26
|
|
25
|
+
qlsdk/interface/collector.py,sha256=ye9dVjRVYfCjeJsGV8Jc4ppwp58qKW5_u5e8IIcvL4U,190
|
|
26
|
+
qlsdk/interface/device.py,sha256=09Z2KQ1dj6gP-7CdPXfMvT8YhyadgqIfo4rf6PAyXog,24
|
|
27
|
+
qlsdk/interface/parser.py,sha256=00Ds01Xp9eUPwx7okL4B1Bl0_fRbgaxfm_2GOeWoZiM,248
|
|
28
|
+
qlsdk/interface/stimulator.py,sha256=MJbgiI-4qTMjbdhcBAZe8zb10hV9x8yhFCPL3Iq_QyI,28
|
|
29
|
+
qlsdk/interface/store.py,sha256=694WQnnrtXThP44JkQlBXzghvqA0PwHKK3uA640aiUo,23
|
|
20
30
|
qlsdk/persist/__init__.py,sha256=b8qk1aOU6snEMCQNYDl1ijV3-2gwBmMt76fiAzNk1E8,107
|
|
21
|
-
qlsdk/persist/ars_edf.py,sha256=
|
|
31
|
+
qlsdk/persist/ars_edf.py,sha256=aY_bGM2QsqpKAAJqs6kR7hBVpq8PaayNtcqeLJlt1Fc,9138
|
|
22
32
|
qlsdk/persist/edf.py,sha256=ETngb86CfkIUJYWmw86QR445MvTFC7Edk_CH9nyNgtY,7857
|
|
23
|
-
qlsdk/persist/rsc_edf.py,sha256=
|
|
33
|
+
qlsdk/persist/rsc_edf.py,sha256=ptM_JfVClgZnh96SUrO_eperIhsnMwGqmhjKaPlLEn0,14042
|
|
24
34
|
qlsdk/persist/stream.py,sha256=TCVF1sqDrHiYBsJC27At66AaCs-_blXeXA_WXdJiIVA,5828
|
|
25
35
|
qlsdk/rsc/__init__.py,sha256=hOMiN0eYn4jYo7O4_0IPlQT0hD15SqqCQUihOVlTZvs,269
|
|
26
36
|
qlsdk/rsc/device_manager.py,sha256=1ucd-lzHkNeQPKPzXV6OBkAMqPp_vOcsLyS-9TJ7wRc,4448
|
|
27
37
|
qlsdk/rsc/discover.py,sha256=ONXN6YWY-OMU0sBoLqqKUyb-8drtAp1g_MvnpzaFvHQ,3124
|
|
28
38
|
qlsdk/rsc/eegion.py,sha256=lxrktO-3Z_MYdFIwc4NxvgLM5AL5kU3UItjH6tsKmHY,11670
|
|
29
39
|
qlsdk/rsc/entity.py,sha256=-fRWFkVWp9d8Y1uh6GiacXC5scdeEKNiNFf3aziGdCE,17751
|
|
30
|
-
qlsdk/rsc/paradigm.py,sha256=
|
|
40
|
+
qlsdk/rsc/paradigm.py,sha256=WH9kAez0wbci-B1z5BC-nw3nqqOtE_txFILue4TM-cE,17644
|
|
31
41
|
qlsdk/rsc/proxy.py,sha256=9CPdGNGWremwBUh4GvlXAykYB-x_BEPPLqsNvwuwIDE,2736
|
|
32
|
-
qlsdk/rsc/command/__init__.py,sha256=
|
|
42
|
+
qlsdk/rsc/command/__init__.py,sha256=lewJj_Ys_oIhAGinLvAp7ZFc_BrCbWjfaNMnOw9sfXw,12791
|
|
33
43
|
qlsdk/rsc/command/message.py,sha256=nTdG-Vp4MBnltyrgedAWiKD6kzOaPrg58Z_hq6yjhys,12220
|
|
34
|
-
qlsdk/rsc/device/__init__.py,sha256=
|
|
35
|
-
qlsdk/rsc/device/arskindling.py,sha256=
|
|
36
|
-
qlsdk/rsc/device/base.py,sha256=
|
|
37
|
-
qlsdk/rsc/device/c16_rs.py,sha256=
|
|
38
|
-
qlsdk/rsc/device/c256_rs.py,sha256=
|
|
39
|
-
qlsdk/rsc/device/c64_rs.py,sha256=
|
|
40
|
-
qlsdk/rsc/device/c64s1.py,sha256=
|
|
41
|
-
qlsdk/rsc/device/device_factory.py,sha256=
|
|
44
|
+
qlsdk/rsc/device/__init__.py,sha256=BzY9lRfssGPUlJ1ys-v3CWNgGihg7mPa2T4X0tl0Vg4,214
|
|
45
|
+
qlsdk/rsc/device/arskindling.py,sha256=RB1qVJQhMaqUQ4KNuU8u27JBPifEbqTjoyfboSTCdT0,12032
|
|
46
|
+
qlsdk/rsc/device/base.py,sha256=zrkQ36hDUyFym_jqP9EN3n-b5DFCcUn4SyhtwG2baDc,22669
|
|
47
|
+
qlsdk/rsc/device/c16_rs.py,sha256=qXt8m5vwcKQsN8JBllWnAsda5_Y6qkEhfHQQX101TMQ,5826
|
|
48
|
+
qlsdk/rsc/device/c256_rs.py,sha256=7vAEzf_ggNcwrXKmcZMylnKzLFD5ZqtAIfkkI3lQ1iI,1682
|
|
49
|
+
qlsdk/rsc/device/c64_rs.py,sha256=x8wHdwATKDU34j9vXNEXsNSJg23RAWmAKL8pgIGamG8,1091
|
|
50
|
+
qlsdk/rsc/device/c64s1.py,sha256=WwiKSjxYpUJVkHDMDzPgp7-klbaiZ2f8EOe3wV6d2WU,1098
|
|
51
|
+
qlsdk/rsc/device/device_factory.py,sha256=6cPhm3pPGrVXA1s1HePFLjZqmhNI1vOAucFI0VRD_Y0,1317
|
|
42
52
|
qlsdk/rsc/interface/__init__.py,sha256=xeRzIlQSB7ZSf4r5kLfH5cDQLzCyWeJAReG8Xq5nOE0,70
|
|
43
53
|
qlsdk/rsc/interface/command.py,sha256=1s5Lxb_ejsd-JNvKMqU2aFSnOoW-_cx01VSD3czxmQI,199
|
|
44
|
-
qlsdk/rsc/interface/device.py,sha256=
|
|
54
|
+
qlsdk/rsc/interface/device.py,sha256=8Aqx-jS6v9pKd9qvTGytPspzGtDUlIxHc0g9R-wkV_s,2623
|
|
45
55
|
qlsdk/rsc/interface/handler.py,sha256=ADDe_a2RAxGMuooLyivH0JBPTGBcFP2JaTVX41R1A4w,198
|
|
46
|
-
qlsdk/rsc/interface/parser.py,sha256=
|
|
56
|
+
qlsdk/rsc/interface/parser.py,sha256=Z4PND5LXcJ_8CQ-OIq3KlOEVOceU1hKUuZkoFSIGGLM,334
|
|
47
57
|
qlsdk/rsc/manager/__init__.py,sha256=4ljT3mR8YPBDQur46B5xPqK5tjLKlsWfgCJVuA0gs-8,40
|
|
48
|
-
qlsdk/rsc/manager/container.py,sha256=
|
|
58
|
+
qlsdk/rsc/manager/container.py,sha256=S6E0_ZXejC_YM_kzMQQHr7daPJPbVwZINBbYhreFW5w,5389
|
|
49
59
|
qlsdk/rsc/manager/search.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
50
60
|
qlsdk/rsc/network/__init__.py,sha256=PfYiqXS2pZV__uegQ1TjaeYhY1pefZ_shwE_X5HNVbs,23
|
|
51
|
-
qlsdk/rsc/network/discover.py,sha256=
|
|
52
|
-
qlsdk/rsc/parser/__init__.py,sha256=
|
|
61
|
+
qlsdk/rsc/network/discover.py,sha256=GRXP0WxxIorDZWXq1X5CPAV60raSRvNiVwMQE8647XA,3044
|
|
62
|
+
qlsdk/rsc/parser/__init__.py,sha256=cVKk06bRYOnwE3XMoksGlatKJSaZE1GVrYypQm-9aro,69
|
|
53
63
|
qlsdk/rsc/parser/base-new.py,sha256=cAOy1V_1fAJyGq7bm7uLxpW41DbkllWOprnfWKpjtsQ,5116
|
|
54
|
-
qlsdk/rsc/parser/base.py,sha256=
|
|
64
|
+
qlsdk/rsc/parser/base.py,sha256=LbRpaa3z6kGL9HtevuEI8Q6O2R4WM5Gxvlx0ZYOndBg,5901
|
|
65
|
+
qlsdk/rsc/parser/rsc.py,sha256=RuBqsg5KZNio7mTyM14svQEeU0_0CLhnRmfbP0NBM2o,4724
|
|
55
66
|
qlsdk/sdk/__init__.py,sha256=v9LKP-5qXCqnAsCkiRE9LDb5Tagvl_Qd_fqrw7y9yd4,68
|
|
56
67
|
qlsdk/sdk/ar4sdk.py,sha256=tugH3UUeNebdka78AzLyrtAXbYQQE3iFJ227zUit6tY,27261
|
|
57
68
|
qlsdk/sdk/hub.py,sha256=uEOGZBZtMDCWlV8G2TZe6FAo6eTPcwHAW8zdqr1eq_0,1571
|
|
@@ -59,7 +70,7 @@ qlsdk/sdk/libs/libAr4SDK.dll,sha256=kZp9_DRwPdAJ5OgTFQSqS8tEETxUs7YmmETuBP2g60U,
|
|
|
59
70
|
qlsdk/sdk/libs/libwinpthread-1.dll,sha256=W77ySaDQDi0yxpnQu-ifcU6-uHKzmQpcvsyx2J9j5eg,52224
|
|
60
71
|
qlsdk/x8/__init__.py,sha256=FDpDK7GAYL-g3vzfU9U_V03QzoYoxH9YLm93PjMlANg,4870
|
|
61
72
|
qlsdk/x8m/__init__.py,sha256=cLeUqEEj65qXw4Qa4REyxoLh6T24anSqPaKe9_lR340,634
|
|
62
|
-
qlsdk2-0.
|
|
63
|
-
qlsdk2-0.
|
|
64
|
-
qlsdk2-0.
|
|
65
|
-
qlsdk2-0.
|
|
73
|
+
qlsdk2-0.6.0.dist-info/METADATA,sha256=ZxsGQsmmUp3qJhK867HMwUrzxItBdPtfv4rcZYW2EtI,1880
|
|
74
|
+
qlsdk2-0.6.0.dist-info/WHEEL,sha256=Z4pYXqR_rTB7OWNDYFOm1qRk0RX6GFP2o8LgvP453Hk,91
|
|
75
|
+
qlsdk2-0.6.0.dist-info/top_level.txt,sha256=2CHzn0SY-NIBVyBl07Suh-Eo8oBAQfyNPtqQ_aDatBg,6
|
|
76
|
+
qlsdk2-0.6.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|