Notify/alert only people present in the house, howto?

Hi,

I have to types of notifications: a normal notification and an alert - both come in two flavours: to all people or only people who are at home.

I successfully created a notification system for the normal notification using a script with service_template, see below that takes care of presence.

I have not yet managed to send alerts only to people who are at home. Any ideas?

Here is my code for the normal stuff. At the end of an automation I call

action:
  - service: notify_people_who_are_present
    data:
      title: foo
      message: bar

and the script looks like this

notify_people_who_are_present:
  alias: Notify people who are present
  sequence:
  - service_template: >
      {% if is_state('person.stefan', 'home') %} 
      notify.mobile_app_swaiphone
      {% else %} {% endif %}
    data_template:
      title: '{{ title }}'
      message: '{{ message }}'
  - service_template: >
      {% if is_state('person.julia', 'home') %} 
      notify.mobile_app_jphone
      {% else %} {% endif %}
    data_template:
      title: '{{ title }}'
      message: '{{ message }}'
  - service_template: >
      {% if is_state('person.anna', 'home') %} 
      notify.mobile_app_iphone_von_anna
      {% else %} {% endif %}
    data_template:
      title: '{{ title }}'
      message: '{{ message }}'
  mode: single

That was fairly easy. How do I create an alert that notifies certain people based on a condition such as presence? I didnā€™t succeed using service templates

fake_alert:
  name: "fake name"
  done_message: fake done
  entity_id: sensor.swa_fake
  state: 'on' # Optional, 'on' is the default value
  repeat: 
    - 1
  can_acknowledge: true # Optional, default is true
#    skip_first: true # Optional, false is the default
  notifiers:
    - urgent_notification

Apparently, one cannot use service templates within notifiers?

- platform: group
  name: urgent_notification
  services:
    - service: mobile_app_swaiphone
      data:
        title: "Title"
        data:
          push:
            sound: 
              name: default
              critical: 1
              volume: 0.3

data_template: has been depracated. Just use data:

You can do this a bit cleaner with a choose structure.

notify_people_who_are_present:
  alias: Notify people who are present
  sequence:
    - choose:
        - conditions: "{{ is_state('person.stefan', 'home') }}"
          sequence:
            - service: notify.mobile_app_jphone
              data:
                title: "{{ title }}"
                message: "{{ message }}"

    - choose:
        - conditions: "{{ is_state('person.julia', 'home') }}"
          sequence:
            - service: notify.mobile_app_swaiphone
              data:
                title: "{{ title }}"
                message: "{{ message }}"

    - choose:
        - conditions: "{{ is_state('person.anna', 'home') }}"
          sequence:
            - service: notify.mobile_app_iphone_von_anna
              data:
                title: "{{ title }}"
                message: "{{ message }}"

You cannot template the notifiers in an alert. You are already sending a notification with your script? What is the alert for?

Also you should get into the habit of using double quotes around templates because you will often have single quotes within the template.

1 Like

Thanks Jason for the hints. Will adapt the code. I think of alerts as ā€˜urgentā€™ and/or ā€˜importantā€™ notifications. I like alerts because they reach the phone even if put on silent mode. Plus, I get repeated notifications and a confirmation if the problem is solved. Too bad, one cannot template notifiers in alerts.

1 Like

Yes, templatable notifiers in alerts would be handy and maybe weā€™ll get that if the devs ever have time to give the alert comoponent a little love.

However, an alert doesnā€™t do anything canā€™t do with notifiers and automations.

To bypass silent mode.

Looping in scripts and automations.

Hereā€™s your script repeating 4 times every 5 minutes.

notify_people_who_are_present:
  alias: Notify people who are present
  sequence:
    - repeat:
        while:
          - condition: template
            value_template: "{{ repeat.index < 5 }}"
            
        sequence:
          - choose:
              - conditions: "{{ is_state('person.stefan', 'home') }}"
                sequence:
                  - service: notify.mobile_app_jphone
                    data:
                      title: "{{ title }}"
                      message: "{{ message }}"
      
          - choose:
              - conditions: "{{ is_state('person.julia', 'home') }}"
                sequence:
                  - service: notify.mobile_app_swaiphone
                    data:
                      title: "{{ title }}"
                      message: "{{ message }}"
      
          - choose:
              - conditions: "{{ is_state('person.anna', 'home') }}"
                sequence:
                  - service: notify.mobile_app_iphone_von_anna
                    data:
                      title: "{{ title }}"
                      message: "{{ message }}"
      
          - delay:
              minutes: 5
