Files
StandardSence/Doc/ARCHITECTURE.md
T
zhaowei.huang a0dc1e6cd0 refactor: 插件 UI 从 WinForms 迁移到 CycleGUI,并修复代码质量问题
将 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 项)暂未处理,留待单独任务。
2026-06-26 15:00:53 +08:00

526 lines
20 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.
# 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.dllscene.mag
├── StandardScene.QrLidar → 输出 StandardScene.QrLidar.dllscene.qrlidar
├── StandardScene.Devices → 输出 StandardScene.Devices.dllscene.device
└── StandardScene.Protocol.VDA5050 → 输出 StandardScene.Protocol.VDA5050.dllscene.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` | 否 | VDA5050MQTT)协议栈与标准车型 |
---
## 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 / SegmentPlanSimpleCore
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 NuGetCore 最重)
`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-classWebApi、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
→ TransportMissionChainedDeliveryMission.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 专题手册 |
---
## 附录 Ascene.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 启动即可生效** 的全局初始化入口之一。