综合平台编程器项目的远程存储
Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.
 
 
 
 

9.7 KiB

综合平台编程器架构

目标与范围

项目是单工程、单 PLC、多 HMI 页面和多控制逻辑的 Qt 桌面编程器,提供 HMI 编辑、结构化梯形图、离线仿真和 Modbus RTU 真机联机。

本项目不生成、编译或下载 PLC 程序,不读取 PLC 内部程序与网络轨迹,不实现完整 XDPPro 指令集,也不支持任意自由画线。真机运行时 PLC 内部程序是唯一控制源,PC 只读写工程实际引用的 M/D 地址。

分层与依赖

app/src/
├── domain/          无 Qt 依赖的模型、值对象、校验和仓库接口
├── services/        编辑、工程、仿真、运行模式和通信契约
├── infrastructure/  JSON、PLC 缓存、Qt Modbus RTU 实现
├── ui/              Qt Widgets 视图、对话框和界面控制器
└── main.cpp         对象创建与依赖注入

生产代码依赖方向固定为:

UI -> Services -> Domain
Infrastructure -> Services contracts + Domain
main.cpp -> UI + Services + Infrastructure
  • domain 不依赖 Qt、文件系统或串口
  • services 执行业务用例和原子编辑,通过接口使用工程存储与 PLC 通信
  • infrastructure 实现 JSON 工程存储、PLC 缓存和异步 Modbus RTU
  • ui 只提交命令并投影模型、轨迹和错误,不直接读写串口或承载业务校验
  • main.cpp 只组合对象,不实现业务规则

主窗口静态布局由 main_window.ui 管理。UI 协调分为:

组件 职责
ProjectWorkspaceController 工程树、当前页面/逻辑会话选择和编辑对象刷新
PropertyPanelController HMI/梯形图选择、属性表单和编辑服务调用
RuntimePanelController 运行会话、操作员 HMI 窗口、诊断工作台、运行值刷新和仿真故障反馈
HmiRuntimeWindow 独立顶层操作窗口,只投影 HMI 页面并转发运行时交互和退出请求
MainWindow 窗口级动作、工程文件操作、控制器组合和模式切换

运行界面按使用角色分为两个投影,二者共享同一份 HmiNavigationService 和活动寄存器仓库,不能各自维护页面或运行状态:

  • HmiRuntimeWindow 是操作员窗口。进入离线或真机运行后最大化显示,只包含 HMI 页面、当前页面、运行数据源状态和退出运行入口;不显示工程树、属性、梯形图编辑或 PLC 配置
  • 主窗口中的 RuntimeMonitorWidget 是工程师诊断工作台。离线时显示只读 HMI、软件梯形图轨迹和自由监控;真机时显示只读 HMI 和自由监控,不能显示本地梯形图伪轨迹。页面跳转会同步到操作员窗口,但按钮和数值输入不能从诊断 HMI 写入
  • 关闭独立 HMI 窗口不是单纯隐藏窗口,而是请求 MainWindow -> RuntimeModeService 返回编辑态。离线时先停止软件扫描,真机时保留 PLC 连接但撤销运行会话

工程模型与持久化

Project
├── metadata
├── hmiPages[] + initialHmiPageId
├── alarmDefinitions[]
├── registerComments[]
└── controlLogics[]
    └── rungs[]
        ├── condition
        └── output
  • 页面、逻辑和节点使用稳定 ID;名称可修改,数组顺序决定工程树顺序和离线扫描顺序
  • 当前编辑页面和当前逻辑是 UI 会话状态,不写入工程
  • HMI 控件类型、默认值、绑定规则和运行值类型由无 Qt 依赖的 hmi_control_registry 统一描述
  • 需要寄存器的 HMI 控件、报警条件和梯形图节点直接保存 M/D 地址;项目不再维护统一 dataPoints
  • registerComments 只是 M/D 地址元数据,不保存当前值或引用位置,也不会让地址自动进入 PLC 轮询

工程 JSON 格式固定为严格的 1.0。加载顺序为 JSON 解析、版本检查、字段解析、领域校验,全部成功后才能替换当前工程;保存使用原子提交。当前版本不读取旧 dataPointsstages/branches 或缺少必填字段的同版本草稿。字段定义见 docs/工程格式说明.md

校验分两级:

  • validate() 保证可保存结构合法,允许未绑定控件、待配置节点和未完成网络作为编辑草稿
  • validateForRunning() 检查运行所需绑定和已启用逻辑;禁用草稿不阻止运行

数量常量集中在 domain/project_limits.h,最终业务口径见 docs/用户使用/数量边界确认方案.md。领域、服务、JSON 和 UI 入口必须使用同一组常量,不能各自维护数字。

结构化梯形图

网络条件保存为规范化表达式树:

ConditionExpression
├── Node       触点、边沿或比较条件
├── Wire       无地址横线,保存条件区列跨度
├── Series     子表达式执行 AND
└── Parallel   子表达式执行 OR

