nova-shell/stats-daemon/src/temp.rs

77 lines
2 KiB
Rust

use std::collections::HashMap;
use std::fs;
use std::io::Write;
#[derive(Debug)]
pub struct ThermalDevice {
pub name: String,
pub celsius: i32,
}
pub fn read_thermal_devices() -> Vec<ThermalDevice> {
let mut by_name: HashMap<String, i32> = HashMap::new();
for i in 0.. {
let temp_path = format!("/sys/class/thermal/thermal_zone{i}/temp");
let type_path = format!("/sys/class/thermal/thermal_zone{i}/type");
let Ok(temp_str) = fs::read_to_string(&temp_path) else {
break;
};
let millic: i32 = match temp_str.trim().parse() {
Ok(v) => v,
Err(_) => continue,
};
let celsius = millic / 1000;
let name = fs::read_to_string(&type_path)
.map_or_else(|_| format!("zone{i}"), |s| s.trim().to_string());
// Keep the highest temp seen for each device type
let entry = by_name.entry(name).or_insert(celsius);
if celsius > *entry {
*entry = celsius;
}
}
let mut devices: Vec<ThermalDevice> = by_name
.into_iter()
.map(|(name, celsius)| ThermalDevice { name, celsius })
.collect();
// Sort descending by temp so the hottest shows first
devices.sort_by(|a, b| b.celsius.cmp(&a.celsius));
devices
}
pub fn emit_temp(out: &mut impl Write) {
let devices = read_thermal_devices();
if devices.is_empty() {
return;
}
let max = devices.iter().map(|d| d.celsius).max().unwrap_or(0);
let devices_json: Vec<String> = devices
.iter()
.map(|d| {
format!(
"{{\"name\":{},\"celsius\":{}}}",
json_str(&d.name),
d.celsius
)
})
.collect();
let _ = writeln!(
out,
"{{\"type\":\"temp\",\"celsius\":{max},\"devices\":[{}]}}",
devices_json.join(",")
);
}
fn json_str(s: &str) -> String {
let escaped = s.replace('\\', "\\\\").replace('"', "\\\"");
format!("\"{escaped}\"")
}