thermal: van-thermal daemon (CPU+NVMe monitor, alert, log)
Single sysfs sample loop drives three jobs off one daemon (modeled on van-failover): - live state at /run/van-thermal/state.json; new Cockpit "Temperatures" card reads it in the existing 5s loop (no per-refresh `sensors` shell-out) - journal alerts on ok<->warn<->crit crossings, with clear_margin hysteresis - throttled, self-rotating CSV history at /var/log/van-thermal.csv Sensors resolved by hwmon name+label (coretemp/Package id 0, nvme/Composite), never by hwmonN index (not stable across boots). Defaults: CPU warn 80 / crit 95, NVMe warn 65 / crit 70. deploy.sh installs + enables the service. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
35466f0141
commit
ef6c1ce182
@@ -66,6 +66,37 @@ function renderAP(ap) {
|
||||
document.getElementById("ap").innerHTML = html;
|
||||
}
|
||||
|
||||
/* ---------- Temperatures (van-thermal daemon state) ---------- */
|
||||
|
||||
async function readThermal() {
|
||||
try {
|
||||
return JSON.parse(await run(["cat", "/run/van-thermal/state.json"]));
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function renderThermal(th) {
|
||||
const el = document.getElementById("thermal");
|
||||
if (!th || !th.sensors) {
|
||||
el.innerHTML = `<p class="muted">van-thermal daemon not running (no state file).</p>`;
|
||||
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>`;
|
||||
Object.keys(th.sensors).forEach(name => {
|
||||
const s = th.sensors[name];
|
||||
const temp = s.temp == null ? "—" : `${esc(s.temp)} °C`;
|
||||
const lvl = s.level || "ok";
|
||||
html += `<tr><td>${esc(name.toUpperCase())}</td><td>${temp}</td>` +
|
||||
`<td><span class="pill ${pillClass[lvl] || ""}">${esc(lvl)}</span></td>` +
|
||||
`<td class="muted">${esc(s.warn)} / ${esc(s.crit)} °C</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>`;
|
||||
el.innerHTML = html;
|
||||
}
|
||||
|
||||
/* ---------- WAN failover (van-failover daemon state) ---------- */
|
||||
|
||||
async function readFailover() {
|
||||
@@ -194,8 +225,9 @@ async function restartAP() {
|
||||
|
||||
async function refresh() {
|
||||
try {
|
||||
const [ap, fo, wan] = await Promise.all([readAP(), readFailover(), readWAN()]);
|
||||
const [ap, th, fo, wan] = await Promise.all([readAP(), readThermal(), readFailover(), readWAN()]);
|
||||
renderAP(ap);
|
||||
renderThermal(th);
|
||||
renderFailover(fo);
|
||||
renderWAN(wan);
|
||||
document.getElementById("updated").textContent = "updated " + new Date().toLocaleTimeString();
|
||||
|
||||
Reference in New Issue
Block a user