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

15 KiB
Raw Blame History

投煤器布料机远程监控与控制功能实现方案

1. 目标

基于当前 plc_control 项目,扩展出面向投煤器与布料机的业务化远程监控与控制能力,满足以下目标:

  • 实时监控投煤器、布料机运行状态
  • 支持远程手动启停
  • 支持投煤器自动定时运行
  • 支持投煤累计触发布料机自动运行
  • 支持故障锁定、人工复位、通讯异常冻结
  • 支持通过配置适配不同现场,不改代码完成项目复用

2. 现有系统能力盘点

当前项目已经具备较好的通用工业采集平台基础:

  • OPC UA 数据源接入与自动重连
  • 节点浏览、批量建点、点位实时订阅
  • 点位批量写入能力
  • 设备 equipment 模型
  • 点位到设备绑定 equipment_id
  • 点位信号角色字段 signal_role
  • WebSocket 实时推送
  • 前端设备、点位、日志、趋势图基础界面
  • 页面配置 page 能力
  • 进程内事件总线 event.rs

现状更接近“通用点位监控平台”,还不是“投煤器/布料机业务控制系统”。

3. 与需求的差距

需求文档要求的软件能力,当前尚未落地的核心部分如下:

  • 缺少“控制单元”概念,无法表达一组投煤器对应一组布料机
  • 缺少业务配置模型,无法配置 RunTimeStopTimeAccTimeBLTime
  • 缺少设备业务类型约束,尚未明确区分投煤器、布料机
  • 缺少设备归属单元字段,尚未形成 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_feederdistributor

如果后续现场出现“一台设备可挂多个单元”或“单元内设备编排顺序复杂”的需求,再演进成关系表会更合适。第一阶段不建议设计过重。

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 表。

原因:

  • 报警通常有独立生命周期:触发、确认、恢复、清除
  • 报警需要独立字段,如 severityactiveackedacked_byacked_atcleared_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
  • 禁止再次自动发命令
  • 发送并持久化关键事件

FLT1 -> 0 恢复:

  • 不自动解锁
  • 标记 manual_ack_required = true
  • 等待人工在界面点击“解除故障锁定”

6.4 通讯异常机制

当质量位异常或 OPC 连接中断:

  • 标记 comm_locked = true
  • 冻结全部控制动作
  • 前端按钮灰化
  • 不允许任何自动/手动写入

通讯恢复后:

  • 重新读取 REM/RUN/FLT
  • 重同步运行态
  • 不自动补发控制命令
  • 发送并持久化恢复事件
  • 等待人工操作或下一次自动触发

7. 事件体系设计

7.1 继续复用 src/event.rs

建议不要另起一套业务事件中心,而是在现有 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

职责划分:

  • handlerHTTP 接口
  • 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 控制引擎运行方式

建议服务启动后增加一个后台任务:

  • 500ms1s 扫描所有启用的 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.kindpoint.signal_role
  4. 实现服务端脉冲写入能力
  5. 实现手动控制接口
  6. 实现 unit 自动控制状态机
  7. 扩展 event.rs 并实现统一 event 表持久化
  8. 实现故障锁定、通讯冻结、人工确认
  9. 增加前端业务页面
  10. 第二阶段再引入独立 alarm

12. 对当前代码的具体落点

基于现有代码,建议主要改动点如下:

13. 本次结论

当前项目不需要推倒重来,可以直接演进成投煤器与布料机远程监控控制系统。

最合理的路径是:

  • 以现有 OPC UA 与点位平台为底座
  • 数据库使用简洁表名 unitevent
  • 代码层保留语义化命名,如 ControlUnitAppEvent
  • equipment 上直接增加 unit_id
  • 在服务端以内存运行态实现状态机和脉冲控制
  • 在现有 src/event.rs 上扩展统一事件体系
  • 第一阶段先做统一 event,第二阶段再拆分独立 alarm

如果进入下一步开发,建议先做“第一阶段最小可用版”。