use std::fs;
use std::path::PathBuf;
#[derive(Clone)]
pub struct HwmonSensor {
pub path: PathBuf,
pub name: String,
}
pub fn find_cpu_hwmon_sensors() -> anyhow::Result<Vec<HwmonSensor>> {
let mut sensors = Vec::new();
for entry in fs::read_dir("/sys/class/hwmon")? {
let entry = entry?;
let path = entry.path();
if !path.is_dir() {
continue;
}
let name = path.file_name().and_then(|n| n.to_str()).unwrap_or("");
let hwmon_name_path = path.join("name");
let hwmon_name = fs::read_to_string(&hwmon_name_path).ok();
if let Some(ref name_str) = hwmon_name {
if name_str.contains("coretemp") || name_str.contains("cpu") {
let sensor = HwmonSensor {
path: path.clone(),
name: name_str.clone(),
};
sensors.push(sensor);
continue;
}
}
let temp_input_path = path.join("temp1_input");
if temp_input_path.exists() {
let sensor = HwmonSensor {
path: path.clone(),
name: hwmon_name.unwrap_or_else(|| name.to_string()),
};
sensors.push(sensor);
}
}
sensors.sort_by(|a, b| {
if a.name.contains("coretemp") {
std::cmp::Ordering::Less
} else if b.name.contains("coretemp") {
std::cmp::Ordering::Greater
} else {
a.name.cmp(&b.name)
}
});
Ok(sensors)
}
#[derive(Debug, Clone)]
pub struct HwmonTempData {
pub id: u32,
pub name: String,
pub temperature: f32,
}
pub fn read_hwmon_temperatures(sensor: &HwmonSensor) -> anyhow::Result<Vec<HwmonTempData>> {
let mut temps = Vec::new();
let mut id = 1;
loop {
let temp_label = sensor.path.join(format!("temp{}_label", id));
let temp_input = sensor.path.join(format!("temp{}_input", id));
if !temp_input.exists() {
break;
}
let temp_name = if temp_label.exists() {
fs::read_to_string(&temp_label)
.ok()
.and_then(|s| {
let s = s.trim().to_string();
if s.is_empty() { None } else { Some(s) }
})
.unwrap_or(format!("temp{}", id))
} else {
format!("temp{}", id)
};
let value = fs::read_to_string(&temp_input)?;
let temperature = value.trim().parse::<f32>()? / 1000.0;
temps.push(HwmonTempData {
id,
name: temp_name,
temperature,
});
id += 1;
}
Ok(temps)
}
pub fn get_tj_max() -> f32 {
let cpuinfo_path = "/proc/cpuinfo";
if let Ok(content) = fs::read_to_string(cpuinfo_path) {
for line in content.lines() {
if line.starts_with("cpu M") && line.contains("TjMax") {
if let Some(value_str) = line.split(':').nth(1) {
if let Ok(value) = value_str.trim().parse::<f32>() {
return value;
}
}
}
}
}
100.0
}