fix: never re-enable SSID pool broadcast (crash guard) + top-bar health chip

Mode 'active' and the advertise toggle could re-enable the SSID-pool
broadcast that segfaults pineapd. active preset now skips ssidpool/enable
(advertise stays false), the advertise endpoint refuses with an
explanation when the pool is disabled, get_ap reports the real pool
state, and the PineAP overview disables the toggle with a notice. Added
a top-bar health chip (PINEAP OK / POOL OFF / PINEAPD DOWN) polled every
15s.
This commit is contained in:
2026-08-18 20:16:41 -05:00
parent 0cd9956c4c
commit d10fba9d1b
6 changed files with 69 additions and 13 deletions
@@ -434,6 +434,7 @@ const Live = (() => {
let ws = null;
let ever = false;
let poll = null;
let pollHealthTimer = null;
const subs = [];
let timer = null;
function stopPoll() {
@@ -442,6 +443,10 @@ const Live = (() => {
function start() {
if (ws && (ws.readyState === WebSocket.OPEN || ws.readyState === WebSocket.CONNECTING)) return;
stopPoll();
if (!pollHealthTimer) {
pollHealthTimer = setInterval(pollHealth, 15000);
pollHealth();
}
try { ws = new WebSocket(App.wsUrl('/api/ws')); }
catch (e) { fallback(); return; }
ws.onopen = () => { ever = true; };
@@ -489,6 +494,23 @@ const Live = (() => {
const el = document.getElementById('live-status');
if (el) el.textContent = 'BAT ' + (b.level == null ? '--' : b.level + '%' + (b.charging ? '+' : '')) + ' CLIENTS ' + n;
}
function pollHealth() {
fetch(API_BASE + '/api/health', { credentials: 'include' }).then((r) => r.json())
.then((h) => {
const el = document.getElementById('health-status');
if (!el) return;
if (h.pineap_up === false) {
el.textContent = 'PINEAPD DOWN';
el.className = 'health-chip bad';
} else if (h.pool_disabled) {
el.textContent = 'POOL OFF';
el.className = 'health-chip warn';
} else if (h.pineap_up) {
el.textContent = 'PINEAP OK';
el.className = 'health-chip good';
}
}).catch(() => {});
}
function onTick(fn) {
subs.push(fn);
return () => {