mirror of
https://github.com/Wojtek242/rwmstatus.git
synced 2024-11-24 00:15:25 +01:00
Automate collection of device dependent paths
This commit is contained in:
parent
4408b3b54b
commit
7172772413
@ -1,16 +1,10 @@
|
|||||||
//! # rwmstatus configuration
|
//! # rwmstatus configuration
|
||||||
|
|
||||||
/// Path to monitors.
|
/// Path to monitors.
|
||||||
pub const HWMON_PATH: &'static str = "/sys/devices/virtual/hwmon";
|
pub const HW_MON_PATH: &'static str = "/sys/devices/virtual/hwmon";
|
||||||
|
|
||||||
/// Array of monitors to use.
|
|
||||||
pub const HWMONS: [&'static str; 3] = ["hwmon0", "hwmon2", "hwmon4"];
|
|
||||||
|
|
||||||
/// Path to power supply information.
|
/// Path to power supply information.
|
||||||
pub const BATT_PATH: &'static str = "/sys/class/power_supply";
|
pub const BATT_PATH: &'static str = "/sys/class/power_supply";
|
||||||
|
|
||||||
/// Batteries to display.
|
|
||||||
pub const BATTS: [&'static str; 2] = ["BAT0", "BAT1"];
|
|
||||||
|
|
||||||
/// Additional time zones to display (short name, full name).
|
/// Additional time zones to display (short name, full name).
|
||||||
pub const TZS: [(char, &'static str); 2] = [('A', "America/Buenos_Aires"), ('U', "UTC")];
|
pub const TZS: [(char, &'static str); 2] = [('A', "America/Buenos_Aires"), ('U', "UTC")];
|
||||||
|
145
src/lib.rs
145
src/lib.rs
@ -6,6 +6,7 @@
|
|||||||
//! [suckless.org](https://suckless.org/) programs to Rust, a programming
|
//! [suckless.org](https://suckless.org/) programs to Rust, a programming
|
||||||
//! language that sucks less.
|
//! language that sucks less.
|
||||||
|
|
||||||
|
// External crates
|
||||||
extern crate chrono;
|
extern crate chrono;
|
||||||
extern crate chrono_tz;
|
extern crate chrono_tz;
|
||||||
extern crate libc;
|
extern crate libc;
|
||||||
@ -16,36 +17,23 @@ use std::io;
|
|||||||
// std type imports
|
// std type imports
|
||||||
use std::io::prelude::*;
|
use std::io::prelude::*;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
|
use std::path::Path;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
// Other external imports
|
// Other external imports
|
||||||
use chrono::prelude::*;
|
use chrono::prelude::*;
|
||||||
|
|
||||||
// Internal module imports
|
|
||||||
mod config;
|
|
||||||
use config::*;
|
|
||||||
|
|
||||||
/// Read the contents of the file base/filename and return as a String.
|
/// Read the contents of the file base/filename and return as a String.
|
||||||
#[inline]
|
#[inline]
|
||||||
fn read_file(base: &str, filename: &str) -> io::Result<String> {
|
fn read_file(base: &PathBuf, filename: &str) -> io::Result<String> {
|
||||||
let mut file = File::open([base, filename].join("/"))?;
|
let mut file = File::open(base.join(filename))?;
|
||||||
let mut contents = String::new();
|
let mut contents = String::new();
|
||||||
file.read_to_string(&mut contents)?;
|
file.read_to_string(&mut contents)?;
|
||||||
Ok(contents)
|
Ok(contents)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return temperature reads from all monitors.
|
|
||||||
pub fn get_temperatures() -> String {
|
|
||||||
let mut temp_strs: Vec<String> = vec![];
|
|
||||||
|
|
||||||
for hwmon in HWMONS.iter() {
|
|
||||||
temp_strs.push(get_temp(&[HWMON_PATH, hwmon].join("/")));
|
|
||||||
}
|
|
||||||
|
|
||||||
temp_strs.join("|")
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return temperature read from the provided monitor.
|
/// Return temperature read from the provided monitor.
|
||||||
fn get_temp(hwmon: &str) -> String {
|
pub fn get_temp(hwmon: &PathBuf) -> String {
|
||||||
match read_file(hwmon, "temp1_input") {
|
match read_file(hwmon, "temp1_input") {
|
||||||
Ok(contents) => {
|
Ok(contents) => {
|
||||||
match contents.trim().parse::<f64>() {
|
match contents.trim().parse::<f64>() {
|
||||||
@ -73,19 +61,8 @@ pub fn get_load_avgs() -> String {
|
|||||||
format!("{:.2} {:.2} {:.2}", avgs[0], avgs[1], avgs[2])
|
format!("{:.2} {:.2} {:.2}", avgs[0], avgs[1], avgs[2])
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return battery status for all batteries.
|
|
||||||
pub fn get_batteries() -> String {
|
|
||||||
let mut batt_strs: Vec<String> = vec![];
|
|
||||||
|
|
||||||
for batt in BATTS.iter() {
|
|
||||||
batt_strs.push(get_batt(&[BATT_PATH, batt].join("/")));
|
|
||||||
}
|
|
||||||
|
|
||||||
batt_strs.join("|")
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return battery status for the battery at the provided path.
|
/// Return battery status for the battery at the provided path.
|
||||||
fn get_batt(batt: &str) -> String {
|
pub fn get_batt(batt: &PathBuf) -> String {
|
||||||
match read_file(&batt, "present") {
|
match read_file(&batt, "present") {
|
||||||
Ok(contents) => {
|
Ok(contents) => {
|
||||||
if !contents.starts_with('1') {
|
if !contents.starts_with('1') {
|
||||||
@ -144,21 +121,8 @@ fn get_batt(batt: &str) -> String {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return times for all configured time zones.
|
|
||||||
pub fn get_times() -> String {
|
|
||||||
let mut tz_strs: Vec<String> = vec![];
|
|
||||||
|
|
||||||
for tz in TZS.iter() {
|
|
||||||
tz_strs.push(format!("{}:{}", tz.0, get_tz_time(tz.1, "%H:%M")));
|
|
||||||
}
|
|
||||||
|
|
||||||
tz_strs.push(get_local_time("KW %W %a %d %b %H:%M %Z %Y"));
|
|
||||||
|
|
||||||
tz_strs.join(" ")
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get the time for the provided time zone.
|
/// Get the time for the provided time zone.
|
||||||
fn get_tz_time(tz_name: &str, fmt: &str) -> String {
|
pub fn get_tz_time(tz_name: &str, fmt: &str) -> String {
|
||||||
match tz_name.parse::<chrono_tz::Tz>() {
|
match tz_name.parse::<chrono_tz::Tz>() {
|
||||||
Ok(tz) => {
|
Ok(tz) => {
|
||||||
let utc = Utc::now().naive_utc();
|
let utc = Utc::now().naive_utc();
|
||||||
@ -169,6 +133,97 @@ fn get_tz_time(tz_name: &str, fmt: &str) -> String {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Get the local time.
|
/// Get the local time.
|
||||||
fn get_local_time(fmt: &str) -> String {
|
pub fn get_local_time(fmt: &str) -> String {
|
||||||
format!("{}", Local::now().format(fmt))
|
format!("{}", Local::now().format(fmt))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// ## RwmStatus
|
||||||
|
///
|
||||||
|
/// This struct collects device dependent paths and user settings. It also
|
||||||
|
/// provides convenience methods to aggregate readouts.
|
||||||
|
pub struct RwmStatus {
|
||||||
|
hw_mons: Vec<PathBuf>,
|
||||||
|
batts: Vec<PathBuf>,
|
||||||
|
tzs: Vec<(char, &'static str)>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RwmStatus {
|
||||||
|
/// Build a new RwmStatus object. This function collects all the monitor
|
||||||
|
/// and battery paths for later use.
|
||||||
|
pub fn new(hw_mon_path: &str, batt_path: &str, tzs: &[(char, &'static str)]) -> RwmStatus {
|
||||||
|
RwmStatus {
|
||||||
|
hw_mons: RwmStatus::get_paths(hw_mon_path, "hwmon"),
|
||||||
|
batts: RwmStatus::get_paths(batt_path, "BAT"),
|
||||||
|
tzs: tzs.to_vec(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Collect all the paths of the form base_path/prefix*
|
||||||
|
fn get_paths(base_path: &str, prefix: &str) -> Vec<PathBuf> {
|
||||||
|
let dir = match Path::new(base_path).read_dir() {
|
||||||
|
Ok(iter) => iter,
|
||||||
|
Err(_) => return vec![],
|
||||||
|
};
|
||||||
|
|
||||||
|
let dir_filtered = dir.filter(|path_result| match path_result {
|
||||||
|
&Ok(ref path) => {
|
||||||
|
match path.file_name().to_str() {
|
||||||
|
Some(entry) => entry.starts_with(prefix),
|
||||||
|
None => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&Err(_) => false,
|
||||||
|
});
|
||||||
|
|
||||||
|
let mut paths: Vec<PathBuf> = dir_filtered
|
||||||
|
.map(|path_result| match path_result {
|
||||||
|
Ok(path) => path.path(),
|
||||||
|
Err(_) => panic!("Unexpected file path"),
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
paths.sort_unstable();
|
||||||
|
paths
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return temperature reads from all monitors.
|
||||||
|
pub fn get_temperatures(&self) -> String {
|
||||||
|
let mut temp_strs: Vec<String> = vec![];
|
||||||
|
|
||||||
|
for hwmon in self.hw_mons.iter() {
|
||||||
|
temp_strs.push(get_temp(&hwmon));
|
||||||
|
}
|
||||||
|
|
||||||
|
temp_strs.join("|")
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return the three load average values.
|
||||||
|
#[inline]
|
||||||
|
pub fn get_load_avgs(&self) -> String {
|
||||||
|
get_load_avgs()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return battery status for all batteries.
|
||||||
|
pub fn get_batteries(&self) -> String {
|
||||||
|
let mut batt_strs: Vec<String> = vec![];
|
||||||
|
|
||||||
|
for batt in self.batts.iter() {
|
||||||
|
batt_strs.push(get_batt(&batt));
|
||||||
|
}
|
||||||
|
|
||||||
|
batt_strs.join("|")
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return times for all configured time zones.
|
||||||
|
pub fn get_times(&self) -> String {
|
||||||
|
let mut tz_strs: Vec<String> = vec![];
|
||||||
|
|
||||||
|
for tz in self.tzs.iter() {
|
||||||
|
tz_strs.push(format!("{}:{}", tz.0, get_tz_time(tz.1, "%H:%M")));
|
||||||
|
}
|
||||||
|
|
||||||
|
tz_strs.push(get_local_time("KW %W %a %d %b %H:%M %Z %Y"));
|
||||||
|
|
||||||
|
tz_strs.join(" ")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
38
src/main.rs
38
src/main.rs
@ -8,10 +8,11 @@
|
|||||||
//! [suckless.org](https://suckless.org/) programs to Rust, a programming
|
//! [suckless.org](https://suckless.org/) programs to Rust, a programming
|
||||||
//! language that sucks less.
|
//! language that sucks less.
|
||||||
|
|
||||||
// Lib imports
|
// Lib import
|
||||||
extern crate rwmstatus;
|
extern crate rwmstatus;
|
||||||
use rwmstatus::*;
|
use rwmstatus::*;
|
||||||
|
|
||||||
|
// External crates
|
||||||
extern crate x11;
|
extern crate x11;
|
||||||
|
|
||||||
// std module imports
|
// std module imports
|
||||||
@ -27,6 +28,9 @@ use std::ffi::CString;
|
|||||||
use x11::xlib::Display;
|
use x11::xlib::Display;
|
||||||
use x11::xlib::{XDefaultRootWindow, XOpenDisplay, XStoreName, XSync};
|
use x11::xlib::{XDefaultRootWindow, XOpenDisplay, XStoreName, XSync};
|
||||||
|
|
||||||
|
// Internal module imports
|
||||||
|
mod config;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let display: *mut Display;
|
let display: *mut Display;
|
||||||
|
|
||||||
@ -39,14 +43,32 @@ fn main() {
|
|||||||
process::exit(1);
|
process::exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
loop {
|
let rwmstatus = RwmStatus::new(config::HW_MON_PATH, config::BATT_PATH, &config::TZS[..]);
|
||||||
let temps = get_temperatures();
|
|
||||||
let avgs = get_load_avgs();
|
|
||||||
let batts = get_batteries();
|
|
||||||
let times = get_times();
|
|
||||||
|
|
||||||
let status = CString::new(format!("T:{} L:{} B:{} {}", temps, avgs, batts, times))
|
loop {
|
||||||
.expect("Failed to create status CString.");
|
let mut stats = vec![];
|
||||||
|
|
||||||
|
let temps = rwmstatus.get_temperatures();
|
||||||
|
if !temps.is_empty() {
|
||||||
|
stats.push(format!("T:{}", temps));
|
||||||
|
}
|
||||||
|
|
||||||
|
let avgs = rwmstatus.get_load_avgs();
|
||||||
|
if !avgs.is_empty() {
|
||||||
|
stats.push(format!("L:{}", avgs));
|
||||||
|
}
|
||||||
|
|
||||||
|
let batts = rwmstatus.get_batteries();
|
||||||
|
if !batts.is_empty() {
|
||||||
|
stats.push(format!("B:{}", batts));
|
||||||
|
}
|
||||||
|
|
||||||
|
let times = rwmstatus.get_times();
|
||||||
|
if !times.is_empty() {
|
||||||
|
stats.push(times);
|
||||||
|
}
|
||||||
|
|
||||||
|
let status = CString::new(stats.join(" ")).expect("Failed to create status CString.");
|
||||||
unsafe {
|
unsafe {
|
||||||
XStoreName(display, XDefaultRootWindow(display), status.as_ptr());
|
XStoreName(display, XDefaultRootWindow(display), status.as_ptr());
|
||||||
XSync(display, false as i32);
|
XSync(display, false as i32);
|
||||||
|
Loading…
Reference in New Issue
Block a user