# 工程 JSON 1.0 格式说明 ## 格式策略 当前开发阶段只有一个有效工程格式:`1.0`。代码直接读写本文描述的结构,不为早期开发草稿增加同版本默认值、字段推断、迁移分支或双写逻辑。缺少必填字段、字段类型错误、引用不存在或领域校验失败时,加载必须失败且不得替换当前工程。 ## 顶层结构 ```json { "formatVersion": "1.0", "id": "project-1", "name": "包装线", "hmiPages": [], "initialHmiPageId": "", "controlLogics": [] } ``` 所有顶层字段必填。空工程允许 `hmiPages` 和 `controlLogics` 为空,此时 `initialHmiPageId` 必须为空。存在页面时,`initialHmiPageId` 必须引用 `hmiPages` 中的页面 ID。 `hmiPages` 与 `controlLogics` 都是有序数组。页面顺序用于工程树显示;控制逻辑顺序是离线扫描顺序。对象 ID 稳定且唯一,名称可修改且在同类对象中唯一。 编辑器的当前页面 ID 和当前逻辑 ID 是主窗口会话状态,不进入工程 JSON。每次进入运行态时,HMI 从 `initialHmiPageId` 重新启动。 ## HMI 页面与控件 ```json { "id": "page-1", "name": "主操作页面", "width": 800, "height": 480, "controls": [] } ``` 每个控件都要求 `id`、`type`、`bounds`、`text`、`binding` 和 `properties`。`bounds` 包含整数 `x`、`y`、`width`、`height`,矩形必须完整位于页面内。`binding` 为寄存器对象或 JSON `null`。 | `type` | 绑定 | 额外必填字段 | | --- | --- | --- | | `button` | M 地址或 `null` 草稿 | `buttonOperation` | | `indicator` | M 地址或 `null` 草稿 | 无 | | `numericDisplay` | D 地址或 `null` 草稿 | 无 | | `numericInput` | D 地址或 `null` 草稿 | 无 | | `label` | 必须为 `null` | 无 | | `pageJump` | 必须为 `null` | `targetPageId` | 按钮操作字符串为 `setOn`、`setOff`、`toggle` 或 `momentaryOn`。PageJump 使用目标页面稳定 ID,不使用名称或数组位置: ```json { "id": "page-jump-1", "type": "pageJump", "bounds": {"x": 20, "y": 20, "width": 120, "height": 40}, "text": "参数设置", "binding": null, "properties": {}, "targetPageId": "page-2" } ``` 编辑草稿允许 `targetPageId` 为空字符串,但进入运行态前必须配置为现存页面 ID。任何页面被 PageJump 引用时不得删除。 ## 控制逻辑 ```json { "id": "logic-1", "name": "主控制逻辑", "enabled": true, "rungs": [] } ``` `enabled` 决定离线执行器是否扫描该逻辑。所有启用逻辑按 `controlLogics` 数组顺序执行;禁用逻辑仍要求 ID、名称、网络和表达式结构合法,但允许保留未完成节点作为草稿。 网络、`Node / Series / Parallel` 条件表达式、触点、比较和线圈字段沿用当前结构化梯形图模型。网格坐标、画布连线和运行轨迹是 UI 或运行会话投影,不进入 JSON。 ## 校验与读写 保存顺序为领域校验、JSON 序列化、`QSaveFile` 原子提交。加载顺序为 JSON 语法、`formatVersion`、必填字段和类型、领域关系校验,全部成功后才替换当前工程。 工程保存允许未绑定的寄存器控件和未完成梯形图草稿。进入离线运行还必须通过运行校验:所有 HMI 寄存器控件完成绑定、所有 PageJump 目标有效、所有启用逻辑完整;禁用草稿逻辑不阻止运行。