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/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 = 0
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 = 0
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
@@ -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"操作区缓存数据不足: expect: {self.header_len}, actual: {buf_len}, 等待数据...")
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.debug(f"数据包头部不匹配: {head.hex()}, 期望: {self.header.hex()},继续查找...")
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 = int.from_bytes(packet[self.cmd_pos : self.cmd_pos + 2], 'little')
135
- cmd_class = CommandFactory.create_command(cmd_code)
136
- instance = cmd_class(self.device)
137
- instance.parse_body(packet[self.header_len:-2])
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):
@@ -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.5.1
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
- # 版本 v0.5.1 (2025-08-04)
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
- # 版本 v0.5.0 (2025-07-29)
32
+ #### ⚙️ Changed
33
+ - C16R通道映射调整为按老的脑电帽位点映射(固件端做了映射)
31
34
 
32
- ## 🚀 新特性
35
+ - 开放底层参数,支持EDF/BDF文件中存储大量事件(>1个/秒)
33
36
 
34
- 1. **C16R设备连接**
37
+ - 优化实时信号数据订阅(发布/订阅模式),在调用者使用不规范时,多个订阅者之间不会互相干扰
38
+
39
+
40
+ ## **v0.5.0** (2025-07-29)
41
+
42
+ #### 🚀 Added
43
+
44
+ - *新增C16R搜索与连接*
35
45
  支持C16R类型设备的搜索与连接
36
46
 
37
- 2. **C16R信号采集/停止控制**
47
+ - *C16R信号采集/停止控制*
38
48
  支持信号采集的参数配置
39
49
  支持信号采集的启动与停止控制
40
50
 
41
- 3. **C16R数据自动记录**
51
+ - *C16R数据自动记录*
42
52
  采集到的信号数据自动保存为bdf文件
43
53
 
44
- 4. **C16R采集通道设置**
54
+ - *C16R采集通道设置*
45
55
  - 支持数字模式通道配置
46
56
  - 支持名称模式通道配置
47
57
  - 支持两种模式混合使用
48
58
 
49
- ## ⚙️ 优化
59
+ #### ⚙️ Changed
50
60
 
51
- 1. **性能提升**
61
+ - *性能提升*
52
62
  - 信号接收效率优化
53
63
  - 指令拆包方式优化
54
64
 
55
- 2. **日志系统改进**
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=1BBbL41zqb0_UsxgoiuyG5zM0CKVzT5VUA_BXSKZmAs,3177
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=KS_pKZcCEFhNGABCOZTOHiVFkfPNZl_0K5RXppwMIvA,3085
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=_pYtHqucB-utMw-xUXZc9IB8_8ThbLFpTl_-WBQR-Sc,10555
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=89Wv7r6u_J4fHlGKsIBAUYD7SOdfqFRxbwV2asvutH8,13315
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=DGfwY36sMdPIMRjbGo661GvUTEwsRRi3jrmG405mSTk,12840
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=2rqWM23fFqvFfgN7K3PLT7rkTyW9mawK4OGCo63hnJg,12292
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=xtTXLT9QFKtb-qS-A8-ewSxJ3zXgImFCX0OoAPw6hHE,185
35
- qlsdk/rsc/device/arskindling.py,sha256=owci6MEGjyWqohEXzPdKj_ESeVIZKgO53StVj6Tmi18,15002
36
- qlsdk/rsc/device/base.py,sha256=osLToxNrb745OzCpgXZU5AH72emMh4OxATeqy4fCxsg,17856
37
- qlsdk/rsc/device/c16_rs.py,sha256=BHQRHOnsTMAKgqSXaAS2RjPIklZQAl2CVfe6i_iX-i4,5928
38
- qlsdk/rsc/device/c256_rs.py,sha256=K1XmLqZpvHTAfCm_dr2VsGxHc67aJQVDV1cI41a1WTI,13955
39
- qlsdk/rsc/device/c64_rs.py,sha256=cZIioIRGgd4Ub0ieho4_XujBNo8AQgJEjXcqgcEkyFQ,13644
40
- qlsdk/rsc/device/c64s1.py,sha256=L7nKmsoMCGj6GMjHYfYkKgkBtrGfP516kQHQ5I1FAUE,13986
41
- qlsdk/rsc/device/device_factory.py,sha256=AL_dtjx6ThcyWTHxGSrLKjEDaCt1Y9gClK4HQ5FGjFI,1315
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=VEV-Ige8tjvASdddP6SPRolTqPuIuHrIZP8wiX-Fhu8,3391
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=DxuFZiprJJbG4pfFbbZPaG8MlBiBRe0S0lJrvc2Iees,251
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=mowoFJNVDSEhqsz-EDzPVDcMRiuu_oakdGLZbJrPvlM,5071
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=4aojzRFInTC3d8K2TYGbnP1Ji5fOFEi31ekghj7ce5k,2977
52
- qlsdk/rsc/parser/__init__.py,sha256=8RgwbKCINu3eTsxVLF9cMoBXJnVrDocOEFP6NGP_atk,34
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=Cqel02BA_AH-deSmzTyUvqecIGoYVBre5UuFlG1eNGA,5728
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.5.1.dist-info/METADATA,sha256=vJ3DPDoa8rM-m9YdziuNsMNlnx5o21C570W8uZ7FtZU,1572
63
- qlsdk2-0.5.1.dist-info/WHEEL,sha256=Z4pYXqR_rTB7OWNDYFOm1qRk0RX6GFP2o8LgvP453Hk,91
64
- qlsdk2-0.5.1.dist-info/top_level.txt,sha256=2CHzn0SY-NIBVyBl07Suh-Eo8oBAQfyNPtqQ_aDatBg,6
65
- qlsdk2-0.5.1.dist-info/RECORD,,
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