综合平台编程器项目的远程存储
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.
 
 
 
 

7.1 KiB

综合平台编程器架构

目标

项目采用 UI、领域、服务和基础设施分层。HMI 编辑、离线仿真和真机联机使用同一套领域模型,UI 不直接依赖串口或 Modbus 实现。

项目代码不使用自定义命名空间,分层边界由目录、接口和依赖方向表达。

目录职责

app/
├── integrated_platform.pro     qmake 工程入口
├── src/
│   ├── main.cpp                应用组合入口
│   ├── ui/                     Qt Designer 界面、视图和交互协调
│   ├── domain/                 工程、HMI、逻辑、M/D 地址等纯业务模型
│   ├── services/               用例编排、运行模式和仿真服务
│   └── infrastructure/         工程文件、Modbus RTU 等外部实现
└── tests/                      单元测试与集成测试工程

依赖方向

生产代码必须保持单向依赖:

UI -> Services -> Domain
Infrastructure -> Domain
main.cpp -> UI + Services + Infrastructure
  • domain 不依赖 UI、串口、文件系统或具体 PLC 库。
  • services 只通过领域定义的接口使用寄存器、工程存储等能力。
  • infrastructure 实现外部能力,例如 JSON 工程文件和 Qt Modbus RTU。
  • ui 只调用服务并展示状态;MainWindow 只组织界面,不实现业务规则、寄存器读写或通信流程。
  • main.cpp 负责创建对象并注入依赖,不承载业务逻辑。

核心数据流

用户操作 HMI
    -> UI 发起服务请求
    -> 服务校验并更新领域模型或寄存器接口
    -> 仿真服务 / 真机 Modbus 实现执行
    -> 服务发布状态变化
    -> UI 刷新控件和状态栏

离线模式由服务连接虚拟 M/D 寄存器与软件逻辑执行器;真机模式由服务连接 PLC 寄存器缓存与 Modbus RTU 服务。两种模式共用 HMI 绑定模型,且软件逻辑执行器不得在真机模式运行。

核心领域模型

领域模型位于 app/src/domain/,只使用 C++17 标准库,不包含 Qt 界面、串口或 Modbus
类型:

文件 职责
register_address.* 定义 M/D 地址值对象,统一校验项目地址范围 0~4000
register_repository.* 定义 M 位和 D 字的统一读写接口,并提供离线内存实现。
project_storage.* 定义工程文件保存和加载的领域存储契约,不依赖具体文件格式。
hmi_model.* 定义 HMI 页面、控件、位置、扩展属性和寄存器绑定,并校验控件位于页面边界内。
control_logic_model.* 定义网络、串联级、并联条件和输出线圈,并校验节点类型及地址区域。
project_model.* 聚合工程元数据、HMI 页面和控制逻辑,并校验工程内标识唯一性。
runtime_state.* 定义编辑态、离线运行态、真机运行态及合法切换规则。

工程管理由 services/ProjectService 编排新建、保存、另存为和加载。JSON 文件转换和原子写入
infrastructure/JsonProjectStorage 实现。加载必须先完成文件解析、版本检查和领域校验,成功
后才能替换当前工程;保存失败或加载失败不得修改当前工程路径和内存内容。

services/HmiEditorService 负责 HMI 页面的控件添加、删除、移动和属性更新,不依赖 Qt 图元。
ui/HmiEditorWidget 使用 QGraphicsScene 将模型投影为画布项,画布项只保存控件标识,移动结束后
才通过编辑服务提交新位置。保存时由 Project::validate() 拒绝缺失必需绑定或绑定区域错误的控件。

RegisterRepository 是 HMI、逻辑执行器和运行服务唯一可见的寄存器边界。离线运行使用
VirtualRegisterRepository;真机运行后续注入由基础设施层实现的 PLC 缓存仓库。仓库读取的是
最近一次有效值,写入成功只表示请求被仓库接受;真实 PLC 的异步确认由服务层负责反馈。

services/HmiRuntimeService 仅持有 RegisterRepository 接口:按钮切换 M 位,指示灯读取 M 位,
数值显示读取 D 字,数值输入写入 D 字。它不依赖虚拟寄存器实现、串口或 Modbus,因此离线和真机
运行可替换数据源而无需改变 HMI 模型或画布代码。

控制逻辑节点使用 std::variant 组合独立配置类型。初版只包含 M 区触点、M 区线圈和 D 值与
常量比较。新增节点时应增加独立配置类型及其校验和执行处理,不得向通用 LogicNode 持续
添加只对单一节点有效的可选字段。定时器不是当前原始需求范围,不提前建立模型或执行逻辑。

控制逻辑按标准梯形图的受限结构表达:一个逻辑包含多个网络,一个网络包含按顺序串联的多个
条件级,每个条件级包含一个或多个并联条件,输出线圈固定在网络最右侧。条件级之间执行逻辑与,
同级并联条件执行逻辑或。状态保持通过启动触点和运行反馈触点并联,并与停止触点串联后驱动运行
线圈表达。该结构是后续软件逻辑执行器的确定性求值契约,不需要通用图遍历或连接表。

services/LogicEditorService 负责新增和删除网络、追加串联条件、增加并联条件、设置输出线圈、
修改属性和删除节点。空网络可作为编辑占位;非空网络保存时必须同时具备条件和输出线圈。
ui/LogicEditorWidget 自动排列左右母线、串联级、并联支路和右侧线圈,不允许自由拖动或手动画线,
也不保存像素坐标。编辑器通过服务提交修改,不访问 HMI、寄存器仓库或 PLC。

运行模式边界

模式 允许编辑工程 寄存器来源 软件逻辑执行器 进入约束
编辑态 无运行仓库 停止 运行态必须先回到编辑态。
离线运行态 虚拟 M/D 运行 仅可从编辑态进入。
真机运行态 PLC 读回缓存 停止 仅可从编辑态进入,且必须先完成 PLC 初次读取。

离线运行态与真机运行态不得直接互切。进入真机运行态时不复制或写入离线仓库值,避免误写
PLC;退出任一运行态后才能重新编辑工程。

测试边界

测试按业务风险和模块边界安排,不要求为每个简单访问器或转发函数单独编写测试:

优先级 测试对象 重点验证内容
domain 地址边界、M/D 类型约束、模型校验、工程唯一性和运行模式切换
services HMI、寄存器仓库和逻辑执行器之间的离线闭环
工程存储 保存加载往返、版本字段、缺失字段和非法文件
infrastructure Modbus 帧解析、超时、CRC、断线和错误反馈
ui 新建工程、编辑、运行切换和错误提示等关键工作流
冒烟 真机联调 少量安全地址的读写和 RUN 联动验证

domainservices 的自动化测试不依赖 Qt 界面或真实 PLC。基础设施优先使用模拟串口
和测试文件,真机测试只覆盖无法在模拟环境确认的通信和联动行为。