1 Like

That repeat loop is not exactly what I was looking for. It loops regardless if the original problem (why the ā€œalertā€ was triggered in the first place) still persists.

I could get around it if I define the same trigger with different intervals, say

  trigger:
  - platform: state
    from: 'off'
    for: 00:05:00
    to: 'on'
    entity_id: group.windows
  - platform: state
    entity_id: group.windows
    from: 'off'
    for: 00:10:00
    to: 'on'

I have no idea yet how to address the case that the windows got closed in between and I want a notification for that as well (similar to the alert function). I could have a state somewhere but that gets messy and hard to maintain.

That was just an example to show you how to use a loop in a script. I pointed to the docs for script syntax so you could figure out how to change it to what you need.

You needed to change value_template: "{{ repeat.index < 5 }}" to the condition you required to start with. If you were intending on using the same trigger as your alert you would change that to.

value_template: "{{ is_state('sensor.swa_fake','on') }}"

Now that automation will continue to repeat until sensor.swa_fake turns off. It will not run at all if swa_fake does not turn on. BTW that delay is important. Without it the script will keep repeating immediately and eventually something will crash.

If you spell out exactly what you want to do for one of your alerts Iā€™ll help you put it together and you can use it as an example to figure out the rest.

Your other choice is to create a separate alert trigger sensor and alert for each event for each person.

Iā€™ve come up with a form (using everyone above as inspiration) that is quite flexible: it can notify individuals at home or anyone at home.

I have one prerequisite: each person has a person entity and a notify service call, each with the same name. So, for instance, I would have person.aaron and notify.aaron.

In that case, the first script notifies a person if they are home (note that I have some fields, like interruption_level and tag that are specific to the iOS companion app):

notify_person_if_at_home:
  alias: "Notify Person if at Home"

  fields:
    interruption_level:
      description: The interruption level to set
      example: critical
    message:
      description: The message to send
      example: Your hair is on fire!
    name:
      description: The lowercase name of the person to notify
      example: aaron
    title:
      description: The optional title to include
      example: Heads Up

  sequence:
    - alias: "Is the person at home?"
      condition: template
      value_template: "{{ states('person.' + name) == 'home' }}"
    - alias: "Send the message"
      service: "notify.{{ name }}"
      data:
        message: "{{ message }}"
        title: "{{ title }}"
        data:
          push:
            interruption-level: "{{ interruption_level }}"
          tag: "{{ message }}"

Then, a second script can use this building block to notify everyone at home:

notify_everyone_at_home:
  alias: "Notify Everyone at Home"

  fields:
    interruption_level:
      description: The interruption level to set
      example: critical
    message:
      description: The message to send
      example: Your hair is on fire!
    title:
      description: The optional title to include
      example: Heads Up

  sequence:
    - alias: "Notify Aaron if he's at home"
      service: script.turn_on
      target:
        entity_id: script.notify_person_if_at_home
      data:
        interruption_level: "{{ interruption_level }}"
        message: "{{ message }}"
        name: aaron
        title: "{{ title }}"
    - alias: "Notify Britt if she's at home"
      service: script.turn_on
      target:
        entity_id: script.notify_person_if_at_home
      data:
        interruption_level: "{{ interruption_level }}"
        message: "{{ message }}"
        name: aaron
        title: "{{ title }}"

Using some other messages as inspiration - Iā€™ve created a similar script to only notify people based on their location. It relies on having a custom attribute for each person to link people to their notifier.

For example:

configuration.yaml

homeassistant:
  customize: !include customize.yaml

customize.yaml

person.t:
  notifier: notify.mobile_app_t
person.a:
  notifier: notify.mobile_app_a

script_to_notify_based_on_location.yaml

alias: Notify people based on location
mode: parallel
fields:
  TITLE:
    description: Notification title
    example: "Example Notification"
    required: true
  MESSAGE:
    description: Message of notification
    example: "Something is happening"
    required: true
  LOCATION:
    description: State of people to send notification to
    example: "home"
    default: "home"
    required: false
  DEBUG:
    description: Only send messages to T
    example: true
    default: false
    required: false
