plc_control/docs/superpowers/plans/2026-03-24-control-engine.md

129 lines
3.3 KiB
Markdown

# 控制引擎实现计划
## 当前状态
该计划对应的核心功能已经落地,且在后续修复中做了几次重要收敛。当前代码状态以仓库实现为准,下面记录的是最新有效设计。
## 已完成范围
- 已实现 `ControlRuntimeStore``UnitRuntime`
- 已实现单元自动控制状态机
- 已实现故障锁定、通信锁定、人工确认流程
- 已实现自动控制相关 API
- 已实现 `UnitRuntimeChanged` WebSocket 推送
- 已实现前端单元运行时展示
- 已实现手动控制前的运行时阻断校验
## 关键实现更新
### 1. 时长配置约束
控制单元时长字段现在统一要求:
- `run_time_sec > 0`
- `stop_time_sec > 0`
- `acc_time_sec > 0`
- `bl_time_sec > 0`
- `acc_time_sec > run_time_sec`
这些约束已在创建和更新接口中统一校验。
### 2. 自动控制启动条件统一
单个启动和批量启动现在使用同一套阻断规则。以下任一条件成立时都不能启动自动控制:
- `fault_locked = true`
- `comm_locked = true`
- `manual_ack_required = true`
### 3. 设备映射刷新策略已调整
最初计划里是“单元任务启动时加载一次设备映射”。这个方案已经被修正。
当前实现:
- 控制引擎在每轮单元循环中重新读取设备和角色映射
- 设备或点位的控制相关配置发生变化后,会主动唤醒对应单元任务
- 因此不再依赖“等下一个 supervisor 周期重启任务”来刷新映射
这解决了运行中的单元长期使用旧 `equipment.kind`、`signal_role`、`equipment_id` 绑定的问题。
## 当前引擎行为
### supervisor
- 周期性扫描已启用单元
- 确保每个启用单元都有对应任务在运行
- 单元被禁用或删除后,其任务会自行退出
### unit_task
每轮循环都会执行:
1. 重读单元配置
2. 重读设备和角色映射
3. 检查故障与通信状态
4. 根据 `auto_enabled`、锁定状态和当前状态机状态推进流程
### wait_phase
- 使用 `sleep_until(deadline)` 控制阶段结束时间
- 中途通过 `fault_tick``notify` 打断
- 打断后重新检查故障、通信和自动控制开关
## 运行时结构
当前 `UnitRuntime` 字段:
```rust
pub struct UnitRuntime {
pub unit_id: Uuid,
pub state: UnitRuntimeState,
pub auto_enabled: bool,
pub accumulated_run_sec: i64,
pub display_acc_sec: i64,
pub fault_locked: bool,
pub flt_active: bool,
pub comm_locked: bool,
pub manual_ack_required: bool,
}
```
说明:
- `accumulated_run_sec``display_acc_sec` 单位都是毫秒
- 运行时状态保存在内存中,不持久化
## 配置变更后的唤醒链路
以下操作现在都会通知相关控制单元尽快刷新配置:
- 更新设备
- 批量调整设备所属单元
- 删除设备
- 更新点位的 `equipment_id` / `signal_role`
- 批量调整点位设备绑定
- 删除点位
## 相关文件
- `src/control/runtime.rs`
- `src/control/engine.rs`
- `src/control/validator.rs`
- `src/handler/control.rs`
- `src/handler/equipment.rs`
- `src/handler/point.rs`
- `src/service/control.rs`
- `src/event.rs`
- `src/websocket.rs`
## 验证状态
当前仓库内已补的相关测试包括:
- 时长字段校验测试
- `comm_locked` 阻止自动启动测试
- 设备映射重载反映最新角色绑定测试
最近一次相关修改完成后,`cargo test` 与 `cargo check` 均已通过。