diff --git a/generate_manual.py b/generate_manual.py
new file mode 100644
index 0000000..27cbfab
--- /dev/null
+++ b/generate_manual.py
@@ -0,0 +1,515 @@
+# -*- coding: utf-8 -*-
+"""
+生成《网关配置工具使用说明书》PDF
+"""
+import os
+from reportlab.lib.pagesizes import A4
+from reportlab.lib.units import mm, cm
+from reportlab.lib.colors import HexColor, white, black
+from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
+from reportlab.lib.enums import TA_CENTER, TA_LEFT, TA_JUSTIFY
+from reportlab.platypus import (
+ SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle,
+ PageBreak, KeepTogether, HRFlowable
+)
+from reportlab.pdfbase import pdfmetrics
+from reportlab.pdfbase.ttfonts import TTFont
+
+# ── 注册中文字体 ──────────────────────────────────────────────
+FONT_DIR = os.path.join(os.environ.get("WINDIR", r"C:\Windows"), "Fonts")
+FONT_NAME = "SimSun"
+FONT_BOLD = "SimHei"
+pdfmetrics.registerFont(TTFont(FONT_NAME, os.path.join(FONT_DIR, "simsun.ttc")))
+pdfmetrics.registerFont(TTFont(FONT_BOLD, os.path.join(FONT_DIR, "simhei.ttf")))
+
+# ── 颜色 ─────────────────────────────────────────────────────
+PRIMARY = HexColor("#1565C0")
+ACCENT = HexColor("#4CAF50")
+LIGHT_BG = HexColor("#E3F2FD")
+TABLE_HEAD_BG = HexColor("#1565C0")
+TABLE_ALT_BG = HexColor("#F5F5F5")
+BORDER_COLOR = HexColor("#BDBDBD")
+
+# ── 样式 ──────────────────────────────────────────────────────
+styles = getSampleStyleSheet()
+
+style_title = ParagraphStyle(
+ "CoverTitle", fontName=FONT_BOLD, fontSize=28, leading=40,
+ alignment=TA_CENTER, textColor=PRIMARY, spaceAfter=10 * mm
+)
+style_subtitle = ParagraphStyle(
+ "CoverSub", fontName=FONT_NAME, fontSize=14, leading=20,
+ alignment=TA_CENTER, textColor=HexColor("#616161"), spaceAfter=6 * mm
+)
+style_h1 = ParagraphStyle(
+ "H1", fontName=FONT_BOLD, fontSize=18, leading=26,
+ textColor=PRIMARY, spaceBefore=12 * mm, spaceAfter=4 * mm
+)
+style_h2 = ParagraphStyle(
+ "H2", fontName=FONT_BOLD, fontSize=14, leading=20,
+ textColor=HexColor("#1976D2"), spaceBefore=8 * mm, spaceAfter=3 * mm
+)
+style_h3 = ParagraphStyle(
+ "H3", fontName=FONT_BOLD, fontSize=12, leading=18,
+ textColor=HexColor("#388E3C"), spaceBefore=5 * mm, spaceAfter=2 * mm
+)
+style_body = ParagraphStyle(
+ "BodyCN", fontName=FONT_NAME, fontSize=10.5, leading=18,
+ alignment=TA_JUSTIFY, spaceAfter=2 * mm
+)
+style_note = ParagraphStyle(
+ "Note", fontName=FONT_NAME, fontSize=9.5, leading=16,
+ textColor=HexColor("#757575"), leftIndent=8 * mm, spaceAfter=2 * mm
+)
+style_toc = ParagraphStyle(
+ "TOC", fontName=FONT_NAME, fontSize=12, leading=22,
+ leftIndent=0, spaceAfter=1 * mm
+)
+style_toc_sub = ParagraphStyle(
+ "TOCSub", fontName=FONT_NAME, fontSize=11, leading=20,
+ leftIndent=10 * mm, spaceAfter=1 * mm
+)
+
+# ── 工具函数 ──────────────────────────────────────────────────
+LQ = "\u300c" # 左角括号
+RQ = "\u300d" # 右角括号
+
+def heading1(text):
+ return Paragraph(text, style_h1)
+
+def heading2(text):
+ return Paragraph(text, style_h2)
+
+def heading3(text):
+ return Paragraph(text, style_h3)
+
+def body(text):
+ return Paragraph(text, style_body)
+
+def note(text):
+ return Paragraph(text, style_note)
+
+def hr():
+ return HRFlowable(width="100%", thickness=0.5, color=BORDER_COLOR, spaceAfter=3 * mm)
+
+def make_table(headers, rows, col_widths=None):
+ data = [headers] + rows
+ wrapped = []
+ for i, row in enumerate(data):
+ wrapped_row = []
+ for cell in row:
+ if i == 0:
+ s = ParagraphStyle("th", fontName=FONT_BOLD, fontSize=10, leading=14,
+ textColor=white, alignment=TA_CENTER)
+ else:
+ s = ParagraphStyle("td", fontName=FONT_NAME, fontSize=9.5, leading=14,
+ alignment=TA_CENTER)
+ wrapped_row.append(Paragraph(str(cell), s))
+ wrapped.append(wrapped_row)
+
+ t = Table(wrapped, colWidths=col_widths, repeatRows=1)
+ style_cmds = [
+ ("BACKGROUND", (0, 0), (-1, 0), TABLE_HEAD_BG),
+ ("TEXTCOLOR", (0, 0), (-1, 0), white),
+ ("ALIGN", (0, 0), (-1, -1), "CENTER"),
+ ("VALIGN", (0, 0), (-1, -1), "MIDDLE"),
+ ("GRID", (0, 0), (-1, -1), 0.5, BORDER_COLOR),
+ ("TOPPADDING", (0, 0), (-1, -1), 4),
+ ("BOTTOMPADDING", (0, 0), (-1, -1), 4),
+ ("LEFTPADDING", (0, 0), (-1, -1), 6),
+ ("RIGHTPADDING", (0, 0), (-1, -1), 6),
+ ]
+ for i in range(1, len(data)):
+ if i % 2 == 0:
+ style_cmds.append(("BACKGROUND", (0, i), (-1, i), TABLE_ALT_BG))
+ t.setStyle(TableStyle(style_cmds))
+ return t
+
+# ── 构建文档 ──────────────────────────────────────────────────
+OUTPUT = os.path.join(os.path.dirname(os.path.abspath(__file__)), "网关配置工具使用说明书.pdf")
+
+doc = SimpleDocTemplate(
+ OUTPUT, pagesize=A4,
+ topMargin=20 * mm, bottomMargin=20 * mm,
+ leftMargin=20 * mm, rightMargin=20 * mm
+)
+
+story = []
+
+# ==================== 封面 ====================
+story.append(Spacer(1, 50 * mm))
+story.append(Paragraph("网关配置工具", style_title))
+story.append(Paragraph("使用说明书", style_title))
+story.append(Spacer(1, 15 * mm))
+story.append(HRFlowable(width="60%", thickness=2, color=PRIMARY, spaceAfter=6 * mm))
+story.append(Paragraph("适用于物联网网关设备的串口配置管理", style_subtitle))
+story.append(Spacer(1, 10 * mm))
+
+cover_info = [
+ ["软件名称", "网关配置工具"],
+ ["适用设备", "物联网网关(HC32F460 + 4G/Cat1 + Ethernet)"],
+ ["通信接口", "串口(UART),波特率 500000"],
+ ["运行环境", "Windows 7/10/11"],
+ ["文档版本", "V1.0"],
+]
+cover_table = Table(cover_info, colWidths=[40 * mm, 90 * mm])
+cover_table.setStyle(TableStyle([
+ ("FONTNAME", (0, 0), (0, -1), FONT_BOLD),
+ ("FONTNAME", (1, 0), (1, -1), FONT_NAME),
+ ("FONTSIZE", (0, 0), (-1, -1), 11),
+ ("TEXTCOLOR", (0, 0), (0, -1), PRIMARY),
+ ("ALIGN", (0, 0), (0, -1), "RIGHT"),
+ ("ALIGN", (1, 0), (1, -1), "LEFT"),
+ ("VALIGN", (0, 0), (-1, -1), "MIDDLE"),
+ ("TOPPADDING", (0, 0), (-1, -1), 6),
+ ("BOTTOMPADDING", (0, 0), (-1, -1), 6),
+ ("LEFTPADDING", (0, 0), (-1, -1), 8),
+ ("RIGHTPADDING", (0, 0), (-1, -1), 8),
+ ("LINEBELOW", (0, 0), (-1, -2), 0.3, BORDER_COLOR),
+]))
+story.append(cover_table)
+story.append(PageBreak())
+
+# ==================== 目录 ====================
+story.append(heading1("目 录"))
+story.append(hr())
+toc_items = [
+ ("1", "产品概述"),
+ (" 1.1", "功能简介"),
+ (" 1.2", "系统要求"),
+ (" 1.3", "软件界面总览"),
+ ("2", "快速入门"),
+ (" 2.1", "连接设备"),
+ (" 2.2", "查看网关配置"),
+ ("3", "功能详解"),
+ (" 3.1", "串口连接"),
+ (" 3.2", "查看配置(para)"),
+ (" 3.3", "通讯方式切换"),
+ (" 3.4", "ETH网络参数配置"),
+ (" 3.5", "Lora信道配置"),
+ (" 3.6", "低功耗配置"),
+ (" 3.7", "自定义指令"),
+ (" 3.8", "通讯日志"),
+ ("4", "指令参考"),
+ ("5", "常见问题(FAQ)"),
+ ("6", "注意事项"),
+]
+for num, title in toc_items:
+ s = style_toc if not num.startswith(" ") else style_toc_sub
+ story.append(Paragraph(f"{num} {title}", s))
+story.append(PageBreak())
+
+# ==================== 1. 产品概述 ====================
+story.append(heading1("1 产品概述"))
+story.append(hr())
+
+story.append(heading2("1.1 功能简介"))
+story.append(body(
+ f"网关配置工具是一款基于串口通信的物联网网关设备配置管理软件。通过本工具,用户可以方便地完成以下操作:"
+))
+story.append(Spacer(1, 2 * mm))
+
+features = [
+ ["功能模块", "说明"],
+ ["串口通信", "通过USB转串口连接网关设备,波特率500000,实时收发指令"],
+ ["配置读取", "一键读取网关全部参数,包括软件/硬件版本、MAC地址、电池状态、注册状态等"],
+ ["通讯方式切换", "支持Cat1(4G)和ETH(以太网)两种通讯方式的切换"],
+ ["ETH参数配置", "配置以太网相关参数:IP地址、端口、子网掩码、网关、服务器地址等"],
+ ["Lora信道配置", "选择并设置Lora通信信道频率(410.1MHz ~ 524.9MHz)"],
+ ["低功耗配置", "查看采集间隔、上报间隔、紧急上报等低功耗参数"],
+ ["自定义指令", "支持手动输入任意指令与网关交互"],
+ ["通讯日志", "实时显示发送和接收的通讯数据,便于调试"],
+]
+story.append(make_table(features[0], features[1:], col_widths=[35 * mm, 115 * mm]))
+story.append(Spacer(1, 3 * mm))
+
+story.append(heading2("1.2 系统要求"))
+req_rows = [
+ ["操作系统", "Windows 7 / 10 / 11(64位推荐)"],
+ ["接口", "USB接口(用于连接USB转串口线)"],
+ ["驱动", "USB转串口芯片驱动(如CH340/CP2102等)"],
+ ["运行依赖", "无需安装Python环境,直接运行可执行文件"],
+]
+story.append(make_table(["项目", "要求"], req_rows, col_widths=[35 * mm, 115 * mm]))
+
+story.append(heading2("1.3 软件界面总览"))
+story.append(body("软件界面自上而下分为以下几个区域:"))
+ui_rows = [
+ [f"{LQ}串口连接{RQ}区", "选择串口、刷新端口列表、打开/关闭串口连接"],
+ [f"基本指令区", f"查看配置、切换通讯方式(Cat1/ETH)的快捷按钮"],
+ [f"当前网关配置", f"显示网关读取到的各项参数(版本、MAC、电池、注册状态等)"],
+ [f"ETH网络参数", f"显示当前ETH网络参数(IP、端口、掩码、服务器地址等)"],
+ [f"低功耗配置", f"显示采集间隔、上报间隔等低功耗相关参数"],
+ [f"ETH参数配置", f"输入并发送ETH相关配置参数"],
+ [f"Lora信道配置", f"选择Lora信道并发送"],
+ [f"通讯日志", f"实时显示收发数据(蓝色=发送,橙色=接收)"],
+ [f"自定义指令", f"手动输入任意指令发送"],
+]
+story.append(make_table(["区域", "功能说明"], ui_rows, col_widths=[35 * mm, 115 * mm]))
+
+story.append(PageBreak())
+
+# ==================== 2. 快速入门 ====================
+story.append(heading1("2 快速入门"))
+story.append(hr())
+
+story.append(heading2("2.1 连接设备"))
+story.append(body("按照以下步骤连接网关设备:"))
+steps = [
+ "使用USB转串口线连接电脑与网关设备的调试串口;",
+ "确认电脑已安装对应的USB转串口驱动;",
+ f"启动{LQ}网关配置工具{RQ}软件;",
+ f"在{LQ}串口连接{RQ}区域,点击刷新按钮,扫描可用串口;",
+ "从下拉列表中选择对应的串口号(如COM3);",
+ "点击打开串口按钮,建立连接。",
+]
+for i, s in enumerate(steps, 1):
+ story.append(Paragraph(f"步骤{i}:{s}", style_body))
+story.append(Spacer(1, 2 * mm))
+story.append(note(f"连接成功后,按钮变为红色{LQ}关闭串口{RQ},状态栏显示已连接的串口号。"))
+
+story.append(heading2("2.2 查看网关配置"))
+story.append(body(
+ f"串口连接成功后,点击查看配置(para)按钮,软件将自动向网关发送{LQ}para{RQ}指令,"
+ f"网关返回配置信息后,界面各区域将自动更新显示当前参数值。"
+))
+
+story.append(PageBreak())
+
+# ==================== 3. 功能详解 ====================
+story.append(heading1("3 功能详解"))
+story.append(hr())
+
+# 3.1
+story.append(heading2("3.1 串口连接"))
+story.append(body("串口连接是使用本工具的前提。软件固定使用以下串口参数:"))
+serial_rows = [
+ ["波特率", "500000"],
+ ["数据位", "8"],
+ ["停止位", "1"],
+ ["校验位", "None(无校验)"],
+]
+story.append(make_table(["参数", "值"], serial_rows, col_widths=[40 * mm, 60 * mm]))
+story.append(Spacer(1, 2 * mm))
+story.append(note("如无法连接,请检查串口驱动是否正确安装,以及串口是否被其他程序占用。"))
+
+# 3.2
+story.append(heading2("3.2 查看配置(para)"))
+story.append(body(
+ f"点击{LQ}查看配置(para){RQ}按钮后,软件发送{LQ}para{RQ}指令,网关返回包含以下信息的配置数据块:"
+))
+para_rows = [
+ ["软件版本", "SoftWare V", "网关固件版本号"],
+ ["硬件版本", "HardWare V", "网关硬件版本号"],
+ ["网关MAC", "GateWay MAC", "网关唯一MAC地址"],
+ ["电池", "Battery", "当前电池电量"],
+ ["注册状态", "Register Status", "0=未注册,1=已注册"],
+ ["通讯方式", "CommInf", "当前通讯方式(Cat1/Eth)"],
+ ["读取间隔", "CommUnitReadInterval", "通讯单元读取间隔(秒)"],
+ ["Cat1 IMEI", "Cat1 IMEI", "4G模块IMEI号"],
+ ["Cat1 SIM", "Cat1 SIM", "SIM卡信息"],
+ ["Lora频率", "Lora fc", "当前Lora信道频率"],
+]
+story.append(make_table(["显示项", "指令关键字", "说明"], para_rows, col_widths=[30 * mm, 45 * mm, 75 * mm]))
+
+# 3.3
+story.append(heading2("3.3 通讯方式切换"))
+story.append(body("网关支持两种通讯方式,可通过快捷按钮切换:"))
+comm_rows = [
+ ["Cat1(comm cat1)", "comm cat1", "切换到4G/Cat1通讯模式"],
+ ["ETH(comm eth)", "comm eth", "切换到以太网通讯模式"],
+]
+story.append(make_table(["按钮", "发送指令", "说明"], comm_rows, col_widths=[40 * mm, 35 * mm, 75 * mm]))
+story.append(Spacer(1, 2 * mm))
+story.append(note(f"切换通讯方式后,需要重新点击{LQ}查看配置{RQ}刷新当前状态。ETH参数配置必须在ETH模式下进行。"))
+
+story.append(PageBreak())
+
+# 3.4
+story.append(heading2("3.4 ETH网络参数配置"))
+story.append(body(
+ f"ETH参数配置区域用于设置网关以太网相关的网络参数。必须先切换到ETH模式才能发送ETH相关指令。"
+))
+story.append(Spacer(1, 2 * mm))
+
+eth_rows = [
+ ["网关IP", "eth ip", "192.168.1.101", "网关本地IP地址"],
+ ["网关端口", "eth port", "10000", "网关本地端口号(1-65535)"],
+ ["服务器网关", "eth gw", "192.168.1.1", "网络网关地址"],
+ ["服务器IP", "eth dip", "192.168.1.100", "远端服务器IP地址"],
+ ["服务器端口", "eth dport", "8080", "远端服务器端口号(1-65535)"],
+]
+story.append(make_table(
+ ["参数名称", "指令前缀", "默认值", "说明"],
+ eth_rows, col_widths=[28 * mm, 25 * mm, 35 * mm, 62 * mm]
+))
+story.append(Spacer(1, 3 * mm))
+
+story.append(heading3("ETH配置流程"))
+eth_steps = [
+ f"点击ETH(comm eth)按钮切换到以太网模式;",
+ "在各输入框中填入目标参数值;",
+ "逐项点击发送按钮,将参数写入网关;",
+ f"最后点击应用ETH配置(eth apply)按钮,使配置生效。",
+]
+for i, s in enumerate(eth_steps, 1):
+ story.append(Paragraph(f"{i}. {s}", style_body))
+story.append(Spacer(1, 2 * mm))
+story.append(note(f"仅发送参数而未点击{LQ}应用ETH配置{RQ},参数不会生效。IP地址格式为 x.x.x.x,端口范围为1-65535。"))
+
+# 3.5
+story.append(heading2("3.5 Lora信道配置"))
+story.append(body(
+ "Lora信道配置用于设置网关的Lora无线通信频率。信道列表覆盖410.1MHz至524.9MHz范围,"
+ "频率间隔0.2MHz,共575个信道可供选择。"
+))
+story.append(Spacer(1, 2 * mm))
+
+story.append(heading3("操作步骤"))
+lora_steps = [
+ "在Lora信道下拉框中选择目标信道(显示信道编号和对应频率);",
+ f"点击发送按钮,发送{LQ}lora fc [频率值]{RQ}指令。",
+]
+for i, s in enumerate(lora_steps, 1):
+ story.append(Paragraph(f"{i}. {s}", style_body))
+story.append(Spacer(1, 2 * mm))
+
+lora_range = [
+ ["起始频率", "410.1 MHz(信道1)"],
+ ["终止频率", "524.9 MHz(信道575)"],
+ ["频率间隔", "0.2 MHz(200 kHz)"],
+ ["指令格式", "lora fc [频率值,单位Hz]"],
+]
+story.append(make_table(["项目", "值"], lora_range, col_widths=[35 * mm, 115 * mm]))
+
+# 3.6
+story.append(heading2("3.6 低功耗配置"))
+story.append(body(
+ f"低功耗配置显示网关的低功耗运行参数,这些参数通过{LQ}查看配置(para){RQ}指令读取,在{LQ}低功耗配置{RQ}分组框中显示:"
+))
+lp_rows = [
+ ["采集间隔(CI)", "传感器数据采集的时间间隔"],
+ ["上报间隔(RI)", "正常数据上报的时间间隔"],
+ ["紧急上报间隔(EI)", "紧急状态下的数据上报间隔"],
+ ["紧急上报时长(ET)", "紧急上报模式持续时长"],
+]
+story.append(make_table(["参数", "说明"], lp_rows, col_widths=[40 * mm, 110 * mm]))
+story.append(Spacer(1, 2 * mm))
+story.append(note("低功耗参数单位可能为秒(sec)或分钟(min),以网关返回的实际值为准。"))
+
+story.append(PageBreak())
+
+# 3.7
+story.append(heading2("3.7 自定义指令"))
+story.append(body(
+ "自定义指令区域允许用户手动输入任意指令与网关交互,适用于高级调试和特殊配置场景。"
+))
+story.append(Spacer(1, 2 * mm))
+
+custom_steps = [
+ "在指令输入框中输入要发送的指令文本;",
+ "按Enter键或点击发送按钮发送指令;",
+ "发送后输入框自动清空,回复数据将在通讯日志中显示。",
+]
+for i, s in enumerate(custom_steps, 1):
+ story.append(Paragraph(f"{i}. {s}", style_body))
+
+# 3.8
+story.append(heading2("3.8 通讯日志"))
+story.append(body("通讯日志区域实时显示与网关的通讯数据,采用深色背景方便阅读:"))
+log_rows = [
+ ["蓝色文字", "发送的指令(>>> 前缀)", "包含时间戳和发送的指令内容"],
+ ["橙色文字", "接收的数据(<<< 前缀)", "包含时间戳和网关返回的原始数据"],
+]
+story.append(make_table(["颜色", "类型", "说明"], log_rows, col_widths=[25 * mm, 45 * mm, 80 * mm]))
+story.append(Spacer(1, 2 * mm))
+story.append(note(f"点击{LQ}清空日志{RQ}按钮可清除当前日志内容。日志数据仅保留在内存中,关闭软件后自动清除。"))
+
+story.append(PageBreak())
+
+# ==================== 4. 指令参考 ====================
+story.append(heading1("4 指令参考"))
+story.append(hr())
+story.append(body("以下为网关配置工具使用的全部指令汇总:"))
+story.append(Spacer(1, 2 * mm))
+
+cmd_rows = [
+ ["para", "读取网关全部配置参数", "查看配置(para)"],
+ ["comm cat1", "切换到Cat1通讯模式", "Cat1(comm cat1)"],
+ ["comm eth", "切换到ETH通讯模式", "ETH(comm eth)"],
+ ["eth ip <IP>", "设置网关本地IP地址", "ETH参数配置"],
+ ["eth port <端口>", "设置网关本地端口号", "ETH参数配置"],
+ ["eth gw <IP>", "设置网络网关地址", "ETH参数配置"],
+ ["eth dip <IP>", "设置远端服务器IP", "ETH参数配置"],
+ ["eth dport <端口>", "设置远端服务器端口", "ETH参数配置"],
+ ["eth apply", "应用ETH配置参数", "应用ETH配置"],
+ ["lora fc <频率>", "设置Lora信道频率(Hz)", "Lora信道配置"],
+]
+story.append(make_table(
+ ["指令格式", "功能说明", "对应操作"],
+ cmd_rows, col_widths=[42 * mm, 58 * mm, 50 * mm]
+))
+story.append(Spacer(1, 3 * mm))
+story.append(note("所有指令以回车换行(\\r\\n)结尾。自定义指令区域可发送以上指令及网关支持的其他指令。"))
+
+story.append(PageBreak())
+
+# ==================== 5. 常见问题 ====================
+story.append(heading1("5 常见问题(FAQ)"))
+story.append(hr())
+
+faqs = [
+ ("Q1:打开串口失败怎么办?",
+ "1)检查USB转串口线是否正确连接;2)确认串口驱动已安装(设备管理器中可见COM口);"
+ f"3)确认该串口未被其他程序占用;4)尝试点击{LQ}刷新{RQ}重新扫描串口列表。"),
+ ("Q2:发送指令后没有回复?",
+ f"1)确认串口已成功打开(按钮显示红色{LQ}关闭串口{RQ});2)检查串口线RX/TX是否接反;"
+ "3)确认网关设备已上电且正常运行;4)尝试重新连接串口。"),
+ (f"Q3:ETH参数发送提示{LQ}请先切换到ETH模式{RQ}?",
+ f"ETH参数配置必须在ETH通讯模式下进行。请先点击{LQ}ETH(comm eth){RQ}按钮切换模式,"
+ "再进行ETH参数的发送。"),
+ ("Q4:修改ETH参数后未生效?",
+ f"修改ETH参数后,需要点击{LQ}应用ETH配置(eth apply){RQ}按钮,参数才会真正生效。"
+ "仅发送参数值而未应用,网关不会更新配置。"),
+ ("Q5:如何确认当前网关的通讯方式?",
+ f"点击{LQ}查看配置(para){RQ}按钮,在{LQ}当前网关配置{RQ}区域查看{LQ}通讯方式{RQ}字段,"
+ "显示为Cat1或Eth。"),
+ ("Q6:Lora信道列表很长,如何快速选择?",
+ "Lora信道下拉框支持鼠标滚轮滚动选择,也可以点击下拉后直接滚动浏览。"
+ "信道编号和频率一一对应,选择后点击发送即可。"),
+]
+for q, a in faqs:
+ story.append(Paragraph(f"{q}", style_body))
+ story.append(Paragraph(f"\u3000\u3000{a}", style_body))
+ story.append(Spacer(1, 2 * mm))
+
+story.append(PageBreak())
+
+# ==================== 6. 注意事项 ====================
+story.append(heading1("6 注意事项"))
+story.append(hr())
+
+warnings = [
+ "通讯模式切换:在进行ETH参数配置前,务必先切换到ETH通讯模式,否则参数发送将被拒绝。",
+ f"ETH配置应用:修改ETH网络参数后,必须点击{LQ}应用ETH配置{RQ}按钮才能使参数生效。",
+ "串口独占:同一串口在同一时间只能被一个程序打开,请确保使用前关闭其他可能占用串口的软件。",
+ "波特率固定:本工具固定使用500000波特率,与网关固件匹配,请勿尝试修改。",
+ "参数格式:IP地址需符合标准格式(如192.168.1.101),端口号范围为1-65535,否则发送可能失败。",
+ f"数据备份:修改配置前建议先通过{LQ}查看配置{RQ}记录当前参数,以便需要时恢复。",
+ "断电保护:配置修改后请确认网关已保存参数,避免在参数写入过程中断电。",
+ "驱动安装:首次使用需安装USB转串口芯片驱动(如CH340、CP2102等),具体型号取决于使用的转接线。",
+]
+for w in warnings:
+ story.append(Paragraph(f"\u26a0 {w}", style_body))
+ story.append(Spacer(1, 1 * mm))
+
+story.append(Spacer(1, 20 * mm))
+story.append(hr())
+story.append(Paragraph("\u2014 文档结束 \u2014", ParagraphStyle(
+ "End", fontName=FONT_NAME, fontSize=10, alignment=TA_CENTER,
+ textColor=HexColor("#9E9E9E")
+)))
+
+# ── 生成PDF ──────────────────────────────────────────────────
+doc.build(story)
+print(f"PDF已生成: {OUTPUT}")
diff --git a/网关配置工具使用说明书.pdf b/网关配置工具使用说明书.pdf
new file mode 100644
index 0000000..c67a23a
Binary files /dev/null and b/网关配置工具使用说明书.pdf differ