How to tell which device in a group caused the state change

I’m trying to create an automation to alert me if something on my network changes to not_home. I’m using the asuswrt tracker.

So Have this group of devices I want to keep an eye on

network_devices_to_track:
  name: Network Devices to Track
  view: no
  entities:   
    - device_tracker.ecobee_downstairs
    - device_tracker.ecobee_upstairs
    - device_tracker.front_doorbell_camera
    - device_tracker.harmony_hub_1
    - device_tracker.harmonyhub_2
    - device_tracker.hue
    - device_tracker.office
    - device_tracker.plex
    - device_tracker.tvdeice
    - device_tracker.sonos_sub
    - device_tracker.sonosplaybar
    - device_tracker.sony_tv
    - device_tracker.tivomini

And I have this automation

- alias: Notify me if device falls off the network
  trigger:
  - platform: state  
    entity_id: network_devices_to_track
    from: 'home'
    to: 'not_home'
  action:
  - service: notify.my_iphone
    data:
      message: "Something is off the network"
      title: "network device off the network"

How to I get the Message to tell me which device is “not_home”?

You can always check the logbook:
image
You may need to check your automation to see when it was last triggered first, then look for that time in the logbook, you’ll see which entity triggered it.
Look for this icon, image the entity that triggered it should be right underneath

You can use a template in your action to tell you what triggered the automation.

See below for how my automation is setup.

1 Like

Sweet, here is what I ended up with

- alias: "Notify if HA Device Offline"
  trigger:
    - platform: state
      entity_id:
        - device_tracker.ecobee_downstairs
        - device_tracker.ecobee_upstairs
        - device_tracker.front_doorbell_camera
        - device_tracker.harmony_hub_1
        - device_tracker.harmonyhub_2
        - device_tracker.hue
        - device_tracker.office
        - device_tracker.plex
        - device_tracker.tvdeice
        - device_tracker.sonos_sub
        - device_tracker.sonosplaybar
        - device_tracker.sony_tv
        - device_tracker.tivomini
      from: 'home'
      to: 'not_home'
  action:
    service: notify.home_assistant
    data_template:
      title: "Home Assistant Device is Offline"
      message: "{{ trigger.to_state.attributes.friendly_name }} is offline"

Following up on my old post. So, what can you do the same thing but if you’re using a group for your devices

for example

- alias: 'Security System - Armed Home'
  trigger:
  - platform: state
    entity_id: group.door_open_close_sensors
    from: 'off'
    to: 'on'

I’d assume that

{{ trigger.to_state.attributes.friendly_name }}

would just return the group. Can you tell which item in the group caused the trigger? Not a huge deal if not, but I have a few alerts, that use groups, and as I’ve gotten better I like the idea of getting more details such as which door was opened, etc.

Thanks

Well, if the group just went from off to on, then that means it went from all the entities in the group being off to one or more being on. And since the automation probably runs pretty quickly, and it’s probably unlikely (although possible) for more than one to open at exactly, or close to exactly, the same time… :wink:

How about a template that selects the entity (or the very few entities) in the group that’s on?

Thats what I meant. I’d like to know which Item in the group caused it to go on. Would it just be better to include all the entities as the trigger, or can I pull which entity in the group cause it to go on?

My point was, there’s probably only one entity in the group that is on, so it’s the one that triggered the automation. Not foolproof, but is easy and probably good enough for an announcement.

EDIT: And, yes, you can find the item that’s on with a template, but writing this from a phone so not so easy to do now. :slight_smile:

I agree, but other how can I tell which one is on.

Might as well just use the initial automation and name the enties vs the group then

- alias: "Notify if door open"
  trigger:
    - platform: state
      entity_id:
        - binary_sensor.open1
        - binary_sensor.open2
        - binary_sensor.open3
action:
    service: notify.home_assistant
    data_template:
      title: "door opened"
      message: "{{ trigger.to_state.attributes.friendly_name }} is opened"

But if I had a group of 10 items, it would be nice to be reusable across multiple automations. How would I know which item is on in the group of 10

So, one way you can tell which entity is on in a group is:

{{ (states.binary_sensor|selectattr(
      'entity_id','in',state_attr('group.door_open_close_sensors','entity_id'))
    |selectattr('state','eq','on')|list)[0].name }}

This assumes there’s only one on, or if there are more than one on you only care about one of them. If you wanted the friendly_name’s of all the entities that are on:

{{ states.binary_sensor|selectattr(
     'entity_id','in',state_attr('group.door_open_close_sensors','entity_id'))
   |selectattr('state','eq','on')|map(attribute='name')|join(', ') }}

But, again, this is kind of “after the fact.” I.e., the group turned on, so one of the entities turned on, so let’s figure out which one it must have been. Also, the biggest downside to this approach over simply listing all the entities in the trigger is it will only trigger when the first one turns on. Once that happens, the group is on so any other entities going on will not change the state of the group, hence the automation won’t trigger again (until all go off and one goes back on.)

Probably a better way to go about this is to use a different type of trigger - an event trigger looking for state_changed events. Then you can use a condition so only the state_changed events you care about cause the automation action(s) to run. Something like this:

automation:
  - alias: Notify if door opens
    trigger:
      platform: event
      event_type: state_changed
    condition:
      condition: template
      value_template: >
        {{ trigger.event.data.entity_id in
             state_attr('group.door_open_close_sensors','entity_id') }}
    action:
      service: notify.home_assistant
      data_template:
        title: "door opened"
        message: "{{ trigger.event.data.new_state.name }} opened"

I’m pretty sure this will work. If you try it and you run into problems, let me know. I can look up a topic where this was discussed.

8 Likes

Event trigger is the most elegant solution the way I see it. One note on the other solutions is by the time evaluation code runs the state could potentially be changed, whereas with the event trigger that is not a risk.

Hi, I’ve been trying some of your suggestions to solve the good old “door is open when alarm is turned on” problem.

I have my triggers in a group and the alarm triggers to state change “on” of that group.

The issue is when I leave a door open, then activate the alarm, the alarm will never trigger because it the group was on already and thus never changes to “on”.

I can prevent the alarm from turning on like this, but I would like to know exactly which door or window is open;

- alias: 'Alarm - Stop arming when windows left open'
  initial_state: true
  trigger:
    - platform: state
      entity_id: alarm_control_panel.alarm
      to: 'pending'
      from: 'disarmed'
  condition:
    - condition: state
      entity_id: group.door_and_window_sensors
      state: 'on'
  action:
    - service: tts.google_say
      data_template:
        entity_id: media_player.google_home_minis
        message: |
          Please note, one or more windows are left open. Disarming alarm...
    - service: alarm_control_panel.alarm_disarm
      entity_id: alarm_control_panel.alarm
      data:
        code: !secret alarm_code

Any ideas how to do that?

Cheers,

Michel

This is what I use if it helps:

To trigger the alarm, I don’t use groups, I list all entities. Same link as above, check the first automation at the top

1 Like
        message: |
          {%- set windows = expand('group.door_and_window_sensors') | selectattr('state','eq','on') | map(attribute='name') | list %}
          {%- set phrase = windows[:-1] | join(', ') ~ ', and ' ~ windows[-1] if windows | length > 2 else windows | join(' and ') %}
          Please note, {{ phrase }} {{ 'are' if windows | length > 1 else 'is' }} open. Disarming alarm...
2 Likes

Thank you both, that helps!