Procházet zdrojové kódy

docs: 整理项目交付与测试说明

main
suyu před 3 týdny
rodič
revize
644035ecee
6 změnil soubory, kde provedl 776 přidání a 130 odebrání
  1. +16
    -42
      docs/ai/handoff.md
  2. +2
    -2
      docs/architecture.md
  3. +154
    -0
      docs/二次开发/modbus优化处理.md
  4. +1
    -1
      docs/开发顺序.md
  5. +59
    -85
      docs/测试约定.md
  6. +544
    -0
      docs/用户使用/软件使用帮助.md

+ 16
- 42
docs/ai/handoff.md Zobrazit soubor

@@ -1,6 +1,6 @@
# 当前开发交接

> 更新日期:2026-08-22。本文件只保留当前状态和下一步;完成事项合并成结论,不追加按日期排列的开发流水账。
> 更新日期:2026-08-23。本文件只保留当前状态和下一步;完成事项合并成结论,不追加按日期排列的开发流水账。

## 当前状态

@@ -14,7 +14,7 @@
- HMI 页面宽高已支持编辑态页面属性设置;业务范围统一为宽 `320~1600`、高 `200~800`,默认新建页面为 `800×400`,页面缩小导致控件越界时由服务层原子拒绝
- HMI 控件属性面板的显示文本输入统一限制为 12 个字符;领域层工程文件文本上限仍为 4096 个 UTF-8 字节
- `docs/二次开发/` 是已有未跟踪资料,不能因当前任务删除
- 测试体系已建立统一 `app/tests/tests.pro` 聚合入口、分层 `.pri` 清单、公共 `TestSupport` fixture 和独立 `performance_tests` 目标;长期测试规则见 `docs/测试约定.md`
- 提交测试已收敛为 9 个功能自动化目标(Domain、Service、JSON 和 Fake PLC)、独立 `performance_tests` 性能目标以及真实 PLC 人工验收;不再保留 Qt UI 自动化目标,长期测试规则见 `docs/测试约定.md`
- 当前没有代码阻塞;实际设备 RUN 联动和离线演示均已完成,下一步是最终交付资料整理

## 已实现能力
@@ -39,17 +39,24 @@

## 最近完成

- 收敛提交测试体系:删除 Qt UI 自动化目标及其 2689 行测试代码,功能回归只保留 9 个 Domain、Service、JSON 和 Fake PLC 目标;性能测试改为通过 `-Suite Performance` 独立运行并输出 CSV,真实 PLC 继续人工实测和记录
- 整理寄存器仓库文件边界:`register_repository.h` 只保留访问契约和结果类型;新增 `virtual_register_repository.h/.cpp` 承载离线内存实现;应用与测试 qmake 清单及具体使用点均改为显式包含新头文件,PLC 仓库继续位于 `infrastructure`
- 调整控制逻辑网络生命周期:新建工程和新建逻辑不自动创建网络,首次实际编辑才创建网络 1;首次条件不生成隐式 `Wire`,首次横线只保存一格 `Wire(span=1)`,首次输出生成无条件输出网络;删除最后网络允许恢复为空逻辑
- 收窄梯形图导线投影:空网格和并联补线格不再绘制真实水平线,无输出网络不再绘制条件末端到输出槽的长线;保留网格、选择态和必要的模型导线
- 增加横线连续追加的十列边界处理,普通追加达到十列后自动新建下一网络;自动建网与编辑共用一条撤销记录,串联、并联领域表达式和执行语义保持不变
- 修复短并联支路右端断线:新增支路宽度小于主支路时,渲染层补齐支路输出到右侧汇合点的水平结构连接,保留空网格不落盘和不绘制无逻辑横线的规则
- 修复首次横线自动建网后撤销再插入失败:梯形图重载时清除已被撤销的过期当前网络 ID,横线可以再次自动创建网络
- 修复并联补线格选中后横线视觉消失:补线格继续使用分支插入目标,但在选中框上层按运行激活状态重画派生横线,普通空网格仍不绘制真实导线
- 修复横线单格选区建立并联旁路时误使用整条横线宽度:新增按横线表达式 ID 和列偏移处理的服务接口,选中范围会原子拆分前置、旁路和后置横线,旁路宽度严格等于选中格数
- 修复视觉连续横线由多个相邻 `Wire` 表达式组成时误提示“必须来自同一条横线”:服务层按同一串联路径的绝对列合并相邻横线网格,仍拒绝跨触点、跨并联支路和跳列选区
- 明确拒绝空白并联格直接建立并联支路或竖线连接;空白格与节点/横线混选时给出明确提示,真实节点和横线网格分别路由到对应编辑用例

- 统一梯形图可见横线网格交互:新网络空格、持久横线格和并联补线格都可直接点击添加条件;并联远端格会只保存必要的中间 `Wire(span)`,不改变空网络、JSON 或运行语义
- 新增 `LogicEditorService::insertConditionInBranchAtColumn()`,校验目标必须位于直属并联分支的视觉补线范围内,并保持失败回滚、脏标记和一次撤销语义
- 网络背景图元命中范围收窄到标题栏,点击线路内容区不再意外选中整条网络;删除网络仍可通过点击标题栏完成
- 修复梯形图编辑失败回滚后错误保留工程脏标记的问题:回滚同时恢复工程内容和操作前的 `modified_` 状态;保存后超出十列的条件插入不会再触发退出保存提示,已有未保存修改也不会被失败操作清除
- 根据编程器面向设备交付、调试和验证工程师的需求定位,不恢复旧的纯 HMI 操作员窗口;新增职责明确的 `RuntimeMonitorWindow`,承载离线和真机共用的完整运行监控大屏
- 主窗口已移除运行监控页签和运行时布局切换;点击离线或真机运行会弹出最大化监控窗口,右上角返回、关闭弹窗和应用退出分别按统一生命周期处理,且全应用只创建一份 `RuntimeMonitorWidget`
- 主窗口已移除运行监控页签和运行时布局切换;点击离线或真机运行会弹出最大化监控窗口,运行期间只允许监控界面内的返回按钮退出,系统窗口关闭路径被忽略,应用退出时才关闭顶层窗口,且全应用只创建一份 `RuntimeMonitorWidget`
- CTU/CTD 输出节点保持现有梯形图网格宽度,将 CV 和 PV 拆成带水平内边距的两行显示,避免 `D4000`、`32767` 等边界配置在右侧电源轨处被裁剪
- 报警列表标题输入上限为 12 个字符,报警文本输入上限为 20 个字符;运行消息保持单行并在空间不足时显示省略号
- 新建报警列表默认尺寸调整为 `360×136`,默认字号比应用字体小 2pt;运行态按当前页 1~5 条记录收缩高度,超过 5 条可通过表头按钮翻页且确认命中使用当前页索引
@@ -58,50 +65,17 @@
- HMI 页面属性面板新增宽度和高度编辑;`HmiEditorService::resizePage()` 复用页面边界校验并纳入撤销/重做,成功后画布和工程树尺寸摘要同步刷新;JSON 页面尺寸也统一按 `320~1600 × 200~800` 校验
- 属性面板新增颜色输入与选择按钮、字号、粗体、斜体;通过既有 `HmiEditorService::updateControl()` 原子提交并保留撤销/重做
- `HmiGraphicsItem` 统一应用文字外观,保留地址提示、按钮禁用色、指示灯状态色、控件边框和选中框的原有语义
- 更新工程格式和数量边界文档;新增领域、HMI 编辑服务、JSON 往返和主窗口 UI 测试
- 更新工程格式和数量边界文档;领域、HMI 编辑服务和 JSON 往返由自动化测试覆盖,主窗口工作流改为交付前人工验收
- 梯形图编辑器新增按绝对条件列插入和按横线单格替换的服务接口;UI 统一将空格、横线格、已有条件和无选择状态路由到对应编辑用例,选中条件后串联插入会优先替换紧邻的右侧横线格,再考虑扩展网络宽度
- 梯形图条件工具提示已明确支持在选中空网格或横线处插入;线圈等输出指令仍写入独立的固定输出槽

## 最近验证

