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]);