thermal: watch NVMe/RP1 temps, fan stall, and undervoltage on the Pi 5
van-thermal grows sensor kinds beyond plain temperatures: "fan" alerts when pwmfan is commanded on (pwm > 0) but reads 0 RPM (warn on first sample, crit if it persists — 0 RPM with pwm 0 is just the firmware idling a cool SoC), and "undervolt" goes crit on the live rpi_volt alarm plus a sticky warn off the firmware's latched since-boot bit, so dips shorter than the 10s sample interval still surface once. All kinds share the existing hysteresis / journal / Pushover machinery (fan 🌀, undervolt ⚡). Config adds nvme Composite (65/70), rp1_adc (80/85 — the RP1 die drives all USB/eth I/O), fan, and undervolt to the existing cpu sensor. The CSV logger now derives per-kind columns and self-rotates when the header changes; the Cockpit Temps card renders RPM + pwm duty and undervoltage state alongside the temperatures. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
6fe683000d
commit
2da97d26f4
@@ -143,14 +143,26 @@ function renderThermal(th) {
|
||||
return;
|
||||
}
|
||||
const pillClass = { ok: "ok", warn: "warn", crit: "bad" };
|
||||
let html = `<table><thead><tr><th>Sensor</th><th>Temp</th><th>Status</th><th>Warn / Crit</th></tr></thead><tbody>`;
|
||||
let html = `<table><thead><tr><th>Sensor</th><th>Value</th><th>Status</th><th>Limits</th></tr></thead><tbody>`;
|
||||
Object.keys(th.sensors).forEach(name => {
|
||||
const s = th.sensors[name];
|
||||
const temp = s.temp == null ? "—" : `${esc(s.temp)} °C`;
|
||||
let value, limits;
|
||||
if (s.kind === "fan") {
|
||||
value = s.rpm == null ? "—" : `${esc(s.rpm)} RPM`;
|
||||
limits = s.pwm == null ? "—" : `pwm ${esc(s.pwm)}/255`;
|
||||
} else if (s.kind === "undervolt") {
|
||||
value = s.now == null ? "—"
|
||||
: s.now ? "undervoltage"
|
||||
: s.since_boot ? "dip since boot" : "ok";
|
||||
limits = "—";
|
||||
} else {
|
||||
value = s.temp == null ? "—" : `${esc(s.temp)} °C`;
|
||||
limits = `${esc(s.warn)} / ${esc(s.crit)} °C`;
|
||||
}
|
||||
const lvl = s.level || "ok";
|
||||
html += `<tr><td>${esc(name.toUpperCase())}</td><td>${temp}</td>` +
|
||||
html += `<tr><td>${esc(name.toUpperCase())}</td><td>${value}</td>` +
|
||||
`<td><span class="pill ${pillClass[lvl] || ""}">${esc(lvl)}</span></td>` +
|
||||
`<td class="muted">${esc(s.warn)} / ${esc(s.crit)} °C</td></tr>`;
|
||||
`<td class="muted">${limits}</td></tr>`;
|
||||
});
|
||||
html += `</tbody></table>`;
|
||||
html += `<p class="muted">History: <code>/var/log/van-thermal.csv</code> · alerts: <code>journalctl -u van-thermal</code></p>`;
|
||||
|
||||
Reference in New Issue
Block a user