use crate::RubbleResult;
use clap::Args;
use clap::ValueEnum;
use handlebars::JsonValue;
use serde_json::json;
use std::error::Error;
use std::thread;
use std::time::Duration;
use systemstat::{Platform, System};
#[derive(Args)]
pub struct DeviceArgs {
pub selector: SystemStats,
}
#[derive(Copy, Clone, ValueEnum)]
pub enum SystemStats {
CPU,
LoadAvg,
Temp,
BootTime,
Battery,
}
impl SystemStats {
pub fn default_format(&self) -> &'static str {
match self {
SystemStats::CPU => "{{total}}%",
SystemStats::LoadAvg => "{{load_avg_1}}, {{load_avg_5}}, {{load_avg_15}}",
SystemStats::Temp => "{{temp}}",
SystemStats::BootTime => "{{boot_time}}",
SystemStats::Battery => "{{charge}}%",
}
}
pub fn formatting_strings(&self) -> &'static str {
match self {
SystemStats::CPU => "total user nice system interrupt",
SystemStats::LoadAvg => "load_avg_1 load_avg_5 load_avg_15",
SystemStats::Temp => "temp",
SystemStats::BootTime => "boot_time",
SystemStats::Battery => "charge time_remaining",
}
}
pub fn to_result(&self) -> RubbleResult {
let sys = System::new();
let r = match self {
SystemStats::CPU => cpu_stat(sys),
SystemStats::LoadAvg => load_avg(sys),
SystemStats::Temp => temp(sys),
SystemStats::BootTime => boot_time(sys),
SystemStats::Battery => battery(sys),
};
RubbleResult::new(r, self.default_format())
}
}
fn battery(sys: System) -> Result<JsonValue, Box<dyn Error>> {
match sys.battery_life() {
Ok(battery) => Ok(json!({
"charge": battery.remaining_capacity * 100.0,
"time_remaining": format!(
"{}h{}m",
battery.remaining_time.as_secs() / 3600,
battery.remaining_time.as_secs() % 60
)
})),
Err(e) => Err(e.into()),
}
}
fn cpu_stat(sys: System) -> Result<JsonValue, Box<dyn Error>> {
match sys.cpu_load_aggregate() {
Ok(cpu) => {
thread::sleep(Duration::from_secs(1));
let cpu = cpu.done().unwrap();
let u = cpu.user * 100.00;
let n = cpu.nice * 100.00;
let s = cpu.system * 100.00;
let i = cpu.interrupt * 100.00;
let t = u + n + s + i;
Ok(json!({ "total": t, "user": u, "nice": n, "system": s, "interrupt": i }))
}
Err(e) => Err(e.into()),
}
}
fn load_avg(sys: System) -> Result<JsonValue, Box<dyn Error>> {
match sys.load_average() {
Ok(loadavg) => Ok(json!({
"load_avg_1": loadavg.one,
"load_avg_5": loadavg.five,
"load_avg_15": loadavg.fifteen,
})),
Err(e) => Err(e.into()),
}
}
fn temp(sys: System) -> Result<JsonValue, Box<dyn Error>> {
match sys.cpu_temp() {
Ok(cpu_temp) => Ok(json!({ "temp": cpu_temp })),
Err(e) => Err(e.into()),
}
}
fn boot_time(sys: System) -> Result<JsonValue, Box<dyn Error>> {
match sys.boot_time() {
Ok(boot_time) => Ok(json!({ "boot_time": boot_time.to_string() })),
Err(x) => Err(x.into()),
}
}