diff --git a/DLPilot/release/DLPilot.exe b/DLPilot/release/DLPilot.exe index a83e40e..df0ea12 100644 Binary files a/DLPilot/release/DLPilot.exe and b/DLPilot/release/DLPilot.exe differ diff --git a/DLPilot/src/app_gui.py b/DLPilot/src/app_gui.py index 2c93ee3..49b8980 100644 --- a/DLPilot/src/app_gui.py +++ b/DLPilot/src/app_gui.py @@ -771,6 +771,8 @@ class App(ctk.CTk): else: color = 'gray60' self.lbl_dlpc_st.configure(text=text, text_color=color) + if text.startswith(('已断开', '串口丢失')): + self._serial_reset_state() elif kind == 'temp': if text.startswith('DMD'): self.var_dmd.set(text) @@ -829,6 +831,7 @@ class App(ctk.CTk): def _dlpc_toggle(self): if self.dlpc.is_connected(): self.dlpc.close() + self._serial_reset_state() # 断开时清序列/定时器/应答归位, 防旧账错配 return port = self._dlpc_selected_port() if not port: @@ -847,10 +850,28 @@ class App(ctk.CTk): config.save_slots(self.slots, self.area_var.get()) # 记住本次串口 self.dlpc.open(port, baud, bytesize=bytesize, parity=parity, stopbits=stopbits) + def _serial_reset_state(self): + """断开/失连时清理进行中的序列与应答归位队列(不碰串口线程本身)""" + self._pd_seq.clear() + self._pwr_seq.clear() + for t in (self._pd_timer, self._pwr_timer): + if t: + try: + self.after_cancel(t) + except Exception: + pass + self._pd_timer = self._pwr_timer = None + self._tl_order.clear() + def _dlpc_send(self, cmd): if not self.dlpc.is_connected(): self.lbl_dlpc_st.configure(text='未连接串口', text_color='#E07A3F') return + if self._pd_seq or self._pwr_seq: + # 序列进行中: 手动命令的应答帧会被序列错认领(它不区分应答属于哪条 + # 命令, 来一帧消费一步), 值会错位 —— 拒绝并提示, 序列结束再发 + self._dlpc_log(f'序列进行中, 命令已忽略: {cmd}') + return self.dlpc.send(cmd) def _dlpc_send_preset(self): diff --git a/DLPilot/src/dlpc_rs485.py b/DLPilot/src/dlpc_rs485.py index 2d7c689..72fe4d1 100644 --- a/DLPilot/src/dlpc_rs485.py +++ b/DLPilot/src/dlpc_rs485.py @@ -290,7 +290,9 @@ class DLPC485: port, baud, bytesize=bytesizes.get(dbsize, serial.EIGHTBITS), parity=parities.get(parity, serial.PARITY_NONE), stopbits=stopbits.get(sbits, serial.STOPBITS_ONE), - timeout=0.15) + timeout=0.15, + write_timeout=1.0) # 写超时: 转换器停滞时 write 会 + # 永久阻塞并卡死线程, 必须设上限 self.parser = FrameParser() self._open_key = target self.on_status(f'已连接 {port} @ {baud} '