Following on from my pizza oven alarm post, I thought it was worth writing up some of the other home automations I have been running. Some of these have been in place for years, others are more recent additions. A few rely on MacroDroid — an Android automation app — working in tandem with Home Assistant via webhooks.

Arriving Home After Dark

When I arrive home after dark, the front door lights turn on at full brightness for ten minutes, then automatically switch off again.

Home Assistant does have its own presence detection, but I found it was too slow — often I would already be in the house by the time it registered that I had arrived. Using MacroDroid on the phone gives a much faster response, because it can combine two triggers: entering a GPS geofence around the house, or connecting to the home Wi-Fi network. Either one will fire the macro. The combination means it typically triggers before I have even reached the driveway.

Before doing anything, the macro checks two conditions. First, it must be after sunset — no point turning on lights in daylight. Second, a stopwatch that resets each time the macro fires must have been running for at least eight minutes. That second check prevents repeated triggering if the phone briefly drops off the Wi-Fi and reconnects, or drifts in and out of the geofence boundary.

If both conditions are satisfied, the macro makes an HTTP PUT request to a Home Assistant webhook. On the HA side, this triggers an automation that turns on the front door lights at full brightness and starts a ten-minute timer. When the timer finishes, a second automation turns the lights back off.

There is also a “leaving home” automation that turns off the lights when both adults have left the home zone, so there is no risk of them being left on all day.

The MacroDroid-to-HA webhook pattern is something I use in a few places. It lets me use the phone’s location and connectivity awareness — things MacroDroid handles very well — whilst leaving the actual smart home control to Home Assistant.

MacroDroid macro: The triggers are “Enter geofence: Home” and “Wi-Fi SSID in range: [your home SSIDs]”. The constraints are “After sunset” and “Stopwatch ‘Got home’ > 8 minutes”. The actions reset the stopwatch then make an HTTP PUT to the HA webhook URL.

Home Assistant automations:

# Turn on front door lights when arriving home after dark
- alias: Arrived Home After Dark
  triggers:
    - trigger: webhook
      webhook_id: "arrived-home-after-dark"
      allowed_methods: [PUT]
  actions:
    - action: light.turn_on
      target:
        area_id: front_door
      data:
        brightness_pct: 100
    - action: timer.start
      target:
        entity_id: timer.arrived_home
      data:
        duration: "00:10:00"

# Turn lights off when the timer finishes
- alias: Arrived Home Complete
  triggers:
    - trigger: event
      event_type: timer.finished
      event_data:
        entity_id: timer.arrived_home
  actions:
    - action: light.turn_off
      target:
        area_id: front_door

# Turn off front door lights when everyone has left the house
- alias: Leaving Home
  triggers:
    - trigger: zone
      entity_id: person.adult_1
      zone: zone.home
      event: leave
    - trigger: zone
      entity_id: person.adult_2
      zone: zone.home
      event: leave
  conditions:
    - condition: not
      conditions:
        - condition: zone
          entity_id: person.adult_1
          zone: zone.home
    - condition: not
      conditions:
        - condition: zone
          entity_id: person.adult_2
          zone: zone.home
  actions:
    - action: light.turn_off
      target:
        area_id: front_door

Children’s Bedroom Lights

Both children have loft beds with bright LED strips underneath. The LEDs are wired via smart switches that Home Assistant can control, but the only physical remote in each room is for the main ceiling light.

Rather than fitting extra remotes or switches, I set up automations that follow the main light’s brightness. When the main light is turned up above a high brightness threshold, the under-bed LEDs switch on. When the main light drops below a lower threshold — or is turned off entirely — they switch off. The gap between the two thresholds acts as a deadband, preventing the LEDs from flickering while someone is slowly adjusting the brightness.

The end result is that one remote effectively controls both the overhead light and the under-bed task lighting, without the children needing to think about it at all.

