How to populate the Action Node with Function Vlaues from a Function

Hi All, I have an issue with the new and supposed improved Action node in NodeRed. Up till a few weeks ago, I was using the old Call Service Node which I believe has been deprecated, but this has left many of my automations broken.

Basically, I was using function nodes to populate fields in the call service node, something that the documentation for the action node say’s is still possible as long as you ensure that the ‘Block input overrides’ is turned off (Unchecked).

The first problem I had was, that is you leave the action field empty, when the flow is run, an error is shown on the action none saying ‘ValidationError: “action” is not allowed to be empty’. I get a similar error when I leave the device/entity field empty, ‘HomeAssistantError: must contain at least one of entity_id, device_id, area_id, floor_id, label_id.’.

After further reading of the documentation, it basically say’s fill with something, and the input values will override the existing values.

Rather than bore you with more details, here are two examples of what is happening.

Example 1 using a function node

[{“id”:“da6f835974f882e4”,“type”:“group”,“z”:“cdd1f3af1e96317f”,“name”:“Test 1”,“style”:{“label”:true},“nodes”:[“ed2b7f0f042ba8b0”,“843d5c66beb3753f”,“bed13b9a501f5406”,“5a07c720fd7d25c0”,“584c3231cabb0494”],“x”:234,“y”:419,“w”:1052,“h”:182},{“id”:“ed2b7f0f042ba8b0”,“type”:“function”,“z”:“cdd1f3af1e96317f”,“g”:“da6f835974f882e4”,“name”:“function 5”,“func”:“\nif (msg.payload === "on") msg = {"action": "light.turn_on",\n "target": {\n "entity_id": ["light.lr_desk_spot_light"]\n },\n "data": {\n "color_name": "yellow",\n "brightness_pct": 90\n },\n}\nif (msg.payload === "off")\n msg = {"action": "light.turn_off",\n };\nreturn msg;”,“outputs”:1,“timeout”:0,“noerr”:0,“initialize”:“”,“finalize”:“”,“libs”:,“x”:640,“y”:520,“wires”:[[“843d5c66beb3753f”,“bed13b9a501f5406”]]},{“id”:“843d5c66beb3753f”,“type”:“debug”,“z”:“cdd1f3af1e96317f”,“g”:“da6f835974f882e4”,“name”:“debug 2”,“active”:true,“tosidebar”:true,“console”:false,“tostatus”:false,“complete”:“true”,“targetType”:“full”,“statusVal”:“”,“statusType”:“auto”,“x”:1180,“y”:540,“wires”:},{“id”:“bed13b9a501f5406”,“type”:“api-call-service”,“z”:“cdd1f3af1e96317f”,“g”:“da6f835974f882e4”,“name”:“Test”,“server”:“49f73a6c.255cd4”,“version”:7,“debugenabled”:false,“action”:“light.turn_on”,“floorId”:,“areaId”:,“deviceId”:,“entityId”:[“light.lr_desk_spot_light”],“labelId”:,“data”:“”,“dataType”:“json”,“mergeContext”:“”,“mustacheAltTags”:false,“outputProperties”:,“queue”:“none”,“blockInputOverrides”:false,“domain”:“light”,“service”:“turn_on”,“x”:930,“y”:460,“wires”:[[“843d5c66beb3753f”]]},{“id”:“5a07c720fd7d25c0”,“type”:“inject”,“z”:“cdd1f3af1e96317f”,“g”:“da6f835974f882e4”,“name”:“”,“props”:[{“p”:“payload”},{“p”:“topic”,“vt”:“str”}],“repeat”:“”,“crontab”:“”,“once”:false,“onceDelay”:0.1,“topic”:“”,“payload”:“on”,“payloadType”:“str”,“x”:330,“y”:500,“wires”:[[“ed2b7f0f042ba8b0”]]},{“id”:“584c3231cabb0494”,“type”:“inject”,“z”:“cdd1f3af1e96317f”,“g”:“da6f835974f882e4”,“name”:“”,“props”:[{“p”:“payload”},{“p”:“topic”,“vt”:“str”}],“repeat”:“”,“crontab”:“”,“once”:false,“onceDelay”:0.1,“topic”:“”,“payload”:“off”,“payloadType”:“str”,“x”:330,“y”:560,“wires”:[[“ed2b7f0f042ba8b0”]]},{“id”:“49f73a6c.255cd4”,“type”:“server”,“name”:“Home Assistant”,“addon”:true,“rejectUnauthorizedCerts”:true,“ha_boolean”:“”,“connectionDelay”:false,“cacheJson”:false,“heartbeat”:false,“heartbeatInterval”:“”,“areaSelector”:“id”,“deviceSelector”:“id”,“entitySelector”:“id”,“statusSeparator”:“”,“enableGlobalContextStore”:false}]