- 2026-08-22 网络生命周期和空网格导线调整已通过 `logic_editor_service_tests`、`main_window_tests` 及完整 Release 功能回归(`domain_tests`、`alarm_service_tests`、`hmi_editor_service_tests`、`offline_simulation_service_tests`、`project_management_tests`、`register_monitor_service_tests`、`runtime_mode_service_tests`、`plc_runtime_tests`),Qt Release 主程序在 `build/release-network-lifecycle` 构建并链接成功;本次不涉及 PLC 通信,因此未连接真实 PLC
- 2026-08-22 复现并修复短并联支路右端断线:修复前新增图形回归断言失败,修复后 `main_window_tests` 和 `logic_editor_service_tests` Release 均通过;本次只涉及梯形图 UI 投影,不涉及 PLC 通信,因此未连接真实 PLC

- 2026-08-22 并联补线网格统一通过独立 Release 构建的 `logic_editor_service_tests` 和 `main_window_tests`;覆盖远端格自动补线、非法列原子拒绝、一次撤销、真实鼠标点击命中网格而非网络背景,以及插入后的剩余可点击横线
- 2026-08-22 Qt Release 主程序已在 `build/release` 重新构建并链接成功;本次改动仅涉及梯形图编辑服务和 UI 投影,不涉及 PLC 通信或真机运行,因此未连接真实 PLC
- 2026-08-22 已补齐 `HmiPage::validate()` 的页面最小尺寸校验,领域、编辑服务、JSON 和 UI 统一使用 `320~1600 × 200~800`;重新构建并运行全部 10 个 Release 功能测试目标,均通过
- 2026-08-22 页面领域校验修复后的 Qt Release 主程序已在 `build/release` 重新构建并链接成功;改动不涉及 PLC 通信,因此未连接真实 PLC
- 脏标记回滚修复已通过独立 Release 构建的 `logic_editor_service_tests`、`project_management_tests` 和 `main_window_tests`;新增覆盖保存后第 11 个条件插入失败以及已有脏状态下失败操作的回归测试;Qt Release 主程序重新构建成功
- 独立运行监控窗口改动已通过重新生成 qmake 构建后的 `main_window_tests`、`hmi_editor_service_tests`、`offline_simulation_service_tests`、`runtime_mode_service_tests` 和 `plc_runtime_tests`;主窗口测试覆盖最大化弹窗、唯一监控实例、主窗口布局不变、离线与模拟真机 HMI 写入、页面跳转、返回编辑、关闭弹窗、通信故障隐藏、重复进入刷新和应用退出
- 独立运行监控窗口改动后的 Qt Release 主程序已在 `build/runtime-monitor-window-release` 完整构建并链接成功
- 2026-08-20 使用 `COM3 / 9600 / 8E1 / 站号 1` 完成真实 PLC 安全读写:读取 `D4000=0`,临时写入并读回 `1`,随后恢复并读回 `0`;没有下载 PLC 程序,也没有执行切换 RUN 的动作
- 2026-08-21 用户使用 `json/motor_forward_reverse.json` 在已连接的真实 PLC 上完成 RUN 联动手动验收:通过运行监控 HMI 操作正转启动、反转启动和停止,并确认对应运行状态反馈正常;该项验证覆盖实际 PLC 内部程序、接线和现场负载,不由自动化替身测试替代
- 2026-08-21 在 Qt/MinGW 运行库 PATH 正确的独立环境中重新执行 10 个 Release 测试目标,全部通过:`alarm_service_tests`、`domain_tests`、`hmi_editor_service_tests`、`logic_editor_service_tests`、`main_window_tests`、`offline_simulation_service_tests`、`plc_runtime_tests`、`project_management_tests`、`register_monitor_service_tests`、`runtime_mode_service_tests`
- 2026-08-21 页面尺寸第一版改动通过 `hmi_editor_service_tests` 和 `main_window_tests`,覆盖原子越界拒绝、撤销/重做、页面属性面板提交和工程树尺寸摘要刷新;随后重新运行全部 10 个 Release 功能测试目标,均通过
- 2026-08-21 页面尺寸最终范围改动新增 JSON 显式边界覆盖:`319/1601` 宽度和 `199/801` 高度加载失败,`320×200` 与 `1600×800` 加载成功;全部 10 个 Release 功能测试目标再次通过
- 2026-08-21 页面尺寸最终范围改动后的 Qt Release 主程序已在 `build/release` 重新构建并链接成功
- 2026-08-21 本地综合演示工程 `json/all_ladder_components_demo.json` 原为 `1280×900`,已调整为 `1280×800`;现有控件仍完整位于页面内,所有本地 JSON 演示工程均符合新页面范围
- 2026-08-21 使用 `scripts/run_qt_tests.ps1 -Configuration Release` 重新构建并运行上述 10 个功能目标及独立 `performance_tests`;功能回归全部通过,性能目标包含 100 个控制逻辑扫描和 4001 个 M 寄存器访问基准
- 2026-08-21 在 `build/tests_aggregate` 对 `app/tests/tests.pro` 执行完整 Release 聚合构建,11 个测试目标(10 个功能目标和 `performance_tests`)全部成功生成可执行文件
- CTU/CTD 显示修复已通过 `main_window_tests`(`QT_QPA_PLATFORM=offscreen`)和 Qt Release 主程序重新构建;改动仅涉及梯形图 UI 投影,因此未连接真实 PLC
- 报警列表和分页改动已通过 `domain_tests`、`alarm_service_tests`、`hmi_editor_service_tests`、`project_management_tests` 和 `main_window_tests`;覆盖输入长度、默认五行尺寸、默认字号、运行态高度收缩、六条报警翻页和跨页确认
- HMI 控件属性文本输入上限改动已通过 Qt Release 功能回归和 `main_window_tests`;普通控件与报警列表均确认属性输入框最大长度为 12
- 报警列表改动后的 Qt Release 主程序已重新构建并链接成功;改动不涉及 PLC 通信、Modbus 地址或运行模式,因此未连接真实 PLC
- 默认工具栏布局改动已通过 `main_window_tests`(`QT_QPA_PLATFORM=offscreen`)和 Qt Release 主程序重新构建
- 批量删除并联支路回归已通过专项探针、`logic_editor_service_tests` 和 `main_window_tests`;逐个删除、删除完整支路和部分批量删除均保持有效
- 修复后全量测试目标均通过:`alarm_service_tests`、`domain_tests`、`hmi_editor_service_tests`、`logic_editor_service_tests`、`main_window_tests`、`offline_simulation_service_tests`、`plc_runtime_tests`、`project_management_tests`、`register_monitor_service_tests`、`runtime_mode_service_tests`
- 本次字体外观改动后的全量测试目标均通过,`main_window_tests` 使用 `QT_QPA_PLATFORM=offscreen` 覆盖了属性面板提交
- Qt Release 主程序已重新构建并链接成功
- `git diff --check` 通过
- 真实 PLC 已使用 `COM3 / 9600 / 8E1 / 站号 1` 验证首次读取、断线恢复和重新首读
- 2026-08-19 已读取 `D4000=0`,写入并读回 `1`,随后恢复并读回 `0`;没有下载 PLC 程序
- 本次修复只影响梯形图编辑结构归一化和删除校验,不涉及 PLC 通信或真机运行,因此没有重复写 PLC
- 运行界面此前的双投影生命周期测试已由独立顶层工程师运行监控窗口的唯一投影测试替代,不再构建或保留旧的纯 HMI 操作员窗口
- 本次窗口改动不改变 PLC 通信、Modbus 地址或寄存器读写实现;模拟真机 UI 路径已由假 PLC 仓库覆盖,真实 PLC 安全读写已在同日完成,因此未因窗口承载方式变化重复写设备
- 本次只修改静态 HMI 外观、领域校验和工程持久化,不改变 PLC 通信、Modbus 地址、寄存器读写或运行模式,因此未进行额外真机读写
- 梯形图网格专项覆盖了新网络 10 个点击目标、第五列和第十列插入、前置空档、持久横线首格/中格/末格/单格拆分、满横线连续替换 10 个触点、多网络、满列拒绝、非法配置、原子失败、撤销/重做,以及主窗口真实 `QAction` 点击链路;同时验证普通/置位/复位线圈复用同一固定输出节点,`logic_editor_service_tests` 和 `main_window_tests` 均通过
- 梯形图网格改动后的 `domain_tests`、`project_management_tests`、`offline_simulation_service_tests` 和 `runtime_mode_service_tests` 回归均通过,确认空网格不进入 JSON 或离线执行语义;Qt Release 主程序已在 `build/grid-feature-release` 完整构建并链接成功
- 本次梯形图改动仅涉及编辑服务和 UI 投影,不改变 PLC 通信、真机运行、Modbus 地址或寄存器读写,因此没有重复连接真实 PLC
- 2026-08-23 从当前工作区重新构建并通过 9 个 Release 功能目标:Domain、Service、JSON 和 Fake PLC 全部通过
- 独立性能基准通过:100 个控制逻辑扫描约 `0.145 ms`,4001 个 M 寄存器完整读写约 `0.052 ms`;CSV 位于 `build/tests/release/performance_tests/benchmark.csv`
- Qt Release 主程序已在 `build/release-submit/release/integrated_platform.exe` 构建并链接成功,`git diff --check` 通过
- 2026-08-20 使用 `COM3 / 9600 / 8E1 / 站号 1` 完成真实 PLC 安全读写:`D4000` 从原值 `0` 临时写入并读回 `1`,随后恢复并读回 `0`;未下载 PLC 程序,未执行 RUN 动作
- 2026-08-21 使用 `json/motor_forward_reverse.json` 完成真实 PLC RUN 联动人工验收:正转启动、反转启动、停止和运行状态反馈正常

