Basic Node-Red Flows for Automating Lighting with Home Assistant

Smart light bulbs are probably the first thing everyone getting into home automation buys. It is easy to see the applications for them – have the lights come on at night, turn off when you’re home, etc. It’s very satisfying to have the lights react to the day and your activities, and my goal with automating lighting has always been to not have to think about it, for it to work in the background.

In my initial post about Home Assistant and Node-Red, I explained the initial hoops you have to jump through to get both pieces of software up and running and talking to each other. Now we will start using them together in some very simple flows to control lighting, to get a better understanding of how Node-Red works, and to start to delve into this powerful tool.


SPLIT PERSONALITY

The way I approach making automations is to think of Home Assistant as a state machine. It’s job is to track all the states of the devices, and to call services to change those states. All the hardware interfacing – the communication between the hub and the device and interpreting that information – is all Home Assistant. Home Assistant is a giant catalog of data (states) and actions (services) that Node-Red can draw from.

Node-Red, on the other hand, is our brain. Node-Red performs the logic. Node-Red doesn’t have to keep track of states or know how to talk to a Philips Hue bulb and a Wemo smart switch, Node-Red just asks Home Assistant when it needs to know the state of something. When Node-Red makes a decision, it sends the command (service) back to Home Assistant to handle. Node-Red is all about the big picture.

This simple separation of duties in our automations will make integrating much easier.


LIGHTING ONE: SIMPLE BINARY

I have a light bulb in an awkward crawl space that is really hard to reach. Every once in a while I need to reach a breaker in there and can never find the switch. So I replaced the bulb with a cheap smart bulb and added a door sensor. When the door opens, the light comes on, when it’s closed, the light is off.

[{"id":"70a001ee.bfd2e","type":"server-state-changed","z":"18835ede.3f82d1","name":"Crawl Space Door","server":"8ac3cd7f.58d3e","entityidfilter":"binary_sensor.crawl_space_door","haltifstate":"","x":131.4206886291504,"y":544.5259022712708,"wires":[["d0ccbd28.cb728"]]},{"id":"d0ccbd28.cb728","type":"switch","z":"18835ede.3f82d1","name":"","property":"payload","propertyType":"msg","rules":[{"t":"eq","v":"on","vt":"str"},{"t":"eq","v":"off","vt":"str"}],"checkall":"true","outputs":2,"x":299.98705673217773,"y":544.2827610969543,"wires":[["5e9a8806.36d148"],["6123b169.361c9"]]},{"id":"5e9a8806.36d148","type":"api-call-service","z":"18835ede.3f82d1","name":"ON","server":"8ac3cd7f.58d3e","service_domain":"light","service":"turn_on","data":"{\"entity_id\":\"light.crawl_space\"}","x":444.8025550842285,"y":516.2688345909119,"wires":[]},{"id":"6123b169.361c9","type":"api-call-service","z":"18835ede.3f82d1","name":"OFF","server":"8ac3cd7f.58d3e","service_domain":"homeassistant","service":"turn_off","data":"{\"entity_id\":\"light.crawl_space\"}","x":445.87427139282227,"y":567.6973919868469,"wires":[]},{"id":"8ac3cd7f.58d3e","type":"server","z":"","name":"Home Assistant","url":"http://localhost:8123","pass":"XXXXX"}]

Our input is a Home Assistant state node that monitors the door sensor. When a state change is detected, it’s sent as a message to the next node, a switch.

If the message (msg.payload in Node-Red terms) is on, route to output 1, if it’s off, route to output 2. These outputs end in Home Assistant service calls that turn the light on or off.

 

You must hit the “DEPLOY” to save and activate your flow.

Congrats, this is the entire process of creating an automation with Node-Red.

LIGHTING TWO: MOTION TIMER

Let’s do something more interesting. For this example we will need an extra node called stoptimer, which can be installed through “Manage palette” in the Node-Red menu. When stoptimer receives a message, the timer starts. If it receives another message the timer is reset. If it gets a message that says “STOP” then it cancels the timer. Pretty useful.

