diff --git a/components/actor/heater_hendi.py b/components/actor/heater_hendi.py index 8454b11..efdfdad 100755 --- a/components/actor/heater_hendi.py +++ b/components/actor/heater_hendi.py @@ -23,13 +23,11 @@ class HeaterHendi(AHeater): def connect(self): ok = self.hendi.connect() self.connected = ok - self.firmware_version = self.hendi.sw_ver if ok else None return ok def disconnect(self): self.hendi.disconnect() self.connected = False - self.firmware_version = None def activate(self, enable): if not self.connected: diff --git a/components/actor/stirrerpololu1376.py b/components/actor/stirrerpololu1376.py index b809740..f49cb08 100644 --- a/components/actor/stirrerpololu1376.py +++ b/components/actor/stirrerpololu1376.py @@ -23,13 +23,11 @@ class StirrerPololu1376(AStirrer): def connect(self): ok = self.drv.connect() self.connected = ok - self.firmware_version = self.drv.firmware_version if ok else None return ok def disconnect(self): self.drv.disconnect() self.connected = False - self.firmware_version = None @contextmanager def remote_open(self): diff --git a/components/connectable.py b/components/connectable.py index bb68045..a9fb036 100644 --- a/components/connectable.py +++ b/components/connectable.py @@ -4,16 +4,15 @@ from utils.value import AttributeChange class Connectable(AttributeChange): """Observable hardware-connection state shared by AHeater/AStirrer. - Simulated devices are always connected and report no firmware version; - real (serial) devices start disconnected and only flip once connect() - actually reaches the hardware. + Simulated devices are always connected; real (serial) devices start + disconnected and only flip once connect() actually reaches the + hardware. """ def __init__(self, simulated): AttributeChange.__init__(self) self.simulated = simulated self.connected = simulated - self.firmware_version = None def connect(self): return self.connected diff --git a/tasks/heater.py b/tasks/heater.py index cd23415..ed67cef 100755 --- a/tasks/heater.py +++ b/tasks/heater.py @@ -21,7 +21,6 @@ class HeaterTask(ATask): self._on_connected_changed = None device.set_on_changed('power_eff', ChangedInteger(self.on_changed_power).set) device.set_on_changed('connected', self.on_connected_changed) - device.set_on_changed('firmware_version', self.on_firmware_version_changed) self.power_set_changed = ChangedInteger(self.on_changed_power_set).set def set_on_closed_loop_changed(self, callback): @@ -38,9 +37,6 @@ class HeaterTask(ATask): if self._on_connected_changed: self._on_connected_changed(value) - def on_firmware_version_changed(self, value): - fire_and_forget(self.send({'FirmwareVersion': value})) - def shutdown(self): """Called when the brew ends (DONE/IDLE). Switches to open-loop at power 0 and disables TC, mirroring what a Stop press should do.""" @@ -125,7 +121,6 @@ class HeaterTask(ATask): # fire and a freshly-subscribed client would never learn it's # connected. await self.send({'Connected': self.device.connected}) - await self.send({'FirmwareVersion': self.device.firmware_version}) with self.device.open(): while True: diff --git a/tasks/stirrer.py b/tasks/stirrer.py index f32c3c7..ed847d9 100644 --- a/tasks/stirrer.py +++ b/tasks/stirrer.py @@ -16,7 +16,6 @@ class StirrerTask(ATask): stirrer_device.set_on_changed("dutyCycle", self.on_dutycycle_changed) stirrer_device.set_on_changed("cycleTime", self.on_cycletime_changed) stirrer_device.set_on_changed("connected", self.on_connected_changed) - stirrer_device.set_on_changed("firmware_version", self.on_firmware_version_changed) def on_speed_changed(self, value): asyncio.create_task(self.send({'Speed': value})) @@ -38,9 +37,6 @@ class StirrerTask(ATask): if self._on_connected_changed: self._on_connected_changed(value) - def on_firmware_version_changed(self, value): - fire_and_forget(self.send({'FirmwareVersion': value})) - async def recv(self, data): for pair in data.items(): if pair[0] == 'Connect': @@ -69,7 +65,6 @@ class StirrerTask(ATask): # for why a simulated device's connect() alone doesn't fire the # observer. await self.send({'Connected': self.device.connected}) - await self.send({'FirmwareVersion': self.device.firmware_version}) with self.device.open(): while True: diff --git a/web/app.js b/web/app.js index 50d14d8..7988307 100644 --- a/web/app.js +++ b/web/app.js @@ -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', () => { diff --git a/web/index.html b/web/index.html index d793444..2b7c72d 100644 --- a/web/index.html +++ b/web/index.html @@ -38,7 +38,10 @@