Lora信道从0编号、波特率可选、修复通讯日志打印不全
- Lora信道以信道0为起点(470.1MHz~492.6MHz,共46信道) - 波特率改为可编辑下拉框,默认500000 - 修复para等大数据量响应日志只打印一小段:延迟解析避免UI阻塞导致串口缓冲溢出丢包 - 说明书同步更新
This commit is contained in:
+66
-18
@@ -1,6 +1,6 @@
|
||||
"""
|
||||
网关配置工具
|
||||
串口配置:波特率500000,数据位8,停止位1,校验位None
|
||||
串口配置:波特率500000(可修改),数据位8,停止位1,校验位None
|
||||
"""
|
||||
|
||||
import sys
|
||||
@@ -83,19 +83,39 @@ class SerialThread(QThread):
|
||||
super().__init__()
|
||||
self.ser = ser
|
||||
self.running = True
|
||||
self._buffer = ""
|
||||
self._buffer = b""
|
||||
|
||||
def run(self):
|
||||
while self.running:
|
||||
try:
|
||||
if self.ser and self.ser.is_open and self.ser.in_waiting > 0:
|
||||
data = self.ser.read(self.ser.in_waiting)
|
||||
try:
|
||||
text = data.decode('utf-8', errors='replace')
|
||||
except Exception:
|
||||
text = data.decode('gbk', errors='replace')
|
||||
self.data_received.emit(text)
|
||||
self.data_received_raw.emit(data)
|
||||
buf = self._buffer + data
|
||||
text = None
|
||||
# 优先 UTF-8;若结尾是不完整字符序列则保留尾部待下次拼接,避免乱码缺字
|
||||
for enc in ('utf-8', 'gbk'):
|
||||
try:
|
||||
text = buf.decode(enc)
|
||||
self._buffer = b""
|
||||
break
|
||||
except UnicodeDecodeError:
|
||||
keep = b""
|
||||
for tail in range(1, min(4, len(buf)) + 1):
|
||||
try:
|
||||
text = buf[:-tail].decode(enc)
|
||||
keep = buf[-tail:]
|
||||
break
|
||||
except UnicodeDecodeError:
|
||||
continue
|
||||
if text is not None:
|
||||
self._buffer = keep
|
||||
break
|
||||
if text is None:
|
||||
text = data.decode('utf-8', errors='replace')
|
||||
self._buffer = b""
|
||||
if text:
|
||||
self.data_received.emit(text)
|
||||
else:
|
||||
time.sleep(0.01)
|
||||
except Exception:
|
||||
@@ -113,6 +133,11 @@ class GatewayConfigTool(QMainWindow):
|
||||
self.serial_thread = None
|
||||
self._recv_buffer = ""
|
||||
self._para_mode = False
|
||||
# para 大数据量返回时,用定时器延迟解析,避免每段数据全量解析阻塞UI导致串口缓冲溢出丢包
|
||||
self._para_timer = QTimer(self)
|
||||
self._para_timer.setSingleShot(True)
|
||||
self._para_timer.setInterval(250)
|
||||
self._para_timer.timeout.connect(self._on_para_parse)
|
||||
self.upgrade_dialog = None
|
||||
self.dev_dialog = None
|
||||
self.init_ui()
|
||||
@@ -145,7 +170,13 @@ class GatewayConfigTool(QMainWindow):
|
||||
conn_layout.addWidget(self.btn_refresh)
|
||||
|
||||
conn_layout.addSpacing(20)
|
||||
conn_layout.addWidget(QLabel("波特率: 500000"))
|
||||
conn_layout.addWidget(QLabel("波特率:"))
|
||||
self.combo_baud = QComboBox()
|
||||
self.combo_baud.setEditable(True)
|
||||
self.combo_baud.addItems(["115200", "230400", "460800", "500000", "921600", "1000000"])
|
||||
self.combo_baud.setCurrentText("500000")
|
||||
self.combo_baud.setFixedWidth(90)
|
||||
conn_layout.addWidget(self.combo_baud)
|
||||
conn_layout.addWidget(QLabel("数据位: 8"))
|
||||
conn_layout.addWidget(QLabel("停止位: 1"))
|
||||
conn_layout.addWidget(QLabel("校验: None"))
|
||||
@@ -174,12 +205,12 @@ class GatewayConfigTool(QMainWindow):
|
||||
self.combo_lora_fc = QComboBox()
|
||||
self.combo_lora_fc.setFixedWidth(200)
|
||||
lora_freqs = []
|
||||
fc_hz = 410100000
|
||||
ch_idx = 1
|
||||
while fc_hz < 493000000:
|
||||
fc_hz = 470100000
|
||||
ch_idx = 0
|
||||
while fc_hz <= 492600000:
|
||||
mhz = fc_hz / 1000000
|
||||
lora_freqs.append((str(fc_hz), f"信道{ch_idx}: {mhz:.1f}MHz"))
|
||||
fc_hz += 200000
|
||||
fc_hz += 500000
|
||||
ch_idx += 1
|
||||
for freq, desc in lora_freqs:
|
||||
self.combo_lora_fc.addItem(desc, freq)
|
||||
@@ -356,10 +387,15 @@ class GatewayConfigTool(QMainWindow):
|
||||
if not port_name:
|
||||
QMessageBox.warning(self, "错误", "请选择有效的串口!")
|
||||
return
|
||||
try:
|
||||
baud = int(self.combo_baud.currentText().strip())
|
||||
except ValueError:
|
||||
QMessageBox.warning(self, "错误", "波特率无效,请输入数字!")
|
||||
return
|
||||
try:
|
||||
self.serial_port = serial.Serial(
|
||||
port=port_name,
|
||||
baudrate=500000,
|
||||
baudrate=baud,
|
||||
bytesize=serial.EIGHTBITS,
|
||||
stopbits=serial.STOPBITS_ONE,
|
||||
parity=serial.PARITY_NONE,
|
||||
@@ -372,7 +408,7 @@ class GatewayConfigTool(QMainWindow):
|
||||
|
||||
self.btn_connect.setText("关闭串口")
|
||||
self.btn_connect.setStyleSheet("background-color:#f44336; color:white; font-weight:bold;")
|
||||
self.log_send(f"已连接 {port_name} @ 500000")
|
||||
self.log_send(f"已连接 {port_name} @ {baud}")
|
||||
self.statusBar().showMessage(f"已连接: {port_name}")
|
||||
except Exception as e:
|
||||
QMessageBox.critical(self, "串口错误", f"无法打开串口:\n{e}")
|
||||
@@ -395,6 +431,14 @@ class GatewayConfigTool(QMainWindow):
|
||||
self._recv_buffer = ""
|
||||
self._para_mode = True
|
||||
self.send_command("para")
|
||||
self._para_timer.start()
|
||||
|
||||
def _on_para_parse(self):
|
||||
if not self._para_mode:
|
||||
return
|
||||
self._try_parse_para()
|
||||
if not self._para_mode:
|
||||
self._para_timer.stop()
|
||||
|
||||
def on_lora_send(self):
|
||||
value = self.combo_lora_fc.currentData()
|
||||
@@ -467,7 +511,7 @@ class GatewayConfigTool(QMainWindow):
|
||||
if self.dev_dialog is not None and self.dev_dialog.isVisible():
|
||||
self.dev_dialog.feed_text(text)
|
||||
if self._para_mode:
|
||||
self._try_parse_para()
|
||||
self._para_timer.start()
|
||||
|
||||
def _try_parse_para(self):
|
||||
buf = self._recv_buffer.replace('\r', '')
|
||||
@@ -544,11 +588,15 @@ class GatewayConfigTool(QMainWindow):
|
||||
self._recv_buffer = ""
|
||||
self.statusBar().showMessage("配置读取完成")
|
||||
|
||||
@staticmethod
|
||||
def _escape_html(s):
|
||||
return s.replace('&', '&').replace('<', '<').replace('>', '>')
|
||||
|
||||
def log_send(self, text):
|
||||
self.text_log.append(f'<span style="color:#569CD6;">{text}</span>')
|
||||
self.text_log.append(f'<span style="color:#569CD6;">{self._escape_html(text)}</span>')
|
||||
|
||||
def log_recv(self, text):
|
||||
clean = text.replace('\r', '').replace('\n', '<br>')
|
||||
clean = self._escape_html(text).replace('\r', '').replace('\n', '<br>')
|
||||
self.text_log.append(f'<span style="color:#CE9178;"><<< {clean}</span>')
|
||||
|
||||
def closeEvent(self, event):
|
||||
@@ -673,7 +721,7 @@ class UpgradeDialog(QDialog):
|
||||
|
||||
def _log(self, msg, tag="info"):
|
||||
color = {"ok": "#2E7D32", "err": "#D32F2F", "info": "#1565C0"}.get(tag, "#000000")
|
||||
self.log_text.append(f'<span style="color:{color};">{msg}</span>')
|
||||
self.log_text.append(f'<span style="color:{color};">{GatewayConfigTool._escape_html(str(msg))}</span>')
|
||||
|
||||
def _log_debug(self, data):
|
||||
if not data:
|
||||
|
||||
Reference in New Issue
Block a user