diff --git a/app/api.py b/app/api.py index 1b1a71b..45359bb 100644 --- a/app/api.py +++ b/app/api.py @@ -155,6 +155,51 @@ def get_status() -> dict: "schedule": get_schedule_status(), } +def get_effective_speed() -> int: + + if ( + schedule_service is not None + and schedule_service.override_active + and schedule_service.override_settings.speed is not None + ): + return schedule_service.override_settings.speed + + state = service.state + + if state is None: + raise HTTPException( + status_code=503, + detail={ + "message": "Tion state unavailable", + }, + ) + + return state.fan_speed + +def get_effective_temperature() -> int: + + if ( + schedule_service is not None + and schedule_service.override_active + and schedule_service.override_settings.target_temp is not None + ): + return ( + schedule_service + .override_settings + .target_temp + ) + + state = service.state + + if state is None: + raise HTTPException( + status_code=503, + detail={ + "message": "Tion state unavailable", + }, + ) + + return state.target_temp async def execute_command(operation, override: ScheduledSettings | None = None): @@ -231,6 +276,30 @@ def get_schedule_status() -> dict: current = resolution.current + current_time = ( + current.when.strftime("%H:%M") + if current is not None + else None + ) + + next_time = ( + resolution.next.when.strftime("%H:%M") + if resolution.next is not None + else None + ) + + next_action = ( + resolution.next.point.action.type.value + if resolution.next is not None + else None + ) + + override_until_time = ( + schedule_service.override_until.strftime("%H:%M") + if schedule_service.override_until + else None + ) + current_action = None if current is not None: @@ -240,7 +309,14 @@ def get_schedule_status() -> dict: "available": True, "enabled": resolution.enabled, "running": schedule_service.running, + "current_action": current_action, + "current_time": current_time, + + "next_time": next_time, + "next_action": next_action, + + "override_until_time": override_until_time, "current": occurrence_to_dict(resolution.current), "next": occurrence_to_dict(resolution.next), @@ -303,9 +379,31 @@ async def set_power(state: Literal["on", "off"]): # ---------------------------------------------------------------------- -# Fan speed +# Fan speed increase / decrease # ---------------------------------------------------------------------- +@app.post("/api/tion/speed/increase") +async def increase_speed(): + + current_speed = get_effective_speed() + + new_speed = min(current_speed + 1, MAX_FAN_SPEED) + + if new_speed == current_speed: + return get_status() + + return await execute_command( + lambda tion: + tion.set_speed(new_speed), + + ScheduledSettings( + speed=new_speed, + ), + ) + +# ---------------------------------------------------------------------- +# Fan speed +# ---------------------------------------------------------------------- @app.post("/api/tion/speed/{speed}") async def set_speed( speed: Annotated[ @@ -316,14 +414,32 @@ async def set_speed( ), ] ): - - return await execute_command( lambda tion: tion.set_speed(speed), ScheduledSettings(speed=speed), ) +@app.post("/api/tion/speed/decrease") +async def decrease_speed(): + + current_speed = get_effective_speed() + + new_speed = max(current_speed - 1, MIN_FAN_SPEED) + + if new_speed == current_speed: + return get_status() + + return await execute_command( + lambda tion: + tion.set_speed(new_speed), + + ScheduledSettings( + speed=new_speed, + ), + ) + + # ---------------------------------------------------------------------- # Heater # ---------------------------------------------------------------------- @@ -344,6 +460,52 @@ async def set_heater(state: Literal["on", "off"]): ScheduledSettings(heater=enabled), ) +# ---------------------------------------------------------------------- +# Target temperature increase / decrease +# ---------------------------------------------------------------------- + +@app.post("/api/tion/temperature/increase") +async def increase_temperature(): + + current_temperature = get_effective_temperature() + + new_temperature = min(current_temperature + 1, MAX_TARGET_TEMP) + + if new_temperature == current_temperature: + return get_status() + + return await execute_command( + lambda tion: + tion.set_target_temperature( + new_temperature + ), + + ScheduledSettings( + target_temp=new_temperature, + ), + ) + + +@app.post("/api/tion/temperature/decrease") +async def decrease_temperature(): + + current_temperature = get_effective_temperature() + + new_temperature = max(current_temperature - 1, MIN_TARGET_TEMP) + + if new_temperature == current_temperature: + return get_status() + + return await execute_command( + lambda tion: + tion.set_target_temperature( + new_temperature + ), + + ScheduledSettings( + target_temp=new_temperature, + ), + ) # ---------------------------------------------------------------------- # Target temperature