Going Further with Home Automations in Node-Red

Home AssistantNode-RedSmart Home

Written by:

In my last post about using Node-Red to make automations with Home Assistant, I showed some very simple flows for turning lights on and off. While it is important to get used to the Node-Red way of doing things and it’s interface, none of the examples in my post are very compelling. All of that can easily be accomplished in Home Assistant already, so what makes Node-Red so awesome?

Let’s examine some of Node-Red’s features a little closer to get a better idea of what’s going on, how we can use that to create dynamic automations with Home Assistant, and an example of an alarm clock radio flow that uses some advanced logic nodes.


The simplest explanation of Node-Red is that it a way to route messages. Input nodes create a msg that has several parts, the nodes in the flow examine this message to decide where to send it next, & this ends in an output that acts on the message.

Usually, we are most interested in the msg.payload, but that’s not the only information the msg carries. By setting a debug node to output the entire message, we can see all the information:

Debug Node's Output Settings

Debug Node’s Output Settings

If I hook this debug node up to my location device_tracker, I get this in the Debug panel:

Full debug msg output

Full debug msg output

That’s a lot more info than just the payload! Both the new and the old state are here, as well as the full range of attributes that Home Assistant tracks.

But how to use this information? To get the latitude and longitude here we would refer to them as:


This can get slightly more complicated if the information is contained in a different data type, such as an array or object. If, like me, you are not a programmer you may want to keep this basic overview of data types in javascript handy if you are having trouble figuring out the syntax.



Now that we can see there’s more to the msg than the payload, let’s use it to make our automations more useful. It’s great to be able to turn a light on or off, but what if we want our automation to set the brightness dynamically?


The call service Home Assistant node will look for a data object in the msg.payload. Anything it finds in the data object will be used to override the settings you entered in the call service node. The syntax for this looks like:

msg.payload = { "data": {"entity_id":"light.bedroom","brightness": 255 } }

Using an inject node, set the msg.payload to JSON and enter the above value. Since we are sending all the information necessary to make the service call, we can just leave the “Data” field blank in the output with a pair of brackets { }.


Inject Node

Inject Node

Service Call Node

Service Call Node

Flow JSON:

[{"id":"aa2c6a07.d910d8","type":"inject","z":"86cf38de.45d048","name":"","topic":"","payload":"{ \"data\": {\"entity_id\":\"light.bedroom\",\"brightness\": 255 } }","payloadType":"json","repeat":"","crontab":"","once":false,"x":170,"y":260,"wires":[["992a58f4.573ad8"]]},{"id":"992a58f4.573ad8","type":"api-call-service","z":"86cf38de.45d048","name":"Service Call","server":"8ac3cd7f.58d3e","service_domain":"light","service":"turn_on","data":"{ }","x":430,"y":260,"wires":[]},{"id":"8ac3cd7f.58d3e","type":"server","z":"","name":"Home Assistant","url":"http://localhost:8123","pass":"YOURPASS"}]

Deploy the flow and press the button on the inject node: boom! Now our service call outputs can accept a range of commands from upstream in the flow, determined programmatically instead of hardcoded into the automation.


You can easily set values for msg.payload.data in your flows using function, change, and set nodes (among others). Another way, pointed out by a very helpful poster on the Hass forums, is to use a template node set to output JSON.

Using a Template Node

Using a Template Node


Morning Radio

Morning Radio

As part of my alarm clock sequence, I want to gradually fade in the volume of the local public radio station so I can wake up to the morning news and traffic. I have an inexpensive Onkyo TX stereo receiver that integrates really well with Home Assistant.

RELATED >>  Useful Sensor: Cardinal Wind Direction for Home Assistant

This flow turns on the receiver, which requires some delays for it to power up and connect to the network before it will accept commands. Once it’s online, it begins a simple loop using the looptimer node.


Simple Node-Red Loop

Simple Node-Red Loop

Once started, the loop runs every 25 seconds. It gets the current stereo volume, adds 5 points to that value with a function node, and sends that new volume as a data override to the service call output.

Function nodes use javascript (if you prefer Python, there’s a node for that). Again, take careful note of the data types. The msg.payload in this case comes in as a string, in order to perform math on it I had to convert it to a float. I then returned the new volume as a data object in the payload.

newmsg = Object();

old_vol = parseFloat(msg.payload);
new_vol = old_vol + 0.05;

newmsg.payload = { data: { 'entity_id': 'media_player.stereo','volume_level': new_vol } };
return newmsg;

Now, I could just set the upper maximums on the looptimer node to quit when it’s reached the level I want. I’m going to make this more complicated than necessary though because I can.


