I have a notification script which I use to send notifications to various notify services. I feed this script with a data property called who. This who can contain for instance husband, wife, daughter, parents, at_home. Based on this value I do some if ... else logic within the script to call the correct service mentioned below.
notify.husband
notify.wife
notify.daughter
notify.parents (notify group with notify.husband and notify.wife)
notify.family (notify group with all family members)
This works fine for all scenarios expect the at_home one. For some automationâs I would like to notify only the people who are at home. For instance if someone is at the door. I know the status of people so thatâs not the problem. The problem is that I cant make a dynamic notify group which only contains the people at home.
Does anyone have any idea if and how to make a dynamic notify group where notify services can be added conditionally? Or is there another way to make this dynamically?
Notify script
notify_engine:
sequence:
- service: >
{% if who == 'husband' %}
notify.husband
{% elif who == 'wife' %}
notify.wife
{% elif who == 'daughter' %}
notify.daughter
{% elif who == 'parents' %}
notify.parents
{% elif who == 'family' %}
notify.family
{% elif who == 'at_home' %}
// todo: notify.at_home group
{% else %}
notify.husband
{% endif %}
data_template:
title: "{{ title }}"
message: "{{ message }}"
Dynamically, in NodeRED, I can accomplish this quite easily. If you donât use it, I would suggest adding it to your toolbox. Itâs very powerful.
I would watch the event bus in NodeRED, creating a flow that captures when a personâs location changes to Home. When it does, they would be added to an array stored as a global variable in NodeRED.
When they go from Home to something else, they would be removed from that array.
When I want to send the notification, I would simply split the array into individual messages and fire them off based who shows up in the array.
If you stick with YAML, you could probably script something that, rather than saying, if WHO is something, you would say, if WHO contains something and then make WHO be a collection of those who are at homeâŚthen loop through WHO to send a notification to each person until youâve looped through one time.
For the first property, enter entity_id.
Select is
change the dropdown az to .* regular expression and add ^person.* to the field.
Add a new property.
Enter state then is then make sure itâs a string (az) and put home in the field.
Output type to Array.
Output location to global.presence.whoIsHere (this is arbitrary). It could read global.bananas.chocolate if you prefer.
Add an inject node to the start of the flow, and a debug msg node set to complete msg object to the end (so you can monitor activity temporarily.)
Deploy, and then click the inject button to grab the information.
Either way, when you expand the sidebar in NodeRED on the right, you should see a little data container tab between the gear and the dropdown arrow in the upper right. Click that stack of pancakes and then refresh the global header.
Youâll see an entry for presence with an array of information that you just created.
Now you have a global variable with a list of people who are home.
The trick now, which I havenât worked out yet, is to use that array to build a message queue to send notifications to each person on that list.
Oh.
Ty so much for fast answer.
I try it yesterday and it work ( but i cant see entitiens. it show me that 1 or more entities are âhomeâ but i cant see who is.
Huh. i dont know too how to work it out but try something scenarios.
You can see who is by looking at the global variables in NodeRED. Itâs on the sidebar tab menu and is usually hidden because the sidebar is too narrow. Drag it wider and youâll see the Data tab show up. Click that tab and the refresh Global and youâll see an entry for the array that was output by the node. That array is an object containing the details of each.
At this point, youâd need to figure out how to build a message queue using the information in this array. You can reference this information in most node fields by using global.presence.whoIsHere.attributes.id or global.presence.whoIsHere.attributes.friendly_name etc.
Original method (still works, but requires a lot more setup and complicated templating)
notify_engine:
sequence:
- service: >
{% if who != 'at_home' %}
notify.{{who}}
{% elif who == 'at_home' %}
notify.{{homies}}
{% else %}
notify.husband
{% endif %}
data_template:
title: "{{ title }}"
message: "{{ message }}"
variables:
homies: >
{% set at_home = expand('person.husband', 'person.wife', 'person.daughter') | selectattr('state', 'eq', 'home') |map(attribute="name")| list |sort %}
{% set count = at_home|count %}
{% if count == 3 %}
family
{% elif count == 1 %}
{{at_home}}
{% elif count == 2 %}
{% set who_select = dict([
(('husband', 'wife'), 'parents'),
(('daughter', 'husband' ), 'husband_daughter'),
(('daughter', 'wife'), 'wife_daughter')
]) %}
{% set y = (at_home[0], at_home[1]) %}
{{ who_select[y] }}
{% endif %}
You would need to create two more notify groups ( âhusband_daughterâ and âwife_daughterâ) and make sure to enter the keys in the dict in alphabetical order of the personâs name.
UPDATE
The addition of the templatable Repeat for Each action makes this a lot easier and extendable to larger size groups without the exponential increase in the number of notifier groups required.
Set up a notifier group for each Person entity in the household, making sure the names match. For example, if your Person entityâs friendly_name is âBobâ, the notifier group should be:
notify:
- name: Bob
platform: group
services:
- service: mobile_app_bob_phone
- name: Alice
platform: group
services:
- service: mobile_app_alice_phone
- service: alexa_media_alice_bedroom_dot
Once you have your notifier groups set up you can use a template to dynamically define the list for the for_each of the Repeat action.
repeat:
for_each: >
{{ states.person | selectattr('state', 'eq' ,'home')
| map(attribute = 'name' ) | list | lower }}
sequence:
- service: notify.{{ repeat.item }}
data:
message: There's someone at the door