Msg.payload is changing within a node

Hi,
i m struggling with some code function in node red.
if you can have a look on please

so the principle is that i want to draw a graph with values correspoding to certain topics.

so first i read a csv file to know which topics i need to record and i store them in an array "SelectedTopics", this is coming from a previous flow and from a global variable msg1

then i receive some topics from a MQTT Broker, now i want to take into account only the topics available in SelectedTopics.

the problem is that, when i check if the topic received is within the list of my selectedTopics, my msg.payload got a new value which is not the one from my MQTT broker but rather the SelectedTopics.payload.
i don t want this to change, so how to avoid it

here is a my code

var SelectedTopics=[];
SelectedTopics=global.get("msg1")
 
 
 var msgs = [];
 
 var time="";


//get the timestamp name

 for(var attr1 in msg.payload)
      {
          // verify the 3 last characters
          if(attr1.substr(attr1.length - 3)=="_ts" )
          {
          time=attr1;
          }

      }
      
      
 for(var attr in msg.payload) //get each message attribute
      {
         
         
          
          // verify that the attribute is one of those we want to record
      
         if (SelectedTopics.hasOwnProperty(attr)) // when i do this my msg.payload change and take the value of SelectedTopics , want to avoid this and keep the msg.payload coming from my broker
          {
              
        // construct an array containing each attribute with its payload value and set a topic name for this
          var newmsg={};
          newmsg.topic=attr;
          node.warn(`topic is ${attr}`)
          newmsg.payload=msg.payload[attr]
          node.warn(`payload value is ${msg.payload[attr]}`)
          newmsg.timestamp=msg.payload[time];
          node.warn(`timestamp is ${msg.payload[time]}`)
          
          msgs.push(newmsg);
          
         
         }
          
    }



    return [msgs];

Hi @Reims

when sharing code on the forum, please try to format it properly. Either use the </> button in the format toolbar, or surround your code with three backticks:

```
your code here
```

Please edit your post and then we can read your code properly and help.

1 Like

sorry Knolleary,
did not know first, i edited my post

Any help please?

We aren't sat in front of our computers endlessly refreshing the page to check if there is something to reply to. Please be a little patient.

Can you provide more of an example of the messages you pass to this function and what you expect the result to be. It is hard to picture what it is meant to be doing, nor what issue you are seeing.

sorry for my impatience...

More details

my SelectedTopic contains this value

image

and my msg.payload contains this value

image

so what i need concretly to do is to return the attributes and value from my msg.payload only if this attribute is one of the selected topic.

in this case i only need to return test_ax:5, test_ay:1.3 and test_rx:1.3

And do you want to return them as a single message containing all of the matching attributes, or one message per attribute?

like this

Your current code appears to create a new message for each matching attribute.

But if you want a single message with the matching attributes left in msg.payload, then something like the following would do it:

var SelectedTopics = global.get("msg1");

var newPayload = {};

SelectedTopics.forEach(function(attribute) {
    newPayload[attribute] = msg.payload[attribute]
})

msg.payload = newPayload;

return msg;

got this from my debugging node

image

and still , i think is is always changing my msg.payload value.

Is that using the code I provided? Or your original code?

What exactly is stored under msg1 in Global context? From your code I assumed you were storing an array. But maybe not.

You can use the Context sidebar to see the contents of context to confirm exactly what you have.

If you are using the code I provided and it hit the error you show, then it would have stopped. You must have something else in your flow changing the payload or you are not looking at what you think you are.

yes using the code you provided,

i have 2 flows, the first flow reads a csv file and save the topics i need to record into the global variable msg1

my csv file looks like this

image

and the function i use to take only the value i need to record is this

var out = [];

msg1={};

for (var i = 0; i < msg.payload.length; i++) {
    if (msg.payload[i].col2 !==null  &&  msg.payload[i].col2=="x")
    {

      
         var tmp=msg.payload[i].col1;
         out.push(tmp);
         
       
    }
}

msg1.payload = out;
global.set("msg1",msg1); 
return msg1;

then in my second flow, i have a MQTT broker which is executing a dummy python code to send some topic with their value

pub1  = mqttPublisher(topic="test/test_HF", name="cansensor")
print("Dummysender running")

while True:
    time.sleep(1)
    mm05Dict = {
        'test_ts': round((time.time()) * 1000),
		#'test_ts': round(time.time()),
        'test_ax': randrange(10),
        'test_ay': randrange(10),
        'test_az': randrange(10),
        'test_rx': 1.3,
        'test_rz': 1.5
    }

now i want just to take the value of a topic if this topic is within the list of the selected topic i took from my csv file, that is why i m using the if

but when i m doing this, it seems like the msg.payload i got from the MQTT broker is erased and remplaced by the msg1

So global.msg1 is not an array of strings. It is an object with a payload property whose contents is an array of the topics you want.

In which case, you can change the first line of the function to:

var SelectedTopics = global.get("msg1.payload");

What does your actual flow look like?

The function you've shared that stores msg1 in global context does send on a message with a payload containing the array of strings. Could it be that message you are seeing?

yes exact,

and obviously it was the msg1 that was returned in the second flow,

i m not sure what solved this but i just remove the return from my first flow. and now i got the correct value i wanted

If you are storing a complete message in context then don't do that. It is dangerous as messages are stored by reference, so if you save a message to context and then pass it on and, for example, the payload gets changed by another node then the payload in the context will also get changed, that can cause very odd effects. Just save to context the bit you need - the array in this case I think.

1 Like

Thanks.
i updated it and just save the array.