Combination of filtered/sorted messages

#1

I was curious (and would REALLY appreciate it) if anyone has an elegant solution in Node-RED for the following problem:

I have data coming in messages from my thermostats in different rooms. Temperatures and setpoints for each room come in separate messages both as "value", with type "temp" or "setpoint", but with the same "description"/roomname field. Topics are "home/roomname/temp" or "home/roomname/setpoint".

How can I combine each message with the same "description"/roomname so I can get a message to send to the IFTTT maker channel/webhook where the included "msg.payload.value1" is the "description"/roomname, "msg.payload.value2" is the temperature, and "msg.payload.value3" is the setpoint. And not send one combined message out more often than every 4 seconds.

I understand that I have to combine or join messages filtered/sorted on the "description"/roomname or topic somehow, but can't seem to figure out how to use the join node or contrib-combine to achieve this.

0 Likes

#2

Is there a pattern to the incoming messages (time based or number of messages) ?
The batch node can do this. See documentation.

You could also store the data from each thermostat in a flow context, use a change node or function to modify the properties and use that to send to IFTTT.

0 Likes

#3

Use a function node. Combining variables in javascript is very easy.

If you want it as a readable string

x= a+” “+b;

0 Likes

#4

"Combine" may have been the wrong word in English, but I meant to get properties from several (2 defines by the same topic) messages and send one message with all the data as new properties.

0 Likes

#5

There's a pattern in that they come around once each 10 minutes. Also that they do come in both of the types but not necessarily in order.

However, I hadn't thought of the flow context variables. I was thinking of retaining MQTT messages (which are also sent per message) with timed reading of these, but may be error prone.

Will a change node store variables to the flow context or do I have to initialise them programmatically ? Also how do I store and retrieve an object where for each key "description"(room name) there are subkeys for "temp" and "setpoint" with a change node ?

0 Likes

#6

Let's break the problem onto meaningful parts.

  1. Definitions & data storage
  2. Updating current conditions by reading data from sensors or by change of setpoints
  3. Sending out messages to third party (IFTTT)

Those parts are logically connected as the system is one and only but they are different as they deal with different tasks. So it is meaningful to separate them visually and create their logic in different TAB-s (this is just suggestion)

  1. Definitions and data storage.

So you have home. var home = {} (object)
Home has rooms. home.rooms = []
Lets define rooms.var room = {name:"name of room",temperature:0, setpoint:0, updatetime:0}
... there will be more rooms...
but they all end up in rooms array
home.rooms[0] = room

By creating such structure and storing it in global context you can then update any of values when they change and store it again as most updated state of your home. Why global context? Because of

  1. Updating current condition

Where ever you'll need to read any of values, or change some of value, you can do it as simple as

var home = global.get("home")
var room = home.rooms["name of room"]
room.temperature = 25
room.updatetime = new Date().getTime()//timestamp
global.set("home",home)

or by using other function type dedicated nodes

  1. Now as you have always up to date home you can create messaging system whatever kind you like.
    some injector -> read values from home -> combine and create message-> send message

This way your system will be easy to manage and easy to use, it'll be simple to add properties to your objects without need to create all over again and stuff like that.

PS. code examples here are pseudo code.

0 Likes

#7

Thank you for taking the time.

That's probably a good way to think of the problem. I'm just not into javascript at all so would need hand-holding. For example I don't understand that a room in the structure as in section 1 is findable by "name of room" in section 2 because I would think you have to find it by array number... ?

Also is the whole section 2 equally easy to do in a Change node ?

0 Likes

#8

As I said it is a bit pseudo coding in examples just to bring code and real life close together.
In reality there is many ways to do it and every one has its own pros and cons and it all depends on needs and so on...
But it all is documented well and is worth of a bit reading time
JavaScript objects
JavaScript Arrays

Basically all of it can be achieved without using the function node. But even then you can understand those nodes better if you understand the structure of your data.

0 Likes

#9

I ended up using contrib-config to make a global object for every room, its temperature and setpoint, and Booleans for both temp and setpoint to signify whether I have gotten new data (they come separately and the booleans are reset when a combined message is sent to IFTTT), whenever NR is restarted.

Also I retained (in Mosquitto) the temps and setpoint already sent via MQTT to make sure my object is quickly populated on restart, and also use an MQTT-in node as input.

I then use a function node to add data to the global object, make adjustments to values, check Booleans and possibly prepare for sending to IFTTT. You were right in preferring function nodes, I just thought this could have been such a common pattern that some kind of generic node existed.

1 Like