I have a motion sensor under my office desk, when I sit down the lights come on. If I walk away I want the lights to turn off – say after 20 minutes of no activity.

[{"id":"6b710453.81dbac","type":"server-state-changed","z":"4056fc4f.0baa64","name":"Office Motion","server":"8ac3cd7f.58d3e","entityidfilter":"binary_sensor.office_motion","haltifstate":"","x":190,"y":380,"wires":[["994dd149.e4555"]]},{"id":"19caec7f.e0b4d4","type":"stoptimer","z":"4056fc4f.0baa64","duration":"20","units":"Minute","payloadtype":"num","payloadval":"0","name":"20min","x":550,"y":420,"wires":[["a9408fec.408e1"],[]]},{"id":"a9408fec.408e1","type":"api-call-service","z":"4056fc4f.0baa64","name":"OFF","server":"8ac3cd7f.58d3e","service_domain":"homeassistant","service":"turn_off","data":"{\"entity_id\":\"group.Office\"}","x":1010,"y":414,"wires":[]},{"id":"fa446f4f.1df58","type":"api-call-service","z":"4056fc4f.0baa64","name":"ON","server":"8ac3cd7f.58d3e","service_domain":"homeassistant","service":"turn_on","data":"{\"entity_id\":\"group.Office\"}","x":1010.1666526794434,"y":373.95236015319824,"wires":[]},{"id":"994dd149.e4555","type":"switch","z":"4056fc4f.0baa64","name":"","property":"payload","propertyType":"msg","rules":[{"t":"eq","v":"on","vt":"str"},{"t":"eq","v":"off","vt":"str"}],"checkall":"true","outputs":2,"x":350,"y":380,"wires":[["19caec7f.e0b4d4","da14546c.577218"],["19caec7f.e0b4d4"]]},{"id":"da14546c.577218","type":"api-current-state","z":"4056fc4f.0baa64","name":"Already On?","server":"8ac3cd7f.58d3e","halt_if":"on","entity_id":"switch.office","x":748,"y":373,"wires":[["fa446f4f.1df58"]]},{"id":"8ac3cd7f.58d3e","type":"server","z":"","name":"Home Assistant","url":"http://localhost:8123","pass":"XXXXX"}]

We’ve added a few nodes to our first example, let’s follow the flow.

If Office Motion is on, the switch sends it down two paths simultaneously:

  • A state node that looks up the state of group.office. If it’s already on, the flow halts, otherwise the lights are turned on
  • Starts or resets the 20 minute stoptimer if it’s already running. If no other state changes come from the Office Motion sensor, the msg.payload terminates in an off service command.
RELATED >>  The Open Source Smart Home: Getting Started with Home Assistant & Node-Red

If Office Motion is off, it starts or resets the timer.

This keeps the lights on as long as something is happening with the motion sensor. When there’s been no activity for 20 minutes, the timer reaches it’s conclusion and the msg.payload is sent to the output to turn the light off.

Note in the “Already On?” node we can halt the flow according to the state it returns:

The alternative would be to use a switch node, but this saves us the trouble. In Home Assistant terminology, this is equivalent to a condition.

LIGHTING THREE: MOTION, TIME RANGE, & OCCUPANCY

Now that’s we’ve done two simple examples, let’s start to show off the real power of Node-Red. For this one we’re going to need another additional node, the time range switch. I’m also using a meta-motion sensor that shows where Home Assistant last saw motion.

