Payload data issue

So I am trying to pass payload data from an array of light entities and cannot seem to figure out where I’m going wrong here.

What should happen is that I turn on “Maintenance Mode” and the flow grabs all of the light entities, puts them in an array and then then turns on each light in the array. The issue seems to be with how the payload is sent to the “Call Service” node.

[{"id":"2c08f48fa6f42b3a","type":"server-state-changed","z":"d0062682251ddce4","name":"Maintenance Mode","server":"58789d9e.7d1274","version":5,"outputs":2,"exposeAsEntityConfig":"","entityId":"input_boolean.maintenance_mode","entityIdType":"exact","outputInitially":false,"stateType":"str","ifState":"on","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":130,"y":6260,"wires":[["1f14eb2e7509b75f"],[]]},{"id":"0af558cd276d527f","type":"function","z":"d0062682251ddce4","name":"Filter Light Entities","func":"var allEntities = msg.payload;\n\n// Ensure the payload is an array\nif (!Array.isArray(allEntities)) {\n    allEntities = [allEntities];\n}\n\n// Filter entities to only include light entities\nvar lightEntities = allEntities.filter(entity => entity.entity_id && entity.entity_id.startsWith('light.'));\n\n// Log the number of light entities found\nnode.log('Total light entities: ' + lightEntities.length);\n\n// Set the payload to the filtered light entities array\nmsg.payload = lightEntities;\n\nreturn msg;","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":550,"y":6260,"wires":[["0dcf9e27b5214128"]]},{"id":"1f14eb2e7509b75f","type":"http request","z":"d0062682251ddce4","name":"Get All Entities","method":"GET","ret":"obj","paytoqs":"ignore","url":"http://192.168.0.5:8123/api/states","tls":"","persist":false,"proxy":"","insecureHTTPParser":false,"authType":"bearer","senderr":false,"headers":[{"keyType":"Authorization","keyValue":"","valueType":"other","valueValue":"Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJjYzM0M2YyYTZmNGY0MDJlYWFhOGRiYTIyNjA3ZmQ3MyIsImlhdCI6MTcxODE1OTgzMiwiZXhwIjoyMDMzNTE5ODMyfQ.FigHP-gYQrDd58aS94Wgs61YSfpSiMNuT2aHv9BIxj8"}],"x":340,"y":6260,"wires":[["0af558cd276d527f"]]},{"id":"0dcf9e27b5214128","type":"function","z":"d0062682251ddce4","name":"Turn On All Light Entities","func":"var lightEntities = msg.payload;\n\n// Ensure the payload is an array\nif (!Array.isArray(lightEntities)) {\n    node.error('Payload is not an array');\n    return null;\n}\n\n// Log the number of light entities found\nnode.log('Total light entities: ' + lightEntities.length);\n\n// Create a new message for each light entity to turn it on\nvar turnOnMessages = lightEntities.map(function(entity) {\n    return {\n        payload: {\n            domain: 'light',\n            service: 'turn_on',\n            data: {\n                entity_id: entity.entity_id\n            }\n        }\n    };\n});\n\n// Return all the turn on messages as an array\nreturn [turnOnMessages];","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":780,"y":6260,"wires":[["17434471df46284d"]]},{"id":"17434471df46284d","type":"split","z":"d0062682251ddce4","name":"Split Light Entities","splt":"\\n","spltType":"str","arraySplt":"1","arraySpltType":"len","stream":false,"addname":"","x":990,"y":6260,"wires":[["be037d8586c1855f"]]},{"id":"4f080f7802b782c4","type":"api-call-service","z":"d0062682251ddce4","name":"Call Service: Light Turn On","server":"edd49280cd758581","version":5,"debugenabled":false,"domain":"light","service":"turn_on","areaId":[],"deviceId":[],"entityId":[],"data":"","dataType":"json","mergeContext":"","mustacheAltTags":false,"outputProperties":[],"queue":"none","output_location":"","output_location_type":"none","x":1400,"y":6260,"wires":[[]]},{"id":"be037d8586c1855f","type":"change","z":"d0062682251ddce4","name":"Format Message","rules":[{"t":"set","p":"payload","pt":"msg","to":"{\"domain\": \"light\", \"service\": \"turn_on\", \"data\": {\"entity_id\": msg.payload.data.entity_id}}","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":1190,"y":6260,"wires":[["4f080f7802b782c4"]]},{"id":"58789d9e.7d1274","type":"server","name":"Home Assistant","addon":true},{"id":"edd49280cd758581","type":"server","name":"Home Assistant","addon":true}]`Preformatted text`

I think the entity_id should be in the same level as the payload and not as an attribute under the data, like…

msg.entity_id = sensor.something
msg.payload = {…}

You might also look into the function node.send(msg) which will send a msg onwards, but keep running in the function node, so you can split the array in the function node directly.

And it looked like I got 2 home assistant servers loaded in your clip out, so check if you have the right servers in Node Red.

So that actually brings up another question . I have a bunch of these servers as options. Not sure where they came from or which one I should be using.

Yes, the correct format for the msg.payload input into a Call Service node is

{
   "domain": "light",
   "service": "turn_on",
   "data": {"entity_id": payload.data.entity_id}
}

You don’t need the msg.payload in JSONata, just payload
You can also send an array directly as the entity_id field, so there is no need to split the result array to pass each message (this may cause websocket queue problems too).

The following should work for you - this gets all the ‘light.*’ entities and turns them on

[{"id":"cce87a566eac3b51","type":"ha-get-entities","z":"7021f7d89ccb8403","name":"","server":"","version":1,"rules":[{"property":"entity_id","logic":"starts_with","value":"light","valueType":"str"}],"outputType":"array","outputEmptyResults":true,"outputLocationType":"msg","outputLocation":"payload","outputResultsCount":1,"x":330,"y":640,"wires":[["a8701cfc2eaba3c6"]]},{"id":"a8701cfc2eaba3c6","type":"change","z":"7021f7d89ccb8403","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"{\t   \"domain\": \"light\",\t   \"service\": \"turn_on\",\t   \"data\": {\"entity_id\": payload.entity_id} \t}","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":520,"y":640,"wires":[[]]}]
1 Like

This is much simpler, thank you.

That needs to be addressed, go to the configuration tab where the debug is.

image

There you will see the servers, the number is how many nodes use them. You want to keep the one with the most and delete the rest. You will likely need to double click on nodes that lost their server to load the right one.

This usually happens when importing flows, to avoid this paste your import code in the scrubber before importing.

I had no idea this was a thing. Thank you for this info.