Example 2 Without a Function Node

[{“id”:“5d4cbccc553574be”,“type”:“group”,“z”:“cdd1f3af1e96317f”,“name”:“Test 2”,“style”:{“label”:true},“nodes”:[“32a6cacf591364fe”,“0822929eb1258a40”,“16823c7600fb4aa7”,“c54838551542ef98”,“0e49e55e82632879”],“x”:234,“y”:679,“w”:1052,“h”:162},{“id”:“32a6cacf591364fe”,“type”:“debug”,“z”:“cdd1f3af1e96317f”,“g”:“5d4cbccc553574be”,“name”:“debug 4”,“active”:true,“tosidebar”:true,“console”:false,“tostatus”:false,“complete”:“true”,“targetType”:“full”,“statusVal”:“”,“statusType”:“auto”,“x”:1180,“y”:760,“wires”:},{“id”:“0822929eb1258a40”,“type”:“api-call-service”,“z”:“cdd1f3af1e96317f”,“g”:“5d4cbccc553574be”,“name”:“Test on”,“server”:“49f73a6c.255cd4”,“version”:7,“debugenabled”:false,“action”:“light.turn_on”,“floorId”:,“areaId”:,“deviceId”:,“entityId”:[“light.lr_desk_spot_light”],“labelId”:,“data”:“{"color_name": "blue", "brightness_pct": 90}”,“dataType”:“json”,“mergeContext”:“”,“mustacheAltTags”:false,“outputProperties”:,“queue”:“none”,“blockInputOverrides”:false,“domain”:“light”,“service”:“turn_on”,“x”:900,“y”:720,“wires”:[[“32a6cacf591364fe”]]},{“id”:“16823c7600fb4aa7”,“type”:“inject”,“z”:“cdd1f3af1e96317f”,“g”:“5d4cbccc553574be”,“name”:“”,“props”:[{“p”:“payload”},{“p”:“topic”,“vt”:“str”}],“repeat”:“”,“crontab”:“”,“once”:false,“onceDelay”:0.1,“topic”:“”,“payload”:“on”,“payloadType”:“str”,“x”:330,“y”:720,“wires”:[[“0822929eb1258a40”]]},{“id”:“c54838551542ef98”,“type”:“inject”,“z”:“cdd1f3af1e96317f”,“g”:“5d4cbccc553574be”,“name”:“”,“props”:[{“p”:“payload”},{“p”:“topic”,“vt”:“str”}],“repeat”:“”,“crontab”:“”,“once”:false,“onceDelay”:0.1,“topic”:“”,“payload”:“off”,“payloadType”:“str”,“x”:330,“y”:800,“wires”:[[“0e49e55e82632879”]]},{“id”:“0e49e55e82632879”,“type”:“api-call-service”,“z”:“cdd1f3af1e96317f”,“g”:“5d4cbccc553574be”,“name”:“Test off”,“server”:“49f73a6c.255cd4”,“version”:7,“debugenabled”:false,“action”:“light.turn_off”,“floorId”:,“areaId”:,“deviceId”:,“entityId”:[“light.lr_desk_spot_light”],“labelId”:,“data”:“”,“dataType”:“json”,“mergeContext”:“”,“mustacheAltTags”:false,“outputProperties”:,“queue”:“none”,“blockInputOverrides”:false,“domain”:“light”,“service”:“turn_off”,“x”:900,“y”:800,“wires”:[[“32a6cacf591364fe”]]},{“id”:“49f73a6c.255cd4”,“type”:“server”,“name”:“Home Assistant”,“addon”:true,“rejectUnauthorizedCerts”:true,“ha_boolean”:“”,“connectionDelay”:false,“cacheJson”:false,“heartbeat”:false,“heartbeatInterval”:“”,“areaSelector”:“id”,“deviceSelector”:“id”,“entitySelector”:“id”,“statusSeparator”:“”,“enableGlobalContextStore”:false}]

