Home Assistant: Notify when a light was left on and no one is at home

I'm using Home Asisstant for about a year now, and this is one of those things that I wanted to add for a long time, but have been postponing it. Until a few days ago, when I've arrived home and found out that one of the lights was on all day. Actually, after checking the Home Assistant log, it was my cat that triggered a motion sensor, that turned the light on (more about cats and motion sensors in a future post).

The basic idea here is that if I'm not at home for more than 30 minutes and a light is on (or turns on), I get a notification on my phone. For sending notifications from Home Assistant to my phone, I'm using the Pushbullet component.

I already had a group were I list all the controllable lights in the house and I wanted to be able to use this group directly in the automation, so I don't have to define every light in two separate places. Also, I want to be able to exclude some lights from triggering a notification (but I don't want to remove them from the group). Unfortunately, if I use the group directly as a trigger for the automation, the automation will fire when the group turns on, which happens when one light on the group turns on. Since I want to exclude some lights, those could already be on, thus automation would not fire if another light turns on after that. The solution, shared by user patrickeasters on the Home Assistant's Discord chat, is using YAML anchors! Those allow us to "copy" pieces of a YAML into another place in the same YAML. Below is an excerpt of the lights group. Notice the &lights_group_entities part! That is the YAML anchor which will be used in the automation.  

lights:
  name: Lights
  entities: &lights_group_entities
    - light.office_ceiling_1
    - light.office_ceiling_2
    - light.yeelight_desk_bulb
    - light.yeelight_desk_strip
    - switch.bedroom_strip
    - light.living_room_ceiling_r
    - light.living_room_ceiling_l
    - switch.kitchen_ceiling

Now, lets look at the automation:

- alias: Lights - Notify if no one home and lights are on
  trigger:
    - platform: state
      entity_id: binary_sensor.someone_home
      to: 'off'
      for:
        minutes: 30
    - platform: state
      entity_id: *lights_group_entities
      to: 'on'
  condition:
    condition: and
    conditions:
      - condition: state
        entity_id: binary_sensor.someone_home
        state: 'off'
        for:
          minutes: 30
      - condition: state
        entity_id: group.lights
        state: 'on'
  action:
    - service: python_script.notify_lights_on

This is a pretty simple automation with two state triggers: one when there is no one home for 30 minutes (using a template binary sensor that goes off when no one is home), and another when any light in the lights group turns on. This is where the YAML anchor is used, with the *lights_group_entities reference. The reference inserts the list of entities directly on the entity_id attribute, making the trigger look at each light's state individually. Since I only want to receive a notification when both conditions are met, I use the same two triggers as conditions, but here I can use the group's state.

Finally, the automation calls the notify_lights_on python_script. This script gets all lights from the lights group that are on, gets their friendly_name and uses Pushbullet to send a notification with them listed on it. The script also has a static list of lights that I don't mind leaving on while I'm away, ignoring them.


# check if any light is on (except those on the exclusion list), and send a notification with them

lights_group = 'group.lights'
excluded = ['light.yeelight_desk_bulb', 'light.yeelight_desk_strip']

entities_on = []
for entity_id in hass.states.get(lights_group).attributes['entity_id']:
    if hass.states.get(entity_id).state is 'on' and entity_id not in excluded:
        entities_on.append(hass.states.get(entity_id).attributes["friendly_name"])

if len(entities_on) > 0:
    notification_tilte = "Some lights are on - Home Assistant"
    notification_message = "The following lights are on: " + ', '.join(entities_on)

    hass.services.call('notify', 'pushbullet', {'title' : notification_tilte, 'message': notification_message})

Let me know if you have any questions, thoughts or suggestions for improvement!

Comments

Popular posts from this blog

Misadventures in Shaderland: the jumping uniform array element