Added power module

This commit is contained in:
Mahesh Asolkar 2025-06-07 16:15:56 -07:00
parent c2eee03ac2
commit 00079662df
Signed by: asolkar
GPG Key ID: 371CA8164433BDCC
3 changed files with 145 additions and 0 deletions

View File

@ -0,0 +1,142 @@
use std::process::{Stdio, Command};
//use std::collections::HashMap;
use regex::Regex;
use crate::common;
use crate::bar_modules;
#[derive(Clone)]
pub struct UnibarModulePower {
opts: common::AppOptions,
power_info: PowerData,
}
#[derive(Debug, Default, Clone)]
struct PowerData {
charging: bool,
level: u64,
}
impl PowerData {
pub fn new() -> Self {
PowerData {
charging: true,
level: 100,
}
}
}
impl UnibarModulePower {
// --------------------
pub fn new(o :common::AppOptions) -> Self {
UnibarModulePower {
opts: o,
power_info: PowerData::new(),
}
}
}
impl bar_modules::BarModuleActions for UnibarModulePower {
// --------------------
fn generate_data(&mut self) {
// Following command is used to get power data:
// % upower -i /org/freedesktop/UPower/devices/DisplayDevice
//
// In UPower, the "display device" is a special object that represents the combined
// power status that should be shown in desktop environments.
//
// Purpose:
//
// It acts as a central point of information for the power icon displayed in your
// system's notification area or taskbar.
// Instead of desktop environments having to query all individual power sources,
// they can access this single "display device" to get a summary of the overall
// power status.
//
// Key characteristics:
//
// Composite device: It combines information from multiple power sources
// (like batteries, UPS) to provide a unified view.
// Object path: It has a dedicated object path, typically
// /org/freedesktop/UPower/devices/DisplayDevice.
// Properties: It exposes properties like Type, State, Percentage, TimeToEmpty,
// TimeToFull, and IconName to describe the device's status and
// icon representation.
// Dynamic Type: Unlike real devices, the Type of the display device can
// change (e.g., from Battery to UPS) depending on the current power situation.
//
// In essence, the "display device" simplifies power management for desktop environments
// by providing a convenient interface to show the relevant power information to the user.
//
let power_dump = Command::new("upower")
.arg("--dump")
.stdout(Stdio::piped())
.output()
.unwrap();
let power_str = String::from_utf8(power_dump.stdout).unwrap();
let lines: Vec<&str> = power_str.split('\n').map(|s| s.trim()).collect();
let mut found_device: bool = false;
// let devices: HashMap<String, HashMap<String, String>>::new();
// let cur_dev: HashMap<String, String>::new();
for line in lines {
if line.is_empty() { continue };
let dev_re = Regex::new(r"^Device:\s+(.*)").unwrap();
if let Some(caps) = dev_re.captures(line) {
if let Some((last, _els)) = &caps[1].split('/').collect::<Vec<_>>().split_last() {
if self.opts.debug {
println!("-----> Power dump - Device - {:#?}", last);
}
if last.to_string() == "DisplayDevice" {
found_device = true;
}
}
}
if found_device {
let level_re = Regex::new(r"^percentage:\s+(\d+)").unwrap();
if let Some(caps) = level_re.captures(line) {
self.power_info.level = caps[1].parse().unwrap_or(0);
if self.opts.debug {
println!("-----> Power dump - level - {:#?}", self.power_info.level);
}
}
let state_re = Regex::new(r"^state:\s+(\S+)").unwrap();
if let Some(caps) = state_re.captures(line) {
self.power_info.charging = caps[1].to_string() != "discharging";
if self.opts.debug {
println!("-----> Power dump - charging - {:#?}", self.power_info.charging);
}
}
}
// if self.opts.debug {
// println!("-----> Power dump {:#?}", line);
// }
}
}
// --------------------
fn get_content(&self) -> String {
// return format!("{}", parts.join(" "));
return format!("{:.0}%", self.power_info.level);
}
// --------------------
fn get_icon(&self) -> String {
match self.power_info.charging {
true => return "🔌".to_string(),
false => return "🔋".to_string()
}
}
}
impl bar_modules::BarModuleDebug for UnibarModulePower {
// --------------------
fn post_debug(&self) {
}
}

View File

@ -22,3 +22,4 @@ pub mod bar_module_music;
pub mod bar_module_network; pub mod bar_module_network;
pub mod bar_module_memory; pub mod bar_module_memory;
pub mod bar_module_cpu; pub mod bar_module_cpu;
pub mod bar_module_power;

View File

@ -57,6 +57,7 @@ impl Unibar {
Box::new(bar_modules::bar_module_music::UnibarModuleMusic::new(self.opts.clone())), Box::new(bar_modules::bar_module_music::UnibarModuleMusic::new(self.opts.clone())),
Box::new(bar_modules::bar_module_memory::UnibarModuleMemory::new(self.opts.clone())), Box::new(bar_modules::bar_module_memory::UnibarModuleMemory::new(self.opts.clone())),
Box::new(bar_modules::bar_module_cpu::UnibarModuleCpu::new(self.opts.clone())), Box::new(bar_modules::bar_module_cpu::UnibarModuleCpu::new(self.opts.clone())),
Box::new(bar_modules::bar_module_power::UnibarModulePower::new(self.opts.clone())),
Box::new(bar_modules::bar_module_network::UnibarModuleNetwork::new(self.opts.clone())), Box::new(bar_modules::bar_module_network::UnibarModuleNetwork::new(self.opts.clone())),
Box::new(bar_modules::bar_module_weather::UnibarModuleWeather::new(self.opts.clone())), Box::new(bar_modules::bar_module_weather::UnibarModuleWeather::new(self.opts.clone())),
]; ];
@ -88,6 +89,7 @@ impl Unibar {
Box::new(bar_modules::bar_module_memory::UnibarModuleMemory::new(self.opts.clone())), Box::new(bar_modules::bar_module_memory::UnibarModuleMemory::new(self.opts.clone())),
Box::new(bar_modules::bar_module_network::UnibarModuleNetwork::new(self.opts.clone())), Box::new(bar_modules::bar_module_network::UnibarModuleNetwork::new(self.opts.clone())),
Box::new(bar_modules::bar_module_cpu::UnibarModuleCpu::new(self.opts.clone())), Box::new(bar_modules::bar_module_cpu::UnibarModuleCpu::new(self.opts.clone())),
Box::new(bar_modules::bar_module_power::UnibarModulePower::new(self.opts.clone())),
]; ];
for md in bar_modules_debugged { for md in bar_modules_debugged {
md.post_debug(); md.post_debug();