4 Commits

Author SHA1 Message Date
YuanHongbin 31612e5b95 docs: 说明书指令参考精简为exe界面涉及指令, 修复表格长文本截断
- 指令参考仅保留界面按钮对应的para与lora fc, 其余指令改为在线帮助提示
- 删除lpcfg/laser/sig等扩展操作指南章节, 恢复原有章节结构
- 表格单元格改为Paragraph自动换行, 修复超宽内容被截断的问题
- 补充界面细节: 串口参数固定8/N/1, 清空日志按钮, 升级自动切9600与超时保护
2026-09-24 11:47:00 +08:00
YuanHongbin 4a6ff717c4 宽带版:exe文件名与属性补充版本号V1.0.0,同步说明书生成脚本并生成宽带版说明书 2026-09-07 18:24:12 +08:00
YuanHongbin 1d0b4b2fd1 宽带版:添加版本信息V1.0.0(窗口标题与exe属性) 2026-09-07 18:23:50 +08:00
YuanHongbin 67bd8ebf91 宽带版:LoRa信道改为433.1~492.6MHz,步进500kHz,共120信道(信道0起始) 2026-09-07 18:23:50 +08:00
5 changed files with 168 additions and 137 deletions
+127 -134
View File
@@ -1,5 +1,10 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
"""生成边坡变形监测配置工具使用说明书(PDF格式)""" # 生成配置工具使用说明书(PDF格式)
# 用法: python generate_manual.py narrow -> 生成窄带版说明书
# python generate_manual.py wide -> 生成宽带版说明书
import os
import sys
from reportlab.lib.pagesizes import A4 from reportlab.lib.pagesizes import A4
from reportlab.lib.units import cm, mm from reportlab.lib.units import cm, mm
from reportlab.lib.colors import HexColor, black, white from reportlab.lib.colors import HexColor, black, white
@@ -11,7 +16,25 @@ from reportlab.platypus import (
) )
from reportlab.pdfbase import pdfmetrics from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.ttfonts import TTFont from reportlab.pdfbase.ttfonts import TTFont
import os
# ── 版本与型号配置 ──
SOFTWARE_VERSION = "V1.0.0"
arg = sys.argv[1].lower() if len(sys.argv) > 1 else "narrow"
if arg in ("wide", "broadband", "宽带"):
EDITION = "宽带版"
FC_RANGE = "433.1MHz ~ 492.6MHz"
FC_CHANNELS = 120
FC_EXAMPLE = "433100000"
else:
EDITION = "窄带版"
FC_RANGE = "470.1MHz ~ 492.6MHz"
FC_CHANNELS = 46
FC_EXAMPLE = "470100000"
FC_STEP = "500kHz"
EXE_NAME = f"边坡变形监测-变形(位移)自动测量系统配置工具({EDITION} {SOFTWARE_VERSION}).exe"
PDF_NAME = f"边坡变形监测-变形(位移)自动测量系统配置工具使用说明书({EDITION} {SOFTWARE_VERSION}).pdf"
# 注册中文字体 # 注册中文字体
font_dir = os.path.join(os.environ.get("WINDIR", r"C:\Windows"), "Fonts") font_dir = os.path.join(os.environ.get("WINDIR", r"C:\Windows"), "Fonts")
@@ -42,20 +65,20 @@ style_step = ParagraphStyle("Step", parent=style_body, leftIndent=20)
style_warning = ParagraphStyle("Warning", parent=style_body, textColor=C_RED, fontName="SimHei") style_warning = ParagraphStyle("Warning", parent=style_body, textColor=C_RED, fontName="SimHei")
style_q = ParagraphStyle("Q", fontName="SimHei", fontSize=11, leading=20, spaceBefore=10, spaceAfter=2) style_q = ParagraphStyle("Q", fontName="SimHei", fontSize=11, leading=20, spaceBefore=10, spaceAfter=2)
style_a = ParagraphStyle("A", fontName="SimSun", fontSize=11, leading=20, leftIndent=20, spaceAfter=6) style_a = ParagraphStyle("A", fontName="SimSun", fontSize=11, leading=20, leftIndent=20, spaceAfter=6)
style_th = ParagraphStyle("TH", fontName="SimHei", fontSize=11, leading=15, textColor=white)
style_td = ParagraphStyle("TD", fontName="SimSun", fontSize=10, leading=14)
def make_table(headers, rows, col_widths=None): def make_table(headers, rows, col_widths=None):
data = [headers] + rows # 单元格统一用 Paragraph 包装,超宽内容自动换行(字符串单元格会被截断)
from xml.sax.saxutils import escape as _esc
data = [[Paragraph(_esc(str(headers[0])), style_th)] + [Paragraph(_esc(str(c)), style_td) for c in headers[1:]]]
for r in rows:
data.append([Paragraph(_esc(str(c)), style_td) for c in r])
if col_widths is None: if col_widths is None:
col_widths = [doc.width / len(headers)] * len(headers) col_widths = [doc.width / len(headers)] * len(headers)
t = Table(data, colWidths=col_widths, repeatRows=1) t = Table(data, colWidths=col_widths, repeatRows=1)
style_cmds = [ style_cmds = [
("BACKGROUND", (0, 0), (-1, 0), C_HEADER_BG), ("BACKGROUND", (0, 0), (-1, 0), C_HEADER_BG),
("TEXTCOLOR", (0, 0), (-1, 0), C_HEADER_FG),
("FONTNAME", (0, 0), (-1, 0), "SimHei"),
("FONTSIZE", (0, 0), (-1, 0), 11),
("FONTNAME", (0, 1), (-1, -1), "SimSun"),
("FONTSIZE", (0, 1), (-1, -1), 10),
("ALIGN", (0, 0), (-1, -1), "LEFT"),
("VALIGN", (0, 0), (-1, -1), "MIDDLE"), ("VALIGN", (0, 0), (-1, -1), "MIDDLE"),
("GRID", (0, 0), (-1, -1), 0.5, HexColor("#CCCCCC")), ("GRID", (0, 0), (-1, -1), 0.5, HexColor("#CCCCCC")),
("TOPPADDING", (0, 0), (-1, -1), 4), ("TOPPADDING", (0, 0), (-1, -1), 4),
@@ -75,10 +98,7 @@ def step(num, text):
return Paragraph(str(num) + ". " + text, style_step) return Paragraph(str(num) + ". " + text, style_step)
# 构建文档 # 构建文档
output_path = os.path.join( output_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), PDF_NAME)
os.path.dirname(os.path.abspath(__file__)),
"边坡变形监测配置工具使用说明书.pdf"
)
doc = SimpleDocTemplate(output_path, pagesize=A4, doc = SimpleDocTemplate(output_path, pagesize=A4,
leftMargin=2.5*cm, rightMargin=2.5*cm, leftMargin=2.5*cm, rightMargin=2.5*cm,
topMargin=2.5*cm, bottomMargin=2.5*cm) topMargin=2.5*cm, bottomMargin=2.5*cm)
@@ -87,9 +107,9 @@ story = []
# 封面 # 封面
story.append(Spacer(1, 6*cm)) story.append(Spacer(1, 6*cm))
story.append(Paragraph("边坡变形监测-变形(位移)<br/>自动测量系统配置工具<br/>使用说明书", style_cover_title)) story.append(Paragraph("边坡变形监测-变形(位移)<br/>自动测量系统配置工具(" + EDITION + ")<br/>使用说明书", style_cover_title))
story.append(Spacer(1, 1.5*cm)) story.append(Spacer(1, 1.5*cm))
story.append(Paragraph("版本 V2.0", style_cover_sub)) story.append(Paragraph("版本 " + SOFTWARE_VERSION, style_cover_sub))
story.append(PageBreak()) story.append(PageBreak())
# 目录 # 目录
@@ -99,23 +119,20 @@ toc_items = [
(True, "2 运行环境"), (True, "2 运行环境"),
(True, "3 软件安装与启动"), (True, "3 软件安装与启动"),
(False, " 3.1 安装"), (False, " 3.1 安装"),
(False, " 3.2 ��动"), (False, " 3.2 启动"),
(False, " 3.3 USB转串口驱动安装"), (False, " 3.3 USB转串口驱动安装"),
(True, "4 软件界面说明"), (True, "4 软件界面说明"),
(False, " 4.1 串口连接区域"), (False, " 4.1 串口连接区域"),
(False, " 4.2 参数配置区域"), (False, " 4.2 参数配置区域"),
(False, " 4.3 设备参数信息区域"), (False, " 4.3 设备参数信息区域"),
(False, " 4.4 低功耗配置区域"), (False, " 4.4 低功耗配置区域"),
(False, " 4.5 功率与激光配置区域"), (False, " 4.5 通讯日志区域"),
(False, " 4.6 通讯日志区域"),
(True, "5 操作指南"), (True, "5 操作指南"),
(False, " 5.1 连接设备"), (False, " 5.1 连接设备"),
(False, " 5.2 查询设备参数"), (False, " 5.2 查询设备参数"),
(False, " 5.3 修改Lora信道频率"), (False, " 5.3 修改Lora信道频率"),
(False, " 5.4 全功率时段配置"), (False, " 5.4 设备升级"),
(False, " 5.5 激光控制"), (False, " 5.5 发送自定义指令"),
(False, " 5.6 设备升级"),
(False, " 5.7 发送自定义指令"),
(True, "6 指令参考"), (True, "6 指令参考"),
(True, "7 常见问题与故障排除"), (True, "7 常见问题与故障排除"),
] ]
@@ -126,7 +143,7 @@ story.append(PageBreak())
# 1 软件概述 # 1 软件概述
story.append(Paragraph("1 软件概述", style_h1)) story.append(Paragraph("1 软件概述", style_h1))
story.append(Paragraph( story.append(Paragraph(
"边坡变形监测-变形(位移)自动测量系统配置工具是一款用于激光示踪传感器设备的网关参数配置软件。" "边坡变形监测-变形(位移)自动测量系统配置工具(" + EDITION + ")是一款用于激光示踪传感器设备的网关参数配置软件。"
"软件通过RS485串口与传感器设备进行通信,支持查询设备参数、修改Lora无线通信频率、发送自定义指令等操作。", "软件通过RS485串口与传感器设备进行通信,支持查询设备参数、修改Lora无线通信频率、发送自定义指令等操作。",
style_body style_body
)) ))
@@ -135,11 +152,11 @@ features = [
"自动识别并列出本机可用串口", "自动识别并列出本机可用串口",
"通过RS485串口连接激光示踪传感器设备", "通过RS485串口连接激光示踪传感器设备",
"一键查询设备全部参数(软件版本、硬件版本、MAC地址、电池电量、注册状态等)", "一键查询设备全部参数(软件版本、硬件版本、MAC地址、电池电量、注册状态等)",
"修改Lora无线通信信道频率(410.1MHz ~ 492.9MHz,步进200kHz)", "修改Lora无线通信信道频率(" + FC_RANGE + ",步进" + FC_STEP + ",共" + str(FC_CHANNELS) + "个信道,信道0起始)",
"波特率支持修改(内置2400~115200常用波特率,也可手动输入)",
"查看设备低功耗配置参数(采集间隔、上报时间、紧急上报间隔/时长)", "查看设备低功耗配置参数(采集间隔、上报时间、紧急上报间隔/时长)",
"查看功率与激光参数,并配置全功率工作时间段", "注册状态自动转换为\"已注册/未注册\"显示",
"控制激光开关及设置自动关闭时间", "通过通用串口升级协议(V1.1)实现设备固件升级,支持进度显示与断口复用",
"通过通用串口升级协议(V1.1)实现设备固件升级",
"支持发送自定义AT指令", "支持发送自定义AT指令",
"通讯日志实时显示,方便调试", "通讯日志实时显示,方便调试",
] ]
@@ -165,17 +182,17 @@ story.append(Paragraph("3 软件安装与启动", style_h1))
story.append(Paragraph("3.1 安装", style_h2)) story.append(Paragraph("3.1 安装", style_h2))
story.append(Paragraph( story.append(Paragraph(
'本软件为绿色免安装版本,无需安装过程。将"边坡变形监测-变形(位移)自动测量系统配置工具.exe"文件复制到电脑任意目录即可使用。', "本软件为绿色免安装版本,无需安装过程。将\"" + EXE_NAME + "\"文件复制到电脑任意目录即可使用。",
style_body style_body
)) ))
story.append(Paragraph("3.2 启动", style_h2)) story.append(Paragraph("3.2 启动", style_h2))
story.append(Paragraph( story.append(Paragraph(
'双击"边坡变形监测-变形(位移)自动测量系统配置工具.exe"文件即可启动软件。', "双击\"" + EXE_NAME + "\"文件即可启动软件。窗口标题栏显示软件型号(" + EDITION + ")与版本号(" + SOFTWARE_VERSION + ")。",
style_body style_body
)) ))
story.append(Paragraph( story.append(Paragraph(
'注意:如果Windows弹出"Windows已保护你的电脑"提示,请点击"更多信息"->"仍要运行"。', "注意:如果Windows弹出\"Windows已保护你的电脑\"提示,请点击\"更多信息\"->\"仍要运行\"。",
style_body style_body
)) ))
@@ -192,7 +209,7 @@ story.append(make_table(
)) ))
story.append(Spacer(1, 6)) story.append(Spacer(1, 6))
story.append(Paragraph( story.append(Paragraph(
'驱动安装成功后,将USB转RS485线插入电脑,在"设备管理器->端口(COM和LPT)"中应能看到对应的COM口编号。', "驱动安装成功后,将USB转RS485线插入电脑,在\"设备管理器->端口(COM和LPT)\"中应能看到对应的COM口编号。",
style_body style_body
)) ))
@@ -205,39 +222,29 @@ story.append(Paragraph("位于界面顶部,用于选择和配置串口连接
story.append(make_table( story.append(make_table(
["项目", "说明", "默认值"], ["项目", "说明", "默认值"],
[ [
["串口选择", '下拉框选择可用串口,点击"刷新"按钮可重新扫描', "自动选择第一个"], ["串口选择", "下拉框选择可用串口(显示端口描述,同名端口自动追加COM号区分),点击\"刷新\"按钮可重新扫描", "自动选择第一个"],
["波特率", "串口通信速率", "9600 bps"], ["波特率", "串口通信速率,可编辑下拉框,内置2400/4800/9600/19200/38400/57600/115200,也可手动输入", "9600 bps"],
["数据位", "每帧数据位数", "8"], ["数据位", "固定为8,与设备通信协议一致(界面仅显示,不可修改)", "8"],
["停止位", "停止位位数", "1"], ["停止位", "固定为1,与设备通信协议一致(界面仅显示,不可修改)", "1"],
["校验", "奇偶校验方式", "None(无校验)"], ["校验", "固定为无校验,与设备通信协议一致(界面仅显示,不可修改)", "None(无校验)"],
["打开/关闭串口", "按钮切换串口连接状态", "—"], ["打开/关闭串口", "按钮切换串口连接状态;连接成功后串口下拉框锁定,关闭后恢复可选", "—"],
], ],
col_widths=[3.5*cm, 8.5*cm, 4*cm] col_widths=[3.5*cm, 8.5*cm, 4*cm]
)) ))
story.append(Paragraph("4.2 参数配置区域", style_h2)) story.append(Paragraph("4.2 参数配置区域", style_h2))
story.append(Paragraph("包含Lora参数、全功率时段配置、激光控制以及查询/升级操作:", style_body)) story.append(Paragraph("包含Lora参数以及查询/升级操作:", style_body))
story.append(Paragraph("Lora 参数:", style_body)) story.append(Paragraph("Lora 参数:", style_body))
story.append(Paragraph( story.append(Paragraph(
"信道频率(fc):下拉选择Lora通信频率,范围410.1MHz ~ 492.9MHz,步进200kHz(共415个信道)。" "信道频率(fc):下拉选择Lora通信频率,范围" + FC_RANGE + ",步进" + FC_STEP
'选择后点击"发送"按钮即可修改设备频率。', + "(共" + str(FC_CHANNELS) + "个信道,信道0起始,即信道0对应" + FC_RANGE.split(" ~ ")[0] + ")。"
style_bullet "选择后点击\"发送\"按钮即可修改设备频率。",
))
story.append(Paragraph("全功率时段配置:", style_body))
story.append(Paragraph(
"设置全功率工作时间段:开始时间(0~23时)、持续时间(0~24时,0=关闭),"
'输入后点击"发送"按钮下发配置。',
style_bullet
))
story.append(Paragraph("激光控制:", style_body))
story.append(Paragraph(
'点击"打开"/"关闭"按钮控制激光开关;"自动关闭(min)"设置激光自动关闭时间(0=禁用),点击"设置"下发。',
style_bullet style_bullet
)) ))
story.append(Paragraph("查询与升级按钮:", style_body)) story.append(Paragraph("查询与升级按钮:", style_body))
story.append(Paragraph( story.append(Paragraph(
'点击"查询当前配置(para)"按钮,软件向设备发送para指令查询全部参数。' "点击\"查询当前配置(para)\"按钮,软件向设备发送para指令查询全部参数。"
'查询结果将自动解析并显示在下方参数信息区域。点击"设备升级"按钮可打开设备升级对话框。', "查询结果将自动解析并显示在下方参数信息区域。点击\"设备升级\"按钮可打开设备升级对话框。",
style_bullet style_bullet
)) ))
@@ -254,43 +261,36 @@ story.append(make_table(
["通信方式", "设备当前通信方式(CommInf)"], ["通信方式", "设备当前通信方式(CommInf)"],
["设备标识", "设备唯一标识(DeviceSign)"], ["设备标识", "设备唯一标识(DeviceSign)"],
["网关MAC", "所连接网关的MAC地址"], ["网关MAC", "所连接网关的MAC地址"],
["注册状态", "设备在网关上的注册状态"], ["注册状态", "设备在网关上的注册状态,自动显示为\"已注册\"或\"未注册\""],
["Lora频率", "当前Lora通信频率"], ["Lora频率", "当前Lora通信频率"],
], ],
col_widths=[4*cm, 12*cm] col_widths=[4*cm, 12*cm]
)) ))
story.append(Paragraph("4.4 低功耗配置区域", style_h2)) story.append(Paragraph("4.4 低功耗配置区域", style_h2))
story.append(Paragraph("显示设备的低功耗运行参数:", style_body)) story.append(Paragraph("显示设备的低功耗运行参数(由para指令返回的LpCfg字段解析而来):", style_body))
story.append(make_table( story.append(make_table(
["参数名称", "说明"], ["参数名称", "说明", "取值范围"],
[ [
["CI(采集间隔)", "传感器数据采集的时间间隔,单位:秒"], ["CI(采集间隔)", "传感器数据采集的时间间隔", "30~7200秒"],
["RI(上报时间)", "数据上报到网关的时间间隔,单位:分钟/时"], ["RI(上报时间)", "数据上报到网关的时间间隔", "5~720分钟"],
["EI(紧急上报间隔)", "紧急状态下数据上报的时间间隔,单位:分钟/时"], ["EI(紧急上报间隔)", "紧急状态下数据上报的时间间隔", "1~5分钟"],
["ET(紧急上报时长)", "紧急上报模式持续时间,单位:分钟/时"], ["ET(紧急上报时长)", "紧急上报模式持续时间", "10~120分钟"],
], ],
col_widths=[5*cm, 11*cm] col_widths=[4.5*cm, 7.5*cm, 4*cm]
))
story.append(Spacer(1, 6))
story.append(Paragraph(
"显示格式说明:CI以\"秒\"显示;RI/EI/ET以\"分钟\"显示,当数值≥60分钟时自动换算为\"X时X分钟\"格式(例如90分钟显示为\"1时30分钟\")。",
style_body
)) ))
story.append(Paragraph("4.5 功率与激光配置区域", style_h2)) story.append(Paragraph("4.5 通讯日志区域", style_h2))
story.append(Paragraph("显示通过para指令查询到的功率与激光运行参数:", style_body))
story.append(make_table(
["参数名称", "说明"],
[
["开始时间", "全功率工作时间段的开始时刻"],
["结束时间", "全功率工作时间段的结束时刻"],
["全功率时长", "全功率工作持续时间"],
["当前模式", "当前工作模式(全功率/低功耗)"],
["激光状态", "激光当前开关状态(ON/OFF)"],
["自动关闭", "激光自动关闭时间"],
],
col_widths=[5*cm, 11*cm]
))
story.append(Paragraph("4.6 通讯日志区域", style_h2))
story.append(Paragraph("界面底部,分为左右两部分:", style_body)) story.append(Paragraph("界面底部,分为左右两部分:", style_body))
story.append(Paragraph("日志窗口:实时显示串口通讯内容。不同类型信息用不同颜色区分:", style_body)) story.append(Paragraph(
"日志窗口:深色背景,实时显示串口通讯内容。不同类型信息用不同颜色区分:",
style_body
))
story.append(make_table( story.append(make_table(
["颜色", "含义"], ["颜色", "含义"],
[ [
@@ -302,7 +302,11 @@ story.append(make_table(
col_widths=[4*cm, 12*cm] col_widths=[4*cm, 12*cm]
)) ))
story.append(Spacer(1, 6)) story.append(Spacer(1, 6))
story.append(Paragraph('自定义指令:右侧面板可输入自定义AT指令,点击"发送"或按Enter键发送。', style_body)) story.append(Paragraph(
"清空日志:点击日志窗口下方的\"清空日志\"按钮可清除当前全部日志内容,便于新一轮操作的观察。",
style_body
))
story.append(Paragraph("自定义指令:右侧面板可输入自定义指令,点击\"发送\"或按Enter键发送,发送成功后输入框自动清空。", style_body))
# 5 操作指南 # 5 操作指南
story.append(Paragraph("5 操作指南", style_h1)) story.append(Paragraph("5 操作指南", style_h1))
@@ -311,18 +315,18 @@ story.append(Paragraph("5.1 连接设备", style_h2))
steps = [ steps = [
"将USB转RS485串口线连接到电脑USB接口。", "将USB转RS485串口线连接到电脑USB接口。",
"将RS485线的A、B端分别连接到传感器设备的RS485接口(注意A接A、B接B)。", "将RS485线的A、B端分别连接到传感器设备的RS485接口(注意A接A、B接B)。",
'启动软件,在"串口连接"区域点击"刷新"按钮扫描可用串口。', "启动软件,在\"串口连接\"区域点击\"刷新\"按钮扫描可用串口。",
"在下拉框中选择对应的COM口。", "在下拉框中选择对应的COM口。",
"确认波特率等参数与设备一致(默认9600, 8N1)。", "确认波特率等参数与设备一致(默认9600, 8N1,波特率可直接修改)。",
'点击"打开串口"按钮,按钮文字变为"关闭串口"即表示连接成功。通讯日志中将显示连接信息。', "点击\"打开串口\"按钮,按钮文字变为\"关闭串口\"即表示连接成功。通讯日志中将显示连接信息。",
] ]
for i, s in enumerate(steps, 1): for i, s in enumerate(steps, 1):
story.append(step(i, s)) story.append(step(i, s))
story.append(Paragraph("5.2 查询设备参数", style_h2)) story.append(Paragraph("5.2 查询设备参数", style_h2))
steps = [ steps = [
'确认串口已成功连接(按钮显示"关闭串口")。', "确认串口已成功连接(按钮显示\"关闭串口\")。",
'点击"查询当前配置(para)"按钮。', "点击\"查询当前配置(para)\"按钮。",
"软件将发送para指令,设备返回参数信息后自动解析。", "软件将发送para指令,设备返回参数信息后自动解析。",
"设备参数信息和低功耗配置区域将显示查询到的数值。", "设备参数信息和低功耗配置区域将显示查询到的数值。",
"Lora频率下拉框也会同步更新为当前设备频率。", "Lora频率下拉框也会同步更新为当前设备频率。",
@@ -333,9 +337,9 @@ for i, s in enumerate(steps, 1):
story.append(Paragraph("5.3 修改Lora信道频率", style_h2)) story.append(Paragraph("5.3 修改Lora信道频率", style_h2))
steps = [ steps = [
"确认串口已成功连接。", "确认串口已成功连接。",
'在"Lora 参数"区域的下拉框中选择目标信道频率。', "在\"Lora 参数\"区域的下拉框中选择目标信道频率。",
'点击"发送"按钮,软件将发送"lora fc <频率值>"指令。', "点击\"发送\"按钮,软件将发送\"lora fc <频率值>\"指令。",
'发送后建议点击"查询当前配置"验证修改是否成功。', "发送后建议点击\"查询当前配置\"验证修改是否成功。",
] ]
for i, s in enumerate(steps, 1): for i, s in enumerate(steps, 1):
story.append(step(i, s)) story.append(step(i, s))
@@ -344,48 +348,33 @@ story.append(Paragraph(
style_warning style_warning
)) ))
story.append(Paragraph("5.4 全功率时段配置", style_h2)) story.append(Paragraph("5.4 设备升级", style_h2))
story.append(Paragraph("设备升级用于通过通用串口升级协议(V1.1)对设备固件进行升级。升级期间请保持设备供电正常。", style_body))
steps = [ steps = [
"确认串口已成功连接。", "确认串口已成功连接。",
'在"参数配置"区域的"全功率时段配置"中输入开始时间(0~23)和持续时间(0~24,0=关闭)。', "点击\"参数配置\"区域中的\"设备升级\"按钮,打开设备升级对话框。",
'点击"发送"按钮下发配置。', "在对话框中点击\"浏览\"选择要更新的固件文件(.bin),并确认设备MAC地址(默认自动填充para查询到的本机MAC;格式为6字节横线分隔,例如 09-00-01-7F-FF-FF)。",
'发送后建议点击"查询当前配置"验证配置是否生效。', "点击\"开始升级\"按钮,软件复用当前串口连接并自动切换至9600bps升级波特率,向设备下发固件信息(包数、大小、CRC32校验值)。",
] "设备校验通过后逐包请求数据,软件按请求逐包下发固件;进度条显示\"n/m 包\"传输进度,升级日志显示握手/下发/完成等过程信息。",
for i, s in enumerate(steps, 1): "升级完成后串口自动恢复原波特率,可在同一对话框再次点击\"开始升级\"重复升级,无需关闭重开。",
story.append(step(i, s))
story.append(Paragraph("5.5 激光控制", style_h2))
steps = [
"确认串口已成功连接。",
'点击"打开"或"关闭"按钮控制激光开关。',
"如需要设置自动关闭时间,在\"自动关闭(min)\"框中输入分钟数(0=禁用),点击\"设置\"下发。",
'发送后建议点击"查询当前配置"验证激光状态。',
]
for i, s in enumerate(steps, 1):
story.append(step(i, s))
story.append(Paragraph("5.6 设备升级", style_h2))
story.append(Paragraph("设备升级用于通过通用串口升级协议对设备固件进行升级。升级期间请保持设备供电正常。", style_body))
steps = [
"确认串口已成功连接。",
'点击"参数配置"区域中的"设备升级"按钮,打开设备升级对话框。',
"在对话框中选择要更新的固件文件(.bin),并确认设备MAC地址(默认自动填充本机MAC)。",
'点击"开始升级"按钮,软件通过协议下发固件并向设备逐包传输。',
"握住安装、进度条显示传输进度;升级日志显示握手/下发/完成等过程信息。",
"升级完成后可在同一对话框再次点击\"开始升级\"重复升级,无需关闭重开。",
] ]
for i, s in enumerate(steps, 1): for i, s in enumerate(steps, 1):
story.append(step(i, s)) story.append(step(i, s))
story.append(Spacer(1, 6))
story.append(Paragraph( story.append(Paragraph(
"注意:升级过程中请勿断开串口或断电,否则可能导致设备无法正常启动。", "注意:升级过程中请勿断开串口或断电,否则可能导致设备无法正常启动。若设备长时间无响应(约10秒),升级将自动停止并提示未完成,可检查接线后重试。",
style_warning style_warning
)) ))
story.append(Paragraph(
"提示:升级期间设备输出的调试信息会以\"[设备]\"前缀转发到主界面通讯日志,可用于排查升级失败原因。",
style_body
))
story.append(Paragraph("5.7 发送自定义指令", style_h2)) story.append(Paragraph("5.5 发送自定义指令", style_h2))
steps = [ steps = [
"确认串口已成功连接。", "确认串口已成功连接。",
'在通讯日志区域右侧的"自定义指令"输入框中输入AT指令。', "在通讯日志区域右侧的\"自定义指令\"输入框中输入AT指令。",
'点击"发送"按钮或按Enter键发送。', "点击\"发送\"按钮或按Enter键发送,发送成功后输入框自动清空。",
"通讯日志中将显示发送的指令和设备的回应。", "通讯日志中将显示发送的指令和设备的回应。",
] ]
for i, s in enumerate(steps, 1): for i, s in enumerate(steps, 1):
@@ -393,21 +382,20 @@ for i, s in enumerate(steps, 1):
# 6 指令参考 # 6 指令参考
story.append(Paragraph("6 指令参考", style_h1)) story.append(Paragraph("6 指令参考", style_h1))
story.append(Paragraph("软件内置以下AT指令:", style_body)) story.append(Paragraph("软件界面涉及的指令如下:", style_body))
story.append(make_table( story.append(make_table(
["指令", "功能", "示例"], ["指令", "功能", "对应操作"],
[ [
["para", "查询设备全部参数", "para"], ["para", "查询设备全部参数", "点击\"查询当前配置(para)\"按钮"],
["lora fc <频率值>", "设置Lora信道频率(单位Hz)", "lora fc 433100000"], ["lora fc <频率值>", "设置Lora信道频率(单位Hz)", "在\"Lora 参数\"下拉框中选择频率后点击\"发送\",范围" + FC_RANGE + ";示例:lora fc " + FC_EXAMPLE],
["fpocfg <开始> <持续>", "设置全功率工作时间段(时,0=关闭)", "fpocfg 8 2"],
["laser on / off", "打开/关闭激光", "laser on"],
["laser time <min>", "设置激光自动关闭时间(0=禁用)", "laser time 10"],
["(自定义指令)", "在自定义指令输入框中输入任意指令", "—"],
], ],
col_widths=[5*cm, 6*cm, 5*cm] col_widths=[4.5*cm, 5.5*cm, 6*cm]
)) ))
story.append(Spacer(1, 6)) story.append(Spacer(1, 6))
story.append(Paragraph("说明:指令以回车换行(\\r\\n)结尾自动发送,无需手动添加。", style_body)) story.append(Paragraph(
"说明:指令以回车换行(\\r\\n)结尾自动发送,无需手动添加。此外,可在自定义指令框中手动输入设备支持的其他指令,发送\"<指令> ?\"可查看该指令的在线帮助。",
style_body
))
# 7 常见问题 # 7 常见问题
story.append(Paragraph("7 常见问题与故障排除", style_h1)) story.append(Paragraph("7 常见问题与故障排除", style_h1))
@@ -417,8 +405,8 @@ qa_items = [
"1. 检查USB转RS485线是否已插入电脑;\n" "1. 检查USB转RS485线是否已插入电脑;\n"
"2. 检查设备管理器中是否出现对应的COM口;\n" "2. 检查设备管理器中是否出现对应的COM口;\n"
"3. 确认USB转串口驱动已正确安装;\n" "3. 确认USB转串口驱动已正确安装;\n"
'4. 点击"刷新"按钮重新扫描。'), "4. 点击\"刷新\"按钮重新扫描。"),
('点击"打开串口"后提示连接失败', ("点击\"打开串口\"后提示连接失败",
"1. 确认该COM口未被其他软件占用(如串口助手、Keil等);\n" "1. 确认该COM口未被其他软件占用(如串口助手、Keil等);\n"
"2. 尝试拔插USB线后重试;\n" "2. 尝试拔插USB线后重试;\n"
"3. 尝试更换USB接口。"), "3. 尝试更换USB接口。"),
@@ -431,11 +419,11 @@ qa_items = [
"1. 确认传感器和网关使用相同的Lora信道频率;\n" "1. 确认传感器和网关使用相同的Lora信道频率;\n"
"2. 修改频率后需等待设备重新连接;\n" "2. 修改频率后需等待设备重新连接;\n"
"3. 可通过para命令验证当前频率设置。"), "3. 可通过para命令验证当前频率设置。"),
('参数信息区域显示 "-"', ("参数信息区域显示 \"-\"",
"1. 表示尚未查询或未收到设备回应;\n" "1. 表示尚未查询或未收到设备回应;\n"
'2. 请先点击"查询当前配置"按钮;\n' "2. 请先点击\"查询当前配置\"按钮;\n"
"3. 检查串口连接是否正常。"), "3. 检查串口连接是否正常。"),
('Windows提示"已保护你的电脑"无法运行', ("Windows提示\"已保护你的电脑\"无法运行",
"1. 点击更多信息;\n" "1. 点击更多信息;\n"
"2. 点击仍要运行按钮;\n" "2. 点击仍要运行按钮;\n"
"3. 此提示是因为exe未做代码签名,软件本身安全。"), "3. 此提示是因为exe未做代码签名,软件本身安全。"),
@@ -444,6 +432,11 @@ qa_items = [
"2. 确认固件文件为正确的.bin文件;\n" "2. 确认固件文件为正确的.bin文件;\n"
"3. 确认串口连接正常、设备供电稳定;\n" "3. 确认串口连接正常、设备供电稳定;\n"
"4. 查看通讯日志中的设备调试信息辅助排查。"), "4. 查看通讯日志中的设备调试信息辅助排查。"),
("升级进度长时间停留/中途停止",
"1. 软件在约10秒未收到设备响应时会自动停止升级,属正常保护机制;\n"
"2. 检查RS485接线是否松动、设备供电是否稳定;\n"
"3. 关闭升级对话框后重新打开重试;\n"
"4. 若多次失败,查看主界面通讯日志中\"[设备]\"前缀的调试信息定位原因。"),
] ]
for q, a in qa_items: for q, a in qa_items:
story.append(Paragraph("Q: " + q, style_q)) story.append(Paragraph("Q: " + q, style_q))
@@ -451,4 +444,4 @@ for q, a in qa_items:
# 生成PDF # 生成PDF
doc.build(story) doc.build(story)
print("说明书已生成: " + output_path) print("说明书已生成: " + output_path)
+6 -3
View File
@@ -18,6 +18,9 @@ import shutil
import subprocess import subprocess
from datetime import datetime from datetime import datetime
# 软件版本号
APP_VERSION = "V1.0.0"
def resource_path(relative_path): def resource_path(relative_path):
if hasattr(sys, '_MEIPASS'): if hasattr(sys, '_MEIPASS'):
@@ -28,7 +31,7 @@ def resource_path(relative_path):
class LaserTracingConfigApp: class LaserTracingConfigApp:
def __init__(self, root): def __init__(self, root):
self.root = root self.root = root
self.root.title("边坡变形监测-变形(位移)自动测量系统配置工具") self.root.title(f"边坡变形监测-变形(位移)自动测量系统配置工具(宽带版 {APP_VERSION})")
self.root.resizable(True, True) self.root.resizable(True, True)
icon_path = resource_path("传感器.ico") icon_path = resource_path("传感器.ico")
@@ -95,7 +98,7 @@ class LaserTracingConfigApp:
self._fc_display_to_value = {} self._fc_display_to_value = {}
self._fc_value_to_display = {} self._fc_value_to_display = {}
fc_displays = [] fc_displays = []
freq = 470100000 freq = 433100000
ch = 0 ch = 0
while freq <= 492600000: while freq <= 492600000:
display = f"信道{ch}: {freq / 1000000:.1f}MHz" display = f"信道{ch}: {freq / 1000000:.1f}MHz"
@@ -104,7 +107,7 @@ class LaserTracingConfigApp:
self._fc_value_to_display[str(freq)] = display self._fc_value_to_display[str(freq)] = display
freq += 500000 freq += 500000
ch += 1 ch += 1
self.lora_fc_display_var = tk.StringVar(value=self._fc_value_to_display.get("470100000", fc_displays[0] if fc_displays else "")) self.lora_fc_display_var = tk.StringVar(value=self._fc_value_to_display.get("433100000", fc_displays[0] if fc_displays else ""))
self.lora_fc_combo = ttk.Combobox(lora_frame, textvariable=self.lora_fc_display_var, self.lora_fc_combo = ttk.Combobox(lora_frame, textvariable=self.lora_fc_display_var,
values=fc_displays, width=20, state="readonly") values=fc_displays, width=20, state="readonly")
self.lora_fc_combo.grid(row=0, column=1, padx=2) self.lora_fc_combo.grid(row=0, column=1, padx=2)
+35
View File
@@ -0,0 +1,35 @@
# -*- coding: utf-8 -*-
# PyInstaller 版本信息文件(宽带版)
VSVersionInfo(
ffi=FixedFileInfo(
filevers=(1, 0, 0, 0),
prodvers=(1, 0, 0, 0),
mask=0x3F,
flags=0x0,
OS=0x40004,
fileType=0x1,
subtype=0x0,
date=(0, 0),
),
kids=[
StringFileInfo(
[
StringTable(
"080404b0",
[
StringStruct("CompanyName", ""),
StringStruct("FileDescription", "边坡变形监测-变形(位移)自动测量系统配置工具(宽带版 V1.0.0)"),
StringStruct("FileVersion", "1.0.0.0"),
StringStruct("InternalName", "laser_tracing_config"),
StringStruct("LegalCopyright", ""),
StringStruct("OriginalFilename", "边坡变形监测-变形(位移)自动测量系统配置工具(宽带版 V1.0.0).exe"),
StringStruct("ProductName", "边坡变形监测-变形(位移)自动测量系统配置工具"),
StringStruct("ProductVersion", "1.0.0.0"),
],
)
]
),
VarFileInfo([VarStruct("Translation", [2052, 1200])]),
],
)
Binary file not shown.