plc_control/docs/投煤器布料机功能实现方案.md

562 lines
15 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 投煤器布料机远程监控与控制功能实现方案
## 1. 目标
基于当前 `plc_control` 项目,扩展出面向投煤器与布料机的业务化远程监控与控制能力,满足以下目标:
- 实时监控投煤器、布料机运行状态
- 支持远程手动启停
- 支持投煤器自动定时运行
- 支持投煤累计触发布料机自动运行
- 支持故障锁定、人工复位、通讯异常冻结
- 支持通过配置适配不同现场,不改代码完成项目复用
## 2. 现有系统能力盘点
当前项目已经具备较好的通用工业采集平台基础:
- OPC UA 数据源接入与自动重连
- 节点浏览、批量建点、点位实时订阅
- 点位批量写入能力
- 设备 `equipment` 模型
- 点位到设备绑定 `equipment_id`
- 点位信号角色字段 `signal_role`
- WebSocket 实时推送
- 前端设备、点位、日志、趋势图基础界面
- 页面配置 `page` 能力
- 进程内事件总线 `event.rs`
现状更接近“通用点位监控平台”,还不是“投煤器/布料机业务控制系统”。
## 3. 与需求的差距
需求文档要求的软件能力,当前尚未落地的核心部分如下:
- 缺少“控制单元”概念,无法表达一组投煤器对应一组布料机
- 缺少业务配置模型,无法配置 `RunTime`、`StopTime`、`AccTime`、`BLTime`
- 缺少设备业务类型约束,尚未明确区分投煤器、布料机
- 缺少设备归属单元字段,尚未形成 `unit -> equipment -> point` 的业务链路
- 缺少业务信号角色规范,尚未标准化 `REM/RUN/FLT/STA/STP`
- 缺少自动控制状态机
- 缺少故障锁定与人工确认恢复流程
- 缺少通讯异常冻结与恢复后重同步机制
- 缺少脉冲写入封装,当前只有通用批量写点
- 缺少单元总览、设备详情、控制面板、报警面板等业务界面
- 缺少统一事件持久化与后续报警模型
## 4. 推荐实现思路
推荐在现有平台上“增量扩展”,而不是重写:
- 保留现有 `source/node/point/equipment` 通用底座
- 新增面向业务控制的配置表和运行态管理
- 将控制逻辑放在 Rust 服务端,复用当前 OPC UA 连接和写点能力
- 前端增加业务页面,不破坏现有通用点位管理页面
- 基于现有 `event.rs` 扩展事件体系,而不是再造一套事件机制
这样做的好处是:
- 现有 OPC UA、点位、设备、WebSocket 基础都能继续复用
- 后续不同现场只需要换设备映射和参数
- 手动调试仍然可以通过现有点位/设备页面完成
- 未来做报警、审计、统计时可以直接复用统一事件体系
## 5. 命名与模型设计
### 5.1 命名原则
建议区分“代码命名”和“表命名”:
- 代码模型名保留语义完整性,如 `ControlUnit`
- 数据库表名尽量简洁,如 `unit`
不建议使用 `group` 作为表名,原因是语义过泛,后续容易与权限分组、界面分组、标签分组等概念冲突。
### 5.2 设备分类
继续复用 `equipment` 表中的 `kind` 字段,约定:
- `coal_feeder`:投煤器
- `distributor`:布料机
### 5.3 点位角色规范
继续复用 `point.signal_role`,建议统一枚举值:
- 状态点:`rem` `run` `flt` `ii` `q`
- 控制点:`start_cmd` `stop_cmd`
- 可选扩展:`estop` `mode_auto` `mode_manual` `reset_cmd`
这样每台设备都可以通过“设备 + 点位角色”完成映射,而不是在代码里写死点名。
### 5.4 新增 `unit` 表
建议新增 `unit` 表,对应代码模型 `ControlUnit`,表示一个业务控制单元。
建议字段:
- `id`
- `code`
- `name`
- `description`
- `enabled`
- `run_time_sec`
- `stop_time_sec`
- `acc_time_sec`
- `bl_time_sec`
- `require_manual_ack_after_fault`
- `created_at`
- `updated_at`
### 5.5 设备直接归属 Unit
当前业务前提下,一台设备只属于一个控制单元,不会跨单元复用,因此不建议单独建立关系表。
更合适的方式是直接在 `equipment` 表新增:
- `unit_id`
这样模型会更简单:
- 一个 `unit` 对多台 `equipment`
- 一台 `equipment` 只属于一个 `unit`
- `equipment.kind` 用于区分 `coal_feeder``distributor`
如果后续现场出现“一台设备可挂多个单元”或“单元内设备编排顺序复杂”的需求,再演进成关系表会更合适。第一阶段不建议设计过重。
### 5.6 Unit 运行态放内存
`unit` 运行态不建议优先落数据库,建议由控制引擎保存在内存中。
建议维护的内存运行态字段:
- `state`
- `accumulated_run_sec`
- `current_run_elapsed_sec`
- `current_stop_elapsed_sec`
- `distributor_run_elapsed_sec`
- `fault_locked`
- `comm_locked`
- `manual_ack_required`
- `last_tick_at`
状态值建议:
- `stopped`
- `running`
- `distributor_running`
- `fault_locked`
- `comm_locked`
原因:
- 这些字段变化频率高,不适合高频写库
- 服务重启后直接恢复旧控制态并不安全
- 更合理的方式是重启后重新读取 `REM/RUN/FLT/Q` 并重建运行态
- 通讯恢复或服务重启后不自动补发控制命令,更符合工业控制安全原则
如后续确实需要“断电恢复上下文”或运行分析,再补充轻量级快照能力即可,但不是第一阶段必须项。
### 5.7 统一 `event` 表,预留 `alarm` 表
建议不要命名为 `control_event`,而是使用统一的 `event` 表。
原因:
- 当前不仅有控制事件,后续还会有配置事件、通讯事件、数据源事件
- `event` 更适合作为统一审计与业务时间线
- 现有 `event.rs` 已经是进程内事件总线,命名保持一致更自然
建议 `event` 表记录:
- 手动启动/停止
- 自动启动/停止
- 故障锁定
- 人工解除故障锁定
- 通讯异常/恢复
- 数据源创建、更新、删除
- 控制参数变更
- 关键状态切换
关键字段建议:
- `id`
- `event_type`
- `level`
- `unit_id`
- `equipment_id`
- `source_id`
- `message`
- `payload`
- `created_at`
同时建议未来单独设计 `alarm` 表,而不是把报警状态硬塞进 `event` 表。
原因:
- 报警通常有独立生命周期:触发、确认、恢复、清除
- 报警需要独立字段,如 `severity`、`active`、`acked`、`acked_by`、`acked_at`、`cleared_at`
- 把报警硬塞到 `event` 中会让通用事件表越来越臃肿
因此推荐边界是:
- `event`:记录“发生了什么”
- `alarm`:记录“需要被告警管理的异常”
第一阶段可以先只落 `event` 表,`alarm` 表先在方案中预留,不急着实现。
## 6. 控制逻辑设计
### 6.1 手动控制
手动控制前置校验:
- `REM == 1`
- `FLT == 0`
- 通讯正常
- 未处于故障锁定
- 如有急停点,`ESTOP == 0`
控制命令统一走脉冲写入:
1. 写入 `1`
2. 延时 `200-500ms`
3. 写回 `0`
服务端需要封装 `pulse_write(point_id, high_ms)`,前端不能直接拼两次写点。
### 6.2 自动控制状态机
每个 `unit` 独立维护状态机。
#### `STOPPED`
- 累计停止时间
-`stop_elapsed >= StopTime`,尝试启动投煤器
- 成功后切换到 `RUNNING`
#### `RUNNING`
- 累计运行时间
- `accumulated_run_sec += delta`
-`run_elapsed >= RunTime`,尝试停止投煤器,切换回 `STOPPED`
-`accumulated_run_sec >= AccTime`,进入布料机触发流程
#### `DISTRIBUTOR_RUNNING`
- 校验布料机 `REM/FLT/通讯`
- 启动布料机
- 等待 `RUN == 1` 反馈
- 计时 `BLTime`
- 停止布料机
- 累计时间清零
- 回到 `STOPPED` 或回到自动节拍起点
### 6.3 故障机制
任意设备检测到 `FLT == 1`
- 停止该单元自动控制
- 标记 `fault_locked = true`
- 禁止再次自动发命令
- 发送并持久化关键事件
`FLT``1 -> 0` 恢复:
- 不自动解锁
- 标记 `manual_ack_required = true`
- 等待人工在界面点击“解除故障锁定”
### 6.4 通讯异常机制
当质量位异常或 OPC 连接中断:
- 标记 `comm_locked = true`
- 冻结全部控制动作
- 前端按钮灰化
- 不允许任何自动/手动写入
通讯恢复后:
- 重新读取 `REM/RUN/FLT`
- 重同步运行态
- 不自动补发控制命令
- 发送并持久化恢复事件
- 等待人工操作或下一次自动触发
## 7. 事件体系设计
### 7.1 继续复用 `src/event.rs`
建议不要另起一套业务事件中心,而是在现有 [src/event.rs](D:/projects/plc_control/src/event.rs) 上扩展。
当前它已经承担两类职责:
- 控制类内部事件分发
- 遥测类高频事件分发
推荐继续保留这个结构:
- `AppEvent` 作为统一进程内事件枚举
- 高频遥测事件继续走内存和 WebSocket
- 低频且有审计价值的事件选择性落库到 `event`
### 7.2 哪些事件适合落库
适合落库的:
- `SourceCreate`
- `SourceUpdate`
- `SourceDelete`
- 自动控制启动/停止
- 手动启动/停止命令发送
- 故障锁定
- 人工确认恢复
- 通讯异常/恢复
- 参数配置变更
- 单元状态切换
不适合直接落库的:
- `PointNewValue`
- 高频实时遥测
- 细碎的内部轮询过程
### 7.3 推荐扩展方向
建议在 `AppEvent` 中逐步增加业务事件,例如:
- `AutoControlStarted`
- `AutoControlStopped`
- `EquipmentStartCommandSent`
- `EquipmentStopCommandSent`
- `FaultLocked`
- `FaultAcked`
- `CommLocked`
- `CommRecovered`
- `UnitStateChanged`
这样后续无论是写日志、落库、推送 WebSocket、做报警触发都可以基于同一个事件入口。
## 8. 后端改造方案
### 8.1 新增模块
建议新增:
- `src/handler/control.rs`
- `src/service/control.rs`
- `src/control/engine.rs`
- `src/control/runtime.rs`
- `src/control/validator.rs`
职责划分:
- `handler`HTTP 接口
- `service`:数据库读写
- `control/engine`:状态机与调度
- `control/runtime`:内存运行态缓存与同步
- `control/validator`:控制前置校验
### 8.2 新增接口
建议新增接口:
- `GET /api/control/unit`
- `POST /api/control/unit`
- `PUT /api/control/unit/{id}`
- `GET /api/control/unit/{id}`
- `POST /api/control/unit/{id}/start-auto`
- `POST /api/control/unit/{id}/stop-auto`
- `POST /api/control/unit/{id}/ack-fault`
- `POST /api/control/equipment/{id}/start`
- `POST /api/control/equipment/{id}/stop`
- `GET /api/events`
说明:
- 设备手动控制必须走业务接口,不建议继续直接暴露给页面做原始点位写入
-`/api/point/value/batch` 保留给调试或底层工具能力
- 事件查询接口可以直接面向统一 `event`
### 8.3 控制引擎运行方式
建议服务启动后增加一个后台任务:
-`500ms``1s` 扫描所有启用的 `unit`
- 从内存读取运行态缓存
- 从当前点位监控数据中取 `REM/RUN/FLT/Q`
- 驱动状态机执行
控制引擎不要直接查 OPC应复用当前 `connection_manager` 已维护的实时点值。
### 8.4 关键复用点
可直接复用当前已有能力:
- `connection_manager` 的点位实时缓存
- `get_point_monitor_data_read_guard`
- 批量写点能力
- WebSocket 实时推送
- `event.rs` 的统一事件入口
- `unit_id + equipment.kind + point.signal_role` 的业务映射关系
## 9. 前端改造方案
建议在现有通用页面之外新增业务页面,避免混杂。
### 9.1 新增页面
- 单元总览页
- 单元详情页
- 设备控制面板
- 事件记录页
- 报警页
- 参数配置页
### 9.2 单元总览页内容
每个 `unit` 展示:
- 单元名称
- 自动/手动状态
- 当前状态机状态
- 投煤器运行状态
- 布料机运行状态
- 当前累计运行时间
- 故障锁定状态
- 通讯状态
并提供按钮:
- 启动自动
- 停止自动
- 故障确认/解除锁定
### 9.3 设备控制页内容
针对单台投煤器/布料机提供:
- REM/RUN/FLT/Q/II 实时显示
- 启动按钮
- 停止按钮
- 通讯异常、故障锁定提示
- 最近事件
### 9.4 趋势、事件与报警
复用已有趋势图能力:
- 电流 `II` 趋势
- 运行状态变化曲线
- 事件时间线
后续报警页面基于独立 `alarm` 表实现:
- 当前活动报警
- 已确认报警
- 已恢复报警
- 报警确认操作
## 10. 分阶段实施建议
### 第一阶段:最小可用版
目标:先让系统具备业务闭环,但不追求复杂页面。
内容:
- 新增 `unit`
-`equipment` 增加 `unit_id`
- 约定设备 `kind` 和点位 `signal_role`
- 新增手动控制接口
- 实现脉冲写入
- 实现故障锁定与通讯冻结
- 实现自动控制状态机
- 基于 `event.rs` 落统一 `event`
- 前端增加一个“控制单元”面板和事件列表
交付后即可验证:
- 单台投煤器启停
- 单元级自动启停
- 累计触发布料机运行
- 故障恢复后人工确认
- 关键操作和状态切换可追溯
### 第二阶段:增强版
内容:
- 单元总览页
- 单元详情页
- 参数在线编辑
- 更丰富的趋势图
- WebSocket 业务事件推送
- 报警规则与 `alarm`
- 报警确认与恢复流程
### 第三阶段:现场适配版
内容:
- 导入导出配置
- 项目模板
- 配置校验工具
- 启停联锁自检
- 操作权限控制
## 11. 建议优先落地顺序
从当前代码基础出发,建议按下面顺序开发:
1. 补齐业务数据模型和数据库迁移
2. 新增 `unit` 表并为 `equipment` 增加 `unit_id`
3. 规范 `equipment.kind``point.signal_role`
4. 实现服务端脉冲写入能力
5. 实现手动控制接口
6. 实现 `unit` 自动控制状态机
7. 扩展 `event.rs` 并实现统一 `event` 表持久化
8. 实现故障锁定、通讯冻结、人工确认
9. 增加前端业务页面
10. 第二阶段再引入独立 `alarm`
## 12. 对当前代码的具体落点
基于现有代码,建议主要改动点如下:
- [src/model.rs](D:/projects/plc_control/src/model.rs)
- 增加 `ControlUnit` 模型
-`Equipment` 增加 `unit_id`
- 后续增加 `EventRecord`、`AlarmRecord` 模型
- [src/event.rs](D:/projects/plc_control/src/event.rs)
- 扩展 `AppEvent` 业务事件类型
- 增加低频关键事件的持久化逻辑
- [src/main.rs](D:/projects/plc_control/src/main.rs)
- 注册控制相关路由
- 启动控制引擎后台任务
- [src/handler/point.rs](D:/projects/plc_control/src/handler/point.rs)
- 保留底层写点接口,不直接承载业务控制
- [src/handler/equipment.rs](D:/projects/plc_control/src/handler/equipment.rs)
- 继续作为设备基础资料管理
- [web/index.html](D:/projects/plc_control/web/index.html)
- 增加业务控制页面入口或独立面板
- [web/js/app.js](D:/projects/plc_control/web/js/app.js)
- 增加控制单元页面事件绑定
## 13. 本次结论
当前项目不需要推倒重来,可以直接演进成投煤器与布料机远程监控控制系统。
最合理的路径是:
- 以现有 OPC UA 与点位平台为底座
- 数据库使用简洁表名 `unit`、`event`
- 代码层保留语义化命名,如 `ControlUnit`、`AppEvent`
-`equipment` 上直接增加 `unit_id`
- 在服务端以内存运行态实现状态机和脉冲控制
- 在现有 [src/event.rs](D:/projects/plc_control/src/event.rs) 上扩展统一事件体系
- 第一阶段先做统一 `event`,第二阶段再拆分独立 `alarm`
如果进入下一步开发,建议先做“第一阶段最小可用版”。