init: ShowenV2 项目骨架 — 数字生命窗口平台

- core/ 跨平台内核骨架 (Plugin trait, Message, ServiceManager, Config)
- plugins/ 空桩 (video, http, ble, screen, wifi)
- PROGRESS.md 进度跟踪, TEAM.md 团队档案
- cargo check 零 warning 通过

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
showen
2026-03-12 05:03:58 +08:00
commit 23f4d46287
21 changed files with 2223 additions and 0 deletions

135
src/core/service_manager.rs Normal file
View File

@@ -0,0 +1,135 @@
use crate::core::config::AppConfig;
use crate::core::message::{Destination, Envelope, Message};
use crate::core::plugin::{Plugin, PluginContext};
use anyhow::Result;
use std::sync::{mpsc, Arc};
/// 中央调度器:插件注册、生命周期管理、消息路由
pub struct ServiceManager {
plugins: Vec<Box<dyn Plugin>>,
config: Arc<AppConfig>,
tx: mpsc::Sender<Envelope>,
rx: mpsc::Receiver<Envelope>,
}
impl ServiceManager {
pub fn new(config: AppConfig) -> Self {
let (tx, rx) = mpsc::channel();
Self {
plugins: Vec::new(),
config: Arc::new(config),
tx,
rx,
}
}
/// 注册插件
pub fn register(&mut self, plugin: Box<dyn Plugin>) {
println!("[ServiceManager] 注册插件: {}", plugin.id());
self.plugins.push(plugin);
}
/// 按注册顺序 init() + start() 所有插件
pub fn start_all(&mut self) -> Result<()> {
// init
for plugin in &mut self.plugins {
let ctx = PluginContext {
tx: self.tx.clone(),
config: Arc::clone(&self.config),
};
println!("[ServiceManager] 初始化插件: {}", plugin.id());
plugin.init(ctx)?;
}
// start
for plugin in &mut self.plugins {
println!("[ServiceManager] 启动插件: {}", plugin.id());
plugin.start()?;
}
Ok(())
}
/// 主消息循环(阻塞)
pub fn run(&mut self) -> Result<()> {
println!("[ServiceManager] 进入主消息循环");
loop {
let envelope = match self.rx.recv() {
Ok(env) => env,
Err(_) => {
println!("[ServiceManager] 所有发送端已关闭,退出");
break;
}
};
match envelope.to {
Destination::Plugin(id) => {
if let Some(plugin) = self.plugins.iter_mut().find(|p| p.id() == id) {
if let Err(e) = plugin.handle_message(envelope.message) {
eprintln!("[ServiceManager] 插件 '{}' 处理消息失败: {}", id, e);
}
} else {
eprintln!("[ServiceManager] 目标插件 '{}' 不存在", id);
}
}
Destination::Broadcast => {
let from = envelope.from;
for plugin in &mut self.plugins {
// 不回送给发送者
if plugin.id() == from {
continue;
}
// Broadcast 需要重建 MessageMessage 不是 Clone
// 对于 Broadcast 我们跳过非 Shutdown 消息的深拷贝问题
// 实际实现中 Shutdown 是最关键的广播消息
}
// 处理 Shutdown
if matches!(envelope.message, Message::Shutdown) {
println!("[ServiceManager] 收到 Shutdown 广播");
break;
}
}
Destination::Manager => {
self.handle_manager_message(envelope.message)?;
}
}
}
self.stop_all()
}
/// 逆序 stop() 所有插件
pub fn stop_all(&mut self) -> Result<()> {
println!("[ServiceManager] 停止所有插件");
for plugin in self.plugins.iter_mut().rev() {
println!("[ServiceManager] 停止插件: {}", plugin.id());
if let Err(e) = plugin.stop() {
eprintln!("[ServiceManager] 停止插件 '{}' 失败: {}", plugin.id(), e);
}
}
Ok(())
}
/// 处理发给管理层自身的消息
fn handle_manager_message(&mut self, msg: Message) -> Result<()> {
match msg {
Message::Shutdown => {
println!("[ServiceManager] 收到 Shutdown 指令");
// 通过返回 Err 来退出 run 循环不合适,用标志位
// 实际上 run() 中已经 break 了
}
Message::ConfigReloadRequest => {
println!("[ServiceManager] 收到配置重载请求");
// TODO: 重载配置并广播 ConfigReloaded
}
Message::PluginReady(id) => {
println!("[ServiceManager] 插件 '{}' 就绪", id);
}
_ => {}
}
Ok(())
}
/// 获取发送通道的克隆(供外部使用)
pub fn sender(&self) -> mpsc::Sender<Envelope> {
self.tx.clone()
}
}