# 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)

```rust
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 → 请求者)

```rust
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 → 广播)

```rust
pub enum DeviceEvent {
    TouchEvent { x: i32, y: i32, action: TouchAction },
    ButtonEvent { button: u8, pressed: bool },
    BatteryLow(u8),
    DisplayConnected,
    DisplayDisconnected,
    SensorAlert { sensor: SensorType, value: f64 },
}
```

## 使用示例

### 查询显示信息

```rust
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);
    }
    _ => {}
}
```

### 防息屏

```rust
// 启用防息屏
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)?;
```

### 光标控制

```rust
// 隐藏光标
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` 命令来实现防息屏和光标隐藏功能。这导致：

1. **平台耦合**: ScreenPlugin 包含大量 Linux 特定代码
2. **重复实现**: 多个插件可能需要类似的硬件访问逻辑
3. **难以扩展**: 添加新平台需要修改多个插件

### 迁移方案 (2026-03-13)

**阶段二**完成了 ScreenPlugin 到 DevicePlugin 的功能迁移：

1. **DevicePlugin 扩展**:
   - 添加 `SetCursorVisible(bool)` 命令
   - LinuxArm64Backend 实现光标控制（通过 unclutter）
   - 添加 `DeviceCapability::Cursor` 能力

2. **ScreenPlugin 重构**:
   - 改为 DevicePlugin 的 thin wrapper
   - 移除直接硬件操作代码
   - 通过 `DeviceCommand` 消息实现所有功能
   - 保持向后兼容的消息接口

3. **架构改进**:
   - 统一设备管理: 所有硬件访问通过 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 包含完整的单元测试和集成测试：

```bash
# 运行所有测试
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 消息流

## 开发指南

### 添加新的设备能力

1. 在 `DeviceCommand` 中添加新命令
2. 在 `DeviceCapability` 中添加新能力
3. 在 `LinuxArm64Backend::handle_command` 中实现命令处理
4. 在 `LinuxArm64Backend::capabilities` 中声明能力
5. 添加单元测试验证功能

### 添加新的平台后端

1. 创建 `src/plugins/device/<platform>.rs`
2. 实现 `DeviceBackend` trait
3. 在 `src/plugins/device/mod.rs` 中注册后端
4. 添加平台特定的测试

## 参考文档

- [DevicePlugin 设计文档](../../docs/DEVICE_PLUGIN_DESIGN.md)
- [ScreenPlugin 迁移总结](../../docs/SCREEN_PLUGIN_MIGRATION_SUMMARY.md)
- [集成测试文档](../../docs/DEVICE_PLUGIN_INTEGRATION_TEST.md)
