forked from wathiede/i3xs
108 lines
3.4 KiB
Rust
108 lines
3.4 KiB
Rust
//! ::::::::::::::
|
|
//! /sys/class/power_supply/hidpp_battery_8/uevent
|
|
//! ::::::::::::::
|
|
//! POWER_SUPPLY_NAME=hidpp_battery_8
|
|
//! POWER_SUPPLY_TYPE=Battery
|
|
//! POWER_SUPPLY_ONLINE=1
|
|
//! POWER_SUPPLY_STATUS=Discharging
|
|
//! POWER_SUPPLY_SCOPE=Device
|
|
//! POWER_SUPPLY_MODEL_NAME=M570
|
|
//! POWER_SUPPLY_MANUFACTURER=Logitech
|
|
//! POWER_SUPPLY_SERIAL_NUMBER=1028-26-d9-b5-38
|
|
//! POWER_SUPPLY_CAPACITY=65
|
|
use std::collections::HashMap;
|
|
|
|
use glob::glob;
|
|
use i3monkit::{Block, Widget, WidgetUpdate};
|
|
use thiserror::Error;
|
|
|
|
#[derive(Debug, Default)]
|
|
pub struct PowerSupply {}
|
|
|
|
const POWER_SUPPLY_GLOB: &'static str = "/sys/class/power_supply/*/uevent";
|
|
|
|
#[derive(Error, Debug)]
|
|
enum PowerSupplyError {
|
|
#[error("IO error {0}")]
|
|
IoError(#[from] std::io::Error),
|
|
#[error("glob error {0}")]
|
|
GlobError(#[from] glob::GlobError),
|
|
#[error("pattern error {0}")]
|
|
PatternError(#[from] glob::PatternError),
|
|
#[error("UTF-8 error {0}")]
|
|
Utf8Error(#[from] std::str::Utf8Error),
|
|
#[error("parse number error {0}")]
|
|
ParseIntErro(#[from] std::num::ParseIntError),
|
|
#[error("parse error {0}")]
|
|
ParseError(String),
|
|
}
|
|
|
|
impl PowerSupply {
|
|
fn get_update(&mut self) -> Result<Vec<String>, PowerSupplyError> {
|
|
const BATT_100: &'static str = "";
|
|
const BATT_75: &'static str = "";
|
|
const BATT_50: &'static str = "";
|
|
const BATT_25: &'static str = "";
|
|
const BATT_0: &'static str = "";
|
|
|
|
let mut res = Vec::new();
|
|
for ps in glob(POWER_SUPPLY_GLOB)? {
|
|
let bytes = std::fs::read(&ps?)?;
|
|
let values: HashMap<&str, &str> = std::str::from_utf8(&bytes)?
|
|
.lines()
|
|
.map(|l| {
|
|
l.split_once('=').ok_or(PowerSupplyError::ParseError(
|
|
"missing = in uevent line".to_string(),
|
|
))
|
|
})
|
|
.collect::<Result<_, _>>()?;
|
|
let cap: u32 = values
|
|
.get("POWER_SUPPLY_CAPACITY")
|
|
.unwrap_or(&"0")
|
|
.parse()?;
|
|
let power = if cap >= 90 {
|
|
BATT_100
|
|
} else if cap >= 70 {
|
|
BATT_75
|
|
} else if cap >= 40 {
|
|
BATT_50
|
|
} else if cap >= 20 {
|
|
BATT_25
|
|
} else {
|
|
BATT_0
|
|
};
|
|
res.push(format!(
|
|
"{} {}: <span face=\"pango:Font Awesome 5 Free\">{}</span>",
|
|
values
|
|
.get("POWER_SUPPLY_MANUFACTURER")
|
|
.unwrap_or(&"Unknown mfg"),
|
|
values
|
|
.get("POWER_SUPPLY_MODEL_NAME")
|
|
.unwrap_or(&"Unknown model"),
|
|
power,
|
|
));
|
|
}
|
|
Ok(res)
|
|
}
|
|
}
|
|
|
|
impl Widget for PowerSupply {
|
|
fn update(&mut self) -> Option<WidgetUpdate> {
|
|
match self.get_update() {
|
|
Ok(statuses) => {
|
|
let mut data = Block::new();
|
|
data.use_pango();
|
|
for status in statuses {
|
|
data.append_full_text(&status);
|
|
}
|
|
return Some(WidgetUpdate {
|
|
refresh_interval: std::time::Duration::new(1, 0),
|
|
data: Some(data),
|
|
});
|
|
}
|
|
Err(err) => eprintln!("Failed to update: {}", err),
|
|
}
|
|
None
|
|
}
|
|
}
|