Files
FT546-WCS/docs/superpowers/specs/2026-08-04-standard-four-way-shuttle-wcs-design.md

683 lines
34 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 标准四向车 WCS 产品总体设计
> 状态:已确认
> 确认日期:2026-08-04
> 目标产品:基于 RuoYi 的可独立交付标准四向车 WCS
> 首个验证项目:FT546
> 适用设备:自研托盘四向车、提升机、输送线、充电桩
## 1. 背景
FT546 已经具备可运行的 WCS、数据库表、生产历史记录和 PLC 通信实现,但当前调度代码主要集中在 `ruoyi-admin`,任务创建、选车、路径规划、设备通信、充电、业务完成和异常处理相互交织。车辆数量、PLC IP、站点编码、寄存器地址和部分业务流程存在项目硬编码,难以直接作为可重复交付的产品内核。
本设计不把现有 FT546 程序继续扩展成通用代码,也不脱离 RuoYi 重新建设平台。目标是在 RuoYi 多模块体系内新增独立 `ruoyi-wcs` 模块,重新实现 WCS 领域内核,并把 FT546 现有代码、数据库、协议和 17136 条历史执行记录作为行为证据、协议事实和验收语料。
本设计只定义标准产品目标形态,不讨论旧程序迁移步骤。
## 2. 产品目标
标准产品必须满足以下定义:
1. 一个部署实例服务一个具体仓库项目,不建设多租户或多项目共享运行平台。
2. 同一套 `ruoyi-wcs` 内核支持不同数量和能力的四向车、不同楼层地图、不同提升机、不同输送线点位及不同充电策略。
3. 新项目通过项目 `ruoyi-admin` 中的适配器、流程定义、策略和配置接入,不修改 `ruoyi-wcs` 的核心调度、交通控制、状态机和恢复代码。
4. WMS 和 PLC 接口变化不传入产品核心,分别由 WMS 适配器和设备适配器转换为标准命令与标准事件。
5. WCS 可以从持久化状态和设备现场快照恢复未完成任务,不依赖进程内线程状态。
6. 所有核心安全不变量都能由自动化测试、设备模拟器和历史回放重复证明。
## 3. 行业定位与系统边界
MHI 将 WCS 定义为协调和控制物料搬运设备的软件。ISA-95 将企业业务层与设备控制层分开。按这一成熟分层,产品边界如下:
| 层次 | 责任 |
| --- | --- |
| WMS | 库存账、货位分配、订单、波次、批次、业务优先级和业务终点 |
| WCS | 业务任务受理、任务拆解、选车、路径、交通资源、设备协同、充电、执行状态和异常恢复 |
| 设备适配器 | 标准设备命令与项目 PLC、厂家协议、寄存器和点位编码之间的转换 |
| PLC/车载控制器 | 毫秒级运动控制、现场互锁、急停、安全回路、动作执行和物理状态采集 |
WCS 不改变 WMS 的库存和业务目标,不承担 PLC 的安全联锁,也不让 WMS 直接驱动设备。
## 4. 首版范围
### 4.1 必须交付
- 单仓库、多楼层、多巷道和多交通区域。
- 可配置数量的自研托盘四向车及车辆能力、楼层归属和运行参数。
- 可配置提升机、提升机站口、输送线点位、出入口模式和充电桩。
- 入库、出库、移库、盘点和充电任务。
- 业务订单、流程实例、执行步骤和设备命令三级拆解。
- 车辆候选筛选、稳定评分、任务防饥饿和能力匹配。
- 图路径规划、交通资源预约、互斥区域控制和死锁预防。
- 四向车、提升机、输送线和充电桩之间的接驳协同。
- 指令幂等、Outbox、超时、重试、取消、回执和结果未知处理。
- 服务重启恢复、设备状态对账、局部隔离和受控人工接管。
- 任务、设备、资源、命令、告警、恢复工单和关联日志监控。
- 确定性设备模拟器、故障注入、FT546 历史回放和 PLC 协议回归。
### 4.2 首版不做
- 不承担 WMS 库存、货位分配、波次和订单管理职责。
- 不修改 FT546 现有 PLC 控制流程和安全联锁。
- 不做一个部署同时运行多个项目的多租户平台。
- 不抽象为支持所有 AGV、堆垛机和机器人的通用控制平台。
- 不提供可视化拖拽流程编排器和运行时热加载插件。
- 不做机器学习调度、数字孪生和三维监控。
- 不做跨机房多活;首版以单仓库部署和数据库支持的故障重启恢复为目标。
- 不定义旧程序迁移、旧表搬迁或灰度替换流程。
## 5. 总体架构
```mermaid
flowchart TB
WMS["项目 WMS / 上位系统"] --> WMSA["ruoyi-admin: WMS 适配器"]
UI["项目接口与运维页面"] --> ADMIN["ruoyi-admin: 项目应用"]
WMSA --> WCS["ruoyi-wcs: 标准 WCS 内核"]
ADMIN --> WCS
WCS --> PORTS["ruoyi-wcs: 出站端口 SPI"]
DA["ruoyi-admin: 设备适配器"] -. "实现 SPI" .-> PORTS
PA["ruoyi-admin: 项目策略与流程定义"] -. "实现 SPI" .-> PORTS
DA --> SHUTTLE["自研四向车"]
DA --> LIFT["提升机 PLC"]
DA --> CONVEYOR["输送线 PLC"]
DA --> CHARGER["充电桩"]
WCS --> DB["SQL Server: WCS 核心状态"]
ADMIN --> PDB["SQL Server: 项目协议与映射配置"]
```
### 5.1 Maven 依赖方向
```text
ruoyi-admin ───────→ ruoyi-wcs ───────→ ruoyi-common
│ │
├─ 项目 API ├─ 领域模型与应用服务
├─ WMS 适配器 ├─ 调度、交通与恢复
├─ 设备适配器 └─ 核心表持久化
└─ 项目策略
```
- `ruoyi-admin` 可以依赖 `ruoyi-wcs`。
- `ruoyi-wcs` 永远不能依赖 `ruoyi-admin`。
- 不新增 `wcs-project-ft546` 模块;每个项目的独立 Admin 就是项目交付边界。
- `ruoyi-wcs` 的领域包不能依赖 RuoYi Controller、项目配置、PLC 类、MyBatis Mapper 或 HTTP DTO。
- `ruoyi-wcs` 的 Mapper 和 Repository 不向 Admin 暴露;Admin 查询和操作必须通过应用服务与 QueryService。
## 6. ruoyi-wcs 六个核心领域
### 6.1 任务与流程
负责 `TransportOrder`、`WorkflowInstance` 和 `TaskStep` 的创建、依赖、暂停、取消、完成与失败。内核提供入库、出库、移库、盘点和充电的标准步骤语义,项目 Admin 提供项目流程定义和外部字段映射。
### 6.2 设备与拓扑
负责仓库、楼层、节点、边、巷道、交通区域、设备、端口、能力和配置版本。项目配置必须先经过核心校验和发布,运行任务绑定不可变拓扑版本。
### 6.3 调度与选车
负责候选任务排序、车辆能力匹配、楼层与可达性过滤、距离、电量、负载和等待时间评分。项目策略可以调整权重和选择偏好,但不能跳过能力、安全和状态机约束。
### 6.4 交通控制
负责软路径、已承诺路径、节点、边、巷道、交叉口、提升机口和其他冲突资源的预约与释放。交通区域是统一调度和版本边界,不默认等于容量为 1 的互斥资源。
### 6.5 设备协同
负责四向车取放货、提升机跨层联合流程、输送站口交接、端口模式和充电桩占用。适配器执行协议转换,协同顺序由内核状态机裁决。
### 6.6 执行与恢复
负责设备命令、Outbox、设备快照、结果确认、告警、局部隔离、启动恢复、恢复工单和人工接管审计。
## 7. 不可覆盖的核心不变量
以下规则属于产品内核,项目代码没有覆盖权:
1. 同一业务请求只能创建一个有效订单。
2. 同一车辆不能同时执行两个互斥任务。
3. 资源保护数不能超过拓扑定义容量。
4. 已经交给设备执行的路径或动作不能被新任务覆盖。
5. 设备状态或命令结果不确定时不能乐观释放资源。
6. 业务完成、步骤完成、设备命令完成和交通资源释放是四个独立事实。
7. 终态不能反向推进,重复事件不能重复完成任务或重复减少资源计数。
8. 项目策略只能返回评分或选择结果,不能直接写表、发设备命令或修改内部状态。
9. 人工操作不能绕过状态机、权限和审计。
## 8. 端到端任务流
```mermaid
sequenceDiagram
participant W as WMS
participant A as Admin Adapter
participant T as Task/Workflow
participant D as Dispatch/Traffic
participant E as Execution/Coordination
participant P as Device Adapter/PLC
W->>A: 项目业务请求
A->>T: 标准 CreateTransportOrderCommand
T->>T: 幂等、校验、生成流程与步骤
T->>D: READY 步骤
D->>D: 选车、路径、资源预约
D->>E: 原子绑定车辆并创建 DeviceCommand + Outbox
E->>P: 标准设备命令
P-->>E: 命令确认、事件与设备快照
E->>E: 校验事实并推进命令状态
E->>D: 释放已确认离开的资源
E->>T: 推进 TaskStep
T-->>A: 标准订单事件
A-->>W: 项目回调
```
### 8.1 数据事实边界
- 数据库保存系统已经接受的业务意图、调度决定、资源账本和待发送命令。
- 设备快照保存物理位置、载货、电量、模式、当前命令和故障事实。
- 意图与物理事实一致时,状态机继续推进。
- 两者不一致时,任务暂停并生成 `RecoveryCase`,不由适配器自行修正。
- WMS 回调失败不回滚已经完成的物理任务,只重试回调 Outbox。
## 9. 核心状态机
### 9.1 TransportOrder
```text
ACCEPTED → PLANNED → EXECUTING → COMPLETED
```
- `SUSPENDED`:可恢复暂停,保留原执行上下文。
- `CANCEL_REQUESTED`:运行中收到取消,等待设备安全停止和资源处理。
- `REJECTED/CANCELLED/FAILED`:终态。
- 只有全部必要 `TaskStep` 成功后才能进入 `COMPLETED`。
### 9.2 TaskStep
```text
WAITING → READY → ASSIGNED → RUNNING → SUCCEEDED
```
- `BLOCKED`:依赖、资源或设备条件暂不满足。
- `SUSPENDED`:执行被恢复流程或人工操作暂停。
- `SKIPPED/CANCELLED/FAILED`:终态。
- `ASSIGNED` 表示车辆和必要资源已经在同一事务内绑定。
- 发送设备命令不等于进入 `RUNNING`;必须获得相应设备事实。
### 9.3 DeviceCommand
```text
PENDING → SENT → ACKNOWLEDGED → SUCCEEDED
```
- `REJECTED`:设备明确拒绝,允许状态机按原因决定后续动作。
- `FAILED`:能够证明命令未被设备执行的失败。
- `UNKNOWN`:命令可能已经执行但没有可靠结果,必须查询设备或人工对账。
- 每个命令使用稳定 `commandKey`,重试使用递增 `attempt`。
### 9.4 ResourceReservation
```text
REQUESTED → GRANTED → OCCUPIED → RELEASED
```
- `REJECTED/EXPIRED/ABORTED` 为未进入物理占用或经恢复终止的状态。
- 授权携带 `fencingToken` 和状态版本。
- `OCCUPIED` 只能由匹配设备事实或受控人工核对释放,时间到期不能证明资源为空。
### 9.5 RecoveryCase
```text
DETECTED → ISOLATED → RECONCILING → READY_TO_RESUME → RESOLVED
└→ WAITING_OPERATOR → READY_TO_RESUME
└→ ABORTED
```
- 不能自动确认时从 `RECONCILING` 进入 `WAITING_OPERATOR`。
- 操作员提交完整现场证据并通过状态机校验后进入 `READY_TO_RESUME`。
- 无法继续原任务时进入 `ABORTED`;只有受影响命令已经裁定、已占资源已经由事实释放或转为隔离资源后,才能终止或幂等创建替代任务。
### 9.6 设备状态维度
设备状态不使用单一数字字段承载全部语义,至少拆分为:
- 连接:`ONLINE/OFFLINE/UNKNOWN`。
- 模式:`AUTO/MANUAL/MAINTENANCE`。
- 健康:`NORMAL/WARNING/FAULT`。
- 占用:`IDLE/RESERVED/BUSY`。
- 物理事实:位置、方向、载货、电量、当前动作和当前命令。
### 9.7 合法迁移与副作用
#### TransportOrder
| 来源 | 目标 | 触发与前置条件 | 必须产生的副作用 |
| --- | --- | --- | --- |
| `ACCEPTED` | `PLANNED` | 业务参数、拓扑引用和流程定义校验通过 | 原子创建流程实例和步骤 |
| `ACCEPTED` | `REJECTED` | 业务请求本身不可接受,且未产生物理命令 | 保存稳定拒绝码,不创建资源预约 |
| `PLANNED` | `EXECUTING` | 第一个必要步骤进入 `RUNNING` | 保存订单开始事件 |
| `ACCEPTED/PLANNED/EXECUTING` | `SUSPENDED` | 恢复流程、设备异常或受控人工暂停 | 停止新分配和新运动命令;保留已承诺命令与未确认资源 |
| `SUSPENDED` | `PLANNED` | 尚无设备接受物理动作,且阻断条件已经消除 | 重新评估 READY 步骤 |
| `SUSPENDED` | `EXECUTING` | 已承诺动作完成对账且可以继续 | 恢复原流程,不重复创建已完成步骤 |
| `ACCEPTED/PLANNED` | `CANCELLED` | 没有设备接受物理动作 | 幂等取消未运行步骤并释放未占用预约 |
| `EXECUTING/SUSPENDED` | `CANCEL_REQUESTED` | 收到取消请求且存在已承诺或未知动作 | 停止新动作,等待设备和资源收敛 |
| `CANCEL_REQUESTED` | `CANCELLED` | 所有活动命令已裁定,已占资源已释放或隔离 | 取消剩余步骤并发布一次取消事件 |
| 任意非终态 | `FAILED` | 恢复工单判定原业务不可继续,且资源与命令已收敛 | 终止剩余必要步骤并发布一次失败事件 |
`REJECTED`、`COMPLETED`、`CANCELLED` 和 `FAILED` 是互斥终态。相同外部请求或相同领域事件重复到达时返回既有结果,不再次执行副作用。
#### TaskStep
| 来源 | 目标 | 触发与前置条件 | 资源和命令处理 |
| --- | --- | --- | --- |
| `WAITING` | `READY` | 所有必要前置步骤成功,业务条件满足 | 尚不占用车辆或交通资源 |
| `WAITING/READY` | `BLOCKED` | 设备、端口、模式或拓扑条件暂不满足 | 记录结构化阻断原因,不发送命令 |
| `BLOCKED` | `READY` | 阻断条件消失 | 重新进入候选排序 |
| `READY` | `ASSIGNED` | 车辆和首批必要资源在同一事务内绑定 | 创建车辆绑定和预约,不代表设备已动作 |
| `ASSIGNED` | `RUNNING` | 首个设备命令被设备确认或现场事实证明已开始 | 锁定不可更换的执行主体 |
| `ASSIGNED/RUNNING` | `SUSPENDED` | 命令未知、设备异常、人工暂停或恢复流程 | 保留已承诺动作与未确认资源 |
| `SUSPENDED` | `ASSIGNED/RUNNING` | 对账结果分别证明动作尚未开始或正在/已经执行 | 从对账后的真实阶段继续 |
| `RUNNING` | `SUCCEEDED` | 该步骤定义的全部物理完成条件成立 | 释放最后资源,唤醒后继步骤 |
| 非终态 | `CANCELLED` | 订单取消且该步骤不存在未知物理动作 | 释放未占用预约,不创建后继动作 |
| `WAITING` | `SKIPPED` | 流程定义将该分支标为可选且进入条件不成立 | 不影响必要步骤完成判断 |
| 非终态 | `FAILED` | 必要步骤无法恢复或其必需前置步骤失败 | 触发订单失败收敛;可选步骤失败不得伪装成功 |
#### DeviceCommand 与 ResourceReservation
| 场景 | 命令迁移 | 预约处理 |
| --- | --- | --- |
| 适配器发送前能够证明未到达设备 | 保持 `PENDING` 并按策略重试,或进入 `FAILED` | `REQUESTED/GRANTED` 可安全 `ABORTED` |
| 发送已受理并收到匹配确认 | `SENT → ACKNOWLEDGED` | 必要预约保持 `GRANTED/OCCUPIED` |
| 设备事实满足完成条件 | `ACKNOWLEDGED/SENT → SUCCEEDED` | 按释放谓词逐项 `RELEASED` |
| 设备明确拒绝且未动作 | `SENT → REJECTED` | 未占预约 `ABORTED`,已占事实必须另行对账 |
| 发送后无法证明成功或失败 | `SENT/ACKNOWLEDGED → UNKNOWN` | 不因超时释放或 `ABORTED`,保持 `GRANTED/OCCUPIED` 并关联 RecoveryCase |
| UNKNOWN 后证明动作未发生 | `UNKNOWN → FAILED` | 未占预约可 `ABORTED` |
| UNKNOWN 后证明动作已完成 | `UNKNOWN → SUCCEEDED` | 仅按匹配物理事实释放对应资源 |
`EXPIRED` 只适用于尚未授予或尚未产生物理占用的请求。任何 `OCCUPIED` 预约都不能因时间到期进入 `EXPIRED`。
## 10. 数据所有权
### 10.1 ruoyi-wcs 独占写入
标准主数据:
- `wcs_warehouse`
- `wcs_floor`
- `wcs_topology_version`
- `wcs_topology_node`
- `wcs_topology_edge`
- `wcs_traffic_zone`
- `wcs_resource_definition`
- `wcs_device`
- `wcs_device_capability`
- `wcs_device_port`
- `wcs_charger`
流程和运行数据:
- `wcs_transport_order`
- `wcs_workflow_instance`
- `wcs_task_step`
- `wcs_task_dependency`
- `wcs_vehicle_assignment`
- `wcs_route_plan`
- `wcs_resource_state`
- `wcs_resource_reservation`
- `wcs_device_command`
- `wcs_command_outbox`
- `wcs_device_snapshot`
- `wcs_domain_event`
- `wcs_alarm`
- `wcs_recovery_case`
- `wcs_manual_action_audit`
这些名称是首版标准逻辑表名。实现阶段只有在现有 `wcs_srgv_traffic_*` 表同时满足核心独占写入、显式状态语义、幂等键、并发版本、资源容量约束和恢复证据要求时才允许复用;复用评估不构成产品对旧表的依赖,也不属于本设计的迁移方案。新内核不能继续依赖 `default02-default08` 或未定义的数字状态。
### 10.2 项目 Admin 所有
- `project_wms_mapping`
- `project_device_endpoint`
- `project_plc_address`
- `project_protocol_profile`
- `project_raw_message`
- 项目专用接口、报表和展示配置
这些表只保存外部协议和项目差异,不保存核心任务、车辆绑定、设备命令或资源占用状态。
### 10.3 RuoYi 平台所有
用户、角色、菜单、字典、平台参数、登录日志和操作日志继续使用 `sys_*` 表。WCS 领域模型不复制认证授权能力。
### 10.4 数据访问规则
- Admin 的写操作必须调用 WCS ApplicationService。
- Admin 页面通过 WCS QueryService 或稳定只读投影查询。
- 任务状态、资源预约、设备命令和 Outbox 在 WCS 应用事务中一致提交。
- 使用架构测试阻止 Admin 访问 WCS Mapper/Repository,并阻止 WCS 反向依赖 Admin。
## 11. 适配器契约
### 11.1 入站用例
- `TransportOrderUseCase`:创建、取消、暂停、恢复和查询业务订单。
- `DeviceEventUseCase`:接收标准设备事件和快照。
- `ConfigurationUseCase`:校验、发布和读取拓扑、设备和流程配置。
- `RecoveryUseCase`:隔离、核对、恢复和终止恢复工单。
### 11.2 出站端口
- `DeviceCommandGateway`:发送标准设备命令,只返回通信层受理结果。
- `DeviceSnapshotGateway`:主动读取指定设备的现场快照。
- `WmsNotificationGateway`:发布标准业务事件。
- `TopologyDefinitionProvider`:提供项目拓扑定义。
- `WorkflowDefinitionProvider`:提供项目流程定义。
- `DispatchPolicy`、`PortSelectionPolicy`、`ChargingPolicy`:提供无副作用的项目策略。
### 11.3 WMS 标准契约
入站操作:`Create/Cancel/Suspend/Resume/Query TransportOrder`。
必要字段:
```text
externalRequestId
orderType
loadId
source
destination
priority
deadline
attributes
```
出站事件:`OrderAccepted/OrderStarted/OrderCompleted/OrderFailed/OrderCancelled/OrderSuspended`。
事件至少包含:`eventId`、`externalRequestId`、`orderId`、`occurredAt`、`resultCode`、`resultMessage` 和 `context`。Outbox 按至少一次投递,项目适配器负责状态码、签名和传输映射。
### 11.4 设备标准语义
| 设备 | 标准命令示例 | 标准事实示例 |
| --- | --- | --- |
| 四向车 | Move、Load、Unload、GoCharge、Stop、Reset、Query | 位置、载货、电量、模式、故障、命令结果 |
| 提升机 | Call、PrepareTransfer、Transfer、Stop、Reset、Query | 楼层、门、端口就绪、占用、故障 |
| 输送线 | PrepareInbound、PrepareOutbound、StartTransfer、Stop、Reset | 货物检测、端口模式、就绪、完成、故障 |
| 充电桩 | Enable、Disable、Stop、Reset、Query | 空闲、预约、连接、充电、完成、故障 |
标准命令表达领域意图,不等同于某个 PLC 寄存器。命令类型是产品契约的可选能力集合,不要求每个首版旧 PLC Profile 实现全部命令。一个已启用的标准命令可以由适配器转换成多步握手,但只能通过标准事件和快照把事实返回核心。
### 11.5 适配器强制约束
- 核心边界使用强类型、可版本化 DTO,不使用 `Map<String, Object>` 传递主要业务数据。
- `send` 成功只表示命令交给通信层,不表示设备完成。
- 事件携带 `eventId`、`commandKey`、设备序号、设备时间和接收时间,核心处理重复与乱序。
- 原始 PLC 报文可以存档审计,但不能直接成为领域状态。
- 有活动命令的设备禁止切换协议 Profile。
- 模拟器实现相同契约,测试不能绕过适配器边界。
## 12. 首版 PLC 能力策略
首版保持 FT546 现有 PLC 协议不变。为了不把旧 PLC 没有的能力伪装成产品保证,每个设备适配器必须声明能力 Profile。
### 12.1 建议能力项
- `POINT_TO_POINT_COMMAND`
- `TWO_STAGE_ATOMIC_TASK`
- `COMMAND_RESULT_QUERY`
- `ORDERED_DEVICE_SNAPSHOT`
- `CANDIDATE_BUFFER`
- `PREPARE_COMMIT_SEGMENT`
- `IDEMPOTENT_COMMAND_KEY`
- `BOOT_SESSION_ID`
### 12.2 FT546 旧 PLC Profile
| 能力 | 首版 FT546 Profile | 证明边界 |
| --- | --- | --- |
| `POINT_TO_POINT_COMMAND` | 启用 | 现有主任务区支持的完整点到点任务;路径长度和动作受旧协议上限约束 |
| `TWO_STAGE_ATOMIC_TASK` | 验收门禁 | 只有旧二段协议回归证明“两段属于同一任务且失联边界可接受”后启用;它不等于 Prepare/Commit |
| `COMMAND_RESULT_QUERY` | 禁用 | 只能读取设备快照,不能按 `commandKey` 查询可靠命令结果 |
| `ORDERED_DEVICE_SNAPSHOT` | 禁用 | WCS 可以记录本地接收序号,但不能伪装成 PLC 提供的单调序号 |
| `CANDIDATE_BUFFER` | 禁用 | 不允许在 PLC 内预装可覆盖候选路径 |
| `PREPARE_COMMIT_SEGMENT` | 禁用 | 旧任务触发位不等于独立原子 COMMIT |
| `IDEMPOTENT_COMMAND_KEY` | 禁用 | PLC 不识别 WCS `commandKey`,发送后不允许盲目重试 |
| `BOOT_SESSION_ID` | 禁用 | 无法用 PLC 启动会话证明重启前后命令连续性 |
FT546 产品验收必须启用并通过 `POINT_TO_POINT_COMMAND` 契约测试;项目深位流程依赖旧二段任务时,`TWO_STAGE_ATOMIC_TASK` 门禁也必须通过,否则该项目不满足首版完整业务验收。
旧 Profile 使用现有主任务区、经过门禁的旧二段任务区和状态轮询,并遵守以下命令粒度:
- 核心在发送前持久化命令,并一次性保护该完整旧 PLC 任务可能经过的路径和设备资源。
- 不把一个旧 PLC 点到点任务拆成需要 PLC 候选缓冲或独立提交的滚动区段。
- 同一设备同一时刻只允许一个可能产生物理动作的命令。
- 下一运动命令只能在快照证明前一任务到达预期端点、设备进入允许状态、任务号和载货结果匹配后生成。
- 写入过程中能够证明未发送的失败可以重试;写入后无法证明结果的命令进入 `UNKNOWN`,保持车辆和相关资源,不自动重发。
- `UNKNOWN` 期间允许继续执行只读快照采集和诊断,不允许并行发送 Move、Load、Unload、Reset 或其他可能改变物理状态的命令。Stop 只在现有 PLC 契约明确支持且 RecoveryCase 授权时使用。
- Stop、Reset 和高级 Query 不属于旧 Profile 的默认验收命令;首版只要求已启用命令和快照读取通过契约测试。
- 不启用必须依赖候选缓冲、独立 COMMIT、PLC 会话号或有序快照才能证明安全的高级滚动能力。
### 12.3 未来增强 PLC
未来 PLC 若支持候选缓冲、Prepare/Commit、命令幂等和有序快照,只新增或替换 Adapter 与 Profile。调度、交通、任务和恢复领域不因此修改。
## 13. 调度、交通和设备协同
### 13.1 车辆选择
硬过滤条件包括在线、自动、健康、可用、电量合格、楼层/提升机可达、载货能力和任务类型匹配。通过硬过滤后,按业务优先级、等待老化、楼层、路径成本、电量、当前负载和项目权重评分;任务号和车辆号作为稳定裁决键。
首个不可撤销设备动作前允许重新选车;设备已经接受物理执行后车辆绑定锁定。
### 13.2 路径与资源
- 基础地图编译为不可变拓扑版本。
- 路径是完整业务意向。支持 Prepare/Commit 的设备可以获得当前资源已经保护的滚动区段;FT546 旧 Profile 只能获得经过完整资源保护的旧协议整段点到点任务或通过验收门禁的旧二段任务。
- 节点、无向边、巷道、交叉口、提升机本体、提升机端口和深位包络都可以成为容量资源。
- 获取多资源时按稳定资源键排序并在同一事务内校验容量。
- 已占资源只能随匹配设备事实滚动释放。
- 生成授权前检查等待图,拒绝会形成环的组合。
- 没有安全让行点时保持等待并告警,不临时选择任意空点。
### 13.3 提升机
跨层任务联合保护源入口、提升机本体和目标出口。目标出口未准备好时车辆停在源层安全点;车辆完全进入后才能释放源入口,完全离开目标出口后才能释放提升机和目标出口。
源入口、提升机本体或目标出口任一预约失败时,步骤保持 `BLOCKED`,不发送进入提升机命令。进入命令、提升机移动或目标出口事实出现 `UNKNOWN` 时,步骤进入 `SUSPENDED`,隔离提升机及已经承诺的源/目标端口;只有车辆位置、提升机楼层/门状态和端口传感器完成联合对账后才能恢复或释放资源。
### 13.4 输送线和出入口
每个输送口独立维护实际模式、允许模式、剩余绑定作业和切换锁定。项目 Admin 映射 PLC 旋钮、站口和握手字段,核心决定是否允许分配与切换。人工强制切换产生模式冲突时,冻结新分配并进入受控处理。
### 13.5 充电
充电策略至少包含低电量强制阈值、任务准入阈值、空闲充电阈值、目标电量、充电桩选择和预约超时。强制充电优先于普通新任务;执行中任务除非设备安全要求,不因达到阈值被中断。
## 14. 异常恢复与运行保障
### 14.1 恢复分级
| 级别 | 场景 | 处理 |
| --- | --- | --- |
| 自动恢复 | 发送前网络失败、WMS 回调失败、重复事件 | 幂等重试、退避和去重 |
| 自动对账 | 发送后超时、设备短时离线、WCS 重启 | 保留资源、查询快照、一致后恢复 |
| 人工确认 | 位置/载货冲突、PLC 手动动作、现场搬运、设备维修 | 隔离设备和区域,通过恢复工单确认事实 |
### 14.2 启动恢复顺序
1. 获取调度实例租约,保持全局调度暂停。
2. 加载活动订单、步骤、车辆绑定和流程状态。
3. 加载路线、资源预约、设备命令、Outbox 和最后快照。
4. 查询所有相关设备的现场状态。
5. 对账位置、载货、命令、模式和资源占用。
6. 恢复事实一致的任务,隔离不一致的设备和最小安全区域。
7. 恢复 WMS 回调和可证明安全的命令投递。
8. 在保留隔离对象的前提下启动其余调度。
即使只部署一个实例,也使用租约和 fencing token,防止旧进程未退出时新进程同时调度。
### 14.3 对账与资源释放谓词
- 重复、倒退或不能关联当前命令的事件只记录审计,不推进状态。
- 设备 `OFFLINE/UNKNOWN` 时立即暂停其活动步骤并隔离已经承诺的资源;任何通信超时都不能作为释放依据。
- 新鲜快照与预期命令、位置、载货和模式一致后,才能从 `SUSPENDED/UNKNOWN` 回到 `ASSIGNED/RUNNING/SUCCEEDED`。
- 点到点移动只有在当前点属于已知路径的合法后继、任务标识匹配且进度不倒退时,才释放已经完全离开的前序节点和边。
- 取放货完成至少要求预期端点、允许的设备完成/待机状态、匹配任务标识和预期载货变化同时成立。
- 提升机资源释放要求车辆位置、提升机楼层/门状态和源/目标端口传感器形成一致事实;楼层变化本身不足以释放。
- 输送端口释放要求货物检测、端口实际模式和握手完成事实一致。
- `UNKNOWN` 命令可以根据已经证明的局部路径进度释放确实离开的前序资源,但不能释放车辆当前节点、后续可能路径和无法证明离开的设备资源。
- 旧 PLC 出现跳点、任务号错配、载货冲突或缺少最小证据集合时,不做局部推断,进入 `WAITING_OPERATOR`。
### 14.4 人工接管
允许暂停任务、隔离设备或区域、确认现场位置和载货、选择恢复或终止方案。禁止直接改核心表、无条件释放资源、跳过状态机或把 `UNKNOWN` 命令直接标记成功。所有高风险操作使用 RuoYi 角色权限并记录操作人、原因、证据、前后状态和时间。
### 14.5 可观测性
结构化日志至少关联:
```text
traceId
externalRequestId
orderId
workflowId
stepId
deviceId
commandKey
resourceId
eventId
recoveryCaseId
```
核心指标包括任务积压、调度耗时、交通等待、命令确认/完成时延、设备利用率、电量、提升机等待、Outbox 重试、故障率和恢复耗时。
## 15. 测试与模拟器
### 15.1 测试分层
1. 领域单元与性质测试:状态机、评分、路径、交通、充电和不变量。
2. 适配器契约测试:标准命令/事件、重复、乱序、超时和能力声明。
3. SQL Server 集成测试:事务、Outbox、幂等、资源并发、fencing token 和回滚。
4. 模拟设备端到端测试:完整业务、设备协同、故障和重启。
5. FT546 历史回放和 PLC 协议样本回归。
6. 真实 PLC 或硬件在环契约验证。
### 15.2 模拟器能力
模拟器覆盖四向车、提升机、输送线、充电桩和 WMS,支持控制运行速度、握手延迟、电量消耗、货物出现和设备模式,并注入断线、超时、重复/乱序事件、命令拒绝、车辆偏位、载货冲突、PLC 手动模式和 WCS 重启。
### 15.3 历史回放原则
- 使用 FT546 历史任务、数据库执行记录、运行日志和 PLC 报文样本。
- 验证业务结果、起终点、协议顺序、状态合法性、资源安全和幂等。
- 新内核可以选择不同车辆、路径和调度顺序,不复制旧程序硬编码决策。
- 无法转换或自相矛盾的历史记录形成异常报告,不通过放宽核心规则迁就脏数据。
## 16. 首版验收门槛
### 16.1 安全指标
以下计数必须为 0:
- 同一车辆并行执行互斥任务。
- 交通资源超过定义容量。
- 非法状态迁移或终态反向推进。
- `UNKNOWN` 命令被盲目重复执行。
- 设备事实不确定时释放资源。
- 人工操作绕过状态机和审计。
- 恢复过程重复完成业务或重复通知 WMS。
### 16.2 产品独立性
同一 `ruoyi-wcs` 构建产物分别运行 FT546 配置和第二套合成仓库配置。第二套配置至少改变楼层、车辆数量、提升机数量、输送点位和充电策略,不允许修改核心代码。
### 16.3 建议性能基线
| 基准规模 | 目标 |
| --- | --- |
| 50 台四向车、10 台提升机、300 个输送点、20 个充电位、2000 个待处理任务 | 调度决策 P95 不超过 500 ms |
| 持续设备事件输入 | Adapter 入站到状态事务提交 P95 不超过 200 ms |
| 上述规模下 WCS 重启 | 可自动确认部分在 60 秒内恢复;不含离线设备和人工等待 |
| 72 小时加速模拟、累计不少于 100000 个任务 | 安全不变量违规为 0,并记录积压、吞吐、内存和数据库增长 |
这些数值是首版标准基线,不表示产品硬上限。项目交付可以在不降低安全门槛的前提下增加专项容量压测。
### 16.4 验收产物
- 场景覆盖清单。
- 自动化测试报告。
- 适配器契约和 PLC 协议回归报告。
- FT546 历史回放报告。
- 72 小时模拟与性能报告。
- 故障恢复和人工接管报告。
- 产品独立性验证报告。
- 未通过项及阻断原因清单。
## 17. 建议代码结构
```text
ruoyi-wcs/
└── src/main/java/com/ruoyi/wcs/
├── application/
│ ├── task/
│ ├── dispatch/
│ ├── device/
│ └── recovery/
├── domain/
│ ├── task/
│ ├── topology/
│ ├── dispatch/
│ ├── traffic/
│ ├── equipment/
│ └── execution/
├── port/
│ ├── in/
│ └── out/
├── infrastructure/
│ └── persistence/
└── query/
ruoyi-admin/
└── src/main/java/com/ruoyi/project/<projectCode>/
├── wms/
├── device/
│ ├── shuttle/
│ ├── lift/
│ ├── conveyor/
│ └── charger/
├── workflow/
├── policy/
├── config/
└── web/
```
核心领域对象保持普通 Java 8 POJO 和明确构造器,不引入要求升级 Java 或替换 RuoYi 的框架。
## 18. 与现有 FT546 文档的关系
现有 `docs/WCS算法优化` 文档仍作为 FT546 交通算法、现状审计、资源模型、PLC 事实和测试证据来源。本设计是标准产品的上位架构,发生冲突时遵循以下规则:
1. 标准产品模块边界、数据所有权和适配器边界以本设计为准。
2. 已经确认的交通安全不变量继续有效。
3. 旧文档中“ACTIVE 必须修改 PLC 为 Prepare/Commit 协议”的要求不适用于首版产品;首版使用能力 Profile 限制旧 PLC 可启用的功能,绝不伪造 PLC 不具备的确认语义。
4. 未来增强 PLC 可以启用更细粒度滚动区段,但不能改变 WCS 核心任务、资源和恢复模型。
5. 旧代码、旧表和旧日志是证据,不是新产品包结构和领域模型的模板。
## 19. 设计完成定义
本设计完成后,后续实施计划必须满足:
- 先建立 `ruoyi-wcs` 模块、领域模型和架构测试,再接入项目适配器。
- 每个增量都以可运行场景和安全不变量测试结束。
- 不把项目 PLC 地址、站点编码、车辆编号和 WMS 字段写入核心。
- 不通过迁就 FT546 旧状态字段破坏标准模型。
- 最终由同一个标准内核完成 FT546 和第二套合成仓库的端到端验收。
## 20. 参考依据
- MHI, Warehouse Control System: https://www.mhi.org/fundamentals/warehouse-control-system
- ISA, ISA-95 Enterprise-Control System Integration: https://www.isa.org/standards-and-publications/isa-standards/isa-95
- OPC Foundation, OPC UA: https://opcfoundation.org/about/opc-technologies/opc-ua/
- VDA/VDMA, VDA 5050: https://www.vda.de/en/topics/innovation-and-technology/vda-5050
- NIST SP 800-82 Rev.3, Guide to Operational Technology Security: https://csrc.nist.gov/pubs/sp/800/82/r3/final
- FT546 `CONTEXT-MAP.md`
- FT546 `docs/traffic-control/CONTEXT.md`
- FT546 `docs/port-mode-control/CONTEXT.md`
- FT546 `docs/WCS算法优化/01-现有程序实现审计.md` 至 `06-测试灰度与验收.md`