29 KiB
运转系统顺控引擎设计
日期:2026-05-18
参考来源:
运转系统逻辑说明.doc(说明书 14 章)docs/运转系统实现方案.md(高层方案)docs/superpowers/specs/2026-04-14-dual-app-shared-core-design.md(双应用共享核心架构)- 现有
crates/app_feeder_distributor实现作为工程参考
1. 目标
在已经搭好的 crates/app_operation_system 骨架内,落地说明书中规定的整线自动控制能力:
- 覆盖 8 个业务子系统:回车线、前端码车道、机械臂、摆渡车、1 号干燥/焙烧窑、2 号干燥/焙烧窑、窑尾下摆渡车、卸砖机位。
- 引擎语义遵循说明书第 1.4 与 13 章:"顺序控制 + 联锁保护 + 检测信号闭环确认 + 异常停留人工恢复"。
- 双窑线(1 号 / 2 号)采用同一套段模板,仅通过参数差异化,不写两套代码。
- 复用
plc_platform_core的接入层(OPC UA / 点位 / 设备 / 事件 / WebSocket / 日志)。 - 不引入
app_feeder_distributor的unit + run_time/stop_time/acc_time/bl_time业务模型。
非目标(首期):
- 不做规则引擎或 DSL,只支持固定
rule_kind联锁判定。 - 不做高级排程(最大化吞吐、动态优化),只做基于空位/资源占用的放行决策。
- 不做权限/审计/历史回放。
2. 设计结论
| 决策 | 选择 | 原因 |
|---|---|---|
| 业务模型 | station + segment + step + interlock | 说明书是工位驱动的整线顺控,不是节拍式设备启停 |
unit 表 |
不复用 | 语义不匹配;ops 自己建 process_segment |
| 引擎调度单位 | 段(segment) | 每个 enabled segment 一个 tokio task,对齐 feeder 引擎结构 |
| 双窑线参数化 | 同一段模板 + line_code 区分实例 | 对齐说明书第 11 章 |
| 联锁配置 | 数据库表 + 固定 rule_kind 枚举 | 首期不引入表达式语言 |
| WebSocket 消息扩展 | core 保持通用通道,ops 使用业务 payload 分支 | 避免 plc_platform_core 反向依赖 ops 领域类型;前端仍只连一处 |
| 报警 | 走 event 表 + subject_type/subject_id + level=warn/error |
复用现有事件表,同时支持按段 / 工位查询 |
| 公共资源互斥 | app 内部命名锁注册表 + 租约/恢复策略 | 摆渡车 / 机械臂 / 卸砖机位等共享资源,防止 task 异常退出后长期占锁 |
3. 不沿用 feeder 模型的理由
ControlUnit 当前字段是 run_time_sec / stop_time_sec / acc_time_sec / bl_time_sec,语义是"运行 N 秒 → 停 M 秒 → 累计 K 秒后启动布料机 → 布料 L 秒"。
运转系统的核心动作完全不是这种节拍:
- 说明书 8.2 要求"码车位到车确认 → 输送机构停止",是检测信号驱动,不是定时。
- 说明书 10.1 要求"开门 → 门开到位确认 → 顶车 → 前位确认 → 顶车后退 → 后位确认 → 关门 → 门关到位确认",是 8 步串行带闭环。
- 说明书 13 章明确要求"动作完成不得仅靠时间,必须结合限位、检测或反馈信号"。
因此引擎需要换语义:段(segment)状态机 + 步骤(step)顺序 + 每步等待闭环信号。
4. 领域模型
4.1 实体一览
source ──┐
│
point ───┼─→ equipment
│
├─→ station_signal ──→ station ──┐
│ │
└──────────────→ segment_step ──→ process_segment ──→ segment_runtime
│ │
│ ├──→ segment_interlock
│ └──→ segment_resource
│
└──→ action_kind (枚举)
source / point / equipment 沿用平台层定义,不改动。
信号边界:
point.signal_role是设备信号角色,例如rem / flt / home / run / start_cmd / stop_cmd / open_cmd / close_cmd。station_signal.signal_role是工位信号角色,例如presence / vacancy / arrived / allow_in / done / fault。- 同一个
point可以同时被设备角色和工位角色引用,但两者语义分开维护。 vacancy可由独立点位绑定,也可由presence = false推导。首期通过station_signal.derived_from_role表达推导关系,避免现场必须额外提供空位点。
4.2 新增对象
4.2.1 station(工位)
表示流程中的一个位置或交接位。
| 字段 | 类型 | 说明 |
|---|---|---|
id |
UUID | |
code |
TEXT UNIQUE | 例 ST-DRY1-IN |
name |
TEXT | 例 "1 号干燥窑进口位" |
line_code |
TEXT NULL | 例 KILN_1 / KILN_2 / COMMON |
segment_code |
TEXT NULL | 用于分组(前端码车 / 双窑线 / 窑尾) |
station_type |
TEXT | load / dry_in / dry_step / dry_out / fire_in / fire_step / fire_out / transfer / unload / return |
enabled |
BOOL | |
description |
TEXT NULL |
4.2.2 station_signal(工位 ↔ 信号绑定)
| 字段 | 类型 | 说明 |
|---|---|---|
id |
UUID | |
station_id |
UUID FK | |
signal_role |
TEXT | presence / vacancy / arrived / allow_in / done / fault |
point_id |
UUID FK | 绑定到具体点位 |
derived_from_role |
TEXT NULL | 例 presence,表示由同工位其他角色反向推导 |
invert_value |
BOOL | 推导或读取时是否取反,默认 false |
| UNIQUE | (station_id, signal_role) |
4.2.3 process_segment(流程段)
| 字段 | 类型 | 说明 |
|---|---|---|
id |
UUID | |
code |
TEXT UNIQUE | 例 SEG-DRY1-INFEED |
name |
TEXT | |
segment_type |
TEXT | front_load / robot / front_release / front_transfer / kiln_infeed / kiln_step / kiln_outfeed / tail_transfer / tail_step / unload / return |
line_code |
TEXT NULL | KILN_1 / KILN_2 / COMMON |
priority |
INT | 公共资源冲突时使用 |
enabled |
BOOL | |
mode |
TEXT | auto / remote_manual / local_manual / disabled |
require_manual_ack_after_fault |
BOOL | 故障解除后是否需要人工确认,默认 true |
description |
TEXT NULL |
模式语义:
local_manual:现场就地优先,软件不推进自动顺控;自动运行中检测到任一相关设备rem=false时,停止当前自动段并进入人工恢复路径。remote_manual:允许通过软件发单步 / 单设备命令,但仍必须执行设备故障、通信质量、安全链和关键门位联锁。auto:允许 supervisor 自动推进段状态机。disabled:段任务不启动;已运行任务在下一次配置重载后退出。
4.2.4 segment_step(段步骤)
| 字段 | 类型 | 说明 |
|---|---|---|
id |
UUID | |
segment_id |
UUID FK | |
step_no |
INT | 序号 |
step_code |
TEXT | 步骤代号 |
action_kind |
TEXT | 见下方动作模板表 |
target_equipment_id |
UUID NULL FK | 例如顶车机 |
target_station_id |
UUID NULL FK | 例如目标摆渡位 |
confirm_signal_role |
TEXT NULL | 等待哪个信号角色为真 |
confirm_point_id |
UUID NULL FK | 直接指定确认点位(覆盖 role) |
expected_value |
BOOL | 信号到位的期望值(默认 true) |
timeout_ms |
INT | 超时即报警转 Faulted |
command_role |
TEXT NULL | 设备命令角色,例 start_cmd / open_cmd / forward_cmd |
stop_command_role |
TEXT NULL | 到位或异常时需要发出的停止命令角色,例 stop_cmd |
pulse_ms |
INT NULL | 脉冲命令宽度;为空时按 action 默认值 |
hold_until_confirm |
BOOL | true 表示命令保持到确认信号或故障;false 表示脉冲后等待 |
cancel_on_fault |
BOOL | 故障 / 模式切换 / 通信异常时是否执行停止命令,默认 true |
next_step_no_on_success |
INT NULL | 成功后跳转;为空表示顺序进入下一 step |
next_step_no_on_failure |
INT NULL | 失败后跳转;首期通常为空并进入 Faulted |
on_timeout |
TEXT | fault / retry / block,首期默认 fault |
description |
TEXT NULL | |
| UNIQUE | (segment_id, step_no) |
action_kind 枚举(首期):
| 值 | 含义 |
|---|---|
open_door |
开门:向门机 open_cmd 发脉冲 |
close_door |
关门 |
push_forward |
顶车机前进 |
push_retract |
顶车机后退复位 |
pull_run |
拉引机拉车 |
pull_retract |
拉引机复位 |
transfer_move_to |
摆渡车移动到目标工位 |
step_once |
节拍步进机执行一步 |
robot_permit |
允许机械臂自动作业 |
robot_release |
允许码车道放车 |
wait_signal |
不发命令,仅等待 confirm_* |
pulse_cmd |
通用脉冲命令(fallback) |
动作执行策略:
- 对
open_door / close_door / robot_permit等短命令,默认pulse_ms=300,命令发出后等待确认信号。 - 对输送、顶车、拉引、步进等持续动作,默认
hold_until_confirm=true,到位后执行stop_command_role。 - 对故障、急停、通信质量异常、自动切就地等中断场景,若
cancel_on_fault=true,先发停止 / 复位命令,再进入Faulted或ManualAckRequired。
4.2.5 segment_interlock(段联锁)
| 字段 | 类型 | 说明 |
|---|---|---|
id |
UUID | |
segment_id |
UUID FK | |
applies_to |
TEXT | start_allow / start_deny / run_halt |
rule_kind |
TEXT | 见下方 |
point_id |
UUID NULL FK | |
station_id |
UUID NULL FK | |
equipment_id |
UUID NULL FK | |
expected_value |
BOOL NULL | |
description |
TEXT NULL |
rule_kind 枚举(首期):
point_eq—— 指定 point 的值等于expected_valuestation_vacant—— 工位空(绑定的vacancy信号 = true 且presence= false)station_occupied—— 工位有车equipment_origin—— 设备在原位(角色home)equipment_no_fault—— 设备无故障(flt= false)equipment_remote—— 设备远程(rem= true)safety_chain_ok—— 安全链路正常
未来可扩展 expression 类型,但首期不引入。
4.2.6 segment_runtime(段运行态,内存)
不落库(与 feeder UnitRuntime 一致,重启重置):
pub enum SegmentState {
Idle,
Checking,
Executing,
Confirming,
Resetting,
Completed,
Blocked,
Faulted,
ManualAckRequired,
}
pub struct SegmentRuntime {
pub segment_id: Uuid,
pub state: SegmentState,
pub auto_enabled: bool,
pub current_step_no: Option<i32>,
pub step_started_at: Option<DateTime<Utc>>,
pub last_completed_at: Option<DateTime<Utc>>,
pub blocked_reason: Option<String>,
pub fault_message: Option<String>,
pub manual_ack_required: bool,
pub comm_locked: bool,
pub rem_local: bool,
pub held_resources: Vec<String>,
}
4.2.7 segment_resource(段资源声明)
| 字段 | 类型 | 说明 |
|---|---|---|
segment_id |
UUID FK | |
resource_key |
TEXT | 例 transfer_front / transfer_tail / robot_arm / unload_position / return_line |
| UNIQUE | (segment_id, resource_key) |
4.2.8 event 表归因扩展
现有 event 表保留 unit_id / equipment_id / source_id,为了支持 ops 按段、工位检索,新增通用归因字段:
| 字段 | 类型 | 说明 |
|---|---|---|
subject_type |
TEXT NULL | segment / station / equipment / source / platform |
subject_id |
UUID NULL | 对应业务对象 ID |
ops 事件写入规则:
- 段级事件:
subject_type='segment',subject_id=segment_id。 - 工位状态事件:
subject_type='station',subject_id=station_id。 - 设备动作事件:优先保留
equipment_id,同时可按上下文设置subject_type='segment'。
4.3 双窑线参数化
不写两套硬编码逻辑。1 号与 2 号窑线的差异由:
process_segment.line_code(KILN_1/KILN_2)segment_step.target_equipment_id与target_station_id(指向各自的门机、顶车机、工位)segment_interlock.point_id/station_id(指向各自工位的检测点)
承载。引擎读到的就是统一的 step 列表,与窑线无关。
5. 顺控引擎设计
5.1 结构(与 feeder 对齐)
crates/app_operation_system/src/
app.rs // AppState 接入 segment_runtime + event_manager + resource_registry
router.rs
event.rs // AppEvent(ops.*)
control/
mod.rs
engine.rs // supervisor + per-segment task
runtime.rs // SegmentRuntime / SegmentRuntimeStore
state.rs // SegmentState enum
step_executor.rs // 按 action_kind 调度
interlock.rs // 通用允许/禁止/停机判定
resource.rs // 摆渡车 / 机械臂 / 卸砖位 互斥
simulate.rs // 开发态信号回灌
handler/
doc.rs (已存在)
station.rs // CRUD + 信号绑定
segment.rs // CRUD + step / interlock 配置
control.rs // 段启停 / 手动动作 / 故障确认
runtime.rs // overview / segment detail / station detail
5.2 段状态机
对应说明书 13.6:
| SegmentState | 含义 | 出口 |
|---|---|---|
Idle |
等待 auto 启动 | → Checking |
Checking |
评估 start_allow / start_deny 联锁 |
通过 → Executing;否则 → Blocked |
Executing |
已发出当前 step 的命令 | → Confirming |
Confirming |
等待 confirm_signal 到位 |
收到 → 下一步;超时 → Faulted |
Resetting |
等待执行机构复位(如顶车机后退) | → 下一步或 Completed |
Completed |
段完成,输出完成信号 | 回 Idle(自动循环段) |
Blocked |
允许条件不满足 | 条件再次满足 → Checking |
Faulted |
故障或超时 | 故障解除 + 满足复位 → ManualAckRequired 或 Idle |
ManualAckRequired |
等待人工确认 | API ack → Idle |
5.3 段内执行循环
伪代码:
loop {
reload segment + steps + interlocks
run check_interlocks(state, run_halt) // 运行中停机检测
match state {
Idle if auto_enabled => state = Checking,
Checking => {
if pass(start_allow) && !any(start_deny) {
step = first_step
state = Executing
} else {
blocked_reason = ...
state = Blocked
}
}
Executing => {
execute(step.action_kind, step.target_*) // 发命令
state = Confirming
}
Confirming => {
wait_signal(step.confirm_*, step.timeout_ms)
on timeout → fault / retry / block by step.on_timeout
on ok → next_step_no_on_success or next step or Completed
}
Faulted => break and wait manual recovery
...
}
notify or fault_tick
}
wait_signal 复用与 feeder wait_phase 类似的 tokio::select! { sleep_until(deadline), notify, fault_tick } 模式,但终止条件是"绑定信号到达期望值"而非时间到。
5.4 step_executor
集中处理 action_kind 到具体写点动作:
- 短命令类
action_kind调plc_platform_core::control::command::send_pulse_command。 - 持续命令类
action_kind先写command_role,确认到位、超时或故障中断时按stop_command_role收尾。 transfer_move_to:写目标工位编号到摆渡车定位命令点位,等待arrived信号。wait_signal:不发命令。- 各设备的
start_cmd / stop_cmd / open_cmd / close_cmd信号角色复用 feeder 已有的signal_role命名空间,equipment 表无需新表结构。
命令执行前必须重新检查:
- 设备
rem=true - 设备
flt=false - 命令点与确认点
quality=Good - 当前段仍处于允许执行模式
- 当前 step 仍是 runtime 中的
current_step_no
6. 联锁与异常
6.1 联锁判定顺序(对齐说明书 8.1 / 13)
- 通信质量(任一绑定点 quality != Good) →
comm_locked - 就地 / 远程状态(
rem=false)→ 停止自动并转人工恢复 - 安全联锁 / 急停 →
Faulted - 设备故障(
flt= true) →Faulted - 门位联锁
- 机械臂联锁
- 工艺允许条件(空位 / 到位)
- 普通顺控条件
高优先级不满足时低优先级不再判断。
6.2 通用允许检查(自动注入到每段)
每段无论是否有显式 segment_interlock,引擎都执行以下通用检查(说明书 13.1):
- 目标工位空位
- 本工位有车或动作前提
- 执行机构原位
- 设备无故障
- 设备处于远程
- 信号质量正常
- 段引用的资源未被占用
6.3 异常恢复(说明书 13.5)
- 故障优先停止当前 step 的命令。
Faulted保留current_step_no,不跳步。remote_manual下允许人工执行复位动作,但复位动作仍执行安全、故障、门位和通信检查。- 故障物理消失后:
- 若
require_manual_ack_after_fault(默认 true) →ManualAckRequired - 否则自动回
Idle。
- 若
POST /api/control/segment/{id}/ack-fault用于人工确认。
7. 公共资源调度
说明书 3.3 / 3.4 指出:前端码车系统、窑尾摆渡、回车线、卸砖线为公共段,1 号 / 2 号窑线在此处汇合。
实现:
pub struct ResourceRegistry {
inner: RwLock<HashMap<String, ResourceLease>>,
}
pub struct ResourceLease {
pub owner_segment_id: Uuid,
pub acquired_at: DateTime<Utc>,
pub heartbeat_at: DateTime<Utc>,
}
资源 key 示例:transfer_front / transfer_tail / robot_arm / unload_position / return_line。
段配置中以新表 segment_resource(segment_id, resource_key) 声明所需资源;段进入 Executing 前必须 try_acquire,进入 Completed 时 release。冲突时停留 Blocked,附 blocked_reason = "resource_busy: transfer_front"。
资源恢复策略:
- 资源持有段每个状态循环刷新
heartbeat_at。 - 若 owner task 已退出、段被禁用、或 owner 已回到
Idle/Completed,supervisor 可回收租约。 Faulted时是否释放资源按资源类型决定:机械臂区、卸砖位等可释放;摆渡车正在载车时不释放,必须人工确认或到达安全位后释放。- 资源等待超时只报警和进入
Blocked,不抢占低优先级段。首期不做死锁自动解除。
8. 事件与 WebSocket
8.1 业务事件命名空间 ops.*
| event_type | level |
|---|---|
ops.segment.auto_started |
info |
ops.segment.auto_stopped |
info |
ops.segment.step_advanced |
info |
ops.segment.completed |
info |
ops.segment.blocked |
warn |
ops.segment.fault_locked |
error |
ops.segment.fault_acked |
info |
ops.segment.comm_locked |
warn |
ops.segment.comm_recovered |
info |
ops.station.state_changed |
info |
ops.alarm.action_timeout |
error |
ops.alarm.signal_conflict |
error |
ops.alarm.resource_busy |
warn |
所有事件经 record_event 落 event 表(复用平台机制)。
8.2 WebSocket 消息扩展
不把 ops 的 SegmentRuntime 类型放进 core。plc_platform_core::websocket::WsMessage 增加一个通用业务消息分支,业务 payload 由 app crate 构造:
pub enum WsMessage {
// 已有 ...
AppEvent(AppWsEvent),
}
pub struct AppWsEvent {
pub app: String, // "operation-system"
pub event_type: String, // "segment_runtime_changed" / "station_state_changed"
pub data: serde_json::Value,
}
ops 侧约定:
event_type="segment_runtime_changed":data序列化SegmentRuntime。event_type="station_state_changed":data包含station_id / presence / vacancy / arrived / updated_at。- feeder 前端忽略未知
AppEvent或非本 app 的消息;ops 前端只处理app="operation-system"。
这样仍保留单一 websocket 入口,但 core 不需要知道 ops 的领域模型。
9. API 设计
9.1 配置 API
GET /api/station
POST /api/station
GET /api/station/{id}
PUT /api/station/{id}
DELETE /api/station/{id}
POST /api/station/{id}/signal // 绑定信号
DELETE /api/station/{id}/signal/{role}
GET /api/segment
POST /api/segment
GET /api/segment/{id}
GET /api/segment/{id}/detail // 含 step / interlock / resource
PUT /api/segment/{id}
DELETE /api/segment/{id}
POST /api/segment/{id}/step
PUT /api/segment/{id}/step/{step_no}
DELETE /api/segment/{id}/step/{step_no}
POST /api/segment/{id}/interlock
DELETE /api/segment/{id}/interlock/{interlock_id}
9.2 控制 API
POST /api/control/segment/{id}/start-auto
POST /api/control/segment/{id}/stop-auto
POST /api/control/segment/{id}/reset // 强制回 Idle,仅在 Faulted/Blocked 状态可用
POST /api/control/segment/{id}/ack-fault
POST /api/control/segment/{id}/manual-step // remote_manual 下单步执行
POST /api/control/segment/batch-start-auto
POST /api/control/segment/batch-stop-auto
POST /api/control/equipment/{id}/manual-action // remote_manual 下单设备动作,仍执行联锁
9.3 运行态 API
GET /api/runtime/overview // 所有段 + 关键工位 + 报警计数
GET /api/runtime/segment/{id}
GET /api/runtime/station/{id}
GET /api/event?type=ops.*
10. 前端
复用 web/core 的源码、点位、设备、事件、日志、文档抽屉。
web/ops/ 增加:
- 总览页:双窑线 + 公共段流程图(首版静态 SVG + 区域绑定段 / 工位状态)
- 段卡片列表:展示
state / current_step / blocked_reason / fault_message - 工位状态视图:有车 / 空位 / 到位
- 配置页:站点 / 段 / step / interlock 表格 + 表单
- 手动操作:段启停 / 故障确认 / 复位
WebSocket 订阅 AppEvent(app="operation-system"),按 event_type 分发 segment_runtime_changed 和 station_state_changed 实时刷新。
11. 复用 vs 新增对照
| 模块 | 来源 | 用途 |
|---|---|---|
plc_platform_core::connection |
复用 | OPC UA 读写 |
plc_platform_core::control::command::send_pulse_command |
复用 | 所有动作命令底层 |
plc_platform_core::event::record_event + EventInsert |
复用 | 事件落库 |
plc_platform_core::event::MetadataCache |
复用 + 扩展 | 通用化为按 (table, id) 查 code;feeder 用 unit/equipment,ops 加 station/segment |
plc_platform_core::websocket::WsMessage |
重构 | 删除 UnitRuntimeChanged(feeder 业务),新增通用 AppEvent(AppWsEvent);feeder 和 ops 都走 AppEvent |
plc_platform_core::handler::platform_routes |
复用 | source / point / equipment / tag / page |
plc_platform_core::model::ControlUnit |
迁出 core | P-1 阶段下放到 feeder;语义本就是 feeder 业务 |
plc_platform_core::control::runtime::{UnitRuntime, ControlRuntimeStore} |
迁出 core | 同上,含 DistributorRunning 这种 feeder 专属状态 |
plc_platform_core::service::control unit CRUD |
迁出 core | 下放到 feeder;event 查询留 core |
app_feeder_distributor::control::* |
不复用 | 结构参考 |
P-1 阶段说明:上表中的"迁出 core"是清理动作,发生在 P0 之前。详见 §12。
12. 阶段计划
| 阶段 | 目标 | 主要工作 |
|---|---|---|
| P-1 Core 业务清理 | core 不再持有 feeder 业务模型 | 把 UnitRuntime / UnitRuntimeState / ControlRuntimeStore / ControlUnit / unit CRUD / WsMessage::UnitRuntimeChanged 从 plc_platform_core 迁到 app_feeder_distributor;WsMessage 新增 AppEvent(AppWsEvent) 分支并删除 UnitRuntimeChanged;feeder 引用全部调整;前端 ws 客户端按 app + event_type 分发;MetadataCache 通用化为 entity_code(table, id)。零行为变更,feeder 通过现有 smoke test |
| P0 骨架对齐 | app_operation_system 与 feeder 在依赖、AppState、bootstrap、tray、启动/退出链路对齐 |
Cargo.toml 补依赖;AppState 加 EventManager + SegmentRuntimeStore + ResourceRegistry;启动接 connect_all_enabled_sources;启动 engine supervisor;退出时断开数据源 |
| P1 数据库迁移 & 模型 | ops 配置表 + event 归因字段 + Rust model | 新 migration 2026-05-1x_create_operation_system.sql;新增 station / station_signal / process_segment / segment_step / segment_interlock / segment_resource;扩展 event.subject_type/subject_id;app_operation_system::model 模块 |
| P2 配置 API | 站点 / 段 / step / interlock CRUD | service::station / segment;handler;router |
| P3 引擎 MVP | 跑通 1 个段端到端(前端码车位进车段,说明书 8.2) | engine、step_executor、interlock、runtime;通用 AppEvent WebSocket 推送 |
| P4 动作模板补全 | 覆盖 8 章 + 10 章典型动作 | 各 action_kind 实现 + simulate 反馈 |
| P5 双窑线段模板化 | 通过段配置实现 1 号 / 2 号窑线 4 段(进口 / 内前移 / 出口) | 段配置 seed;端到端跑通 |
| P6 资源调度 | 公共段互斥 | ResourceRegistry;segment_resource 表;Blocked 路径完善 |
| P7 公共段 | 摆渡车 / 卸砖 / 回车线 | 段实例 + 段间交接 |
| P8 报警 & 异常恢复 | 超时报警、信号冲突、人工确认完整链路 | AppEvent::Alarm*;ack-fault API |
| P9 前端监控页 | 段卡片 + 工位状态 + 流程图 | web/ops/html + JS |
| P10 配置前端 | 段 / 工位 / 联锁可视化配置 | web/ops/html 表格表单 |
每阶段都要求:
cargo build -p app_operation_system通过- 至少 1 个单元测试或 smoke test
- 不破坏
app_feeder_distributor编译
13. 风险与约束
13.1 主要风险
- P-1 迁移破坏 feeder:从 core 把 unit 模型迁到 feeder 时容易漏改 import 或 ws 客户端调用。要求迁移单独成 commit,feeder 启动 + 单元测试 + ws 推送链路逐项验证。
- 现场 I/O 清单缺失:说明书描述了逻辑关系但未明确每个工位 / 设备对应的具体点位。落地前必须补 I/O 对照表。
- 段切分粒度:段切得太细 → 状态机膨胀;切得太粗 → 段内步骤过多。首期建议按说明书章节级切(一节 = 一段)。
- WebSocket 领域边界:不得把
SegmentRuntime放入 core,否则 core 会反向依赖 ops 业务模型;采用通用AppEventpayload。 - 公共资源死锁:例如摆渡车被段 A 占用、段 A 又等卸砖位空(被段 B 占用)。首期通过段优先级与超时报警缓解,不引入死锁检测。
- 持续命令收尾:输送、顶车、拉引等不是纯脉冲动作,必须在超时、故障和模式切换时明确停止命令。
13.2 约束
- 首期不做规则引擎,所有联锁靠固定
rule_kind枚举。 - 首期段 / step 改动不做热加载——supervisor 每 10s 重读配置,与 feeder 一致。
- 首期
segment_runtime不持久化,重启全部回Idle。 - 首期不做资源抢占;资源冲突只阻塞、报警和等待人工处理。
14. 验收标准
完成 P0–P5 后应达到:
- 仓库新增 6 张 ops 业务配置表,并扩展
event.subject_type/subject_id,与 feeder 业务表互不干扰。 app_operation_system可独立编译为 exe,可启动并连接 OPC UA 数据源。- 启动后具备
EventManager、SegmentRuntimeStore、ResourceRegistry、engine supervisor,退出时可断开数据源。 - 至少 1 条段(例如 2 号干燥窑进口段,含 8 步)可通过配置驱动跑通:
- 自动启停
- 步骤顺序推进
- 闭环信号确认
- 持续动作到位后停止命令
- 故障停步 + 人工确认
- WebSocket 通过
AppEvent(app="operation-system")推送段运行态变化、工位状态变化。 - 前端可见段卡片与当前步骤进度。
event表能按ops.*和subject_type/subject_id查到全链路事件。
完成 P6–P10 后应达到:
- 1 号 / 2 号窑线全部 6 段(进口 / 内前移 / 出口 × 2 窑)跑通。
- 公共段(前端码车、摆渡车、窑尾、卸砖、回车)跑通。
- 报警分类齐全(说明书 13.4 全部 10 类)。
- 监控前端 + 配置前端可用。
15. 后续可演进项(非首期)
- 联锁
expression类型:引入简单布尔表达式语言,替代rule_kind枚举。 - 段历史持久化:将每段每次完成 / 故障写入
segment_run_history,支持时间线回放。 - 现场调试视图:模拟点位值、单步推进、跳步授权(带操作员签名)。
- 公共能力下沉:若后续出现第三套类似业务,再把 segment 引擎抽到
plc_platform_core::control::segment。