将 StandardScene 各插件的配置/监控窗体从 WinForms 迁移到 CycleGUI(删除 .Designer.cs/.resx,重写为 PanelBuilder 立即模式 UI,新增 CycleUiHelper 统一对话框)。 同时修复代码审核中的问题: - 后台文件写入加锁 + try/catch(ButtonBoxManager / DoorManager,对齐 LoopViewer.SaveTasks 模式) - CoderFieldsMetadata.cs 启用 #nullable enable,消除 CS8632 警告 - DummyCar 移除已废弃的 rightClickAction()/SetPosition() - CarRemoteHelper.OpenVehicleWebPage 的 Process.Start 加 try/catch - 重命名名不副实的 Mstsc()(现为打开网页) - 统一弃元命名为 _ - TrafficInterlockViewer 改用稳定 Id(GUID)做选择/编辑,替代行索引 - csproj 改用 $(CGUILibDir) 解析 CycleGUI,绝对路径收敛到 Directory.Build.props 构建:dotnet build StandardScene.sln → 0 错误,30 警告(均为历史遗留)。 注:static 单例状态重构(审核第 8 项)暂未处理,留待单独任务。
526 lines
20 KiB
Markdown
526 lines
20 KiB
Markdown
# StandardScene 代码架构文档
|
||
|
||
> **目标读者**:接手本仓库的工程师、AI Agent、架构审查人员
|
||
> **最后更新**:2026-06-25
|
||
> **配套文档**:`DEVELOPMENT_GUIDE.md`(开发实操)、`QUICK_REFERENCE.md`(速查)、`StandardScene架构重构方案.md`(演进方向)
|
||
|
||
---
|
||
|
||
## 1. 项目定位
|
||
|
||
StandardScene 是一套 **AGV/AMR 场内调度与联动控制** 的场景插件库,不是独立可执行程序。
|
||
|
||
| 维度 | 说明 |
|
||
| --- | --- |
|
||
| 工程类型 | 类库插件(1 基座 + 4 卫星 = 5 个 DLL) |
|
||
| 宿主 | `SimpleLite.exe`(CycleGUI 桌面应用) |
|
||
| 内核 | `SimpleCore.dll`(Mission、交通、路径编译、导航契约) |
|
||
| 目标框架 | `net8.0-windows`(x64) |
|
||
| 语言 | C# |
|
||
| UI 演进 | WinForms → CycleGUI(`DeliveryViewer` 等已迁移) |
|
||
|
||
典型业务能力:搬运任务、环线任务、区域交通管制、充电编排、门禁/按钮盒联动、HTTP / MQTT / Modbus 对外接口。
|
||
|
||
---
|
||
|
||
## 2. 解决方案结构
|
||
|
||
```
|
||
StandardScene.sln
|
||
├── StandardScene.Core → 输出 StandardScene.dll(基座,始终加载)
|
||
├── StandardScene.Magnetic → 输出 StandardScene.Magnetic.dll(scene.mag)
|
||
├── StandardScene.QrLidar → 输出 StandardScene.QrLidar.dll(scene.qrlidar)
|
||
├── StandardScene.Devices → 输出 StandardScene.Devices.dll(scene.device)
|
||
└── StandardScene.Protocol.VDA5050 → 输出 StandardScene.Protocol.VDA5050.dll(scene.vda5050)
|
||
```
|
||
|
||
### 2.1 依赖关系(星型拓扑)
|
||
|
||
```mermaid
|
||
graph TD
|
||
Host["SimpleLite.exe"]
|
||
SC["SimpleCore.dll"]
|
||
SL["SimpleLite.dll"]
|
||
|
||
Core["StandardScene.dll<br/>基座"]
|
||
Mag["StandardScene.Magnetic.dll"]
|
||
Qr["StandardScene.QrLidar.dll"]
|
||
Dev["StandardScene.Devices.dll"]
|
||
VDA["StandardScene.Protocol.VDA5050.dll"]
|
||
|
||
Host --> Core
|
||
Host --> Mag
|
||
Host --> Qr
|
||
Host --> Dev
|
||
Host --> VDA
|
||
|
||
Core --> SC
|
||
Core --> SL
|
||
Mag --> Core
|
||
Qr --> Core
|
||
Dev --> Core
|
||
VDA --> Core
|
||
```
|
||
|
||
**规则**:
|
||
- 卫星 **只能** 引用基座,禁止循环引用
|
||
- 所有插件 **运行时** 依赖 `SimpleCore` + `SimpleLite`
|
||
- 卫星通过 `InternalsVisibleTo` 访问 Core 的 `internal` 字段袋类型,避免大规模 `public` 暴露
|
||
|
||
### 2.2 插件清单对照表
|
||
|
||
| DLL | scene id | 始终加载 | 职责 |
|
||
| --- | --- | --- | --- |
|
||
| `StandardScene.dll` | — | 是 | 任务调度、交通互锁、充电编排、门禁抽象、HTTP API、数据模型 |
|
||
| `StandardScene.Magnetic.dll` | `scene.mag` | 否 | 磁导航车型 + 磁循迹 Coder |
|
||
| `StandardScene.QrLidar.dll` | `scene.qrlidar` | 否 | 激光 SLAM + 二维码导航,多种车型 |
|
||
| `StandardScene.Devices.dll` | `scene.device` | 否 | Modbus 门控、充电桩、按钮盒具体驱动 |
|
||
| `StandardScene.Protocol.VDA5050.dll` | `scene.vda5050` | 否 | VDA5050(MQTT)协议栈与标准车型 |
|
||
|
||
---
|
||
|
||
## 3. 运行时架构
|
||
|
||
### 3.1 启动与加载流程
|
||
|
||
```mermaid
|
||
sequenceDiagram
|
||
participant Host as SimpleLite.exe
|
||
participant PM as PluginManager
|
||
participant Core as StandardScene.dll
|
||
participant Sat as 卫星 DLL
|
||
|
||
Host->>PM: 扫描 plugins\ 目录
|
||
PM->>Core: 加载 requiresCore 指向的基座(不可回收)
|
||
PM->>PM: 读取 active-scenes.json / CLI --scenes
|
||
PM->>Sat: 按场景 id 加载选中的卫星 DLL
|
||
Sat->>Core: 引用已加载的基座类型
|
||
PM->>PM: UiTypeDiscovery 反射 [MissionType]/[CarType]/[DoorType] 等
|
||
alt 导航插件
|
||
PM->>Sat: 实例化 NavigationProfileBase → OnActivate
|
||
end
|
||
Host->>Core: CustomOperationsBeforeLoading.Set()(死锁回调等)
|
||
```
|
||
|
||
**场景选择优先级**(高 → 低):
|
||
1. CLI 参数 `--scenes`
|
||
2. `active-scenes.json`
|
||
3. `simple.json` 中的 `scenes` 字段
|
||
4. 加载全部已发现的卫星
|
||
|
||
> **注意**:若 `active-scenes.json` 仅包含 `scene.mag`,则 `scene.device` / `scene.vda5050` 不会加载,门控/充电桩/VDA5050 车型将不可用。生产部署需显式包含所需场景 id。
|
||
|
||
### 3.2 构建与部署
|
||
|
||
`Directory.Build.targets` 在编译后自动将产物复制到 `build\plugins\`:
|
||
|
||
- 各插件 DLL + PDB
|
||
- 各卫星的 `*.scene.json`
|
||
- Devices 插件附带的 `leegKeys-sdk.dll`
|
||
|
||
部署步骤:
|
||
1. 先构建宿主:`dotnet build Simple\SimpleLite\SimpleLite.csproj`
|
||
2. 构建本方案:`dotnet build StandardScene.sln`
|
||
3. 将 `build\plugins\` 内容复制到 `SimpleLite.exe` 工作目录的 `plugins\`
|
||
4. 配置 `active-scenes.json` 后启动 `SimpleLite.exe`
|
||
|
||
### 3.3 业务运行时链路
|
||
|
||
```
|
||
外部系统 (HTTP/MQTT/Modbus)
|
||
↓
|
||
WebApi / 设备驱动 / 车型通信
|
||
↓
|
||
Mission(后台进程:搬运/环线/充电/门控/心跳…)
|
||
↓
|
||
SimpleLib / TrafficControl / SegmentPlan(SimpleCore)
|
||
↓
|
||
GhostCar / Car 实例(车辆状态机 + 下位机通信)
|
||
↓
|
||
地图站点 / 轨道 / fields & tags 配置
|
||
```
|
||
|
||
---
|
||
|
||
## 4. 核心概念
|
||
|
||
### 4.1 Mission(场景进程)
|
||
|
||
Mission 是本系统的 **可启动后台业务单元**,继承自 `SimpleCore.Mission`,由宿主 UI 或 HTTP 反射 API 启停。
|
||
|
||
**生命周期模式**(以 `HeartBeatMission` 为范本):
|
||
|
||
| 阶段 | 典型实现 |
|
||
| --- | --- |
|
||
| 注册 | `[MissionType(Name="...", editor=typeof(...))]` |
|
||
| 工厂 | `public static Mission Create()` |
|
||
| 启动 | `[MethodMember(Name="启动进程")] public override void Execute()` |
|
||
| 后台 | `Thread` / `Task.Run` / `async` + `CancellationTokenSource` |
|
||
| 状态 | 更新 `status.status` 或自定义 `MissionStatus` 子类 |
|
||
| 停止 | `[MethodMember(Name="关闭进程")] public void Stop()` |
|
||
|
||
**Mission 继承树**:
|
||
|
||
```
|
||
Mission (SimpleCore)
|
||
├── HeartBeatMission, RegionalTrafficControlMission, SecuritySignalMission
|
||
├── NodeIsEnableMission
|
||
├── DoorMission, ButtonMission
|
||
├── AbstractInterlockMission
|
||
│ ├── TrafficInterlockMission
|
||
│ └── AbstractChargeLogicMission → StandardChargeMission
|
||
├── ChainedDeliveryMission → TransportMission(搬运调度)
|
||
└── AbstractLoopMission → LoopMission(环线任务)
|
||
```
|
||
|
||
### 4.2 CarType(车型)
|
||
|
||
车型代表一种 AGV 下位机协议与行为模型,继承自 `SimpleLite.RCS.CarTypes.GhostCar` 或 `Car`。
|
||
|
||
**注册三要素**:
|
||
|
||
1. **类型特性**:`[CarType(Name="显示名", editor=typeof(XxxCar))]`
|
||
2. **轨迹编码器**:`[ProgramTrackCoderSettings(priority=N, program=typeof(XxxCoder))]`
|
||
3. **场景清单**:`scene.json` 的 `provides.carTypes` +(导航插件)`NavigationProfileBase.CarTypes`
|
||
|
||
**Coder(轨迹编码器)** 实现 `SimpleCore.Compiler.ITrackCoder`,在路径规划时将站点/轨道上的 `fields` 编译为 Topaz 脚本片段(如 `agv.MagGo`、`agv.BasicGo`)。
|
||
|
||
### 4.3 设备驱动(门 / 充电桩 / 按钮盒)
|
||
|
||
设备采用 **抽象在 Core、实现在 Devices** 的模式:
|
||
|
||
| 设备 | Core 抽象 | Devices 实现 | 发现机制 |
|
||
| --- | --- | --- | --- |
|
||
| 门控 | `BasicDoorController` | `ModbusDoorController` | `[DoorType("...")]` + `UiTypeDiscovery` |
|
||
| 充电桩 | `AbstractChargeStation` | `FL/PCB/MuXingChargeStation` | 类型全名 + `UiTypeDiscovery` |
|
||
| 按钮盒 | `BasicButtonBox` | `Leeg/AzowieButtonBox` | 类名 + `UiTypeDiscovery` |
|
||
|
||
### 4.4 Fields & Tags(轻量配置)
|
||
|
||
除 JSON 配置文件外,系统大量使用地图上的 **fields**(键值对)和 **tags** 驱动行为,例如:
|
||
- 站点 `Region1=1` → 区域流控
|
||
- 轨道 `Magnet=1` → 磁导航段
|
||
- 车辆 `address` → 下位机 IP
|
||
|
||
通用读写入口:`Commons.cs` 中的 `GetXxxField` / `AddOrUpdateXxxField` 系列方法。
|
||
|
||
### 4.5 NavigationProfile(导航场景画像)
|
||
|
||
仅 **Magnetic** 与 **QrLidar** 两个导航卫星实现 `SimpleCore.Navigation.NavigationProfileBase`:
|
||
|
||
```csharp
|
||
public sealed class MagneticSceneProfile : NavigationProfileBase
|
||
{
|
||
public override NavKind Kind => NavKind.Magnetic;
|
||
public override string SceneId => "scene.mag";
|
||
public override IReadOnlyList<Type> CarTypes => new[] { typeof(MagCar) };
|
||
public override void OnActivate(ISceneContext context) { ... }
|
||
}
|
||
```
|
||
|
||
`scene.json` 与 `NavigationProfile` 中的 `CarTypes` **必须保持一致**。
|
||
|
||
---
|
||
|
||
## 5. 模块地图(StandardScene.Core)
|
||
|
||
基座约 110+ 源文件,按目录职责划分如下:
|
||
|
||
| 目录 | 职责 | 关键类型 |
|
||
| --- | --- | --- |
|
||
| `Scheduler/` | 辅助后台 Mission(心跳、区域流控、安全信号) | `HeartBeatMission`, `RegionalTrafficControlMission` |
|
||
| `Chained/` | 搬运与环线任务主流程 | `ChainedDeliveryMission`, `TransportMission`, `AbstractLoopMission`, `LoopMission` |
|
||
| `Chained/Loop/` | 环线规则策略接口 | `IEnterRule`, `IExitRule`, `IJoinRule`, `IBranchRule`, `ITaskStrategy` |
|
||
| `Charge/` | 充电策略、站点管理、UDP 通信、配置 UI | `StandardChargeMission`, `AbstractChargeLogicMission` |
|
||
| `ChargeStationType/` | 充电桩抽象基类 | `AbstractChargeStation` |
|
||
| `InterLock/` | 区域互锁与交通管制 | `AbstractInterlockMission`, `TrafficInterlockMission` |
|
||
| `ExtendDevice/Door/` | 门控抽象、管理器、Mission | `BasicDoorController`, `DoorMission`, `DoorManager` |
|
||
| `ExtendDevice/ButtonBox/` | 按钮盒抽象与管理 | `BasicButtonBox`, `ButtonMission`, `ButtonBoxManager` |
|
||
| `CarTypes/` | 共享字段袋、模拟车 | `BasicFields`, `DummyCar`, `KivaFields` |
|
||
| `Coders/` | 导航无关的通用轨迹编码器 | `CommonTrackCoders`, `LidarAreaSwitchCoder` |
|
||
| `Model/` | 任务、地图、配置数据模型 | `TaskModel`, `LoopTask`, `Map`, `ChargingSetting` |
|
||
| `TCP/` | 异步 TCP 客户端 | `AsyncTcpClient` |
|
||
| `Utils/` | JSON、Modbus、WebAPI、CycleGUI 辅助 | `WebAPIHelper`, `CycleUiHelper`, `CarRemoteHelper` |
|
||
| `CommonTools/` | 原子文件写入、雪花 ID | `AtomicFileUpdateHelper`, `SnowflakeIdGenerator` |
|
||
| 根目录 | 全局工具与 HTTP 入口 | `Commons.cs`, `WebApi.cs`, `Heuristic.cs`, `LadderLogic.cs` |
|
||
|
||
### 5.1 卫星插件内容
|
||
|
||
**StandardScene.Magnetic**(5 文件)
|
||
- `CarTypes/MagCar.cs` — 磁导航 UDP 车型
|
||
- `Coders/MagneticTrackCoder.cs` — `agv.MagGo` / `agv.NaiveMagGo`
|
||
- `MagneticSceneProfile.cs` + `StandardScene.Magnetic.scene.json`
|
||
|
||
**StandardScene.QrLidar**(12 文件)
|
||
- `CarTypes/` — Forklift, Kiva, ArmCar, DualLiftingCar, MultiVehicleCar, MultiWheelForkLifter, MultiWheelLifterCar
|
||
- `Cad/SyncQrMap.cs` — 二维码地图同步 CAD 工具
|
||
- `QrLidarSceneProfile.cs` + `StandardScene.QrLidar.scene.json`
|
||
|
||
**StandardScene.Devices**(8 文件)
|
||
- `Door/ModbusDoorController.cs`
|
||
- `Charge/FLChargeStation.cs`, `PCBChargeStation.cs`, `MuXingChargeStation.cs`
|
||
- `ButtonBox/LeegButtonBox.cs`, `AzowieButtonBox.cs`
|
||
- `StandardScene.Devices.scene.json`
|
||
|
||
**StandardScene.Protocol.VDA5050**(13 文件)
|
||
- `VDACar/VDA5050Car.cs` — MQTT VDA5050 标准车
|
||
- `VDACar/MasterMQTTCommunication.cs` — MQTT 通信层
|
||
- `StandardScene.Protocol.VDA5050.scene.json`
|
||
|
||
### 5.2 已注册车型一览
|
||
|
||
| 类名 | 所属插件 | 显示名 |
|
||
| --- | --- | --- |
|
||
| `DummyCar` | Core | 模拟车-包络 |
|
||
| `MagCar` | Magnetic | 磁导航车 |
|
||
| `Forklift` | QrLidar | 叉车 |
|
||
| `MultiWheelForkLifter` | QrLidar | 多舵轮叉车 |
|
||
| `DualLiftingCar` | QrLidar | 锂电双举升 |
|
||
| `MultiVehicleCar` | QrLidar | 多车联动 AGV |
|
||
| `ArmCar` | QrLidar | ArmCar |
|
||
| `Kiva` | QrLidar | Kiva |
|
||
| `MultiWheelLifterCar` | QrLidar | 多舵轮顶升车 |
|
||
| `VDA5050Car` | Protocol.VDA5050 | VDA5050 标准车 |
|
||
|
||
### 5.3 已注册 Mission 一览
|
||
|
||
| 类名 | 显示名 | 目录 |
|
||
| --- | --- | --- |
|
||
| `HeartBeatMission` | 调度心跳进程 | Scheduler |
|
||
| `RegionalTrafficControlMission` | 区域流量监控 | Scheduler |
|
||
| `SecuritySignalMission` | 安全信号交互 | Scheduler |
|
||
| `NodeIsEnableMission` | 锁点上传迷毂 | Scheduler |
|
||
| `TransportMission` | 搬运任务进程 | Chained |
|
||
| `LoopMission` | 环线进程 | Chained |
|
||
| `StandardChargeMission` | 充电进程 | Charge |
|
||
| `TrafficInterlockMission` | 交通管制 | InterLock |
|
||
| `DoorMission` | 门控进程 | ExtendDevice/Door |
|
||
| `ButtonMission` | 按钮进程 | ExtendDevice/ButtonBox |
|
||
|
||
---
|
||
|
||
## 6. 扩展点指南
|
||
|
||
接手后最常见的三类扩展:
|
||
|
||
### 6.1 新增 Mission
|
||
|
||
1. 在 `StandardScene.Core` 合适目录新建类,继承 `Mission`(或现有抽象基类)
|
||
2. 添加 `[MissionType(Name="...", editor=typeof(...))]`
|
||
3. 实现 `Create()`、`Execute()`、`Stop()` 三件套
|
||
4. **参考**:`Scheduler/HeartBeatMission.cs`(最小)、`Scheduler/RegionalTrafficControlMission.cs`(事件订阅)
|
||
|
||
### 6.2 新增车型(导航卫星)
|
||
|
||
1. 确定目标卫星(Magnetic / QrLidar / VDA5050)
|
||
2. 新建 `CarTypes/XxxCar.cs`,继承 `GhostCar`,标注 `[CarType]` + `[ProgramTrackCoderSettings]`
|
||
3. 如需新 Coder,在同插件 `Coders/` 实现 `ITrackCoder`
|
||
4. 更新 `XxxSceneProfile.CarTypes` 与 `*.scene.json` 的 `provides.carTypes`
|
||
5. 字段袋扩展放在 Core `CarTypes/`(`internal`,卫星通过 `InternalsVisibleTo` 访问)
|
||
|
||
### 6.3 新增设备驱动
|
||
|
||
1. 在 `StandardScene.Devices` 实现 Core 抽象(如 `BasicDoorController`)
|
||
2. 添加类型特性(如 `[DoorType("MyDoor")]`)
|
||
3. 更新 `StandardScene.Devices.scene.json` 的 `provides` 列表
|
||
4. 确保 `active-scenes.json` 包含 `scene.device`
|
||
|
||
### 6.4 新增 HTTP 接口
|
||
|
||
入口在 `StandardScene.Core/WebApi.cs`(`ApiController`,Nancy 框架)。常见路由前缀:
|
||
- `/car/*` — 车辆与任务
|
||
- `/map/*` — 地图
|
||
- `/task/*` — 任务查询
|
||
- `/mission_reflection/*` — Mission 反射调用
|
||
|
||
> 长期计划是将 WebApi 从 Core 拆出并迁移到 SimpleLite EmbedIO,当前仍以 `WebApi.cs` 为唯一活跃 HTTP 入口。
|
||
|
||
---
|
||
|
||
## 7. 配置文件
|
||
|
||
| 文件 | 位置 | 用途 |
|
||
| --- | --- | --- |
|
||
| `active-scenes.json` | 宿主 `plugins\` | 选择加载哪些卫星场景 |
|
||
| `simple.json` | 宿主工作目录 | 宿主基础配置(含 scenes 备选) |
|
||
| `Config/traffic.json` | 运行时 | 交通互锁 / 区域配置 |
|
||
| `Config/ChargeStations.json` | 运行时 | 充电桩定义 |
|
||
| `Config/ChargeStrategyConfig.json` | 运行时 | 充电策略 |
|
||
| `Config/AlarmConfigs.json` | 运行时 | 报警配置 |
|
||
| `DoorConfig.json` | 运行时 | 门禁配置 |
|
||
| `tasklist.json` | 运行时 | 环线任务配置 |
|
||
|
||
---
|
||
|
||
## 8. 外部依赖
|
||
|
||
### 8.1 程序集引用(HintPath,需本机构建)
|
||
|
||
| DLL | 用途 |
|
||
| --- | --- |
|
||
| `SimpleLite.dll` | 宿主框架:RCS、CAD、UI、`UiTypeDiscovery`、特性标注 |
|
||
| `SimpleCore.dll` | 内核:Mission、Car、交通、路径编译、导航契约 |
|
||
| `CommonUsage.dll` | 数学、VDA5050 消息类型 |
|
||
| `Topaz.dll` | Coder 脚本模板引擎 |
|
||
| `CycleGUI.dll` | 3D / 立即模式 UI(`Private=false`,由宿主加载) |
|
||
| `MDCSToolBox.dll` | 运动学 / 数学(Core、QrLidar) |
|
||
| `LessokajiWeaverUtilities.dll` | i18n、诊断工具 |
|
||
| `leegKeys-sdk.dll` | Leeg 按钮盒 SDK |
|
||
|
||
### 8.2 NuGet(Core 最重)
|
||
|
||
`Nancy`, `MQTTnet`, `EasyModbusTCP`, `IoTClient`, `Jint`, `DocumentFormat.OpenXml`, `Newtonsoft.Json`
|
||
|
||
Protocol.VDA5050 额外使用 `MQTTnet`;Magnetic / QrLidar 仅 `Newtonsoft.Json`。
|
||
|
||
---
|
||
|
||
## 9. 关键设计决策与现状问题
|
||
|
||
### 9.1 当前设计的合理之处
|
||
|
||
- **星型插件拓扑**:基座承载全部 Mission 与设备抽象,卫星按场景热插拔
|
||
- **`scene.json` 清单**:声明式描述插件能力,宿主无需硬编码
|
||
- **`NavigationProfileBase`**:导航平台与车型注册的标准契约
|
||
- **`Chained/Loop/` 规则接口**:环线策略可插拔(`IEnterRule` 等)
|
||
- **`InternalsVisibleTo` 拆分策略**:在不破坏封装的前提下外移车型代码
|
||
|
||
### 9.2 已知架构债务(详见 `StandardScene架构重构方案.md`)
|
||
|
||
| 编号 | 问题 | 影响 |
|
||
| --- | --- | --- |
|
||
| S1 | Core 背负 MQTT/Modbus/Nancy/OpenXml 等协议依赖 | 基座臃肿,卫星无法独立瘦身 |
|
||
| S2 | WinForms 与 CycleGUI 并存 | 阻塞纯 `net8.0` 跨平台 |
|
||
| S3 | 多个 600~2700 行 God-class(WebApi、AbstractLoopMission 等) | 改动风险高、难测试 |
|
||
| S8 | Coder 注册表限定内核程序集反射 | 导航 Coder 热插拔受限 |
|
||
| S9 | csproj 绝对路径 HintPath | CI / 换机构建需手动适配 |
|
||
|
||
### 9.3 演进方向(摘要)
|
||
|
||
1. 抽离 `StandardScene.Abstractions`(纯契约 + 模型)
|
||
2. 充电子系统独立为卫星 `StandardScene.Charge`
|
||
3. WebApi 按资源拆模块并迁出 Core
|
||
4. UI 全部迁至 CycleGUI 或独立 UI 程序集
|
||
5. 目标 TFM 从 `net8.0-windows` 过渡到 `net8.0`(基础设施层)
|
||
|
||
---
|
||
|
||
## 10. AI / 新工程师接手清单
|
||
|
||
### 10.1 第一天:建立全局认知
|
||
|
||
1. 阅读 `README.md` → 本文档 → `DEVELOPMENT_GUIDE.md`
|
||
2. 打开 `DocumentHub.html` 浏览模块导航
|
||
3. 本地构建:先 SimpleLite,再 StandardScene,部署到 `plugins\`
|
||
4. 启动宿主,确认 `active-scenes.json` 包含所需场景
|
||
|
||
### 10.2 第二天:跟踪一条完整链路
|
||
|
||
**搬运任务链路**(推荐):
|
||
```
|
||
WebApi /car/createTask
|
||
→ TransportMission(ChainedDeliveryMission.LoopAsync)
|
||
→ Commons.NearestTask / 选车逻辑
|
||
→ GhostCar 下发路径(SegmentPlan + Coder 脚本)
|
||
→ TrafficControl 互锁
|
||
→ 下位机 HTTP/MQTT/UDP 通信
|
||
```
|
||
|
||
**充电链路**:
|
||
```
|
||
StandardChargeMission
|
||
→ AbstractChargeLogicMission(电量策略)
|
||
→ AbstractInterlockMission(站点互锁)
|
||
→ AbstractChargeStation 实例(Devices 插件驱动)
|
||
```
|
||
|
||
### 10.3 按任务类型定位文件
|
||
|
||
| 我要做… | 先看 |
|
||
| --- | --- |
|
||
| 最小 Mission 样板 | `Scheduler/HeartBeatMission.cs` |
|
||
| 搬运调度 | `Chained/ChainedDeliveryMission.cs`, `Chained/TransportMission.cs` |
|
||
| 环线任务 | `Chained/AbstractLoopMission.cs`, `Chained/LoopMission.cs` |
|
||
| 区域流控 | `Scheduler/RegionalTrafficControlMission.cs` |
|
||
| 充电 | `Charge/StandardChargeMission.cs`, `Charge/AbstractChargeLogicMission.cs` |
|
||
| 门控 | `ExtendDevice/Door/DoorMission.cs`, `Devices/Door/ModbusDoorController.cs` |
|
||
| HTTP API | `WebApi.cs` |
|
||
| 新车型 | 对应卫星 `CarTypes/` + `Coders/` + `*SceneProfile.cs` |
|
||
| 字段/选车/路径辅助 | `Commons.cs` |
|
||
| 地图与任务模型 | `Model/` |
|
||
|
||
### 10.4 修改前的安全检查
|
||
|
||
- [ ] 确认目标变更属于 Core 还是卫星(避免在 Core 放平台专有逻辑)
|
||
- [ ] 若改车型,同步 `scene.json` + `NavigationProfile.CarTypes`
|
||
- [ ] 若改设备驱动,确认 `scene.device` 在 `active-scenes.json` 中
|
||
- [ ] 若改 Coder,注意 `priority` 与字段袋哨兵值(`-1` 语义)
|
||
- [ ] 编译后检查 `build\plugins\` 产物是否完整
|
||
|
||
---
|
||
|
||
## 11. 文档索引
|
||
|
||
| 文档 | 用途 |
|
||
| --- | --- |
|
||
| **本文档 `ARCHITECTURE.md`** | 整体架构、模块地图、扩展点、接手清单 |
|
||
| `DEVELOPMENT_GUIDE.md` | 开发环境、案例教程、调试建议 |
|
||
| `QUICK_REFERENCE.md` | 高频入口与配置速查 |
|
||
| `StandardScene架构重构方案.md` | 架构演进与分层目标 |
|
||
| `StandardScene拆分计划.md` | 程序集拆分进度 |
|
||
| `StandardScene代码审查报告.md` | 质量缺陷与修复记录 |
|
||
| `StandardScene.Core/Docs/` | 充电、门控、Coder 专题手册 |
|
||
|
||
---
|
||
|
||
## 附录 A:scene.json 完整示例
|
||
|
||
**导航插件(scene.mag)**:
|
||
```json
|
||
{
|
||
"id": "scene.mag",
|
||
"displayName": "磁导航平台",
|
||
"navKind": "magnetic",
|
||
"assembly": "StandardScene.Magnetic.dll",
|
||
"coreVersion": ">=1.0.0",
|
||
"requiresCore": "StandardScene.dll",
|
||
"provides": {
|
||
"carTypes": ["MagCar"],
|
||
"missionTypes": []
|
||
}
|
||
}
|
||
```
|
||
|
||
**设备插件(scene.device)**:
|
||
```json
|
||
{
|
||
"id": "scene.device",
|
||
"displayName": "设备驱动(门 / 充电桩 / 按钮盒)",
|
||
"assembly": "StandardScene.Devices.dll",
|
||
"coreVersion": ">=1.0.0",
|
||
"requiresCore": "StandardScene.dll",
|
||
"provides": {
|
||
"doorControllers": ["ModbusDoorController"],
|
||
"chargeStations": ["FLChargeStation", "PCBChargeStation", "MuXingChargeStation"],
|
||
"buttonBoxes": ["LeegButtonBox", "AzowieButtonBox"]
|
||
}
|
||
}
|
||
```
|
||
|
||
## 附录 B:插件引导钩子
|
||
|
||
基座在宿主加载早期通过反射调用:
|
||
|
||
```csharp
|
||
// StandardScene.Core/Commons.cs
|
||
public class CustomOperationsBeforeLoading
|
||
{
|
||
public static void Set()
|
||
{
|
||
TrafficControl.OnDeadLock = (loopingCar) => { /* 死锁告警 */ };
|
||
}
|
||
}
|
||
```
|
||
|
||
这是少数几个 **无 Mission 启动即可生效** 的全局初始化入口之一。
|