How can I call an HA service from a function node?

I have a function node that possibly needs to run between 0-5 service calls to HA based on the data it receives. What’s the easiest way to do that?

Use node.send and multiple outputs where each output maps to a particular call service node. Basically your code would look kinda like this:

if (msg.something === "option_1"){
  node.send([null, null, msg, null, null]);
}
else if (msg.something === "option_2"){
  node.send([null, msg, null, msg, null])
}
...

Obviously you’d also have to craft the msg object from the available data needed to make the service call before sending it.

2 Likes

Oh! That’s neat. I think all I need is a node.send for each, as all I need to do is asynchronously call the same service with different entities.

Thanks!

1 Like

Although this is an older post, I have been searching for a solution to make Node-RED work with various entities asynchronously, and I wanted to share my approach. I use a function node with the following logic:

const states = global.get('homeassistant.homeAssistant.states');

const lights = {
    bathroom: states['light.bathroom_lights_group'],
    bedroom: states['light.bedroom_lights_group'],
    kitchen: states['light.kitchen_lights_group'],
    livingRoom: states['light.living_room_lights_group'],
    office: states['light.office_lights_group'],
    stairs: states['light.stairs_lights_group'],
    workshop: states['light.workshop_lights_group'],
}

for (const lightId in lights)
{
    const light = lights[lightId]

    if(light && light.state && light.state === 'on')
    {
        node.send({
            payload: {
                "domain": "light",
                "target": { 
                    "entity_id": light.entity_id 
                    },
                "service": "turn_off"
                }
        });
    }
}

node.done();
  • runtime needs to know when the function node has completed its asynchronous work so node.done() is called

  • there should be no “return msg;” at the end in function node.

This is how flow in node red looks like in a nutshell:
Trigger Node > Function Node > Call Service Node

The Call Service node only needs to have the domain defined, which is “light” in my case. All other information will come from the “node.send()” method.

You can send that as well, you can leave a call service completely blank. You already have domain defined in the function. Also sending this message format to a defined call service, will override it’s settings.

Asynchronous is used to send a message while the node continues to do more work. For a simple statement like yours there is no reason to use asynchronous send.