From 6d6c847c237a435fa9e6578e2ea7d029b23c351f Mon Sep 17 00:00:00 2001 From: YuanHongbin <975559679@qq.com> Date: Thu, 25 Jun 2026 11:24:39 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E7=95=8C=E9=9D=A2=E5=8F=8A?= =?UTF-8?q?=E5=8F=82=E6=95=B0=E8=A7=A3=E6=9E=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- laser_tracing_config.py | 171 +++++++++++++++++++++++----------------- 1 file changed, 98 insertions(+), 73 deletions(-) diff --git a/laser_tracing_config.py b/laser_tracing_config.py index e17ff21..cc41967 100644 --- a/laser_tracing_config.py +++ b/laser_tracing_config.py @@ -17,7 +17,7 @@ class LaserTracingConfigApp: def __init__(self, root): self.root = root self.root.title("激光示踪配置工具") - self.root.geometry("960x720") + self.root.geometry("900x700") self.root.resizable(True, True) self.serial_port = None @@ -42,19 +42,19 @@ class LaserTracingConfigApp: self.port_combo.grid(row=0, column=1, padx=2) ttk.Button(conn_frame, text="刷新", width=5, command=self._refresh_ports).grid(row=0, column=2, padx=2) - ttk.Label(conn_frame, text="波特率:").grid(row=0, column=3, sticky=tk.W, padx=(12, 2)) + ttk.Label(conn_frame, text="波特率:").grid(row=0, column=3, sticky=tk.W, padx=2) self.baudrate_var = tk.StringVar(value="9600") ttk.Label(conn_frame, textvariable=self.baudrate_var, width=8).grid(row=0, column=4, padx=2) - ttk.Label(conn_frame, text="数据位:").grid(row=0, column=5, sticky=tk.W, padx=(12, 2)) + ttk.Label(conn_frame, text="数据位:").grid(row=0, column=5, sticky=tk.W, padx=2) self.databits_var = tk.StringVar(value="8") ttk.Label(conn_frame, textvariable=self.databits_var, width=4).grid(row=0, column=6, padx=2) - ttk.Label(conn_frame, text="停止位:").grid(row=0, column=7, sticky=tk.W, padx=(12, 2)) + ttk.Label(conn_frame, text="停止位:").grid(row=0, column=7, sticky=tk.W, padx=2) self.stopbits_var = tk.StringVar(value="1") ttk.Label(conn_frame, textvariable=self.stopbits_var, width=4).grid(row=0, column=8, padx=2) - ttk.Label(conn_frame, text="校验:").grid(row=0, column=9, sticky=tk.W, padx=(12, 2)) + ttk.Label(conn_frame, text="校验:").grid(row=0, column=9, sticky=tk.W, padx=2) self.parity_var = tk.StringVar(value="None") ttk.Label(conn_frame, textvariable=self.parity_var, width=6).grid(row=0, column=10, padx=2) @@ -95,34 +95,54 @@ class LaserTracingConfigApp: ttk.Label(query_frame, text="配置后可通过para命令验证是否成功", foreground="gray").pack(side=tk.LEFT, padx=8) - # 参数显示区域 + # 参数显示区域 - 改用grid布局每行两个参数 para_frame = ttk.LabelFrame(self.root, text="设备参数信息", padding=8) - para_frame.pack(fill=tk.BOTH, expand=True, padx=8, pady=4) + para_frame.pack(fill=tk.X, padx=8, pady=4) - # 使用Treeview展示解析后的参数(双列无表头,不可选定) - columns = ("参数", "值") - self.para_tree = ttk.Treeview(para_frame, columns=columns, show="tree headings", - height=10, selectmode="none") - self.para_tree.heading("#0", text="") - self.para_tree.heading("参数", text="") - self.para_tree.heading("值", text="") - self.para_tree.column("#0", width=0, stretch=False) - self.para_tree.column("参数", width=180, anchor=tk.W) - self.para_tree.column("值", width=380, anchor=tk.W) - tree_scroll = ttk.Scrollbar(para_frame, orient=tk.VERTICAL, command=self.para_tree.yview) - self.para_tree.configure(yscrollcommand=tree_scroll.set) - self.para_tree.pack(side=tk.LEFT, fill=tk.BOTH, expand=True) - tree_scroll.pack(side=tk.RIGHT, fill=tk.Y) + # 配置两列均匀分布 + para_frame.columnconfigure(0, weight=1) + para_frame.columnconfigure(1, weight=1) + para_frame.columnconfigure(2, weight=1) + para_frame.columnconfigure(3, weight=1) - # 预填充参数表格(值为"-"待读取后更新) + # 参数按顺序每两个一组 self._para_order = ["软件版本", "硬件版本", "本机MAC", "电池电量", "设备类型", - "通信方式", "设备标识", "网关MAC", "注册状态", - "RS485_1", "RS485_2", "Lora参数", "低功耗配置", - "设备时间", "错误信息"] - self._para_value_items = {} - for key in self._para_order: - item_id = self.para_tree.insert("", tk.END, values=(key, "-")) - self._para_value_items[key] = item_id + "通信方式", "设备标识", "网关MAC", "注册状态", "Lora频率"] + + # 创建标签对 + self._para_labels = {} + for idx, key in enumerate(self._para_order): + row = idx // 2 + col = (idx % 2) * 2 + + # 参数名标签 + name_label = ttk.Label(para_frame, text=f"{key}:", font=("SimSun", 9)) + name_label.grid(row=row, column=col, sticky=tk.W, padx=(0, 2), pady=2) + + # 参数值标签 + value_label = ttk.Label(para_frame, text="-", font=("SimSun", 9), foreground="green") + value_label.grid(row=row, column=col + 1, sticky=tk.W + tk.E, padx=(0, 10), pady=2) + + self._para_labels[key] = value_label + + # 低功耗配置单独区块 - 布局与设备参数信息一致 + lp_frame = ttk.LabelFrame(self.root, text="低功耗配置", padding=6) + lp_frame.pack(fill=tk.X, padx=8, pady=4) + + lp_frame.columnconfigure(0, weight=1) + lp_frame.columnconfigure(1, weight=1) + lp_frame.columnconfigure(2, weight=1) + lp_frame.columnconfigure(3, weight=1) + + self._lp_labels = {} + lp_params = [("CI", "采集间隔"), ("RI", "上报时间"), ("EI", "紧急上报间隔"), ("ET", "紧急上报时长")] + for idx, (key, label) in enumerate(lp_params): + row = idx // 2 + col = (idx % 2) * 2 + ttk.Label(lp_frame, text=f"{label}:", font=("SimSun", 9)).grid(row=row, column=col, sticky=tk.W, padx=(0, 2), pady=2) + val_label = ttk.Label(lp_frame, text="-", font=("SimSun", 9), foreground="green") + val_label.grid(row=row, column=col + 1, sticky=tk.W + tk.E, padx=(0, 10), pady=2) + self._lp_labels[key] = val_label # 通讯日志区域 log_frame = ttk.LabelFrame(self.root, text="通讯日志", padding=4) @@ -281,15 +301,11 @@ class LaserTracingConfigApp: # ─────────────────── 回应解析 ─────────────────── def _parse_para_response(self, text): - # 清空Treeview - for item in self.para_tree.get_children(): - self.para_tree.delete(item) - lines = text.replace("\r\n", "\n").replace("\r", "\n").split("\n") key_value_patterns = [ - (r"SoftWare V:(.*)", "软件版本"), - (r"HardWare V:(.*)", "硬件版本"), + (r"[Ss]oft[Ww]are\s*[Vv]:\s*(\d+\.\d+)", "软件版本"), + (r"[Hh]ard[Ww]are\s*[Vv]:\s*(\d+\.\d+)", "硬件版本"), (r"Local MAC:\s*(.*)", "本机MAC"), (r"Battery:\s*(.*)", "电池电量"), (r"LocalType:\s*(.*)", "设备类型"), @@ -297,9 +313,7 @@ class LaserTracingConfigApp: (r"DeviceSign:\s*(.*)", "设备标识"), (r"GateWay MAC:\s*(.*)", "网关MAC"), (r"Register Status:\s*(.*)", "注册状态"), - (r"RS485h1:\s*(.*)", "RS485_1"), - (r"RS485h2:\s*(.*)", "RS485_2"), - (r"Lora:\s*(.*)", "Lora参数"), + (r"Lora.*?fc\s*(\d+)", "Lora频率"), (r"LpCfg:\s*(.*)", "低功耗配置"), ] @@ -310,46 +324,57 @@ class LaserTracingConfigApp: if m: found[label] = m.group(1).strip() - # 解析日期时间 - dt_match = re.search(r"(\d{4}/\d{1,2}/\d{1,2}-\d{1,2}:\d{2}:\d{2})", text) - if dt_match: - found["设备时间"] = dt_match.group(1) - - # 检查Error - err_match = re.search(r"Error:\s*(.*)", text) - if err_match: - found["错误信息"] = err_match.group(1).strip() - - # 重建参数表格(每次收到完整响应时) - for item in self.para_tree.get_children(): - self.para_tree.delete(item) - self._para_value_items = {} + # 更新参数显示 for key in self._para_order: value = found.get(key, "-") - item_id = self.para_tree.insert("", tk.END, values=(key, value)) - self._para_value_items[key] = item_id + if key in self._para_labels: + self._para_labels[key].configure(text=value) - # 解析Lora详细参数并更新配置界面 - if "Lora参数" in found: - lora_str = found["Lora参数"] - fc_match = re.search(r"fc\s+(\d+)", lora_str) - if fc_match: - fc_val = fc_match.group(1) - display = self._fc_value_to_display.get(fc_val) - if display: - self.lora_fc_display_var.set(display) + # 更新Lora频率下拉框 + if "Lora频率" in found: + fc_val = found["Lora频率"] + display = self._fc_value_to_display.get(fc_val) + if display: + self.lora_fc_display_var.set(display) + else: + new_display = f"自定义: {int(fc_val) / 1000000:.1f}MHz" + self._fc_display_to_value[new_display] = fc_val + self._fc_value_to_display[fc_val] = new_display + self.lora_fc_combo["values"] = list(self.lora_fc_combo["values"]) + [new_display] + self.lora_fc_display_var.set(new_display) + + # 解析低功耗配置参数 + if "低功耗配置" in found: + lp_str = found["低功耗配置"] + + ci_match = re.search(r"CI[:#\s]*(\d+)", lp_str) + ri_match = re.search(r"RI[:#\s]*(\d+)", lp_str) + ei_match = re.search(r"EI[:#\s]*(\d+)", lp_str) + et_match = re.search(r"ET[:#\s]*(\d+)", lp_str) + + def format_sec(val): + return f"{val}秒" + + def format_min(val): + val = int(val) + if val >= 60: + hours = val // 60 + mins = val % 60 + if mins == 0: + return f"{hours}时" + else: + return f"{hours}时{mins}分钟" else: - new_display = f"自定义: {int(fc_val) / 1000000:.1f}MHz" - self._fc_display_to_value[new_display] = fc_val - self._fc_value_to_display[fc_val] = new_display - self.lora_fc_combo["values"] = list(self.lora_fc_combo["values"]) + [new_display] - self.lora_fc_display_var.set(new_display) + return f"{val}分钟" - # 解析RS485波特率并提示 - if "RS485_1" in found: - baud_match = re.search(r"Baudrate\s+(\d+)", found["RS485_1"]) - if baud_match: - self.baudrate_var.set(baud_match.group(1)) + if ci_match: + self._lp_labels["CI"].configure(text=format_sec(ci_match.group(1))) + if ri_match: + self._lp_labels["RI"].configure(text=format_min(ri_match.group(1))) + if ei_match: + self._lp_labels["EI"].configure(text=format_min(ei_match.group(1))) + if et_match: + self._lp_labels["ET"].configure(text=format_min(et_match.group(1))) # ─────────────────── 日志 ───────────────────