输出是网络最右侧的单独节点。LogicEditorService 把串联、并联、旁路、替换和删除转换为表达式树操作,失败时回退整个编辑;LogicEditorWidget 只把树投影成正交网格。竖线由 Parallel 边界派生,网格坐标和自由线段不持久化,因此领域模型不会产生悬空线、环路或多输出路径。

单网络前 10 列为条件区,输出最多位于第 11 列;横线只能占条件区。第 11 个条件、过深表达式或过多并联行会在编辑和加载阶段被拒绝,具体数值以数量边界文档为准。

网络运行语义:

  • 空网络不执行
  • 有条件但没有输出的已启用网络不能运行
  • 有输出但没有条件的网络是恒真网络,每次扫描执行输出
  • Wire 的逻辑值为真,但运行轨迹是否导通仍取决于上游电流

节点配置使用 std::variant 的独立类型。当前条件包括 M 触点与上下沿、T/C 触点和 D 比较;输出包括普通/置位/复位 M 线圈、TON、CTU/CTD、MOVE、ADD/SUB。新增指令必须增加独立配置、校验、JSON、执行、编辑和测试分支,不能向通用节点堆叠无关字段。

SoftwareLogicExecutorcontrolLogics 和网络数组顺序扫描已启用逻辑,前面网络的 M/D 写入在同一扫描周期对后面网络可见。T/C 是离线执行器内部资源,不映射 PLC T/C 区,也不进入 Modbus 轮询;计数器 CV/PV 等显式 M/D 引用仍使用统一仓库。扫描轨迹按逻辑 ID 分区,避免不同逻辑中的重复节点 ID 相互覆盖。

数据源与运行模式

运行界面只访问 RegisterRepositoryActiveRegisterRepository 根据模式切换实际数据源:

编辑:UI -> Editor Services -> ProjectService -> Project
                                  └── ProjectStorage -> JSON

离线:HMI 运行窗口 / 诊断工作台 -> ActiveRegisterRepository -> VirtualRegisterRepository
                                                          ^
                                     OfflineSimulationService(SoftwareLogicExecutor)

真机:HMI 运行窗口 / 诊断工作台 -> ActiveRegisterRepository -> PlcRegisterRepository(cache)
                                                              ^
PLC <-> PlcCommunicationService <---------------------------------┘
模式 允许工程编辑 寄存器来源 软件逻辑执行器 进入条件
编辑态 无运行数据源 停止 运行态先退出
离线运行 虚拟 M/D 运行 工程通过运行校验
真机运行 PLC 读回缓存 停止 PLC 已连接并完成本次首读

离线和真机不能直接互切。进入真机不复制或下发离线值,也不显示本地梯形图导通轨迹。

自由监控是会话级诊断工具,不属于 Project,不写入 JSON。它通过活动仓库读取和单点写入 M/D;真机写入仍必须经过连接与首读门槛。

Modbus RTU 通信

PlcCommunicationService 使用 QModbusRtuSerialMaster 异步连接、轮询和单点写入,UI 线程不等待串口响应。Modbus 地址使用从 0 开始的原始地址。

轮询集合由 HMI、报警、梯形图中的显式 M/D 引用和自由监控地址合并,按区域去重并合并相邻地址。T/C 内部资源、横线和注释不进入轮询。动态修改监控地址时,当前请求按旧快照解析,空闲后再应用新集合。

PLC 缓存只保存最后一次成功读回值。写请求受理后不乐观修改缓存,界面等待后续轮询确认真实值。真机运行资格属于当前连接代次:必须完成完整首读,旧连接的异步回复不能污染重连后的状态。

通信状态包括 Disconnected / Connecting / Connected / Recovering / Faulted。连接失败或物理断线会关闭串口会话并进入 Disconnected;超时、协议或读写故障会停止正常轮询、保留最后有效缓存并进入 Faulted。所有通信故障都会撤销首读资格;若当时处于真机运行,运行模式服务立即返回编辑态。可恢复超时探测成功后进入 Recovering 并重新完整首读,但不会自动重新进入真机运行。

扩展规则

  • 新业务先确定所属领域模型和服务用例,再添加 UI;不得从 UI 直接改工程容器或串口状态
  • 编辑操作必须在服务层校验并原子提交,失败不能污染撤销历史或留下半成品
  • 新持久化字段必须同步领域校验、严格 JSON 往返、缺失/非法字段测试和格式说明;是否升级格式版本必须明确决定
  • 新数量边界必须进入 project_limits.h、数量边界文档和上下界测试
  • 新 HMI 类型优先扩展 hmi_control_registry,专用交互留在对应服务和图元
  • 不重新引入数据点表、自由线段、UI 直连串口或真机执行本地梯形图
  • 自动化测试按风险覆盖领域、服务、存储、通信和 UI;真实串口、接线和设备 RUN 联动必须现场验证