feat(ota): TCP(ETH)升级通道与升级页面关闭释放连接, 版本V1.3.0 -> V1.3.1

- 升级通道下拉新增TCP(ETH), 与TCP(Cat1)共用通道逻辑, ETH局域网升级打通
- TCP发送批次超时重置(3秒定时器重启动), 避免链路抖动后批次卡死
- 关闭升级页面主动释放连接: 停止TCP监听并断开所有已连客户端(shutdown+close), 关闭升级串口与接收线程
- 修复UpgradeDialog未初始化self.ser/_serial_rx导致closeEvent清理中断的问题
- TcpServerThread.stop统一收口: 关监听socket打断accept轮询+清空连接表, 按钮状态复位
This commit is contained in:
2026-10-12 10:24:51 +08:00
parent bae784f849
commit 577a15c400
+49 -4
View File
@@ -294,8 +294,33 @@ class TcpServerThread(QThread):
def stop(self):
self.running = False
try:
if self.sock:
self.sock.close() # 打断accept轮询, run循环立即退出
except Exception:
pass
self._close_all_clients()
self.wait(3000)
def _close_all_clients(self):
"""主动断开所有已连接客户端(网关模组的TCP链路随之释放, 对端能立刻感知断开)。"""
with self.conn_lock:
conns = list(self._conns.keys())
self._conns.clear()
self.conn = None
self.target_ip = None
for conn in conns:
try:
conn.shutdown(socket.SHUT_RDWR)
except Exception:
pass
try:
conn.close()
except Exception:
pass
self._hexbufs.clear()
self._push_ip_list()
class GatewayConfigTool(QMainWindow):
def __init__(self):
@@ -315,7 +340,7 @@ class GatewayConfigTool(QMainWindow):
self.refresh_ports()
def init_ui(self):
self.setWindowTitle("网关配置工具(宽带版 V1.3.0)")
self.setWindowTitle("网关配置工具(宽带版 V1.3.1)")
self.setWindowIcon(QIcon(resource_path("物联网网关.png")))
self.setMinimumSize(940, 640)
self.resize(1000, 700)
@@ -795,6 +820,8 @@ class UpgradeDialog(QDialog):
self._timer = QTimer()
self.channel = 'serial' # 升级通道: serial / tcp
self.tcp_thread = None
self.ser = None # 升级通道串口对象(独立于主界面串口)
self._serial_rx = None # 升级串口接收线程
self._window = 8 # TCP模式每批包数(窗口流控)
self._window_start = 0 # 当前批次首包序号(超时重发用)
self._retry_cnt = 0 # TCP模式超时重发计数
@@ -832,7 +859,7 @@ class UpgradeDialog(QDialog):
# 通道选择 + TCP监听
cfg_layout.addWidget(QLabel("通道:"), 2, 0)
self.combo_channel = QComboBox()
self.combo_channel.addItems(["串口", "TCP(Cat1)"])
self.combo_channel.addItems(["串口", "TCP(Cat1)", "TCP(ETH)"])
self.combo_channel.currentIndexChanged.connect(self._on_channel_changed)
cfg_layout.addWidget(self.combo_channel, 2, 1)
tcp_row = QHBoxLayout()
@@ -1263,6 +1290,7 @@ class UpgradeDialog(QDialog):
done = max(self._sent) + 1
self.progress.setValue(min(int(done * 100.0 / self._pkg_num), 100))
self.status_lbl.setText(f"{done}/{self._pkg_num} 包")
self._timer.start(3000) # 批次发完重置超时: 防止上次定时器虚假触发(REQ已处理仍判超时)
if len(self._sent) >= self._pkg_num:
self._finish()
@@ -1309,8 +1337,25 @@ class UpgradeDialog(QDialog):
self._cancel_upgrade()
else:
self._release_session()
if self.ser and self.ser.is_open:
self._toggle_serial()
# 升级TCP通道: 停止监听并主动断开已连接的客户端, 释放网关模组建立的TCP链路
if self.tcp_thread is not None:
if self.tcp_thread.isRunning():
self.tcp_thread.stop()
self.tcp_thread = None
self.btn_tcp_listen.setText("开始监听")
# 串口通道: 关闭升级页面打开的串口
if self.ser is not None:
if self._serial_rx is not None:
self._serial_rx.stop()
self._serial_rx = None
try:
self.ser.close()
except Exception:
pass
self.ser = None
self.btn_serial_open.setText("打开串口")
self.serial_status_lbl.setText("未打开")
self.serial_status_lbl.setStyleSheet("color:#909090;")
self._reset_ui()
event.accept()