将 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 项)暂未处理,留待单独任务。
614 lines
51 KiB
Markdown
614 lines
51 KiB
Markdown
# StandardScene 插件化拆分计划(导航场景插件化 · Phase C 落地)
|
||
|
||
> 版本:草案 **v2**(按评审反馈更新)
|
||
> 编写依据:对当前工程 `E:\Work\Core\Simple-FR\StandardSence`(.NET Framework 4.8 单体插件)的**逐文件精读**。
|
||
> 上游设计:承接并细化《配置向导与导航场景插件化设计.md》第 5 节「StandardScene 拆分」与第 11.3 节「Phase C」。
|
||
> 本文目标:把上游"框架级"拆分意图,落地为**基于真实代码事实、可直接执行**的文件级/类级拆分计划。
|
||
> 范围声明:本文原为**计划文档**。**自「会话1」(2026-06-09) 起已开始落地实施**,实际进度与代码现状见 **§11 实施进度记忆**(含已落地改动、当前可编译状态、待确认阻塞项)。
|
||
|
||
### ⚠️ 架构决策变更(2026-06-12,用户拍板):「磁 / 二维码 / 激光」三场景 → **两场景平台**
|
||
|
||
原计划的 `Magnetic` / `QrCode` / `Laser` 三个导航 dll 调整为 **两个场景平台插件**(已落地,全解决方案 0 错误):
|
||
|
||
| 插件 dll | scene id | 内容 | 说明 |
|
||
|---|---|---|---|
|
||
| `StandardScene.Magnetic.dll` | `scene.mag` | Kiva、MultiWheelLifterCar + `MagneticTrackCoder` | 磁导航平台(保留车型上的 Qr 地标段能力) |
|
||
| `StandardScene.QrLidar.dll` | `scene.qrlidar` | Forklift、MultiWheelForkLifter、DualLiftingCar、MultiVehicleCar、ArmCar + `SyncQrMap` | 激光+二维码融合平台:激光坐标导航由内核 `GhostCar.BasicGo` 兜底,`QrGo` 按轨道 tag 逐段触发,**融合或单独使用均可** |
|
||
| `StandardScene.Devices.dll` | `scene.device` | 不变 | 清单 id 由 `devices` 规范化 |
|
||
| `StandardScene.Protocol.VDA5050.dll` | `scene.vda5050` | 不变 | 清单 id 由 `protocol.vda5050` 规范化 |
|
||
|
||
关键机制结论与配套改动:
|
||
|
||
1. **车型按平台归位**(推翻 v2 "车型留基座"):依据 = 项目存档按**短类名**(`JSONLoader` 用 `type.Name.ToLower()`)匹配车型,类迁 dll 不破坏旧存档;coder 特性 `GetCustomAttributes(inherit:true)` 沿继承链收集,内核 `GhostCar` 的 BasicGo 天然被所有车型继承。
|
||
2. **共享字段袋下沉基座**:`KivaFields.cs` / `MultiWheelLifterFields.cs`(ArmCar、MultiVehicleCar 跨平台继承它们);`IScriptErrorRecoverable` 接口解耦 `AbstractLoopMission` 对 Kiva 的反向依赖。
|
||
3. **清单命名修正**:内核只识别 `<dll>.scene.json`,原裸 `scene.json` 永远不会被扫描到——已全部改名并规范 id。
|
||
4. **内核配套**(Simple 仓库):① `Startup.LoadPlugins` 两阶段加载——清单 `requiresCore` 声明的基座(`StandardScene.dll`)自动并入 alwaysLoad 且 **non-collectible 先行加载**(否则衍生插件的 collectible ALC 解析不到基座,运行期必炸);② `SceneManifest.navKinds` 多导航声明 + `INavigationProfile.Kinds`(qrlidar 同时覆盖 Laser+QrCode,`FindByKind` 按集合匹配);③ `ShouldLoad` 规则改为「**有清单(含设备/协议)即参与激活判定**,无清单兼容全加载」,scene.device 因此可被选择性加载。
|
||
5. **平台配套**(Migu2.0):`DeploymentProfile.NavKindToSceneId` 改映射 magnetic→scene.mag、qrcode/laser→scene.qrlidar;向导写 active-scenes.json 时固定并入 scene.device。
|
||
|
||
### v2 评审反馈要点(本次更新依据)
|
||
|
||
1. **宿主切换**:StandardScene 改为依赖 **`SimpleLite`(net8.0)**,**老 `SimpleComposer.exe`(net4.8)废弃**。内核引用层(命名空间 `SimpleComposer.RCS` → `SimpleLite.RCS` 等)正由**另一个 AI 会话**同步改造,本文按新宿主表述。
|
||
2. **目标框架统一 `net8.0`**(与 SimpleLite 一致;**非 net8.0-windows**)。SimpleLite UI 采用 **CycleGUI**、WebApi 采用 **EmbedIO**,故 StandardScene **需去除 WinForms 依赖**,窗体迁移到 CycleGUI 或平台 Web。
|
||
3. **设备驱动必须独立 dll**,且**支持热卸载/加载**(配合 SimpleLite `/plugins` reload/unload + collectible ALC)。
|
||
4. **`FactoryTest` 与松灵残留:直接删除**,不纳入 Core,也不纳入 Customer。
|
||
5. **`WebApi.cs` 是面向老平台的 Nancy 接口**:本次**整理后暂留 Core**,**后期废弃**,能力迁移到 SimpleLite 接口(见 `E:\Work\Core\Simple-FR\Simple\SimpleLite\Docs\MIGU-API.md`)。此版本先保留。
|
||
|
||
---
|
||
|
||
## 0. TL;DR(结论先行)
|
||
|
||
1. **导航方式与车型是正交的两个维度**。导航(磁 / 二维码 / 激光)由**轨道/站点字段 + TrackCoder**决定,不是车型固有属性;同一车型(如 `Kiva`)的类上**同时**挂磁、二维码、激光避障三类 coder。上游"按车型整包切到某导航 dll"**切不干净**,修正为「**车型留基座 + 导航能力抽离为可插拔 coder**」。
|
||
2. **激光"避障"(LidarArea) ≠ 激光"导航定位"(LidarMap/SLAM)**:避障通用留 Core,仅 SLAM 地图进 Laser。
|
||
3. **`WebApi.cs`(123KB) 是老平台 Nancy 接口**,导航耦合极弱(仅二维码 `QrMap`、激光 `getLidarMap`)。**整理后暂留 Core,标记 deprecated,后期迁 SimpleLite EmbedIO 接口**(§4.7 给出端点映射)。
|
||
4. **存在大量重复代码**可借本次"抽离标准功能"沉淀:磁导航循迹器写了**两份**、`newReset/newTrafficReset` 在 3 个车型复制、`SetDisplayInfo/GetCarStatus/Mstsc/EmergencyStop` 雷同。
|
||
5. **三个正交维度**:①导航(磁/二维码/激光) ②车型(顶升/叉车/Kiva/机械臂…) ③设备驱动(充电桩/门/按钮盒)。设备驱动**独立成可热插拔 dll**。
|
||
6. **VDA5050 是自成一体的 MQTT 协议栈**,独立 dll。
|
||
7. **两大技术主线**:① 把 TrackCoder 从"编译期特性硬绑定车型"改为"导航插件运行期注册",需内核 `SimpleCore` 配合;② **net4.8 → net8.0 迁移**:换宿主(SimpleComposer→SimpleLite)+ **去 WinForms(窗体迁 CycleGUI/Web)**。
|
||
|
||
---
|
||
|
||
## 1. 现状盘点(基于代码事实)
|
||
|
||
### 1.1 工程概况(来自 `StandardScene.csproj`)
|
||
|
||
| 项 | 现状 | 目标(本次方向) |
|
||
|---|---|---|
|
||
| 输出类型 | `Library`(插件) | 多个 `Library` 插件 dll |
|
||
| 目标框架 | `.NET Framework 4.8` | **`net8.0`**(与 SimpleLite 一致,去 WinForms) |
|
||
| 宿主 | `SimpleComposer.exe`(net4.8) | **`SimpleLite`(net8.0)**,老 Composer 废弃 |
|
||
| 契约引用 | `RefSimpleCore.dll` + `SimpleComposer.exe` | **`SimpleCore`(netstandard2.0/net8) + `SimpleLite` 程序集** |
|
||
| UI | `System.Windows.Forms`(大量窗体) | **CycleGUI / 平台 Web**(移除 WinForms) |
|
||
| 对外接口 | `WebApi.cs`(Nancy 1.4.5) | 暂留 Core;后期迁 **SimpleLite EmbedIO**(MIGU-API) |
|
||
| 其它程序集 | `CommonUsage`、`MDCSToolBox`、`leegKeys-sdk`、`LessokajiWeaverUtilities` | 随归属 dll 保留/下沉 |
|
||
| NuGet | `MQTTnet`、`EasyModbusTCP`、`IoTClient`、`Jint`、`Nancy(1.4.5)`、`Newtonsoft.Json`、`DocumentFormat.OpenXml` | 随归属拆分(Nancy 验证 net8 兼容或对齐 SimpleLite 的 Nancy 2.0) |
|
||
| 产物落地 | `PostBuildEvent` 拷 dll → `build\plugins\` | 各 dll + `scene.json` → SimpleLite `plugins\` |
|
||
|
||
### 1.2 模块与文件分组(约 110 个有效 `.cs`)
|
||
|
||
| 目录 | 内容 | 现状性质 |
|
||
|---|---|---|
|
||
| `CarTypes/` | `Forklift`、`Kiva`、`ArmCar`、`DualLiftingCar`、`MultiWheelForkLifter`、`MultiVehicleCar`、`MultiWheelLifterCar`、`DummyCar`、`UselessCar`、`BasicFields`、`VehicleMonitor`(窗体) | 车型 + 内联导航 coder |
|
||
| `CarTypes/VDACar/` | `VDA5050Car`、`VDA5050Commons/Helper/Interface/Segment/WebApi`、`MasterMQTTCommunication`、`TextViewer`(窗体) | VDA5050 通信协议栈 |
|
||
| `Chained/`(含 `Loop/`) | 搬运/环线任务 + `DeliveryViewer/LoopViewer`(窗体) | 任务调度 |
|
||
| `Charge/` | 充电任务 + `ChargeStation*`/`ChargeStrategy*`/`Alarm*`/`Communication*` + 多个 `*Form`(窗体) | 充电逻辑 + UI/服务 |
|
||
| `ChargeStationType/` | `AbstractChargeStation` → `FL`/`MuXing`/`PCB` | 充电桩厂商驱动 |
|
||
| `InterLock/` | `AbstractInterlockMission`、`TrafficInterlockMission`、`TrafficInterlockViewer`(窗体) | 互锁/交管 |
|
||
| `Scheduler/` | `HeartBeat`/`NodeIsEnable`/`RegionalTrafficControl`/`SecuritySignal` Mission | 调度信号 |
|
||
| `ExtendDevice/Door/` | `BasicDoorController` → `ModbusDoorController`、`DoorMission`、`DoorTypeAttribute`、`DoorManager/DoorMonitor`(窗体) | 门控驱动 |
|
||
| `ExtendDevice/ButtonBox/` | `BasicButtonBox` → `LeegButtonBox`/`AzowieButtonBox`、`ButtonMission`、`ButtonBoxManager`(窗体) | 呼叫器驱动 |
|
||
| `Model/` | `Map`(含 `LidarMap`)、`SimpleMap`、`TaskModel`、`LoopTask`、各 `*Setting`、`VehicleStatus`、`MissionState`、`MapStructure` | 数据模型 |
|
||
| `Utils/` `TCP/` `CommonTools/` | Json/Modbus/WebAPIHelper、AsyncTcpClient、Snowflake/AtomicFile | 基础设施 |
|
||
| 根 | `Commons.cs`、`Heuristic.cs`、`LadderLogic.cs`、`StandardCADTool.cs`、`WebApi.cs`、`FactoryTest.cs` | 公共 + 契约 + 老 API + 产测 |
|
||
|
||
### 1.3 车型清单与继承
|
||
|
||
| 车型类 | `[CarType]` | 基类 | 关键特征 |
|
||
|---|---|---|---|
|
||
| `Kiva` | "Kiva" | `GhostCar` | 内联磁 coder `AllCarMagTrackCoder` + Qr + 避障 + 取放货 + `KivaCarTrackCoder`(转弯) |
|
||
| `Forklift` | "叉车" | `GhostCar` | 避障 + 取放货(无显式磁/二维码) |
|
||
| `MultiWheelLifterCar`(CarTypes) | "多舵轮顶升车" | `GhostCar` | 内联磁 coder `MagTrackCoder` + Qr + 钻车/夹抱 |
|
||
| `MultiWheelForkLifter` | "多舵轮叉车" | `GhostCar` | 简化取放货 |
|
||
| `MultiVehicleCar` | "多车联动AGV" | `GhostCar` | 多车 sync + Qr + 钻车 |
|
||
| `DualLiftingCar` | "锂电双举升" | `GhostCar` | 无 coder(仅 UI/测试) |
|
||
| `ArmCar` | "ArmCar" | `GhostCar` | 机械臂动作;**依赖 `VDA5050SiteField`**、继承 `Kiva*Fields` |
|
||
| `DummyCar` | "模拟车-包络" | `Car` | **命名空间 `AMRScene1`**;`Jint` 仿真 |
|
||
| `UselessCar` | (已注释,未注册) | `GhostCar` | 测试残留 |
|
||
|
||
### 1.4 Mission 继承体系(均派生内核 `Mission`,导航无关)
|
||
|
||
```
|
||
Mission
|
||
├─ AbstractChainedDeliveryMission / ChainedDeliveryMission(→TransportDelivery) Chained/
|
||
├─ AbstractLoopMission(→LoopMission) Chained/
|
||
├─ TrafficInterlockMission / AbstractInterlockMission InterLock/
|
||
│ └─ AbstractChargeLogiceMission(→StandardChargeMission) Charge/
|
||
├─ HeartBeat/NodeIsEnable/RegionalTrafficControl/SecuritySignal Mission Scheduler/
|
||
├─ DoorMission / ButtonMission ExtendDevice/
|
||
└─ FactoryTest(产测,本次删除) 根
|
||
```
|
||
|
||
### 1.5 设备驱动体系(第三正交维度,本次独立 dll + 热插拔)
|
||
|
||
- 充电桩:`AbstractChargeStation` → `FLChargeStation` / `MuXingChargeStation`(牧星) / `PCBChargeStation`;`ChargeStationType` 枚举;`StandardChargeMission` 按 `car.fields["MuXing"]` 区分 FRLD/MuXing。
|
||
- 门:`BasicDoorController` → `ModbusDoorController`;`DoorTypeAttribute`(注册契约)。
|
||
- 按钮盒:`BasicButtonBox` → `LeegButtonBox`(依赖 `leegKeys-sdk`/`leegiot`) / `AzowieButtonBox`。
|
||
|
||
### 1.6 VDA5050 子系统(独立 MQTT 协议栈)
|
||
|
||
- `VDA5050Car : Car` + `MasterMQTTCommunication` + `VDA5050Interface/Helper/Commons/Segment/WebApi` + `TextViewer`(窗体);依赖 `CommonUsage.Protocols.VDA5050.*` + `MQTTnet`。
|
||
- VDA5050 车端自管导航定位,与磁/二维码/激光维度无关。
|
||
- 耦合点:`ArmCar` 引用 `VDA5050SiteField`(拆分时解依赖)。
|
||
|
||
### 1.7 删除项(拆分前清理,**不进 Core/Customer**)
|
||
|
||
| 文件/类 | 原因 | 处置 |
|
||
|---|---|---|
|
||
| `FactoryTest.cs` | 产测专用,非标准能力 | **删除**(评审已确认) |
|
||
| 根 `SongLingDeliveryViewer.Designer.cs` | 松灵客户残留,仅 `.Designer.cs`、无主文件、未被 `csproj` 收录 | **删除** |
|
||
| 根 `MultiWheelLifterCar.cs` | 与 `CarTypes/MultiWheelLifterCar.cs` 重名旧文件,**未被 `csproj` 收录**(死文件) | **删除** |
|
||
| `CarTypes/UselessCar.cs` | `[CarType]` 已注释、仅反射示例 | 删除(或移测试样例) |
|
||
|
||
---
|
||
|
||
## 2. 关键洞察(精读结论 → 对上游设计的修正)★
|
||
|
||
### 2.1 洞察 A:导航是"轨道/站点字段 + Coder",与车型正交
|
||
- `CarTypes/BasicFields.cs:23` `TagValue //磁导航,二维码值,或者rfid 值`(站点字段)。
|
||
- 磁:`Kiva.cs:37`、`CarTypes/MultiWheelLifterCar.cs:34` `track.fields["Magnet"]`/`NaiveMagnet`(轨道字段)。
|
||
- 二维码:车型 coder `useVerb="dst.tag>0 && src.tag>0"` → `agv.QrGo(...)`。
|
||
- 激光避障:`useVerb="track.LidarArea != -2"` → `agv.SwitchLidarArea(...)`。
|
||
- **结论**:同一车型在不同轨道字段下走不同 coder 分支;按车型切 dll 会复制车型或丢能力。
|
||
|
||
### 2.2 洞察 B:导航逻辑以"特性"内联在车型,且多导航混杂
|
||
- `[TemplateTrackCoderSettings]`/`[ProgramTrackCoderSettings(program=typeof(...))]` 编译期硬绑定到车型类型。
|
||
- `Kiva` 同时挂磁(prio19)+二维码(prio30)+避障+取放货。
|
||
- **结论**:导航 dll 要可插拔地为车型提供 coder,必须把 coder 外置并由内核支持**运行期注册**(§7.1)。
|
||
|
||
### 2.3 洞察 C:激光"避障" ≠ 激光"导航定位"
|
||
- 避障:`LidarArea`/`SwitchLidarArea`/`ChangeAvoidanceDistance`/`FrontLidarDetect`——几乎所有车型都有,通用 → Core。
|
||
- 定位:`Model/Map.cs:183 LidarMap`(拉 `127.0.0.1:4321` SLAM 栅格) + `WebApi.cs:1021 /map/getLidarMap` → Laser。
|
||
|
||
### 2.4 洞察 D:可"抽离为标准功能"的重复代码
|
||
| 重复项 | 位置 | 抽离目标 |
|
||
|---|---|---|
|
||
| 磁循迹器(选路+`MagGo/NaiveMagGo`) | `Kiva.cs:32 AllCarMagTrackCoder`、`CarTypes/MultiWheelLifterCar.cs:29 MagTrackCoder` | 合并为唯一 `MagneticTrackCoder`(Magnetic dll) |
|
||
| `newReset/newTrafficReset` | `Kiva.cs:715`、`Forklift.cs:279`、`CarTypes/MultiWheelLifterCar.cs:347` | 上提 Core 车型基类 |
|
||
| `SetDisplayInfo` | 各车型雷同 | Core 基类默认实现 |
|
||
| `Mstsc/EmergencyStop/ResetClumsy`(HTTP:8008) | 多车型重复 | Core 基类 |
|
||
| 避障/IO/纠偏 coder 模板 | 各车型重复粘贴 | Core 通用 coder 模板集 |
|
||
| `GetCarStatus` | `Commons` 与 `MultiWheelForkLifter` 各一份 | 统一 `Commons` |
|
||
|
||
### 2.5 洞察 E:`WebApi.cs` 是老平台 Nancy 接口,整体面临废弃
|
||
- `ApiController : NancyModule`(`WebApi.cs:35`),40+ 端点;导航相关仅二维码 `QrMap`(`:38/:40/:2050`)+`QrSite`(`:2807`) 与激光 `getLidarMap`(`:1021`)。
|
||
- 其能力在 SimpleLite 已由 **EmbedIO**`/projection/*`(投影快照 + reflection + map-edit + scenes,见 MIGU-API.md)覆盖。
|
||
- **处置(本版)**:整理后**暂留 Core**(标 `[Obsolete]`/注释 deprecated);**后期整体废弃**,迁移索引见 §4.7。
|
||
|
||
### 2.6 洞察 F:设备驱动是第三个正交维度(本次独立 dll + 热插拔)
|
||
- 充电桩/门/按钮盒按厂商/型号扩展,与导航、车型都正交。
|
||
- 通过既有特性(`ChargeStationType`/`DoorTypeAttribute`/新增 ButtonBoxType)注册,编译为独立 `Devices.*` dll,支持 SimpleLite `/plugins` 热加载/卸载。
|
||
|
||
### 2.7 洞察 G:UI 形态需从 WinForms 迁到 CycleGUI/Web(net8.0 约束)
|
||
- SimpleLite = `net8.0`(纯)、UI 用 **CycleGUI**、WebApi 用 **EmbedIO**,**不依赖 `System.Windows.Forms`**。
|
||
- StandardScene 现有窗体:`DeliveryViewer/LoopViewer/TrafficInterlockViewer/VehicleMonitor/各 Charge*Form/Door*/ButtonBox*/TextViewer` + `Commons` 内 `MessageBox`。
|
||
- **统一 net8.0 ⇒ 必须移除 WinForms**:窗体迁 **CycleGUI**(SimpleLite 立即模式 UI)或平台 **Web**;`MessageBox` 类提示改 CycleGUI 弹窗 / 平台通知。这是本次**重要工作量与风险**。
|
||
|
||
---
|
||
|
||
## 3. 目标架构与目录规划
|
||
|
||
### 3.1 分层依赖图
|
||
|
||
```mermaid
|
||
flowchart TD
|
||
SC["SimpleCore (netstandard2.0/net8)<br/>AbstractCar/CarType/Mission/ITrackCoder/Heuristics<br/>+ 导航契约 NavKind/INavigationProfile/ISceneContext<br/>+ (新增)TrackCoder 运行期注册表"]
|
||
SL["SimpleLite (net8.0 宿主)<br/>CycleGUI UI · EmbedIO WebApi · /plugins 热插拔 · /scenes 选择性加载"]
|
||
CORE["StandardScene.Core (net8.0)<br/>导航无关基座:车型本体+任务/充电/互锁/调度+模型/工具+Commons+通用避障coder<br/>(暂留)WebApi.Core(Nancy, deprecated)"]
|
||
MAG["StandardScene.Magnetic"]
|
||
QR["StandardScene.QrCode"]
|
||
LAS["StandardScene.Laser"]
|
||
VDA["StandardScene.Protocol.VDA5050"]
|
||
DCH["StandardScene.Devices.Charge<br/>(热插拔)"]
|
||
DDR["StandardScene.Devices.Door<br/>(热插拔)"]
|
||
DBT["StandardScene.Devices.ButtonBox<br/>(热插拔)"]
|
||
|
||
SC --> CORE
|
||
SC --> SL
|
||
CORE --> MAG & QR & LAS & VDA & DCH & DDR & DBT
|
||
SL -. 加载/卸载 .-> CORE & MAG & QR & LAS & VDA & DCH & DDR & DBT
|
||
```
|
||
|
||
### 3.2 解决方案目录布局(单工程 → 多工程,统一 net8.0)
|
||
|
||
```
|
||
StandardScene/ 解决方案根
|
||
├─ StandardScene.Core/ net8.0,标准基座(alwaysLoad,不单独作为导航场景)
|
||
│ ├─ Navigation/ INavigationProfile/NavKind/ISceneContext/Registry
|
||
│ ├─ Cars/ 车型基类 StandardCarBase + 各车型本体(无导航 coder、无 WinForms)
|
||
│ │ └─ Sim/ DummyCar(仿真,AMRScene1 命名空间收敛)
|
||
│ ├─ Coders/ 通用 coder(避障/IO/纠偏/取放货模板)
|
||
│ ├─ Chained/ Charge/ ChargeStationType(抽象) / InterLock/ Scheduler/
|
||
│ ├─ ExtendDevice/ 设备框架(基类 + 注册特性)
|
||
│ ├─ Model/ Utils/ TCP/ CommonTools/
|
||
│ ├─ Ui/ CycleGUI 面板(替代原 WinForms 窗体)
|
||
│ ├─ Commons.cs Heuristic.cs LadderLogic.cs StandardCADTool.cs
|
||
│ └─ WebApi.Core.cs 老 Nancy API(deprecated,暂留,后期删)
|
||
├─ StandardScene.Magnetic/ → plugins/ + scene.json
|
||
├─ StandardScene.QrCode/ → plugins/ + scene.json
|
||
├─ StandardScene.Laser/ → plugins/ + scene.json
|
||
├─ StandardScene.Protocol.VDA5050/ → plugins/ + scene.json
|
||
├─ StandardScene.Devices.Charge/ → plugins/(热插拔)
|
||
├─ StandardScene.Devices.Door/ → plugins/(热插拔)
|
||
├─ StandardScene.Devices.ButtonBox/ → plugins/(热插拔)
|
||
└─ StandardScene.sln
|
||
```
|
||
|
||
### 3.3 各 dll 职责
|
||
|
||
| dll | 职责 | 可激活/热插拔 |
|
||
|---|---|---|
|
||
| `StandardScene.Core` | 导航无关一切:车型本体、任务/充电/互锁/调度、模型/工具、`Commons`/契约、通用避障 coder、(暂留)老 WebApi | 基座(`alwaysLoad`) |
|
||
| `StandardScene.Magnetic` | 统一 `MagneticTrackCoder` + 磁条字段语义 | 是 |
|
||
| `StandardScene.QrCode` | `QrTrackCoder` + `SyncQrMap` + 二维码地图下发 | 是 |
|
||
| `StandardScene.Laser` | `LidarMap`/`getLidarMap`(SLAM) | 是 |
|
||
| `StandardScene.Protocol.VDA5050` | VDA5050/MQTT 协议栈 + `VDA5050Car` | 是 |
|
||
| `StandardScene.Devices.Charge` | 充电桩 FL/MuXing/PCB 驱动 | **是(热插拔)** |
|
||
| `StandardScene.Devices.Door` | 门 Modbus 驱动 | **是(热插拔)** |
|
||
| `StandardScene.Devices.ButtonBox` | 按钮盒 Leeg/Azowie 驱动 | **是(热插拔)** |
|
||
|
||
---
|
||
|
||
## 4. 功能归属矩阵(文件级 / 类级)★
|
||
|
||
> 动作:**移动**/**拆分**/**抽离**/**保留**/**删除**/**迁UI**(WinForms→CycleGUI/Web)/**待复核**。
|
||
|
||
### 4.1 车型(`CarTypes/`)
|
||
|
||
| 现状 | 目标 | 动作 | 说明 |
|
||
|---|---|---|---|
|
||
| `BasicFields.cs` | Core | 移动 | 车型公共字段 |
|
||
| `Kiva.cs::Kiva` | Core(Cars) | 拆分 | 本体留 Core;移除内联磁/Qr coder 特性 |
|
||
| `Kiva.cs::AllCarMagTrackCoder` | Magnetic | 抽离 | 并入唯一 `MagneticTrackCoder` |
|
||
| `Kiva.cs::KivaCarTrackCoder` | Core(Coders) | 移动 | 转弯,导航无关 |
|
||
| `Forklift.cs` | Core(Cars) | 移动 | 通用避障/取放货 |
|
||
| `CarTypes/MultiWheelLifterCar.cs::MultiWheelLifterCar` | Core(Cars) | 拆分 | 本体留 Core;移除内联磁/Qr |
|
||
| `CarTypes/MultiWheelLifterCar.cs::MagTrackCoder` | Magnetic | 抽离 | 并入 `MagneticTrackCoder`(去重) |
|
||
| `MultiWheelForkLifter.cs` | Core(Cars) | 移动 | `GetCarStatus` 并入 `Commons` |
|
||
| `MultiVehicleCar.cs` | Core(Cars) | 拆分 | 联动留 Core;Qr coder 外移 QrCode |
|
||
| `DualLiftingCar.cs` | Core(Cars) | 移动 | 无 coder |
|
||
| `ArmCar.cs` | Core(Cars) | 拆分/解耦 | 解除 `VDA5050SiteField` 依赖 |
|
||
| `DummyCar.cs` | Core(Cars/Sim) | 移动 | `AMRScene1` 命名空间收敛 |
|
||
| `UselessCar.cs` | — | 删除 | 未注册 |
|
||
| `VehicleMonitor.cs(.Designer)` | Core(Ui) | **迁UI** | WinForms → CycleGUI |
|
||
|
||
### 4.2 VDA5050(`CarTypes/VDACar/`)
|
||
|
||
| 现状 | 目标 | 动作 |
|
||
|---|---|---|
|
||
| `VDA5050*` + `MasterMQTTCommunication` | `Protocol.VDA5050` | 移动(整子目录) |
|
||
| `TextViewer.cs(.Designer)` | `Protocol.VDA5050`(Ui) | 迁UI(CycleGUI) |
|
||
| `VDA5050SiteField`(被 ArmCar 引用) | Core 公共字段 或 VDA dll | 待复核(ArmCar 留 Core 则下沉 Core) |
|
||
|
||
### 4.3 任务族(`Chained/` `InterLock/` `Scheduler/`)
|
||
|
||
| 现状 | 目标 | 动作 |
|
||
|---|---|---|
|
||
| `Chained/*`、`InterLock/*`、`Scheduler/*` 逻辑 | Core | 移动(导航无关) |
|
||
| `DeliveryViewer/LoopViewer/TrafficInterlockViewer`(窗体) | Core(Ui) | 迁UI(CycleGUI/Web) |
|
||
|
||
### 4.4 充电(`Charge/` `ChargeStationType/`)
|
||
|
||
| 现状 | 目标 | 动作 | 说明 |
|
||
|---|---|---|---|
|
||
| `AbstractChargeLogicMission`、`StandardChargeMission` | Core | 移动 | 充电逻辑 |
|
||
| `ChargeStation*`/`ChargeStrategy*`/`Alarm*`/`Communication*`(服务) | Core | 移动 | 充电管理/服务 |
|
||
| 各 `Charge/*Form`(窗体) | Core(Ui) | 迁UI | CycleGUI/Web |
|
||
| `ChargeStationType/AbstractChargeStation.cs` | Core | 移动 | 抽象 + 注册契约 |
|
||
| `ChargeStationType/{FL,MuXing,PCB}ChargeStation.cs` | **`Devices.Charge`** | 拆分 | 厂商驱动,独立热插拔 dll |
|
||
|
||
### 4.5 扩展设备(`ExtendDevice/`)
|
||
|
||
| 现状 | 目标 | 动作 | 说明 |
|
||
|---|---|---|---|
|
||
| `Door/BasicDoorController`、`DoorMission`、`DoorModel`、`DoorTypeAttribute` | Core(框架) | 移动 | 门控框架 + 注册契约 |
|
||
| `Door/ModbusDoorController` | **`Devices.Door`** | 拆分 | Modbus 驱动,独立热插拔 |
|
||
| `Door/DoorManager/DoorMonitor`(窗体) | Core(Ui)/Devices.Door(Ui) | 迁UI | CycleGUI |
|
||
| `ButtonBox/BasicButtonBox`、`ButtonMission`、`ButtonBoxModel` | Core(框架) | 移动 | 按钮盒框架 |
|
||
| `ButtonBox/LeegButtonBox`(`leegKeys-sdk`)、`AzowieButtonBox` | **`Devices.ButtonBox`** | 拆分 | 厂商驱动,`leegKeys-sdk` 随驱动走 |
|
||
| `ButtonBox/ButtonBoxManager`(窗体) | 对应 dll(Ui) | 迁UI | CycleGUI |
|
||
|
||
### 4.6 公共 / 契约 / 模型 / 基础设施
|
||
|
||
| 现状 | 目标 | 动作 | 说明 |
|
||
|---|---|---|---|
|
||
| `Commons.cs::Commons` | Core | 移动 | 解除对 `DummyCar` 硬引用(`GetVehicleStatus`) |
|
||
| `Commons.cs::CustomOperationsBeforeLoading` | 各可激活 dll 各一份 | 复制/分发 | `MessageBox` 死锁提醒改 CycleGUI 弹窗 |
|
||
| `Commons.cs::NoReflectionApi`/`ReflectionApiWithParameter` | SimpleCore 或 Core | 待复核 | 多 dll 共用建议下沉 SimpleCore |
|
||
| `Heuristic.cs` | Core | 移动 | 启发式(宿主反射注册) |
|
||
| `LadderLogic.cs` | Core | 移动 | 防抖/梯形逻辑 |
|
||
| `StandardCADTool.cs`(多数 `CADTool`) | Core | 移动 | 地图编辑工具 |
|
||
| `StandardCADTool.cs::SyncQrMap` | QrCode | 拆分 | 二维码地图下发 |
|
||
| `Model/Map.cs::Map/ArcHelper` | Core | 移动 | 地图序列化 |
|
||
| `Model/Map.cs::LidarMap` | Laser | 拆分 | SLAM 栅格图 |
|
||
| `Model/*`(其余) | Core | 移动 | 数据模型 |
|
||
| `Utils/*`、`TCP/*`、`CommonTools/*` | Core | 移动 | 基础设施 |
|
||
| `FactoryTest.cs` | — | **删除** | 评审确认 |
|
||
| 根 `MultiWheelLifterCar.cs`、根 `SongLingDeliveryViewer.Designer.cs` | — | **删除** | 死/残留 |
|
||
|
||
### 4.7 老 WebApi(`WebApi.cs`)整理与迁移索引
|
||
|
||
**本版处置**:通用端点整理为 `WebApi.Core.cs` 暂留 Core 并标 deprecated;二维码/激光端点随导航 dll;**后期整体删除**,前端改用 SimpleLite 接口。下表为废弃迁移索引(老 Nancy → SimpleLite EmbedIO,依据 MIGU-API.md):
|
||
|
||
| 老端点(`WebApi.cs`) | 行号 | SimpleLite 替代(`/api/sl/projection/...`) |
|
||
|---|---|---|
|
||
| `car_reflection/mission_reflection get_type/methods/fields/execute` | 191–537 | `reflection/methods/*`、`/fields/*`、`/execute/*`、`/bundle/*` |
|
||
| `car/getAllCars`、`api/agv/list` | 1047、2095 | `projection/cars` |
|
||
| `task/getTask` | 1099 | `projection/missions` |
|
||
| `map/getMap` | 995 | `projection/sites`+`/tracks`、或 `map-edit` |
|
||
| `car/goSite` | 1070 | `reflection/car/{id}/goto-site` |
|
||
| `car/reset/repair/blown/ForceStop/ReStart/...` | 767+ | `reflection/execute/{kind}/{id}/{method}`(`[MethodMember]`) |
|
||
| `car/createTask/carTask/cancelTask` | 542/597/900 | `reflection/execute` + `projection/deliveries/*` |
|
||
| `set{Charging,Envelope,TrafficControl,PlanRules}Setting` | 1680+ | `reflection/fields/{kind}/{id}/{field}`(写字段) |
|
||
| `api/CreateSite` | 2055 | `map-edit/objects/site` |
|
||
| `api/QrMap`(二维码) | 2050 | 暂随 QrCode dll;SimpleLite 侧待新增(无直接对应) |
|
||
| `map/getLidarMap`(激光) | 1021 | 暂随 Laser dll;SimpleLite 侧待新增(无直接对应) |
|
||
|
||
> 注:二维码地图下发、激光 SLAM 取图在 SimpleLite 现有 MIGU-API 中**无直接对应**,迁移时需在 SimpleLite/场景插件侧补接口,故这两块随导航 dll 先行保留。
|
||
|
||
---
|
||
|
||
## 5. "抽离标准功能"清单(去重与沉淀)
|
||
|
||
1. **统一磁导航循迹器**:`AllCarMagTrackCoder` + `MagTrackCoder` → 唯一 `StandardScene.Magnetic.MagneticTrackCoder`(参数化 fields)。
|
||
2. **车型基类 `StandardCarBase`(Core)**:上提 `newReset/newTrafficReset`、`SetDisplayInfo`、`Mstsc`、`EmergencyStop/Release`、`ResetClumsy`、`GetCarStatus` 默认实现。
|
||
3. **通用 Coder 模板集(Core/Coders)**:沉淀避障/IO/纠偏/避障尺寸等重复 `[TemplateTrackCoderSettings]`。
|
||
4. **导航能力抽象 `INavigationProfile`**:每个导航 dll 实现一个 Profile(声明 `NavKind` + 提供的 coder/字段语义),Core/宿主反射收集。
|
||
5. **`Commons` 去重**:合并 `GetCarStatus`;`GetVehicleStatus` 去除对 `DummyCar` 的硬编码(改标记接口)。
|
||
6. **设备注册标准化**:充电桩/门/按钮盒统一特性注册,驱动 dll 即插即用 + 热插拔。
|
||
7. **UI 标准化**:原 WinForms 窗体统一迁 CycleGUI 面板(沉淀少量通用面板基类)。
|
||
|
||
---
|
||
|
||
## 6. 命名空间与依赖治理
|
||
|
||
- **宿主/命名空间迁移**:`SimpleComposer.RCS`/`SimpleComposer.UI` → `SimpleLite.RCS`/对应(以内核改造为准,另一会话进行中);引用 `SimpleComposer.exe` → `SimpleLite` 程序集 + `SimpleCore` 契约。
|
||
- **命名空间收敛**:`DummyCar` 的 `AMRScene1` → `StandardScene.Core.Cars.Sim`。
|
||
- **去 WinForms**:移除 `System.Windows.Forms` 引用,窗体迁 CycleGUI/Web,`MessageBox` 改 CycleGUI 弹窗。
|
||
- **反向依赖治理**:`Commons.GetVehicleStatus`↛`DummyCar`;`ArmCar`↛`VDA5050SiteField`;二维码相关集中 QrCode dll,Core 仅留中立扩展点。
|
||
- **三方依赖随归属**:`MQTTnet`→VDA5050;`leegKeys-sdk`→ButtonBox 驱动;`EasyModbusTCP/IoTClient`→Door/Charge 驱动或 Core 工具;`Nancy`→(暂留的 WebApi.Core,验证 net8 兼容或对齐 SimpleLite 的 Nancy 2.0);`Jint`→含 DummyCar 仿真的 Core。
|
||
|
||
---
|
||
|
||
## 7. 关键技术难点与对策
|
||
|
||
### 7.1 难点①:TrackCoder 由"编译期特性"改为"运行期注册"
|
||
- 现状:coder 通过特性硬绑定车型类型。
|
||
- 目标:导航 dll 不改 Core 车型源码即可为车型补 coder。
|
||
- 对策:① **内核扩展(推荐)**——`SimpleCore` 增 coder 注册表,导航 dll 在 `INavigationProfile.OnActivate` 注册/卸载时移除(契合 `/plugins` 热插拔);② 车型留占位、导航 dll 实现委派;③ **兜底**——Core 内置全量 coder,导航 dll 只承载 API/地图/字段/清单。
|
||
- **行动项**:与正在改内核引用的会话同步,确认是否纳入注册表 API。
|
||
|
||
### 7.2 难点②:net4.8 → net8.0 迁移(换宿主 + 去 WinForms)
|
||
- 宿主:引用 `SimpleComposer.exe`(net4.8) → `SimpleLite`/`SimpleCore`(net8);`SimpleComposer` 独有类型在内核侧补齐/下沉(与另一会话协作)。
|
||
- **去 WinForms(重点)**:所有窗体迁 CycleGUI(SimpleLite 立即模式 UI)或平台 Web;`MessageBox`→CycleGUI 弹窗/平台通知。工作量集中在 `Charge/*Form`、`Delivery/Loop/TrafficInterlock Viewer`、`VehicleMonitor`、`Door/ButtonBox` 管理窗体、`VDACar/TextViewer`。
|
||
- 三方库 net8 验证:`Nancy(1.4.5)`(暂留 WebApi,验证或升 2.0)、`MQTTnet/EasyModbusTCP/IoTClient/Jint/Newtonsoft/DocumentFormat.OpenXml`。
|
||
- Fody/`LessokajiWeaver`:与内核一致(注意上游 §13.2 环境约束)。
|
||
|
||
### 7.3 难点③:插件钩子与多 dll 初始化
|
||
- `CustomOperationsBeforeLoading.Set()` 宿主按 dll 反射调用:拆分后每个可激活 dll 各保留一份;用 `INavigationProfile.OnActivate` 做导航 dll 自初始化,避免重复注册全局回调。
|
||
|
||
### 7.4 难点④:设备/导航 dll 热插拔(collectible 卸载)
|
||
- 配合 SimpleLite `/plugins/reload`、`/plugins/{name}/unload` 与 `/scenes/apply`:dll 须可被 collectible ALC 干净卸载(卸载前无存活 `Car/Mission` 实例),`OnDeactivate` 清理注册的 coder/设备/回调/MQTT 连接/TCP 客户端。
|
||
|
||
### 7.5 难点⑤:老 WebApi 暂留与最终下线
|
||
- `WebApi.Core`(Nancy) 暂留 Core 仅为过渡;新功能一律走 SimpleLite EmbedIO。按 §4.7 索引逐步迁移,迁完即删;二维码/激光取图需先在 SimpleLite/场景插件侧补接口。
|
||
|
||
---
|
||
|
||
## 8. 分阶段实施计划(务实路线)
|
||
|
||
> 原则:每阶段都能编译、能加载、可回退。
|
||
|
||
### C0 · 准备与对齐(低风险,先做)
|
||
- 删除:`FactoryTest.cs`、根 `SongLingDeliveryViewer.Designer.cs`、根 `MultiWheelLifterCar.cs`、`UselessCar`。
|
||
- 去重沉淀(§5):统一 `MagTrackCoder`、`GetCarStatus`;提取 `StandardCarBase`。
|
||
- 命名空间收敛 `AMRScene1`→Core。
|
||
- 与内核会话对齐:`SimpleLite`/`SimpleCore` 引用与命名空间、coder 注册表(§7.1)、导航契约(上游 Phase A 已就绪)。
|
||
- 验收:编译通过、行为不变。
|
||
|
||
### C1 · Core 基座 net8.0 化(换宿主 + 去 WinForms 闭环)
|
||
- 新建 `StandardScene.Core`(net8.0),迁入导航无关全部内容;引用切到 `SimpleLite`/`SimpleCore`。
|
||
- **去 WinForms**:窗体迁 CycleGUI;`MessageBox`→CycleGUI。
|
||
- 整理老 `WebApi`→`WebApi.Core`(deprecated, 暂留)。
|
||
- coder 先用兜底(§7.1 方案③)保证不回归。
|
||
- 验收:`StandardScene.Core.dll` 被 SimpleLite 加载、跑通搬运/充电/交管。
|
||
|
||
### C2 · 抽离导航能力 dll
|
||
- `Magnetic`(唯一 `MagneticTrackCoder`)/ `QrCode`(`QrTrackCoder`+`SyncQrMap`+`QrMap`)/ `Laser`(`LidarMap`+`getLidarMap`),各带 `scene.json`。
|
||
- 按 §7.1 选定方案把 coder 接到车型。
|
||
- 验收:仅激活某导航时对应能力可用,其余不加载。
|
||
|
||
### C3 · 设备驱动 dll 化(必做,热插拔)
|
||
- `Devices.Charge`(FL/MuXing/PCB)、`Devices.Door`(Modbus)、`Devices.ButtonBox`(Leeg/Azowie);`leegKeys-sdk` 随驱动。
|
||
- 验证 `/plugins` reload/unload 热插拔;`OnDeactivate` 清理连接。
|
||
- 验收:设备驱动可独立热加载/卸载。
|
||
|
||
### C4 · VDA5050 协议 dll
|
||
- `Protocol.VDA5050`(整 `VDACar/` 迁出,含 MQTT);解 `ArmCar↔VDA5050SiteField`。
|
||
- 验收:激活后 VDA5050 车可用、可卸载。
|
||
|
||
### C5 · 联调、WebApi 迁移与文档
|
||
- 三导航 + 设备 + 协议组合联调;对接 `/scenes/apply` + `active-scenes.json`。
|
||
- 按 §4.7 把可迁的 WebApi 端点切到 SimpleLite,逐步删 `WebApi.Core`。
|
||
- 更新本文件 §11 进度 + `scene.json` 实际清单 + `README/DEVELOPMENT_GUIDE`。
|
||
|
||
---
|
||
|
||
## 9. 插件清单契约(`scene.json`,对接上游 §5.5 与 SimpleLite `/scenes`)
|
||
|
||
```json
|
||
{
|
||
"id": "scene.magnetic",
|
||
"displayName": "磁导航场景",
|
||
"navKind": "Magnetic",
|
||
"assembly": "StandardScene.Magnetic.dll",
|
||
"requiresCore": "StandardScene.Core.dll",
|
||
"provides": { "trackCoders": ["MagneticTrackCoder"], "carTypeBindings": ["*"] }
|
||
}
|
||
```
|
||
|
||
- 平台「配置向导」→ `WizardController` 写配置 → 调 SimpleLite `POST /api/sl/projection/scenes/apply`(写 `active-scenes.json` + 增量 reload)。
|
||
- 数据契约:`data/config-deployment.json`(平台)/ `plugins/active-scenes.json`(内核)/ `plugins/<dll>.scene.json`(插件)。
|
||
|
||
---
|
||
|
||
## 10. 风险、待确认与验收口径
|
||
|
||
### 已确认(v2)
|
||
- 宿主 = SimpleLite;老 SimpleComposer 废弃。
|
||
- 目标框架 = `net8.0`(去 WinForms,UI 迁 CycleGUI/Web)。
|
||
- 设备驱动 = 独立 dll + 热插拔。
|
||
- `FactoryTest`、松灵残留 = 删除。
|
||
- `WebApi.cs` = 整理后暂留 Core、后期废弃迁 SimpleLite。
|
||
|
||
### 待确认
|
||
1. **coder 注册表**:内核是否纳入"运行期把 TrackCoder 注册到车型"的 API(否则 C2 用兜底方案③)。
|
||
2. **UI 迁移范围与节奏**:窗体一次性迁 CycleGUI,还是按 dll 分批;是否部分仅保留平台 Web 入口。
|
||
3. **VDA5050** 独立 dll 确认(推荐独立)。
|
||
4. **二维码地图下发 / 激光 SLAM 取图**:SimpleLite 侧补接口的归属与时间点。
|
||
5. **车型↔导航映射**:是否存在车型仅支持单一导航的硬约束。
|
||
|
||
### 验收口径(每阶段通用)
|
||
- 编译 0 错误;搬运/环线/充电/交管不回归。
|
||
- 选择性加载 + 热插拔:激活集合内能力可用,未激活不加载、可干净卸载。
|
||
- 反射 API(SimpleLite `/reflection`)、车型/面板随已激活 dll 自然收敛。
|
||
|
||
---
|
||
|
||
## 11. 实施进度记忆(跨会话持续更新)
|
||
|
||
> 状态:⬜ 未开始 / 🟦 进行中 / ✅ 完成 / ⏸ 暂缓。
|
||
> **最近更新:会话1(续3,2026-06-09)——设备三 dll 合并为单一 `StandardScene.Devices` + `ChangeAvoidanceParam` 去重(方案 B),全解 `dotnet build` 0 错误。**
|
||
|
||
### 11.0 当前代码现状(重要:已领先早期文档)
|
||
|
||
会话1 接手时发现**代码已被先前会话推进**,与 v2 文档/会话14交接摘要描述的「net4.8 单体、未动代码」**不一致**。以 `StandardScene.csproj` 实际为准:
|
||
|
||
| 项 | 早期文档记述 | **当前实际** |
|
||
|---|---|---|
|
||
| 目标框架 | net4.8 | **`net8.0-windows`**(仍 `UseWindowsForms=true`,过渡态,**尚未**去 WinForms 到纯 net8.0) |
|
||
| 宿主/契约引用 | SimpleComposer.exe + RefSimpleCore | **已切 `SimpleLite.dll` + `SimpleCore.dll`(netstandard2.0)** |
|
||
| Nancy | 1.4.5 | **已对齐 `2.0.0`** |
|
||
| 死代码 | 在仓库 | csproj 已 `Compile Remove`,会话1 已物理删除 |
|
||
| 命名空间 | SimpleComposer.RCS | 车型 using 已是 `SimpleLite.RCS`(内核改造会话已推进) |
|
||
|
||
**可编译基线**:`dotnet build`(net8.0-windows,dotnet SDK 10.0.300)= **0 错误 / 47 警告**(均无害:重复 using、隐藏成员 CS0108、未用变量、`Thread.Abort` SYSLIB0006、CS4014 未 await 等)。
|
||
|
||
### 11.1 步骤状态
|
||
|
||
| 步骤 | 内容 | 状态 | 说明 |
|
||
|---|---|---|---|
|
||
| P0 | 精读现状 + 产出拆分计划 v1 | ✅ | 逐文件精读 |
|
||
| P0.1 | 按评审反馈更新 v2 | ✅ | |
|
||
| **路线决策** | 评审定 **路线乙**:先「纯搬运不改逻辑」的结构拆分,去重在新结构里从容做 | ✅ | 会话1 用户拍板 |
|
||
| **C0-a** | 物理删除死代码 + 清理 csproj | ✅ | 见 §11.3 |
|
||
| **C0-b** | 抽离 **4 个通用(导航无关) coder** 并在 4 车型切换 | ✅ | 见 §11.3;编译 0 错误 |
|
||
| C0-c | 合并两份磁循迹器为唯一 `MagneticTrackCoder` | ✅ | 用户定:采用含 `track.Speed` 的 `NaiveMagGo`;MWL 旧类已删、引用改向;编译 0 错误 |
|
||
| C0-d | `ChangeAvoidanceParam` 去重 | ✅ | 方案 B:4 参 flag 版 `AvoidanceParamCoder`(MWL+MultiVehicle) + 2 参 L,W 版 `AvoidanceParamLWCoder`(Kiva+Forklift);见 §11.4-2 |
|
||
| C0-e | 提取 `StandardCarBase`(newReset/Mstsc/GetCarStatus 等上提)| ⬜ | 未启动 |
|
||
| C0-f | `AMRScene1` 命名空间收敛 | ⬜ | 建议并入 C1 建 Core 工程时一起做 |
|
||
| 路线乙·1 | 工程迁入 `StandardScene.Core/` + 重写 sln(纯搬运) | ✅ | 编译 0 错;AssemblyName 仍=`StandardScene`,对外 dll 名不变 |
|
||
| C1 | 去 WinForms + WebApi.Core 整理 | ⏸ | 用户暂缓(窗体后续迁 migu 平台);过渡期各工程暂 `net8.0-windows` |
|
||
| C2 | Magnetic/QrCode/Laser 三导航 dll | ⏸ | 受阻于内核 coder 注册表(§11.4-4) + 用户将自行重构 coder |
|
||
| **C3** | 设备驱动 dll 化(Charge/Door/ButtonBox,热插拔) | ✅ | 见 §11.3-E3;**合为单一 `StandardScene.Devices`**(用户定,不分多个),编译 0 错、scene.json 产出 |
|
||
| **C4** | VDA5050 协议 dll | ✅ | 见 §11.3-E2;`VDACar/` 整迁出、`VDA5050SiteField` 下沉 Core |
|
||
| C5 | 联调 + WebApi 迁移 SimpleLite + 文档收尾 | ⬜ | 含卫星 dll→宿主 `plugins/` 部署 + 真机联调(见 §11.4-5) |
|
||
|
||
### 11.2 关键决策记录
|
||
- **路线乙(会话1 确认)**:结构拆分优先、纯搬运不改逻辑;去重沉淀在新结构内做。理由:本环境无法跑真实 AGV 回归,纯搬运行为风险低、编译即可保障。
|
||
- 导航与车型正交;导航 coder 外置为可插拔(运行期注册,内核配合;**当前用兜底=Core/单体内置 coder**,用户要求"先抽离合适的通用 coder")。
|
||
- 激光避障(LidarArea)留 Core,仅 SLAM 地图(LidarMap/getLidarMap)进 Laser。
|
||
- 设备驱动单列 `Devices.*` 独立 dll + 热插拔(评审确认)。
|
||
- 宿主 SimpleComposer→SimpleLite;框架统一 net8.0;UI 去 WinForms 迁 CycleGUI/Web(评审确认)。
|
||
- `FactoryTest`、松灵残留删除(评审确认,会话1 已执行)。
|
||
- 老 `WebApi.cs`(Nancy) 暂留 Core、标 deprecated,后期迁 SimpleLite EmbedIO,迁移索引见 §4.7(评审确认)。
|
||
|
||
### 11.3 会话1 已落地改动明细(2026-06-09)
|
||
|
||
**A. C0 死代码物理删除**(编译范围不变,0 错误)
|
||
- 删 `FactoryTest.cs`(`[MissionType]` 展会演示进程,反射注册,无其它引用)
|
||
- 删 根 `MultiWheelLifterCar.cs`(与 `CarTypes/MultiWheelLifterCar.cs` 重名死文件)
|
||
- 删 根 `SongLingDeliveryViewer.Designer.cs`(松灵残留,无主文件)
|
||
- 删 `CarTypes/UselessCar.cs`(`[CarType]` 已注释、未注册)
|
||
- `csproj`:移除上述 3 条 `Compile Remove`;**保留** `Chained\AbstractChainedDeliveryMission.cs` 的 Remove(孤立未编译旧版本,去留待后续核对)
|
||
|
||
**B. 抽离通用(导航无关) coder** —— 新增 `Coders/CommonTrackCoders.cs`(命名空间 `StandardScene.Coders`)
|
||
- 基类 `CommonTemplateTrackCoder : ITrackCoder`:内部复用内核 `ProgramCoderHelper.PrepareTrackEngine` + Topaz 求值,`useVerb`/`templateString` 与原模板逐字一致;统一用 `BasicXxxFields`(这些 coder 仅引用 Basic 字段,等价)。priority 由车型 `[ProgramTrackCoderSettings]` 指定。
|
||
- 4 个通用 coder:
|
||
- `LidarAreaSwitchCoder`(避障,`track.LidarArea != -2` → `SwitchLidarArea`)
|
||
- `AvoidanceDistanceCoder`(无 useVerb → `ChangeAvoidanceDistance(StopDistance,SlowDistance)`)
|
||
- `IoAreaSwitchCoder`(`track.IOArea != -1` → `SwitchIoArea`)
|
||
- `TrackingErrThreshCoder`(`BiasAlarmThresh>0||DthAlarmThresh>0` → `ChangeTrackingErrThresh`)
|
||
- 4 车型已把对应内联 `[TemplateTrackCoderSettings]` 删除,改为 `[ProgramTrackCoderSettings]` 引用(保留各自原 priority):
|
||
|
||
| 车型 | LidarArea | AvoidanceDistance | IoArea | TrackingErrThresh |
|
||
|---|---|---|---|---|
|
||
| `Kiva` | 17 | 20 | 20 | 20 |
|
||
| `MultiWheelLifterCar` | 27 | 20 | 20 | 20 |
|
||
| `MultiVehicleCar` | 27 | 20 | 20 | 20 |
|
||
| `Forklift` | 20 | —(原无) | 20 | 20 |
|
||
|
||
- 各车型加 `using StandardScene.Coders;`。
|
||
- **验证**:每步 `dotnet build` 均 0 错误(Kiva 单切先验范式,再批量推 MWL/MultiVehicle/Forklift)。
|
||
|
||
**C. 仍保留为内联 Template / 程序 coder(本次未动)**
|
||
- 磁程序 coder:`Kiva.AllCarMagTrackCoder`、`MultiWheelLifterCar.MagTrackCoder`(待 C0-c 合并)
|
||
- `ChangeAvoidanceParam`(三变体,待 C0-d)
|
||
- `Kiva.KivaCarTrackCoder`(转弯)、`CalibrateWheelEncoder`(仅 Kiva)
|
||
- 二维码 `QrGo`(导航专用,归 QrCode dll);各车型取放货/钻车/夹抱/TireFollowing 等(车型专用)
|
||
|
||
**D. 会话1(续)去重落地**(编译 0 错误 / 0 lint)
|
||
- **磁循迹器合并(C0-c)**:`Kiva.AllCarMagTrackCoder` 重命名为唯一 `MagneticTrackCoder`(含 `${track.Speed}` 的 `NaiveMagGo`,用户确认);`MultiWheelLifterCar.MagTrackCoder` 整类删除,其 `[ProgramTrackCoderSettings(priority=19)]` 改向 `MagneticTrackCoder`。(暂置 `Kiva.cs` 的 `StandardScene.CarTypes` 命名空间,C2 抽 Magnetic dll 时物理迁出。)
|
||
- **避障 4 参对合并(C0-d 部分)**:新增 `Coders.AvoidanceParamCoder`(`CommonTemplateTrackCoder` 子类,覆写站点字段袋为含 `ChangeAvoidanceParam` 标志位的 `AvoidanceParamSiteFields`),useVerb/模板与原 `MWL`/`MultiVehicle` 逐字一致;两车型删内联 4 参模板、改 `[ProgramTrackCoderSettings(priority=20)]` 引用。基类新增可覆写 `SiteFieldsType` 钩子(默认 `BasicSiteFields`)。
|
||
|
||
**E. 会话1(续2)结构性拆分落地**(路线乙·结构拆分;全解决方案 `dotnet build` 0 错误 / 45 无害警告)
|
||
|
||
*E1. 工程迁入 `StandardScene.Core/`(纯搬运)*
|
||
- 原单体整体迁入子目录 `StandardScene.Core/`;`StandardScene.csproj`→`StandardScene.Core.csproj`(**AssemblyName 仍=`StandardScene`**,对外 dll 名不变);重写 `StandardScene.sln`。
|
||
- 新增 `Properties/InternalsVisibleTo.cs`:对 4 卫星程序集开放 internal(`Protocol.VDA5050`/`Devices.Charge`/`Devices.Door`/`Devices.ButtonBox`),使卫星以"纯搬运"访问 Core internal,免去大量 internal→public 侵入式改动。
|
||
|
||
*E2. `StandardScene.Protocol.VDA5050`(C4)*
|
||
- `CarTypes/VDACar/`(10 文件)整迁至新工程;`scene.json`(provides VDA5050Car);csproj 引 Core(ProjectReference)+SimpleLite/SimpleCore/CommonUsage/Topaz/Weaver + MQTTnet/Nancy/Jint/Newtonsoft。
|
||
- 解耦:`VDA5050SiteField` 由 `VDACar/VDA5050Car.cs` **下沉**至 Core `CarTypes/ArmCar.cs`(`ArmCar` 留 Core 且引用它,不能反依赖 VDA dll)。
|
||
|
||
*E3. `StandardScene.Devices`(C3,用户选 A;**门/充电桩/按钮盒合并为单一 dll**,用户定不分多个;内部按 `Door/`、`Charge/`、`ButtonBox/` 子目录组织,Core 的 IVT 仅 `StandardScene.Devices` 一项)*
|
||
- 搬出 6 具体驱动(**命名空间不变**,仍 `StandardScene.ExtendDevice.*` / `StandardScene.ChargeStationType`,以满足发现谓词 `t.Namespace==基类.Namespace`):
|
||
- Door:`ModbusDoorController`(基类 `BasicDoorController`+`[DoorType]` 留 Core)
|
||
- Charge:`FL/PCB/MuXingChargeStation`(基类 `AbstractChargeStation`+`ChargeUdpService`/`StandardChargeMission` 留 Core)
|
||
- ButtonBox:`Leeg/AzowieButtonBox`(基类 `BasicButtonBox`+`ButtonMission`/`ButtonBoxManager` 留 Core;该 dll 额外引 `Ref/leegKeys-sdk.dll`)
|
||
- **行为保持解耦(2 处下转型→基类虚方法)**:
|
||
- `ChargeUdpService`:`if(cs is PCBChargeStation s) s.IndexReceive=msg[1]` → `cs.OnUdpMessage(msg)`(`AbstractChargeStation` 空实现、`PCB` override)。
|
||
- `ButtonMission`:`if(bb is AzowieButtonBox a) a.ClearButtonRegister(i)` → `bb.ClearButtonRegister(i)`(`BasicButtonBox` 空实现、`Azowie` 改 override)。
|
||
- **类型发现改跨程序集(5 处,关键)**:原 Core 限定扫描(`Type.GetType(简单名)` / `typeof(基类).Assembly.GetTypes()` / `Assembly.GetExecutingAssembly().GetTypes()`)只在 Core 内找类型,驱动外移后**运行期将找不到**。统一改用内核公开的 `SimpleLite.Utils.UiTypeDiscovery.AllTypes()`(`AppDomain.GetAssemblies()` 全域 + 内置 `ReflectionTypeLoadException` 安全枚举),谓词不变 → 今天在 Core 内仍找到原类型(**行为等价**)、外移后亦能发现。涉及 `StandardChargeMission` / `DoorMission` / `DoorManager` / `ButtonMission` / `ButtonBoxManager`。
|
||
- 关键依据:SimpleLite 自身类型发现即 `UiTypeDiscovery`(AppDomain 全域) + `PluginManager`(从 `./plugins/*.dll` 以 collectible ALC 热加载)→**卫星 dll 路线运行期成立**(同时回证 VDA5050Car 可被发现)。
|
||
|
||
### 11.4 待确认 / 阻塞项(影响 C0 收尾与 C2)
|
||
|
||
1. ~~**磁 `NaiveMagGo` 参数差异**~~ **【会话1 已决】**:用户定采用含 `${track.Speed}` 的版本(Kiva 版)。已合并为唯一 `MagneticTrackCoder`;`MultiWheelLifterCar.MagTrackCoder` 删除并改向引用。编译 0 错误。(普通 `MagGo` 两份原本一致;合并后磁逻辑全平台统一。)
|
||
2. ~~**`ChangeAvoidanceParam` 统一方式**~~ **【会话1续3 已决:方案 B】**:用户选 B。落地=4 参 flag 版 `AvoidanceParamCoder`(MWL+MultiVehicle) + 新增 2 参 L,W 版 `AvoidanceParamLWCoder`(Kiva+Forklift,触发统一取 `dst.CarLength!=-1 && dst.CarWidth!=-1`);两车型内联 `[TemplateTrackCoderSettings]`→`[ProgramTrackCoderSettings(priority=20)]` 引用。Forklift 行为不变;Kiva 原无条件→统一后未配置长宽(-1)时不再下发 `(-1,-1)`(预期内安全收敛)。编译 0 错。原分析留档如下:
|
||
- 现状:`Kiva`=无条件/2 参;`Forklift`=`L≠-1&&W≠-1`/2 参;`MWL`/`MultiVehicle`=`ChangeAvoidanceParam==true`/4 参(含中心点)。
|
||
- 已落地(零行为变更):把**逐字相同**的 `MWL`+`MultiVehicle` 4 参对合并为 `Coders.AvoidanceParamCoder`。
|
||
- 关键事实:`CarLength/CarWidth/CarCenterX/CarCenterY` 均已在 `BasicSiteFields` 定义(中心点默认 0),故 4 参模板对各车型都可解析编译;差异只剩「触发条件 + 参数个数」。
|
||
- 选项(已在会话中给用户):**A**=真·单 coder 分支(flag→4 参 / 否则 L,W 有效→2 参;副作用:Kiva 未配置站点不再发 `(-1,-1)` + MWL 设了 L,W 但 flag=false 会新发 2 参);**B**=两 coder(4 参 flag 版+2 参 L,W 版;仅 Kiva `(-1,-1)` 行为差,无 MWL 污染);**C**=只留已合并的同构对,Kiva/Forklift 维持内联(零变更)。**建议 B**(避障涉安全,最小行为差)。
|
||
3. ~~**去 WinForms 迁移策略**~~ **【会话1 暂定】**:用户"暂不/去掉",本阶段不动窗体,留待 C1 专门处理。
|
||
4. ~~**内核 coder 运行期注册表**~~ **【会话1 已核查】**:当前内核**无插件化 coder 注册表**。`SegmentPlan.SetCoders()` 仅硬接 `TemplateCoderSet`+`ProgramCoderSet` 两套,均按**车型类特性**(`[*TrackCoderSettings]`)反射、在**同程序集**内 `Activator.CreateInstance`(无参构造)实例化——无外部 dll 扫描/动态注册 API。
|
||
- 推论①:本次抽出的 `StandardScene.Coders.*` 程序 coder **能被正确加载**(车型特性 `typeof()` 引用 + 无参构造,命名空间无关),故 C0-b/c/d 成立。
|
||
- 推论②:**C2「导航 coder 拆独立可热插拔 dll」受阻**——需内核侧(另一会话)补「运行期 coder 注册 / 插件程序集扫描」插桩;在此之前**继续兜底=coder 留在 Core 同程序集**、由车型特性引用。
|
||
5. ~~**设备驱动外移后运行期发现**~~ **【会话1续2 已解】**:StandardScene 自有的设备类型发现原为 **Core 限定扫描**(与内核 `UiTypeDiscovery` 全域发现不一致),直接外移会断。已把 5 处统一改 `UiTypeDiscovery.AllTypes()`(行为等价、跨程序集)。**遗留验证项(运行期,归 C5)**:卫星 dll 须被 SimpleLite 实际加载入 AppDomain(`PluginManager` 从 `./plugins/` 加载)发现方生效——需将 `StandardScene.Devices.*.dll`+`scene.json` 部署到宿主 `plugins/` 并做一次真机/集成联调。与 coder(§11.4-4) 不同:设备发现码在**本仓库**、可自主修改,故 C3 不受内核阻塞。
|
||
|
||
### 11.5 下一会话推荐起手式
|
||
1. 读 §11.0(代码现状)+ §11.3(已落地,含 **E. 结构拆分**)+ §11.4(待确认/已解)。
|
||
2. **结构拆分现状**:`StandardScene.Core` + 卫星 `Protocol.VDA5050`、`Devices.{Door,Charge,ButtonBox}` 已建并全解 0 错;导航 dll(C2) 待用户重构 coder + 内核注册表后再动。
|
||
3. 待用户就 §11.4-2 拍板:`ChangeAvoidanceParam` 收尾(建议 B)。coder 整体重构由用户主导。
|
||
4. C5 验证项:把 `StandardScene.Devices.*.dll`+`scene.json` 部署到宿主 `plugins/`,真机/集成验证设备与 VDA 车型的**运行期发现**(§11.4-5)。
|
||
5. 校验手段:每步 `dotnet build StandardScene.sln`(net8.0-windows)须保持 0 错误;真机回归留待有环境时。
|
||
|
||
### 11.6 变更日志
|
||
|
||
| 时间 | 步骤 | 改动 | 备注 |
|
||
|---|---|---|---|
|
||
| 初始 | P0 | 新增 `StandardScene拆分计划.md`(v1) | 现状精读 + 归属矩阵 + 抽离清单 + 技术难点 + 分阶段 |
|
||
| v2 | P0.1 | 全文更新 | 宿主 SimpleLite、框架 net8.0、去 WinForms、设备独立 dll、删除项、WebApi 暂留+迁移索引 |
|
||
| 会话1 | C0-a | 物理删除 4 个死代码文件 + 清理 csproj | 编译 0 错误 |
|
||
| 会话1 | C0-b | 新增 `Coders/CommonTrackCoders.cs`(4 通用 coder);Kiva/MWL/MultiVehicle/Forklift 切换为 ProgramTrackCoder 引用 | 编译 0 错误;NaiveMag/AvoidanceParam 留待确认 |
|
||
| 会话1续 | C0-c | 磁循迹器去重:`AllCarMagTrackCoder`→唯一 `MagneticTrackCoder`(含 `track.Speed`);删 `MagTrackCoder` 改向引用 | 用户确认 track.Speed 版;编译 0 错误 |
|
||
| 会话1续 | C0-d | 避障同构对去重:`MWL`+`MultiVehicle` 4 参模板→`AvoidanceParamCoder`;基类加 `SiteFieldsType` 钩子 | 零行为变更;Kiva/Forklift 并法待定(§11.4-2) |
|
||
| 会话1续 | 核查 | 内核 coder 注册机制核查:无插件注册表,仅车型特性+同程序集反射 | 见 §11.4-4;C2 需内核插桩 |
|
||
| 会话1续2 | 路线乙·1 | 工程迁入 `StandardScene.Core/`、`.csproj`→`StandardScene.Core.csproj`、重写 `.sln`、加 `Properties/InternalsVisibleTo.cs`(4 卫星) | 纯搬运;编译 0 错 |
|
||
| 会话1续2 | C4 | 拆 `Protocol.VDA5050`:`CarTypes/VDACar/`(10 文件)整迁出;`VDA5050SiteField` 下沉 `ArmCar.cs` 解耦;scene.json | 编译 0 错 |
|
||
| 会话1续2 | C3 | 拆 `Devices.{Door,Charge,ButtonBox}`:6 驱动外移;2 处 `is 具体类`→基类虚方法;5 处类型发现→`UiTypeDiscovery.AllTypes()` 跨程序集 | 行为等价;全解编译 0 错、3 dll+scene.json 产出 |
|
||
| 会话1续3 | C3 | 三 `Devices.*` **合并为单一 `StandardScene.Devices`**(内部 Door/Charge/ButtonBox 子目录;IVT 3→1;删旧 3 工程、重写 sln) | 用户定"不分多个";编译 0 错、单 dll+scene.json 产出 |
|
||
| 会话1续3 | C0-d | `ChangeAvoidanceParam` 去重收尾(方案 B):新增 2 参 `AvoidanceParamLWCoder`;Kiva/Forklift 内联模板→`[ProgramTrackCoderSettings(priority=20)]` 引用 | 编译 0 错;Forklift 不变、Kiva `(-1,-1)` 安全收敛 |
|
||
|
||
---
|
||
|
||
*附:本计划引用的类/文件/行号均来自当前工程 `E:\Work\Core\Simple-FR\StandardSence` 实际代码走查;SimpleLite 接口依据 `E:\Work\Core\Simple-FR\Simple\SimpleLite\Docs\MIGU-API.md` 与 `SimpleLite.csproj`(net8.0 / CycleGUI / EmbedIO)。*
|