## 待完成



+ 2
- 2
docs/architecture.md Zobrazit soubor

@@ -48,7 +48,7 @@ main.cpp -> UI + Services + Infrastructure
- 主窗口不保留运行监控页签,也不创建第二份监控控件;工程对象刷新和运行交互始终指向弹窗中的唯一实例
- 离线时显示可交互 HMI、软件梯形图轨迹和自由监控;真机时显示可交互 HMI 和自由监控,不能显示本地梯形图伪轨迹
- HMI 页面跳转、按钮和数值输入都通过同一份 `HmiNavigationService` 和活动寄存器仓库完成;离线写虚拟 M/D,真机写 PLC,仿真停止或通信不可用时禁止写入
- 运行监控的返回编辑按钮或窗口关闭按钮都请求 `MainWindow -> RuntimeModeService` 返回编辑态离线时先停止软件扫描,真机时保留 PLC 连接但撤销运行会话;应用退出时允许顶层窗口真正关闭
- 运行监控只能通过界面内的返回编辑按钮请求 `MainWindow -> RuntimeModeService` 返回编辑态;运行期间系统窗口关闭路径被忽略,离线时先停止软件扫描,真机时保留 PLC 连接但撤销运行会话;应用退出时允许顶层窗口真正关闭

## 工程模型与持久化

@@ -153,4 +153,4 @@ PLC 缓存只保存最后一次成功读回值。写请求受理后不乐观修
- 新数量边界必须进入 `project_limits.h`、数量边界文档和上下界测试
- 新 HMI 类型优先扩展 `hmi_control_registry`,专用交互留在对应服务和图元
- 不重新引入数据点表、自由线段、UI 直连串口或真机执行本地梯形图
- 自动化测试按风险覆盖领域、服务、存储、通信和 UI;真实串口、接线和设备 RUN 联动必须现场验证
- 自动化测试覆盖领域、服务、JSON 存储和 Fake PLC 通信状态;UI 工作流在交付前人工验收,真实串口、接线和设备 RUN 联动必须现场验证

+ 154
- 0
docs/二次开发/modbus优化处理.md Zobrazit soubor

@@ -0,0 +1,154 @@
不需要把所有底层 Modbus 细节都自己补一遍。基于当前项目的业务目标,建议分成“必须完善”和“暂时不用做”两类。

## 必须确认或完善的部分

### 1. 确认功能码和地址映射

必须用 XDH-60T4-E 手册确认:

```text
M 区是否对应 Coils
D 区是否对应 Holding Registers
M 区读写功能码是否支持
D 区读写功能码是否支持
地址是否使用 0 开始的原始地址
```

当前代码的方向是:

```text
M 区 -> Coils
D 区 -> Holding Registers
```

只要和设备手册一致,就不需要重新设计。

### 2. 确保 Qt 错误能正确转换成业务状态

当前已经能处理:

```text
连接失败
PLC 不响应
超时
串口断线
协议错误
读取失败
写入失败
```

这部分已经满足核心业务。

建议后续补充测试:

```text
每种 Qt 错误都能映射到正确的 PlcCommunicationError
错误后会停止轮询
错误后会撤销首读资格
真机运行时会退出编辑态
UI 能收到错误通知
```

### 3. 需要明确写入异常后的业务反馈

当前写入错误会进入 `Faulted`,这是安全的。

但最好确认 UI 能明确显示:

```text
写入请求失败
PLC 拒绝写入
写入后未读回目标值
```

也就是说,不要只显示“通信错误”,而要让用户知道是“写入失败”。

---

## 当前不必自行实现的部分

### 1. 不需要自己写 CRC 校验

Qt Modbus 已经负责:

```text
CRC 计算
CRC 校验
RTU 帧解析
异常响应识别
```

自己再写一套容易和 Qt 的通信流程冲突。

### 2. 不需要自己测量 3.5T 帧间隔

3.5T 是 Modbus RTU 底层帧边界规则,Qt 串口和 Modbus 层负责处理即可。

当前业务代码只需要处理:

```text
请求成功
请求超时
协议错误
读取失败
```

### 3. 不需要自己解析帧头、帧尾垃圾数据

除非现场经常出现:

```text
线路严重干扰
串口收到大量乱码
设备协议不标准
Qt 无法判断具体原因
```

否则没有必要把原始串口字节全部接管过来分析。

---

## 可以作为增强项的部分

如果以后要提升现场调试能力,可以增加:

```text
1. 保存 Qt 返回的 errorString()
2. 显示具体 Modbus 异常码
3. 记录请求区域、起始地址、数量和读写方向
4. 记录最近一次成功通信时间
5. 记录连续超时次数
6. 记录最近一次读失败地址
7. 区分“PLC 拒绝”与“线路超时”
8. 提供通信诊断日志
```

这些属于“诊断体验增强”,不是当前系统能否正常运行的基础功能。

## 结论

当前不建议为了“国际 Modbus 标准完整”而大改通信底层。

建议保持现在的分层:

```text
Qt Modbus:
负责 RTU 帧、CRC、3.5T、底层协议

PlcCommunicationService:
负责异步读写、轮询、超时、状态和恢复

业务层:
负责首读资格、缓存有效性、真机运行安全和 UI 反馈
```

目前最值得补的是:

```text
设备手册功能码和地址映射确认
Modbus 错误分类测试
写入失败和读回失败的清晰提示
通信诊断日志
```

而 CRC、3.5T、帧头帧尾这些,不需要在当前业务层重复实现。

+ 1
- 1
docs/开发顺序.md Zobrazit soubor

@@ -109,7 +109,7 @@

完成标准:核心流程可重复执行,异常有反馈,程序不会崩溃或误写 PLC。

完成情况:自动化回归已覆盖核心领域、编辑、存储、仿真、运行模式、PLC 缓存和主界面;真实串口和 STOP 安全读写已经完成,2026-08-21 由用户在已连接的 XDH-60T4-E 上完成 RUN 联动手动验收。自动化测试不能替代这项现场验证,因为它还依赖 PLC 内部程序、接线和实际负载。
完成情况:自动化回归已覆盖核心领域、编辑服务、JSON 存储、离线仿真、运行模式和 Fake PLC;主界面在交付前人工验收。真实串口和 STOP 安全读写已经完成,2026-08-21 由用户在已连接的 XDH-60T4-E 上完成 RUN 联动手动验收。自动化测试不能替代这项现场验证,因为它还依赖 PLC 内部程序、接线和实际负载。

## 12. 完成交付与演示



+ 59
- 85
docs/测试约定.md Zobrazit soubor

@@ -1,118 +1,92 @@
# 测试约定

文件是测试代码的长期约束。新增或修改测试时,先判断被验证的契约、所属生产层和运行环境,再决定测试文件和测试目标。测试数量不是质量指标,重复断言也不是覆盖率;每个测试必须能回答一个明确的失败问题
项目已经进入交付整理阶段,测试只保留能直接证明交付质量的三类内容:功能自动化测试、性能测试和真实 PLC 实测。测试数量不是质量指标,不重复验证同一个业务结论

