refactor: drop firmware-version display, move Enable toggle to Controller

Firmware version is already printed to the log at connect() time
(HendiCtrl/Pololu1376) - remove the live GUI/websocket firmware
reporting entirely (Connectable, HeaterHendi/StirrerPololu1376,
Heater/StirrerTask, web GUI) as redundant.

Also move the Heater panel's Closed-loop checkbox into the Controller
panel and rename it "Enable" - the Controller panel now shows a
live Enabled (green) / Disabled (gray) status badge next to its
heading, matching the Connected/Disconnected badges on the Heater/
Stirrer panels.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YaPLuRPpyjWcwhMvCvpHCL
This commit is contained in:
2026-07-03 20:23:55 +02:00
co-authored by Claude Sonnet 5
parent 7377fe3b6b
commit 7b162cf1f5
8 changed files with 30 additions and 43 deletions
+23 -18
View File
@@ -45,10 +45,8 @@ let closedLoop = true;
// are always connected and never expose Connect/Disconnect (see
// updateDeviceStatus()).
let heaterConnected = false;
let heaterFirmware = null;
let heaterSimulated = null;
let stirrerConnected = false;
let stirrerFirmware = null;
let stirrerSimulated = null;
// Pot hardware config from server's Pot section - used for display before
@@ -536,15 +534,14 @@ function updateSudActions() {
document.getElementById('btn-sud-stop').disabled = !(running || paused);
}
// Shared by onHeaterChanged/onStirrerChanged - updates the status badge,
// firmware label, and Connect/Disconnect buttons for one device. Simulated
// devices are always connected and have nothing to connect/disconnect, so
// their buttons are hidden entirely rather than just disabled.
function updateDeviceStatus(prefix, isConnected, firmware, simulated) {
// Shared by onHeaterChanged/onStirrerChanged - updates the status badge
// and Connect/Disconnect buttons for one device. Simulated devices are
// always connected and have nothing to connect/disconnect, so their
// buttons are hidden entirely rather than just disabled.
function updateDeviceStatus(prefix, isConnected, simulated) {
const statusEl = document.getElementById(`${prefix}-status`);
statusEl.textContent = isConnected ? 'Connected' : 'Disconnected';
statusEl.className = `panel-status ${isConnected ? 'status-connected' : 'status-disconnected'}`;
document.getElementById(`${prefix}-firmware`).textContent = firmware ? `F/W ${firmware}` : '';
const connectBtn = document.getElementById(`btn-${prefix}-connect`);
const disconnectBtn = document.getElementById(`btn-${prefix}-disconnect`);
connectBtn.classList.toggle('hidden', !!simulated);
@@ -553,6 +550,15 @@ function updateDeviceStatus(prefix, isConnected, firmware, simulated) {
disconnectBtn.disabled = !isConnected;
}
// Reflects closedLoop (the Controller panel's Enable toggle) in the
// Controller heading's status badge - Enabled/green when the TC is
// driving the heater, Disabled/gray in open-loop.
function updateClosedLoopStatus() {
const statusEl = document.getElementById('closed-loop-status');
statusEl.textContent = closedLoop ? 'Enabled' : 'Disabled';
statusEl.className = `panel-status ${closedLoop ? 'status-connected' : 'status-disconnected'}`;
}
// Mirrors client/brewpi_gui.py's show_user_message(): the Sud is already
// blocked in WAIT_USER server-side - dismissing this dialog (OK or Escape,
// both fire the dialog's 'close' event) is what unblocks it.
@@ -632,6 +638,7 @@ function onHeaterChanged(msg) {
} else if (key === 'ClosedLoop') {
closedLoop = msg.ClosedLoop;
document.getElementById('closed-loop').checked = closedLoop;
updateClosedLoopStatus();
updateControlsEnabled();
} else if (key === 'Capabilities') {
const power = msg.Capabilities.Power;
@@ -641,15 +648,12 @@ function onHeaterChanged(msg) {
slider.max = power.Max;
} else if (key === 'Connected') {
heaterConnected = msg.Connected;
updateDeviceStatus('heater', heaterConnected, heaterFirmware, heaterSimulated);
updateDeviceStatus('heater', heaterConnected, heaterSimulated);
updateControlsEnabled();
updateSudActions();
} else if (key === 'FirmwareVersion') {
heaterFirmware = msg.FirmwareVersion;
updateDeviceStatus('heater', heaterConnected, heaterFirmware, heaterSimulated);
} else if (key === 'Simulated') {
heaterSimulated = msg.Simulated;
updateDeviceStatus('heater', heaterConnected, heaterFirmware, heaterSimulated);
updateDeviceStatus('heater', heaterConnected, heaterSimulated);
}
}
}
@@ -669,15 +673,12 @@ function onStirrerChanged(msg) {
slider.max = power.Max;
} else if (key === 'Connected') {
stirrerConnected = msg.Connected;
updateDeviceStatus('stirrer', stirrerConnected, stirrerFirmware, stirrerSimulated);
updateDeviceStatus('stirrer', stirrerConnected, stirrerSimulated);
updateControlsEnabled();
updateSudActions();
} else if (key === 'FirmwareVersion') {
stirrerFirmware = msg.FirmwareVersion;
updateDeviceStatus('stirrer', stirrerConnected, stirrerFirmware, stirrerSimulated);
} else if (key === 'Simulated') {
stirrerSimulated = msg.Simulated;
updateDeviceStatus('stirrer', stirrerConnected, stirrerFirmware, stirrerSimulated);
updateDeviceStatus('stirrer', stirrerConnected, stirrerSimulated);
}
}
}
@@ -751,6 +752,7 @@ function onSudChanged(msg) {
if (isRunningNow && !wasRunning) {
closedLoop = true;
document.getElementById('closed-loop').checked = true;
updateClosedLoopStatus();
sendMsg('Heater', {ClosedLoop: true});
// Accept the next Soll push from the server even if it
// arrives before sudRunning has gone true at this client
@@ -886,6 +888,7 @@ function connect() {
initialTempSollSync = true;
initialPotTempSync = true;
closedLoop = true;
updateClosedLoopStatus();
potConfig = {};
setConnected(true);
for (const channel of CHANNELS) {
@@ -937,6 +940,8 @@ document.getElementById('btn-connect').addEventListener('click', () => {
});
document.getElementById('closed-loop').addEventListener('change', (e) => {
closedLoop = e.target.checked;
updateClosedLoopStatus();
sendMsg('Heater', {ClosedLoop: e.target.checked});
});
document.getElementById('btn-heater-connect').addEventListener('click', () => {