sequence:
  # Determine all the people at scripted location to send notification to
  # Have debug handling to only send to me when debug = true
  - variables:
      NOTIFIERS: >
        {% if DEBUG %}
          {{ states.person | selectattr("entity_id", "eq", "person.t") | selectattr('state', 'eq', LOCATION) | map(attribute='attributes.notifier') | list }}
        {% else %}
          {{ states.person | selectattr('state', 'eq', LOCATION) | map(attribute='attributes.notifier') | list }}
        {% endif %}
  # Iterate through all the people and send the relevant notification
  - repeat:
      count: "{{ NOTIFIERS | count }}"
      sequence:
        - variables:
            NOTIFIER: "{{ NOTIFIERS[repeat.index - 1] }}"
        - service: "{{ NOTIFIER }}"
          data:
            title: "{{ TITLE }}"
            message: "{{ MESSAGE }}"
3 Likes

Hi,
I tried using your code:

alias: Anwesende Menschen benachrichtigen
sequence:
  - choose:
      - conditions: "{{ is_state('person.stephan', 'home') }}"
        sequence:
          - service: notify.mobile_app_stephan_handy
            data:
              title: "{{ title }}"
              message: "{{ message }}"
      - conditions: "{{ is_state('person.manuel', 'home') }}"
        sequence:
          - service: notify.mobile_app_manuel_smartphone_app
            data:
              title: "{{ title }}"
              message: "{{ message }}"
      - conditions: "{{ is_state('person.jannis', 'home') }}"
        sequence:
          - service: notify.mobile_app_iphone_von_jannis
            data:
              title: "{{ title }}"
              message: "{{ message }}"
      - conditions: "{{ is_state('person.alina', 'home') }}"
        sequence:
          - service: notify.mobile_app_alina_handy
            data:
              title: "{{ title }}"
              message: "{{ message }}"
      - conditions: "{{ is_state('person.sandra', 'home') }}"
        sequence:
          - service: notify.mobile_app_mcintosh
            data:
              title: "{{ title }}"
              message: "{{ message }}"
      - conditions: "{{ is_state('person.anna_lena', 'home') }}"
        sequence:
          - service: notify.mobile_app_iphone_leni
            data:
              title: "{{ title }}"
              message: "{{ message }}"
mode: parallel
icon: mdi:account
max: 10
fields:
  title:
    name: Titel der Nachricht
    selector:
      text: null
  message:
    name: Inhalt der Nachricht
    selector:
      text: null

My only problem: It only works for the first person in this list. If other persons are home, they donā€™t get a notification. Why would that be?

Just for amusement, I thought I would post a pyscript version that achieves the same thing. This one uses pushover for notification.

@service
def notify_all_at_home(subject=None, content=None):
    household = state.names(domain="person")
    for person in household:
        name = state.get(person + ".friendly_name")
        location = state.get(person)
        if location == "home":
            notify.pushover(message=content, title=subject, target=name, data={'sound':'pushover','priority':0})

As shown in Jasonā€™s original script, each person should be their own Choose action so that they are evaluated independently. Your script is currently 1 Choose action for 6 people instead of 6 Choose actions.

1 Like

Thank you. Thatā€™s what if you just copy & paste different things. Someone on the discord also told me this and I then just redid the whole thing via the ui and it now works perfectly :slight_smile:

Hi everyone,
I had the same problem that I wanted to notify everyone who is home. This is my current solution:

sequence:
  - repeat:
      for_each: >-
        {{ expand('person.first', 'person.second') | selectattr('state', 'eq',
                'home') | map(attribute='entity_id') | list | replace('person', "notify") }}
      sequence:
        - service: "{{ repeat.item }}"
          data:
            title: "Dummy title"
            message: "Dummy message"

For every person there must be a matching notifier. I use notification groups for this:

notify:
  - name: first
    platform: group
    services:
      - service: mobile_app_1
  - name: second
    platform: group
    services:
      - service: mobile_app_2
6 Likes

based on that, you would be able to simplify the foreach part

{{ expand('group.users') | selectattr('state', 'eq','home') | map(attribute='attributes.source') | list  | replace('device_tracker.', "notify.mobile_app_") }}

then you donā€™t have to create a notify event per user. downside is that now only the source device is listed and not all device_trackers, but if you want that, I think itā€™s easy to implement that as well.
According to the documentation mobile notification always has the same format

[edit:] I see this fails for Iphone devices