# Example for one child's room — repeat with different entities for the other
- alias: Set Child Bedroom Under-Bed Light
  triggers:
    - trigger: state
      entity_id: light.bedroom_main_light
      attribute: brightness
    - trigger: state
      entity_id: light.bedroom_main_light
  actions:
    - choose:
        - conditions:
            - condition: numeric_state
              entity_id: light.bedroom_main_light
              attribute: brightness
              above: 190
          sequence:
            - action: light.turn_on
              target:
                entity_id: light.bedroom_under_bed
        - conditions:
            - condition: or
              conditions:
                - condition: numeric_state
                  entity_id: light.bedroom_main_light
                  attribute: brightness
                  below: 100
                - condition: state
                  entity_id: light.bedroom_main_light
                  state:
                    - "off"
                    - unavailable
                    - unknown
          sequence:
            - action: light.turn_off
              target:
                entity_id: light.bedroom_under_bed

Note that HA represents brightness on a scale of 0–255, so above: 190 corresponds to roughly 75% brightness and below: 100 to roughly 40%.

The TV

Sharing Links from the Phone

One of my favourite automations is being able to share a link from my phone directly to the living room TV.

Home Assistant’s companion app registers itself as a share target on Android. When you share a URL to it, HA fires a mobile_app.share event containing the URL. An automation picks this up and checks whether the URL is a YouTube link using a regular expression. If it is, it extracts the video ID and launches the YouTube app on the TV at that specific video, rather than opening a browser. If the URL is not a YouTube link, it opens the TV’s built-in browser at that address instead.

The TV has a kids lock enabled, which requires a PIN before content will play. A parallel sequence handles this automatically: two seconds after launching the app (to give it time to open and show the PIN prompt), it sends the PIN digits as individual button presses to the TV, followed by Enter.

The whole thing means I can be reading something on my phone, tap Share, select Home Assistant, and it is playing on the TV within a few seconds.

- alias: Share to TV
  triggers:
    - trigger: event
      event_type: mobile_app.share
  actions:
    - if:
        - condition: template
          value_template: >
            {{ trigger.event.data.url | regex_match(
              '^(?:https?:\/\/)?(?:www\.|m\.)?(?:youtube\.com\/(?:watch\?v=|shorts\/)|youtu\.be\/)([0-9A-Za-z_-]{11}).*'
            ) }}
      then:
        - variables:
            vID: >
              {{ trigger.event.data.url | regex_replace(
                '^(?:https?:\/\/)?(?:www\.|m\.)?(?:youtube\.com\/(?:watch\?v=|shorts\/)|youtu\.be\/)([0-9A-Za-z_-]{11}).*$',
                'v=\1'
              ) }}
        - parallel:
            - action: webostv.command
              data:
                entity_id: media_player.living_room_tv
                command: system.launcher/launch
                payload:
                  id: youtube.leanback.v4
                  contentId: "{{ vID }}"
            - sequence:
                - delay: "00:00:02"
                - action: webostv.button
                  data:
                    entity_id: media_player.living_room_tv
                    button: "1"  # Replace these four digits with your PIN
                - action: webostv.button
                  data:
                    entity_id: media_player.living_room_tv
                    button: "2"
                - action: webostv.button
                  data:
                    entity_id: media_player.living_room_tv
                    button: "3"
                - action: webostv.button
                  data:
                    entity_id: media_player.living_room_tv
                    button: "4"
                - action: webostv.button
                  data:
                    entity_id: media_player.living_room_tv
                    button: ENTER
      else:
        - parallel:
            - action: webostv.command
              data:
                entity_id: media_player.living_room_tv
                command: system.launcher/open
                payload:
                  target: "{{ trigger.event.data.url }}"
            - sequence:
                - delay: "00:00:02"
                - action: webostv.button
                  data:
                    entity_id: media_player.living_room_tv
                    button: "1"
                - action: webostv.button
                  data:
                    entity_id: media_player.living_room_tv
                    button: "2"
                - action: webostv.button
                  data:
                    entity_id: media_player.living_room_tv
                    button: "3"
                - action: webostv.button
                  data:
                    entity_id: media_player.living_room_tv
                    button: "4"
                - action: webostv.button
                  data:
                    entity_id: media_player.living_room_tv
                    button: ENTER

