15 KiB
投煤器布料机远程监控与控制功能实现方案
最后更新:2026-03-24(基于当前代码重新审阅)
1. 目标
基于当前 plc_control 项目,扩展出面向投煤器与布料机的业务化远程监控与控制能力,满足以下目标:
- 实时监控投煤器、布料机运行状态
- 支持远程手动启停
- 支持投煤器自动定时运行
- 支持投煤累计触发布料机自动运行
- 支持故障锁定、人工复位、通讯异常冻结
- 支持通过配置适配不同现场,不改代码完成项目复用
2. 当前系统能力盘点
2.1 通用平台基础(已有)
- OPC UA 数据源接入与自动重连(
connection.rs) - 节点浏览、批量建点、点位实时订阅(
handler/point.rs,handler/source.rs) - 点位批量写入能力(
connection.rs: write_point_values_batch) - WebSocket 实时推送(
websocket.rs) - 前端设备、点位、日志、趋势图基础界面
- 页面配置
page能力 - 进程内事件总线
event.rs(control + telemetry 双通道) - HTTP 中间件、鉴权、分页等工具链
2.2 业务模型(已有)
unit表(migrations/20260324090000_add_unit_and_event.sql)- 包含
run_time_sec,stop_time_sec,acc_time_sec,bl_time_sec,require_manual_ack_after_fault
- 包含
event表(同上迁移),含unit_id,equipment_id,source_id,level,payloadequipment.unit_idFKequipment.kind,point.signal_roleControlUnit,EventRecord模型(model.rs)
2.3 业务逻辑(已有)
- Unit CRUD 接口:
GET/POST/PUT/DELETE /api/unit,GET /api/unit/{id} - 设备手动控制接口:
POST /api/control/equipment/{id}/start|stop- 内置脉冲写入(写 1 → 等 300ms → 写 0)
- 前置校验:
rem == 1,flt == 0, 通讯质量 good(control/validator.rs)
AppEvent::EquipmentStartCommandSent/EquipmentStopCommandSent,自动持久化event表并推送 WebSocket- 内存运行态结构体(
control/runtime.rs)UnitRuntimeState: Stopped / Running / DistributorRunning / FaultLocked / CommLockedUnitRuntime:含accumulated_run_sec,fault_locked,comm_locked,manual_ack_required等全部字段ControlRuntimeStore:全局HashMap<Uuid, UnitRuntime>,已注册到AppState
control/validator.rs:独立的控制前置校验模块control/engine.rs:模块骨架已建立,start()函数为空桩- 前端:Unit 列表(
units.js),事件列表(events.js),设备 Unit 绑定(equipment.js) - 事件列表接口:
GET /api/event(支持unit_id,event_type过滤)
3. 与需求的差距(当前真实状态)
| 需求项 | 状态 | 说明 |
|---|---|---|
| Unit / 设备 / 点位数据模型 | ✅ 已完成 | 迁移、模型、CRUD 全部到位 |
| 脉冲写入封装 | ✅ 已完成 | 内置在 handler/control.rs |
| 手动控制前置校验 | ✅ 已完成 | validator.rs 实现 REM/FLT/quality 检查 |
| 手动启停接口 | ✅ 已完成 | start/stop 接口含脉冲写入和事件持久化 |
| 运行态内存模型 | ✅ 已完成 | runtime.rs 数据结构完整,已注入 AppState |
| 事件持久化与查询 | ✅ 已完成 | event 表 + 事件处理 + GET /api/event |
| 自动控制状态机 | ❌ 未实现 | engine.rs 是空桩,无任何调度逻辑 |
| 自动控制接口 | ❌ 未实现 | 缺 start-auto, stop-auto 接口 |
| 故障锁定联动 | ❌ 未实现 | runtime.fault_locked 有字段但无联动逻辑 |
| 通讯冻结联动 | ❌ 未实现 | runtime.comm_locked 有字段但无联动逻辑 |
| 人工确认解锁接口 | ❌ 未实现 | 缺 ack-fault 接口 |
| 手动控制检查运行态 | ❌ 未实现 | validator.rs 未读取 ControlRuntimeStore |
| 运行态 WebSocket 推送 | ❌ 未实现 | 单元状态变更未推送前端 |
| 运行态查询接口 | ❌ 未实现 | 缺 GET /api/unit/{id}/runtime |
| 前端设备控制面板 | ❌ 未实现 | 缺 REM/RUN/FLT 展示和手动启停按钮 |
| 前端单元详情/总览 | ❌ 未实现 | 缺状态机状态展示、自动/手动切换 |
| 前端参数在线编辑 | 🔶 部分 | Unit 编辑 Modal 有表单,但无运行态反馈 |
4. 推荐实现思路
继续在现有平台上"增量扩展":
- 现有
unit/equipment/point/event底座不动 - 填充
control/engine.rs实现状态机调度 - 新增自动控制和 ack-fault 接口
validator.rs增加对运行态的检查- 扩展
AppEvent业务事件,通过 WebSocket 推送运行态变更 - 前端增加业务控制页面
5. 命名与模型设计(已落地,确认)
5.1 设备分类(equipment.kind)
coal_feeder:投煤器distributor:布料机
5.2 点位角色规范(point.signal_role)
- 状态点:
remrunfltiiq - 控制点:
start_cmdstop_cmd - 可选扩展:
estopmode_automode_manualreset_cmd
5.3 Unit 运行态放内存(已确认)
运行态字段已在 control/runtime.rs:UnitRuntime 中定义完整,不落库。
服务重启后重新从 REM/RUN/FLT/Q 重建运行态,不自动补发命令。
5.4 统一 event 表,预留 alarm 表(已落地)
event:记录"发生了什么",已上线alarm:记录"需要被告警管理的异常",第二阶段实现
6. 控制逻辑设计
6.1 手动控制(已实现,待补充运行态检查)
当前已实现:
rem == 1检查flt == 0检查- 通讯质量检查
- 脉冲写入(300ms)
待补充:在 validator.rs 中增加对 ControlRuntimeStore 的检查:
fault_locked == true→ 拒绝comm_locked == true→ 拒绝manual_ack_required == true→ 拒绝(等待人工确认)
6.2 自动控制状态机(待实现)
每个 unit 独立维护状态机,在 control/engine.rs 中以后台任务驱动。
STOPPED
- 累计停止时间
current_stop_elapsed_sec - 若
stop_elapsed >= StopTime→ 校验投煤器 REM/FLT/质量 → 发启动命令 → 切换到RUNNING
RUNNING
- 累计运行时间
current_run_elapsed_sec accumulated_run_sec += delta- 若
run_elapsed >= RunTime→ 停止投煤器 → 切换回STOPPED - 若
accumulated_run_sec >= AccTime→ 进入DISTRIBUTOR_RUNNING
DISTRIBUTOR_RUNNING
- 校验布料机 REM/FLT/质量
- 启动布料机,等待
RUN == 1 - 计时
BLTime - 停止布料机
- 清零
accumulated_run_sec - 切回
STOPPED或自动节拍起点
6.3 故障机制(待实现)
任意设备检测到 FLT == 1:
- 停止该单元自动控制
state = FaultLocked,fault_locked = true- 发送并持久化
FaultLocked事件
当 FLT 从 1 → 0 恢复:
- 不自动解锁
manual_ack_required = true- 等待人工调用
POST /api/control/unit/{id}/ack-fault
6.4 通讯异常机制(待实现)
当 OPC UA 质量位异常或连接中断:
state = CommLocked,comm_locked = true- 冻结全部控制动作
- 前端按钮灰化
通讯恢复后:
- 重新读取
REM/RUN/FLT - 重同步运行态
- 不自动补发控制命令
- 持久化恢复事件
- 等待人工操作或下一次自动触发
7. 事件体系设计
7.1 继续复用 src/event.rs
当前 AppEvent 已有:
SourceCreate/Update/DeletePointCreateBatch/PointDeleteBatchEquipmentStartCommandSent/EquipmentStopCommandSentPointNewValue(遥测)
待扩展:
AutoControlStarted { unit_id }
AutoControlStopped { unit_id }
FaultLocked { unit_id, equipment_id }
FaultAcked { unit_id }
CommLocked { unit_id }
CommRecovered { unit_id }
UnitStateChanged { unit_id, from_state, to_state }
7.2 哪些事件适合落库
- 适合:所有手动/自动启停、故障、通讯、参数变更、状态切换
- 不适合:
PointNewValue、高频遥测、内部轮询过程
8. 后端改造方案
8.1 已有模块(确认现状)
| 模块 | 文件 | 状态 |
|---|---|---|
| HTTP 控制接口 | src/handler/control.rs |
✅ 有 Unit CRUD + start/stop + event list |
| 控制前置校验 | src/control/validator.rs |
✅ REM/FLT/质量检查,待加运行态检查 |
| 内存运行态 | src/control/runtime.rs |
✅ 数据结构完整 |
| 自动控制引擎 | src/control/engine.rs |
❌ 空桩,待实现 |
| 服务层 Unit | src/service/ |
✅ CRUD 完整 |
8.2 待新增接口
POST /api/control/unit/{id}/start-auto 启动自动控制
POST /api/control/unit/{id}/stop-auto 停止自动控制
POST /api/control/unit/{id}/ack-fault 人工确认故障解锁
GET /api/unit/{id}/runtime 查询运行态(state, elapsed, fault_locked 等)
说明:
start/stop-auto修改运行态auto_enabled,引擎轮询时读取ack-fault仅在manual_ack_required == true时允许操作,否则返回 400
8.3 控制引擎运行方式(待实现)
在 control/engine.rs: start() 中实现后台任务:
每 500ms 扫描所有 enabled unit
↓
从 ControlRuntimeStore 读取运行态
↓
从 connection_manager.get_point_monitor_data_read_guard() 取实时点值
↓
检查质量位 → 更新 comm_locked
↓
检查 FLT → 更新 fault_locked
↓
驱动状态机 tick
↓
有状态变化 → 更新 ControlRuntimeStore → 发 AppEvent → 推 WebSocket
8.4 手动控制补充运行态检查
在 control/validator.rs: validate_manual_control() 中增加:
let runtime = state.control_runtime.get(unit_id).await;
if let Some(runtime) = runtime {
if runtime.fault_locked {
return Err(ApiErr::Forbidden("Unit is fault locked", ...));
}
if runtime.comm_locked {
return Err(ApiErr::Forbidden("Unit is comm locked", ...));
}
if runtime.manual_ack_required {
return Err(ApiErr::Forbidden("Fault ack required before control", ...));
}
}
8.5 关键复用点
可直接复用当前已有能力:
connection_manager.get_point_monitor_data_read_guard()→ 读取实时点值connection_manager.write_point_values_batch()→ 写点(自动控制也走此接口)event_manager.send()→ 统一事件入口ws_manager.send_to_public()→ 推送运行态变更unit_id + equipment.kind + point.signal_role三元组 → 业务映射
9. 前端改造方案
9.1 已有页面(确认现状)
| 页面/功能 | 状态 |
|---|---|
| Unit 列表(含 CRUD Modal) | ✅ 基础实现 |
| 事件列表 | ✅ 基础实现 |
| 设备列表(含 Unit 归属绑定) | ✅ 实现 |
| 点位绑定(equipment/signal_role) | ✅ 实现 |
| 趋势图 | ✅ 实现 |
9.2 待新增页面/功能
设备控制面板(单台投煤器/布料机):
- REM / RUN / FLT / Q / II 实时显示
- 启动 / 停止按钮(灰化逻辑:comm_locked / fault_locked / manual_ack_required)
- 通讯异常、故障锁定提示
- 最近控制事件
单元总览(Unit 卡片增强):
- 当前状态机状态(STOPPED / RUNNING / DISTRIBUTOR_RUNNING / FAULT_LOCKED / COMM_LOCKED)
- 自动/手动切换按钮
- 故障确认按钮(
manual_ack_required == true时显示) - 累计运行时间进度
- 投煤器 + 布料机运行状态摘要
参数在线编辑:
- 现有 Unit Modal 已有表单
- 需补充:保存后通知引擎重新加载(或引擎每次 tick 从 DB 读取配置)
WebSocket 运行态更新:
- 新增
WsMessage::UnitRuntimeChanged { unit_id, runtime }消息类型 - 前端收到后实时更新 Unit 卡片状态,无需轮询
10. 分阶段实施建议
第一阶段:补全控制闭环(当前阶段)
目标:让自动控制可以跑起来,故障/通讯保护机制生效。
待完成工作:
-
补充运行态检查到
validator.rs- 手动控制时检查
fault_locked,comm_locked,manual_ack_required
- 手动控制时检查
-
实现
control/engine.rs- 后台 500ms 轮询任务
- 质量检查 →
comm_locked更新 - FLT 检测 →
fault_locked更新 - 状态机 tick(STOPPED / RUNNING / DISTRIBUTOR_RUNNING)
-
新增接口
POST /api/control/unit/{id}/start-autoPOST /api/control/unit/{id}/stop-autoPOST /api/control/unit/{id}/ack-faultGET /api/unit/{id}/runtime
-
扩展
AppEventFaultLocked,FaultAcked,CommLocked,CommRecovered,UnitStateChanged,AutoControlStarted,AutoControlStopped
-
WebSocket 运行态推送
WsMessage::UnitRuntimeChanged
-
前端设备控制面板
- REM/RUN/FLT 展示 + 启停按钮 + 灰化逻辑
-
前端 Unit 卡片增强
- 状态机状态展示、自动/手动切换、故障确认
交付后可验证:
- 单台设备手动启停(含故障/通讯拦截)
- 单元自动定时启停
- 累计触发布料机运行
- 故障恢复后人工确认才能操作
- 通讯异常冻结后恢复自动同步
第二阶段:增强版
- 单元详情页(运行趋势、事件时间线、参数在线编辑)
- 更丰富的趋势图(电流 II、运行状态变化曲线)
- 报警规则与
alarm表 - 报警确认与恢复流程
第三阶段:现场适配版
- 导入导出配置
- 项目模板
- 配置校验工具
- 启停联锁自检
- 操作权限控制
11. 当前优先落地顺序
从当前代码基础出发,第一阶段建议按下面顺序开发:
validator.rs补充运行态检查engine.rs实现质量检查与comm_locked更新engine.rs实现 FLT 检测与fault_locked更新engine.rs实现状态机主循环handler/control.rs新增start-auto,stop-auto,ack-faulthandler/control.rs新增GET /api/unit/{id}/runtime- 扩展
AppEvent业务事件类型并落库 websocket.rs新增UnitRuntimeChanged消息- 前端设备控制面板
- 前端 Unit 卡片增强
- 第二阶段再引入独立
alarm表
12. 对当前代码的具体落点
| 文件 | 改动内容 |
|---|---|
src/control/engine.rs |
填充后台轮询任务,实现状态机 tick |
src/control/validator.rs |
增加运行态检查(fault/comm/ack) |
src/handler/control.rs |
新增 start-auto, stop-auto, ack-fault, runtime 接口 |
src/event.rs |
扩展 AppEvent 业务事件枚举 |
src/websocket.rs |
新增 WsMessage::UnitRuntimeChanged |
web/js/units.js |
Unit 卡片增加状态机状态、auto 切换、fault ack 按钮 |
web/js/equipment.js |
增加设备控制面板(REM/RUN/FLT + 启停) |
web/js/app.js |
绑定新按钮事件,处理 WebSocket 运行态消息 |
不需要改动的:
src/model.rs(数据模型完整)src/control/runtime.rs(运行态结构体完整)- 所有迁移文件(schema 已完整)
src/handler/point.rs(保留底层写点,不承载业务控制)
13. 本次结论
当前项目已经完成了业务底座的建设(数据模型、脉冲写入、手动控制、事件持久化、运行态数据结构),具备了较好的基础。
下一步核心工作集中在:
- 填充
control/engine.rs——这是最核心的缺口,所有自动控制、故障保护、通讯冻结都需要它来驱动 - 前端业务控制面板——让操作员看到并操作设备状态
其余部分(接口、事件、WebSocket)属于连接层,工作量相对可控。