[{"id":"4876c05d.90497","type":"server-state-changed","z":"4056fc4f.0baa64","name":"Bathroom Motion","server":"8ac3cd7f.58d3e","entityidfilter":"binary_sensor.bathroom_motion","haltifstate":"off","x":220,"y":420,"wires":[["e25bff84.3451d"]]},{"id":"e25bff84.3451d","type":"time-range-switch","z":"4056fc4f.0baa64","name":"After 6AM","lat":"","lon":"","startTime":"06:00","endTime":"23:59","x":403.333309173584,"y":419.9999780654907,"wires":[["e6559f89.5c606","ec4009c3.5b4c48"],[]]},{"id":"e6559f89.5c606","type":"api-current-state","z":"4056fc4f.0baa64","name":"Light Off?","server":"8ac3cd7f.58d3e","halt_if":"on","entity_id":"switch.bathroom_light","x":573.3334007263184,"y":381.33339405059814,"wires":[["13aee75f.de9699"]]},{"id":"13aee75f.de9699","type":"api-call-service","z":"4056fc4f.0baa64","name":"ON","server":"8ac3cd7f.58d3e","service_domain":"switch","service":"turn_on","data":"{\"entity_id\":\"switch.bathroom_light\"}","x":1034.9999504089355,"y":382.99997901916504,"wires":[]},{"id":"1c5dbbe7.4de5e4","type":"api-render-template","z":"4056fc4f.0baa64","name":"Still in Bathroom?","server":"8ac3cd7f.58d3e","template":"{{ states.variable.last_motion.state != 'Bathroom Motion' }}","x":743.3333396911621,"y":440.0000238418579,"wires":[["67242a38.922154"]]},{"id":"ec4009c3.5b4c48","type":"stoptimer","z":"4056fc4f.0baa64","duration":"12","units":"Minute","payloadtype":"num","payloadval":"0","name":"12min","x":560.0000190734863,"y":446.6667079925537,"wires":[["1c5dbbe7.4de5e4"],[]]},{"id":"67242a38.922154","type":"switch","z":"4056fc4f.0baa64","name":"","property":"payload","propertyType":"msg","rules":[{"t":"eq","v":"True","vt":"str"}],"checkall":"true","outputs":1,"x":908.3333015441895,"y":440.00000286102295,"wires":[["e1e6dad7.9a0dc8"]]},{"id":"e1e6dad7.9a0dc8","type":"api-call-service","z":"4056fc4f.0baa64","name":"OFF","server":"8ac3cd7f.58d3e","service_domain":"homeassistant","service":"turn_off","data":"{\"entity_id\":\"group.bathroom\"}","x":1037.5001754760742,"y":440.00003147125244,"wires":[]},{"id":"ed231cde.fc99","type":"server-state-changed","z":"4056fc4f.0baa64","name":"Bathroom Switch Flipped On","server":"8ac3cd7f.58d3e","entityidfilter":"switch.bathroom_light","haltifstate":"off","x":353.33336639404297,"y":495.0001130104065,"wires":[["ec4009c3.5b4c48"]]},{"id":"8ac3cd7f.58d3e","type":"server","z":"","name":"Home Assistant","url":"http://localhost:8123","pass":"XXXXX"}]

In my bathroom I’ve got a motion sensor and a Z-Wave wall switch that controls the light. I want the light to turn off after 12 minutes of no motion, but not if I’m still… taking care of business. The switch should trigger the same timer if someone uses it. And also – I don’t want to get blinded if I get up in the middle of the night.

Following the flow, the state of the Bathroom Motion sensor is sent to the time-range switch, which will only continue if it’s after 6AM. After that we essentially do the same thing as the last example, checking to see if the light is already on before calling the light.turn_on service. The stop timer accepts another input from the wall switch if guests use it.

After the timer concludes, it gets the state of the meta-motion sensor and the switch evaluates if I’m still in the Bathroom before turning the light off.

LIGHTING FOUR: SOLAR EVENT TRIGGER

What about having the lights turn on at sunset? There’s more than one node for that. Here I am using bigtimer because it allows offsetting solar events. You can read the documentation for bigtimer, it’s kind of more complicated than it needs to be IMO, but it’s useful here for turning my aquarium on at sunset and off at 10pm.

