51 KiB
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 规范化 |
关键机制结论与配套改动:
- 车型按平台归位(推翻 v2 "车型留基座"):依据 = 项目存档按短类名(
JSONLoader用type.Name.ToLower())匹配车型,类迁 dll 不破坏旧存档;coder 特性GetCustomAttributes(inherit:true)沿继承链收集,内核GhostCar的 BasicGo 天然被所有车型继承。 - 共享字段袋下沉基座:
KivaFields.cs/MultiWheelLifterFields.cs(ArmCar、MultiVehicleCar 跨平台继承它们);IScriptErrorRecoverable接口解耦AbstractLoopMission对 Kiva 的反向依赖。 - 清单命名修正:内核只识别
<dll>.scene.json,原裸scene.json永远不会被扫描到——已全部改名并规范 id。 - 内核配套(Simple 仓库):①
Startup.LoadPlugins两阶段加载——清单requiresCore声明的基座(StandardScene.dll)自动并入 alwaysLoad 且 non-collectible 先行加载(否则衍生插件的 collectible ALC 解析不到基座,运行期必炸);②SceneManifest.navKinds多导航声明 +INavigationProfile.Kinds(qrlidar 同时覆盖 Laser+QrCode,FindByKind按集合匹配);③ShouldLoad规则改为「有清单(含设备/协议)即参与激活判定,无清单兼容全加载」,scene.device 因此可被选择性加载。 - 平台配套(Migu2.0):
DeploymentProfile.NavKindToSceneId改映射 magnetic→scene.mag、qrcode/laser→scene.qrlidar;向导写 active-scenes.json 时固定并入 scene.device。
v2 评审反馈要点(本次更新依据)
- 宿主切换:StandardScene 改为依赖
SimpleLite(net8.0),老SimpleComposer.exe(net4.8)废弃。内核引用层(命名空间SimpleComposer.RCS→SimpleLite.RCS等)正由另一个 AI 会话同步改造,本文按新宿主表述。 - 目标框架统一
net8.0(与 SimpleLite 一致;非 net8.0-windows)。SimpleLite UI 采用 CycleGUI、WebApi 采用 EmbedIO,故 StandardScene 需去除 WinForms 依赖,窗体迁移到 CycleGUI 或平台 Web。 - 设备驱动必须独立 dll,且支持热卸载/加载(配合 SimpleLite
/pluginsreload/unload + collectible ALC)。 FactoryTest与松灵残留:直接删除,不纳入 Core,也不纳入 Customer。WebApi.cs是面向老平台的 Nancy 接口:本次整理后暂留 Core,后期废弃,能力迁移到 SimpleLite 接口(见E:\Work\Core\Simple-FR\Simple\SimpleLite\Docs\MIGU-API.md)。此版本先保留。
0. TL;DR(结论先行)
- 导航方式与车型是正交的两个维度。导航(磁 / 二维码 / 激光)由轨道/站点字段 + TrackCoder决定,不是车型固有属性;同一车型(如
Kiva)的类上同时挂磁、二维码、激光避障三类 coder。上游"按车型整包切到某导航 dll"切不干净,修正为「车型留基座 + 导航能力抽离为可插拔 coder」。 - 激光"避障"(LidarArea) ≠ 激光"导航定位"(LidarMap/SLAM):避障通用留 Core,仅 SLAM 地图进 Laser。
WebApi.cs(123KB) 是老平台 Nancy 接口,导航耦合极弱(仅二维码QrMap、激光getLidarMap)。整理后暂留 Core,标记 deprecated,后期迁 SimpleLite EmbedIO 接口(§4.7 给出端点映射)。- 存在大量重复代码可借本次"抽离标准功能"沉淀:磁导航循迹器写了两份、
newReset/newTrafficReset在 3 个车型复制、SetDisplayInfo/GetCarStatus/Mstsc/EmergencyStop雷同。 - 三个正交维度:①导航(磁/二维码/激光) ②车型(顶升/叉车/Kiva/机械臂…) ③设备驱动(充电桩/门/按钮盒)。设备驱动独立成可热插拔 dll。
- VDA5050 是自成一体的 MQTT 协议栈,独立 dll。
- 两大技术主线:① 把 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:23TagValue //磁导航,二维码值,或者rfid 值(站点字段)。- 磁:
Kiva.cs:37、CarTypes/MultiWheelLifterCar.cs:34track.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:4321SLAM 栅格) +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 分层依赖图
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. "抽离标准功能"清单(去重与沉淀)
- 统一磁导航循迹器:
AllCarMagTrackCoder+MagTrackCoder→ 唯一StandardScene.Magnetic.MagneticTrackCoder(参数化 fields)。 - 车型基类
StandardCarBase(Core):上提newReset/newTrafficReset、SetDisplayInfo、Mstsc、EmergencyStop/Release、ResetClumsy、GetCarStatus默认实现。 - 通用 Coder 模板集(Core/Coders):沉淀避障/IO/纠偏/避障尺寸等重复
[TemplateTrackCoderSettings]。 - 导航能力抽象
INavigationProfile:每个导航 dll 实现一个 Profile(声明NavKind+ 提供的 coder/字段语义),Core/宿主反射收集。 Commons去重:合并GetCarStatus;GetVehicleStatus去除对DummyCar的硬编码(改标记接口)。- 设备注册标准化:充电桩/门/按钮盒统一特性注册,驱动 dll 即插即用 + 热插拔。
- 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随驱动。- 验证
/pluginsreload/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)
{
"id": "scene.magnetic",
"displayName": "磁导航场景",
"navKind": "Magnetic",
"assembly": "StandardScene.Magnetic.dll",
"requiresCore": "StandardScene.Core.dll",
"provides": { "trackCoders": ["MagneticTrackCoder"], "carTypeBindings": ["*"] }
}
- 平台「配置向导」→
WizardController写配置 → 调 SimpleLitePOST /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。
待确认
- coder 注册表:内核是否纳入"运行期把 TrackCoder 注册到车型"的 API(否则 C2 用兜底方案③)。
- UI 迁移范围与节奏:窗体一次性迁 CycleGUI,还是按 dll 分批;是否部分仅保留平台 Web 入口。
- VDA5050 独立 dll 确认(推荐独立)。
- 二维码地图下发 / 激光 SLAM 取图:SimpleLite 侧补接口的归属与时间点。
- 车型↔导航映射:是否存在车型仅支持单一导航的硬约束。
验收口径(每阶段通用)
- 编译 0 错误;搬运/环线/充电/交管不回归。
- 选择性加载 + 热插拔:激活集合内能力可用,未激活不加载、可干净卸载。
- 反射 API(SimpleLite
/reflection)、车型/面板随已激活 dll 自然收敛。
11. 实施进度记忆(跨会话持续更新)
状态:⬜ 未开始 / 🟦 进行中 / ✅ 完成 / ⏸ 暂缓。 最近更新:会话1(续3,2026-06-09)——设备三 dll 合并为单一
StandardScene.Devices+ChangeAvoidanceParam去重(方案 B),全解dotnet build0 错误。
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下沉至 CoreCarTypes/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)
- Door:
- 行为保持解耦(2 处下转型→基类虚方法):
ChargeUdpService:if(cs is PCBChargeStation s) s.IndexReceive=msg[1]→cs.OnUdpMessage(msg)(AbstractChargeStation空实现、PCBoverride)。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参数差异${track.Speed}的版本(Kiva 版)。已合并为唯一MagneticTrackCoder;MultiWheelLifterCar.MagTrackCoder删除并改向引用。编译 0 错误。(普通MagGo两份原本一致;合并后磁逻辑全平台统一。)【会话1续3 已决:方案 B】:用户选 B。落地=4 参 flag 版ChangeAvoidanceParam统一方式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+MultiVehicle4 参对合并为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(避障涉安全,最小行为差)。
- 现状:
去 WinForms 迁移策略【会话1 暂定】:用户"暂不/去掉",本阶段不动窗体,留待 C1 专门处理。内核 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 同程序集、由车型特性引用。
- 推论①:本次抽出的
设备驱动外移后运行期发现【会话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 下一会话推荐起手式
- 读 §11.0(代码现状)+ §11.3(已落地,含 E. 结构拆分)+ §11.4(待确认/已解)。
- 结构拆分现状:
StandardScene.Core+ 卫星Protocol.VDA5050、Devices.{Door,Charge,ButtonBox}已建并全解 0 错;导航 dll(C2) 待用户重构 coder + 内核注册表后再动。 - 待用户就 §11.4-2 拍板:
ChangeAvoidanceParam收尾(建议 B)。coder 整体重构由用户主导。 - C5 验证项:把
StandardScene.Devices.*.dll+scene.json部署到宿主plugins/,真机/集成验证设备与 VDA 车型的运行期发现(§11.4-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)。