redbear-info: Add thermal, fan, and C-state health dashboard items
Reads from /scheme/acpi/thermal/, /scheme/acpi/fan/, and /scheme/acpi/cstates/ plus /scheme/sys/cstate_policy to populate the --health dashboard with hardware thermal status, fan activity, and CPU power-management state.
This commit is contained in:
@@ -2859,6 +2859,76 @@ fn collect_health_items(runtime: &Runtime, report: &Report<'_>) -> Vec<HealthIte
|
||||
},
|
||||
});
|
||||
|
||||
let thermal_zones = runtime.read_dir_names("/scheme/acpi/thermal").unwrap_or_default();
|
||||
if !thermal_zones.is_empty() {
|
||||
let temps: Vec<String> = thermal_zones
|
||||
.iter()
|
||||
.filter_map(|zone| {
|
||||
read_trimmed(runtime, &format!("/scheme/acpi/thermal/{zone}/temperature"))
|
||||
})
|
||||
.collect();
|
||||
let avg_temp = temps.iter().filter_map(|t| t.parse::<f64>().ok()).sum::<f64>()
|
||||
/ temps.len().max(1) as f64;
|
||||
let state = if avg_temp > 85.0 {
|
||||
HealthState::Critical
|
||||
} else if avg_temp > 70.0 {
|
||||
HealthState::Warning
|
||||
} else {
|
||||
HealthState::Healthy
|
||||
};
|
||||
items.push(HealthItem {
|
||||
label: "Thermal",
|
||||
state,
|
||||
detail: format!("{} zone(s), avg {:.1}°C", thermal_zones.len(), avg_temp),
|
||||
});
|
||||
} else {
|
||||
items.push(HealthItem {
|
||||
label: "Thermal",
|
||||
state: HealthState::Warning,
|
||||
detail: "no thermal zones".to_string(),
|
||||
});
|
||||
}
|
||||
|
||||
let fans = runtime.read_dir_names("/scheme/acpi/fan").unwrap_or_default();
|
||||
if !fans.is_empty() {
|
||||
let active = fans
|
||||
.iter()
|
||||
.filter(|fan| {
|
||||
read_trimmed(runtime, &format!("/scheme/acpi/fan/{fan}/status"))
|
||||
.map(|s| s == "on")
|
||||
.unwrap_or(false)
|
||||
})
|
||||
.count();
|
||||
items.push(HealthItem {
|
||||
label: "Fans",
|
||||
state: HealthState::Healthy,
|
||||
detail: format!("{} fan(s), {} active", fans.len(), active),
|
||||
});
|
||||
} else {
|
||||
items.push(HealthItem {
|
||||
label: "Fans",
|
||||
state: HealthState::Warning,
|
||||
detail: "no fan devices".to_string(),
|
||||
});
|
||||
}
|
||||
|
||||
let cstate_policy = read_trimmed(runtime, "/scheme/sys/cstate_policy");
|
||||
let cstates = runtime.read_dir_names("/scheme/acpi/cstates").unwrap_or_default();
|
||||
if !cstates.is_empty() {
|
||||
let max_policy = cstate_policy.as_deref().unwrap_or("unlimited");
|
||||
items.push(HealthItem {
|
||||
label: "C-states",
|
||||
state: HealthState::Healthy,
|
||||
detail: format!("{} processor(s), policy={}", cstates.len(), max_policy),
|
||||
});
|
||||
} else {
|
||||
items.push(HealthItem {
|
||||
label: "C-states",
|
||||
state: HealthState::Warning,
|
||||
detail: "no C-state surface".to_string(),
|
||||
});
|
||||
}
|
||||
|
||||
items
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user