## 测试目标
## 测试范围

项目测试分为四种用途,不能互相替代:

| 用途 | 证明什么 | 是否进入普通自动化回归 |
| 类型 | 证明内容 | 执行方式 |
| --- | --- | --- |
| 功能测试 | 业务规则、服务用例和用户工作流结果正确 | 是 |
| 性能测试 | 在固定代表性规模下满足时间、吞吐或资源预算 | 单独运行 |
| 真机/HIL 测试 | 串口、PLC 响应、接线和现场联动真实有效 | 手工执行 |
| 稳定性/故障测试 | 断线、超时、非法输入和恢复状态可控 | 是;真实设备部分除外 |

功能测试按生产边界分层:
| 功能自动化测试 | 领域规则、服务用例、JSON 工程、离线执行和 Fake PLC 状态机正确 | 提交前自动执行 |
| 性能测试 | 代表性工程扫描和边界规模寄存器访问性能 | 独立执行 |
| 真实 PLC 实测 | 串口、Modbus RTU、PLC 响应、接线和现场联动有效 | 人工执行并记录 |

```text
Domain -> Services -> Infrastructure -> UI -> E2E
```
不保留 Qt UI 自动化测试。界面是否可操作、布局是否正常和完整工作流由交付前人工验收确认;领域规则和业务结果由更稳定的 Domain、Service、JSON 和 Fake PLC 测试负责。

- `Domain`:纯模型和值对象规则,不依赖 Qt Widgets、文件系统或串口
- `Services`:业务用例、原子编辑、撤销重做、离线扫描和运行模式,使用内存仓库或 Fake
- `Infrastructure`:JSON 文件、PLC 缓存、Modbus 地址规划和错误分类
- `UI`:Qt Widgets 事件、动作、投影和窗口生命周期,使用 `QT_QPA_PLATFORM=offscreen`
- `E2E`:少量跨层用户主流程,不重复覆盖每一条领域边界
## 功能自动化测试

当前目标映射如下:
| 测试目标 | 主要契约 |
| --- | --- |
| `domain_tests` | 地址、模型、数量边界和运行前校验 |
| `alarm_service_tests` | 报警定义和运行记录生命周期 |
| `hmi_editor_service_tests` | HMI 编辑、原子删除、历史和导航 |
| `logic_editor_service_tests` | 结构化梯形图编辑、归一化和历史 |
| `offline_simulation_service_tests` | 扫描语义、定时器、计数器和故障 |
| `project_management_tests` | JSON 往返、非法文件和工程保存状态 |
| `register_monitor_service_tests` | 监视地址、读写和活动仓库 |
| `runtime_mode_service_tests` | 编辑、离线和真机状态转换 |
| `plc_runtime_tests` | PLC 缓存、轮询、错误恢复和 Fake gateway |

| 测试目标 | 所属层 | 主要契约 |
| --- | --- | --- |
| `domain_tests` | Domain | 地址、模型、边界和运行前校验 |
| `alarm_service_tests` | Services | 报警编辑和运行记录生命周期 |
| `hmi_editor_service_tests` | Services | HMI 编辑、原子删除、历史和导航 |
| `logic_editor_service_tests` | Services | 结构化梯形图编辑、归一化和历史 |
| `offline_simulation_service_tests` | Services | 扫描语义、定时器、计数器和故障 |
| `runtime_mode_service_tests` | Services | 编辑/离线/真机状态转换和准入条件 |
| `register_monitor_service_tests` | Services | 监视地址、读写和活动仓库 |
| `project_management_tests` | Infrastructure + Services | JSON 往返、非法文件和工程保存状态 |
| `plc_runtime_tests` | Infrastructure + Services | PLC 缓存、轮询约束、错误恢复和 Fake gateway |
| `main_window_tests` | UI | 编辑工作流、运行监控窗口和 UI 投影 |
| `performance_tests` | Performance | 代表性梯形图扫描和寄存器访问基准 |
同一规则只在成本最低、失败定位最清楚的层验证:

## 防止冗余
- Domain 验证数据和模型是否合法
- Service 验证一次业务操作如何改变模型、历史或寄存器
- JSON 验证工程文件能否严格保存、加载和拒绝非法内容
- Fake PLC 验证无需真实设备即可重复执行的缓存、首读、超时、断线和恢复逻辑

同一业务场景可以在多层出现,但断言必须不同:
如果两个测试的输入、执行路径和断言相同,只保留更低层的一个。一个测试函数只验证一个行为主题,多个上下界属于同一业务规则时可以放在一起。

- Domain 断言“什么配置合法”
- Service 断言“用例如何改变模型或寄存器”
- UI 断言“用户操作是否调用正确用例并显示结果”
- 真机断言“设备实际响应和现场动作是否正确”
功能测试统一运行:

如果两个测试的输入、执行路径和断言都相同,只保留更低层、更快且失败定位更清晰的那个。UI 测试不得重新复制领域边界矩阵;真机测试不得把软件执行器的内部语义再测一遍。

每个生产契约至少有一个主要测试负责人。跨层回归只保留一条关键链路,例如“运行监控按钮 -> 活动仓库 -> Fake PLC gateway”,不要在每个窗口测试中重复构造完整 PLC 状态机。

## 测试代码规范
```powershell
pwsh -NoLogo -NoProfile -File .\scripts\run_qt_tests.ps1 -Configuration Release
```

- 测试名称使用“对象_行为_结果”语义,例如 `project_rejectsDuplicatePageIds`
- 一个测试函数只验证一个行为主题;多个边界属于同一规则时可以放在同一函数
- 失败消息必须说明预期和业务含义,不能只写 `failed`
- Fixture 放在 `app/tests/support/`;只有语义确实不同的 Fake 才允许留在测试文件内
- `TestSupport::require` 和 `TestSupport::InMemoryProjectStorage` 是通用基础设施,不要重新定义同名版本
- 测试不得修改 `app/src` 生产代码来迁就断言;发现难以测试时,优先检查服务契约和依赖注入边界
- 测试不依赖测试执行顺序;每个函数建立自己的仓库、服务和工程状态
- 测试使用 UTF-8;中文错误消息和工程样例必须按 UTF-8 读取
`app/tests/tests.pro` 只聚合上述 9 个功能测试目标。测试构建输出放在 `build/`,不写入 `app/`。

当前历史测试仍使用轻量自定义 `main()`,后续新增测试优先使用 Qt Test:`QTEST_APPLESS_MAIN` 或 `QTEST_MAIN`、`private slots`、`QVERIFY/QCOMPARE` 和 `QBENCHMARK`。迁移旧测试时按测试目标逐步进行,不为了换框架重写无关业务覆盖。
## 性能测试

## qmake 组织
性能测试不混入普通功能回归,当前独立目标为 `performance_tests`:

- `app/tests/tests.pro` 是所有自动化目标的聚合入口
- `app/tests/pri/test_defaults.pri` 只放公共 qmake 配置
- `app/tests/pri/test_layers.pri` 只放按生产层分组的源码清单
- 测试 `.pro` 只选择自己需要的层变量,不得重新手写重复的 `../src` 清单
- 不把所有生产源码放入一个“大而全”测试库;测试目标应能反映真实依赖边界
- 构建输出放在 `build/`,不能写入 `app/`
- 100 个控制逻辑的一次软件扫描
- 4001 个 M 寄存器的一次完整写入和读取遍历

统一运行:
运行方式:

```powershell
pwsh -NoLogo -NoProfile -File .\scripts\run_qt_tests.ps1 -Configuration Release
pwsh -NoLogo -NoProfile -File .\scripts\run_qt_tests.ps1 -Configuration Release -Suite Performance
```

只构建聚合目标而不运行时,可在独立构建目录对 `app/tests/tests.pro` 执行 qmake 和 `mingw32-make`。UI 测试必须设置 `QT_QPA_PLATFORM=offscreen`
性能基准使用固定规模和 `QBENCHMARK`,不设置容易受机器差异影响的脆弱毫秒阈值。结果用于记录当前交付版本基线,不替代功能断言

## 性能测试
需要连续执行功能和性能测试时使用:

