# 控制引擎实现计划 ## 当前状态 该计划对应的核心功能已经落地,且在后续修复中做了几次重要收敛。当前代码状态以仓库实现为准,下面记录的是最新有效设计。 ## 已完成范围 - 已实现 `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` 均已通过。