diff options
author | fxqnlr <[email protected]> | 2024-09-23 14:52:55 +0200 |
---|---|---|
committer | fxqnlr <[email protected]> | 2024-09-23 14:52:55 +0200 |
commit | 0bd5337ad4aeddf5b3a709a95dbeaab75dfa8454 (patch) | |
tree | 845cfe0e388ba06a391e7f974aaa549b3459cece | |
download | esbnd-0bd5337ad4aeddf5b3a709a95dbeaab75dfa8454.tar esbnd-0bd5337ad4aeddf5b3a709a95dbeaab75dfa8454.tar.gz esbnd-0bd5337ad4aeddf5b3a709a95dbeaab75dfa8454.zip |
initial commit
-rwxr-xr-x | main | bin | 0 -> 3887512 bytes | |||
-rw-r--r-- | main.rs | 82 |
2 files changed, 82 insertions, 0 deletions
Binary files differ | |||
@@ -0,0 +1,82 @@ | |||
1 | use std::{ | ||
2 | collections::HashMap, env, fs::File, io::Read, process::Command, thread::sleep, time::Duration, | ||
3 | }; | ||
4 | |||
5 | fn main() { | ||
6 | let mut args = env::args(); | ||
7 | |||
8 | assert!( | ||
9 | args.len() > 2, | ||
10 | "Too few arguments, provide battery id and values with warning levels" | ||
11 | ); | ||
12 | // Skip process (argc[0]) | ||
13 | args.next(); | ||
14 | |||
15 | // 1: Battery ID | ||
16 | let bat = args.next().expect("Invalid Battery id"); | ||
17 | let bat_path = format!("/sys/class/power_supply/{bat}"); | ||
18 | let cap_path = format!("{bat_path}/capacity"); | ||
19 | let status_path = format!("{bat_path}/status"); | ||
20 | |||
21 | // 2: Sleep | ||
22 | let sleep_secs = args | ||
23 | .next() | ||
24 | .expect("Invalid sleep duration") | ||
25 | .parse::<u64>() | ||
26 | .expect("Invalid sleep value"); | ||
27 | |||
28 | let mut warnings: HashMap<u8, String> = HashMap::new(); | ||
29 | for arg in args { | ||
30 | let (lvl, value) = arg.split_at(1); | ||
31 | assert!( | ||
32 | lvl == "l" || lvl == "n" || lvl == "c", | ||
33 | "Unknown notification level" | ||
34 | ); | ||
35 | warnings.insert( | ||
36 | value.parse::<u8>().expect("Invalid battery value"), | ||
37 | lvl.to_string(), | ||
38 | ); | ||
39 | } | ||
40 | |||
41 | let mut cap_cache = String::new(); | ||
42 | loop { | ||
43 | let cur_cap = read_file(&cap_path); | ||
44 | if cur_cap != cap_cache { | ||
45 | cap_cache.clone_from(&cur_cap); | ||
46 | if &read_file(&status_path) == "Charging" { continue; }; | ||
47 | let val = cur_cap | ||
48 | .parse::<u8>() | ||
49 | .expect("Couldn't parse capacity value"); | ||
50 | if let Some(lvl) = warnings.get(&val) { | ||
51 | notify(lvl, val); | ||
52 | }; | ||
53 | } | ||
54 | sleep(Duration::from_secs(sleep_secs)); | ||
55 | } | ||
56 | } | ||
57 | |||
58 | fn read_file(path: &str) -> String { | ||
59 | let mut f = File::open(path).expect("Could't open file"); | ||
60 | let mut buf = String::new(); | ||
61 | f.read_to_string(&mut buf).expect("Couldn't read file"); | ||
62 | buf.trim().to_string() | ||
63 | } | ||
64 | |||
65 | fn notify(lvl: &str, remaining: u8) { | ||
66 | let urgency = match lvl { | ||
67 | "l" => "low", | ||
68 | "n" => "normal", | ||
69 | "c" => "critical", | ||
70 | _ => unreachable!(), | ||
71 | }; | ||
72 | let notif = format!("Remaining battery capacity: {remaining}"); | ||
73 | Command::new("notify-send") | ||
74 | .arg("--app-name=esbnd") | ||
75 | .arg("--category=device") | ||
76 | .arg("--icon=battery-low-symbolic") | ||
77 | .arg("-u") | ||
78 | .arg(urgency) | ||
79 | .arg(notif) | ||
80 | .spawn() | ||
81 | .expect("Couldn't send notification"); | ||
82 | } | ||