# How to build a flow variable array in a function

**URL:** https://discourse.nodered.org/t/how-to-build-a-flow-variable-array-in-a-function/30585
**Category:** General
**Created:** [23 July 2020 07:04 UTC](https://discourse.nodered.org/t/how-to-build-a-flow-variable-array-in-a-function/30585 "2020-07-23T07:04:16Z")
**Posts on this page:** 13
**Page:** 2

<div class="post-metadata">

### Author: ![zazas321](https://avatars.discourse-cdn.com/v4/letter/z/59ef9b/32.png) [@zazas321](https://discourse.nodered.org/u/zazas321)
#### Post date: [23 July 2020 12:31 UTC](https://discourse.nodered.org/t/how-to-build-a-flow-variable-array-in-a-function/30585/21 "2020-07-23T12:31:07Z")

</div>

I have managed to implement most things I needed ,just got stuck on one:

```auto
if(msg.payload == 0){
    var i=0;
    //node.warn(flow.get(individual_items))
    var items = flow.get('individual_items')
    var number = flow.get('counter_temp')
    node.warn("COUNTER 0 DETECTED")
    node.warn(items)
    node.warn(number)
    for(i;i<number;i++)
        msg.topic[i] = items[i]
        node.warn(msg.topic[i])
}
return msg

```

[{"id":"6bdf19ef.77f2a8","type":"debug","z":"df177cb8.27882","name":"status","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":770,"y":1880,"wires":},{"id":"88eb8b89.498378","type":"function","z":"df177cb8.27882","name":"-1 from counter when status=DONE","func":"var temp\_var;\nif (msg.payload == "DONE"){\n msg.topic = "global/counter"\n flow.set('counter',flow.get('counter')-1)\n msg.payload = flow.get('counter')\n node.warn("COUNTER DECREMENTED")\n return msg\n}\nelse {\n return msg\nnode.warn("STATUS NOT DONE")\n}\n\n\n\n","outputs":1,"noerr":0,"initialize":"","finalize":"","x":1020,"y":1820,"wires":[["cef1a3c2.340f5","aa9503a7.c2c02"]]},{"id":"aa9503a7.c2c02","type":"debug","z":"df177cb8.27882","name":"decremented counter","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":1360,"y":1820,"wires":},{"id":"72f7e508.9a6dfc","type":"mqtt in","z":"df177cb8.27882","name":"","topic":"+/status","qos":"2","datatype":"auto","broker":"2727c5a5.a4fb6a","x":770,"y":1820,"wires":[["88eb8b89.498378"]]},{"id":"cef1a3c2.340f5","type":"function","z":"df177cb8.27882","name":"function to make msg.payload to flow.counter","func":"if(msg.payload == 0){\n var i=0;\n [//node.warn](https://node.warn)(flow.get(individual\_items))\n var items = flow.get('individual\_items')\n var number = flow.get('counter\_temp')\n node.warn("COUNTER 0 DETECTED")\n node.warn(items)\n node.warn(number)\n for(i;i\<number;i++)\n msg.topic[i] = items[i]\n node.warn(msg.topic[i])\n}\nreturn msg","outputs":1,"noerr":0,"initialize":"","finalize":"","x":1110,"y":1720,"wires":[]},{"id":"9be853bd.5da3c","type":"debug","z":"df177cb8.27882","name":"GOOD JOB","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"topic","targetType":"msg","statusVal":"","statusType":"auto","x":1410,"y":1720,"wires":},{"id":"2727c5a5.a4fb6a","type":"mqtt-broker","z":"","name":"","broker":"localhost","port":"1883","clientid":"","usetls":false,"compatmode":true,"keepalive":"60","cleansession":true,"birthTopic":"","birthQos":"0","birthRetain":"false","birthPayload":"","closeTopic":"","closeQos":"0","closeRetain":"false","closePayload":"","willTopic":"","willQos":"0","willRetain":"false","willPayload":""}]

```auto

In the function, I am checking if the payload is 0 ( thats the counter value that I decrement).
When the value reaches 0, I want to set the msg.topic to the Individual item array as following:

msg.topic[0] = Individual_items[0]
msg.topic[1] = Individual_items[1] .....

![2020-07-23-152919_1920x1080_scrot|690x388](upload://gijBjzOcoSw1XDA0ZTsxwvTytj9.png) 

I Used node.warn to print what are the individual_items and I sucessfully get an debug message that Individual_items=[device1,device2] which is correct.

However, it wont let me set the msg.topic[0] = individual_items[0] like I have tried
```

---

<div class="post-metadata">

### Author: ![Colin](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/colin/32/17040_2.png) [@Colin](https://discourse.nodered.org/u/Colin)
#### Post date: [23 July 2020 12:49 UTC](https://discourse.nodered.org/t/how-to-build-a-flow-variable-array-in-a-function/30585/22 "2020-07-23T12:49:55Z")

</div>

Since msg.topic is not an array, you can't set msg.topic[0] to anything. You would have to do something like  
`msg.topic = []`  
before the start of the for loop.

Also note that you have not used `{ }` round the for loop contents, so the code you have shown is actually

```auto
    for(i;i<number;i++)
        msg.topic[i] = items[i]
    node.warn(msg.topic[i])

```

with the node.warn statement after the loop. This is one of the commonest coding errors made (by experienced coders and beginners alike) and is why I would never indent code without using {..}. It is just too easy to start with

```auto
    for(i;i<number;i++)
        msg.topic[i] = items[i]

```

and then realise that you need an extra line in the loop and just add it. The same error can also be easily made with `if` statements etc.

**Edit** Are you sure you want msg.topic to be an array? That is very unusual and you might find that another node you feed it into has a nervous breakdown and crashes node red when it finds that topic is an array. That would be a bug of course, but it is just the sort of edge case that few would think of testing for.

---

<div class="post-metadata">

### Author: ![zazas321](https://avatars.discourse-cdn.com/v4/letter/z/59ef9b/32.png) [@zazas321](https://discourse.nodered.org/u/zazas321)
#### Post date: [23 July 2020 13:15 UTC](https://discourse.nodered.org/t/how-to-build-a-flow-variable-array-in-a-function/30585/23 "2020-07-23T13:15:07Z")

</div>

Thank you very much for detailed response!

The reason why I am trying to make my msg.topic an array is because I will be using this function node output as an input to MQTT publish node which takes msg.topic and msg.payload as input parameters.

I need to publish a mqtt message to multiple devices, for example if my number is 3, and device names are device1, device4, device6,  
I want to publish a mqtt message to each device ( keep in mind that these device names math the topic names as well) so device1/stauts, device4,status, device6/status is what I need to build

I havent tried whether having an msg.topic as an array as an input to MQTT publish node works but I assumed it will.

---

<div class="post-metadata">

### Author: ![Colin](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/colin/32/17040_2.png) [@Colin](https://discourse.nodered.org/u/Colin)
#### Post date: [23 July 2020 13:41 UTC](https://discourse.nodered.org/t/how-to-build-a-flow-variable-array-in-a-function/30585/24 "2020-07-23T13:41:59Z")

</div>

> [@zazas321](#):
>
> I havent tried whether having an msg.topic as an array as an input to MQTT publish node works but I assumed it will.

I suspect not, unless it specifically mentions that in the node. You might be better to send a number of separate messages, each with the appropriate topic and payload. You can do that using `node.send()` in your for loop. Also I just noticed you are not initialising i in your for statement but relying on it being set at the top, it is better to remove that and use

```auto
    ...
    for(let i= 0; i<number; i++) {
        msg.topic = items[i]
        node.send(msg)
    }
    msg = null
}
return msg

```

The line `msg=null` causes no message to be sent at the end (in the case where payload is zero).

---

<div class="post-metadata">

### Author: ![zazas321](https://avatars.discourse-cdn.com/v4/letter/z/59ef9b/32.png) [@zazas321](https://discourse.nodered.org/u/zazas321)
#### Post date: [23 July 2020 13:43 UTC](https://discourse.nodered.org/t/how-to-build-a-flow-variable-array-in-a-function/30585/25 "2020-07-23T13:43:21Z")

</div>

That is great idea. I will do that tommorow. Thanks a lot

---

<div class="post-metadata">

### Author: ![zazas321](https://avatars.discourse-cdn.com/v4/letter/z/59ef9b/32.png) [@zazas321](https://discourse.nodered.org/u/zazas321)
#### Post date: [24 July 2020 05:15 UTC](https://discourse.nodered.org/t/how-to-build-a-flow-variable-array-in-a-function/30585/26 "2020-07-24T05:15:45Z")

</div>

I have managed to do as you suggested - sending a node.send(msg) in a loop and that works fine, however, I am facing another issue now:

This is whats inside my function node ( it is doing many things: checking if the global flag(task\_started\_ is set, updating MYSQL database, setting the counter based on how many individual items I have.

```auto

if(flow.get('task_started')==0){
    var items_array = flow.get("individual_items")|| []
    flow.set("individual_items",items_array);
    var internal_counter = flow.get("internal_counter")||0;
    node.warn("task STARTED")
}
else
    node.warn("task already started")

var quantity = msg.payload
    var device_id = msg.topic.split("/");// split the whole topic to devicex ( untill /)
    msg.payload = device_id[0];
    msg.topic=`UPDATE pack_to_light SET Quantity = '${quantity}' WHERE Device = '${device_id[0]}'`

if(quantity >0){// only increment when quantity is more than 0,
// when quantity is 0, that means we finished picking items from that box
    flow.set("individual_items["+internal_counter+"]",msg.payload);
    flow.set('internal_counter',internal_counter+1)
}
return msg;

```

The problem lies somewhere withing those lines:

```
var items_array = flow.get("individual_items")|| []
flow.set("individual_items",items_array);

```

So if i understand this correctly, It only sets the items arrray to an empty array during the first launch (deployment) of the flow. If I am doing multiple tasks withing single deployment, this will not be reinitialized which causes some trouble.

As I mentioned, this sets the flow.counter variable to the number of individual items, I have another function node which decrements the counter and when counter reaches 0, I need to send some data to my devices :  
msg.payload refers to counter here

```auto
if(msg.payload == 0){
   msg.topic=0;
   msg.payload = "GOOD_JOB"
   //node.warn(flow.get(individual_items))
   var items = flow.get('individual_items')
   var number = flow.get('counter_temp')
   node.warn("COUNTER 0 DETECTED")
   node.warn(items)
   node.warn(number)
   for(let i=0;i<number;i++){
       msg.topic = items[i] + "/status"
       //node.warn(msg.topic)
       node.send(msg)
   }
   flow.set('task_started',0);
   flow.set('individual_items',0);// HERE I NEED TO COMPLETELY RESET INDIVIDUAL_ITEMS INSTEAD OF SETTING TO 0
   //return msg
}
return msg=null

```

Here, when counter reaches 0, I need to completely reset individual\_items array, so I dont need to redeploy the flow everytime. I have tried doing so:  
flow.set('individual\_items',0);  
but this does not reset the variable, instead, just sets the elements of the array to 0.

In the function node above, I do:

```auto
   var items = flow.get('individual_items')
   var number = flow.get('counter_temp')
   node.warn("COUNTER 0 DETECTED")
   node.warn(items)

```

I create a variable "items" in which I save data from individual\_items flow and I print it to debug using node.warn(items).

During the first task, this is fine:

```auto
GOOD_JOB to all active devices
function : (warn)
array[2]
0: "device1"
1: "device3"

```

However, during the second task, items variable looks like that:

```auto
[GOOD_JOB to all active devices]
function : (warn)
array[4]
0: null
1: null
2: "device1"
3: "device3"

```

Could someone suggest me a way how do I completely clear flow.individual\_items variable after counter gets to = 0 ( msg.payload refers to counter in 2nd function)

---

<div class="post-metadata">

### Author: ![bakman2](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/bakman2/32/6207_2.png) [@bakman2](https://discourse.nodered.org/u/bakman2)
#### Post date: [24 July 2020 05:44 UTC](https://discourse.nodered.org/t/how-to-build-a-flow-variable-array-in-a-function/30585/27 "2020-07-24T05:44:10Z")

</div>

> [@zazas321](#):
>
> The problem lies somewhere withing those lines:
> 
> ```auto
> var items_array = flow.get("individual_items")|| []
> flow.set("individual_items",items_array);
> 
> ```
> 
> So if i understand this correctly, It only sets the items arrray to an empty array during the first launch (deployment) of the flow.

It sets it to an empty array - **if it does not exist**. If you re-deploy it still exists. And if you have enabled the storage parameter it will survive a reboot as well.

I see a lot of code in this thread but it is not entirely clear what you are trying to accomplish (ie what is the purpose?), it looks complicated.

---

<div class="post-metadata">

### Author: ![zazas321](https://avatars.discourse-cdn.com/v4/letter/z/59ef9b/32.png) [@zazas321](https://discourse.nodered.org/u/zazas321)
#### Post date: [24 July 2020 05:51 UTC](https://discourse.nodered.org/t/how-to-build-a-flow-variable-array-in-a-function/30585/28 "2020-07-24T05:51:16Z")

</div>

What I am trying to do is to control multiple remote devices from the main controller ( raspberry PI). What happens is a raspberry PI initiates a task and assigns multiple devices some number. I need to save those device names and counter to a flow type variable because I use it onther functions.

So for example raspberry PI initiate a task for device1, device4, device5

I need to save those items in "individual\_items" array which is what I do.

When remote devices finished their task, they send a singal back to raspberry PI which decrements counter. When counter reaches 0, raspberry PI knows that all assigned devices finished their tasks and I send them a message "GOOD\_JOB". Also, when task is finished, I need to reset "individual\_items" array so when the next task starts, I start from a clear array ( Now it does not reset, it saves the values from the last task and just appends which is not good).

So in short, I am designing a system simmilar to "pick\_to\_light" where I have many remote devices assigned to a box which lights up an led to show an operator that he needs to grab some items from this box .

---

<div class="post-metadata">

### Author: ![zazas321](https://avatars.discourse-cdn.com/v4/letter/z/59ef9b/32.png) [@zazas321](https://discourse.nodered.org/u/zazas321)
#### Post date: [24 July 2020 05:54 UTC](https://discourse.nodered.org/t/how-to-build-a-flow-variable-array-in-a-function/30585/29 "2020-07-24T05:54:57Z")

</div>

I could set a new array in this function :

```auto

if(flow.get('task_started')==0){
    var items_array = flow.get("individual_items")|| []
    flow.set("individual_items",items_array);
    var internal_counter = flow.get("internal_counter")||0;
    node.warn("task STARTED")
}
else
    node.warn("task already started")

var quantity = msg.payload
    var device_id = msg.topic.split("/");// split the whole topic to devicex ( untill /)
    msg.payload = device_id[0];
    msg.topic=`UPDATE pack_to_light SET Quantity = '${quantity}' WHERE Device = '${device_id[0]}'`

if(quantity >0){// only increment when quantity is more than 0,
// when quantity is 0, that means we finished picking items from that box
    flow.set("individual_items["+internal_counter+"]",msg.payload);
    flow.set('internal_counter',internal_counter+1)
}
return msg;

```

However, this function gets called many times during a single task ( it gets called once per each activated device). So if I need to activate 3 devices, this function will be called 3 times so I cannot reinitialize the array everytime 😕

I believe the best solution would be to somehow clear the array when the counter value reaches 0 ( as I mentioned on my previous post) or I need to somehow change the way my array is initialized in the first place

---

<div class="post-metadata">

### Author: ![JGKK](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/jgkk/32/18515_2.png) [@JGKK](https://discourse.nodered.org/u/JGKK)
#### Post date: [24 July 2020 06:04 UTC](https://discourse.nodered.org/t/how-to-build-a-flow-variable-array-in-a-function/30585/30 "2020-07-24T06:04:47Z")

</div>

- to completely delete a context var set it to `undefinded`:  
`flow.set("your_var", undefined);`
- to set it to an empty array simply do:  
`flow.set("your_var", []);` when your counter reaches 0

---

<div class="post-metadata">

### Author: ![zazas321](https://avatars.discourse-cdn.com/v4/letter/z/59ef9b/32.png) [@zazas321](https://discourse.nodered.org/u/zazas321)
#### Post date: [24 July 2020 06:13 UTC](https://discourse.nodered.org/t/how-to-build-a-flow-variable-array-in-a-function/30585/31 "2020-07-24T06:13:32Z")

</div>

Thank you as always sir. You helped a lot.  
I actually managed to find the root cause of the error:

```auto

if(flow.get('task_started')==0){
    var items_array = flow.get("individual_items")|| []
    flow.set("individual_items",items_array);
    
    var internal_counter = flow.get("internal_counter")||0;

    node.warn("task STARTED")
    node.warn(internal_counter)
}
else
    node.warn("task already started")

var quantity = msg.payload
    var device_id = msg.topic.split("/");// split the whole topic to devicex ( untill /)
    msg.payload = device_id[0];
    msg.topic=`UPDATE pack_to_light SET Quantity = '${quantity}' WHERE Device = '${device_id[0]}'`

if(quantity >0){// only increment when quantity is more than 0,
// when quantity is 0, that means we finished picking items from that box
    flow.set("individual_items["+internal_counter+"]",msg.payload);
    flow.set('internal_counter',internal_counter+1)
}
return msg;

```

In this function, I am setting "individual\_items" to an array which is controlled by "internal\_counter". We only initialize internal\_counter once, and I realized that I do not reset it, so when the first task starts, it increments by a few numbers, when the second task starts, it continues to increment, that is why it appends to an individual\_items array.

I just have to set internal\_counter to 0 when counter reaches 0 and that fixes the issue. Anyway it is probabaly a good idea to clear the array after the counter reaches 0

---

<div class="post-metadata">

### Author: ![zenofmud](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/zenofmud/32/316_2.png) [@zenofmud](https://discourse.nodered.org/u/zenofmud)
#### Post date: [24 July 2020 10:52 UTC](https://discourse.nodered.org/t/how-to-build-a-flow-variable-array-in-a-function/30585/32 "2020-07-24T10:52:34Z")

</div>

Curiosity question - are you actually saving an array of data for each device (i.e device1 [1,2,3..]) or an array of devices with one value? If an array of devices with one value, why not use an object?  
{"device1" : 1, "device2" : 2, "device3" : 3}  
Here is a little flow demonstrating what I mean

```auto
[{"id":"81ea6f6d.49c9a8","type":"inject","z":"16b1321b.7fa8d6","name":"","topic":"device/1","payload":"data for device 1","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":230,"y":100,"wires":[["fb6499fa.5adff"]]},{"id":"ab9e8d40.e5d5e8","type":"inject","z":"16b1321b.7fa8d6","name":"","topic":"device/2","payload":"data for device 2","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":230,"y":160,"wires":[["fb6499fa.5adff"]]},{"id":"cf6db212.1e57c8","type":"inject","z":"16b1321b.7fa8d6","name":"","topic":"device/3","payload":"data for device 3","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":230,"y":240,"wires":[["fb6499fa.5adff"]]},{"id":"fb6499fa.5adff","type":"function","z":"16b1321b.7fa8d6","name":"","func":"\nvar data = msg.payload\nvar device_part = msg.topic.split(\"/\")\nvar device_id = device_part[0]+device_part[1]\nvar devices = flow.get('devices')||{}\n\ndevices[device_id] = msg.payload\nflow.set('devices', devices)\nreturn msg;","outputs":1,"noerr":0,"x":450,"y":160,"wires":[["e4b11b58.54463"]]},{"id":"e4b11b58.54463","type":"debug","z":"16b1321b.7fa8d6","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":610,"y":160,"wires":[]}]

```

---

<div class="post-metadata">

### Author: ![system](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/1X/d073cd938eafa2e558d7c2cd59003b3ef4963033.png) [@system](https://discourse.nodered.org/u/system)
#### Post date: [22 September 2020 10:52 UTC](https://discourse.nodered.org/t/how-to-build-a-flow-variable-array-in-a-function/30585/33 "2020-09-22T10:52:35Z")

</div>

This topic was automatically closed 60 days after the last reply. New replies are no longer allowed.

[Previous page](https://discourse.nodered.org/t/how-to-build-a-flow-variable-array-in-a-function/30585.md?page=1)