Notification When the TV Is Turned On

This one started as a parenting tool. When the TV is turned on, Home Assistant sends a notification to any adult who is currently at home, telling them what time it came on and offering a “Turn Off” button. The check for whether each adult is home is there to avoid spamming someone who is out at work with notifications they cannot act on. Tapping the button fires a separate automation that turns the TV off via the media player integration.

The idea was to make it obvious to the children that we would always know if they had turned the TV on without permission. These days they are well aware the notification exists, which is arguably just as effective as it ever was.

- alias: TV Is On
  triggers:
    - trigger: device
      device_id: your_tv_device_id
      domain: media_player
      type: turned_on
  actions:
    - if:
        - condition: zone
          entity_id: person.adult_1
          zone: zone.home
      then:
        - action: notify.mobile_app_adult_1_phone
          data:
            title: TV is on
            message: "Someone turned on the TV at {{ now().strftime('%H:%M') }}"
            data:
              notification_icon: mdi:television
              actions:
                - action: TURN_OFF_TV
                  title: Turn Off
    - if:
        - condition: zone
          entity_id: person.adult_2
          zone: zone.home
      then:
        - action: notify.mobile_app_adult_2_phone
          data:
            title: TV is on
            message: "Someone turned on the TV at {{ now().strftime('%H:%M') }}"
            data:
              notification_icon: mdi:television
              actions:
                - action: TURN_OFF_TV
                  title: Turn Off

- alias: Turn Off TV via Notification
  triggers:
    - trigger: event
      event_type: mobile_app_notification_action
      event_data:
        action: TURN_OFF_TV
  actions:
    - action: media_player.turn_off
      target:
        entity_id: media_player.living_room_tv

Bluetooth Headphone Battery in Home Assistant

Home Assistant does a good job of tracking battery levels for devices — mobile phones, sensors, remote controls — but Bluetooth audio devices are a notable gap. There is no standard way for the Home Assistant mobile companion app to poll the battery level of a connected headset.

The solution uses MacroDroid on the phone. Android broadcasts a system intent (android.bluetooth.device.action.BATTERY_LEVEL_CHANGED) whenever a connected Bluetooth device reports a change in its battery level. MacroDroid can listen for system intents and extract values from the broadcast extras — in this case, the BATTERY_LEVEL extra is stored in a local variable.

The macro then POSTs that value as JSON to a Home Assistant webhook, but only when the value is not -1. Android uses -1 to indicate that the battery level is unknown or unavailable, so that constraint prevents spurious updates reaching HA.

On the Home Assistant side, the webhook automation reads the battery_level field from the JSON payload and writes it into an input_number helper. From there it appears on the dashboard alongside every other battery sensor.

MacroDroid macro: Trigger is “Intent received: android.bluetooth.device.action.BATTERY_LEVEL_CHANGED”, with the android.bluetooth.device.extra.BATTERY_LEVEL extra mapped to a local variable (e.g. bt_batt). The single action is an HTTP POST to the HA webhook with body {"battery_level": {lv=bt_batt}}, with a constraint that bt_batt != -1.

Home Assistant — helper and automation:

First, create an input_number helper for the battery level (this can also be done via the UI under Settings → Helpers):

input_number:
  headphone_battery:
    name: Headphone Battery
    min: 0
    max: 100
    step: 1
    unit_of_measurement: "%"
    icon: mdi:headphones

Then the automation to receive updates from the webhook:

- alias: Update Headphone Battery
  triggers:
    - trigger: webhook
      webhook_id: "headphone-battery-update"
      allowed_methods: [POST]
  actions:
    - action: input_number.set_value
      target:
        entity_id: input_number.headphone_battery
      data:
        value: "{{ trigger.json.battery_level }}"

I have many other simple automations for example turning lights on and off at set times, but the ones listed here are the more interesting ones I thought it would be worth sharing. I hope this can be of help or inspiration to someone else.