This commit is contained in:
2021-12-12 09:51:59 -08:00
parent 3f92e9dc10
commit 62b53199b1
6 changed files with 306 additions and 165 deletions

View File

@@ -7,6 +7,7 @@ use structopt::StructOpt;
use i3xs::widgets::cpu::CpuWidget;
use i3xs::widgets::datetime::{DateTimeWidget, TimeColor};
use i3xs::widgets::network::NetworkSpeedWidget;
use i3xs::widgets::power::PowerSupply;
#[derive(Debug, StructOpt)]
#[structopt(name = "i3xs", about = "Custom i3 status bar program.")]
@@ -20,6 +21,7 @@ fn main() {
let opts = Opt::from_args();
bar.push(PowerSupply::default());
bar.push(CpuWidget::new());
// Realtime upload/download rate for a interface

View File

@@ -7,6 +7,7 @@ use structopt::StructOpt;
use i3xs::widgets::cpu::CpuWidget;
use i3xs::widgets::datetime::{DateTimeWidget, TimeColor};
use i3xs::widgets::network::NetworkSpeedWidget;
use i3xs::widgets::power::PowerSupply;
#[derive(Debug, StructOpt)]
#[structopt(name = "i3xs", about = "Custom i3 status bar program.")]
@@ -20,6 +21,7 @@ fn main() {
let opts = Opt::from_args();
bar.push(PowerSupply::default());
bar.push(CpuWidget::new());
// Realtime upload/download rate for a interface

View File

@@ -1,3 +1,4 @@
pub mod cpu;
pub mod datetime;
pub mod network;
pub mod power;

107
src/widgets/power.rs Normal file
View File

@@ -0,0 +1,107 @@
//! ::::::::::::::
//! /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 = "&#xf240;";
const BATT_75: &'static str = "&#xf241;";
const BATT_50: &'static str = "&#xf242;";
const BATT_25: &'static str = "&#xf243;";
const BATT_0: &'static str = "&#xf244;";
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
}
}