[{"id":"c49b6101.4865","type":"bigtimer","z":"59230ccd.4625e4","outtopic":"","outpayload1":"","outpayload2":"","name":"Sunset","lat":"37.799564008","lon":"-122.268797","starttime":"5004","endtime":"5003","startoff":"-60","endoff":"240","offs":0,"outtext1":"on","outtext2":"off","timeout":1440,"sun":true,"mon":true,"tue":true,"wed":true,"thu":true,"fri":true,"sat":true,"jan":true,"feb":true,"mar":true,"apr":true,"may":true,"jun":true,"jul":true,"aug":true,"sep":true,"oct":true,"nov":true,"dec":true,"day1":0,"month1":0,"day2":0,"month2":0,"day3":0,"month3":0,"day4":0,"month4":0,"day5":0,"month5":0,"d1":0,"w1":0,"d2":0,"w2":0,"d3":0,"w3":0,"d4":0,"w4":0,"d5":0,"w5":0,"suspend":false,"random":false,"repeat":true,"atstart":true,"odd":false,"even":false,"x":353.75000381469727,"y":428.7500057220459,"wires":[[],[],["c6e50538.2732a8"]]},{"id":"c6e50538.2732a8","type":"switch","z":"59230ccd.4625e4","name":"","property":"payload","propertyType":"msg","rules":[{"t":"eq","v":"on","vt":"str"},{"t":"eq","v":"off","vt":"str"}],"checkall":"true","outputs":2,"x":593.1337394714355,"y":406.8185729980469,"wires":[["4c8b4d1b.32ece4"],["db50b01e.eea8e"]]},{"id":"893ff0c6.accba","type":"api-call-service","z":"59230ccd.4625e4","name":"Turn off Aquarium","server":"8ac3cd7f.58d3e","service_domain":"switch","service":"turn_off","data":"{\"entity_id\":\"switch.aquarium\"}","x":990.0001640319824,"y":446.24994373321533,"wires":[]},{"id":"4c8b4d1b.32ece4","type":"api-call-service","z":"59230ccd.4625e4","name":"Turn on Aquarium","server":"8ac3cd7f.58d3e","service_domain":"switch","service":"turn_on","data":"{\"entity_id\":\"switch.aquarium\"}","x":989.3838424682617,"y":382.6952495574951,"wires":[]},{"id":"bc733e16.0eb51","type":"inject","z":"59230ccd.4625e4","name":"10pm","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"00 22 * * *","once":false,"x":600.6250152587891,"y":444.9523983001709,"wires":[["893ff0c6.accba"]]},{"id":"db50b01e.eea8e","type":"api-current-state","z":"59230ccd.4625e4","name":"Off Already?","server":"8ac3cd7f.58d3e","halt_if":"off","entity_id":"switch.aquarium","x":762.4783706665039,"y":422.348180770874,"wires":[["893ff0c6.accba"]]},{"id":"8ac3cd7f.58d3e","type":"server","z":"","name":"Home Assistant","url":"http://localhost:8123","pass":"XXXXXX"}]

MORE LINKS

Hopefully now you’ve got a better idea of some of the things that are possible using just a handful of nodes with Home Assistant. I’ve got a big list of nodes I’ve used in home automation linked below if you want to explore some more.

One of the great things about Node-Red is how easy it is to share flows. Copy from the pastebin link below to get all the flows here and start automating your lights immediately!

18 Comments

  1. Thanks a lot for the great and detailed post. I try to use also node red for my home assistant automation. But i have problems with the current state node, it is always off.
    Due you have any idea why this is the case ? Would be great if you could have a look:

    [{“id”:”23462cfb.475464″,”type”:”switch”,”z”:”3933a201.bdd7ae”,”name”:”button_click”,”property”:”payload.event.click_type”,”propertyType”:”msg”,”rules”:[{“t”:”eq”,”v”:”single”,”vt”:”str”},{“t”:”eq”,”v”:”hold”,”vt”:”str”}],”checkall”:”true”,”outputs”:2,”x”:534.2475891113281,”y”:364.9352340698242,”wires”:[[“9dd96177.eb1e9″],[]],”outputLabels”:[“single”,”hold”]},{“id”:”cdc0d0df.b3f62″,”type”:”switch”,”z”:”3933a201.bdd7ae”,”name”:”switch_158d000152d6cc”,”property”:”payload.entity_id”,”propertyType”:”msg”,”rules”:[{“t”:”eq”,”v”:”binary_sensor.switch_158d0001a674c3″,”vt”:”str”}],”checkall”:”true”,”outputs”:1,”x”:335.2500762939453,”y”:365.49078369140625,”wires”:[[“23462cfb.475464”]]},{“id”:”7daff023.9cab”,”type”:”server-events”,”z”:”3933a201.bdd7ae”,”name”:””,”server”:”79ffe1ba.7d31e”,”x”:105,”y”:363.3515567779541,”wires”:[[“cdc0d0df.b3f62”]]},{“id”:”9dd96177.eb1e9″,”type”:”api-current-state”,”z”:”3933a201.bdd7ae”,”name”:”Light on ?”,”server”:”79ffe1ba.7d31e”,”halt_if”:”off”,”entity_id”:”switch.wall_switch_left_158d00012bad84″,”x”:685.0962829589844,”y”:314.2708396911621,”wires”:[[“9cf7568b.2681d8”]]},{“id”:”9cf7568b.2681d8″,”type”:”api-call-service”,”z”:”3933a201.bdd7ae”,”name”:”OFF”,”server”:”79ffe1ba.7d31e”,”service_domain”:”homeassistant”,”service”:”turn_off”,”data”:”{\”entity_id\”:\”switch.wall_switch_left_158d00012bad84\”}”,”x”:841.0129890441895,”y”:359.0104064941406,”wires”:[]},{“id”:”79ffe1ba.7d31e”,”type”:”server”,”z”:””,”name”:”Home Assistant”,”url”:”http://localhost:8123″,”pass”:”xxxx”}]

    Greetings,

    Reply

    1. I see, so your switch does not change states, it generates an event? I do not have any hardware that behaves this way so am unable to test it, but your flow seems like you are on the right track with the “events all” node and then filtering based on that. I would use the debug nodes to narrow down what is happening here. Also see the commenter below, who seems to be dealing with the same issue you are – you might want to look into HA’s MQTT Event stream feature, might be a simpler way of accomplishing this.

      Reply

  2. Hello, thanks for putting this out there. I have the dashboard and Hue add ons installed and working and now want to control some hassio components that are not Hue. I am having difficulties with the node-red-contrib-home-assistant v0.2.0 component that are likely simple. In the simple binary example, I get nothing from either output 1 or 2 of the function switch looking for true or false when triggered from a dashboard switch. The dashboard switch only gives a true or false boolean payload which should be routed through the function switch to services that either turn_on or turn_off a light or fan domain. My goal is to make a dashboard to display on a wink relay that controls on/off, brightness and color looping of a bedside hue lamp and also a Hampton Bay fan controller lamp on/off and brightness as well as fan on/off and speed. I have the hue lamp portion working.

    Reply

    1. Thanks for the comment, the dashboard node looks very cool, that is definitely my next project!

      I would hook a debug node up to your input (the dashboard switch) and see what exactly it is sending as a message. I bet this is some kind of formatting issue, and once you see it in the debug node it will probably be obvious.

      One thing to watch for – make sure the evaluation in the string matches the message type the switch is sending. This varies based on the input node you are using. In your case is the dashboard switch actually sending a boolean (if so, evaluate with ‘is true’ or ‘is false’ in the switch) or is it sending it as a string (if so, use == “True” in the switch).

      In my example above, my input is a string (the words “on” or “off”) so I am matching the words, not a boolean state.

      Reply

    1. Interesting I see, so the button is generating an event instead of a state change. It looks like you need to use the ‘events all’ node, and then filter out (switch node) the event your button is creating. I haven’t done that but that should work.

      An alternative solution you might find useful is to the HA MQTT Eventstream: https://home-assistant.io/components/mqtt_eventstream/

      edit: Looks like commenter above has same issue, please post back if you resolve it.

      Reply

  3. Hey brad,

    thanks a lot. But the problem isn’t that the switch send an event,
    as you mentioned it is quite easy to react to it and to filter the right events.

    The problem is that for some reason the “current state” node always,
    provides off for the flow i posted.

    Do you know if the “current state” node is requesting it data from homeassistant or if it simple parses the input ? If it just parses the input it would explain everything.

    Thanks

    Reply

    1. “Current state” requests the data from Home Assistant, and it should replace the message with that state. The input just begins the request. That is strange behavior, I am not sure what your issue is, it appears fine when I import it into my Node-Red.

      Does “current state” give the appropriate response in other flows, or getting the state of other entities? I wonder if there is some other issue going on here. You may want to try uninstalling/reinstalling the Home Assistant nodes, I have seen a few comments suggesting this might clear up unexpected behavior.

      Reply

  4. Hello, ch comments that it is ‘easy to react to it and to filter the right events’ but i’m not experiencing that. I’ve been trying to send a current fan speed to a dashboard dropdown so that the dropdown is current and am having difficulty (pulling my hair out, actually) doing so. I only see the changed state from the events_all node and the message is:1/8/2018, 6:10:34 PMnode: a5c95c.e59b86a8
    state_changed : msg.payload : Object
    object
    event_type: “state_changed”
    entity_id: “fan.hannahs_fan”
    event: object
    entity_id: “fan.hannahs_fan”
    old_state: object
    entity_id: “fan.hannahs_fan”
    state: “on”
    attributes: object
    speed: “lowest”
    speed_list: array[5]
    manufacturer_device_model: “home_decorators_home_decorators_fan”
    device_manufacturer: “home_decorators”
    model_name: “Ceiling Fan”
    friendly_name: “Hannahs Fan”
    supported_features: 5
    last_changed: “2018-01-09T00:59:48.647143+00:00”
    last_updated: “2018-01-09T00:59:48.647143+00:00”
    new_state: object
    entity_id: “fan.hannahs_fan”
    state: “on”
    attributes: object
    speed: “low”
    speed_list: array[5]
    manufacturer_device_model: “home_decorators_home_decorators_fan”
    device_manufacturer: “home_decorators”
    model_name: “Ceiling Fan”
    friendly_name: “Hannahs Fan”
    supported_features: 5
    last_changed: “2018-01-09T00:59:48.647143+00:00”
    last_updated: “2018-01-09T01:10:34.260948+00:00”
    I’m interested in sensing the new state speed string of auto, lowest, low, medium or high to pass to the dashboard dropdown. Any help filtering to this would be greatly appreciated.

    Reply

    1. Glad you got it working, not sure if you are aware but that JSON includes your HASS password – be careful!!

      Nice flow – makes sense to me. One tip, I think maybe you could simplify it slightly. Instead of your first switch branching out to all those change nodes to set the msg.payload, I think you could use just one change node. Instead of “Set” msg.payload, try “Move” msg.payload.event.new_state.attributes.speed TO msg.payload. That should work. Could also do this with a function node too.

      Reply

  5. Hey guys,

    i figured out what the problem was. My problems comes from the implementation
    of the “current state” node. If in the payload of the “current state” a entity_id is defined, this entity_id is used instead of the one you configure in “current state” node. For me this makes no really sense and seams for me to be a bug.
    I changed the behavior so always the entity_id of the “current state” node is used.

    It works like a charm now.

    Thanks a lot.

    Reply

Leave a Reply

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