Please let me know if I am doing something wrong, but this was working fine using the old Call Service node.

Thanks for any assistance you can offer.

If you post a Node-RED flow JSON just as unformatted text, then the formatting is scrambled and it becomes unreadable and cannot be copied.

The empty array bracket pair [] in the editor becomes which looks very nice, but to import this requires hand editing the code, and you have a lot of in there…

Please use the code block </> option that you will find in the editor. This is a stated and de facto requirement of posting any structured code or data in this forum.

PS - the documentation says that input to the Action node needs to be under msg.payload, and if I read the stuff above correctly, you are setting

msg = {"action": "light.turn.off", }

which is both invalid JSON and is not setting msg.payload.

Using a Change node, and setting msg.payload to

{
   "action": "homeassistant.toggle",
   "target": {"entity_id": ["switch.t3_2"]}
}

overrides the UI settings and works perfectly for me.

The changes to the call service node were due to a structural change inside home assistant. Specifically the removal of call_service that was replaced with action.

You can leave it completely empty. There is a new check box towards the bottom that is enabled by default, Block input overrides uncheck it to send the configuration in.

[{"id":"d72cb4ef4b16815e","type":"api-call-service","z":"0a325c35fc29f44e","name":"","server":"","version":7,"debugenabled":false,"action":"","floorId":[],"areaId":[],"deviceId":[],"entityId":[],"labelId":[],"data":"","dataType":"jsonata","mergeContext":"","mustacheAltTags":false,"outputProperties":[],"queue":"none","blockInputOverrides":false,"domain":"","service":"","x":690,"y":1900,"wires":[[]]},{"id":"b8b8d5ea9d615f74","type":"inject","z":"0a325c35fc29f44e","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"{\t    \"action\": \"light.turn_on\",\t    \"target\": {\t        \"entity_id\": \"light.dj\"\t    },\t    \"data\": {\t        \"brightness_pct\": 50\t    }\t}","payloadType":"jsonata","x":530,"y":1900,"wires":[["d72cb4ef4b16815e"]]}]

Also because of the change mention above the format to send the configuration to an action node has changed. The format is in the flow posted. A complete config can be found here.

My Apologies, my mistake, and should have look for that “</>” in the editor. Thankyou for looking at this problem for me. Unfortunately even using your simple example, still did not work for me.

[{"id":"da6f835974f882e4","type":"group","z":"cdd1f3af1e96317f","name":"Test 1","style":{"label":true},"nodes":["ed2b7f0f042ba8b0","843d5c66beb3753f","bed13b9a501f5406","5a07c720fd7d25c0","584c3231cabb0494","e2bf5a7c18eade46","5dcd0a3881ea897a"],"x":234,"y":359,"w":1052,"h":242},{"id":"ed2b7f0f042ba8b0","type":"function","z":"cdd1f3af1e96317f","g":"da6f835974f882e4","name":"Test Function","func":"\nif (msg.payload === \"on\") msg = {\"action\": \"homeassistant.turn_on\",\n    \"target\": {\n        \"entity_id\": [\"light.lr_desk_spot_light\"]\n    },\n    \"data\": {\n        \"color_name\": \"blue\",\n        \"brightness_pct\": 90\n    },\n}\nif (msg.payload === \"off\")\n    msg = {\"action\": \"homeassistant.turn_off\",\n    };\nreturn msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":570,"y":560,"wires":[["843d5c66beb3753f","bed13b9a501f5406"]]},{"id":"843d5c66beb3753f","type":"debug","z":"cdd1f3af1e96317f","g":"da6f835974f882e4","name":"debug 2","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":1180,"y":560,"wires":[]},{"id":"bed13b9a501f5406","type":"api-call-service","z":"cdd1f3af1e96317f","g":"da6f835974f882e4","name":"Test Action Node","server":"49f73a6c.255cd4","version":7,"debugenabled":false,"action":"homeassistant.turn_on","floorId":[],"areaId":[],"deviceId":[],"entityId":["light.lr_desk_spot_light"],"labelId":[],"data":"","dataType":"json","mergeContext":"","mustacheAltTags":false,"outputProperties":[],"queue":"none","blockInputOverrides":false,"domain":"homeassistant","service":"turn_on","x":710,"y":440,"wires":[["843d5c66beb3753f","5dcd0a3881ea897a"]]},{"id":"5a07c720fd7d25c0","type":"inject","z":"cdd1f3af1e96317f","g":"da6f835974f882e4","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"on","payloadType":"str","x":330,"y":500,"wires":[["ed2b7f0f042ba8b0"]]},{"id":"584c3231cabb0494","type":"inject","z":"cdd1f3af1e96317f","g":"da6f835974f882e4","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"off","payloadType":"str","x":330,"y":560,"wires":[["ed2b7f0f042ba8b0"]]},{"id":"e2bf5a7c18eade46","type":"api-current-state","z":"cdd1f3af1e96317f","g":"da6f835974f882e4","name":"Current Test Light State","server":"49f73a6c.255cd4","version":3,"outputs":1,"halt_if":"","halt_if_type":"str","halt_if_compare":"is","entity_id":"light.lr_desk_spot_light","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":1110,"y":400,"wires":[["843d5c66beb3753f"]]},{"id":"5dcd0a3881ea897a","type":"delay","z":"cdd1f3af1e96317f","g":"da6f835974f882e4","name":"","pauseType":"delay","timeout":"3","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"allowrate":false,"outputs":1,"x":900,"y":400,"wires":[["e2bf5a7c18eade46"]]},{"id":"49f73a6c.255cd4","type":"server","name":"Home Assistant","addon":true,"rejectUnauthorizedCerts":true,"ha_boolean":"","connectionDelay":false,"cacheJson":false,"heartbeat":false,"heartbeatInterval":"","areaSelector":"id","deviceSelector":"id","entitySelector":"id","statusSeparator":"","enableGlobalContextStore":false},{"id":"5d4cbccc553574be","type":"group","z":"cdd1f3af1e96317f","name":"Test 2","style":{"label":true},"nodes":["32a6cacf591364fe","0822929eb1258a40","16823c7600fb4aa7","c54838551542ef98","0e49e55e82632879"],"x":234,"y":679,"w":1052,"h":162},{"id":"32a6cacf591364fe","type":"debug","z":"cdd1f3af1e96317f","g":"5d4cbccc553574be","name":"debug 4","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":1180,"y":760,"wires":[]},{"id":"0822929eb1258a40","type":"api-call-service","z":"cdd1f3af1e96317f","g":"5d4cbccc553574be","name":"Test on","server":"49f73a6c.255cd4","version":7,"debugenabled":false,"action":"light.turn_on","floorId":[],"areaId":[],"deviceId":[],"entityId":["light.lr_desk_spot_light"],"labelId":[],"data":"{\"color_name\": \"blue\", \"brightness_pct\": 90}","dataType":"json","mergeContext":"","mustacheAltTags":false,"outputProperties":[],"queue":"none","blockInputOverrides":false,"domain":"light","service":"turn_on","x":900,"y":720,"wires":[["32a6cacf591364fe"]]},{"id":"16823c7600fb4aa7","type":"inject","z":"cdd1f3af1e96317f","g":"5d4cbccc553574be","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"on","payloadType":"str","x":330,"y":720,"wires":[["0822929eb1258a40"]]},{"id":"c54838551542ef98","type":"inject","z":"cdd1f3af1e96317f","g":"5d4cbccc553574be","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"off","payloadType":"str","x":330,"y":800,"wires":[["0e49e55e82632879"]]},{"id":"0e49e55e82632879","type":"api-call-service","z":"cdd1f3af1e96317f","g":"5d4cbccc553574be","name":"Test off","server":"49f73a6c.255cd4","version":7,"debugenabled":false,"action":"light.turn_off","floorId":[],"areaId":[],"deviceId":[],"entityId":["light.lr_desk_spot_light"],"labelId":[],"data":"","dataType":"json","mergeContext":"","mustacheAltTags":false,"outputProperties":[],"queue":"none","blockInputOverrides":false,"domain":"light","service":"turn_off","x":900,"y":800,"wires":[["32a6cacf591364fe"]]}]

Here is a modified version of what I tried to post yesterday.

I did see the ’ Block input overrides’ in the Action node, and have used both checked and unchecked, but seems to make no difference in my results.

Again, Thankyou for taking the time to look at this.

Thank you for looking at this issue. I thought so as well, but checked or unchecked, when the node is run, it throws up this error 'ValidationError: “action” is not allowed to be empty". When you create the node and save it, it does not report any problems, it only flags the issue when attempting to perform an Action.

“Also because of the change mention above the format to send”

That was the documentation I followed, and if I understand it correctly, I only need to use the properties I need, EG, it I need to action an Entity, I only need to include the entity line of that example and not all the other properties it has listed, which would make sense, as I do not use Floors and have not configured any floors in HA.

Thanks again for your input.

As I said in my earlier post, the UI fields you want to merge into the Action nodes must reside in msg.payload and not msg.

Also, this needs to be a valid JSON object. You have an extra , at the end of the last field in every object. The comma is a separator, not a terminator.

I don’t have your light, but the following (JavaScript in your function node) is working absolutely perfectly for me.

let myswitch = msg.payload;

if (myswitch === "on")
    msg.payload =
    {"action": "homeassistant.turn_on",
    "target": {"entity_id": ["switch.t2_2"]},
    "data": {}
};

if (myswitch === "off")
    msg.payload =
    {"action": "homeassistant.turn_off",
    "target": {"entity_id": ["switch.t2_2"]},
    "data": {}    
};

return msg;

Note that I can leave an empty ‘data’ field in the merge object, and Home Assistant does not complain, although it will if there are extra or missing options fields that the particular action is expecting.

Naturally this could be much simplified, and also done in a Change node with JSONata, but this does at least work.

Also, since this is now working, there is indeed no need to have anything in the UI fields in the Action node - the node takes everything from the input.

Brilliant, That has fixed it. Thankyou so very much for your help. Think the extra comma was let over from something I deleted, then replicated through to all others. Completely missed the msg part not including the .payload afterwards.

Again, thank you for your help. HA, all is forgiven :slight_smile:

I know you like to learn. Here are a couple of clarifications. When passing data into the action node, it doesn’t need to be valid JSON, just a valid JavaScript object. So, the extra comma is valid, and the quotes around key names aren’t necessary unless the key has special characters.

Also, you can simplify your code a bit. Here’s a cleaner version:

msg.payload = {
  action: `homeassistant.turn_${msg.payload}`,
  target: {
    entity_id: ["switch.t2_2"],
  },
  data: {},
};

return msg;

This will work the same way, with fewer steps.

1 Like

Thanks for this info. I’m looking at doing more coding using JSon in order to streamline and re use as much of the repetitive things, hopefully creating many sub flows to replace much of the repetitive tasks. I 've learned a little bit in creating those functions, but I know I can steam line some more.

Thanks for all your help.