Help sending an array to call service node

Thanks to some help from folks here, I have successfully set up a Node-RED sequence that will send my Roomba vacuum to specific rooms. Here is the sequence I’m using:

I’m using the following data in the call service node to send the Roomba to a specific room:

{
    "command": "start",
    "params": {
        "pmap_id": "{{pmap_id}}",
        "regions": [
            {
                "region_id": "{{region_id}}",
                "type": "rid"
            }
        ],
        "user_pmapv_id": "{{user_pmapv_id}}"
    }
}

While I can successfully send Roomba to one room, I cannot figure out how to send the Roomba multiple region_id values to then queue up multiple rooms to clean. As you can see from the sequence, I am using a join node to gather the various region_id values and create an Array. How can I revise my call service node data to send the array of values rather than just a single region_id?

I’m assuming that you’re clicking on a bunch of toggles in the UI. The main problem you will encounter is the join will need a timeout - say 5 seconds. If it takes you longer than 5 seconds to click all of the toggles, it will send two commands, and I’m guessing the second will override the first so only some rooms will be cleaned. I guess you can overcome this by having a longer timeout, but then you’ll be sitting waiting for the timeout to know if it has worked. You might be better off keeping these toggles, but also having a “start” button and trigger your flow off that instead. Then you’d be using “current state” nodes to get the data, although you could use “get entities” to avoid needing the join.

Regardless, I don’t have a Roomba, so I’m guessing the format. It looks like “pmap_id” and “user_pmapv_id” are fairly static, and “region_id” is what defines the room. So assuming you set the output of each “id” change node is something like:

{
    "pmap_id": "my_pmap_id",
    "user_pmapv_id": "my_user_pmapv_id",
    "regions": {
        "region_id": "1",
        "type": "rid"
    }
}

And you’re joining “msg.region” to produce an array, you would use:

{
    "command": "start",
    "params": {
        "pmap_id": "{{pmap_id}}",
        "regions": {{regions}},
        "user_pmapv_id": "{{user_pmapv_id}}"
    }
}

As it stands, I’m guessing your nodes just pass the region, rather than the structure. In this case you could use JSONata instead of JSON, but it’s more complex:

{
    "command": "start",
    "params": {
        "pmap_id": pmap_id,
        "regions":
            ($map(regions, function ($e) {
                {
                    "region_id": $e,
                    "type": "rid"
                }
            })),
        "user_pmapv_id": user_pmapv_id
    }
}
1 Like

A belated thank you Michael, I was able to get my iRobot room specific commands working this morning. I restructured my Node Red flow a bit and then used your JSONata call service node example. For folks who come looking for how to send a Roomba to multiple rooms via Node Red, here is my overall flow:

