smartpi 0.1.13__py3-none-any.whl → 0.1.14__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.
smartpi/__init__.py CHANGED
@@ -1,4 +1,4 @@
1
1
  __all__ = ["base_driver"]
2
2
 
3
- __version__ = "0.1.13"
3
+ __version__ = "0.1.14"
4
4
 
smartpi/base_driver.py CHANGED
@@ -1,9 +1,11 @@
1
1
  # coding=utf-8
2
- import serial,time,struct
2
+ import serial,time,struct,threading
3
3
  from typing import List, Optional
4
4
  from collections import deque
5
5
  from . import servo,motor,cw2015,gui
6
6
 
7
+ # 创建全局线程锁
8
+ serial_lock = threading.RLock()
7
9
 
8
10
  # 命令常量
9
11
  BOOT_UPDATE_H = 0XFF
@@ -66,10 +68,16 @@ ser = serial.Serial(
66
68
  stopbits=serial.STOPBITS_ONE, # 1位停止位
67
69
  timeout=TIMEOUT,
68
70
  xonxoff=False, # 关闭软件流控
69
- rtscts=False, # 关闭硬件流控
70
-
71
+ rtscts=False, # 关闭硬件流控
71
72
  )
72
73
 
74
+ def is_lock_locked(lock):
75
+ """检查锁是否被占用"""
76
+ acquired = serial_lock.acquire(blocking=True)
77
+ if acquired:
78
+ serial_lock.release()
79
+ return False
80
+ return True
73
81
 
74
82
  def uart3_init() -> Optional[serial.Serial]:
75
83
  """初始化串口"""
