TL DR: The code is at the bottom of the page if you rather just import into Node-RED instead of following this guide
I have / had a bad habit of forgetting bottles at home for my now 1 year old in the morning while bringing my 1 year old and 3 year old to daycare. This of course was not an issue for my wife. Part of the problem I ran into was that my wife’s job is hybrid while mine is work from home. Days that my wife WFH she would take the kids to daycare and I would pick them up at the end of the day, and days that my wife was not working from home I would take the kids and my wife would pick them up from daycare at the end of the day.
My wife’s schedule was a bit erratic, so I used a mixture of a proximity sensor (not a device, home assistant configuration), a weekday node, a time range node, a delay node, a smart door lock (Z-Wave), a home assistant zone for daycare, and the home assistant companion app to help send reminders automatically.
If you aren’t already familiar with the proximity sensor in home assistant, you can read about it here: https://www.home-assistant.io/integrations/proximity/, alternatively if you did not wish to setup a proximity sensor, you could use an event state node that checks if a person (your husband or wife) is away from the house (if you choose this route, I would also suggest waiting for 5 minutes).
Using this tutorial, I’m under the assumption that you have a home proximity sensor setup.
Using the events: state node, we’re going to check to see if my wife is more than 26000 ft away from the house. In the entity field I’m going to use the Home <family member> distance entity, and I’m going to use the greater than symbol.
Next, I’m going to install the weekday node, and select M-F: https://flows.nodered.org/node/node-red-contrib-weekday
You can install a new node type by clicking on the hamburger menu in the top right of node red, and then choosing “Manage palette”
Inside Manage Palette, click on install. You will want to install “node-red-contrib-weekday” and “node-red-contrib-time-range-switch”
One we have both we’re now going to connect the true part of the state node to a weekday node. Inside my weekday node I selected Mon, Tue, Wed, Thu, and Fri
Next I’m going to add a time range node. In this particular case my wife leaves for work after 5am, and before 9am daily. So I’m going to limit my time from 05:00 to 09:00 daily. You will also need to know the latitude and longitude of your location for accurate time representation, you can open up google maps and right click on the map to easily obtain your latitude and longitude.
Next we’re going to add a delay node, not necessarily to delay the notification but to rate limit the number of messages being sent. Inside the delay node you should change the action to rate limit, select all messages, and change the rate limit to 1 message per 5 hours. For the action you want to drop intermediate messages as to not flood your phone with notifications.
Next we’re going to add a change node to set the title and message, alternatively you can do this directly in the call service node.
For the change node, I have it set to set the msg.message to “Remember to bring the bottles to daycare!”, and then I have msg.title set to the title of the notification, in my case it’s “Bottles for Declan”
Next we’re going to add two separate call service nodes. The first one I created a Input boolean helper (see https://www.home-assistant.io/integrations/input_boolean/) to deal with a secondary message I send after I open the front door, the second one is to send the first notification.
For the helper node, I simply turn the boolean helper to on when all of the previous conditions are met (more on this later):
For the notification, I set the domain to notify, the service to my phone which is mobile_app_dan_pixel_8_pro, and then change the data from J expression to JSON (drop down before the message) and add the following
{
"message": "{{message}}",
"title": "{{title}}",
"data": {
"channel": "Bottle Reminder",
"tag": "bottle-reminder",
"priority": "high",
"ttl": 0
}
}
A few notes on the above, in the data section I set the following options
- Channel: Bottle Reminder, this is used so that you can set specific sounds or actions (such as ignore dnd) for that notification category in android. More on channels is located here: https://companion.home-assistant.io/docs/notifications/notifications-basic/#notification-channels
- Tag: We use the tag so that we can go back later and clear a notification from our phone automatically, information located here: https://companion.home-assistant.io/docs/notifications/notifications-basic/#clearing
- Priority, in this case we’re setting the priority to high to make sure we receive the notification in a timely manner: https://companion.home-assistant.io/docs/notifications/notifications-basic/#notification-channel-importance
- TTL: 0, making sure that the notification is sent even if the phone is stationary, info here: https://companion.home-assistant.io/docs/notifications/critical-notifications/
At this point your flow should look like this:
We’re going to add a few more things, especially since I’m forgetful. The first is to send yet another notification as soon as I’m walking out the door.
First we’re going to use the event state node to check and see if the door is unlocked:
Next we’re going to use the previous input boolean helper we created to check and see if my wife is away by using a current state node
If both these options are true, we’re going to set the title and message again, and send a second notification.
First we’re going to create another change node, msg.message is set to “Remember to bring the bottles to daycare!” and msg.title is set to “Double Checking!”
For the notification, you can just copy the previous call service phone notification above and paste it after the set title and message, if you need a reminder, this is how it’s setup
And the JSON information is as follows:
{
"message": "{{message}}",
"title": "{{title}}",
"data": {
"channel": "Bottle Reminder",
"tag": "bottle-reminder",
"priority": "high",
"ttl": 0
}
}
Next we’re going to add another call service node, this time to shut off the input boolean helper we created above using a call service node:
Your flow should now look as follows:
Now there’s two additional things I’ve added, the first is to set the input boolean healper to off at 10am daily using an inject node. This is to “reset” the flow for the next day. Using the bottom of an inject node, set the inject node to repeat at a specific time each day, in my instance I chose 10am as the kids and I should be out of the house and in daycare at that point:
and connect it to a call service node to turn off the input boolean healper you created
Last but not least, I dislike having a million notifications that are no longer useful, so I clear the notifications automatically after arriving at daycare (at this point, if I still forgot the bottles the notifications were pointless anyways).
First I need to create a zone in home assistant for daycare. I’m not going to go over in this guide but information on creating zones can be found here: https://www.home-assistant.io/integrations/zone/
Next I’m going to create an event state node, in my event state node I’m going to check if person.dan (myself) is in the “Daycare” zone (again, under the assumption that you created a daycare zone in home assistant)
Next, I’m going to create a call service node and clear my notifications
For this particular notification, you can either leave it as JSON on J Expression, and the code will be as follows:
{
"message":"clear_notification",
"data":{
"channel":"Bottle Reminder",
"tag":"bottle-reminder"
}
}
In the above code, I’m calling “clear_notification” in the message, in the data I’m referencing the channel and the tag I used above for the bottle reminder notifications. Alternatively you could also set the priority to high and the TTL to 0 if you wish to have it cleared quicker.
Your whole flow should now look like this:
And as noted above, if you don’t wish to do all this work, you can import this into node red directly using the hamburger menu in the top right and then import. You may still need to add the mission palette’s however. You may also need to modify most if not all of the flow.
[{“id”:”6eddc596f690c961″,”type”:”server-state-changed”,”z”:”34612c8b68f0a720″,”name”:”Robyn Proximity Sensor”,”server”:”2e31528c.f3973e”,”version”:5,”outputs”:2,”exposeAsEntityConfig”:””,”entityId”:”sensor.home_robyn_distance”,”entityIdType”:”exact”,”outputInitially”:false,”stateType”:”str”,”ifState”:”26000″,”ifStateType”:”num”,”ifStateOperator”:”gt”,”outputOnlyOnStateChange”:true,”for”:”0″,”forType”:”num”,”forUnits”:”minutes”,”ignorePrevStateNull”:false,”ignorePrevStateUnknown”:false,”ignorePrevStateUnavailable”:false,”ignoreCurrentStateUnknown”:false,”ignoreCurrentStateUnavailable”:false,”outputProperties”:[{“property”:”payload”,”propertyType”:”msg”,”value”:””,”valueType”:”entityState”},{“property”:”data”,”propertyType”:”msg”,”value”:””,”valueType”:”eventData”},{“property”:”topic”,”propertyType”:”msg”,”value”:””,”valueType”:”triggerId”}],”x”:140,”y”:2980,”wires”:[[“2773bc5691a90935”],[]]},{“id”:”abc2aa7fb574b6eb”,”type”:”change”,”z”:”34612c8b68f0a720″,”name”:”Set Title and Message”,”rules”:[{“t”:”set”,”p”:”message”,”pt”:”msg”,”to”:”Remember to bring the bottles to daycare!”,”tot”:”str”},{“t”:”set”,”p”:”title”,”pt”:”msg”,”to”:”Bottles for Declan”,”tot”:”str”}],”action”:””,”property”:””,”from”:””,”to”:””,”reg”:false,”x”:980,”y”:2980,”wires”:[[“db64285d7255a0a4”]]},{“id”:”db64285d7255a0a4″,”type”:”api-call-service”,”z”:”34612c8b68f0a720″,”name”:”Notify Dan Phone (Priority)”,”server”:”2e31528c.f3973e”,”version”:5,”debugenabled”:false,”domain”:”notify”,”service”:”mobile_app_dan_pixel_8_pro”,”areaId”:[],”deviceId”:[],”entityId”:[],”data”:”{\”message\”:\”{{message}}\”,\”title\”:\”{{title}}\”,\”data\”:{\”channel\”:\”Bottle Reminder\”,\”tag\”:\”bottle-reminder\”,\”priority\”:\”high\”,\”ttl\”:0}}”,”dataType”:”json”,”mergeContext”:””,”mustacheAltTags”:false,”outputProperties”:[],”queue”:”none”,”x”:1220,”y”:2980,”wires”:[[]]},{“id”:”2773bc5691a90935″,”type”:”weekday”,”z”:”34612c8b68f0a720″,”name”:””,”sun”:false,”mon”:true,”tue”:true,”wed”:true,”thu”:true,”fri”:true,”sat”:false,”x”:340,”y”:2980,”wires”:[[“1f4bc2ddaee2391b”],[]]},{“id”:”1f4bc2ddaee2391b”,”type”:”time-range-switch”,”z”:”34612c8b68f0a720″,”name”:””,”lat”:”35.717300″,”lon”:”-78.894638″,”startTime”:”05:00″,”endTime”:”09:00″,”startOffset”:0,”endOffset”:”0″,”x”:510,”y”:2980,”wires”:[[“6f1fe7e2404b094d”],[]]},{“id”:”6f1fe7e2404b094d”,”type”:”delay”,”z”:”34612c8b68f0a720″,”name”:”Limit to 1 message per day”,”pauseType”:”rate”,”timeout”:”5″,”timeoutUnits”:”seconds”,”rate”:”1″,”nbRateUnits”:”5″,”rateUnits”:”hour”,”randomFirst”:”1″,”randomLast”:”5″,”randomUnits”:”seconds”,”drop”:true,”allowrate”:false,”outputs”:1,”x”:740,”y”:2980,”wires”:[[“abc2aa7fb574b6eb”,”ae51ef92da577553″]]},{“id”:”ae51ef92da577553″,”type”:”api-call-service”,”z”:”34612c8b68f0a720″,”name”:”Turn on Robyn away”,”server”:”2e31528c.f3973e”,”version”:5,”debugenabled”:false,”domain”:”input_boolean”,”service”:”turn_on”,”areaId”:[],”deviceId”:[],”entityId”:[“input_boolean.robyn_away_dan_bottle”],”data”:””,”dataType”:”jsonata”,”mergeContext”:””,”mustacheAltTags”:false,”outputProperties”:[],”queue”:”none”,”x”:1000,”y”:3040,”wires”:[[]]},{“id”:”da6d988b6be05dff”,”type”:”server-state-changed”,”z”:”34612c8b68f0a720″,”name”:”Front Door is unlocked”,”server”:”2e31528c.f3973e”,”version”:5,”outputs”:2,”exposeAsEntityConfig”:””,”entityId”:”lock.front_door”,”entityIdType”:”exact”,”outputInitially”:false,”stateType”:”str”,”ifState”:”unlocked”,”ifStateType”:”str”,”ifStateOperator”:”is”,”outputOnlyOnStateChange”:true,”for”:”0″,”forType”:”num”,”forUnits”:”minutes”,”ignorePrevStateNull”:false,”ignorePrevStateUnknown”:false,”ignorePrevStateUnavailable”:false,”ignoreCurrentStateUnknown”:false,”ignoreCurrentStateUnavailable”:false,”outputProperties”:[{“property”:”payload”,”propertyType”:”msg”,”value”:””,”valueType”:”entityState”},{“property”:”data”,”propertyType”:”msg”,”value”:””,”valueType”:”eventData”},{“property”:”topic”,”propertyType”:”msg”,”value”:””,”valueType”:”triggerId”}],”x”:140,”y”:3140,”wires”:[[“6598665837c7c11e”],[]]},{“id”:”2c99ee59cfc5a77b”,”type”:”api-call-service”,”z”:”34612c8b68f0a720″,”name”:”Turn off Robyn away”,”server”:”2e31528c.f3973e”,”version”:5,”debugenabled”:false,”domain”:”input_boolean”,”service”:”turn_off”,”areaId”:[],”deviceId”:[],”entityId”:[“input_boolean.robyn_away_dan_bottle”],”data”:””,”dataType”:”jsonata”,”mergeContext”:””,”mustacheAltTags”:false,”outputProperties”:[],”queue”:”none”,”x”:1260,”y”:3140,”wires”:[[]]},{“id”:”6598665837c7c11e”,”type”:”api-current-state”,”z”:”34612c8b68f0a720″,”name”:”Robyn Away Helper is on”,”server”:”2e31528c.f3973e”,”version”:3,”outputs”:2,”halt_if”:”on”,”halt_if_type”:”str”,”halt_if_compare”:”is”,”entity_id”:”input_boolean.robyn_away_dan_bottle”,”state_type”:”str”,”blockInputOverrides”:false,”outputProperties”:[{“property”:”payload”,”propertyType”:”msg”,”value”:””,”valueType”:”entityState”},{“property”:”data”,”propertyType”:”msg”,”value”:””,”valueType”:”entity”}],”for”:”0″,”forType”:”num”,”forUnits”:”minutes”,”override_topic”:false,”state_location”:”payload”,”override_payload”:”msg”,”entity_location”:”data”,”override_data”:”msg”,”x”:410,”y”:3140,”wires”:[[“b6e6d77134604767”],[]]},{“id”:”b6e6d77134604767″,”type”:”change”,”z”:”34612c8b68f0a720″,”name”:”Set Title and Message”,”rules”:[{“t”:”set”,”p”:”message”,”pt”:”msg”,”to”:”Remember to bring the bottles to daycare!”,”tot”:”str”},{“t”:”set”,”p”:”title”,”pt”:”msg”,”to”:”Double Checking!”,”tot”:”str”}],”action”:””,”property”:””,”from”:””,”to”:””,”reg”:false,”x”:700,”y”:3140,”wires”:[[“4b2558fdeb46d06a”]]},{“id”:”4b2558fdeb46d06a”,”type”:”api-call-service”,”z”:”34612c8b68f0a720″,”name”:”Notify Dan Phone (Priority)”,”server”:”2e31528c.f3973e”,”version”:5,”debugenabled”:false,”domain”:”notify”,”service”:”mobile_app_dan_pixel_8_pro”,”areaId”:[],”deviceId”:[],”entityId”:[],”data”:”{\”message\”:\”{{message}}\”,\”title\”:\”{{title}}\”,\”data\”:{\”channel\”:\”Bottle Reminder\”,\”tag\”:\”bottle-reminder\”,\”priority\”:\”high\”,\”ttl\”:0}}”,”dataType”:”json”,”mergeContext”:””,”mustacheAltTags”:false,”outputProperties”:[],”queue”:”none”,”x”:980,”y”:3140,”wires”:[[“2c99ee59cfc5a77b”]]},{“id”:”941b107fe0ebb085″,”type”:”inject”,”z”:”34612c8b68f0a720″,”name”:””,”props”:[{“p”:”payload”},{“p”:”topic”,”vt”:”str”}],”repeat”:””,”crontab”:”00 10 * * *”,”once”:false,”onceDelay”:0.1,”topic”:””,”payload”:””,”payloadType”:”date”,”x”:130,”y”:3220,”wires”:[[“f65963c069c2e9bf”]]},{“id”:”f65963c069c2e9bf”,”type”:”api-call-service”,”z”:”34612c8b68f0a720″,”name”:”Turn off Robyn away”,”server”:”2e31528c.f3973e”,”version”:5,”debugenabled”:false,”domain”:”input_boolean”,”service”:”turn_off”,”areaId”:[],”deviceId”:[],”entityId”:[“input_boolean.robyn_away_dan_bottle”],”data”:””,”dataType”:”jsonata”,”mergeContext”:””,”mustacheAltTags”:false,”outputProperties”:[],”queue”:”none”,”x”:360,”y”:3220,”wires”:[[]]},{“id”:”1d7799b546d86a98″,”type”:”server-state-changed”,”z”:”34612c8b68f0a720″,”name”:”Dan at Daycare”,”server”:”2e31528c.f3973e”,”version”:5,”outputs”:2,”exposeAsEntityConfig”:””,”entityId”:”person.dan”,”entityIdType”:”exact”,”outputInitially”:false,”stateType”:”str”,”ifState”:”Daycare”,”ifStateType”:”str”,”ifStateOperator”:”is”,”outputOnlyOnStateChange”:true,”for”:”0″,”forType”:”num”,”forUnits”:”minutes”,”ignorePrevStateNull”:false,”ignorePrevStateUnknown”:false,”ignorePrevStateUnavailable”:false,”ignoreCurrentStateUnknown”:false,”ignoreCurrentStateUnavailable”:false,”outputProperties”:[{“property”:”payload”,”propertyType”:”msg”,”value”:””,”valueType”:”entityState”},{“property”:”data”,”propertyType”:”msg”,”value”:””,”valueType”:”eventData”},{“property”:”topic”,”propertyType”:”msg”,”value”:””,”valueType”:”triggerId”}],”x”:120,”y”:3300,”wires”:[[“3a651005c5cf3646”],[]]},{“id”:”41cfab4c672bf180″,”type”:”comment”,”z”:”34612c8b68f0a720″,”name”:”Bottle Reminders”,”info”:””,”x”:120,”y”:2920,”wires”:[]},{“id”:”3a651005c5cf3646″,”type”:”api-call-service”,”z”:”34612c8b68f0a720″,”name”:”Clear Notifications”,”server”:”2e31528c.f3973e”,”version”:5,”debugenabled”:false,”domain”:”notify”,”service”:”notify”,”areaId”:[],”deviceId”:[],”entityId”:[],”data”:”{\t \”message\”:\”clear_notification\”,\t \”data\”:{\t \”channel\”:\”Bottle Reminder\”,\t \”tag\”:\”bottle-reminder\”\t }\t}”,”dataType”:”jsonata”,”mergeContext”:””,”mustacheAltTags”:false,”outputProperties”:[],”queue”:”none”,”x”:370,”y”:3300,”wires”:[[]]},{“id”:”2e31528c.f3973e”,”type”:”server”,”name”:”Home Assistant”,”version”:5,”addon”:true,”rejectUnauthorizedCerts”:true,”ha_boolean”:”y|yes|true|on|home|open”,”connectionDelay”:true,”cacheJson”:true,”heartbeat”:false,”heartbeatInterval”:”30″,”areaSelector”:”friendlyName”,”deviceSelector”:”friendlyName”,”entitySelector”:”friendlyName”,”statusSeparator”:”at: “,”statusYear”:”hidden”,”statusMonth”:”short”,”statusDay”:”numeric”,”statusHourCycle”:”h23″,”statusTimeFormat”:”h:m”,”enableGlobalContextStore”:true}]