summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYves Fischer <yvesf-git@xapek.org>2018-01-04 20:34:54 +0100
committerYves Fischer <yvesf-git@xapek.org>2018-01-05 01:10:48 +0100
commit7b8412d8b84d3fd37f43c0b07a1b8049a21dd999 (patch)
tree9d90bd58d551f6abfe90e898b6890a90a79d9c09
downloadbatteriewarner-7b8412d8b84d3fd37f43c0b07a1b8049a21dd999.tar.gz
batteriewarner-7b8412d8b84d3fd37f43c0b07a1b8049a21dd999.zip
seems to work
-rw-r--r--.gitignore5
-rw-r--r--Cargo.toml6
-rw-r--r--src/main.rs81
3 files changed, 92 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..388c7e7
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,5 @@
+/target/
+**/*.rs.bk
+.idea
+*iml
+Cargo.lock
diff --git a/Cargo.toml b/Cargo.toml
new file mode 100644
index 0000000..a801c97
--- /dev/null
+++ b/Cargo.toml
@@ -0,0 +1,6 @@
+[package]
+name = "batteriewarner"
+version = "0.1.0"
+authors = ["Yves Fischer <yvesf-git@xapek.org>"]
+
+[dependencies]
diff --git a/src/main.rs b/src/main.rs
new file mode 100644
index 0000000..b404cfa
--- /dev/null
+++ b/src/main.rs
@@ -0,0 +1,81 @@
+use std::str;
+use std::fs::OpenOptions;
+use std::io::{Result, Read, Write, Error, ErrorKind};
+use std::convert::AsRef;
+use std::path::Path;
+use std::thread::sleep;
+use std::time::Duration;
+
+const PATH_ENERGY_NOW: &'static str = "/sys/class/power_supply/BAT0/energy_now";
+const PATH_ENERGY_FULL: &'static str = "/sys/class/power_supply/BAT0/energy_full_design";
+const PATH_LIGHT: &'static str = "/sys/devices/platform/thinkpad_acpi/leds/tpacpi::power/brightness";
+
+fn file_read_integer<P: AsRef<Path>>(path: P) -> Result<u64> {
+ let mut buf = [0; 20];
+ let mut file = OpenOptions::new().read(true).open(path.as_ref())?;
+ let len = file.read(&mut buf)?;
+ if len < 1 {
+ return Err(Error::new(ErrorKind::Other, "Empty file"));
+ };
+
+ let s = str::from_utf8(&buf[0..len])
+ .map_err(|e| Error::new(ErrorKind::Other, e))?;
+ s.trim().parse()
+ .map_err(|err| Error::new(ErrorKind::Other, format!("String parse failed: {}", err)))
+}
+
+fn read_battery_percentage() -> Result<u32> {
+ let now = file_read_integer(PATH_ENERGY_NOW)?;
+ let full = file_read_integer(PATH_ENERGY_FULL)?;
+ Ok(((now * 100) / full) as u32)
+}
+
+fn write_brightness(level: u8) -> Result<()> {
+ let string = format!("{}\n", level);
+ let mut file = OpenOptions::new().write(true).open(PATH_LIGHT)?;
+ if file.write(string.as_bytes())? == string.len() {
+ Ok(())
+ } else {
+ Err(Error::new(ErrorKind::Other, "Failed to write brightness"))
+ }
+}
+
+fn read_brightness() -> Result<u8> {
+ let level = file_read_integer(PATH_LIGHT)?;
+ Ok(level as u8)
+}
+
+fn indicate_battery_level(level: u32) -> Result<()> {
+ let led_state = read_brightness()?;
+ let flashing_time: u32 = 10000;
+ let offtime: u32 = 40;
+ let ontime: u32 = 20;
+ let n = flashing_time / (level * offtime + level * ontime);
+ for _ in 0..n {
+ write_brightness(0)?;
+ sleep(Duration::from_millis((level * offtime) as u64));
+ write_brightness(1)?;
+ sleep(Duration::from_millis((level * ontime) as u64));
+ }
+ write_brightness(led_state)?;
+ Ok(())
+}
+
+#[allow(unused)]
+fn main() {
+ loop {
+ let p = read_battery_percentage();
+ match p {
+ Ok(level) => {
+ println!("Battery Level: {}", level);
+ if level < 20 {
+ match indicate_battery_level(level) {
+ Err(e) => panic!("Error: {}", e),
+ _ => {}
+ }
+ }
+ }
+ Err(e) => panic!("Error: {}", e),
+ }
+ }
+} \ No newline at end of file