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

I made an automation to detect when a light is on (or turns on) after I’m away for more than 30 minutes. It is nothing really advanced, but I think it provides a nice example.

The group with all my lights:

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

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

The python_script that checks the lights, ignores some of them, and sends a pretty notification:

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})

Hope it is useful for someone. More info here: https://ledstripsandcode.blogspot.com/2017/12/home-assistant-notify-when-light-was.html

11 Likes

So do you just use the python script for excluding some of the lights and sending the notification? i feel like with a little tinkering we could make it all just fit into the automation.

Yes. We could probably do it with templates in an automation, but it would result in a big and complex template. A python_script is easier to read and update if needed.

HI,

Nice, just learned about your config and seems close to what is was looking to achieve . checking state changes on Entities in a group.

Would this also go for groups within groups?

As it is i have several groups with lights, and i could create a all_lights group with these smaller groups as entity_id’s. As opposed to creating this all_lights group with all separate lights. Which by the way also is a ‘system’ group i believe (though that also contains other ‘light’ items that aren’t lights…) ?

Thanks,
Marius

I have something similar for my aircoditioner.
If AC is left on for 30 mins while no one is home, a notification is sent to all media players / Chromecast / Google homes stating that the AC is about to turn off.
Without intervention the AC turns off shortly after.
The script can be cancelled by toggling a lamp in the loungroom.

It will not work for groups inside a group. But you can use multiple triggers on the same automation, one for each group.
I don’t think you should define a group named “all_lights” since that is a system reserved group…

Thanks,
I know about the reserved group, thats’s why i asked :wink:
I now have group.all_lights_only , since the system group also had groups in it.

The python script works fine, with the exception of 0 lights on.
If all lights are off, it still shows the last light that was on.

How can we change that, anyone please?

thesis what i am using now:
lights_group = ‘group.all_lights_only’
#show only lights, not light groups
excluded = [‘light.custom_group_for_group’,‘light.custom_group_for_lights_2’]

    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"])

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:
        state = hass.states.get(entity_id)

if len(entities_on) > 0:

#     if (not state is None):
#         hidden = False #if (state.state != 'Normal') else True
#         if (state.state != 'Unknown'):
#             dt = hass.states.get('group.all_lights_only').attributes.get('last_changed')
#             if (not dt is None):
#                 time = "%02d:%02d" % (dt.hour+1, dt.minute)
#         if not hidden:
    lights_on_desc = "Lights on: " + ', '.join(entities_on)
    hass.states.set('sensor.lights_on', '', {
        'custom_ui_state_card': 'state-card-value_only',
        'text': lights_on_desc
     })

As you can see, ive been experimenting a bit, to fit it in my bigger script, based heavily on @mviezzer s Summary.

Showing nicely:

48

the script runs triggered by this simple automation:

- alias: 'Call Service Event (Light)'
  id: 'unique-id'
  hide_entity: True
  initial_state: 'on'
  trigger:
    platform: event
    event_type: call_service
    event_data:
      domain: light
  action:
    - delay: 00:00:02
    - service: python_script.summary
      data_template:
       event: "{{ trigger.event }}"

next to the Last Light On issue, i want to have the time displayed if the last change, just as with the other displayed items. Could you have a look at that too please? Maybe use some of the bits already after the ##'s

name: Lights
  entities: &lights_group_entities
- platform: state
      entity_id: *lights_group_entities

Never seen this. Is this the way to use sort of a joker for all the entities included in the group?

Its an anchor, they are part of the YAML format: https://blog.daemonl.com/2016/02/yaml.html
They put everything below the “entities: &lights_group_entities” line in the “entity_id: *lights_group_entities” line.