From 0f06ac2286397082228f32fc5f9642778cf84d72 Mon Sep 17 00:00:00 2001 From: Jesse Luehrs Date: Mon, 14 May 2018 20:15:39 -0400 Subject: factor out os-specific battery detection code stub out osx for now, will come back with a real implementation later --- src/power.rs | 139 ------------------------------------------------- src/power/mod.rs | 86 ++++++++++++++++++++++++++++++ src/power/sys/linux.rs | 45 ++++++++++++++++ src/power/sys/macos.rs | 3 ++ src/power/sys/mod.rs | 24 +++++++++ 5 files changed, 158 insertions(+), 139 deletions(-) delete mode 100644 src/power.rs create mode 100644 src/power/mod.rs create mode 100644 src/power/sys/linux.rs create mode 100644 src/power/sys/macos.rs create mode 100644 src/power/sys/mod.rs diff --git a/src/power.rs b/src/power.rs deleted file mode 100644 index 6ae762c..0000000 --- a/src/power.rs +++ /dev/null @@ -1,139 +0,0 @@ -use std; -use walkdir; - -use std::io::Read; - -// XXX maybe extract this out into a separate crate? - -#[derive(PartialEq, Eq, Debug, Clone)] -enum PowerSupplyType { - AC, - Battery, -} - -#[derive(Debug)] -pub struct PowerInfo { - power_supplies: Vec, -} - -#[derive(Debug, Clone)] -struct PowerSupplyInfo { - name: String, - ty: PowerSupplyType, - energy_now: Option, - energy_full: Option, - online: Option, -} - -impl PowerInfo { - pub fn new() -> PowerInfo { - let mut power_supplies = vec![]; - for entry in walkdir::WalkDir::new("/sys/class/power_supply/") - .min_depth(1) - .max_depth(1) - .follow_links(true) - { - let entry = entry.unwrap(); - - let name = entry - .path() - .file_name() - .unwrap() - .to_string_lossy() - .into_owned(); - let ty = slurp(entry.path().join("type")) - .map(|t: String| PowerSupplyType::from_str(&t)) - .expect("couldn't find power supply type"); - let energy_full = slurp(entry.path().join("energy_full")); - let energy_now = slurp(entry.path().join("energy_now")); - let online = - slurp(entry.path().join("online")).map(|n: u8| n != 0); - - power_supplies.push(PowerSupplyInfo { - name, - ty, - energy_now, - energy_full, - online, - }) - } - - PowerInfo { - power_supplies, - } - } - - pub fn battery_usage(&self) -> Option { - let mut total_now = 0; - let mut total_full = 0; - for battery in self.batteries() { - if let Some(now) = battery.energy_now { - total_now += now; - } - else { - return None; - } - if let Some(full) = battery.energy_full { - total_full += full; - } - else { - return None; - } - } - - if total_full > 0 { - Some((total_now as f64) / (total_full as f64)) - } - else { - None - } - } - - pub fn charging(&self) -> bool { - for mains in self.mains() { - if mains.online == Some(true) { - return true; - } - } - false - } - - pub fn has_batteries(&self) -> bool { - self.batteries().count() > 0 - } - - fn batteries(&self) -> impl Iterator { - self.power_supplies - .iter() - .filter(|p| p.ty == PowerSupplyType::Battery) - } - - fn mains(&self) -> impl Iterator { - self.power_supplies - .iter() - .filter(|p| p.ty == PowerSupplyType::AC) - } -} - -impl PowerSupplyType { - fn from_str(ty: &str) -> Self { - match ty { - "Mains" => PowerSupplyType::AC, - "Battery" => PowerSupplyType::Battery, - _ => panic!("unknown power supply type {}", ty), - } - } -} - -fn slurp(path: U) -> Option -where - T: std::str::FromStr, - U: AsRef, -{ - let mut contents = String::new(); - std::fs::File::open(path).ok().and_then(|mut fh| { - fh.read_to_string(&mut contents) - .ok() - .and_then(|_| contents.trim().parse().ok()) - }) -} diff --git a/src/power/mod.rs b/src/power/mod.rs new file mode 100644 index 0000000..afe5194 --- /dev/null +++ b/src/power/mod.rs @@ -0,0 +1,86 @@ +use std; + +use std::io::Read; + +mod sys; + +// XXX maybe extract this out into a separate crate? + +#[derive(Debug)] +pub struct PowerInfo { + power_supplies: Vec, +} + +impl PowerInfo { + pub fn new() -> PowerInfo { + let power_supplies = sys::power_supplies(); + + PowerInfo { + power_supplies, + } + } + + pub fn battery_usage(&self) -> Option { + let mut total_now = 0; + let mut total_full = 0; + for battery in self.batteries() { + if let Some(now) = battery.energy_now { + total_now += now; + } + else { + return None; + } + if let Some(full) = battery.energy_full { + total_full += full; + } + else { + return None; + } + } + + if total_full > 0 { + Some((total_now as f64) / (total_full as f64)) + } + else { + None + } + } + + pub fn charging(&self) -> bool { + for mains in self.mains() { + if mains.online == Some(true) { + return true; + } + } + false + } + + pub fn has_batteries(&self) -> bool { + self.batteries().count() > 0 + } + + fn batteries(&self) -> impl Iterator { + self.power_supplies + .iter() + .filter(|p| p.ty == sys::PowerSupplyType::Battery) + } + + fn mains(&self) -> impl Iterator { + self.power_supplies + .iter() + .filter(|p| p.ty == sys::PowerSupplyType::AC) + } +} + +fn slurp(path: U) -> Option +where + T: std::str::FromStr, + U: AsRef, +{ + let mut contents = String::new(); + std::fs::File::open(path).ok().and_then(|mut fh| { + fh.read_to_string(&mut contents) + .ok() + .and_then(|_| contents.trim().parse().ok()) + }) +} diff --git a/src/power/sys/linux.rs b/src/power/sys/linux.rs new file mode 100644 index 0000000..670498a --- /dev/null +++ b/src/power/sys/linux.rs @@ -0,0 +1,45 @@ +use walkdir; + +pub fn power_supplies() -> Vec { + let mut power_supplies = vec![]; + for entry in walkdir::WalkDir::new("/sys/class/power_supply/") + .min_depth(1) + .max_depth(1) + .follow_links(true) + { + let entry = entry.unwrap(); + + let name = entry + .path() + .file_name() + .unwrap() + .to_string_lossy() + .into_owned(); + let ty = super::super::slurp(entry.path().join("type")) + .map(|t: String| super::PowerSupplyType::from_str(&t)) + .expect("couldn't find power supply type"); + let energy_full = super::super::slurp(entry.path().join("energy_full")); + let energy_now = super::super::slurp(entry.path().join("energy_now")); + let online = + super::super::slurp(entry.path().join("online")).map(|n: u8| n != 0); + + power_supplies.push(super::PowerSupplyInfo { + name, + ty, + energy_now, + energy_full, + online, + }) + } + power_supplies +} + +impl super::PowerSupplyType { + fn from_str(ty: &str) -> Self { + match ty { + "Mains" => super::PowerSupplyType::AC, + "Battery" => super::PowerSupplyType::Battery, + _ => panic!("unknown power supply type {}", ty), + } + } +} diff --git a/src/power/sys/macos.rs b/src/power/sys/macos.rs new file mode 100644 index 0000000..a0455ac --- /dev/null +++ b/src/power/sys/macos.rs @@ -0,0 +1,3 @@ +pub fn power_supplies() -> Vec { + vec![] +} diff --git a/src/power/sys/mod.rs b/src/power/sys/mod.rs new file mode 100644 index 0000000..b6bb469 --- /dev/null +++ b/src/power/sys/mod.rs @@ -0,0 +1,24 @@ +#[cfg(target_os = "linux")] +mod linux; +#[cfg(target_os = "linux")] +pub use self::linux::*; + +#[cfg(target_os = "macos")] +mod macos; +#[cfg(target_os = "macos")] +pub use self::macos::*; + +#[derive(PartialEq, Eq, Debug, Clone)] +pub enum PowerSupplyType { + AC, + Battery, +} + +#[derive(Debug, Clone)] +pub struct PowerSupplyInfo { + pub name: String, + pub ty: PowerSupplyType, + pub energy_now: Option, + pub energy_full: Option, + pub online: Option, +} -- cgit v1.2.3-54-g00ecf