性能测试必须单独命名为 `*_performance` 或 `performance_tests`,使用固定规模输入和 `QBENCHMARK`。每个基准需要说明:
```powershell
pwsh -NoLogo -NoProfile -File .\scripts\run_qt_tests.ps1 -Configuration Release -Suite All
```

- 输入规模,例如 100 个控制逻辑、4001 个寄存器
- 测量对象,例如一次扫描或一次完整读写遍历
- 不纳入测量的准备工作
- 结果用途,是观察趋势还是有明确预算
## 真实 PLC 实测

性能基准不是功能断言,不能因为机器差异设置脆弱的毫秒硬阈值。功能前置校验可以使用 `QVERIFY`,但基准循环只测目标操作
真实 PLC 测试不写入自动化测试代码,也不进入 `tests.pro`。Fake PLC 测试只能证明软件状态机,不能代替串口、设备、接线和现场负载验证。

## 真机/HIL 测试
标准安全验证使用 `COM3 / 9600 / 8E1 / 站号 1` 或现场批准配置,并记录:

真实 PLC 测试不放入普通 `tests.pro` 的自动执行流程,也不使用自动化 Fake 测试冒充真机结论。真机测试必须记录:
1. PLC 的 STOP/RUN 状态、串口参数、接线和现场负载条件
2. 写入前读取的原值
3. 临时写入值及 PLC 读回结果
4. 恢复原值及再次读回结果
5. 是否涉及 PLC 内部程序和现场动作

- `COM3 / 9600 / 8E1 / 站号 1` 或实际批准的配置
- 测试前读取的原值、测试动作、读回结果和恢复结果
- STOP/RUN 状态、接线和现场负载条件
- 测试是否涉及 PLC 内部程序;本项目不下载或生成 PLC 程序
安全通信验证先在 STOP 状态读原值,测试后恢复并再次读回。未经确认接线、地址和负载,不执行 RUN 联动。本项目不生成、下载或修改 PLC 程序。

通信安全验证先读原值,测试后恢复并再次读回。未经确认接线和地址,不执行 RUN 联动。真机记录属于验收证据,不应把设备状态写进可重复的单元测试。
当前已完成的真机证据:

## 修改测试的决策流程
- `COM3 / 9600 / 8E1 / 站号 1` 下读取 `D4000=0`,临时写入并读回 `1`,恢复并读回 `0`
- 使用 `json/motor_forward_reverse.json` 完成 RUN 联动,正转启动、反转启动、停止和状态反馈正常

1. 写出要保护的业务契约和失败风险
2. 选择能以最低环境成本证明契约的层
3. 搜索现有测试,确认不是已有相同断言
4. 复用 `support/` fixture 和 `.pri` 层变量
5. 运行受影响目标,再运行完整自动化集合
6. 涉及 PLC 通信、运行模式或 UI 工作流时扩大回归,并在 `docs/ai/handoff.md` 记录未做真机测试的原因
## 提交前检查

提交前至少完成对应自动化测试、Release 构建和 `git diff --check`。性能结果和真机记录不替代功能测试结果,三者必须分别报告。
1. 运行 9 个 Release 功能测试目标
2. 单独运行 `performance_tests` 并保留基准输出
3. 构建 Qt Release 主程序
4. 按风险决定是否重新执行真实 PLC 实测;未重测时引用已有验收记录并说明原因
5. 运行 `git diff --check`

+ 544
- 0
docs/用户使用/软件使用帮助.md Zobrazit soubor

@@ -0,0 +1,544 @@
# 综合平台编程器用户使用帮助

> 适用版本:第一版(工程格式 `1.0`)
> 适用对象:设备调试、交付和验证人员
> 文档目的:帮助用户完成工程创建、HMI 配置、控制逻辑编辑、离线仿真和 PLC 真机联机

## 1. 先看懂这个软件

综合平台编程器把 HMI 画面、简化梯形图、寄存器监控和 PLC 通信放在同一个工程里。一般可以按下面的顺序使用:

1. 新建或打开一个工程。
2. 在 HMI 页面中添加按钮、指示灯、数值显示等控件,并配置 M/D 地址。
3. 在控制逻辑中编写需要验证的梯形图网络。
4. 保存工程,先进入离线运行检查逻辑。
5. 确认接线和 PLC 参数无误后,再连接真实 PLC 做真机运行。

软件有三种工作状态:

| 状态 | 适合做什么 | 数据来自哪里 | 能不能编辑工程 |
| --- | --- | --- | --- |
| 编辑态 | 新建工程、配置 HMI、编辑梯形图 | 不读取运行值 | 可以 |
| 离线运行态 | 不接 PLC 做逻辑仿真和画面联动 | 软件内部的虚拟 M/D | 不可以 |
| 真机运行态 | 与现场 PLC 联调和查看状态 | PLC 最近一次成功读回的 M/D | 不可以 |

有两点请先记住:

- 软件可以保存和仿真本地梯形图,但**不会生成、编译或下载 PLC 程序**。
- 真机运行时,PLC 内部已有程序是唯一的控制逻辑来源,软件不会执行本地梯形图,也不会把离线仿真的值自动写入 PLC。

## 2. 第一次打开软件

### 2.1 主窗口布局

打开软件后,主窗口通常包含以下区域:

- 顶部菜单:文件、编辑、运行、视图。
- 运行模式工具栏:编辑、离线运行、真机运行、PLC 配置和断开 PLC。
- HMI 编辑工具栏:添加 HMI 控件。当前正在编辑 HMI 页面时显示。
- 控制逻辑工具栏:新建网络、插入横线/竖线、并联支路、触点和输出指令。切换到“控制逻辑”页签后显示。
- 左侧“工程”树:管理 HMI 页面和控制逻辑。
- 中间编辑区:显示当前 HMI 页面或梯形图。
- 右侧“属性”面板:编辑当前页面、控件或逻辑节点的参数。
- 底部“输出”区域和状态栏:显示保存、运行、通信和错误提示。

> **截图占位:主窗口整体布局**
> 建议截取完整主窗口,能同时看到顶部菜单、运行模式工具栏、左侧工程树、中间 HMI 画布、右侧属性面板和底部输出区域

### 2.2 编辑工具的基本操作

- 选择对象:在画布或工程树中单击对象。
- 移动 HMI 控件:在编辑态下拖动控件,控件会被限制在页面范围内。
- 删除:选中对象后按 `Delete`,也可以使用“编辑 → 删除所选”。
- 清除选择:按 `Esc`,或使用“编辑 → 清除选择”。
- 撤销:`Ctrl+Z`。重做:`Ctrl+Y`。
- HMI 和梯形图分别维护编辑历史,撤销/重做针对当前正在查看的编辑页签。
- 进入离线或真机运行后,编辑工具会自动禁用;需要点击运行监控中的“返回编辑态”才能继续修改。

## 3. 工程管理

### 3.1 新建工程

1. 点击“文件 → 新建工程”,或按 `Ctrl+N`。
2. 在弹出的对话框中输入工程名称。
3. 确认后,软件会创建一个新的空工程,并自动准备一个默认 HMI 页面和一组控制逻辑。
4. 默认 HMI 页面大小为 `800 × 400`。控制逻辑刚创建时可以没有网络,第一次添加条件、横线或输出时才会生成网络。
5. 建议马上使用“文件 → 工程另存为”保存到一个容易找到的位置。

如果当前工程有未保存修改,新建工程前软件会先询问是否保存。选择“取消”可以放弃本次新建操作。

### 3.2 保存、另存为和加载

| 操作 | 菜单 | 快捷键 | 说明 |
| --- | --- | --- | --- |
| 保存工程 | 文件 → 保存工程 | `Ctrl+S` | 已经有文件路径时直接保存;第一次保存会转到另存为 |
| 工程另存为 | 文件 → 工程另存为 | `Ctrl+Shift+S` | 选择新的 JSON 文件路径,并把它作为当前工程文件 |
| 加载工程 | 文件 → 加载工程 | `Ctrl+O` | 选择工程 JSON 文件并替换当前工程 |

工程文件使用 JSON 格式,建议保留软件生成的 `.json` 文件,不要手工删除必填字段。当前版本只支持工程格式 `1.0`;格式不对、内容不完整或超出软件规则的文件会加载失败,当前打开的工程不会被替换。

软件标题栏出现 `*` 时,表示工程还有未保存修改。保存成功后,状态栏和底部输出区域都会显示结果。

