bread/breadd/src/adapters/power.rs
2026-05-11 11:56:03 +08:00

92 lines
2.5 KiB
Rust

use std::fs;
use std::path::Path;
use anyhow::Result;
use bread_shared::{now_unix_ms, AdapterSource, RawEvent};
use serde_json::json;
use tokio::sync::mpsc;
use tokio::time::{sleep, Duration};
use tracing::debug;
use crate::adapters::Adapter;
#[derive(Clone)]
pub struct PowerAdapter {
poll_interval_secs: u64,
}
impl PowerAdapter {
pub fn new(poll_interval_secs: u64) -> Self {
Self { poll_interval_secs }
}
}
#[async_trait::async_trait]
impl Adapter for PowerAdapter {
fn name(&self) -> &'static str {
"power"
}
async fn run(&self, tx: mpsc::Sender<RawEvent>) -> Result<()> {
debug!("power adapter started");
let mut last = read_power_state();
tx.send(power_raw_event(&last)).await?;
loop {
sleep(Duration::from_secs(self.poll_interval_secs.max(5))).await;
let now = read_power_state();
if now != last {
tx.send(power_raw_event(&now)).await?;
last = now;
}
}
}
}
#[derive(Debug, Clone, PartialEq)]
struct PowerSnapshot {
ac_connected: bool,
battery_percent: Option<u8>,
}
fn power_raw_event(snapshot: &PowerSnapshot) -> RawEvent {
RawEvent {
source: AdapterSource::Power,
kind: "power.snapshot".to_string(),
payload: json!({
"ac_connected": snapshot.ac_connected,
"battery_percent": snapshot.battery_percent,
}),
timestamp: now_unix_ms(),
}
}
fn read_power_state() -> PowerSnapshot {
let power_dir = Path::new("/sys/class/power_supply");
let mut ac_connected = false;
let mut battery_percent = None;
if let Ok(entries) = fs::read_dir(power_dir) {
for entry in entries.flatten() {
let path = entry.path();
let typ = fs::read_to_string(path.join("type")).unwrap_or_default();
if typ.trim().eq_ignore_ascii_case("Mains") || typ.trim().eq_ignore_ascii_case("USB") {
let online = fs::read_to_string(path.join("online")).unwrap_or_default();
if online.trim() == "1" {
ac_connected = true;
}
} else if typ.trim().eq_ignore_ascii_case("Battery") {
let cap = fs::read_to_string(path.join("capacity")).unwrap_or_default();
if let Ok(parsed) = cap.trim().parse::<u8>() {
battery_percent = Some(parsed.min(100));
}
}
}
}
PowerSnapshot {
ac_connected,
battery_percent,
}
}