diff --git a/server/brewpi.py b/server/brewpi.py index e5e2001..83e5823 100755 --- a/server/brewpi.py +++ b/server/brewpi.py @@ -145,6 +145,8 @@ if __name__ == '__main__': tc.set_on_changed("y", heater_task.actor) # HeaterTask owns TC enable: enabled in closed-loop mode, disabled in open-loop. heater_task.set_on_closed_loop_changed(tc.set_enabled) + # Brew end (DONE/IDLE): shut heater off and broadcast open-loop/power-0 to clients. + sud_task.set_on_end(heater_task.shutdown) # Assign temp. sensor readings to tc sensor_task.set_on_changed("temp", ChangedFloat(tc.set_theta_ist, prec=2).set) diff --git a/tasks/heater.py b/tasks/heater.py index 3511b27..09b4e07 100755 --- a/tasks/heater.py +++ b/tasks/heater.py @@ -24,6 +24,16 @@ class HeaterTask(ATask): def set_on_closed_loop_changed(self, callback): self._on_closed_loop_changed = callback + 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.""" + self.closed_loop = False + self.power_soll = 0 + if self._on_closed_loop_changed: + self._on_closed_loop_changed(False) + asyncio.create_task(self.send({'ClosedLoop': False})) + self.power_set_changed(0) + def actor(self, y): self.power_actor = max(0, self.device.get_power_max() * y) diff --git a/tasks/sud.py b/tasks/sud.py index cc9c5de..6c86e64 100644 --- a/tasks/sud.py +++ b/tasks/sud.py @@ -110,6 +110,7 @@ class SudTask(ATask): # Saved on pause so resume can restore the effective setpoint even # when the current step has temperature=None (inherits from a prior step). self._paused_temp_soll = None + self._on_end = None msg_handler.set_recv_handler(self.recv) def apply_plant_params(self, grain_mass, water_mass): @@ -217,12 +218,17 @@ class SudTask(ATask): 'WaitForUser': step.get('user_wait_for_continue', False) if step else None, }})) + def set_on_end(self, callback): + self._on_end = callback + def on_state_changed(self, value): asyncio.create_task(self.send({'State': str(value)})) if value in (SudState.DONE, SudState.IDLE): self.stirrer.set_duty_cycle(1.0) self.stirrer.set_speed(0) + if self._on_end: + self._on_end() def on_user_message_changed(self, value): asyncio.create_task(self.send({'UserMessage': value}))