From 88988237aebd04b7d61bf6f5053ab24068fbce61 Mon Sep 17 00:00:00 2001 From: dlawler489 <104159223@student.swin.edu.au> Date: Thu, 17 Sep 2026 23:50:54 +1000 Subject: [PATCH] Don't let a busy printer's reports hold back spool sync; hide placeholder chamber temps MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A printer mid-print reports every second, and each report restarted the five-second wait, so a printing printer's spools never synced. Only a change in what's loaded restarts it now. Printers without a chamber sensor report 5 °C, which is no longer shown. Co-Authored-By: Claude Opus 5 --- lib/printerLive.js | 8 +++++++- public/app.js | 9 ++++++--- test/printerLive.test.js | 22 ++++++++++++++++++++++ 3 files changed, 35 insertions(+), 4 deletions(-) diff --git a/lib/printerLive.js b/lib/printerLive.js index b27fe01..645409e 100644 --- a/lib/printerLive.js +++ b/lib/printerLive.js @@ -34,6 +34,7 @@ function requestFullReport(c) { async function flushTrays(c) { clearTimeout(c.traysTimer); c.traysTimer = null; + c.pendingKey = null; const trays = allTrays(c); if (!c.ams && !c.external) return null; c.syncedKey = traysKey(trays); @@ -60,7 +61,11 @@ function handleMessage(c, payload) { if (Array.isArray(units) && units.every((u) => Array.isArray(u.tray))) c.ams = describeAms(units); if (p.vt_tray) c.external = describeTray(p.vt_tray, null); - if ((c.ams || c.external) && traysKey(allTrays(c)) !== c.syncedKey) { + // A printer mid-print reports every second or so, so only a change in what's + // loaded restarts the wait — otherwise the sync would never come round. + const key = (c.ams || c.external) ? traysKey(allTrays(c)) : null; + if (key && key !== c.syncedKey && key !== c.pendingKey) { + c.pendingKey = key; clearTimeout(c.traysTimer); c.traysTimer = setTimeout(() => flushTrays(c), TRAYS_SETTLE_MS); } @@ -82,6 +87,7 @@ function open(p) { ams: null, external: null, syncedKey: null, + pendingKey: null, lastSync: null, traysTimer: null, waiters: [], diff --git a/public/app.js b/public/app.js index fc35f86..bb2b26e 100644 --- a/public/app.js +++ b/public/app.js @@ -2747,7 +2747,10 @@ const temp = (now, target) => { return target ? `${t} / ${Math.round(target)} °C` : `${t} °C`; }; -function printerStatusHtml(snap) { +// These report a placeholder chamber temperature (5 °C) rather than a reading. +const NO_CHAMBER_SENSOR = ['A1 mini', 'A1', 'A2L', 'P1P', 'P1S']; + +function printerStatusHtml(snap, model) { if (!snap || !snap.live) { return '
Not connected Fill in the address, serial number and access code to connect.
'; } @@ -2778,7 +2781,7 @@ function printerStatusHtml(snap) { const temps = [ temp(s.nozzle, s.nozzleTarget) && `Nozzle ${temp(s.nozzle, s.nozzleTarget)}`, temp(s.bed, s.bedTarget) && `Bed ${temp(s.bed, s.bedTarget)}`, - s.chamber ? `Chamber ${temp(s.chamber)}` : null, + s.chamber > 5 && !NO_CHAMBER_SENSOR.includes(model) ? `Chamber ${temp(s.chamber)}` : null, ].filter(Boolean); if (temps.length) lines.push(`
${temps.map(escapeHtml).join(' · ')}
`); @@ -2808,7 +2811,7 @@ async function pollPrinters() { const snap = live[id]; const box = card.querySelector('.printer-status'); if (box) { - const html = printerStatusHtml(snap); + const html = printerStatusHtml(snap, card.querySelector('select[name="model"]').value); if (box.dataset.html !== html) { box.innerHTML = html; box.dataset.html = html; } } // A spool swap shows as soon as the printer reports it. diff --git a/test/printerLive.test.js b/test/printerLive.test.js index c994ed3..6ac4a01 100644 --- a/test/printerLive.test.js +++ b/test/printerLive.test.js @@ -61,6 +61,28 @@ test('live status merges partial reports, and a tray change syncs spools once', assert.equal(c.published.at(-1).body.pushing.command, 'pushall'); }); +test('a busy printer’s steady reports don’t hold back a spool sync', async (t) => { + t.mock.timers.enable({ apis: ['setTimeout'] }); + t.after(() => live.stopAll()); + clients.length = 0; + const synced = []; + live.setTraysHandler(async (id) => { synced.push(id); return {}; }); + live.reconcile([{ ...printerRow, id: 5, serial: 'SER5' }]); + const c = clients[0]; + c.connected = true; + c.emit('connect'); + c.emit('message', 't', report({ ams: { ams: [{ id: '0', tray: [tray(0, 'PLA', 'FF0000FF')] }] } })); + for (let i = 0; i < 10; i += 1) { + t.mock.timers.tick(1000); + c.emit('message', 't', report({ mc_percent: i })); + } + assert.equal(synced.length, 1, 'synced once, five seconds after the change'); + // The same trays again change nothing. + c.emit('message', 't', report({ ams: { ams: [{ id: '0', tray: [tray(0, 'PLA', 'FF0000FF')] }] } })); + t.mock.timers.tick(6000); + assert.equal(synced.length, 1); +}); + test('changing a printer’s code reopens its connection; removing it closes it', () => { clients.length = 0; live.reconcile([printerRow]);