Skip to content

sfox38/time_off

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

39 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Time Off ⏳

A Powerful Auto-Off Timer for Home Assistant

Time Off is a lightweight, local-push integration that solves the "I forgot to turn it off" problem once and for all. It adds a set of timer controls and sensors directly into the control panel of your selected devices, so you can manage countdowns without writing a single line of YAML.


Eliminates Helper Fatigue

In standard Home Assistant setups, creating a simple auto-off timer usually requires:

  1. Creating a Timer Helper
  2. Writing an Automation to start the timer when the device turns on
  3. Writing a Second Automation to turn the device off when the timer finishes

This leads to a cluttered Helpers list and disconnected logic — a timer named timer.fan_1 living in a separate menu from the fan itself, with no obvious link between them.

Time Off changes the workflow:

  • Tethered Logic: The timer, controls, and sensors all live inside the device itself.
  • No More Ghost Helpers: Everything is created and named automatically based on the device it's controlling.
  • One-Step Setup: No YAML or multi-step automations required. Just add the integration, pick your device, and set a duration.

Universal Functionality

Time Off is device-aware. It automatically detects the type of device you are controlling and sends the correct command when the timer expires:

Device Type Action on Expiry
Lights / Fans / Switches / Media Players / Humidifiers / Sirens homeassistant.turn_off
Covers (Gates / Blinds) cover.close_cover
Valves valve.close_valve
Vacuums vacuum.return_to_base

Template entities, Groups, and Helpers are also fully supported.


Installation

Manual

  1. Download the time_off zip archive from this repository and unpack it.
  2. Copy the time_off folder into your custom_components/ directory.
  3. Restart Home Assistant.
  4. Go to Settings → Devices & Services → Add Integration and search for Time Off.

HACS (Recommended)

  1. Open HACS.
  2. Click the three dots (top right) → Custom repositories.
  3. Paste https://github.com/sfox38/time_off and select Integration as the category.
  4. Click Download, then restart Home Assistant.

Upgrading from Time Off version 1

This new version of Time Off has several breaking changes. It is recommended you remove Time Off from all your devices before you upgrade to this version. If you do not, you may find disabled/ghost entities on your device page which you will have to manually delete.

Note

If you used automations or scripts in conjunction with the previous version of Time Off, please review this documentation for breaking changes.


Adding Devices

Once installed, Time Off appears in your Integrations panel.

  1. Click Add Service (or the + icon) to add a new device.
  2. Select your device from the dropdown and click Submit.
  3. You will be taken to the device's control page where the Time Off entities will appear.

Templates, Groups, and Helpers: Since these device types usually lack a dedicated Device page, Time Off automatically creates one containing only the Time Off entities.

Note

By default, adding Time Off to a device will not affect its behaviour. You must set Time Off to a value greater than 0 to activate the timer.


Entities

Time Off adds the following entities to your device:

Time Off

number.[device]_time_off

The default timer duration. This is the value that Off After is set to each time the device turns on.

  • Unit: Minutes (supports 0.1 increments for 6-second precision).
  • Set to 0 to disable the timer entirely.
  • Survives restarts — if HA restarts while the timer is running, the countdown resumes automatically. If the timer expired during the shutdown, the device will be turned off (or the expired event fired) immediately on restart.

Time Off Trigger Only

switch.[device]_trigger_only

Controls how Time Off behaves when the timer expires.

State Behaviour
Off (default) Time Off turns the device off automatically.
On Time Off fires the event only — the device is left alone.

In both cases the time_off_timer_expired event is fired. In Trigger Only mode the timer loops continuously, firing the event on each cycle, until the device is turned off or time_off.stop_timer is called.

Timer Active

binary_sensor.[device]_timer_active

Indicates whether a countdown is currently in progress.

  • Visible in the Sensor section of the device card.
  • State: on while counting down, off when idle.
  • Attributes:
    • expiry — the exact timestamp when the timer will finish.
    • remaining — a human-readable countdown string (e.g. 2m 30s).

Off After

sensor.[device]_off_after

A sensor showing the active countdown duration currently in use. This value is taken from the Time Off entity each time your device is turned on.

  • Visible in the Diagnostic section of the device card.
  • Can be changed via the time_off.set_off_after service (see Services) without affecting the Time Off default.
    • Your device must already be on in order for any change to take effect.
    • The timer will immediately restart with the new duration when this value is changed.
    • Setting this value to 0 will immediately stop the timer and fire a time_off_timer_expired event.
  • When your device is turned off this value will reset to 0.

Services

time_off.start_timer

Manually starts or restarts the timer for a managed device. It uses the value from Time Off for the timer duration.

Important

The entity_id must be the managed device (e.g. fan.bathroom_fan, light.porch_light) — not the Time Off entity.

action: time_off.start_timer
data:
  entity_id: fan.bathroom_fan

time_off.stop_timer

Stops the active timer immediately. Does not turn the device off and does not fire the time_off_timer_expired event.

Important

The entity_id must be the managed device (e.g. fan.bathroom_fan, light.porch_light) — not the Time Off entity.

action: time_off.stop_timer
data:
  entity_id: fan.bathroom_fan

time_off.set_off_after

Immediately restarts the timer with a specific duration without changing the Time Off default.

Use this to start a countdown with a duration that differs from the Time Off default. Since automations can not change the value of Off After directly — set_off_after is the sole mechanism. start_timer by contrast always starts the countdown from the Time Off default, so it cannot be used to inject a custom duration.

