# One Function node instead of multiple change nodes!

**URL:** <https://discourse.nodered.org/t/one-function-node-instead-of-multiple-change-nodes/62447>\
**Category:** General\
**Tags:** node-red-dashboard, function-node\
**Created:** [10 May 2022 11:48 UTC](https://discourse.nodered.org/t/one-function-node-instead-of-multiple-change-nodes/62447 "2022-05-10T11:48:14Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![mkdthanga](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/mkdthanga/32/61384_2.png) [@mkdthanga](https://discourse.nodered.org/u/mkdthanga)\
**Post date:** [10 May 2022 11:48 UTC](https://discourse.nodered.org/t/one-function-node-instead-of-multiple-change-nodes/62447/1 "2022-05-10T11:48:14Z")

</div>

I have a lot of change nodes which sets new properties to the msg.payload as shown below. I want to use function node instead of multiple change nodes which are complex to read! How can I achieve this? Please help, I am new to Node-Red!

 ![grafik](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/4/a/4a3aedfc4ee017f93ad0cd5c679b309eb4a3eafc.png)

Regards,  
Mukara

---

<div class="post-metadata">

**Author:** ![mkdthanga](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/mkdthanga/32/61384_2.png) [@mkdthanga](https://discourse.nodered.org/u/mkdthanga)\
**Post date:** [2 June 2022 14:16 UTC](https://discourse.nodered.org/t/one-function-node-instead-of-multiple-change-nodes/62447/2 "2022-06-02T14:16:38Z")

</div>

I tried to implement the above requirement using function node (tested only for 2 variables), but can't get the desired output! It reacts nothing!

 ![grafik](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/b/4/b4ba16107f311643ffd1a403c5c1f3e732fbacea.png)

Any Idea how to achieve this using function node? Please advice!

Regards,  
Mukara

---

<div class="post-metadata">

**Author:** ![jbudd](https://avatars.discourse-cdn.com/v4/letter/j/5f8ce5/32.png) [@jbudd](https://discourse.nodered.org/u/jbudd)\
**Post date:** [2 June 2022 14:27 UTC](https://discourse.nodered.org/t/one-function-node-instead-of-multiple-change-nodes/62447/3 "2022-06-02T14:27:37Z")

</div>

In a function node you can use simple assignment statements like this:

msg.payload.event = "speed skating";  
msg.payload.location = "Lillehammer";  
msg.payload.time = 107.68;

---

<div class="post-metadata">

**Author:** ![mkdthanga](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/mkdthanga/32/61384_2.png) [@mkdthanga](https://discourse.nodered.org/u/mkdthanga)\
**Post date:** [2 June 2022 14:35 UTC](https://discourse.nodered.org/t/one-function-node-instead-of-multiple-change-nodes/62447/4 "2022-06-02T14:35:28Z")

</div>

Thank you @jbudd

I tried this below function its not working either,  
**Function:**

```auto
msg.topic = 'NodeID;ns=3;s="ExGrafanaDB"."MachineState"."Data"."Mode"."TimeProductionStart"';
msg.measurement= 'ExGrafanaDBMachineStateDataModeTimeProductionStart';

msg.topic = 'NodeID;ns=3;s="ExGrafanaDB"."MachineState"."Data"."Mode"."TimeProduction"';
msg.measurement= 'ExGrafanaDBMachineStateDataModeTimeProduction';

```

Any other suggestions are also welcome!

Regards,  
Mukara

---

<div class="post-metadata">

**Author:** ![jbudd](https://avatars.discourse-cdn.com/v4/letter/j/5f8ce5/32.png) [@jbudd](https://discourse.nodered.org/u/jbudd)\
**Post date:** [2 June 2022 14:43 UTC](https://discourse.nodered.org/t/one-function-node-instead-of-multiple-change-nodes/62447/5 "2022-06-02T14:43:29Z")

</div>

In what sense not working?

Do you really want to set msg.topic to that long and complex string, or are you hoping to include values from somewhere else?

So that we can understand what you are doing, share some of your data and the msg you want to create from it.

---

<div class="post-metadata">

**Author:** ![mkdthanga](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/mkdthanga/32/61384_2.png) [@mkdthanga](https://discourse.nodered.org/u/mkdthanga)\
**Post date:** [2 June 2022 15:07 UTC](https://discourse.nodered.org/t/one-function-node-instead-of-multiple-change-nodes/62447/6 "2022-06-02T15:07:04Z")

</div>

When I connect this function node between time trigger node & OPC UA client node, its not returning anything like its returned with individual change node for each variable (as shown in my original first post)!

I am trying to read all the available values from opc server running on siemens PLC and store them all (on value change) in Influx DB as measurements.

In order to use OPC Ua Client node which reads & stores them all into the database server (Influxdb), I have to set the msg.topic & msg.measurement for each variable which I want to store!  
**Flow:**  
FYI From OPC UA Client node & afterwards everything works fine!

 ![grafik](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/d/9/d941927360f50552c94599bab67437b902209888.png)

PFA flow file (.json)

[Read\_Multiple\_Data\_from\_OPC\_Server.json](https://discourse.nodered.org/uploads/short-url/clUelZpHWfogeavc8AzisEmgRxO.json) (3.7 KB)

This is what I created in order to store data from siemens opc server in influxdb!

Please feel free to advice/correct my implementations. I will be grateful for each & every tip!

Regards,  
Mukara

---

<div class="post-metadata">

**Author:** ![jbudd](https://avatars.discourse-cdn.com/v4/letter/j/5f8ce5/32.png) [@jbudd](https://discourse.nodered.org/u/jbudd)\
**Post date:** [2 June 2022 15:44 UTC](https://discourse.nodered.org/t/one-function-node-instead-of-multiple-change-nodes/62447/7 "2022-06-02T15:44:58Z")

</div>

Put debug nodes to show the entire message object at these points and compare the outputs.

 ![Untitled 5](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/6/9/69b834b642c08c2cdcc167bb454c018c29174bbf.jpeg)

Since I don't have a Siemens opc server or influxdb, or even necessarily know what they are, and you have not provided sample data, I will only point out that you probably only get one message from the function node versus two from the two change nodes.  
You can send multiple messages from a function with `node.send(msg);`, or with `return [msg1, msg2];`

So this might work

```auto
msg.topic = 'a long string';
msg.payload = 'another long string';
node.send(msg);
msg.topic = 'a third long string';
msg.payload = 'yet another long string';
return msg;

```

---

<div class="post-metadata">

**Author:** ![TotallyInformation](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/totallyinformation/32/31_2.png) [@TotallyInformation](https://discourse.nodered.org/u/TotallyInformation)\
**Post date:** [2 June 2022 18:29 UTC](https://discourse.nodered.org/t/one-function-node-instead-of-multiple-change-nodes/62447/8 "2022-06-02T18:29:18Z")

</div>

> [@jbudd](#):
>
> msg.payload.event = "speed skating";

Just a note that the code as written won't work if the incoming payload isn't an object.

The safest approach is something like:

```auto
msg.payload = {} // blank object
msg.payload.event = "speed skating"
// ... etc ...

```

---

<div class="post-metadata">

**Author:** ![craigcurtin](https://avatars.discourse-cdn.com/v4/letter/c/94ad74/32.png) [@craigcurtin](https://discourse.nodered.org/u/craigcurtin)\
**Post date:** [2 June 2022 23:58 UTC](https://discourse.nodered.org/t/one-function-node-instead-of-multiple-change-nodes/62447/9 "2022-06-02T23:58:19Z")

</div>

> [@mkdthanga](#):
>
> I tried this below function its not working either,  
> **Function:**

Based on the function that you have listed i think you are missing a fundamental concept in relation to NR

Each message is a distinct entity - so in the case of the function code above - you have set the msg.topic and the msg.measurement twice. The function node will overwrite the first one of each that you set with the 2nd one - and you will get a single message spat out that has the last values - in your case

> [@mkdthanga](#):
>
> ```auto
> msg.topic = 'NodeID;ns=3;s="ExGrafanaDB"."MachineState"."Data"."Mode"."TimeProduction"';
> msg.measurement= 'ExGrafanaDBMachineStateDataModeTimeProduction';
> 
> ```

What we need is a debug node on the incoming data from the Siemens PLC showing the complete message object that comes in and we can then advise you on the best way to tackle it

Craig

---

<div class="post-metadata">

**Author:** ![mkdthanga](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/mkdthanga/32/61384_2.png) [@mkdthanga](https://discourse.nodered.org/u/mkdthanga)\
**Post date:** [3 June 2022 07:04 UTC](https://discourse.nodered.org/t/one-function-node-instead-of-multiple-change-nodes/62447/10 "2022-06-03T07:04:13Z")

</div>

It worked perfect.Thank you very much 🙂 @jbudd

**Function Node (instead of 3 change nodes):**

```auto
msg.topic = 'NodeID;ns=3;s="ExGrafanaDB"."MachineState"."Data"."Mode"."TimeProductionStart"';
msg.measurement = 'ExGrafanaDBMachineStateDataModeTimeProductionStart';
node.send(msg);

msg.topic = 'NodeID;ns=3;s="ExGrafanaDB"."MachineState"."Data"."Mode"."TimeProductionEnd"';
msg.measurement = 'ExGrafanaDBMachineStateDataModeTimeProductionEnd';
node.send(msg);

msg.topic = 'NodeID;ns=3;s="ExGrafanaDB"."MachineState"."Data"."Mode"."TimeProduction"';
msg.measurement = 'ExGrafanaDBMachineStateDataModeTimeProduction';
return msg;

```

**Debug Logs:**

 ![grafik](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/4/f/4f898e054015d0711b9ca04bae4ca87ece082af2.png)

Debug from changes nodes as well (as you mentioned):

 ![grafik](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/8/5/85c5abeb579026d837f63a33e39cfc958d0ebe13.png)

---

<div class="post-metadata">

**Author:** ![mkdthanga](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/mkdthanga/32/61384_2.png) [@mkdthanga](https://discourse.nodered.org/u/mkdthanga)\
**Post date:** [3 June 2022 07:34 UTC](https://discourse.nodered.org/t/one-function-node-instead-of-multiple-change-nodes/62447/11 "2022-06-03T07:34:31Z")

</div>

Thank you so much for your suggestions/Help @craigcurtin

The OPC Client node can't read out the entire structure or PLC datablock (extension object), I tried to read out the entire datablock, but it returns null value! (see below screenshot)!

So far the only possibility is that we can read each & every variables/items individually ☹

 ![grafik](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/4/d/4d752fc2ca15ce8886626068f285b720e28ab349.png)

But here is the structure of variables from Siemens PLC via OPC Protocol:

 ![grafik](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/f/3/f380028ed51b13a3c366435a35264658eb763083.png)

I tried using the opc items node also, to read out the entire structure (MachineState), but I received "TypeError: Cannot read property 'length' of undefined" ☹

Please feel free to advice anything on this topic.

Regards,  
Mukara

---

<div class="post-metadata">

**Author:** ![TotallyInformation](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/totallyinformation/32/31_2.png) [@TotallyInformation](https://discourse.nodered.org/u/TotallyInformation)\
**Post date:** [3 June 2022 09:37 UTC](https://discourse.nodered.org/t/one-function-node-instead-of-multiple-change-nodes/62447/12 "2022-06-03T09:37:16Z")

</div>

> [@mkdthanga](#):
>
> Function Node (instead of 3 change nodes)

You may wish to note that doing it that way can occasionally catch you out since msg is a REFERENCE to the data and so making changes to it changes everywhere that the msg happens to be in use at the time of change.

While that won't probably impact you here, it can sometimes catch you out if your downstream nodes process things asynchronously.

To be really safe, this should work:

```auto
return [ [
    {
        topic: 'NodeID;ns=3;s="ExGrafanaDB"."MachineState"."Data"."Mode"."TimeProductionStart"',
        measurement: 'ExGrafanaDBMachineStateDataModeTimeProductionStart',
    },
    {
        topic: 'NodeID;ns=3;s="ExGrafanaDB"."MachineState"."Data"."Mode"."TimeProductionEnd"',
        measurement: 'ExGrafanaDBMachineStateDataModeTimeProductionEnd',
    },
    {
        topic: 'NodeID;ns=3;s="ExGrafanaDB"."MachineState"."Data"."Mode"."TimeProduction"',
        measurement: 'ExGrafanaDBMachineStateDataModeTimeProduction',
    }
] ]

```

The outer array sends to the first output port (only 1 in this case) and the inner array sends multiple independent messages.

---

<div class="post-metadata">

**Author:** ![mkdthanga](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/mkdthanga/32/61384_2.png) [@mkdthanga](https://discourse.nodered.org/u/mkdthanga)\
**Post date:** [3 June 2022 12:18 UTC](https://discourse.nodered.org/t/one-function-node-instead-of-multiple-change-nodes/62447/13 "2022-06-03T12:18:32Z")

</div>

Thanks a lot @TotallyInformation

Can anyone tell me why my below 'for loop' program is not working?  
**Error:**  
"Function tried to send a message of type Array"

**Function:**

```auto
topic_array = ['NodeID;ns=3;s="ExGrafanaDB"."MachineState"."Data"."Mode"."TimeProductionStart"',
				'NodeID;ns=3;s="ExGrafanaDB"."MachineState"."Data"."Mode"."TimeProductionEnd"',
				'NodeID;ns=3;s="ExGrafanaDB"."MachineState"."Data"."Mode"."TimeProduction"'
				];
				
meas_array = ['ExGrafanaDBMachineStateDataModeTimeProductionStart',
				'ExGrafanaDBMachineStateDataModeTimeProductionEnd',
				'ExGrafanaDBMachineStateDataModeTimeProduction'
				];

function append_array(topic_array, meas_array){
    var totalCount = topic_array.length ;
    const appended_array = [];
    //append dicts to array
    for (var i = 0; i < totalCount; i++){
    	appended_array.concat({topic: topic_array[i],measurement: meas_array[i]});
        }
    return appended_array;
}
    
msg= [
    [append_array(topic_array, meas_array)] 
];

return msg;

```

I would be grateful, If someone could help me find the mistake in above program!

Thanks in advance.

---

<div class="post-metadata">

**Author:** ![Steve-Mcl](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/steve-mcl/32/4826_2.png) [@Steve-Mcl](https://discourse.nodered.org/u/Steve-Mcl)\
**Post date:** [3 June 2022 12:43 UTC](https://discourse.nodered.org/t/one-function-node-instead-of-multiple-change-nodes/62447/14 "2022-06-03T12:43:14Z")

</div>

> [@mkdthanga](#):
>
> "Function tried to send a message of type Array"

1. `append_array` returns an array
2. you set msg to `[[ the_array_returned_by_append_array] ]`

e.g. you are returning `[[ [obj, obj, obj] ] ]`

Try this...

```auto
const topic_array = [
  'NodeID;ns=3;s="ExGrafanaDB"."MachineState"."Data"."Mode"."TimeProductionStart"',				 
  'NodeID;ns=3;s="ExGrafanaDB"."MachineState"."Data"."Mode"."TimeProductionEnd"',
  'NodeID;ns=3;s="ExGrafanaDB"."MachineState"."Data"."Mode"."TimeProduction"'
];
				
const meas_array = [
  'ExGrafanaDBMachineStateDataModeTimeProductionStart',
  'ExGrafanaDBMachineStateDataModeTimeProductionEnd',
  'ExGrafanaDBMachineStateDataModeTimeProduction'
];
const messages = topic_array.map((e,i) => { return {topic:e,measurement:meas_array[i]} })
return [messages]

```

  

That said: I assume some of this is dynamic - otherwise you would simply return an array of objects right?

Just in case: this will work...

```auto
return [
 [
  {
    topic: 'NodeID;ns=3;s="ExGrafanaDB"."MachineState"."Data"."Mode"."TimeProductionStart"',
    measurement: 'ExGrafanaDBMachineStateDataModeTimeProductionStart'
  },
  {
    topic: 'NodeID;ns=3;s="ExGrafanaDB"."MachineState"."Data"."Mode"."TimeProductionEnd"',
    measurement: 'ExGrafanaDBMachineStateDataModeTimeProductionEnd'
  },
  {
    topic: 'NodeID;ns=3;s="ExGrafanaDB"."MachineState"."Data"."Mode"."TimeProduction"',
    measurement: 'ExGrafanaDBMachineStateDataModeTimeProduction'
  }
 ]
]

```

---

<div class="post-metadata">

**Author:** ![mkdthanga](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/mkdthanga/32/61384_2.png) [@mkdthanga](https://discourse.nodered.org/u/mkdthanga)\
**Post date:** [3 June 2022 12:52 UTC](https://discourse.nodered.org/t/one-function-node-instead-of-multiple-change-nodes/62447/15 "2022-06-03T12:52:25Z")

</div>

Thanks a lot @Steve-Mcl

it works perfect. I want to program it as a loop, because its easier if my machine has 1000 variables. I just have to define an array with 1000 elements (topic & measurment) and the msg array formation will be done by the function (future oriented), no need to form 1000 dictionary inside the array in hard coded way.

Thank you once again 🙂

Best Regards,  
Mukara

 ![grafik](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/c/4/c48dd04ba73283e662b43f66a4536b6bef8fe464.png)

---

<div class="post-metadata">

**Author:** ![TotallyInformation](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/totallyinformation/32/31_2.png) [@TotallyInformation](https://discourse.nodered.org/u/TotallyInformation)\
**Post date:** [3 June 2022 12:59 UTC](https://discourse.nodered.org/t/one-function-node-instead-of-multiple-change-nodes/62447/16 "2022-06-03T12:59:06Z")

</div>

You can, of course, use node.send inside your loop and that is absolutely fine. Just create the output object for each send rather than reusing the incoming msg object.

---

<div class="post-metadata">

**Author:** ![mkdthanga](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/mkdthanga/32/61384_2.png) [@mkdthanga](https://discourse.nodered.org/u/mkdthanga)\
**Post date:** [13 June 2022 15:43 UTC](https://discourse.nodered.org/t/one-function-node-instead-of-multiple-change-nodes/62447/17 "2022-06-13T15:43:02Z")

</div>

How do you mean @TotallyInformation ? Like this below one?

```auto
timestamp= new Date().getTime();

topic_array = ['NodeID;ns=3;s="ExGrafanaDB"."MachineState"."Data"."Mode"."TimeProductionStart"',
				'NodeID;ns=3;s="ExGrafanaDB"."MachineState"."Data"."Mode"."TimeProductionEnd"',
				'NodeID;ns=3;s="ExGrafanaDB"."MachineState"."Data"."Mode"."TimeProduction"'
				];
				
meas_array = ['ExGrafanaDBMachineStateDataModeTimeProductionStart',
				'ExGrafanaDBMachineStateDataModeTimeProductionEnd',
				'ExGrafanaDBMachineStateDataModeTimeProduction'
				];

function append_array(topic_array, meas_array, timestamp){
    var totalCount = topic_array.length ;
    const appended_array = [];
    //append dicts to array
    for (var i = 0; i < totalCount; i++){
    	appended_array.concat({topic: topic_array[i],measurement: meas_array[i], timestamp: timestamp});
    	node.send();
        }
    return appended_array;
}

msg= append_array(topic_array, meas_array, timestamp) ;

return msg;

```

This function does not output anything! What is wrong here?

---

<div class="post-metadata">

**Author:** ![TotallyInformation](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/totallyinformation/32/31_2.png) [@TotallyInformation](https://discourse.nodered.org/u/TotallyInformation)\
**Post date:** [13 June 2022 17:03 UTC](https://discourse.nodered.org/t/one-function-node-instead-of-multiple-change-nodes/62447/18 "2022-06-13T17:03:15Z")

</div>

Yes, well, nearly. You aren't getting any output because you've not passed a msg object to the send function. Send takes the same data that return does.

---

<div class="post-metadata">

**Author:** ![mkdthanga](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/mkdthanga/32/61384_2.png) [@mkdthanga](https://discourse.nodered.org/u/mkdthanga)\
**Post date:** [14 June 2022 09:53 UTC](https://discourse.nodered.org/t/one-function-node-instead-of-multiple-change-nodes/62447/19 "2022-06-14T09:53:30Z")

</div>

thanks a lot @TotallyInformation , The below code is working perfect 🙂

```auto
timestamp= new Date().getTime();

topic_array = ['NodeID;ns=3;s="ExGrafanaDb"."MachineState1"."Data"."Mode"."TimeProduction"',
                'NodeID;ns=3;s="ExGrafanaDb"."MachineState1"."Data"."Mode"."TimeProductionStart"',
                'NodeID;ns=3;s="ExGrafanaDb"."MachineState1"."Data"."Mode"."TimeProductionEnd"'
				];
				
meas_array = ['ExGrafanaDbMachineState1DataModeTimeProduction',
                'ExGrafanaDbMachineState1DataModeTimeProductionStart',
				'ExGrafanaDbMachineState1DataModeTimeProductionEnd'
				];

function append_array(topic_array, meas_array, timestamp){
    var totalCount = topic_array.length ;
    for (var i = 0; i < totalCount; i++){
    	msg= {topic: topic_array[i],measurement: meas_array[i], timestamp: timestamp};
    	node.send(msg);
        }
}
append_array(topic_array, meas_array, timestamp) ;

```

Regards,  
Mukara

---

<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:** [28 June 2022 09:53 UTC](https://discourse.nodered.org/t/one-function-node-instead-of-multiple-change-nodes/62447/20 "2022-06-28T09:53:58Z")

</div>

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