diff --git a/button.py b/button.py index fcf513d..a8cc170 100644 --- a/button.py +++ b/button.py @@ -54,6 +54,10 @@ class Button(Mqtt): if action == 'single': state = self.get_state(self.args['ref_entity']) kwargs = {'kwargs': {'cause': f'button single click: toggle while {state}'}} + + if manual_entity := self.args.get('manual_mode'): + self.set_state(entity_id=manual_entity, state='off') + if state == 'on': self.app.deactivate(**kwargs) else: diff --git a/model.py b/model.py index 92f5007..ef3b1fd 100644 --- a/model.py +++ b/model.py @@ -49,7 +49,7 @@ class ControllerStateConfig(BaseModel): elevation: Optional[float] = None direction: Optional[Annotated[SunDirection, BeforeValidator(str_to_direction)]] = None off_duration: Optional[OffDuration] = None - scene: dict[str, State] + scene: dict[str, State] | str @root_validator(pre=True) def check_args(cls, values): @@ -68,6 +68,8 @@ class RoomControllerConfig(BaseModel): states: List[ControllerStateConfig] = Field(default_factory=list) off_duration: Optional[OffDuration] = None sleep_state: Optional[ControllerStateConfig] = None + rich: Optional[str] = None + manual_mode: Optional[str] = None @classmethod def from_yaml(cls: Self, yaml_path: Path) -> Self: @@ -86,12 +88,15 @@ class RoomControllerConfig(BaseModel): collapse_padding=True, ) for state in self.states: - scene_json = state.to_apply_kwargs() - lines = [ - f'{name:20}{state["state"]} Brightness: {state["brightness"]:<4} Temp: {state["color_temp"]}' - for name, state in scene_json['entities'].items() - ] - table.add_row(state.time.strftime('%I:%M:%S %p'), '\n'.join(lines)) + if isinstance(state, str): + pass + elif isinstance(state, dict): + scene_json = state.to_apply_kwargs() + lines = [ + f'{name:20}{state["state"]} Brightness: {state.get("brightness", ""):<4} Temp: {state.get("color_temp", "")}' + for name, state in scene_json['entities'].items() + ] + table.add_row(state.time.strftime('%I:%M:%S %p'), '\n'.join(lines)) yield table def sort_states(self): diff --git a/room_control.py b/room_control.py index ab6df81..33f7d5e 100755 --- a/room_control.py +++ b/room_control.py @@ -76,7 +76,7 @@ class RoomController(Hass, Mqtt): Parsed states have an absolute time for the current day. """ # re-parse the state strings into times for the current day - self._room_config = RoomControllerConfig(**self.args) + self._room_config = RoomControllerConfig.model_validate(self.args) self.log(f'{len(self._room_config.states)} states in the app configuration', level='DEBUG') for state in self._room_config.states: @@ -150,6 +150,12 @@ class RoomController(Hass, Mqtt): else: return False + def manual_mode(self) -> bool: + if manual_entity := self.args.get('manual_mode'): + return self.get_state(manual_entity) == 'on' + else: + return False + # @sleep_bool.setter # def sleep_bool(self, val) -> bool: # if (sleep_var := self.args.get('sleep')): @@ -213,7 +219,7 @@ class RoomController(Hass, Mqtt): def activate_any_on(self, *args, **kwargs): """Activate if any of the entities are on. Args and kwargs are passed directly to self.activate()""" - if self.any_on(): + if self.any_on() and not self.manual_mode(): self.activate(*args, **kwargs) else: self.log('Skipped activating - everything is off')