Hi there,
This time I have been working on a project which was use-full to me.
For context I'm running my laptop on PopOS with i3wm. My laptop getting a bit old now the battery is a bit tired :D.
i3wm being a you configure it all manual Window Manager, and by default I don't have or I'm not aware out-of-the-box to get a notification when my battery is getting low. I decide to use the opportunity to develop the tool myself.
use dbus::blocking::Connection;
use dbus::{Message, arg::messageitem::MessageItemArray};
use std::{time::Duration, vec};
pub fn prendlebus() -> Result<(), Box<dyn std::error::Error>> {
let timeout = Duration::new(2000,0);
// First open up a connection to the session bus.
let conn = Connection::new_session()?;
// Create a message that calls the Notify method of the Notifications interface
let mut m = Message::new_method_call(
"org.freedesktop.Notifications", // destination
"/org/freedesktop/Notifications", // path
"org.freedesktop.Notifications", // interface
"Notify" // method
).unwrap();
// Append the required arguments to the message
let notificationlevel: u32 = 0;
let actions = MessageItemArray::new(vec![],"as".into()).unwrap();
let hints = MessageItemArray::new(vec![],"a{sv}".into()).unwrap();
let timingout = 5000;
m = Message::append3(m,"bll",notificationlevel,"/usr/share/icons/ubuntu-mono-dark/status/24/unity-battery-020.svg")
.append3("BATTERY", "Your Battery is running low !!", actions)
.append2(hints, timingout);
// Send the message to the bus and handle the possible errors
match conn.channel().send_with_reply_and_block(m, timeout){
//match conn.send_with_reply_and_block(m, 2000) {
Ok(_) => println!("Notification sent successfully"),
Err(e) => println!("Error: {}", e),
}
Ok(())
}
use std::fs;
use bll::prendlebus;
fn main() {
let warning_value = 600000;
let battery_level = "/sys/class/power_supply/BAT1/charge_now";
let battery_status = "/sys/class/power_supply/BAT1/status";
println!("Check from {}", battery_level);
let current_battery_level = fs::read_to_string(battery_level)
.expect("Should have been able to read the file")
.as_str()
.trim()
.parse::<u32>()
.unwrap();
let current_battery_status: String = fs::read_to_string(battery_status).expect("should be ok").trim().parse().unwrap();
//println!("{:#?}",¤t_battery_status);
//println!("This is the content: {}",current_battery_level);
// if current now is lower than warning_value
// trigger dbus nofitication
if current_battery_level <= warning_value {
if current_battery_status == "Discharging" {
println!("Battery is going to ie !! See {warning_value} > {current_battery_level}");
let _ = prendlebus();
} else {
print!("We are charging all good!\n")
}
}
}
This is the configuration file to create the service
[Unit]
Description=Battery Low Level
[Service]
Type=oneshot
ExecStart=/devouille/bll/target/release/bll
User=mducorps
This is the timer to run it every 30sec
[Unit]
Description=Bll timer
[Timer]
OnUnitActiveSec=30s
OnBootSec=30s
[Install]
WantedBy=timers.target
With this I have now a desktop notification when my laptop is running low on Battery. working flawlessly so far.
You can find the source code here.
https://github.com/Vagrantin/bll
With kind regards
Matthieu.