@@ -94,20 +102,21 @@ def calculate_pro_check(command_h: int, command_l: int, data: List[bytes] = None
94
102
 
95
103
  return base_sum % 256 # 确保结果为单字节(原C代码未取模,需根据实际协议调整)
96
104
 
97
- def write_data(command_h: int, command_l: int, send_data: bytes= None) -> Optional[bytes]:
98
- buffer = bytearray()
99
- HEADER = bytes.fromhex('86 AB') # 帧头
100
- FOOTER = bytes.fromhex('CF') # 帧尾
101
- MIN_FRAME_LEN = 9 # 最小帧长度
102
- if send_data:
103
- pro_check = calculate_pro_check(command_h, command_l, list(send_data))
104
- send_packet = [0x86, 0xAB, (0x09+len(send_data))//256, (0x09+len(send_data))%256, command_h, command_l, *send_data, 0x01, pro_check, 0xCF]
105
- else:
106
- pro_check = calculate_pro_check(command_h, command_l)
107
- send_packet = [0x86, 0xAB, 0x00, 0x09, command_h, command_l, 0x01, pro_check, 0xCF]
108
- send_bytes = bytes(send_packet)
109
-
110
- ser.write(send_bytes)
105
+ def write_data(command_h: int, command_l: int, send_data: bytes= None) -> Optional[bytes]:
106
+ #with serial_lock:
107
+ buffer = bytearray()
108
+ HEADER = bytes.fromhex('86 AB') # 帧头
109
+ FOOTER = bytes.fromhex('CF') # 帧尾
110
+ MIN_FRAME_LEN = 9 # 最小帧长度
111
+ if send_data:
112
+ pro_check = calculate_pro_check(command_h, command_l, list(send_data))
113
+ send_packet = [0x86, 0xAB, (0x09+len(send_data))//256, (0x09+len(send_data))%256, command_h, command_l, *send_data, 0x01, pro_check, 0xCF]
114
+ else:
115
+ pro_check = calculate_pro_check(command_h, command_l)
116
+ send_packet = [0x86, 0xAB, 0x00, 0x09, command_h, command_l, 0x01, pro_check, 0xCF]
117
+ send_bytes = bytes(send_packet)
118
+
119
+ ser.write(send_bytes)
111
120
 
112
121
 
113
122
  def check_frame(frame: bytes) -> bool:
@@ -122,85 +131,65 @@ def check_frame(frame: bytes) -> bool:
122
131
  return calculated_checksum == frame_checksum
123
132
 
124
133
  def process_received_data():
125
- global buffer
126
- # 读取所有可用数据
127
- data = ser.read(ser.in_waiting or 1)
128
- if data:
129
- buffer.extend(data)
130
- while len(buffer)>=2:
131
- # for x in buffer:
132
- # print(f"{x:02X}", end=' ')
133
- # print("\n")
134
- # 1. 查找帧头
135
- start_idx = buffer.find(HEADER)
136
- if start_idx == -1:
137
- # 没有找到帧头,清空无效数据(保留最后可能的部分帧头)
138
- #print("Header no found")
139
- if len(buffer) > len(HEADER) - 1:
140
- buffer = buffer[-len(HEADER) + 1:]
141
- return
142
- # 2. 检查帧头后的长度字段是否足够
143
- if start_idx + 4 > len(buffer):
144
- # 长度字段不完整,等待更多数据
145
- return
146
- # 3. 解析帧长度
147
- frame_length = (buffer[start_idx + 2] << 8) + buffer[start_idx + 3]
148
- # 4. 检查完整帧是否已到达
149
- end_idx = start_idx + frame_length - 1
150
- if end_idx >= len(buffer):
151
- # 完整帧尚未完全到达
152
- return
153
- # 5. 检查帧尾
154
- if buffer[end_idx] != ord(FOOTER):
155
- # 跳过当前帧头,继续查找
156
- print("End no found")
157
- buffer = buffer[start_idx + 1:]
158
- continue
159
- # 6. 提取完整帧
160
- frame = buffer[start_idx:end_idx + 1]
161
- frames_queue.append(frame)
162
- # 7. 从缓冲区移除已处理帧
163
- buffer = buffer[end_idx + 1:]
164
- # 处理所有完整帧
165
- if len(frames_queue) > 0:
166
- frame = frames_queue.popleft()
167
- if check_frame(frame):
168
- return frame
169
- else:
170
- print("Check byte error")
134
+ #with serial_lock:
135
+ global buffer
136
+ # 读取所有可用数据
137
+ data = ser.read(ser.in_waiting or 1)
138
+ if data:
139
+ buffer.extend(data)
140
+ while len(buffer)>=2:
141
+ # for x in buffer:
142
+ # print(f"{x:02X}", end=' ')
143
+ # print("\n")
144
+ # 1. 查找帧头
145
+ start_idx = buffer.find(HEADER)
146
+ if start_idx == -1:
147
+ # 没有找到帧头,清空无效数据(保留最后可能的部分帧头)
148
+ #print("Header no found")
149
+ if len(buffer) > len(HEADER) - 1:
150
+ buffer = buffer[-len(HEADER) + 1:]
151
+ return
152
+ # 2. 检查帧头后的长度字段是否足够
153
+ if start_idx + 4 > len(buffer):
154
+ # 长度字段不完整,等待更多数据
155
+ return
156
+ # 3. 解析帧长度
157
+ frame_length = (buffer[start_idx + 2] << 8) + buffer[start_idx + 3]
158
+ # 4. 检查完整帧是否已到达
159
+ end_idx = start_idx + frame_length - 1
160
+ if end_idx >= len(buffer):
161
+ # 完整帧尚未完全到达
162
+ return
163
+ # 5. 检查帧尾
164
+ if buffer[end_idx] != ord(FOOTER):
165
+ # 跳过当前帧头,继续查找
166
+ print("End no found")
167
+ buffer = buffer[start_idx + 1:]
168
+ continue
169
+ # 6. 提取完整帧
170
+ frame = buffer[start_idx:end_idx + 1]
171
+ frames_queue.append(frame)
172
+ # 7. 从缓冲区移除已处理帧
173
+ buffer = buffer[end_idx + 1:]
174
+ # 处理所有完整帧
175
+ if len(frames_queue) > 0:
176
+ frame = frames_queue.popleft()
177
+ if check_frame(frame):
178
+ return frame
179
+ else:
180
+ print("Check byte error")
171
181
 
172
182
  # 功能函数类
173
183
  ##############################################################################读取设备信息
174
- """固件升级模式"""
175
- def boot_update() -> None:
176
- write_data(BOOT_UPDATE_H, BOOT_UPDATE_L)
177
- while True:
178
- response =process_received_data()
179
- if response:
180
- display_data = response[6:-3]
181
- if display_data[0]==0X03:
182
- print("固件更新启动\n")
183
- elif display_data[0]==0X01:
184
- print("擦除中......",f"{10*display_data[1]}","%\n")
185
- elif display_data[0]==0X02:
186
- print("升级中......",f"{10*display_data[1]}","%\n")
187
- elif display_data[0]==0X05:
188
- print("更新成功!\n")
189
- elif display_data[0]==0X06:
190
- print("更新失败!\n")
191
- else:
192
- for x in display_data:
193
- print(f"{x:02X}", end=' ')
194
- print("\n")
195
-
196
-
197
184
  """读取设备型号"""
198
185
  def read_device_model() -> Optional[bytes]:
186
+ serial_lock.acquire() #获取线程锁
199
187
  write_data(READ_MODEL_H, READ_MODEL_L)
200
188
  start_time = time.time()
201
189
  while True:
202
190
  response =process_received_data()
203
191
  if response:
192
+ serial_lock.release() #释放线程锁
204
193
  display_data = response[6:-3].decode(errors="ignore")
205
194
  # print(f"设备型号: {display_data}")
206
195
  return display_data
@@ -208,15 +197,18 @@ def read_device_model() -> Optional[bytes]:
208
197
  if time.time() - start_time > 3:
209
198
  print("读取超时")
210
199
  buffer.clear()
200
+ serial_lock.release() #释放线程锁
211
201
  return None
212
202
 
213
203
  """读取版本号"""
214
204
  def read_version() -> Optional[bytes]:
205
+ serial_lock.acquire() #获取线程锁
215
206
  write_data(READ_VERSION_H, READ_VERSION_L)
216
207
  start_time = time.time()
217
208
  while True:
218
209
  response =process_received_data()
219
210
  if response:
211
+ serial_lock.release() #释放线程锁
220
212
  display_data = response[6:-3].decode(errors="ignore")
221
213
  # print(f"版本号: {display_data}")
222
214
  return display_data
@@ -224,15 +216,18 @@ def read_version() -> Optional[bytes]:
224
216
  if time.time() - start_time > 3:
225
217
  print("读取超时")
226
218
  buffer.clear()
219
+ serial_lock.release() #释放线程锁
227
220
  return None
228
221
 
229
222
  """读取工厂信息"""
230
223
  def read_factory_data() -> Optional[bytes]:
224
+ serial_lock.acquire() #获取线程锁
231
225
  write_data(READ_FACTORY_H, READ_FACTORY_L)
232
226
  start_time = time.time()
233
227
  while True:
234
228
  response =process_received_data()
235
229
  if response:
230
+ serial_lock.release() #释放线程锁
236
231
  display_data = response[6:-3].decode(errors="ignore")
237
232
  # print(f"厂家信息: {display_data}")
238
233
  return display_data
@@ -240,15 +235,18 @@ def read_factory_data() -> Optional[bytes]:
240
235
  if time.time() - start_time > 3:
241
236
  print("读取超时")
242
237
  buffer.clear()
238
+ serial_lock.release() #释放线程锁
243
239
  return None
244
240
 
245
241
  """读取硬件ID"""
246
242
  def read_hardware_ID() -> Optional[bytes]:
243
+ serial_lock.acquire() #获取线程锁
247
244
  write_data(READ_HW_ID_H, READ_HW_ID_L)
248
245
  start_time = time.time()
249
246
  while True:
250
247
  response =process_received_data()
251
248
  if response:
249
+ serial_lock.release() #释放线程锁
252
250
  display_data = response[6:-3].decode(errors="ignore")
253
251
  # print(f"硬件ID: {display_data}")
254
252
  return display_data
@@ -256,15 +254,18 @@ def read_hardware_ID() -> Optional[bytes]:
256
254
  if time.time() - start_time > 3:
257
255
  print("读取超时")
258
256
  buffer.clear()
257
+ serial_lock.release() #释放线程锁
259
258
  return None
260
259
 
261
260
  """读取设备名称"""
262
- def read_device_name() -> Optional[bytes]:
261
+ def read_device_name() -> Optional[bytes]:
262
+ serial_lock.acquire() #获取线程锁
263
263
  write_data(READ_NAME_H, READ_NAME_L)
264
264
  start_time = time.time()
265
265
  while True:
266
266
  response =process_received_data()
267
267
  if response:
268
+ serial_lock.release() #释放线程锁
268
269
  display_data = response[6:-3].decode(errors="ignore")
269
270
  # print(f"设备名称: {display_data}")
270
271
  return display_data
@@ -272,16 +273,19 @@ def read_device_name() -> Optional[bytes]:
272
273
  if time.time() - start_time > 3:
273
274
  print("读取超时")
274
275
  buffer.clear()
276
+ serial_lock.release() #释放线程锁
275
277
  return None
276
278
 
277
279
  """设置设备名称"""
278
280
  def write_device_name(send_data: str) -> Optional[bytes]:
281
+ serial_lock.acquire() #获取线程锁
279
282
  data_bytes = send_data.encode('utf-8')
280
283
  write_data(WRITE_NAME_H, WRITE_NAME_L, data_bytes)
281
284
  start_time = time.time()
282
285
  while True:
283
286
  response =process_received_data()
284
287
  if response:
288
+ serial_lock.release() #释放线程锁
285
289
  display_data = response[6:-3].decode(errors="ignore")
286
290
  # print(f"设置状态: {display_data}")
287
291
  return 0
@@ -289,22 +293,26 @@ def write_device_name(send_data: str) -> Optional[bytes]:
289
293
  if time.time() - start_time > 3:
290
294
  print("读取超时")
291
295
  buffer.clear()
296
+ serial_lock.release() #释放线程锁
292
297
  return None
293
298
 
294
299
  """读取连接方式"""
295
300
  def read_connected() -> Optional[bytes]:
301
+ serial_lock.acquire() #获取线程锁
296
302
  write_data(READ_CONNECT_H, READ_CONNECT_L)
297
303
  start_time = time.time()
298
304
  while True:
299
305
  response =process_received_data()
300
306
  if response:
307
+ serial_lock.release() #释放线程锁
301
308
  display_data = response[6:-3].decode(errors="ignore")
302
309
  # print(f"连接方式: {display_data}")
303
310
  return display_data
304
311
  else:
305
312
  if time.time() - start_time > 3:
306
313
  print("读取超时")
307
- buffer.clear()
314
+ buffer.clear()
315
+ serial_lock.release() #释放线程锁
308
316
  return None
309
317
 
310
318
  """读取电池电量百分比"""
@@ -317,39 +325,39 @@ def read_battery() -> Optional[bytes]:
317
325
 
318
326
  ###############################################################################固件升级
319
327
 
320
- """下载更新请求"""
321
- def update_request() -> Optional[bytes]:
322
- write_data(UPDATE_REQUEST_H, UPDATE_REQUEST_L)
323
- start_time = time.time()
324
- while True:
325
- response =process_received_data()
326
- if response:
327
- display_data = response[6:-3].decode(errors="ignore")
328
- print(f"从机响应: {display_data}")
329
- return display_data
330
- else:
331
- if time.time() - start_time > 3:
332
- print("读取超时")
333
- buffer.clear()
334
- return None
335
-
336
- """查询最大通讯长度"""
337
- def read_max_com_len() -> Optional[bytes]:
338
- write_data(MAX_COM_LEN_H, MAX_COM_LEN_L)
339
- start_time = time.time()
340
- while True:
341
- response =process_received_data()
342
- if response:
343
- display_data = response[6:-3].decode(errors="ignore")
344
- print(f"从机响应: {display_data}")
345
- return display_data
346
- else:
347
- if time.time() - start_time > 3:
348
- print("读取超时")
349
- buffer.clear()
350
- return None
351
-
352
- """下载文件的信息"""
328
+ #"""下载更新请求"""
329
+ #def update_request() -> Optional[bytes]:
330
+ # write_data(UPDATE_REQUEST_H, UPDATE_REQUEST_L)
331
+ # start_time = time.time()
332
+ # while True:
333
+ # response =process_received_data()
334
+ # if response:
335
+ # display_data = response[6:-3].decode(errors="ignore")
336
+ # print(f"从机响应: {display_data}")
337
+ # return display_data
338
+ # else:
339
+ # if time.time() - start_time > 3:
340
+ # print("读取超时")
341
+ # buffer.clear()
342
+ # return None
343
+ #
344
+ #"""查询最大通讯长度"""
345
+ #def read_max_com_len() -> Optional[bytes]:
346
+ # write_data(MAX_COM_LEN_H, MAX_COM_LEN_L)
347
+ # start_time = time.time()
348
+ # while True:
349
+ # response =process_received_data()
350
+ # if response:
351
+ # display_data = response[6:-3].decode(errors="ignore")
352
+ # print(f"从机响应: {display_data}")
353
+ # return display_data
354
+ # else:
355
+ # if time.time() - start_time > 3:
356
+ # print("读取超时")
357
+ # buffer.clear()
358
+ # return None
359
+ #
360
+ #"""下载文件的信息"""
353
361
  #def download_massage() -> Optional[bytes]:
354
362
  # write_data(DL_MESSAGE_H, DL_MESSAGE_L, file_data)#文件信息来源从哪获取?
355
363
  # start_time = time.time()
@@ -416,12 +424,14 @@ def read_max_com_len() -> Optional[bytes]:
416
424
  ###############################################################################读取传感器信息
417
425
 
418
426
  """读取外设连接情况"""
419
- def read_peripheral() -> Optional[bytes]:
427
+ def read_peripheral() -> Optional[bytes]:
428
+ serial_lock.acquire() #获取线程锁
420
429
  write_data(READ_PERIPH_H, READ_PERIPH_L)
421
430
  start_time = time.time()
422
431
  while True:
423
432
  response =process_received_data()
424
433
  if response:
434
+ serial_lock.release() #释放线程锁
425
435
  display_data = response[6:-3]
426
436
  # for x in display_data:
427
437
  # print(f"{x:02X}", end=' ')
@@ -431,24 +441,28 @@ def read_peripheral() -> Optional[bytes]:
431
441
  if time.time() - start_time > 3:
432
442
  print("读取超时")
433
443
  buffer.clear()
444
+ serial_lock.release() #释放线程锁
434
445
  return None
435
446
 
436
447
  """单次操作外设"""
437
- def single_operate_sensor(op_struct: bytes) -> Optional[bytes]:
448
+ def single_operate_sensor(op_struct: bytes) -> Optional[bytes]:
449
+ serial_lock.acquire() #获取线程锁
438
450
  write_data(SINGLE_OP_H, SINGLE_OP_L, op_struct)
439
451
  start_time = time.time()
440
452
  while True:
441
453
  response =process_received_data()
442
454
  if response:
455
+ serial_lock.release() #释放线程锁
443
456
  display_data = response[6:-3]
444
457
  # for x in display_data:
445
458
  # print(f"{x:02X}", end=' ')
446
459
  # print("\n")
447
460
  return display_data
448
461
  else:
449
- if time.time() - start_time > 3:
462
+ if time.time() - start_time > 2:
450
463
  print("读取超时")
451
464
  buffer.clear()
465
+ serial_lock.release() #释放线程锁
452
466
  return None
453
467
 
454
468
  #P端口初始化释放
@@ -462,12 +476,14 @@ def P_port_init(port:bytes) -> Optional[bytes]:
462
476
  return None
463
477
 
464
478
  """从机模式转换"""
465
- def mode_change(send_data: str) -> Optional[bytes]:
479
+ def mode_change(send_data: str) -> Optional[bytes]:
480
+ serial_lock.acquire() #获取线程锁
466
481
  write_data(MODE_CHANGE_H, MODE_CHANGE_L, send_data)
467
482
  start_time = time.time()
468
483
  while True:
469
484
  response =process_received_data()
470
485
  if response:
486
+ serial_lock.release() #释放线程锁
471
487
  display_data = response[6:-3]
472
488
  for x in display_data:
473
489
  print(f"{x:02X}", end=' ')
@@ -477,15 +493,18 @@ def mode_change(send_data: str) -> Optional[bytes]:
477
493
  if time.time() - start_time > 3:
478
494
  print("读取超时")
479
495
  buffer.clear()
496
+ serial_lock.release() #释放线程锁
480
497
  return None
481
498
 
482
499
  """智能模式发送周期"""
483
- def mode_change(send_data: str) -> Optional[bytes]:
500
+ def mode_change(send_data: str) -> Optional[bytes]:
501
+ serial_lock.acquire() #获取线程锁
484
502
  write_data(SEND_CYCLE_H, SEND_CYCLE_L, send_data)
485
503
  start_time = time.time()
486
504
  while True:
487
505
  response =process_received_data()
488
506
  if response:
507
+ serial_lock.release() #释放线程锁
489
508
  display_data = response[6:-3]
490
509
  for x in display_data:
491
510
  print(f"{x:02X}", end=' ')
@@ -494,11 +513,17 @@ def mode_change(send_data: str) -> Optional[bytes]:
494
513
  else:
495
514
  if time.time() - start_time > 3:
496
515
  print("读取超时")
497
- buffer.clear()
516
+ buffer.clear()
517
+ serial_lock.release() #释放线程锁
498
518
  return None
499
519
 
500
520
  """H2-RCU初始化"""
501
521
  def smartpi_init():
522
+
523
+ if is_lock_locked(serial_lock):
524
+ serial_lock.release()
525
+
526
+ serial_lock.acquire()
502
527
  uart3_init()
503
528
  P_port_init(1)
504
529
  P_port_init(2)
@@ -531,6 +556,7 @@ def smartpi_init():
531
556
  motor.reset_motor_encoder(5)
532
557
  motor.reset_motor_encoder(6)
533
558
  time.sleep(0.1)
534
- gui.init()
559
+ gui.init()
560
+ serial_lock.release()
535
561
  time.sleep(0.1)
536
562
 
smartpi/gui.py CHANGED
@@ -1,97 +1,28 @@
1
1
  import socket
2
2
  import json
3
3
  import sys
4
- import threading
5
- import queue
6
- import atexit
7
4
 
8
5
  # 连接对象(模块级单例)
9
6
  _connection = None
10
- # 命令队列
11
- _command_queue = queue.Queue(maxsize=1000)
12
- # 后台发送线程
13
- _sender_thread = None
14
- # 线程停止标志
15
- _stop_event = threading.Event()
16
7
 
17
8
  def init(host="127.0.0.1", port=65167):
18
9
  """初始化GUI连接"""
19
- global _connection, _sender_thread, _stop_event
20
- if _connection is None:
21
- try:
22
- _connection = socket.create_connection((host, port))
23
- _connection.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
24
- except ConnectionRefusedError:
25
- print(f"无法连接到GUI服务器 {host}:{port}", file=sys.stderr)
26
- return
27
-
28
- # 启动后台发送线程
29
- _stop_event.clear()
30
- _sender_thread = threading.Thread(target=_send_worker, daemon=True)
31
- _sender_thread.start()
32
- _send({"type": "clear"})
33
-
34
- def _send_worker():
35
- """后台发送线程的工作函数"""
36
- while not _stop_event.is_set():
37
- try:
38
- # 从队列中获取命令,最多等待0.01秒
39
- cmd = _command_queue.get(timeout=0.01)
40
-
41
- if _connection:
42
- data = json.dumps(cmd) + "\n"
43
- _connection.sendall(data.encode())
44
-
45
- # 标记任务完成
46
- _command_queue.task_done()
47
- except queue.Empty:
48
- continue
49
- except (BrokenPipeError, ConnectionResetError):
50
- # 连接断开,尝试重新连接
51
- _reconnect()
52
- except Exception as e:
53
- print(f"发送错误: {e}", file=sys.stderr)
54
- time.sleep(0.1)
55
-
56
- def _reconnect():
57
- """尝试重新连接服务器"""
58
10
  global _connection
59
- if _connection:
60
- try:
61
- _connection.close()
62
- except:
63
- pass
64
- _connection = None
65
-
66
- # 尝试重新连接
67
- try:
68
- _connection = socket.create_connection(("127.0.0.1", 65167))
69
- _connection.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
11
+ if _connection is None:
12
+ _connection = socket.create_connection((host, port))
70
13
  _send({"type": "clear"})
71
- except Exception as e:
72
- print(f"重新连接失败: {e}", file=sys.stderr)
73
14
 
74
15
  def _send(cmd):
75
- """发送命令到服务器(线程安全)"""
76
- # 如果没有连接,直接返回
77
- if _connection is None and "pytest" not in sys.modules:
78
- return
79
-
80
- # 将命令放入队列由后台线程发送
81
- try:
82
- _command_queue.put(cmd, block=False)
83
- except queue.Full:
84
- # 队列满时丢弃最旧的一条命令
85
- try:
86
- _command_queue.get_nowait()
87
- except queue.Empty:
88
- pass
89
- _command_queue.put(cmd, block=False)
16
+ """发送命令到服务器"""
17
+ if _connection is None and "pytest" not in sys.modules: # 允许测试环境不初始化
18
+ raise ConnectionError("GUI not initialized. Call gui.init() first.")
19
+ if _connection:
20
+ _connection.sendall((json.dumps(cmd) + "\n").encode())
90
21
 
91
22
  def show_text(x, y, text, color="black", size=16):
92
23
  _send({"type": "text", "x": x, "y": y, "text": text, "color": color, "size": size})
93
24
 
94
- def print(text):
25
+ def print(text): # 使用print作为函数名,因为调用时使用gui.print()
95
26
  _send({"type": "print", "text": text})
96
27
 
97
28
  def println(text):
@@ -120,18 +51,11 @@ def clear():
120
51
 
121
52
  def close():
122
53
  """关闭GUI连接"""
123
- global _connection, _sender_thread, _stop_event
124
- # 设置停止事件
125
- _stop_event.set()
126
- if _sender_thread:
127
- # 等待发送线程退出
128
- _sender_thread.join(timeout=0.5)
54
+ global _connection
129
55
  if _connection:
130
- try:
131
- _connection.close()
132
- except:
133
- pass
56
+ _connection.close()
134
57
  _connection = None
135
58
 
136
59
  # 注册程序退出时自动关闭连接
60
+ import atexit
137
61
  atexit.register(close)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: smartpi
3
- Version: 0.1.13
3
+ Version: 0.1.14
4
4
  Summary: A library use for H2-RCU
5
5
  Author: ZMROBO
6
6
  Classifier: Programming Language :: Python :: 3
@@ -1,8 +1,8 @@
1
- smartpi/__init__.py,sha256=hSlULYmtHrtLpplBFTQagFL4pXXCSoMgkNVFfklgtzc,55
2
- smartpi/base_driver.py,sha256=FmnwZFqKE2HVUsDoqxXigdX1YlElcY07YkLnlvKY_x8,18033
1
+ smartpi/__init__.py,sha256=7gd_8YTZSFswemDB4ymWsDfhMpyAMzJ0BMImjrWF6vc,55
2
+ smartpi/base_driver.py,sha256=ChZAacB5ACUoA6R1bB4MYQH4Mkl0umrlZ3UFaTfoz-Q,19571
3
3
  smartpi/color_sensor.py,sha256=sTqD3jApjmc6qHMrDyEy2UjaRt8vhJZNR88vzgUiLKs,496
4
4
  smartpi/cw2015.py,sha256=1lAF-pi_ye_ya1AZQS1sjbgsDf7MThO5IAskKsNGBzA,5695
5
- smartpi/gui.py,sha256=M0VXAxk9VmW8VXSbbcRfOtZUVigWIDn0pEEYZHMTeI0,4416
5
+ smartpi/gui.py,sha256=E98_soyWbEf_dwYhXZgMSXrgY5QuYoDTuFCPK63flIQ,2102
6
6
  smartpi/humidity.py,sha256=xtALQ_IlcwR2RCYvopCSmeNajB45kQU_ckk6FZ0rqko,497
7
7
  smartpi/led.py,sha256=n3_k1jGcQptfGXhezDLaYzH6UptgluP4Ze6qP_Y4WmU,536
8
8
  smartpi/light_sensor.py,sha256=kWmoXklYS1QG0eDz4Qn9FF4WueR3GARb3OwQSkXqUNA,569
@@ -12,7 +12,7 @@ smartpi/servo.py,sha256=B6X3yCoEz82qqpUIE5MSO0Eg9YZJ5zDzJEcRpioZpUo,4625
12
12
  smartpi/temperature.py,sha256=px2YeqgG63nPkyhJA1wDg3dwYx_oOCYuhMjtsVm_YO0,460
13
13
  smartpi/touch_sensor.py,sha256=F6IIQGewNRhC9U1RbHpVzuGYqb8H41lpeQ1Ejwsc_T8,438
14
14
  smartpi/ultrasonic.py,sha256=0meczFKXFLUt92kLxipeEc37vb5duvJjPs4kgtlpO8M,622
15
- smartpi-0.1.13.dist-info/METADATA,sha256=fyS1LxSRoLa2FGN9JpZ7QYayqJ6zx57Nyt_mTBP6JI0,311
16
- smartpi-0.1.13.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
17
- smartpi-0.1.13.dist-info/top_level.txt,sha256=PoLhUCmWAiQUg5UeN2fS-Y1iQyBbF2rdUlizXtpHGRQ,8
18
- smartpi-0.1.13.dist-info/RECORD,,
15
+ smartpi-0.1.14.dist-info/METADATA,sha256=X3ikK51XRpqcegUbzHDAtzSIy3L4Z_A7pc7rOuM6SAI,311
16
+ smartpi-0.1.14.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
17
+ smartpi-0.1.14.dist-info/top_level.txt,sha256=PoLhUCmWAiQUg5UeN2fS-Y1iQyBbF2rdUlizXtpHGRQ,8
18
+ smartpi-0.1.14.dist-info/RECORD,,