- 更新 DEVICE_PLUGIN_DESIGN.md: 阶段二标记完成+验收项勾选+成果章节 - 新建 src/plugins/device/README.md: 完整DevicePlugin文档 - 新建 docs/SCREEN_PLUGIN_MIGRATION_SUMMARY.md: 迁移总结 - 更新 li-siqi soul + TEAM_CHAT 汇报 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
6.7 KiB
6.7 KiB
DevicePlugin — 统一设备管理插件
概述
DevicePlugin 是 ShowenV2 的统一硬件访问层,负责管理所有设备相关的操作。通过抽象的 DeviceBackend trait,支持多平台适配(Linux ARM64、Android、Embedded 等)。
架构
业务插件 (Video/Screen/BLE/HTTP/...)
↓ 发送 DeviceCommand
DevicePlugin
↓ 分发给 Backend
DeviceBackend (Linux/Android/Embedded)
↓ 硬件访问
硬件层 (Framebuffer/DRM/GPIO/I2C/SPI/...)
支持的能力
DevicePlugin 通过 DeviceCapability enum 声明支持的硬件能力:
- Display: 显示信息查询(分辨率、像素格式)
- Backlight: 背光控制(开关、亮度)
- SleepInhibit: 防息屏(通过 systemd-inhibit)
- Cursor: 光标控制(显示/隐藏,通过 unclutter)
- Framebuffer: 帧缓冲写入(待实现)
- Touch: 触摸输入(待实现)
- Buttons: 按钮输入(待实现)
- Audio: 音频播放(待实现)
- Battery: 电池状态(待实现)
- Sensors: 传感器数据(待实现)
- GPIO: GPIO 控制(待实现)
消息接口
DeviceCommand (业务插件 → DevicePlugin)
pub enum DeviceCommand {
// 显示
GetDisplayInfo,
SetBrightness(u8),
SetBacklight(bool),
WriteFramebuffer { data: Vec<u8>, format: PixelFormat },
// 输入
GetTouchEvents,
GetButtonState,
GetSensorData(SensorType),
// 音频
PlayAudio { path: String },
SetVolume(u8),
// 电源
GetBatteryLevel,
SetSleepInhibit(bool),
// 光标
SetCursorVisible(bool),
// 通用
CustomCommand { subsystem: String, payload: serde_json::Value },
}
DeviceResponse (DevicePlugin → 请求者)
pub enum DeviceResponse {
DisplayInfo { width: u32, height: u32, format: PixelFormat },
SensorData { sensor: SensorType, value: f64 },
BatteryLevel(u8),
Ok,
Error(String),
Custom(serde_json::Value),
}
DeviceEvent (DevicePlugin → 广播)
pub enum DeviceEvent {
TouchEvent { x: i32, y: i32, action: TouchAction },
ButtonEvent { button: u8, pressed: bool },
BatteryLow(u8),
DisplayConnected,
DisplayDisconnected,
SensorAlert { sensor: SensorType, value: f64 },
}
使用示例
查询显示信息
let envelope = Envelope {
from: "my_plugin".to_string(),
to: Destination::Plugin("device".to_string()),
message: Message::DeviceCommand(DeviceCommand::GetDisplayInfo),
};
ctx.tx.send(envelope)?;
// 接收响应
match message {
Message::DeviceResponse(DeviceResponse::DisplayInfo { width, height, format }) => {
println!("Display: {}x{} {:?}", width, height, format);
}
_ => {}
}
防息屏
// 启用防息屏
let envelope = Envelope {
from: "my_plugin".to_string(),
to: Destination::Plugin("device".to_string()),
message: Message::DeviceCommand(DeviceCommand::SetSleepInhibit(true)),
};
ctx.tx.send(envelope)?;
// 禁用防息屏
let envelope = Envelope {
from: "my_plugin".to_string(),
to: Destination::Plugin("device".to_string()),
message: Message::DeviceCommand(DeviceCommand::SetSleepInhibit(false)),
};
ctx.tx.send(envelope)?;
光标控制
// 隐藏光标
let envelope = Envelope {
from: "my_plugin".to_string(),
to: Destination::Plugin("device".to_string()),
message: Message::DeviceCommand(DeviceCommand::SetCursorVisible(false)),
};
ctx.tx.send(envelope)?;
// 显示光标
let envelope = Envelope {
from: "my_plugin".to_string(),
to: Destination::Plugin("device".to_string()),
message: Message::DeviceCommand(DeviceCommand::SetCursorVisible(true)),
};
ctx.tx.send(envelope)?;
与 ScreenPlugin 的关系
历史背景
在 DevicePlugin 引入之前,ScreenPlugin 直接调用 systemd-inhibit 和 unclutter 命令来实现防息屏和光标隐藏功能。这导致:
- 平台耦合: ScreenPlugin 包含大量 Linux 特定代码
- 重复实现: 多个插件可能需要类似的硬件访问逻辑
- 难以扩展: 添加新平台需要修改多个插件
迁移方案 (2026-03-13)
阶段二完成了 ScreenPlugin 到 DevicePlugin 的功能迁移:
-
DevicePlugin 扩展:
- 添加
SetCursorVisible(bool)命令 - LinuxArm64Backend 实现光标控制(通过 unclutter)
- 添加
DeviceCapability::Cursor能力
- 添加
-
ScreenPlugin 重构:
- 改为 DevicePlugin 的 thin wrapper
- 移除直接硬件操作代码
- 通过
DeviceCommand消息实现所有功能 - 保持向后兼容的消息接口
-
架构改进:
- 统一设备管理: 所有硬件访问通过 DevicePlugin
- 平台解耦: ScreenPlugin 不再包含平台特定代码
- 消息驱动: 插件间通过消息通信,松耦合
当前状态
- ScreenPlugin 保留作为兼容层,处理
Message::ScreenLockRequest和Message::CursorVisibility - 实际硬件操作由 DevicePlugin 的 LinuxArm64Backend 执行
- 未来可能完全移除 ScreenPlugin,业务插件直接使用 DeviceCommand
平台支持
Linux ARM64 (当前实现)
- Display: 通过 DRM/KMS 查询显示信息
- Backlight: 通过
/sys/class/backlight控制背光 - SleepInhibit: 通过
systemd-inhibit防止系统休眠 - Cursor: 通过
unclutter隐藏光标
Android (待实现)
- Display: 通过 Android API 查询
- Backlight: 通过 Settings API 控制
- SleepInhibit: 通过 WakeLock
- Cursor: N/A (触摸设备无光标)
Embedded (待实现)
- Display: 直接访问 framebuffer
- Backlight: GPIO 控制
- SleepInhibit: 自定义电源管理
- Cursor: N/A (无操作系统)
测试
DevicePlugin 包含完整的单元测试和集成测试:
# 运行所有测试
cargo test --package showen --lib plugins::device
# 运行特定测试
cargo test --package showen --lib plugins::device::tests::test_set_cursor_visible
测试覆盖:
- 消息序列化/反序列化(DeviceCommand/DeviceResponse/DeviceEvent)
- MockBackend 功能验证
- LinuxArm64Backend 能力声明
- ScreenPlugin ↔ DevicePlugin 消息流
开发指南
添加新的设备能力
- 在
DeviceCommand中添加新命令 - 在
DeviceCapability中添加新能力 - 在
LinuxArm64Backend::handle_command中实现命令处理 - 在
LinuxArm64Backend::capabilities中声明能力 - 添加单元测试验证功能
添加新的平台后端
- 创建
src/plugins/device/<platform>.rs - 实现
DeviceBackendtrait - 在
src/plugins/device/mod.rs中注册后端 - 添加平台特定的测试