### 3.3 使用左侧工程树

工程树分为“**HMI 页面**”和“**控制逻辑**”两部分。右键页面或逻辑项,可以看到对应操作:

- 新建页面:输入页面名称。
- 新建控制逻辑:输入逻辑名称。
- 重命名:修改页面或逻辑名称。
- 删除:删除选中的页面或逻辑。
- 上移、下移:调整页面顺序或逻辑顺序。
- 设为初始页面:指定进入运行态时首先显示的 HMI 页面。
- 启用/禁用控制逻辑:禁用的逻辑保留在工程中,但离线运行时不会扫描。

> **截图占位:工程树和右键菜单**
> 建议截取页面、逻辑、初始页标记以及右键菜单,帮助用户快速找到新建、重命名、排序和启停逻辑入口

注意事项:

- 已经存在页面时,不能删除最后一个页面。
- 某个页面被“页面跳转”控件引用时,不能直接删除该页面。先修改或删除跳转控件,再删除页面。
- 逻辑的顺序就是离线扫描顺序。前面的网络写入 M/D 后,后面的网络在同一扫描周期可以读到更新后的值。
- 禁用逻辑仍会保存,但不能用它来替代运行前检查。需要运行的逻辑请确认工程树中没有“已禁用”标记。

## 4. 编辑 HMI 页面

### 4.1 新建和选择页面

在左侧工程树中单击某个 HMI 页面,软件会切换到“HMI 页面”页签并显示该页面。页面标题和当前尺寸会显示在画布上方。

选中工程树中的页面后,右侧属性面板会显示“页面宽度”和“页面高度”:

- 宽度范围:`320~1600`。
- 高度范围:`200~800`。
- 修改数值后点击“应用页面尺寸”。
- 页面缩小后如果会让已有控件越出页面,软件会拒绝本次修改,原尺寸和控件位置保持不变。

> **截图占位:HMI 页面属性面板**
> 建议显示页面画布、页面尺寸摘要以及右侧“应用页面尺寸”按钮

### 4.2 添加控件

在 HMI 编辑工具栏中可以直接添加常用控件。工具栏空间不足时,点击“更多控件”按钮查看其他类型。

| 控件 | 作用 | 是否需要绑定 |
| --- | --- | --- |
| 按钮 | 向 M 位发送开、关、取反或瞬时 ON 操作 | M 地址 |
| 指示灯 | 根据 M 位显示开/关状态 | M 地址 |
| 数值显示 | 显示 D 寄存器的当前值,只读 | D 地址 |
| 数值输入 | 在运行态输入一个数值并写入 D 寄存器 | D 地址 |
| 文本 | 显示固定文字,不随寄存器变化 | 不需要 |
| 页面跳转 | 点击后切换到另一个 HMI 页面 | 选择目标页面 |
| 报警列表 | 显示当前运行中的报警记录 | 不绑定单个地址,报警条件在“报警配置”中设置 |
| 进度条 | 把 D 值按设定的最小值和最大值换算成百分比 | D 地址 |

新控件添加后会自动选中,右侧属性面板会显示“未绑定”或“未配置”。这不是软件故障,继续配置属性即可。

### 4.3 配置控件属性

选中画布中的控件后,在右侧属性面板中填写或修改以下内容:

- **控件 ID**:用于区分同一页面上的控件,通常保持软件自动生成的值即可。
- **显示文本**:控件显示的标题或提示文字。编辑界面最多输入 12 个字符。
- **X、Y、宽度、高度**:调整控件位置和大小。也可以直接在画布中拖动控件。
- **绑定区域、绑定地址**:按钮/指示灯选择 M,数值类控件和进度条选择 D,地址范围为 `0~4000`。
- **按钮操作**:选择“置 ON”“置 OFF”“取反”或“瞬时 ON”。
- **目标页面**:页面跳转控件必须选择一个已经存在的页面。
- **最小值、最大值、显示百分比**:只对进度条有效。最小值必须小于最大值。
- **字体颜色**:可以直接填写类似 `#E53935` 的颜色值,也可以点击“选择”。
- **字号**:范围为 `6~72`。
- **粗体、斜体**:按需要勾选。

填好后点击“应用属性”。如果输入内容不合法,软件会提示原因,并且不会留下半成品修改。

> **截图占位:HMI 控件属性配置**
> 建议选中一个按钮或数值输入控件,画面中同时显示绑定区域、地址、按钮操作、颜色、字号和“应用属性”按钮

### 4.4 编辑时和运行时的控件操作

编辑态下,HMI 控件主要用于选择、拖动和修改属性。进入运行态后,控件行为会变成实际操作:

- 按钮:按下按钮即可执行配置好的 M 位操作。选择“瞬时 ON”时,按下为 ON,松开后恢复 OFF。
- 指示灯:只读取 M 位,不产生写入。
- 数值显示:只显示 D 值,不产生写入。
- 数值输入:双击控件,在“输入数值”对话框中填写 `-32768~32767` 的整数并确认写入。
- 页面跳转:单击控件切换页面。
- 报警列表:单击未确认的报警记录可以确认;报警超过当前页可显示数量时,点击表头左右箭头翻页。
- 进度条:根据 D 值在最小值和最大值之间的位置显示百分比。

运行态中,按钮和数值输入只有在当前数据源可写时才会启用。真机通信故障或尚未完成首次读取时,写入入口会自动禁用。

## 5. 配置报警

### 5.1 新增报警定义

报警配置入口在 HMI 工具栏的“更多控件”菜单中,选择“报警配置”。打开窗口后按下面操作:

1. 选择地址区域:M 或 D。
2. 输入地址,范围为 `0~4000`。
3. 选择触发条件:
- M:`M 为 ON`。
- D:`D 大于等于阈值` 或 `D 小于等于阈值`。
4. D 报警需要填写阈值,范围为 `-32768~32767`。
5. 输入报警文本,编辑界面最多 20 个字符。
6. 点击“新增”。

表格中选中已有报警后,可以修改输入内容并点击“更新”,也可以点击“删除”移除定义。删除前软件会再次确认。

> **截图占位:报警配置窗口**
> 建议显示报警表格、地址区域、触发条件、阈值、报警文本以及新增/更新/删除按钮

### 5.2 在 HMI 中显示和确认报警

添加“报警列表”控件后,它会显示工程中所有报警定义在当前运行会话产生的报警记录。报警列表不需要再绑定 M 或 D 地址。

- 没有活动报警时,运行态的报警列表会隐藏。
- 有报警时,列表按当前控件大小显示记录,每页最多显示 5 条。
- 超过 5 条时,点击表头左右箭头切换页面。
- 点击未确认的报警行可以确认报警。
- 报警条件恢复后,该条记录会自动清除。
- 多个 HMI 页面放置报警列表时,共享同一组报警记录和确认状态。

## 6. 维护 M/D 软元件注释

如果希望在梯形图编辑和逻辑排查时看到地址含义,可以打开“视图 → 软元件注释”。

在窗口中:

1. 选择 M 或 D。
2. 输入地址 `0~4000`。
3. 填写注释,例如“启动按钮”“当前温度”。
4. 点击“保存”。
5. 需要删除时,先在表格中选中地址,再点击“删除”。

软元件注释只用于说明地址,不会改变寄存器值,也不会因为添加注释就自动加入 PLC 轮询。

## 7. 编辑控制逻辑(梯形图)

### 7.1 新建逻辑和网络

1. 在左侧工程树中右键“控制逻辑”,选择“新建控制逻辑”,输入逻辑名称。
2. 单击新逻辑,软件会切换到“控制逻辑”页签。
3. 点击工具栏的“新建网络”,在当前逻辑末尾创建一个网络。
4. 也可以不先点“新建网络”,直接添加条件、横线或输出,软件会在同一个操作中自动创建网络。

梯形图网络是从左到右的条件区和最右侧输出槽:

- 条件区最多 10 列。
- 输出指令固定放在第 11 列。
- 一个网络最多配置一个输出指令。
- 空网格只是可编辑位置,不代表已经保存了一条真实横线。
- 软件按结构自动连线,不支持任意拖动画自由线段。

> **截图占位:梯形图编辑区**
> 建议显示“新建网络、横线、竖线、并联支路、触点、输出”工具栏,以及一个包含串联和并联的示例网络