Another useful logic node is the traffic light. It can be turned red or green, and accordingly will either drop or forward the messages through based on it’s state. In order for this to make sense, read the documentation on both the traffic light and the looptimer to see how these nodes are controlled via messages.

Loop Threshold

Loop Threshold

In my example, the traffic light is turned to GREEN (messages allowed through) when the loop starts. The volume of the stereo is monitored with a state change node through another function – if above 45, send a STOP message to the traffic light. Because the light is GREEN, the STOP message is forwarded to the looptimer node, which is the signal to turn itself off. On completion of the loop, the looptimer outputs a stopped message through it’s second output, which goes back to the traffic light and switches the traffic light to RED, blocking future volume changes from activating the loop again.

I thought it was kind of interesting that these two nodes, which effectively cancel each other out, visually form an “X” with their wires.


Copy this to import the whole flow into Node-Red:

[{"id":"ec1c1cc0.89f0a","type":"link in","z":"20e65bf6.292fb4","name":"","links":["829f9430.fc3088","b73a76c2.703498"],"x":60.00002670288086,"y":1669.9999589920044,"wires":[["fee08205.45787"]]},{"id":"41b5a4e4.9cae8c","type":"comment","z":"20e65bf6.292fb4","name":"Fade in NPR with Alarm","info":"","x":143.33335494995117,"y":1623.3333101272583,"wires":[]},{"id":"d844d3fa.5a26d","type":"switch","z":"20e65bf6.292fb4","name":"","property":"payload","propertyType":"msg","rules":[{"t":"eq","v":"on","vt":"str"}],"checkall":"true","outputs":1,"x":335.66672134399414,"y":1923.3331894874573,"wires":[["99146127.9daf4","6b99dd1f.172194"]]},{"id":"1b9b043f.e39a8c","type":"server-state-changed","z":"20e65bf6.292fb4","name":"Stereo Volume","server":"8ac3cd7f.58d3e","entityidfilter":"sensor.stereo_volume","haltifstate":"","x":194.66672134399414,"y":2010.3331894874573,"wires":[["350a9df1.760542"]]},{"id":"350a9df1.760542","type":"function","z":"20e65bf6.292fb4","name":"> 45?","func":"newmsg = Object();\nif (msg.payload > 0.44) {\n newmsg.payload = \"STOP\";\n} else {\n newmsg.payload = \"Not Yet\";\n}\nreturn newmsg;","outputs":1,"noerr":0,"x":195.66672134399414,"y":2063.3331894874573,"wires":[["49e87859.3c9e68"]]},{"id":"49e87859.3c9e68","type":"switch","z":"20e65bf6.292fb4","name":"","property":"payload","propertyType":"msg","rules":[{"t":"eq","v":"STOP","vt":"str"}],"checkall":"true","outputs":1,"x":335.66672134399414,"y":2063.3331894874573,"wires":[["6b99dd1f.172194"]]},{"id":"7d6b19a8.1c3058","type":"switch","z":"20e65bf6.292fb4","name":"","property":"payload","propertyType":"msg","rules":[{"t":"eq","v":"STOP","vt":"str"}],"checkall":"true","outputs":1,"x":546.6667404174805,"y":1984.6664643287659,"wires":[["99146127.9daf4"]]},{"id":"99146127.9daf4","type":"looptimer","z":"20e65bf6.292fb4","duration":"25","units":"Second","maxloops":"15","maxtimeout":"10","maxtimeoutunits":"Minute","name":"Turn Up Volume","x":732.3333702087402,"y":1922.3331718444824,"wires":[["3632c93f.a0b866"],["6b99dd1f.172194"]]},{"id":"6b99dd1f.172194","type":"traffic","z":"20e65bf6.292fb4","name":"","property_allow":"payload","filter_allow":"on","ignore_case_allow":false,"negate_allow":false,"send_allow":false,"property_stop":"payload","filter_stop":"stopped","ignore_case_stop":false,"negate_stop":false,"send_stop":false,"default_start":false,"differ":false,"x":555.6667442321777,"y":2062.3332085609436,"wires":[["7d6b19a8.1c3058"]]},{"id":"325e1bca.fc58d4","type":"comment","z":"20e65bf6.292fb4","name":"Loop","info":"","x":960.0000610351562,"y":1931.3332405090332,"wires":[]},{"id":"3632c93f.a0b866","type":"api-current-state","z":"20e65bf6.292fb4","name":"Stereo Volume","server":"8ac3cd7f.58d3e","halt_if":"","entity_id":"sensor.stereo_volume","x":990.5000495910645,"y":1973.3332934379578,"wires":[["1aeb6c59.1a9474"]]},{"id":"1aeb6c59.1a9474","type":"function","z":"20e65bf6.292fb4","name":"+5 Volume","func":"newmsg = Object();\n\nold_vol = parseFloat(msg.payload);\nnew_vol = old_vol + 0.05;\n\nnewmsg.payload = { data: { 'entity_id': 'media_player.stereo','volume_level': new_vol } }\n\nreturn newmsg;","outputs":1,"noerr":0,"x":998.0000076293945,"y":2019.9999270439148,"wires":[["d001ed10.c8e12"]]},{"id":"d001ed10.c8e12","type":"api-call-service","z":"20e65bf6.292fb4","name":"Turn Up Volume","server":"8ac3cd7f.58d3e","service_domain":"media_player","service":"volume_set","data":"{\"entity_id\":\"media_player.stereo\"}","x":1199.1666679382324,"y":2020.3333044052124,"wires":[]},{"id":"99e3766f.1769d8","type":"api-current-state","z":"20e65bf6.292fb4","name":"Receiver On?","server":"8ac3cd7f.58d3e","halt_if":"","entity_id":"switch.dualplug_right","x":181.3333854675293,"y":1729.9999380111694,"wires":[["ee90183e.999a08"]]},{"id":"ee90183e.999a08","type":"switch","z":"20e65bf6.292fb4","name":"","property":"payload","propertyType":"msg","rules":[{"t":"eq","v":"on","vt":"str"},{"t":"eq","v":"off","vt":"str"}],"checkall":"true","outputs":2,"x":344.3333854675293,"y":1729.9999380111694,"wires":[["84655780.58a0f8"],["4caef560.20d36c","84655780.58a0f8"]]},{"id":"4caef560.20d36c","type":"api-call-service","z":"20e65bf6.292fb4","name":"Turn On Receiver","server":"8ac3cd7f.58d3e","service_domain":"switch","service":"turn_on","data":"{\"entity_id\":\"switch.dualplug_right\"}","x":760.3333854675293,"y":1733.9999380111694,"wires":[]},{"id":"84655780.58a0f8","type":"delay","z":"20e65bf6.292fb4","name":"Let it Turn On - 50s","pauseType":"delay","timeout":"50","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"x":286.8333854675293,"y":1783.9999589920044,"wires":[["813154b7.868cc8","6d45ef3c.29bba"]]},{"id":"813154b7.868cc8","type":"api-call-service","z":"20e65bf6.292fb4","name":"Set Volume to 0","server":"8ac3cd7f.58d3e","service_domain":"media_player","service":"volume_set","data":"{\"entity_id\":\"media_player.stereo\",\"volume_level\":\"0.10\"}","x":750.3333854675293,"y":1783.9999380111694,"wires":[]},{"id":"e42b6f68.f7683","type":"api-call-service","z":"20e65bf6.292fb4","name":"Switch Receiver to FM","server":"8ac3cd7f.58d3e","service_domain":"media_player","service":"select_source","data":"{\"entity_id\":\"media_player.stereo\",\"source\":\"fm\"}","x":771.3333854675293,"y":1832.9999380111694,"wires":[]},{"id":"585bee5f.37de9","type":"change","z":"20e65bf6.292fb4","name":"Turn On Loop","rules":[{"t":"set","p":"payload","pt":"msg","to":"on","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":304.58337783813477,"y":1875.8332796096802,"wires":[["d844d3fa.5a26d"]]},{"id":"6d45ef3c.29bba","type":"delay","z":"20e65bf6.292fb4","name":"","pauseType":"delay","timeout":"50","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"x":515.8333854675292,"y":1824.9999380111692,"wires":[["e42b6f68.f7683","585bee5f.37de9"]]},{"id":"fee08205.45787","type":"api-current-state","z":"20e65bf6.292fb4","name":"Want Music?","server":"8ac3cd7f.58d3e","halt_if":"off","entity_id":"input_boolean.alarmradio","x":168.1667137145996,"y":1670.6666860580444,"wires":[["99e3766f.1769d8"]]},{"id":"21f780ba.d339d","type":"comment","z":"20e65bf6.292fb4","name":"Turn On Receiver & Prep it","info":"","x":776.6666679382324,"y":1679.999924659729,"wires":[]},{"id":"b0732620.9a2ae8","type":"comment","z":"20e65bf6.292fb4","name":"Volume Threshold","info":"","x":201.66669845581055,"y":1968.333176612854,"wires":[]},{"id":"8ac3cd7f.58d3e","type":"server","z":"","name":"Home Assistant","url":"http://localhost:8123","pass":"YOURPASS"}]


Hopefully by now, you can start to see the power of using Node-Red for your Home Assistant automations. With an understanding of how the message is handled and how to dynamically interact with Home Assistant almost anything is possible.

I have only used a few nodes here, there are many, many more – each of which can be added to your flows to greatly expand the possibilities. Take a look through Node Red’s library to see a list of community contributed nodes.

If you’ve found any novel nodes or made cool things with them, please post in the comments below!



11 Replies to “Going Further with Home Automations in Node-Red”

  1. Kevin says:

    These node-red articles are really well done! I felt compelled to recreated my automations in node-red for testing purposes. I’m fairly impressed with how easy ::most:: of it was! The flow/GUI aspect of node-red is amazing; Home Assistant could use a visualization tool like node-red!

    I do think you overstate the simplicity of node-red &&& the complexity of yaml. Even my most simple automations are longer (in terms of flow and generated json) compared to the yaml configuration.

    I’m also torn by introducing another software stack into my setup. It was not complicated to install node-red, but it is another thing to worry about breaking – itself, its integration with HA, etc.

    So thanks for these great articles, introducing me to a new tool. Home automations is a learning process!

    • brad says:

      Thanks for the reply, glad you found it helpful! I don’t think YAML is hard, it’s just limiting. Like, how do you do a simple if-then? Or a loop? There are ways to work around those things, or you can do it in Python, but it’s not intuitive to me. There’s also this kind of catch-22: if your configuration is even moderately complicated you need to split everything out into multiple YAML files, but then when you work on something with multiple parts, the pieces of it are all over the place. And then how do you debug it? I was going around waving my hand in front of motion sensors etc trying to see if things actually worked!

      Not a big deal if you’re just scheduling some lights, but for the more complicated stuff I felt like I was struggling against it. And the constant restarting of HA for every tiny change…

      I was hesitant to add more software, but so far so good for me. Very stable & haven’t had any issues. The nodes to integrate with HA are just making API calls.

  2. Alex says:

    I’ve been following your blog which has been a huge help in getting my Node Red environment up and running. I’m trying to wrap my head around how to pull specific attribute information from an HA entity so I can pass the value into a NR chart object.

    I can see the attribute I’m interested in, when I debug the Current State node that’s pulling the data from HA. What I’m stuck on is how to get the specific JSON value I need from the payload.

    I’ve tried setting the output of the Current State node to reflect the JSON syntax for the value I need, but it doesn’t seem to be right.

    Can you give me any pointers?

    • brad says:

      If you send the output of the Current State node to a debug node (set to “whole object” not just the payload) you should see all the information available to you in a tree. This will tell you what the information is called. ex: msg.payload.old_state.state is the specific value for that piece of data in the payload.

      There are then a lot of ways to access that information. Send the output of your Current State node to a Change node. Have that Change node “Set” the msg.payload to “msg.payload.old_state.state” – if you want to pass that piece of info to the next one as the payload. You can also take a look at the Function nodes (for manipulating the payload data with simple javascript) or the Template node (if you’d rather use JSON to create a new msg).

  3. Djiwondee says:

    Hello Brad,

    I would be interested in how you have integrated your Onkyo AVR with node-red. I this also explained somewhere else in your blog?

    • brad says:

      I was using the Home Assistant component, but there appears to be a long running bug with selecting the input on my model.

      I sort of came up with my own solution using “Universal Media Player” component and a Broadlink IR unit.

  4. Djiwondee says:

    Hello Brad,
    thanks for your reply. In the meantime I did my own exercises with:
    https://github.com/miracle2k/onkyo-eiscp and use this by executing commands from node-red. It works quite well and selecting input as well as control volume, station preset and power on/off. So at least thanks for the inspiration with the wake up timer!

  5. Chris says:

    Hello Brad,

    Why the need for the Traffic Light node? Why not just have the Function node return msg.payload to “stop” only if Volume is >= 45 and send that to the Loop Timer node to stop it?

  6. […] Going Further with Home Automations in Node-Red – DIY Futurism (diyfuturism.com) Portland, Oregon #homeassistant #node-red Mon, Sep 2, 2019 9:58am -07:00 Have you written a response to this? Let me know the URL: […]

  7. Hey Brad,
    Thanks for the write up. I’m trying to see if I can condition the flow based on the effect of a light. I know it’s located at data.attributes.effect when I pass it through the current state node to debug. However, setting the STATE LOCATION to data.attributes.effect doesn’t do what I’d expect. It only comes back with “on” rather than the name of the effect (Pulse YELLOW).

Leave a Reply

Your email address will not be published. Required fields are marked *