qlsdk2 0.3.0a3__py3-none-any.whl → 0.4.0a2__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 ADDED
@@ -0,0 +1,312 @@
1
+ from enum import Enum
2
+ from abc import ABC, abstractmethod
3
+ from loguru import logger
4
+ import struct
5
+
6
+ from qlsdk.core import to_bytes, to_channels
7
+
8
+ class C64Channel(Enum):
9
+ CH0 = 0
10
+ CH1 = 1
11
+ CH2 = 2
12
+ CH3 = 3
13
+ CH4 = 4
14
+ CH5 = 5
15
+ CH6 = 6
16
+ CH7 = 7
17
+ CH8 = 8
18
+ CH9 = 9
19
+ CH10 = 10
20
+ CH11 = 11
21
+ CH12 = 12
22
+ CH13 = 13
23
+ CH14 = 14
24
+ CH15 = 15
25
+
26
+ class WaveForm(Enum):
27
+ DC = 0
28
+ PULSE = 1
29
+ AC = 2
30
+ SQUARE = 3
31
+
32
+ class StimulationChannel(ABC):
33
+ def __init__(self, channel_id: int, wave_form: int, current: float, duration: float, ramp_up: float = None, ramp_down: float = None,):
34
+ self.channel_id = channel_id
35
+ self.wave_form = wave_form
36
+ self.current_max = current
37
+ self.current_min = 0
38
+ self.duration = duration
39
+ self.ramp_up = ramp_up
40
+ self.ramp_down = ramp_down
41
+ self.delay_time = 0
42
+ self.frequency = 0
43
+ self.phase_position = 0
44
+ # 预留值,用作占位
45
+ self.reserved = 0
46
+
47
+ def to_bytes(self):
48
+ result = self.channel_id.to_bytes(1, 'little')
49
+ result += self.wave_form.to_bytes(1, 'little')
50
+ result += int(self.current_max * 1000 ).to_bytes(2, 'little', signed = True)
51
+ result += int(self.current_min * 1000 ).to_bytes(2, 'little', signed = True)
52
+ result += struct.pack('<f', self.frequency)
53
+ result += struct.pack('<f', self.phase_position)
54
+
55
+ result += self._ext_bytes()
56
+
57
+ result += int(self.delay_time).to_bytes(4, 'little')
58
+ result += int(self.ramp_up * 1000).to_bytes(4, 'little')
59
+ result += int((self.duration + self.ramp_up) * 1000).to_bytes(4, 'little')
60
+ result += int(self.ramp_down * 1000).to_bytes(4, 'little')
61
+
62
+ return result
63
+
64
+ def _ext_bytes(self):
65
+ return bytes.fromhex("00000000000000000000000000000000")
66
+
67
+ def to_json(self):
68
+ pass
69
+
70
+ def from_json(self, param):
71
+ pass
72
+
73
+ def __str__(self):
74
+ 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})"
75
+
76
+
77
+
78
+ # 刺激模式-直流
79
+ class DCStimulation(StimulationChannel):
80
+ '''
81
+ channel_id: int, 通道编号,从0开始
82
+ current: float, 电流值,单位为mA
83
+ duration: float, 刺激时间,单位为秒
84
+ ramp_up: float, 上升时间,单位为秒
85
+ ramp_down: float, 下降时间,单位为秒
86
+ '''
87
+ def __init__(self, channel_id: int, current: float, duration: float, ramp_up: float = 0, ramp_down: float = 0):
88
+ super().__init__(channel_id, WaveForm.DC.value, current, duration, ramp_up, ramp_down)
89
+ def to_json(self):
90
+ return {
91
+ "channel_id": self.channel_id,
92
+ "waveform": self.wave_form,
93
+ "current_max": self.current_max,
94
+ "duration": self.duration,
95
+ "ramp_up": self.ramp_up,
96
+ "ramp_down": self.ramp_down,
97
+ "frequency": self.frequency,
98
+ "phase_position": self.phase_position,
99
+ "delay_time": self.delay_time
100
+ }
101
+
102
+ def from_json(self, param):
103
+ pass
104
+ def __str__(self):
105
+ 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})"
106
+
107
+
108
+ # 刺激模式-方波
109
+ class SquareWaveStimulation(StimulationChannel):
110
+ '''
111
+ channel_id: int, 通道编号,从0开始
112
+ current: float, 电流值,单位为mA
113
+ duration: float, 刺激时间,单位为秒
114
+ ramp_up: float, 上升时间,单位为秒
115
+ ramp_down: float, 下降时间,单位为秒
116
+ frequency: float, 频率,单位为Hz
117
+ duty_cycle: float, 占空比,高电平时间/周期,范围(0, 100)
118
+ '''
119
+ def __init__(self, channel_id: int, current: float, duration: float, ramp_up: float = 0, ramp_down: float = 0,
120
+ frequency: float = None, duty_cycle: float = 0.5):
121
+ super().__init__(channel_id, WaveForm.SQUARE.value, current, duration, ramp_up, ramp_down)
122
+ self.frequency = frequency
123
+ self.duty_cycle = duty_cycle
124
+
125
+
126
+ def to_bytes(self):
127
+ # Convert the object to bytes for transmission
128
+ result = self.channel_id.to_bytes(1, 'little')
129
+ result += self.wave_form.to_bytes(1, 'little')
130
+ result += int(self.current_max * 1000 * 1000).to_bytes(4, 'little', signed = True)
131
+ # result += int(self.current_min * 1000).to_bytes(2, 'little')
132
+ result += int(self.frequency).to_bytes(2, 'little')
133
+ result += int(self.reserved).to_bytes(2, 'little')
134
+ result += struct.pack('<f', self.duty_cycle)
135
+
136
+ result += self._ext_bytes()
137
+
138
+ result += int(self.delay_time).to_bytes(4, 'little')
139
+ result += int(self.ramp_up * 1000).to_bytes(4, 'little')
140
+ result += int((self.duration + self.ramp_up) * 1000).to_bytes(4, 'little')
141
+ result += int(self.ramp_down * 1000).to_bytes(4, 'little')
142
+
143
+ return result
144
+
145
+ # 刺激模式-交流
146
+ class ACStimulation(StimulationChannel):
147
+ '''
148
+ channel_id: int, 通道编号,从0开始
149
+ current: float, 电流值,单位为mA
150
+ duration: float, 刺激时间,单位为秒
151
+ ramp_up: float, 上升时间,单位为秒
152
+ ramp_down: float, 下降时间,单位为秒
153
+ frequency: float, 频率,单位为Hz
154
+ phase_position: int, 相位位置,单位为度
155
+ '''
156
+
157
+ def __init__(self, channel_id: int, current: float, duration: float, ramp_up: float = 0, ramp_down: float = 0,
158
+ frequency: float = None, phase_position: int = 0):
159
+ super().__init__(channel_id, WaveForm.AC.value, current, duration, ramp_up, ramp_down)
160
+ self.current_max = abs(current)
161
+ self.current_min = -abs(current)
162
+ self.frequency = frequency
163
+ # self.frequency = frequency
164
+ self.phase_position = phase_position
165
+
166
+ def to_json(self):
167
+ return {
168
+ "channel_id": self.channel_id,
169
+ "waveform": self.wave_form,
170
+ "current_max": self.current_max,
171
+ "duration": self.duration,
172
+ "ramp_up": self.ramp_up,
173
+ "ramp_down": self.ramp_down,
174
+ "frequency": self.frequency,
175
+ "phase_position": self.phase_position
176
+ }
177
+
178
+ def from_json(self, param):
179
+ pass
180
+ def __str__(self):
181
+ 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
+
183
+ # 刺激模式-脉冲
184
+ class PulseStimulation(StimulationChannel):
185
+ '''
186
+ channel_id: int, 通道编号,从0开始
187
+ current: float, 电流值,单位为mA
188
+ duration: float, 刺激时间,单位为秒
189
+ frequency: float, 频率,单位为Hz
190
+ pulse_width: int, 脉冲宽度,单位为ms
191
+ pulse_width_ratio: float, 脉冲宽度比,范围(0, 1)
192
+ ramp_up: float, 上升时间,单位为秒
193
+ ramp_down: float, 下降时间,单位为秒
194
+ delay_time: float, 延迟启动时间,单位为秒(暂未启用)
195
+ '''
196
+ def __init__(self, channel_id: int, current: float, duration: float, frequency: float, pulse_width: int,
197
+ pulse_width_ratio: float = 1, ramp_up: float = 0, ramp_down: float = 0, delay_time = 0):
198
+ super().__init__(channel_id, WaveForm.PULSE.value, current, duration, ramp_up, ramp_down)
199
+ self.frequency = frequency
200
+ self.delay_time = delay_time
201
+ self.pulse_width = pulse_width
202
+ self.pulse_width_ratio = pulse_width_ratio
203
+ self.pulse_interval = 0
204
+ self.with_group_repeats = 1
205
+ self.pulse_time_f = 0
206
+ self.pulse_time_out = 0
207
+ self.pulse_time_idle = 0
208
+
209
+ def to_bytes(self):
210
+ # Convert the object to bytes for transmission
211
+ result = self.channel_id.to_bytes(1, 'little')
212
+ result += self.wave_form.to_bytes(1, 'little')
213
+ result += int(self.current_max * 1000 * 1000).to_bytes(4, 'little', signed = True)
214
+ # result += int(self.current_min * 1000).to_bytes(2, 'little')
215
+ result += int(self.frequency).to_bytes(2, 'little')
216
+ result += int(self.pulse_width).to_bytes(2, 'little')
217
+ result += struct.pack('<f', self.pulse_width_ratio)
218
+
219
+ result += int(self.pulse_interval).to_bytes(2, 'little')
220
+ result += int(self.with_group_repeats).to_bytes(2, 'little')
221
+ result += int(self.pulse_time_f).to_bytes(4, 'little')
222
+ result += int(self.pulse_time_out).to_bytes(4, 'little')
223
+ result += int(self.pulse_time_idle).to_bytes(4, 'little')
224
+
225
+ result += int(self.delay_time).to_bytes(4, 'little')
226
+ result += int(self.ramp_up * 1000).to_bytes(4, 'little')
227
+ result += int((self.duration + self.ramp_up) * 1000).to_bytes(4, 'little')
228
+ result += int(self.ramp_down * 1000).to_bytes(4, 'little')
229
+
230
+ return result
231
+
232
+ def to_json(self):
233
+ return {
234
+ "channel_id": self.channel_id,
235
+ "wave_form": self.wave_form,
236
+ "current_max": self.current_max,
237
+ "current_min": self.current_min,
238
+ "duration": self.duration,
239
+ "ramp_up": self.ramp_up,
240
+ "ramp_down": self.ramp_down,
241
+ "frequency": self.frequency,
242
+ "phase_position": self.phase_position,
243
+ "duration_delay": self.duration_delay,
244
+ "pulse_width": self.pulse_width,
245
+ "delay_time": self.delay_time,
246
+ "pulse_interval": self.pulse_interval,
247
+ "with_group_repeats": self.with_group_repeats
248
+ }
249
+
250
+
251
+ # 刺激范式
252
+ class StimulationParadigm(object):
253
+ def __init__(self):
254
+ self.channels = None
255
+ self.duration = None
256
+ self.interval_time = 0
257
+ self.characteristic = 1
258
+ self.mode = 0
259
+ self.repeats = 0
260
+
261
+ def add_channel(self, channel: StimulationChannel, update=False):
262
+ if self.channels is None:
263
+ self.channels = {}
264
+ channel_id = channel.channel_id + 1
265
+ if channel_id in self.channels.keys():
266
+ logger.warning(f"Channel {channel_id} already exists")
267
+ if update:
268
+ self.channels[channel_id] = channel
269
+ else:
270
+ self.channels[channel_id] = channel
271
+
272
+ # 计算刺激时间
273
+ duration = channel.duration + channel.ramp_up + channel.ramp_down
274
+ if self.duration is None or duration > self.duration:
275
+ self.duration = duration
276
+
277
+
278
+ def to_bytes(self):
279
+ result = to_bytes(list(self.channels.keys()), 64)
280
+ result += int(self.duration * 1000).to_bytes(4, 'little')
281
+ result += int(self.interval_time).to_bytes(4, 'little')
282
+ result += int(self.characteristic).to_bytes(4, 'little')
283
+ result += int(self.mode).to_bytes(1, 'little')
284
+ result += int(self.repeats).to_bytes(4, 'little')
285
+ for channel in self.channels.values():
286
+ result += channel.to_bytes()
287
+ return result
288
+
289
+ def to_json(self):
290
+ # Convert the object to JSON for transmission
291
+ return {
292
+ "channels": list(self.channels.keys()),
293
+ "duration": self.duration,
294
+ "interval_time": self.interval_time,
295
+ "characteristic": self.characteristic,
296
+ "mode": self.mode,
297
+ "repeats": self.repeats,
298
+ "stim": [channel.to_json() for channel in self.channels.values()]
299
+ }
300
+
301
+ # @staticmethod
302
+ # def from_json(param: Dict[str, Any]):
303
+ # pass
304
+
305
+ def clear(self):
306
+ self.channels = None
307
+ self.duration = None
308
+ self.interval_time = 0
309
+ self.characteristic = 1
310
+ self.mode = 0
311
+ self.repeats = 0
312
+
qlsdk/rsc/proxy.py ADDED
@@ -0,0 +1,76 @@
1
+ from loguru import logger
2
+ from threading import Thread, Lock
3
+ import socket
4
+
5
+ class DeviceProxy(object):
6
+ def __init__(self, client_socket):
7
+ self.client_socket = client_socket
8
+ self.server_socket = None
9
+ # 客户端设备
10
+ # self.device = QLDevice(client_socket)
11
+ # self.parser = DeviceParser(self.device)
12
+
13
+ self._init_server()
14
+
15
+ def _init_server(self):
16
+ # 连接目标服务(桌面端运行在本地的18125端口)
17
+ self.server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
18
+ self.server_socket.connect(('localhost', 18125))
19
+
20
+ def start(self):
21
+ logger.info("DeviceProxy连接已建立")
22
+
23
+ try:
24
+ # 创建双向转发线程
25
+ client_thread = Thread(
26
+ target=self.data_forward,
27
+ args=(self.client_socket, self.server_socket, "设备->软件")
28
+ )
29
+ server_thread = Thread(
30
+ target=self.data_forward,
31
+ args=(self.server_socket, self.client_socket, "软件->设备")
32
+ )
33
+
34
+ # 启动线程
35
+ client_thread.start()
36
+ server_thread.start()
37
+
38
+ # 等待线程结束
39
+ client_thread.join()
40
+ server_thread.join()
41
+
42
+ except Exception as e:
43
+ logger.error(f"连接异常: {str(e)}")
44
+ self.client_socket.close()
45
+ finally:
46
+ logger.error(f"连接已结束")
47
+ self.client_socket.close()
48
+
49
+ def data_forward(self, src, dest, direction, callback=None):
50
+ """
51
+ 数据转发函数
52
+ :param src: 源socket连接
53
+ :param dest: 目标socket连接
54
+ :param direction: 转发方向描述
55
+ """
56
+ try:
57
+ logger.debug(f"[{direction}] 转发开始")
58
+ while True:
59
+ data = src.recv(4096*1024) # 接收数据缓冲区设为4KB
60
+ if not data:
61
+ break
62
+ logger.info(f"[{direction}] 转发指令: {hex(int.from_bytes(data[12:14], 'little'))} ")
63
+ logger.debug(f"[{direction}] 转发 {data.hex()} ")
64
+ if callback:
65
+ callback(data)
66
+ dest.sendall(data)
67
+ logger.debug(f"[{direction}] 转发 {len(data)} 字节")
68
+ except ConnectionResetError:
69
+ logger.error(f"[{direction}] 连接已关闭")
70
+ finally:
71
+ src.close()
72
+ dest.close()
73
+
74
+ # def device_message(self, data):
75
+ # # 解析数据包
76
+ # self.parser.append(data)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: qlsdk2
3
- Version: 0.3.0a3
3
+ Version: 0.4.0a2
4
4
  Summary: SDK for quanlan device
