Files
wldash/src/widgets/battery.rs
T

178 lines
5.4 KiB
Rust
Raw Normal View History

2023-01-11 00:28:54 +01:00
use std::{
2023-02-13 18:49:44 +01:00
error::Error,
2023-01-12 00:13:27 +01:00
sync::{Arc, Mutex},
2023-01-11 00:28:54 +01:00
thread,
2023-02-06 18:34:07 +01:00
time::Duration,
};
use dbus::blocking::{
stdintf::org_freedesktop_dbus::{Properties, PropertiesPropertiesChanged},
LocalConnection,
2023-01-11 23:54:39 +01:00
};
2023-01-11 00:28:54 +01:00
use crate::{
color::Color,
2023-02-06 18:34:07 +01:00
event::{Event, Events},
2023-02-08 22:53:41 +01:00
fonts::FontMap,
2023-01-12 00:13:27 +01:00
widgets::bar_widget::{BarWidget, BarWidgetImpl},
2023-01-11 00:28:54 +01:00
};
2023-02-06 18:34:07 +01:00
enum UpowerBatteryState {
2023-02-08 22:53:41 +01:00
Unknown,
2023-02-06 18:34:07 +01:00
Charging,
Discharging,
Empty,
2023-02-08 22:53:41 +01:00
FullyCharged,
PendingCharge,
PendingDischarge,
}
impl UpowerBatteryState {
fn from_dbus(val: u64) -> UpowerBatteryState {
match val {
1 => UpowerBatteryState::Charging,
2 => UpowerBatteryState::Discharging,
3 => UpowerBatteryState::Empty,
4 => UpowerBatteryState::FullyCharged,
5 => UpowerBatteryState::PendingCharge,
6 => UpowerBatteryState::PendingDischarge,
_ => UpowerBatteryState::Unknown,
}
}
2023-02-06 18:34:07 +01:00
}
2023-01-11 00:28:54 +01:00
struct InnerBattery {
value: f32,
2023-02-06 18:34:07 +01:00
state: UpowerBatteryState,
2023-01-16 00:25:34 +01:00
dirty: bool,
2023-01-11 00:28:54 +01:00
}
2023-02-12 17:02:44 +01:00
fn get_battery_state() -> Result<UpowerBatteryState, Box<dyn Error>> {
let conn = LocalConnection::new_system()?;
let device_path = "/org/freedesktop/UPower/devices/DisplayDevice";
let proxy = conn.with_proxy(
"org.freedesktop.UPower",
device_path,
Duration::from_millis(500),
);
2023-02-13 18:49:44 +01:00
let state: u32 = proxy.get("org.freedesktop.UPower.Device", "State")?;
2023-02-12 17:02:44 +01:00
Ok(UpowerBatteryState::from_dbus(state as u64))
}
2023-01-16 00:25:34 +01:00
fn start_monitor(inner: Arc<Mutex<InnerBattery>>, events: Arc<Mutex<Events>>) {
2023-01-11 23:54:39 +01:00
thread::Builder::new()
.name("battmon".to_string())
.spawn(move || {
2023-02-06 18:34:07 +01:00
let conn = LocalConnection::new_system().unwrap();
let device_path = "/org/freedesktop/UPower/devices/DisplayDevice";
let proxy = conn.with_proxy(
"org.freedesktop.UPower",
device_path,
Duration::from_millis(500),
);
let capacity: f64 = proxy
.get("org.freedesktop.UPower.Device", "Percentage")
.expect("unable to get property");
let state: u32 = proxy
.get("org.freedesktop.UPower.Device", "State")
.expect("unable to get state");
{
let mut inner = inner.lock().unwrap();
inner.value = capacity as f32 / 100.;
2023-02-08 22:53:41 +01:00
inner.state = UpowerBatteryState::from_dbus(state as u64);
2023-02-06 18:34:07 +01:00
}
proxy
.match_signal(
move |c: PropertiesPropertiesChanged,
_: &LocalConnection,
_: &dbus::Message| {
if c.interface_name != "org.freedesktop.UPower.Device" {
return true;
}
let mut inner = inner.lock().unwrap();
for (key, value) in c.changed_properties {
match key.as_str() {
"State" => {
2023-02-08 22:53:41 +01:00
inner.state =
UpowerBatteryState::from_dbus(value.0.as_u64().unwrap());
2023-02-06 18:34:07 +01:00
inner.dirty = true;
let mut events = events.lock().unwrap();
events.add_event(Event::PowerUpdate);
}
"Percentage" => {
inner.value = value.0.as_f64().unwrap() as f32 / 100.;
inner.dirty = true;
let mut events = events.lock().unwrap();
events.add_event(Event::PowerUpdate);
}
_ => (),
}
}
true
},
)
2023-01-12 00:13:27 +01:00
.unwrap();
2023-02-06 18:34:07 +01:00
loop {
conn.process(Duration::from_millis(60000)).unwrap();
}
2023-01-12 00:13:27 +01:00
})
.unwrap();
2023-01-11 00:28:54 +01:00
}
pub struct Battery {
inner: Arc<Mutex<InnerBattery>>,
}
impl Battery {
2023-02-08 22:53:41 +01:00
pub fn new(
events: Arc<Mutex<Events>>,
fm: &mut FontMap,
font: &'static str,
size: f32,
) -> BarWidget {
2023-01-12 00:13:27 +01:00
let battery = Battery {
inner: Arc::new(Mutex::new(InnerBattery {
2023-01-11 00:28:54 +01:00
value: 0.,
2023-02-06 18:34:07 +01:00
state: UpowerBatteryState::Unknown,
2023-01-16 00:25:34 +01:00
dirty: false,
2023-01-11 00:28:54 +01:00
})),
};
2023-01-16 00:25:34 +01:00
start_monitor(battery.inner.clone(), events);
2023-02-02 23:52:59 +01:00
BarWidget::new(Box::new(battery), fm, font, size)
2023-01-11 00:28:54 +01:00
}
2023-02-12 17:02:44 +01:00
pub fn detect() -> bool {
match get_battery_state() {
Ok(_) => true,
Err(_) => false,
}
}
2023-01-11 00:28:54 +01:00
}
impl BarWidgetImpl for Battery {
fn get_dirty(&self) -> bool {
2023-01-16 00:25:34 +01:00
self.inner.lock().unwrap().dirty
2023-01-11 00:28:54 +01:00
}
fn name(&self) -> &'static str {
"battery"
}
2023-02-06 18:34:07 +01:00
fn value(&mut self) -> f32 {
2023-01-16 00:25:34 +01:00
let mut inner = self.inner.lock().unwrap();
inner.dirty = false;
2023-01-11 00:28:54 +01:00
inner.value
}
fn color(&self) -> Color {
let inner = self.inner.lock().unwrap();
match inner.state {
2023-02-08 22:53:41 +01:00
UpowerBatteryState::Charging | UpowerBatteryState::FullyCharged => Color::LIGHTGREEN,
2023-02-06 18:34:07 +01:00
_ if inner.value > 0.25 => Color::WHITE,
_ if inner.value > 0.1 => Color::DARKORANGE,
_ => Color::RED,
2023-01-11 00:28:54 +01:00
}
}
}