This distinction is what makes the Trigger Only looping pattern so powerful: Time Off holds the initial, default, duration (e.g. 20 minutes), while set_off_after injects a shorter recheck duration (e.g. 5 minutes) for subsequent cycles — without permanently altering the 20-minute default. Thus when the device is turned on again, the timer duration is taken from Time Off - 20 minutes.

If minutes is 0, the timer stops immediately rather than restarting.

Important

The entity_id must be the managed device (e.g. fan.bathroom_fan, light.porch_light) — not the Off After sensor or other Time Off entity.

action: time_off.set_off_after
data:
  entity_id: fan.bathroom_fan
  minutes: 30

Events

time_off_timer_expired

Fired when the timer reaches zero. In Trigger Only mode this fires on every loop cycle.

Payload:

Field Description
entity_id The managed device entity ID (e.g. fan.bathroom_fan)
device_id The Time Off config entry ID

Note

You only need entity_id to filter or act on an event. It is unlikely you will need to use device_id directly. In general, automations written against entity IDs are more readable, portable, and easier to debug than those written against device IDs.

trigger: event
event_type: time_off_timer_expired
event_data:
  entity_id: fan.bathroom_fan

Sample Use Cases

Porch Light — Simple Auto-Off

Set Time Off to 4 minutes. The light turns off automatically after 4 minutes every time it's switched on. No coding required.

If you want to also trigger a notification when the light turns off:

alias: Porch Light - Turned Off Notification
description: "Notify when the porch light timer expires"
mode: single
triggers:
  - trigger: device
    domain: time_off
    device_id: light.porch_light
    type: timer_expired
actions:
  - action: notify.mobile_app
    data:
      message: "Porch light has been turned off automatically."

Front Gate — Auto-Close

Set Time Off to 2 minutes. As soon as the gate opens, the timer starts. After 2 minutes it closes automatically. No coding required.

If you also want a warning notification before the gate closes:

alias: Front Gate - Pre-Close Warning
description: "Notify 30 seconds before the gate closes"
mode: single
triggers:
  - trigger: state
    entity_id: binary_sensor.gate_timer_active
    to: "on"
actions:
  - delay: "00:01:30"
  - action: notify.mobile_app
    data:
      message: "Front gate closing in 30 seconds."

Bathroom Fan — Humidity-Aware Shutoff

Set Time Off to 20 minutes and enable Time Off Trigger Only. Use the time_off_timer_expired event to trigger a humidity check — if humidity is still high, let the fan keep running; otherwise turn it off.

alias: Shower Fan Off (Humidity Check)
description: "Only turns off the fan if humidity is below 30%"
mode: single
triggers:
  - trigger: device
    domain: time_off
    device_id: fan.bathroom_fan
    type: timer_expired
actions:
  - if:
      - condition: numeric_state
        entity_id: sensor.bathroom_humidity
        below: 30
    then:
      - action: time_off.stop_timer
        data:
          entity_id: fan.bathroom_fan
      - action: fan.turn_off
        target:
          entity_id: fan.bathroom_fan
    else:
      - action: time_off.start_timer
        data:
          entity_id: fan.bathroom_fan

Porch Light — Presence-Aware Shutoff

The porch light turns on for 20 minutes (Time Off = 20, Trigger Only = On). When the first timer expires, switch to 5-minute rechecks scanning two mmWave sensors. The light stays on as long as presence is detected, then turns off cleanly once the area is clear.

alias: Porch Light - Presence-Aware Shutoff
description: >
  After the initial 20-minute period, recheck every 5 minutes for presence. 
  Turn off the light only when both mmWave sensors report clear.
mode: single
triggers:
  - trigger: device
    domain: time_off
    device_id: light.porch_light
    type: timer_expired
actions:
  - if:
      - condition: or
        conditions:
          - condition: state
            entity_id: binary_sensor.porch_mmwave_1
            state: "on"
          - condition: state
            entity_id: binary_sensor.porch_mmwave_2
            state: "on"
    then:
      # Presence detected — set Off After to 5 minutes before for the next cycle.
      # Trigger Only mode restarts the timer automatically, so no explicit timer restart is needed.
      - action: time_off.set_off_after
        data:
          entity_id: light.porch_light
          minutes: 5
    else:
      # No presence — turn off the light. The timer stops itself automatically.
      - action: light.turn_off
        target:
          entity_id: light.porch_light

Note

Set Time Off to 20 and Time Off Trigger Only to On on the device card. On the first expiry the automation sets Off After to 5 minutes — Trigger Only mode immediately restarts the timer and picks up the new value for the next cycle. This continues every 5 minutes until no presence is detected and the light is turned off.


Advanced Notes

  • Trigger Only loop: In Trigger Only mode the timer fires the time_off_timer_expired event and immediately restarts. This continues until the device is manually turned off or time_off.stop_timer is called. Each cycle reads the current Off After value, so you can change the duration mid-loop via time_off.set_off_after.

  • Restart recovery: Timer state is persisted to .storage/time_off.timers. On restart, Time Off waits up to 30 seconds for all managed entities to report their state before resuming countdowns. If a timer expired during the shutdown window, the appropriate action (turn off or fire event) is taken immediately on startup.

  • Manual stop is clean: Calling time_off.stop_timer cancels the countdown, clears the persisted expiry, and fires time_off_cache_updated — but does not turn the device off and does not fire time_off_timer_expired.

  • Multiple devices: Each device gets its own independent instance. Timers run in parallel with no shared state between devices.

  • Template entities: Fully supported. Template fans, lights, and switches work identically to physical devices.

About

Time Off : A powerful "Auto-Off" timer for Home Assistant devices

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Languages