123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135 |
- extern crate time;
- use comm;
- use comm::Channel;
- use config::Config;
- use std::fs::File;
- use std::io::SeekFrom;
- use std::io::prelude::*;
- use std::thread;
- trait Sensor {
- fn status(&mut self) -> String;
- }
- struct BatterySensor {
- charge_now: File,
- charge_full: File
- }
- impl BatterySensor {
- fn new(supply: &str) -> BatterySensor {
- let path = format!("/sys/class/power_supply/{}", supply);
- BatterySensor {
- charge_now: File::open(format!("{}/{}", path, "charge_now")).unwrap(),
- charge_full: File::open(format!("{}/{}", path, "charge_full")).unwrap()
- }
- }
- }
- impl Sensor for BatterySensor {
- fn status(&mut self) -> String {
- let mut s = String::new();
- self.charge_now.read_to_string(&mut s).ok().expect("Could not read current charge");
- let charge_now : u32 = s.trim().parse().ok().expect("Could not parse charge");
- s.clear();
- self.charge_full.read_to_string(&mut s).ok().expect("Could not read current charge");
- let charge_full : u32 = s.trim().parse().ok().expect("Could not parse charge");
- self.charge_now.seek(SeekFrom::Start(0)).ok();
- self.charge_full.seek(SeekFrom::Start(0)).ok();
- format!("{}%", charge_now / (charge_full / 100))
- }
- }
- struct TempSensor {
- file: File
- }
- impl TempSensor {
- fn new(zone: &str) -> TempSensor {
- let path = format!("/sys/class/thermal/{}/temp", zone);
- TempSensor {
- file: File::open(path).unwrap()
- }
- }
- }
- impl Sensor for TempSensor {
- fn status(&mut self) -> String {
- let mut s = String::new();
- self.file.read_to_string(&mut s).ok().expect("Could not read temperature stats");
- let i : Option<u32> = s.trim().parse().ok();
- self.file.seek(SeekFrom::Start(0)).ok().expect("Could not reread temperature");
- match i {
- Some(i) => format!("{}°C", i/1000),
- None => "?°C".to_string(),
- }
- }
- }
- struct TimeSensor {
- format: String,
- is_utc: bool
- }
- impl TimeSensor {
- fn new(format: &str, is_utc: bool) -> TimeSensor {
- TimeSensor {
- format: format.to_string(),
- is_utc: is_utc
- }
- }
- }
- impl Sensor for TimeSensor {
- fn status(&mut self) -> String {
- let now =
- if self.is_utc {
- time::now_utc()
- }
- else {
- time::now()
- };
- let time = time::strftime(&self.format, &now);
- time.unwrap()
- }
- }
- pub fn sensors(tx: &Channel, config: &Config) {
- let zone = config.lookup("sensors.thermal_zone").unwrap();
- let zone = zone.as_str().unwrap();
- let mut sensors: Vec<Box<Sensor>> = vec![
- Box::new(TempSensor::new(zone)),
- Box::new(TimeSensor::new("UTC %H:%M", true)),
- Box::new(TimeSensor::new("%Y-%m-%d %H:%M", false))
- ];
- let bat = config.lookup("sensors.battery");
- let bat = bat.map(|bat| bat.as_str().unwrap());
- bat.map(|bat| sensors.insert(0, Box::new(BatterySensor::new(bat))));
- loop {
- let status = sensors.iter_mut()
- .map(|sensor| sensor.status())
- .collect::<Vec<String>>();
- comm::send(tx, "sensors", &reduce(status));
- thread::sleep_ms(1000);
- }
- }
- fn reduce(arr: Vec<String>) -> String {
- let result = arr.into_iter()
- .fold("".to_string(), |acc, elem| format!("{} | {}", acc, elem));
- if result.len() > 0 { result[3..].to_string() } else { result }
- }
|