| @@ -13,7 +13,7 @@ | |||
| - HMI 和梯形图直接配置 M/D 地址,不依赖预先创建的数据点 | |||
| - `ActiveRegisterRepository` 在离线虚拟仓库与 PLC 缓存仓库之间切换 | |||
| - `PlcCommunicationService` 使用 Qt SerialBus 异步连接、轮询和单点写入,UI 不阻塞 | |||
| - 真机连接收集 HMI 和梯形图实际引用地址,按 M/D 分区并合并相邻地址读取 | |||
| - 真机连接收集 HMI、报警定义和梯形图实际引用地址,按 M/D 分区并合并相邻地址读取 | |||
| - 真机模式要求首次读取完成,不复制离线值,不运行 PC 软件逻辑执行器 | |||
| - 通信错误停止轮询并保留最后一次有效缓存,状态栏和日志显示错误 | |||
| - 通信故障立即撤销当前连接的首读资格;真机运行中发生故障会自动返回编辑态,重新进入真机前必须重新连接并完成新一轮首读 | |||
| @@ -28,14 +28,20 @@ | |||
| - 主窗口使用会话态当前页面 ID、当前逻辑 ID,所有编辑入口不再固定操作第一项 | |||
| - 工程持久化初始 HMI 页面;运行态由 `HmiNavigationService` 从初始页启动并处理本地 PageJump 导航 | |||
| - HMI 已开放不绑定寄存器的 `Label` 和独立 `PageJump` 创建入口,属性区按控件类型显示绑定、按钮操作或目标页面 | |||
| - HMI 已增加 AlarmList 和报警配置入口,支持 M ON、D 高限、D 低限,统一显示当前报警和确认状态;运行态无报警时隐藏,报警恢复后立即移除 | |||
| - 离线执行器按工程顺序扫描所有启用逻辑,禁用草稿不阻止运行;轨迹按逻辑 ID 隔离,运行工作台可切换当前投影 | |||
| - 梯形图已支持上升沿、下降沿、T 常开/常闭触点和非保持 TON;边沿只输出一个扫描周期,TON 按 `steady_clock` 计算实际 ET | |||
| - T 是 `T0~T4000` 的离线仿真内部资源,不读写 M/D,也不进入 Modbus 轮询;同一 T 只允许一个已启用 TON 驱动 | |||
| - 工程已支持 M/D 地址注释和 `LadderRung` 网络注释;地址注释只保存地址与文本,不混入当前值和引用状态 | |||
| - HMI 运行按钮已区分悬停、按下、释放和禁止写入外观,运行态不再显示编辑选中框,可写按钮使用手型光标 | |||
| - PLC 轮询集合已扩展为 HMI、梯形图和自由监控地址的并集,连接后可动态增删监控地址 | |||
| - PLC 轮询集合已扩展为 HMI、报警定义、梯形图和自由监控地址的并集,连接后可动态增删监控地址 | |||
| - 已在真实 `COM3 / 9600 / 8E1 / 站号 1` 上完成只读联机验证,项目通信服务可完成 M/D 首次读取并进入真机运行前置状态 | |||
| ## 关键决策 | |||
| - 工程格式继续使用 `1.0`,当前文件只保存 HMI 和梯形图表达式树,不保留 `dataPoints` 结构及兼容代码 | |||
| - 工程格式继续使用 `1.0`,当前文件保存 HMI、报警定义和梯形图表达式树,不保留 `dataPoints` 结构及兼容代码 | |||
| - 工程 `1.0` 直接要求 `alarmDefinitions`,不为缺少该字段的旧草稿增加迁移或默认值 | |||
| - AlarmList 不直接保存报警逻辑,项目级 `AlarmService` 统一管理运行状态;当前不设置提示、警告、故障等级 | |||
| - 当前 `1.0` 直接要求 `initialHmiPageId` 和 PageJump 的 `targetPageId`,开发阶段不为同版本旧草稿补默认值或迁移分支 | |||
| - 页面跳转保存目标页面稳定 ID,不保存名称或数组索引;编辑器当前页面和当前逻辑属于会话状态,不写入工程 | |||
| - 按钮操作是工程 `1.0` 的必填字段,不兼容或迁移缺少该字段的旧按钮数据 | |||
| @@ -44,12 +50,14 @@ | |||
| - 网格仅作为编辑投影,不进入工程格式;服务层把连续范围操作转换为规范化表达式树 | |||
| - 条件节点继续使用 `std::variant` 的独立配置类型,不向通用节点添加无关字段 | |||
| - HMI、梯形图和通信共享 `M0~M4000`、`D0~D4000` 地址范围 | |||
| - 已删除统一数据点表、主窗口数据点 Dock 和属性区数据点下拉框;软元件注释功能待后续按信捷业务单独设计 | |||
| - 已删除统一数据点表、主窗口数据点 Dock 和属性区数据点下拉框;M/D 注释作为独立的工程级地址元数据实现 | |||
| - PLC 读写使用从 `0` 开始的原始 Modbus 地址 | |||
| - HMI 写请求不乐观修改 PLC 缓存,由下一次轮询确认真实值 | |||
| - 真机运行时 PLC 内部程序是控制源,软件逻辑执行器保持停止 | |||
| - 真机运行不显示本地梯形图导通轨迹,避免把本地工程误表示为 PLC 内部程序的真实执行状态 | |||
| - 自由监控表属于当前调试会话,不进入工程 `1.0` JSON,不重新引入数据点表 | |||
| - 工程 `1.0` 直接要求顶层 `registerComments` 和每个网络的 `comment` 字段,不增加旧工程迁移或缺省兼容 | |||
| - 50 ms Qt 定时器只调度离线扫描;每个 TON 不创建独立 Qt 定时器,真机模式继续停止整个软件逻辑执行器 | |||
| ## 自动化验证 | |||
| @@ -64,9 +72,12 @@ | |||
| - `plc_runtime_tests` | |||
| - `main_window_tests` | |||
| - `register_monitor_service_tests` | |||
| - `alarm_service_tests` | |||
| `main_window_tests` 还覆盖 PLC 配置参数往返、独立配置弹窗入口,以及主窗口不再内嵌串口参数控件。 | |||
| 本轮边沿、TON 和注释实现增加了:上下沿一次扫描脉冲、不同逻辑同名边沿状态隔离、TON 到时与断开复位、多个 T 独立计时、网络顺序可见性、运行重启状态清理、T 引用完整性、M/D 与网络注释 JSON 往返、严格新字段缺失失败,以及 T 和纯注释地址不进入 PLC 轮询集合的覆盖。 | |||
| 本轮多页面和多逻辑实现增加了领域、服务、存储和主窗口集成覆盖:初始页约束、页面引用删除保护、页面/逻辑名称唯一性和顺序、禁用草稿逻辑、多逻辑扫描与轨迹隔离、严格 JSON `1.0` 必填字段、工程树选择切换、Label/PageJump 属性可见性、运行态页面跳转和逻辑轨迹选择。 | |||
| 2026-08-13 真机排查发现 `QModbusRtuSerialMaster::connectDevice()` 在当前 Windows | |||
| @@ -141,6 +152,14 @@ HMI 图元现已分离编辑选择与运行输入状态。运行按钮悬停时 | |||
| 后出现编辑选中框。主窗口测试使用真实鼠标按下和释放事件验证瞬时按钮写入、视觉状态切换、 | |||
| 手型光标、禁止写入和无运行选中框。 | |||
| 本轮新增最小报警闭环。项目级报警定义支持 M 位为 ON、D 值大于等于阈值、D 值小于等于 | |||
| 阈值;AlarmService 只维护当前报警的发生时间和确认状态,报警恢复后立即移除,多个 AlarmList 共享状态。 | |||
| 报警配置和列表展示分别由独立 Qt Designer 对话框与 HMI 图元完成,主窗口只协调服务。报警 | |||
| 地址已进入 PLC 聚合轮询。工程版本保持 `1.0`,`alarmDefinitions` 为必填字段,不增加兼容分支。 | |||
| 2026-08-17 使用 `COM3 / 9600 / 8E1 / 站号 1` 完成报警功能后的真机只读冒烟,成功读取 | |||
| `M0~M2 = OFF`、`D0 = 0`,测试结束后正常关闭串口。本次没有执行任何 PLC 写操作。 | |||
| ## 待完成事项 | |||
| 1. 在 PLC STOP 状态确认 COM2 参数和 RS-485 A/B 接线 | |||
| @@ -46,16 +46,17 @@ main.cpp -> UI + Services + Infrastructure | |||
| | `register_repository.*` | 定义 M/D 统一读写接口和离线内存实现 | | |||
| | `active_register_repository.*` | 在虚拟仓库与 PLC 缓存仓库之间切换当前数据源 | | |||
| | `register_monitor_model.*` | 保存当前调试会话的自由监控 M/D 地址集合 | | |||
| | `alarm_model.*` | 定义项目级 M ON、D 高限和 D 低限报警条件 | | |||
| | `hmi_model.*` | 定义页面、控件、布局和寄存器绑定 | | |||
| | `control_logic_model.*` | 定义梯形图表达式树、条件节点和输出线圈 | | |||
| | `project_model.*` | 聚合 HMI 页面和控制逻辑并执行工程校验 | | |||
| | `control_logic_model.*` | 定义梯形图表达式树、边沿/触点/比较/TON 节点和输出线圈 | | |||
| | `project_model.*` | 聚合 HMI 页面、报警定义和控制逻辑并执行工程校验 | | |||
| | `runtime_state.*` | 定义编辑、离线运行和真机运行状态机 | | |||
| 工程文件格式保持 `1.0`。当前 `1.0` 直接保存有序 `hmiPages`、`initialHmiPageId`、有序 `controlLogics` 和梯形图表达式树,不读取其他结构,也不包含迁移和兼容代码。加载必须先完成 JSON 解析、版本检查和领域校验,成功后才能替换当前工程;保存使用原子提交。完整字段定义见 `docs/工程格式说明.md`。 | |||
| 工程文件格式保持 `1.0`。当前 `1.0` 直接保存有序 `hmiPages`、`initialHmiPageId`、有序 `alarmDefinitions`、工程级 `registerComments`、有序 `controlLogics` 和梯形图表达式树,不读取其他结构,也不包含迁移和兼容代码。加载必须先完成 JSON 解析、版本检查和领域校验,成功后才能替换当前工程;保存使用原子提交。完整字段定义见 `docs/工程格式说明.md`。 | |||
| `HmiPage.id` 和 `ControlLogic.id` 是稳定内部标识,名称可修改,数组顺序分别决定工程树页面顺序和离线逻辑扫描顺序。`MainWindow` 保存 `current_hmi_page_id_` 与 `current_logic_id_` 作为编辑会话选择,它们不进入 JSON。`Project.initialHmiPageId` 是运行态每次启动 HMI 时使用的持久化初始页,与编辑器当前正在查看的页面相互独立。 | |||
| `Project::validate()` 允许未绑定控件、待配置节点和未完成网络作为编辑草稿保存。`Project::validateForRunning()` 额外拒绝未绑定 HMI、待配置节点、空条件和缺少输出的网络。 | |||
| `Project::validate()` 允许未绑定控件、待配置节点和未完成网络作为编辑草稿保存。`Project::validateForRunning()` 额外拒绝未绑定 HMI、待配置节点、空条件和缺少输出的网络,并检查已启用逻辑中的 T 触点必须有唯一的 TON 驱动。 | |||
| HMI 按钮操作作为工程 `1.0` 的强类型字段保存,支持 `置 ON`、`置 OFF`、`取反` 和 | |||
| `瞬时 ON`。新建按钮默认使用瞬时 ON;按钮按下和释放事件由 UI 转交运行服务解释,UI | |||
| @@ -63,6 +64,8 @@ HMI 按钮操作作为工程 `1.0` 的强类型字段保存,支持 `置 ON`、 | |||
| `Label` 是不绑定 M/D 的固定文本控件。`PageJump` 是独立控件,使用强类型 `targetPageId` 引用目标页面稳定 ID,同样不绑定 M/D。编辑态点击 PageJump 只执行选择和拖动;离线或真机运行态点击后由 `HmiNavigationService` 在本地切换运行页面,不发出 PLC 写请求,因此 PLC 通信写权限不可用时也不影响页面导航。被 PageJump 引用的页面不能删除,初始页必须先切换后才能删除,工程至少保留一个页面。 | |||
| `AlarmList` 是不绑定单个寄存器的运行状态投影。项目级 `AlarmDefinition` 只支持 M 位为 ON、D 值大于等于阈值和 D 值小于等于阈值三种条件,不设置提示、警告、故障等级。`AlarmEditorService` 负责定义增删改,`AlarmService` 统一读取活动寄存器仓库并维护当前报警的发生时间和确认状态,所有页面上的 AlarmList 共享这份状态。报警条件恢复后立即删除对应运行记录;运行态没有报警时 AlarmList 隐藏,出现报警时显示并置顶。返回编辑态时清空运行记录,工程 JSON 只保存报警定义。 | |||
| ## 结构化梯形图 | |||
| 网络条件采用递归表达式: | |||
| @@ -88,23 +91,25 @@ Parallel | |||
| `LogicEditorWidget` 将表达式树投影到固定行列网格,串联节点横向占列,并联分支纵向占行,所有连接只使用水平线和竖线。用户只选择画布中可见的节点:单击定位当前节点,橡皮框或多选连续节点后可直接建立并联支路。内部 `Series / Parallel` 容器不作为可选 UI 对象暴露。网格是编辑投影,不持久化自由线段,因此不会产生悬空线、环路和多输出路径。 | |||
| 工具栏中的常开、常闭和比较条件在没有选择时追加到当前网络末尾,选中一个条件节点时插入到该节点后。并联支路按钮默认建立常开触点,下拉菜单可选择常闭触点或比较条件。新增节点保持待配置状态,并自动选中供属性区继续编辑。 | |||
| 工具栏中的常开、常闭、上升沿、下降沿、T 触点和比较条件在没有选择时追加到当前网络末尾,选中一个条件节点时插入到该节点后。并联支路按钮默认建立常开触点,下拉菜单可选择常闭、边沿、T 触点或比较条件。新增节点保持待配置状态,并自动选中供属性区继续编辑。 | |||
| 条件节点使用 `std::variant` 保存独立配置类型,当前包含 M 常开/常闭触点和 D 值与常量比较。输出支持普通、置位和复位 M 线圈。新增节点类型时应增加独立配置类型及校验、存储和执行分支,不能向通用节点堆叠无关字段。 | |||
| 条件节点使用 `std::variant` 保存独立配置类型,当前包含 M 常开/常闭触点、M 上升沿/下降沿触点、T 常开/常闭触点和 D 值与常量比较。输出支持普通、置位、复位 M 线圈和非保持 TON。边沿节点在每个扫描周期比较当前 M 值与该逻辑节点自己的上一扫描值,只产生一个扫描周期的脉冲。T 地址是 `T0~T4000` 的离线资源,不是 M/D 地址。新增节点类型时应增加独立配置类型及校验、存储和执行分支,不能向通用节点堆叠无关字段。 | |||
| ## 执行与运行反馈 | |||
| `SoftwareLogicExecutor` 按 `controlLogics` 数组顺序扫描所有已启用逻辑,再按网络顺序递归求值 `Node / Series / Parallel`。禁用逻辑仅保留结构校验,未完成的禁用草稿不会阻止离线运行。普通线圈每周期写入网络结果,置位和复位线圈只在网络成立时写入;前面逻辑或网络的写入对后面逻辑和网络在同一扫描周期立即可见。 | |||
| 上升沿和下降沿是标准的一次扫描脉冲,运行状态按逻辑 ID 和节点 ID 隔离。TON 是正常非保持接通延时:输入接通后记录 `steady_clock` 起点,`ET` 使用实际经过的毫秒数,达到 `PT` 后 `Q` 为真;输入断开立即清零 `ET/Q`。TON 的输出状态保存在离线执行器的 T 资源表中,T 触点只读取对应 TON 的 `Q`。软件不为每个 TON 创建 Qt `QTimer`,现有 50 ms `QTimer` 只负责扫描调度,因此不会与 Qt 事件循环或 PLC 轮询形成额外定时器线程。 | |||
| 每次扫描生成按逻辑 ID 分区的 `LogicTraceSnapshot`,记录节点、表达式、网络和线圈的导通状态,避免不同逻辑中重复的 `rung-1`、`contact-1` 相互覆盖。运行工作台的逻辑下拉框只切换当前轨迹投影,所有已启用逻辑仍持续执行。逻辑画布以绿色显示导通节点和路径;执行错误携带逻辑、网络和节点上下文,画布选择并以红色突出故障位置。 | |||
| `OfflineSimulationService` 以 50 ms 目标周期驱动扫描,启动时复制逻辑快照并清空虚拟 M/D。故障后停止扫描并保留最终寄存器值,HMI 可继续显示但禁止写入。该周期不提供硬实时保证。 | |||
| `OfflineSimulationService` 以 50 ms 目标周期驱动扫描,启动时复制逻辑快照、清空虚拟 M/D 并重置边沿和 T 运行状态。故障或停止后清理这些运行状态;重新启动不会继承上次边沿历史或 TON 的 ET/Q。该周期只提供调度精度,不提供硬实时保证。 | |||
| ## M/D 地址使用 | |||
| HMI 控件和梯形图节点直接绑定 `M0~M4000`、`D0~D4000` 地址,不要求预先创建数据点。地址是程序和通信的真实标识,属性面板只编辑区域与地址。 | |||
| 软元件注释、网络注释和命令语视图不属于当前实现。后续如增加注释,应把地址级软元件注释和网络级说明分开建模,不能重新引入“名称、注释、当前值、引用位置”混合的数据点表。 | |||
| 工程级 `registerComments` 只保存 M/D 地址和注释文本,作为地址元数据供编辑器和注释对话框使用,不保存当前值、引用位置或缓存状态,也不会因为存在注释而加入 PLC 轮询。`LadderRung.comment` 保存单个网络的说明文本。两者在 JSON 中分开建模,不能重新引入混合“名称、注释、当前值、引用位置”的数据点表。 | |||
| ## 自由监控与运行工作台 | |||
| @@ -134,8 +139,8 @@ HMI 控件和梯形图节点直接绑定 `M0~M4000`、`D0~D4000` 地址,不要 | |||
| - 真机运行使用 `PlcRegisterRepository` 的最近一次有效缓存 | |||
| `PlcCommunicationService` 使用 `QModbusRtuSerialMaster` 异步连接、读取和写入。轮询集合由 | |||
| HMI 引用、梯形图引用和自由监控地址合并而成,去重后按区域合并相邻地址。M 使用线圈,D | |||
| 使用保持寄存器;所有 Modbus 地址均为从 `0` 开始的原始地址。 | |||
| HMI 引用、报警定义、梯形图中的 M/D 引用和自由监控地址合并而成,去重后按区域合并相邻地址。 | |||
| T 触点、TON 和工程级注释不会进入该集合。M 使用线圈,D 使用保持寄存器;所有 Modbus 地址均为从 `0` 开始的原始地址。 | |||
| PLC 连接后可以动态增删自由监控地址。存在读取请求时,新的轮询集合在当前响应处理完成后 | |||
| 应用,旧响应仍按发出时的读取块解析。连接级首次读取完成后,动态增加地址不会撤销真机 | |||
| @@ -13,11 +13,13 @@ | |||
| "name": "包装线", | |||
| "hmiPages": [], | |||
| "initialHmiPageId": "", | |||
| "alarmDefinitions": [], | |||
| "registerComments": [], | |||
| "controlLogics": [] | |||
| } | |||
| ``` | |||
| 所有顶层字段必填。空工程允许 `hmiPages` 和 `controlLogics` 为空,此时 `initialHmiPageId` 必须为空。存在页面时,`initialHmiPageId` 必须引用 `hmiPages` 中的页面 ID。 | |||
| 所有顶层字段必填。空工程允许 `hmiPages`、`alarmDefinitions`、`registerComments` 和 `controlLogics` 为空,此时 `initialHmiPageId` 必须为空。存在页面时,`initialHmiPageId` 必须引用 `hmiPages` 中的页面 ID。 | |||
| `hmiPages` 与 `controlLogics` 都是有序数组。页面顺序用于工程树显示;控制逻辑顺序是离线扫描顺序。对象 ID 稳定且唯一,名称可修改且在同类对象中唯一。 | |||
| @@ -45,6 +47,7 @@ | |||
| | `numericInput` | D 地址或 `null` 草稿 | 无 | | |||
| | `label` | 必须为 `null` | 无 | | |||
| | `pageJump` | 必须为 `null` | `targetPageId` | | |||
| | `alarmList` | 必须为 `null` | 无 | | |||
| 按钮操作字符串为 `setOn`、`setOff`、`toggle` 或 `momentaryOn`。PageJump 使用目标页面稳定 ID,不使用名称或数组位置: | |||
| @@ -62,6 +65,53 @@ | |||
| 编辑草稿允许 `targetPageId` 为空字符串,但进入运行态前必须配置为现存页面 ID。任何页面被 PageJump 引用时不得删除。 | |||
| AlarmList 只负责显示项目级当前报警,不保存独立触发逻辑,也不直接绑定单个寄存器。多个页面放置 AlarmList 时共享同一组当前报警和确认状态。运行态没有报警时控件隐藏;报警恢复后对应记录立即移除,最后一条报警恢复后控件再次隐藏。 | |||
| ## 报警定义 | |||
| ```json | |||
| { | |||
| "id": "alarm-1", | |||
| "address": {"area": "M", "index": 0}, | |||
| "condition": "mOn", | |||
| "threshold": 0, | |||
| "message": "急停已按下" | |||
| } | |||
| ``` | |||
| `alarmDefinitions` 是项目级有序数组,报警 ID 必须唯一。触发条件只包含当前业务需要的三种: | |||
| | `condition` | 地址区域 | 触发规则 | | |||
| | --- | --- | --- | | |||
| | `mOn` | M | 位值为 ON | | |||
| | `dHigh` | D | 字值大于等于 `threshold` | | |||
| | `dLow` | D | 字值小于等于 `threshold` | | |||
| `threshold` 使用有符号 16 位范围;M 报警仍保留该必填字段但不参与判断。报警文本不能为空。发生时间、活动状态、确认状态和清除时间属于运行会话,不进入工程 JSON。 | |||
| ## 地址注释与网络注释 | |||
| `registerComments` 是工程级 M/D 地址元数据数组。每个元素必须包含有效的 `address` 和非空 `text`,同一地址只能出现一次: | |||
| ```json | |||
| { | |||
| "address": {"area": "M", "index": 0}, | |||
| "text": "启动按钮" | |||
| } | |||
| ``` | |||
| 注释不保存寄存器当前值,也不自动把地址加入 Modbus 轮询。网络注释属于 `LadderRung`,与网络 ID、名称、条件和输出并列保存: | |||
| ```json | |||
| { | |||
| "id": "rung-1", | |||
| "name": "启动网络", | |||
| "comment": "启动按钮接通后延时启动", | |||
| "condition": null, | |||
| "output": null | |||
| } | |||
| ``` | |||
| ## 控制逻辑 | |||
| ```json | |||
| @@ -75,10 +125,19 @@ | |||
| `enabled` 决定离线执行器是否扫描该逻辑。所有启用逻辑按 `controlLogics` 数组顺序执行;禁用逻辑仍要求 ID、名称、网络和表达式结构合法,但允许保留未完成节点作为草稿。 | |||
| 网络、`Node / Series / Parallel` 条件表达式、触点、比较和线圈字段沿用当前结构化梯形图模型。网格坐标、画布连线和运行轨迹是 UI 或运行会话投影,不进入 JSON。 | |||
| 网络、`Node / Series / Parallel` 条件表达式、触点、边沿、T 触点、比较、线圈和 TON 字段沿用当前结构化梯形图模型。网格坐标、画布连线和运行轨迹是 UI 或运行会话投影,不进入 JSON。节点配置的类型和值域如下: | |||
| ```json | |||
| {"type": "edgeContact", "address": {"area": "M", "index": 0}, "mode": "rising"} | |||
| {"type": "edgeContact", "address": {"area": "M", "index": 0}, "mode": "falling"} | |||
| {"type": "timerContact", "timer": {"index": 0}, "mode": "normallyOpen"} | |||
| {"type": "ton", "timer": {"index": 0}, "presetMs": 1000} | |||
| ``` | |||
| T 地址范围为 `0~4000`,TON `presetMs` 范围为 `1~86400000`。上升沿和下降沿是一次扫描脉冲;TON 是非保持接通延时,输入断开时 `ET/Q` 立即清零。T 不参与 Modbus,也不写入 M/D 仓库。 | |||
| ## 校验与读写 | |||
| 保存顺序为领域校验、JSON 序列化、`QSaveFile` 原子提交。加载顺序为 JSON 语法、`formatVersion`、必填字段和类型、领域关系校验,全部成功后才替换当前工程。 | |||
| 工程保存允许未绑定的寄存器控件和未完成梯形图草稿。进入离线运行还必须通过运行校验:所有 HMI 寄存器控件完成绑定、所有 PageJump 目标有效、所有启用逻辑完整;禁用草稿逻辑不阻止运行。 | |||
| 工程保存允许未绑定的寄存器控件和未完成梯形图草稿。进入离线运行还必须通过运行校验:所有 HMI 寄存器控件完成绑定、所有 PageJump 目标有效、所有报警定义合法、所有启用逻辑完整;禁用草稿逻辑不阻止运行。 | |||
| @@ -59,8 +59,9 @@ | |||
| - 使用 `Node / Series / Parallel` 表达式树建立梯形图逻辑模型,支持嵌套串并联关系。 | |||
| - 支持节点前后串联插入、与节点并联、与整个支路并联、删除和输出线圈配置。 | |||
| - 初版实现常开、常闭、普通线圈、置位/复位以及 D 值与常量比较。 | |||
| - 定时器不属于当前原始需求范围,只有在后续需求明确时才新增对应配置和执行逻辑。 | |||
| - 实现常开、常闭、上升沿、下降沿、T 触点、普通线圈、置位/复位、TON 以及 D 值与常量比较。 | |||
| - 上升沿和下降沿按一次扫描脉冲执行;TON 使用离线执行器的 `steady_clock` 和 T 资源表,不为每个 TON 创建独立 Qt 定时器。 | |||
| - M/D 注释作为工程级地址元数据保存,网络注释作为 `LadderRung` 字段保存,两者都不改变寄存器轮询行为。 | |||
| - 新增节点类型时使用独立配置类型,不向通用节点结构持续堆叠无关字段。 | |||
| - 编辑器只生成逻辑模型,不直接修改 HMI 或 PLC。 | |||
| - 工程可包含多个有序控制逻辑,离线执行器按顺序扫描全部启用项,运行工作台只切换当前轨迹投影。 | |||
| @@ -70,8 +71,9 @@ | |||
| ## 8. 实现离线仿真运行 | |||
| - 实现虚拟 M/D 寄存器和固定周期的软件逻辑执行器。 | |||
| - 实现虚拟 M/D 寄存器和固定周期的软件逻辑执行器,T 仅作为离线仿真内部资源。 | |||
| - 将 HMI、虚拟寄存器和控制逻辑形成完整闭环。 | |||
| - 验证 TON 的接通延时、断开复位、多个 T 独立计时和网络顺序语义。 | |||
| - 实现启动、停止、异常和当前运行状态反馈。 | |||
| - 记录节点、支路和网络导通轨迹,在画布突出导通路径和故障节点。 | |||