Skip to content

Ideas and automations

What you can do with the entities and trackers, with examples to copy. Each example is a package: put the file into a packages folder next to configuration.yaml and add

homeassistant:
  packages: !include_dir_named packages

once, then restart. Or create the same automation in the editor (Settings, Automations, three dots, Edit in YAML) from the part below automation:. Replace rt2600ac and mr2200ac with your devices' entity ID prefixes, and notify.mobile_app_phone with your phone's notify action.

Presence: who is home

A tracker is home while the client is on the network, so a phone's tracker can make a person home or away: Settings, People, choose the person, and add the phone's tracker. The time until away in the options (3 minutes by default) keeps a phone that sleeps briefly from leaving.

Phones use a private Wi-Fi address that can change, and a changed address is a new client to the router. On an iPhone, iPad or Mac, set Private Wi-Fi Address of your home network to Fixed (or Off), not Rotating (Apple). Android phones have a similar per-network setting whose name depends on the maker, for example MAC address type.

Internet down, and for how long

# The internet is down for 2 minutes, and when it is back: for how long it was gone.
# Replace notify.mobile_app_phone with your phone's notify action; while the internet is down,
# a notification to a phone may not arrive, so the second automation reports afterwards.
automation:
  - alias: Internet down
    triggers:
      - trigger: state
        entity_id: binary_sensor.rt2600ac_wan_connection
        to: "off"
        for: {minutes: 2}
    actions:
      - action: persistent_notification.create
        data:
          title: Internet down
          message: "The router lost its WAN connection at {{ now().strftime('%H:%M') }}."
  - alias: Internet back
    triggers:
      - trigger: state
        entity_id: binary_sensor.rt2600ac_wan_connection
        from: "off"
        to: "on"
    actions:
      - action: notify.mobile_app_phone
        data:
          title: Internet back
          message: >
            Down for {{ ((as_timestamp(now()) - as_timestamp(trigger.from_state.last_changed))
            / 60) | round(0) | int }} minutes.

Public address changed

# The address the internet sees has changed, for example for a firewall rule elsewhere.
automation:
  - alias: Public IP changed
    triggers:
      - trigger: state
        entity_id: sensor.rt2600ac_public_ipv4_address
        not_from: [unknown, unavailable]
        not_to: [unknown, unavailable]
    actions:
      - action: notify.mobile_app_phone
        data:
          title: Public IP changed
          message: "{{ trigger.from_state.state }} → {{ trigger.to_state.state }}"

Behind carrier-grade NAT the public address is shared and changes without notice; see Entities.

Router or access point restarted

# The router or access point started again (planned or not).
automation:
  - alias: Router restarted
    triggers:
      - trigger: state
        entity_id: [sensor.rt2600ac_last_boot, sensor.mr2200ac_last_boot]
        not_from: [unknown, unavailable]
        not_to: [unknown, unavailable]
    actions:
      - action: notify.mobile_app_phone
        data:
          title: "{{ trigger.to_state.attributes.friendly_name }}"
          message: "Started at {{ as_datetime(trigger.to_state.state) | as_local }}."

An important device is offline

# An important device is gone for 10 minutes. Pick its tracker (Settings, Entities, filter
# device_tracker); the integration's time until away already ignores short dropouts.
automation:
  - alias: NAS offline
    triggers:
      - trigger: state
        entity_id: device_tracker.nas
        to: not_home
        for: {minutes: 10}
    actions:
      - action: notify.mobile_app_phone
        data:
          title: NAS offline
          message: "It left the network at {{ trigger.from_state.last_changed | as_local }}."

A device that barely talks to the router, for example a managed switch with a fixed address, can appear offline in SRM's client list although it works. For such devices, Home Assistant's Ping integration is the better source.

Weak Wi-Fi

# A device that should stay put has a weak Wi-Fi signal for 10 minutes; a hint to move it to the
# access point or to 5 GHz. SRM's signal is 0 to 100.
automation:
  - alias: Weak Wi-Fi
    triggers:
      - trigger: template
        value_template: "{{ (state_attr('device_tracker.living_room_tv', 'signal') or 100) < 30 }}"
        for: {minutes: 10}
    actions:
      - action: notify.mobile_app_phone
        data:
          title: Weak Wi-Fi
          message: >
            Living room TV: signal {{ state_attr('device_tracker.living_room_tv', 'signal') }}
            on {{ state_attr('device_tracker.living_room_tv', 'radio') }} at
            {{ state_attr('device_tracker.living_room_tv', 'connected_to') }}.

Clients per band

Three sensors that count the clients at home by band and cable; with their history you see how many still use 2.4 GHz.

# Clients at home per band, as sensors with history: how many still use 2.4 GHz in the evening?
template:
  - sensor:
      - name: Wi-Fi clients 2.4 GHz
        unique_id: wifi_clients_2_4_ghz
        state_class: measurement
        state: >
          {{ states.device_tracker | selectattr('state', 'eq', 'home')
             | selectattr('attributes.radio', 'eq', '2.4G') | list | count }}
      - name: Wi-Fi clients 5 GHz
        unique_id: wifi_clients_5_ghz
        state_class: measurement
        state: >
          {{ states.device_tracker | selectattr('state', 'eq', 'home')
             | selectattr('attributes.radio', 'in', ['5G', '5G-2']) | list | count }}
      - name: Wired clients
        unique_id: wired_clients
        state_class: measurement
        state: >
          {{ states.device_tracker | selectattr('state', 'eq', 'home')
             | selectattr('attributes.connection', 'eq', 'ethernet') | list | count }}

Data per day and month

# Downloaded data per day and month, estimated from the download rate (read every 30 seconds, so
# short bursts in between are missed). The integral adds up the rate over time in the rate's
# display unit (Mbit for Mbit/s, kB for kB/s, ...); the template turns any of them into GB; the
# utility meters reset daily and monthly.
sensor:
  - platform: integration
    name: Downloaded data raw
    unique_id: downloaded_data_raw
    source: sensor.rt2600ac_download_rate
    unit_time: s
    method: left
    round: 2
template:
  - sensor:
      - name: Downloaded data
        unique_id: downloaded_data
        device_class: data_size
        state_class: total_increasing
        unit_of_measurement: GB
        state: >
          {% set gb = {'bit': 1.25e-10, 'kbit': 1.25e-7, 'Mbit': 1.25e-4, 'Gbit': 0.125,
                       'B': 1e-9, 'kB': 1e-6, 'MB': 1e-3, 'GB': 1,
                       'KiB': 1.024e-6, 'MiB': 1.048576e-3, 'GiB': 1.073741824} %}
          {% set unit = state_attr('sensor.downloaded_data_raw', 'unit_of_measurement') %}
          {{ (states('sensor.downloaded_data_raw') | float(0) * gb[unit]) | round(3) }}
        availability: >
          {{ has_value('sensor.downloaded_data_raw') and state_attr('sensor.downloaded_data_raw',
             'unit_of_measurement') in ['bit', 'kbit', 'Mbit', 'Gbit', 'B', 'kB', 'MB', 'GB',
             'KiB', 'MiB', 'GiB'] }}
utility_meter:
  downloaded_today:
    name: Downloaded today
    source: sensor.downloaded_data
    cycle: daily
  downloaded_this_month:
    name: Downloaded this month
    source: sensor.downloaded_data
    cycle: monthly

The examples are tested: the demo instance loads them at every start.