2023-01-11 00:28:54 +01:00
|
|
|
use std::{
|
2023-01-12 00:13:27 +01:00
|
|
|
sync::{Arc, Mutex},
|
2023-01-11 00:28:54 +01:00
|
|
|
thread,
|
|
|
|
|
time::Duration,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
use calloop::ping::Ping;
|
|
|
|
|
|
2023-01-11 23:54:39 +01:00
|
|
|
use dbus::blocking::{
|
2023-01-12 00:13:27 +01:00
|
|
|
stdintf::org_freedesktop_dbus::{Properties, PropertiesPropertiesChanged},
|
2023-01-11 23:54:39 +01:00
|
|
|
LocalConnection,
|
|
|
|
|
};
|
|
|
|
|
|
2023-01-11 00:28:54 +01:00
|
|
|
use crate::{
|
|
|
|
|
color::Color,
|
2023-01-12 00:13:27 +01:00
|
|
|
widgets::bar_widget::{BarWidget, BarWidgetImpl},
|
2023-01-11 00:28:54 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
enum UpowerBatteryState {
|
|
|
|
|
Charging,
|
|
|
|
|
Discharging,
|
|
|
|
|
Empty,
|
|
|
|
|
Full,
|
|
|
|
|
NotCharging,
|
|
|
|
|
Unknown,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct InnerBattery {
|
|
|
|
|
value: f32,
|
|
|
|
|
state: UpowerBatteryState,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn start_monitor(inner: Arc<Mutex<InnerBattery>>, ping: Ping) {
|
2023-01-11 23:54:39 +01:00
|
|
|
thread::Builder::new()
|
|
|
|
|
.name("battmon".to_string())
|
|
|
|
|
.spawn(move || {
|
2023-01-12 00:13:27 +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),
|
|
|
|
|
);
|
2023-01-11 00:28:54 +01:00
|
|
|
|
2023-01-12 00:13:27 +01:00
|
|
|
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");
|
2023-01-11 00:28:54 +01:00
|
|
|
|
2023-01-12 00:13:27 +01:00
|
|
|
{
|
|
|
|
|
let mut inner = inner.lock().unwrap();
|
|
|
|
|
inner.value = capacity as f32 / 100.;
|
|
|
|
|
inner.state = match state {
|
|
|
|
|
1 => UpowerBatteryState::Charging,
|
|
|
|
|
2 => UpowerBatteryState::Discharging,
|
|
|
|
|
3 => UpowerBatteryState::Empty,
|
|
|
|
|
4 => UpowerBatteryState::Full,
|
|
|
|
|
5 => UpowerBatteryState::NotCharging,
|
|
|
|
|
6 => UpowerBatteryState::Discharging,
|
|
|
|
|
_ => UpowerBatteryState::Unknown,
|
2023-01-11 00:28:54 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-12 00:13:27 +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" => {
|
|
|
|
|
inner.state = match value.0.as_u64().unwrap() {
|
|
|
|
|
1 => UpowerBatteryState::Charging,
|
|
|
|
|
2 => UpowerBatteryState::Discharging,
|
|
|
|
|
3 => UpowerBatteryState::Empty,
|
|
|
|
|
4 => UpowerBatteryState::Full,
|
|
|
|
|
5 => UpowerBatteryState::NotCharging,
|
|
|
|
|
6 => UpowerBatteryState::Discharging,
|
|
|
|
|
_ => UpowerBatteryState::Unknown,
|
|
|
|
|
};
|
|
|
|
|
ping.ping();
|
|
|
|
|
}
|
|
|
|
|
"Percentage" => {
|
|
|
|
|
inner.value = value.0.as_f64().unwrap() as f32 / 100.;
|
|
|
|
|
ping.ping();
|
|
|
|
|
}
|
|
|
|
|
_ => (),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
true
|
|
|
|
|
},
|
|
|
|
|
)
|
|
|
|
|
.unwrap();
|
|
|
|
|
|
|
|
|
|
loop {
|
|
|
|
|
conn.process(Duration::from_millis(60000)).unwrap();
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
.unwrap();
|
2023-01-11 00:28:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub struct Battery {
|
|
|
|
|
inner: Arc<Mutex<InnerBattery>>,
|
|
|
|
|
dirty: bool,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Battery {
|
|
|
|
|
pub fn new(ping: Ping) -> 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.,
|
|
|
|
|
state: UpowerBatteryState::Unknown,
|
|
|
|
|
})),
|
|
|
|
|
dirty: false,
|
|
|
|
|
};
|
|
|
|
|
start_monitor(battery.inner.clone(), ping);
|
|
|
|
|
BarWidget::new(Box::new(battery))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl BarWidgetImpl for Battery {
|
|
|
|
|
fn get_dirty(&self) -> bool {
|
|
|
|
|
self.dirty
|
|
|
|
|
}
|
|
|
|
|
fn set_dirty(&mut self, dirty: bool) {
|
|
|
|
|
self.dirty = dirty
|
|
|
|
|
}
|
|
|
|
|
fn name(&self) -> &'static str {
|
|
|
|
|
"battery"
|
|
|
|
|
}
|
|
|
|
|
fn value(&self) -> f32 {
|
|
|
|
|
let inner = self.inner.lock().unwrap();
|
|
|
|
|
inner.value
|
|
|
|
|
}
|
|
|
|
|
fn color(&self) -> Color {
|
|
|
|
|
let inner = self.inner.lock().unwrap();
|
|
|
|
|
match inner.state {
|
|
|
|
|
UpowerBatteryState::Discharging | UpowerBatteryState::Unknown => {
|
2023-01-11 23:54:39 +01:00
|
|
|
if inner.value > 0.25 {
|
2023-01-11 00:28:54 +01:00
|
|
|
Color::new(1.0, 1.0, 1.0, 1.0)
|
2023-01-11 23:54:39 +01:00
|
|
|
} else if inner.value > 0.1 {
|
2023-01-11 00:28:54 +01:00
|
|
|
Color::new(1.0, 0.5, 0.0, 1.0)
|
2023-01-11 23:54:39 +01:00
|
|
|
} else {
|
|
|
|
|
Color::new(1.0, 0.0, 0.0, 1.0)
|
2023-01-11 00:28:54 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
UpowerBatteryState::Charging | UpowerBatteryState::Full => {
|
|
|
|
|
Color::new(0.5, 1.0, 0.5, 1.0)
|
|
|
|
|
}
|
|
|
|
|
UpowerBatteryState::NotCharging | UpowerBatteryState::Empty => {
|
|
|
|
|
Color::new(1.0, 0.5, 0.5, 1.0)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|