### 7.2 添加和配置条件

先在梯形图中单击目标网格或已有节点,再点击工具栏按钮。不同选择状态下,软件的插入位置如下:

- 选中空网格:把条件放到该列。
- 选中横线网格:用条件替换该格横线。
- 选中已有条件:在该条件后面串联插入。
- 没有选择:追加到当前网络末尾。

可用条件如下:

| 工具 | 作用 |
| --- | --- |
| 常开 | M 位为 ON 时导通 |
| 常闭 | M 位为 OFF 时导通 |
| 上升沿 | M 位从 OFF 变为 ON 时产生一个扫描周期的脉冲 |
| 下降沿 | M 位从 ON 变为 OFF 时产生一个扫描周期的脉冲 |
| T 触点 | 读取离线仿真中的定时器完成状态 |
| C 触点 | 读取离线仿真中的计数器完成状态 |
| D 比较 | 将 D 值与常量比较,支持等于、不等于、小于、小于等于、大于、大于等于 |

“常开”和“常闭”在工具栏上直接可见;上升沿、下降沿、T 触点和 C 触点在“更多触点”菜单中;“D 比较”在工具栏中直接可见。

添加节点后,选中节点并在右侧属性面板中修改地址、工作方式、比较运算和比较常量,最后点击“应用属性”。M、D、T、C 地址均使用 `0~4000` 范围。

### 7.3 设置网络输出

输出指令位于网络最右侧的固定输出槽。可用输出包括:

- **线圈**:网络导通时写入目标 M 位。
- **置位**:网络导通时把目标 M 置为 ON,并保持。
- **复位**:网络导通时把目标 M 置为 OFF。
- **TON**:非保持接通延时定时器。配置定时器编号和预设时间,范围为 `1 ms~86400000 ms`。
- **CTU**:按条件上升沿加计数。
- **CTD**:按条件上升沿减计数。
- **MOVE**:把常量或 D 寄存器的值写入目标 D。
- **ADD**:两个常量/D 值相加,结果写入目标 D。
- **SUB**:两个常量/D 值相减,结果写入目标 D。

点击 TON、CTU、CTD、MOVE、ADD 或 SUB 后,软件会打开配置对话框。按照对话框填写定时器/计数器资源、CV/PV、复位输入、操作数和目标 D 地址,再点击确定。

ADD/SUB 的结果按有符号 16 位数处理,超出 `-32768~32767` 时会压到边界值,不会因为一次溢出中止离线扫描。

### 7.4 建立并联支路

有两种常见方法:

1. 选中一段连续的条件节点,点击“并联支路”,在新支路中添加或配置触点。
2. 选中连续的横线网格,点击“竖线”(快捷键 `F12`),建立横线旁路和竖线连接。

并联操作要求选择范围连续,并且必须来自同一网络、同一支路。只选空白网格不能直接建立并联;如果选择不合法,软件会提示原因并回退整个操作。

### 7.5 横线、竖线和删除

| 操作 | 菜单/工具 | 快捷键 |
| --- | --- | --- |
| 插入横线 | 横线 | `F11` |
| 插入竖线和并联旁路 | 竖线 | `F12` |
| 删除横线 | 编辑 → 删除横线 | `Shift+F11` |
| 删除竖线及对应并联支路 | 编辑 → 删除竖线 | `Shift+F12` |
| 删除节点或网络 | 删除节点/网络,或按 `Delete` | `Delete` |

横线最多占用条件区 10 列。横线占满当前网络后,继续在没有选择的情况下追加横线,软件会自动在同一次操作中创建下一个网络,方便连续编辑。

### 7.6 网络注释和逻辑启停

- 单击网络标题后,点击“网络注释”,可以填写网络说明,例如“启动保持”“温度高报警”。
- 网络注释只建议写一行短说明。
- 右键左侧工程树中的逻辑项,可以在“禁用控制逻辑”和“启用控制逻辑”之间切换。
- 只有启用逻辑才会参与离线扫描。
- 只有条件、没有输出的网络属于未完成网络,不能进入运行态。
- 只有输出、没有条件的网络表示条件恒为真,进入运行后会周期性执行该输出。
- 删除最后一个网络后,逻辑可以恢复为空,软件不会自动留下一个看不见的网络。

## 8. 离线仿真

### 8.1 进入离线运行

进入离线运行前,先保存工程并检查以下内容:

- 需要读写的按钮、指示灯、数值控件和进度条已经绑定正确的 M/D 地址。
- 所有页面跳转控件都指向现有页面。
- 报警地址和阈值填写完整。
- 所有启用的控制逻辑都包含可运行的输出。
- CTU/CTD、TON、MOVE、ADD/SUB 等指令已经完成配置。

然后点击顶部“离线运行”,或选择“运行 → 离线运行”。如果工程未通过运行检查,软件会在状态栏或输出区域说明原因,修正后再试。

进入成功后,软件会弹出并最大化“运行监控”窗口,主编程器窗口会留在后面。

> **截图占位:离线运行监控窗口**
> 建议显示顶部“离线仿真 · 虚拟 M/D”、HMI 运行视图、梯形图运行状态、逻辑选择框和自由监控区域

### 8.2 使用离线运行监控

运行监控窗口通常分为三块:

- **HMI 运行视图**:操作按钮、双击数值输入、跳转页面和确认报警。
- **梯形图运行状态**:离线模式下显示软件逻辑的导通轨迹;有多组启用逻辑时可以在下拉框中切换查看。
- **自由监控**:临时添加 M/D 地址,查看或写入虚拟寄存器。

离线运行时:

- HMI 按钮写入的是虚拟 M,不会碰真实 PLC。
- 数值输入写入的是虚拟 D。
- 软件逻辑执行器按逻辑和网络顺序持续扫描。
- 梯形图的导通状态会反映在运行状态视图中。
- 可以通过自由监控直接改变虚拟 M/D,观察 HMI 和逻辑是否按预期变化。

### 8.3 返回编辑态

运行期间请点击运行监控顶部的“返回编辑态”按钮。系统窗口的关闭按钮在运行期间不会代替这个操作,避免用户误关窗口后仍以为已经退出运行。

返回编辑态后:

- 离线软件扫描会停止。
- HMI、逻辑和工程树重新恢复可编辑。
- 离线虚拟值只属于本次运行会话,不会自动保存到工程 JSON。

## 9. 自由监控

自由监控位于运行监控窗口下方,是临时查看寄存器的工具,不属于工程内容,不会写入工程 JSON。

### 9.1 添加监控地址

1. 在“起始地址”中输入 `M0` 或 `D0` 这样的地址。
2. 在“连续个数”中输入需要添加的数量,范围为 `1~64`。
3. 点击“添加”,也可以在地址输入框中按回车。
4. 软件会自动去重,已经存在的地址不会重复添加。

当前会话最多保留 64 个去重后的监控地址,地址范围仍为 `M0~M4000`、`D0~D4000`。

### 9.2 查看和写入

监控表包含“地址、类型、当前值、目标值、写入、状态”几列:

- M 地址的目标值选择 `OFF` 或 `ON`。
- D 地址的目标值填写有符号整数,范围为 `-32768~32767`。
- 点击对应行的“写入”按钮发送单点写入。
- 写入后不要只看按钮动作,要等待下一次轮询,在“当前值”中确认 PLC 或虚拟仓库已经读回目标值。
- 前一笔写请求还没有完成时,新的写请求可能会被拒绝,等待状态更新后再操作。

可以选中一行或多行后点击“删除”,也可以点击“清空”清除当前自由监控表。

> **截图占位:自由监控区域**
> 建议显示起始地址、连续个数、添加按钮、M/D 监控表以及一次写入后的状态提示

## 10. 连接真实 PLC

真机联机前请先确认现场接线、PLC 程序和设备状态。软件的真机功能是读写 M/D 寄存器,不负责配置 PLC 内部程序。

### 10.1 联机前检查

以 XDH-60T4-E 为例,常用接线和检查顺序如下:

1. PLC 已正常供电。
2. 使用 PLC 的 `COM2` RS-485 接口。
3. PC 通过 USB 转 RS-485 转换器连接 PLC。
4. 转换器 A 接 PLC A,转换器 B 接 PLC B。无响应时优先检查 A/B 是否接反。
5. 使用信捷官方工具把 PLC 的 COM2 配置为 Modbus RTU 从站,并确认站号、波特率、数据位、校验位和停止位。
6. 修改 PLC 串口参数后按设备要求重启 PLC,使设置生效。
7. 第一次联机建议在安全条件下先读取 M0、D0,再进行 HMI 联动。

> **截图占位:PLC RS-485 接线示意**
> 这张图建议放在正式交付版本中,标明 PC、USB 转 RS-485、PLC COM2、A/B 线序

### 10.2 配置和连接

在编辑态点击“运行 → PLC 配置”,或点击运行模式工具栏中的“PLC 配置”。对话框包含:

- 端口:选择或输入 PC 上的 COM 端口。
- PLC 站号:`1~247`。
- 波特率:`9600、19200、38400、57600、115200`。
- 数据位:`7` 或 `8`。
- 校验方式:无校验、奇校验或偶校验。
- 停止位:`1` 或 `2`。
- 响应超时:`100~30000 ms`。
- 失败重试:`0~5` 次。
- 轮询周期:`50~10000 ms`。

项目已用 `COM3 / 9600 / 8E1 / 站号 1` 做过安全读写验证,但实际使用时必须以现场 PLC 的真实配置为准,不能只因为示例参数可用就直接套用。

点击确定后,软件会先建立异步连接,再读取工程中 HMI、报警、梯形图和自由监控实际引用到的 M/D 地址。状态栏可能依次显示:

- PLC 正在连接。
- PLC 已连接,正在首次读取。
- PLC 已连接,首次读取完成。
- PLC 通信故障或 PLC 已断开。

> **截图占位:PLC 通信配置窗口**
> 建议显示端口、站号、9600、8、偶校验、1 停止位、超时、重试和轮询周期等字段

### 10.3 进入真机运行

连接成功后不要立即认为已经可以运行。必须等状态栏明确显示“PLC 已连接,首次读取完成”,再点击“真机运行”。

真机运行规则如下:

- 进入真机前必须完成本次连接的首次 M/D 读取。
- 真机运行使用 PLC 最近一次成功读回的缓存。
- HMI 按钮和数值输入会向真实 PLC 发起单点写入。
- 自由监控可以读写真实 PLC 的 M/D,但每次写入都要等待轮询确认。
- 真机运行不显示 PC 本地梯形图的伪运行轨迹,也不执行 PC 内的离线逻辑。
- 离线运行和真机运行不能直接互切。需要先点击“返回编辑态”,再切换到另一种运行模式。

真机联调时,建议先用 STOP 状态验证安全读写,确认接线、地址和现场负载后,再进行 RUN 联动。未经确认不要直接操作会影响设备动作的 M 地址。

### 10.4 断开 PLC 和通信故障处理

- 断开 PLC:选择“运行 → 断开 PLC”。如果当前处于真机运行,软件会先返回编辑态再断开连接。
- 物理断线、超时、协议错误或串口失效时,软件会停止正常轮询,并保留最后一次有效缓存值。
- 真机运行中发生通信故障,软件会立即退出真机运行,回到编辑态;通信恢复后也不会自动重新进入真机运行。
- 重新连接后必须重新完成一次完整首次读取,再点击“真机运行”。

## 11. 常见问题

### 11.1 点击“离线运行”没有进入

通常是工程还没有通过运行检查。请依次检查:

- HMI 的按钮、指示灯、数值显示、数值输入和进度条是否已经绑定 M/D。
- 页面跳转是否选择了现有页面。
- 启用的控制逻辑是否有输出。
- CTU/CTD、TON、MOVE、ADD/SUB 是否完成配置。
- 梯形图是否存在“只有条件、没有输出”的未完成网络。

错误原因会出现在状态栏、底部输出区域或弹出的提示框中。

### 11.2 “真机运行”按钮不能点击或进入失败

请检查:

- PLC 是否已经连接。
- 是否等待到“首次读取完成”。只显示“已连接,正在首读”还不够。
- 当前是否仍处于离线运行态。离线和真机不能直接切换,先返回编辑态。
- PLC 站号、串口参数和 PC 端口是否与现场一致。

### 11.3 HMI 控件不能拖动或属性不能修改

这通常表示当前处于离线或真机运行态。点击运行监控中的“返回编辑态”,回到主编程器后再修改。

### 11.4 PLC 已连接但没有数据

优先检查以下项目:

- USB 转 RS-485 转换器是否被其他软件占用。
- PLC 是否使用 COM2 的 Modbus RTU 从站模式。
- A/B 线是否接反。
- 站号、波特率、数据位、校验位、停止位是否完全一致。
- PLC 是否在修改串口参数后完成重启。
- 工程中是否使用了错误的 M/D 地址。软件使用从 `0` 开始的原始地址。

### 11.5 HMI 按钮点了但设备没有动作

先确认软件的写入状态和轮询读回值,再确认 PLC 内部程序是否把该 M 位作为动作条件。M 位本身只是软元件,软件不会直接驱动 PLC 输出,也不会替现场 PLC 生成梯形图程序。

### 11.6 报警列表没有显示

检查报警定义是否已经在“报警配置”中新增,并确认地址条件在运行时确实成立。报警列表在没有活动报警时会自动隐藏;报警恢复后对应记录也会消失。

### 11.7 工程文件无法打开

当前版本使用严格的 JSON `1.0` 格式。请优先使用软件的“保存工程/工程另存为”生成文件,不要把早期草稿格式、旧字段或手工拼接的 JSON 直接混用。文件内容不完整、格式版本不支持、地址越界或页面/控件越界时,加载会失败。

## 12. 常用范围速查

| 项目 | 范围 |
| --- | --- |
| M 地址 | `M0~M4000` |
| D 地址 | `D0~D4000` |
| D 数值、比较值、报警阈值 | `-32768~32767` |
| 页面宽度 | `320~1600` |
| 页面高度 | `200~800` |
| HMI 控件文字输入 | 最多 12 个字符 |
| 报警标题 | 最多 12 个字符 |
| 报警文本 | 最多 20 个字符 |
| 梯形图条件区 | 最多 10 列 |
| TON 预设时间 | `1 ms~86400000 ms` |
| 自由监控地址 | 最多 64 个去重地址 |
| PLC 站号 | `1~247` |
| PLC 响应超时 | `100~30000 ms` |
| PLC 失败重试 | `0~5` 次 |
| PLC 轮询周期 | `50~10000 ms` |

## 13. 推荐的完整使用流程

下面是一条比较稳妥的第一版使用流程,适合做项目演示或第一次配置设备:

1. 新建工程,输入工程名称并立即另存为 JSON 文件。
2. 在工程树中把默认页面重命名为“主操作页面”,按需要新建“参数页面”或“报警页面”。
3. 设置初始页面和页面尺寸。
4. 在 HMI 中添加按钮、指示灯、数值显示、数值输入和报警列表,逐个配置文本与 M/D 地址。
5. 在“报警配置”中新增 M/D 报警定义。
6. 在“控制逻辑”中新建逻辑和网络,添加触点、并联支路和输出,配置每个节点属性。
7. 添加 M/D 注释,方便后续排查。
8. 保存工程。
9. 点击“离线运行”,用 HMI 和自由监控改变虚拟 M/D,观察 HMI、报警和梯形图轨迹。
10. 点击“返回编辑态”,保存工程并准备现场联机。
11. 确认 PLC 接线和 Modbus 参数,打开“PLC 配置”并等待首次读取完成。
12. 在安全条件下先验证少量 M/D 读写,确认值能读回后再进入“真机运行”。
13. 真机联调结束后点击“返回编辑态”,需要断开时选择“断开 PLC”。

## 14. 安全提醒

- 真机操作前确认设备急停、负载和现场安全条件。
- 第一次写 PLC 前先读取原值,测试结束后恢复并再次读回确认。
- 未确认接线、站号和地址前,不要在 RUN 状态下操作会改变设备动作的 M 位。
- 不要把离线仿真结果当成 PLC 内部程序结果;真机模式只反映 PLC 实际读回值。
- 软件不下载 PLC 程序。需要修改 PLC 内部程序时,请使用信捷官方工具,并遵守现场控制流程。

Načítá se…
Zrušit
Uložit