5
5
  Home-page: https://github.com/hehuajun/qlsdk
6
6
  Author: hehuajun
@@ -0,0 +1,40 @@
1
+ qlsdk/__init__.py,sha256=mjjFQ8LEHgwMmud5ie2Tgl2aOafnz53gkcAju0q7T0c,446
2
+ qlsdk/ar4/__init__.py,sha256=iR0bFanDwqSxSEM1nCcge1l-GSIWjwnMeRQa47wGrds,4752
3
+ qlsdk/ar4m/__init__.py,sha256=Z13X53WKmKp6MW_fA1FUPdQgJxhxxuyzemJWPS_CEHA,639
4
+ qlsdk/core/__init__.py,sha256=nFXRJIMxV8nnHIn0doWey0pDZvfmhMu8J4ECMfzAZgc,126
5
+ qlsdk/core/device.py,sha256=dPoQUwd78-Ieef6ZcBI7isVm0W8aYarqBy6UHP7Yjoc,587
6
+ qlsdk/core/exception.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
+ qlsdk/core/local.py,sha256=vbison4XZtS4SNYLJ9CqBhetEcukdviTWmvtdA1efkQ,811
8
+ qlsdk/core/utils.py,sha256=eAg6oa8lGoVdaPcUAR128J1-Nwf_ghDPehUVtbw_WCc,4036
9
+ qlsdk/core/crc/__init__.py,sha256=kaYSr6KN5g4U49xlxAvT2lnEeGtwX4Dz1ArwKDvUIIY,143
10
+ qlsdk/core/crc/crctools.py,sha256=sDeE6CMccQX2cRAyMQK0SZUk1fa50XMuwqXau5UX5C8,4242
11
+ qlsdk/core/entity/__init__.py,sha256=xEROyxn-KX1aa1XomOmYgwfeYOx52ZXDAs0SftAEOD8,3289
12
+ qlsdk/core/filter/__init__.py,sha256=YIWIzDUKN30mq2JTr53ZGblggZfC_rLUp2FSRrsQFgU,36
13
+ qlsdk/core/filter/norch.py,sha256=5RdIBX5eqs5w5nmVAnCB3ESSuAT_vVBZ2g-dg6HMZdY,1858
14
+ qlsdk/core/message/__init__.py,sha256=sHuavOyHf4bhH6VdDpTA1EsCh7Q-XsPHcFiItpVz3Rs,51
15
+ qlsdk/core/message/command.py,sha256=wk5DAsvlAtUikGZ4a8honRZf-iQQaIypjzud8GpnHtU,11311
16
+ qlsdk/core/message/tcp.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
17
+ qlsdk/core/message/udp.py,sha256=KS_pKZcCEFhNGABCOZTOHiVFkfPNZl_0K5RXppwMIvA,3085
18
+ qlsdk/persist/__init__.py,sha256=OR8mnPTsktxw67G-z0VsPWJXInkKircMTHQdibmmz3M,63
19
+ qlsdk/persist/edf.py,sha256=usgFjZJVcfAUwSy6cJtRdgjdqMgOS4viLCDGcwAGMZE,7106
20
+ qlsdk/persist/rsc_edf.py,sha256=DM871w2-2vXNSEIzNnMLzW_ftCZSM8NhPSmu56h5jz4,8692
21
+ qlsdk/rsc/__init__.py,sha256=bR678DilIIK7tFP65tscPUI7Bp4VN0ndVQWt6bnQKGg,197
22
+ qlsdk/rsc/device_manager.py,sha256=KeCJX97OCjTNa5J2S-1swxaRXf1DcznH9F5e4pVvNuo,4289
23
+ qlsdk/rsc/discover.py,sha256=ONXN6YWY-OMU0sBoLqqKUyb-8drtAp1g_MvnpzaFvHQ,3124
24
+ qlsdk/rsc/eegion.py,sha256=lxrktO-3Z_MYdFIwc4NxvgLM5AL5kU3UItjH6tsKmHY,11670
25
+ qlsdk/rsc/entity.py,sha256=WN05GviA_FjLkQUM5W9t2UVnDcHNR06dqMUzKxyXFuU,21023
26
+ qlsdk/rsc/paradigm.py,sha256=zK_YFI4320lRa7GBXJfIQklhzJQSP823TeaXcMJngj4,12746
27
+ qlsdk/rsc/proxy.py,sha256=9CPdGNGWremwBUh4GvlXAykYB-x_BEPPLqsNvwuwIDE,2736
28
+ qlsdk/rsc/command/__init__.py,sha256=D5pBE2leqFG-IPU2pDAGuLsqHmc0wRPrBOXR0-K8d6k,8117
29
+ qlsdk/rsc/command/message.py,sha256=bcuUDJj0CMekcZMNhKrzIpkHtDC-QBCs3dJG6Bx_PHc,8723
30
+ qlsdk/sdk/__init__.py,sha256=v9LKP-5qXCqnAsCkiRE9LDb5Tagvl_Qd_fqrw7y9yd4,68
31
+ qlsdk/sdk/ar4sdk.py,sha256=ZILuUVgUZN7-LNQm4xdItxmZWGwvFt4oWUKGez1BCLI,27101
32
+ qlsdk/sdk/hub.py,sha256=uEOGZBZtMDCWlV8G2TZe6FAo6eTPcwHAW8zdqr1eq_0,1571
33
+ qlsdk/sdk/libs/libAr4SDK.dll,sha256=kZp9_DRwPdAJ5OgTFQSqS8tEETxUs7YmmETuBP2g60U,15402132
34
+ qlsdk/sdk/libs/libwinpthread-1.dll,sha256=W77ySaDQDi0yxpnQu-ifcU6-uHKzmQpcvsyx2J9j5eg,52224
35
+ qlsdk/x8/__init__.py,sha256=XlQn3Af_HA7bGrxhv3RZKWMob_SnmissXiso7OH1UgI,4750
36
+ qlsdk/x8m/__init__.py,sha256=cLeUqEEj65qXw4Qa4REyxoLh6T24anSqPaKe9_lR340,634
37
+ qlsdk2-0.4.0a2.dist-info/METADATA,sha256=B3h3rXNFoF04Meat9Cq1aokL0QghKnyWF7-0xR5ykyY,7066
38
+ qlsdk2-0.4.0a2.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
39
+ qlsdk2-0.4.0a2.dist-info/top_level.txt,sha256=2CHzn0SY-NIBVyBl07Suh-Eo8oBAQfyNPtqQ_aDatBg,6
40
+ qlsdk2-0.4.0a2.dist-info/RECORD,,
@@ -1,16 +0,0 @@
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/persist/__init__.py,sha256=UYaNL_RSczIZL_YrBWAifoAnNxpgZHEeSp-goHqyqv4,27
5
- qlsdk/persist/edf.py,sha256=usgFjZJVcfAUwSy6cJtRdgjdqMgOS4viLCDGcwAGMZE,7106
6
- qlsdk/sdk/__init__.py,sha256=v9LKP-5qXCqnAsCkiRE9LDb5Tagvl_Qd_fqrw7y9yd4,68
7
- qlsdk/sdk/ar4sdk.py,sha256=ZILuUVgUZN7-LNQm4xdItxmZWGwvFt4oWUKGez1BCLI,27101
8
- qlsdk/sdk/hub.py,sha256=uEOGZBZtMDCWlV8G2TZe6FAo6eTPcwHAW8zdqr1eq_0,1571
9
- qlsdk/sdk/libs/libAr4SDK.dll,sha256=kZp9_DRwPdAJ5OgTFQSqS8tEETxUs7YmmETuBP2g60U,15402132
10
- qlsdk/sdk/libs/libwinpthread-1.dll,sha256=W77ySaDQDi0yxpnQu-ifcU6-uHKzmQpcvsyx2J9j5eg,52224
11
- qlsdk/x8/__init__.py,sha256=XlQn3Af_HA7bGrxhv3RZKWMob_SnmissXiso7OH1UgI,4750
12
- qlsdk/x8m/__init__.py,sha256=cLeUqEEj65qXw4Qa4REyxoLh6T24anSqPaKe9_lR340,634
13
- qlsdk2-0.3.0a3.dist-info/METADATA,sha256=FE9C1YckDtBRsYXY6VInPhcf_WT5X1D-t_FO7WL-MUc,7066
14
- qlsdk2-0.3.0a3.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
15
- qlsdk2-0.3.0a3.dist-info/top_level.txt,sha256=2CHzn0SY-NIBVyBl07Suh-Eo8oBAQfyNPtqQ_aDatBg,6
16
- qlsdk2-0.3.0a3.dist-info/RECORD,,