diff --git a/client/brewpi_gui.py b/client/brewpi_gui.py index 0995e7e..4cb15fb 100755 --- a/client/brewpi_gui.py +++ b/client/brewpi_gui.py @@ -722,6 +722,9 @@ class Window(QtWidgets.QMainWindow, Ui_MainWindow): self.sud_state = None self.sud_user_message = None self._close_confirm_dialog() + for w in (self.Slider_temp_soll, self.doubleSpinBox_heatrate_soll, + self.Slider_pwr_soll, self.Slider_speed_soll): + w.setEnabled(True) # ambient_temp (the server's last echoed reading, shown in the # status bar) is no longer trustworthy, but the spinbox itself is # a client-owned setting (see closeEvent()/connect()) - leave it @@ -912,16 +915,13 @@ class Window(QtWidgets.QMainWindow, Ui_MainWindow): if 'Temp' in submsg: self.plot_temp_soll = submsg['Temp'] self.lcdNumber_temp_soll.display(f'{submsg["Temp"]:.1f}') - if self.slider_temp_soll_initial_update: - # blockSignals: setValue() here is just syncing the - # slider's display to the server's current value, not - # a user edit - without this it would also fire - # valueChanged and echo the value straight back as a - # command. + sud_running = self.sud_state in SUD_RUNNING_STATES + if self.slider_temp_soll_initial_update or sud_running: self.Slider_temp_soll.blockSignals(True) self.Slider_temp_soll.setValue(int(round(submsg['Temp']))) self.Slider_temp_soll.blockSignals(False) - self.slider_temp_soll_initial_update = False + if not sud_running: + self.slider_temp_soll_initial_update = False if 'Rate' in submsg: subsubmsg = submsg['Rate'] for subkey in subsubmsg: @@ -929,11 +929,13 @@ class Window(QtWidgets.QMainWindow, Ui_MainWindow): self.plot_rate_soll = subsubmsg['Current'] self.lcdNumber_heatrate_soll.display(f'{subsubmsg["Current"]:.1f}') if "Set" in subkey: - if self.heatrate_soll_initial_update: - self.heatrate_soll_initial_update = False + sud_running = self.sud_state in SUD_RUNNING_STATES + if self.heatrate_soll_initial_update or sud_running: self.doubleSpinBox_heatrate_soll.blockSignals(True) self.doubleSpinBox_heatrate_soll.setValue(subsubmsg['Set']) self.doubleSpinBox_heatrate_soll.blockSignals(False) + if not sud_running: + self.heatrate_soll_initial_update = False if "Ist" in key: submsg = msg['Ist'] if 'Temp' in submsg: @@ -949,6 +951,10 @@ class Window(QtWidgets.QMainWindow, Ui_MainWindow): if "PowerSet" in key: self.plot_power_set = msg['PowerSet'] self.lcdNumber_power_heater.display(msg['PowerSet']) + if self.sud_state in SUD_RUNNING_STATES: + self.Slider_pwr_soll.blockSignals(True) + self.Slider_pwr_soll.setValue(int(round(msg['PowerSet']))) + self.Slider_pwr_soll.blockSignals(False) elif "Power" in key: self.plot_power_eff = msg['Power'] self.lcdNumber_power_pot.display(msg['Power']) @@ -977,11 +983,13 @@ class Window(QtWidgets.QMainWindow, Ui_MainWindow): if "Speed" in key: self.stirrer_speed_ist = msg['Speed'] self._update_step_plates() - if self.slider_speed_initial_update: + sud_running = self.sud_state in SUD_RUNNING_STATES + if self.slider_speed_initial_update or sud_running: self.Slider_speed_soll.blockSignals(True) self.Slider_speed_soll.setValue(int(round(msg['Speed']))) self.Slider_speed_soll.blockSignals(False) - self.slider_speed_initial_update = False + if not sud_running: + self.slider_speed_initial_update = False elif "Capabilities" in key: submsg = msg['Capabilities'] if "Power" in submsg: @@ -1008,6 +1016,10 @@ class Window(QtWidgets.QMainWindow, Ui_MainWindow): elif "State" in key: prev_state = self.sud_state self.sud_state = msg['State'] + running = self.sud_state in SUD_RUNNING_STATES + for w in (self.Slider_temp_soll, self.doubleSpinBox_heatrate_soll, + self.Slider_pwr_soll, self.Slider_speed_soll): + w.setEnabled(not running) if self.sud_state in SUD_RUNNING_STATES and self.sud_elapsed_seconds is None: self.sud_elapsed_seconds = 0.0 diff --git a/web/app.js b/web/app.js index 72ccce5..569bb14 100644 --- a/web/app.js +++ b/web/app.js @@ -526,6 +526,10 @@ function onHeaterChanged(msg) { heaterPowerSoll = msg.PowerSet; document.getElementById('lcd-power-soll').textContent = msg.PowerSet; updateFireVisualization(); + if (RUNNING_STATES.has(sudState)) { + document.getElementById('heater-power').value = msg.PowerSet; + document.getElementById('heater-power-readout').textContent = msg.PowerSet; + } } else if (key === 'Power') { heaterPowerIst = msg.Power; document.getElementById('lcd-power-ist').textContent = msg.Power; @@ -548,10 +552,11 @@ function onStirrerChanged(msg) { for (const key of Object.keys(msg)) { if (key === 'Speed') { stirrerSpeedIst = msg.Speed; - if (initialSpeedSync) { + const sudRunningSpd = RUNNING_STATES.has(sudState); + if (initialSpeedSync || sudRunningSpd) { document.getElementById('stirrer-speed').value = msg.Speed; document.getElementById('stirrer-speed-readout').textContent = msg.Speed; - initialSpeedSync = false; + if (!sudRunningSpd) initialSpeedSync = false; } updateStirrerVisualization(); updateStepPlates(); @@ -571,9 +576,10 @@ function onTempCtrlChanged(msg) { if ('Temp' in soll) { plotTempSoll = soll.Temp; document.getElementById('lcd-temp-soll').textContent = soll.Temp.toFixed(1); - if (initialTempSollSync) { + const sudRunning = RUNNING_STATES.has(sudState); + if (initialTempSollSync || sudRunning) { document.getElementById('temp-soll').value = Math.round(soll.Temp); - initialTempSollSync = false; + if (!sudRunning) initialTempSollSync = false; } document.getElementById('temp-soll-readout').textContent = document.getElementById('temp-soll').value; updatePotVisualization(); @@ -583,9 +589,10 @@ function onTempCtrlChanged(msg) { if ('Current' in rate) { document.getElementById('lcd-rate-soll').textContent = rate.Current.toFixed(1); } - if ('Set' in rate && initialHeatrateSync) { + const sudRunningHr = RUNNING_STATES.has(sudState); + if ('Set' in rate && (initialHeatrateSync || sudRunningHr)) { document.getElementById('heatrate-soll').value = rate.Set; - initialHeatrateSync = false; + if (!sudRunningHr) initialHeatrateSync = false; } } } @@ -635,6 +642,10 @@ function onSudChanged(msg) { } wasRunning = isRunningNow; sudState = newState; + const sliderDisabled = RUNNING_STATES.has(sudState); + for (const id of ['temp-soll', 'heatrate-soll', 'heater-power', 'stirrer-speed']) { + document.getElementById(id).disabled = sliderDisabled; + } if (newState === WAIT_USER_STATE && prevState !== WAIT_USER_STATE && sudUserMessage) { showUserMessage(sudUserMessage); } else if (prevState === WAIT_USER_STATE && newState !== WAIT_USER_STATE) { @@ -740,6 +751,10 @@ function connect() { ws = ws_; statusEl.textContent = 'Connecting…'; ws.onopen = () => { + initialPowerSync = true; + initialSpeedSync = true; + initialHeatrateSync = true; + initialTempSollSync = true; setConnected(true); for (const channel of CHANNELS) { ws.send(JSON.stringify({'+': channel})); @@ -754,7 +769,12 @@ function connect() { statusEl.textContent = `Could not connect to ${url}`; statusEl.className = 'status-disconnected'; }; - ws.onclose = () => setConnected(false); + ws.onclose = () => { + for (const id of ['temp-soll', 'heatrate-soll', 'heater-power', 'stirrer-speed']) { + document.getElementById(id).disabled = false; + } + setConnected(false); + }; ws.onmessage = (event) => { const msg = JSON.parse(event.data); for (const channel of Object.keys(msg)) {