Only write to MQTT when value is changed to current value

I have a two scripts which do calculates and then output to a single MQTT topic.
Now externally the controlled machines reload their config also when the MQTT topic is unchanged, just the edit is in itself enough to reload.

Now I would like to have simple solution by checking whether the payload output is different from the target MQTT topic.

So I have a function body which payload output goes to the MQTT out. What is an elegant way to read in the MQTT value, compare it to the payload, and only pass it to the MQTT out when the value is different from the current value?

Have you looked at the filter node?
It only allows a message to pass if it's payload is different from the previous value.

2 Likes

It turns out I have to read another MQTT topic to get the status and second one to set the new value. Accordingly it gets already messy.

I solved it like this. I happy for feedback, I have a programming background but I don't feel at at home in Node Red at all yet... :frowning:
At the bottom: status is red, stored in a variable. That automatically updates. At the top the value, which might have changes, comes into the script, source shown. It's send further to the cmd mqtt topic only if it's value is indeed different.

You managed to include a global context variable too :face_with_peeking_eye:

And var

That's bad practice? How should I do it instead?

Again... I'm lost... that's bad practice? How should I do it instead? What would be correct?

  1. there is (probably) no need to store in global. flow context would limit it to "this flow" (slightly more portable)
  2. var is old skool - try to use const first but use let if you need to change its overall value.
  3. lastly, there is no real need for the overhead of a function node, a switch node would be sufficient here.
1 Like

At the root of flow based programming is the message.
It is a collection of one or more related bits of data.
For example an external sensor sends a message containing a timestamp, temperature, humidity and air pressure values.
This message travels along the wires between the nodes in the flow.
They might use it to update a database, to add new points on a chart, to trigger a warning email, and so on.

Ideally, everything needed by the processing is a part of the message.
Of course sometimes you need to compare this message with the previous one.
One way might be to introduce a function node like this:

msg.payload.previoustemp = context.get('previoustemp') || 0    // the default is 0
context.set('previoustemp', msg.payload.temperature)
return msg

Note that this context variable has no existence outside this single function node.
There is no way that it can fail to tack the previous temperature (or zero) onto the payload.
If another flow uses an identically named variable it will not interfere with this node.

Consider this little flow

If writing to the database takes a little time and a new message arrives, it doesn't matter. The previous value is safely attached to the payload, all the nodes are using the same data .
Now consider your way, comparing the current value with a global context variable.
If a new message arrives, there is scope for the context variable to be reset before you have finished using it.
Worse, you forgot an unrelated flow from last year which also uses global.previoustemp. Now messages in that flow can "magically" interfere with this one, and vice versa.

I have used a function node in this example, hopefully it's easy to understand. But it can be done, probably more efficiently, without functions.

Finally, my first reply above suggests using a filter node like this
image

The filter automatically compares this message with the previous one.
The message will only be passed to the LED if the filtered property (msg.payload.temperature) changes from the previous value.
I think this is all you need to prevent your machines receiving duplicates.

Note that @node_red2025 is comparing values from a different topic to that which he is writing.

Indeed he is but he described the problem as machines resetting when they receive a duplicate message over MQTT. So I suggest filtering that message to remove the duplicates.

True, but these seem to be hardcoded into the mqtt nodes anyway, so filtered messages will be sent to correct topic.

But what is required is to compare the current value of one topic to a new value coming in, which goes to a different topic.

The best way to do that is to use a Join node to join the current value of the status topic with the incoming payload, then the compare can be done.

TBH from what we are shown I don't really understand the logic of the flow.

If the device is reporting it's current mode, then why send this back to the device at all, seems like a good way to create a loop :wink:

The objective is to set the current mode which is done via a command. Sending the command has side effects so he/she doesn't want to send the command if the mode is already correct.