from shared.cookingState import CookingStates import shared.config as config class MicrowaveStateFields: STATE = "state" PAUSED = "paused" COOKING_STATE = "cooking_state" COOKING_ESTIMATED_REMAINING_TIME = "cooking_estimated_remaining_time" COOKING_START_TIME = "cooking_start_time" class MicrowaveState: state = None paused = False cooking_state = None cooking_estimated_remaining_time = 0 cooking_start_time = 0 def __init__(self, id, on_change_callback=None): self.friendly_name = f"Microwave-{id}" self.state = MicrowaveState.IDLE self.cooking_state = CookingStates.IDLE self.on_change_callback = on_change_callback def _notify_change(self, field: MicrowaveStateFields = None): """Invokes callback if registered on state attribute changes.""" if self.on_change_callback: try: self.on_change_callback(self, field) except Exception as e: print(f"[MicrowaveState] Error in change callback: {e}") def set_state(self, new_state): if config.DEBUG: assert new_state in ( MicrowaveState.IDLE, MicrowaveState.ANALYZING, MicrowaveState.WAITING_FOR_CLOUD, MicrowaveState.COOKING, MicrowaveState.DONE, MicrowaveState.ALERT, ), f"Invalid state: {new_state}" if self.state != new_state: self.state = new_state self._notify_change(MicrowaveStateFields.STATE) def set_paused(self, is_paused): if self.paused != is_paused: self.paused = is_paused self._notify_change(MicrowaveStateFields.PAUSED) def toggle_pause(self): self.set_paused(not self.paused) def set_cooking_state(self, new_cooking_state): if config.DEBUG: assert new_cooking_state in ( CookingStates.IDLE, CookingStates.COOKING, CookingStates.DONE, CookingStates.STIRRING_REQUIRED, CookingStates.ALERT ), "Invalid cooking state: " + str(new_cooking_state) if self.cooking_state != new_cooking_state: if self.cooking_state == CookingStates.COOKING and new_cooking_state == CookingStates.DONE: self.set_state(MicrowaveState.DONE) self.cooking_state = new_cooking_state self._notify_change(MicrowaveStateFields.COOKING_STATE) def set_cooking_estimated_remaining_time(self, time_seconds): if self.cooking_estimated_remaining_time != time_seconds: self.cooking_estimated_remaining_time = time_seconds self._notify_change(MicrowaveStateFields.COOKING_ESTIMATED_REMAINING_TIME) def set_cooking_start_time(self, start_time): if self.cooking_start_time != start_time: self.cooking_start_time = start_time self._notify_change(MicrowaveStateFields.COOKING_START_TIME) def to_dict(self): return { "friendly_name": self.friendly_name, "state": self.state, "paused": self.paused, "cooking_estimated_remaining_time": self.cooking_estimated_remaining_time, "cooking_start_time": self.cooking_start_time } IDLE = "IDLE" # Microwave is empty ANALYZING = "ANALYZING" # Reading sensors & waiting for IR WAITING_FOR_CLOUD = "WAITING_FOR_CLOUD" # Waiting for API parameters COOKING = "COOKING" # Microwave is active DONE = "DONE" # Finished/Stopped, waiting for dish removal ALERT = "ALERT" # Alert state, waiting for user action