[{"id":"92a6f213cac12657","type":"server-state-changed","z":"a85642c551c2b8f0","name":"Roomba - Dining Room","server":"e9a2a376.9289","version":4,"exposeToHomeAssistant":false,"haConfig":[{"property":"name","value":""},{"property":"icon","value":""}],"entityidfilter":"input_boolean.roomba_dining_room_toggle","entityidfiltertype":"exact","outputinitially":false,"state_type":"str","haltifstate":"","halt_if_type":"str","halt_if_compare":"is","outputs":1,"output_only_on_state_change":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":200,"y":260,"wires":[["e8dba4ea0a4bb5a6"]]},{"id":"92243e6687f57b83","type":"change","z":"a85642c551c2b8f0","name":"Dining Room id","rules":[{"t":"set","p":"region_id","pt":"msg","to":"1","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":580,"y":260,"wires":[["21e009ba4d6ebc53"]]},{"id":"ed022c05fdc0a177","type":"server-state-changed","z":"a85642c551c2b8f0","name":"Roomba - Down Bath","server":"e9a2a376.9289","version":4,"exposeToHomeAssistant":false,"haConfig":[{"property":"name","value":""},{"property":"icon","value":""}],"entityidfilter":"input_boolean.roomba_downstairs_bathroom","entityidfiltertype":"exact","outputinitially":false,"state_type":"str","haltifstate":"","halt_if_type":"str","halt_if_compare":"is","outputs":1,"output_only_on_state_change":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":200,"y":320,"wires":[["1b5ab3b0f1031f12"]]},{"id":"77803e0066aa3841","type":"change","z":"a85642c551c2b8f0","name":"Down Bath id","rules":[{"t":"set","p":"region_id","pt":"msg","to":"12","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":570,"y":320,"wires":[["21e009ba4d6ebc53"]]},{"id":"362afb779586cf35","type":"server-state-changed","z":"a85642c551c2b8f0","name":"Roomba - Down Bed","server":"e9a2a376.9289","version":4,"exposeToHomeAssistant":false,"haConfig":[{"property":"name","value":""},{"property":"icon","value":""}],"entityidfilter":"input_boolean.roomba_downstairs_bedroom","entityidfiltertype":"exact","outputinitially":false,"state_type":"str","haltifstate":"","halt_if_type":"str","halt_if_compare":"is","outputs":1,"output_only_on_state_change":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":190,"y":380,"wires":[["80b5ad4ffc4138fd"]]},{"id":"3ce7e50b508f9a77","type":"change","z":"a85642c551c2b8f0","name":"Down Bed id","rules":[{"t":"set","p":"region_id","pt":"msg","to":"19","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":570,"y":380,"wires":[["21e009ba4d6ebc53"]]},{"id":"5e654a32891480d9","type":"server-state-changed","z":"a85642c551c2b8f0","name":"Roomba - Down Hall","server":"e9a2a376.9289","version":4,"exposeToHomeAssistant":false,"haConfig":[{"property":"name","value":""},{"property":"icon","value":""}],"entityidfilter":"input_boolean.roomba_downstairs_hallway","entityidfiltertype":"exact","outputinitially":false,"state_type":"str","haltifstate":"","halt_if_type":"str","halt_if_compare":"is","outputs":1,"output_only_on_state_change":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":190,"y":440,"wires":[["5786aa415d4c1e41"]]},{"id":"6d5f25631b6d029e","type":"change","z":"a85642c551c2b8f0","name":"Down Hall id","rules":[{"t":"set","p":"region_id","pt":"msg","to":"16","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":570,"y":440,"wires":[["21e009ba4d6ebc53"]]},{"id":"b974b69ea2e40f76","type":"server-state-changed","z":"a85642c551c2b8f0","name":"Roomba - Entryway","server":"e9a2a376.9289","version":4,"exposeToHomeAssistant":false,"haConfig":[{"property":"name","value":""},{"property":"icon","value":""}],"entityidfilter":"input_boolean.roomba_entryway","entityidfiltertype":"exact","outputinitially":false,"state_type":"str","haltifstate":"","halt_if_type":"str","halt_if_compare":"is","outputs":1,"output_only_on_state_change":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":190,"y":500,"wires":[["e3f62f85fb75e815"]]},{"id":"185c1434635164b2","type":"change","z":"a85642c551c2b8f0","name":"Entryway id","rules":[{"t":"set","p":"region_id","pt":"msg","to":"14","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":570,"y":500,"wires":[["21e009ba4d6ebc53"]]},{"id":"e8dba4ea0a4bb5a6","type":"switch","z":"a85642c551c2b8f0","name":"On/Off","property":"payload","propertyType":"msg","rules":[{"t":"eq","v":"on","vt":"str"},{"t":"eq","v":"off","vt":"str"}],"checkall":"true","repair":false,"outputs":2,"x":390,"y":260,"wires":[["92243e6687f57b83"],[]]},{"id":"1b5ab3b0f1031f12","type":"switch","z":"a85642c551c2b8f0","name":"On/Off","property":"payload","propertyType":"msg","rules":[{"t":"eq","v":"on","vt":"str"},{"t":"eq","v":"off","vt":"str"}],"checkall":"true","repair":false,"outputs":2,"x":390,"y":320,"wires":[["77803e0066aa3841"],[]]},{"id":"80b5ad4ffc4138fd","type":"switch","z":"a85642c551c2b8f0","name":"On/Off","property":"payload","propertyType":"msg","rules":[{"t":"eq","v":"on","vt":"str"},{"t":"eq","v":"off","vt":"str"}],"checkall":"true","repair":false,"outputs":2,"x":390,"y":380,"wires":[["3ce7e50b508f9a77"],[]]},{"id":"5786aa415d4c1e41","type":"switch","z":"a85642c551c2b8f0","name":"On/Off","property":"payload","propertyType":"msg","rules":[{"t":"eq","v":"on","vt":"str"},{"t":"eq","v":"off","vt":"str"}],"checkall":"true","repair":false,"outputs":2,"x":390,"y":440,"wires":[["6d5f25631b6d029e"],[]]},{"id":"e3f62f85fb75e815","type":"switch","z":"a85642c551c2b8f0","name":"On/Off","property":"payload","propertyType":"msg","rules":[{"t":"eq","v":"on","vt":"str"},{"t":"eq","v":"off","vt":"str"}],"checkall":"true","repair":false,"outputs":2,"x":390,"y":500,"wires":[["185c1434635164b2"],[]]},{"id":"351e3a4f5c1d7f63","type":"server-state-changed","z":"a85642c551c2b8f0","name":"Roomba - Kitchen","server":"e9a2a376.9289","version":4,"exposeToHomeAssistant":false,"haConfig":[{"property":"name","value":""},{"property":"icon","value":""}],"entityidfilter":"input_boolean.roomba_kitchen","entityidfiltertype":"exact","outputinitially":false,"state_type":"str","haltifstate":"","halt_if_type":"str","halt_if_compare":"is","outputs":1,"output_only_on_state_change":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":190,"y":560,"wires":[["020a2391f4dc81dc"]]},{"id":"622b017c0f4faf15","type":"server-state-changed","z":"a85642c551c2b8f0","name":"Roomba - Living Room","server":"e9a2a376.9289","version":4,"exposeToHomeAssistant":false,"haConfig":[{"property":"name","value":""},{"property":"icon","value":""}],"entityidfilter":"input_boolean.roomba_living_room","entityidfiltertype":"exact","outputinitially":false,"state_type":"str","haltifstate":"","halt_if_type":"str","halt_if_compare":"is","outputs":1,"output_only_on_state_change":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":200,"y":620,"wires":[["7060e7331b8a0d28"]]},{"id":"a928a529c122153b","type":"change","z":"a85642c551c2b8f0","name":"Kitchen id","rules":[{"t":"set","p":"region_id","pt":"msg","to":"17","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":560,"y":560,"wires":[["21e009ba4d6ebc53"]]},{"id":"020a2391f4dc81dc","type":"switch","z":"a85642c551c2b8f0","name":"On/Off","property":"payload","propertyType":"msg","rules":[{"t":"eq","v":"on","vt":"str"},{"t":"eq","v":"off","vt":"str"}],"checkall":"true","repair":false,"outputs":2,"x":390,"y":560,"wires":[["a928a529c122153b"],[]]},{"id":"296ad24661f39f7b","type":"change","z":"a85642c551c2b8f0","name":"Living Room id","rules":[{"t":"set","p":"region_id","pt":"msg","to":"18","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":580,"y":620,"wires":[["21e009ba4d6ebc53"]]},{"id":"7060e7331b8a0d28","type":"switch","z":"a85642c551c2b8f0","name":"On/Off","property":"payload","propertyType":"msg","rules":[{"t":"eq","v":"on","vt":"str"},{"t":"eq","v":"off","vt":"str"}],"checkall":"true","repair":false,"outputs":2,"x":390,"y":620,"wires":[["296ad24661f39f7b"],[]]},{"id":"21e009ba4d6ebc53","type":"join","z":"a85642c551c2b8f0","name":"Join Region ids","mode":"custom","build":"array","property":"region_id","propertyType":"msg","key":"topic","joiner":"\\n","joinerType":"str","accumulate":false,"timeout":"10","count":"","reduceRight":false,"reduceExp":"","reduceInit":"","reduceInitType":"","reduceFixup":"","x":840,"y":420,"wires":[["0cb907099b658d50"]]},{"id":"997c17d6e694e79e","type":"api-call-service","z":"a85642c551c2b8f0","name":"Roomba Send (JSONata)","server":"e9a2a376.9289","version":5,"debugenabled":false,"domain":"vacuum","service":"send_command","areaId":[],"deviceId":["582363ccdc7257dd66baf8e9d342a338"],"entityId":["vacuum.downstairs"],"data":"{\t    \"command\": \"start\",\t    \"params\": {\t        \"pmap_id\": pmap_id,\t        \"regions\":\t            ($map(region_id, function ($e) {\t                {\t                    \"region_id\": $e,\t                    \"type\": \"rid\"\t                }\t            })),\t        \"user_pmapv_id\": user_pmapv_id\t    }\t}","dataType":"jsonata","mergeContext":"","mustacheAltTags":false,"outputProperties":[],"queue":"none","x":1370,"y":420,"wires":[[]]},{"id":"0cb907099b658d50","type":"change","z":"a85642c551c2b8f0","name":"Set pmapv_id and pmap_id","rules":[{"t":"set","p":"user_pmapv_id","pt":"msg","to":"230109T14xxxx","tot":"str"},{"t":"set","p":"pmap_id","pt":"msg","to":"iiKUNVywXYupkxxxx","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":1100,"y":420,"wires":[["997c17d6e694e79e"]]},{"id":"e9a2a376.9289","type":"server","name":"Home Assistant","addon":true}]

As Michael intuited, I have several toggles on my UI dashboard that allow the user to choose to which rooms they would like to send the Roomba. The join node waits 10 seconds before aggregating the region ids and joining them in an array to send to the Roomba.