Some hardware links on this page are affiliate links. As an Amazon Associate I earn from qualifying purchases. We may earn a commission if you buy through them, at no extra cost to you. See the affiliate disclosure.
A bathroom fan that should run 07:00–08:30 on weekdays is a clock problem, not an “on means 30 minutes” problem. This workflow turns a switch, light, or fan on at a time you pick, off at a later time, and only on the days you tick. An optional timer helper tracks the remaining minutes until the scheduled off so a dashboard ring stays honest after a wall-switch override or a Home Assistant restart.
Entity ids are blueprint inputs. Do not publish a live plug name.
This is not relay auto-off timer. That pack starts a duration when you turn the device on. This pack owns the daily window; the timer is a display and a recovery aid, not the schedule itself.
What problem it solves
You want “this load is on between two clock times, on these days,” with a visible countdown, without the timer restarting from a full duration when someone flips the switch at 08:10, and without forgetting the off after a reboot.
How it works
- Clock triggers — two time triggers (
on_time,off_time). Each run checks today’s weekday against seven boolean inputs (Mon–Sun, default all on). Uncheck a day and that day’s on/off do nothing. Uncheck every day and the schedule is paused (same as disabling the automation). - Scheduled on — if today is enabled,
homeassistant.turn_onthe device. If a timer helper is configured,timer.startwith duration = seconds from now untiloff_time(not a fixed 30 minutes). - Scheduled off —
homeassistant.turn_off.timer.cancelif the helper is still active. - Manual / mid-window on — a state trigger on the device going
onoutside the clock trigger. If we are still inside today’s window (after on, before off, day enabled), start the timer with the remaining time untiloff_time. A 07:00–08:30 fan flipped on at 08:10 gets twenty minutes, not ninety. - Manual off — device goes
off→timer.cancel. The clock off later is a no-op if the device is already off. - Restart — a
homeassistantstart trigger. If the device is on, today is enabled, and now is still inside the window, sync the timer to the remaining seconds. The timer helper must have Restore enabled so a mid-countdown reboot still has a remaining time; the start trigger covers the case where the device stayed on but the timer did not. - Timer idle — if the optional timer expires (active → idle, not a cancel), turn the device off. That is the safety net for a missed clock-off after a restart.
Overnight windows (on 22:00, off 06:00) wrap midnight the same way quiet-hours packs do: “after on or before off” instead of a naive after/before pair.
Do not also put an ESPHome off_delay or a second daily time automation on the same entity. Two owners fight.
Hardware notes
- Any HA switch, light, or fan. A smart plug, a GPIO relay already adopted, a ceiling fan entity. The pack does not care about the transport.
- Timer helper. Optional. Create it with Restore on (
Settings → Devices & services → Helpers, orrestore: truein YAML). Skip it if you only want the clock and do not need a dashboard ring. - No extra hub. If the entity already toggles in HA, this is a blueprint and (optionally) one helper.
Snippet
The pack ships a blueprint. Inputs replace real entity ids:
trigger:
- platform: time
at: !input on_time
id: clock_on
- platform: time
at: !input off_time
id: clock_off
- platform: state
entity_id: !input target_device
to: "on"
id: device_on
- platform: state
entity_id: !input target_device
to: "off"
id: device_off
- platform: homeassistant
event: start
id: ha_start
- platform: state
entity_id: !input off_timer
from: active
to: idle
id: timer_expired
action:
- variables:
day_ok: >
{{ {0: monday, 1: tuesday, 2: wednesday, 3: thursday,
4: friday, 5: saturday, 6: sunday}[now().weekday()] }}
remain_s: >
{{ [((off_clock - now().strftime('%H:%M:%S')) | as_timedelta).total_seconds(),
0] | max | int }}
- choose:
- conditions:
- condition: trigger
id: clock_on
- condition: template
value_template: "{{ day_ok }}"
sequence:
- service: homeassistant.turn_on
target:
entity_id: !input target_device
- service: timer.start
target:
entity_id: !input off_timer
data:
duration:
seconds: "{{ remain_s }}"
- conditions:
- condition: trigger
id: clock_off
sequence:
- service: homeassistant.turn_off
target:
entity_id: !input target_device
- service: timer.cancel
target:
entity_id: !input off_timer
# mid-window manual on, restart sync, timer-expired off: full blueprint in the pack
Timer helper (restore is the reboot-safe part):
timer:
daily_schedule:
name: Daily schedule remaining
duration: "01:30:00"
restore: true
Setup outline
- Confirm the switch / light / fan toggles from HA. Optionally create a timer helper with Restore on.
- Import the blueprint. Fill the device, on time, off time, weekday ticks, and the optional timer.
- Wait for the next on-time (or set times a few minutes ahead). Confirm: device on, timer showing time-until-off — not a canned duration.
- Test the edges: flip on mid-window → remaining, not full length; flip off early → timer cancelled; restart HA while in-window and on → timer resynced and still turns off at the clock; uncheck today → no clock on.
Troubleshooting
- Never turns on. Today is unchecked, the automation is disabled, or you pointed at a
binary_sensorinstead of a switch. Weekday0is Monday in the pack. - Timer always starts at the full window. The mid-window path used
!input default_durationinstead of remaining-until-off. Use the pack’s remaining calculation. - Forgot to turn off after a reboot. Restore is off on the timer and the start trigger is missing. Enable both; a
delay:in an automation will not come back. - Manual off leaves the timer running. The device-off trigger is missing, or you used
timer.finish(that looks like an expiry and will bounce an off). Usetimer.cancel. - Overnight window never matches.
after/beforewithout wrap. Use the pack’s wrapping condition. - Two offs, or a chatter. Another daily time automation or an ESPHome
off_delayalso owns this entity. Pick one owner.
Credits
Based on the community blueprint Daily Time-Based Device Scheduler with Optional Timer. This write-up is an original overview of the weekday-filtered clock window with remaining-time timer sync.