# ShowenV2 插件依赖模型 ## 插件分类 ### 独立插件(Independent Plugins) **定义**: 只依赖 core,不依赖其他插件,可以独立运行 **特点**: - 自包含,功能完整 - 只通过 core 的消息机制与其他插件通信 - 可以单独测试和部署 - 启动顺序无要求 **示例**: - screen - 屏幕管理(唤醒锁、光标控制) - wifi - WiFi 管理(扫描、连接、热点) ### 依赖插件(Dependent Plugins) **定义**: 依赖其他插件的功能,需要特定插件先启动 **特点**: - 功能依赖其他插件 - 需要声明依赖关系 - 启动顺序有要求 - 通过消息机制与依赖插件通信 **示例**: - ble - 依赖 wifi(通过 BLE 配置 WiFi) - http - 依赖 video(通过 HTTP API 控制视频播放) --- ## 依赖关系图 ``` 独立插件层: ┌─────────┐ ┌─────────┐ ┌─────────┐ │ screen │ │ wifi │ │ video │ └─────────┘ └─────────┘ └─────────┘ ↑ ↑ ↑ │ │ │ └────────────┴────────────┘ core 依赖插件层: ┌─────────┐ ┌─────────┐ │ ble │ │ http │ │ (依赖 │ │ (依赖 │ │ wifi) │ │ video) │ └─────────┘ └─────────┘ ↑ ↑ │ │ └────────────┘ core ``` --- ## 插件依赖声明 ### Plugin Trait 扩展 ```rust pub trait Plugin: Send { fn info(&self) -> PluginInfo; // 新增:声明依赖的插件 fn dependencies(&self) -> Vec<&'static str> { vec![] // 默认无依赖 } fn init(&mut self, ctx: PluginContext) -> Result<()>; fn start(&mut self) -> Result<()>; fn handle_message(&mut self, msg: Message) -> Result<()>; fn stop(&mut self) -> Result<()>; } ``` ### 依赖声明示例 ```rust impl Plugin for BlePlugin { fn dependencies(&self) -> Vec<&'static str> { vec!["wifi"] // BLE 依赖 WiFi 插件 } } impl Plugin for HttpPlugin { fn dependencies(&self) -> Vec<&'static str> { vec!["video"] // HTTP 依赖 Video 插件 } } impl Plugin for WifiPlugin { fn dependencies(&self) -> Vec<&'static str> { vec![] // WiFi 是独立插件 } } ``` --- ## 启动顺序管理 ### ServiceManager 职责 1. **依赖检查**: 启动前检查所有依赖是否满足 2. **拓扑排序**: 根据依赖关系计算启动顺序 3. **顺序启动**: 按照拓扑排序结果依次启动插件 4. **错误处理**: 依赖插件启动失败时,跳过依赖它的插件 ### 启动流程 ``` 1. 注册所有插件 2. 构建依赖图 3. 检查循环依赖(报错) 4. 拓扑排序 5. 按顺序 init() 所有插件 6. 按顺序 start() 所有插件 ``` ### 示例启动顺序 ``` Phase 1: 独立插件 - screen.init() → screen.start() - wifi.init() → wifi.start() - video.init() → video.start() Phase 2: 依赖插件 - ble.init() → ble.start() (依赖 wifi) - http.init() → http.start() (依赖 video) ``` --- ## 消息通信模式 ### 独立插件 - 接收 Broadcast 消息 - 发送消息给 core - 不直接与其他插件通信 ### 依赖插件 - 接收 Broadcast 消息 - 发送消息给特定插件(通过 core 路由) - 等待依赖插件的响应消息 ### 消息路由示例 ```rust // BLE 请求 WiFi 扫描 ble_plugin.send(Message::WifiCommand(WifiCommand::Scan)); // WiFi 返回扫描结果(Broadcast) wifi_plugin.send(Message::WifiResult(result)); // BLE 接收到 WifiResult 消息 ble_plugin.handle_message(Message::WifiResult(result)); ``` --- ## 当前插件分类 ### 独立插件 | 插件 | 功能 | 依赖 | 状态 | |------|------|------|------| | screen | 屏幕管理 | core | ✅ 完成 | | wifi | WiFi 管理 | core | ✅ 完成 | | video | 视频播放 | core | ✅ 完成 | ### 依赖插件 | 插件 | 功能 | 依赖 | 状态 | |------|------|------|------| | ble | 蓝牙配网 | core + wifi | ✅ 完成 | | http | HTTP API | core + video | ✅ 完成 | --- ## 未来插件规划 ### Phase 2 独立插件 - render - 3D 渲染引擎(独立) - ai_voice - AI 语音识别(独立) - ai_tts - AI 语音合成(独立) ### Phase 2 依赖插件 - vr - VR 输出(依赖 render 或 video) - ar - AR 输出(依赖 render 或 video) - ai_assistant - AI 助手(依赖 ai_voice + ai_tts + video) ### Phase 3 依赖插件 - cloud_sync - 云端同步(依赖 http) - social - 社交分享(依赖 http + cloud_sync) - editor - 内容编辑器(依赖 video + render) --- ## 设计原则 ### 1. 最小依赖原则 - 尽量设计独立插件 - 依赖关系要有明确的业务理由 - 避免过度依赖 ### 2. 单向依赖原则 - 依赖关系必须是单向的 - 禁止循环依赖 - 依赖层级不超过 3层 ### 3. 松耦合原则 - 通过消息通信,不直接调用 - 依赖插件可以缺失(降级运行) - 依赖插件可以替换(接口兼容) ### 4. 可测试原则 - 依赖插件可以 mock - 独立插件可以单独测试 - 依赖插件可以集成测试 --- ## 实现任务 ### 架构团队任务 1. 扩展 Plugin trait,添加 dependencies() 方法 2. 实现 ServiceManager 依赖检查和拓扑排序 3. 编写技术设计文档 ### 开发团队任务 1. 为现有插件添加 dependencies() 实现 2. 测试启动顺序是否正确 3. 验证消息通信是否正常 ### 产品团队任务 1. 梳理 Phase 2/3 插件的依赖关系 2. 确认依赖关系的业务合理性 3. 编写插件依赖的 PRD --- **文档版本**: v1.0 **最后更新**: 2026-03-12 **负责人**: 陈逸飞 (CEO)