From your debug output, it seems that every msg has a single reading, under different property names. As Colin suggests, every sensor should use it's own topic, if only for clarification while debugging. You can still have single mqtt in
node with a wildcard topic module/#
that receives all the sensor readings. And you can still pass along a JSON payload with a named property (i.e. msg.payload.humidity
) just like you are showing, if you want to.
The goal is to have every dashboard widget only receive the messages it can show -- which is why Steve suggested you use a switch
node to route the messages, and why Colin likes separate mqtt
nodes, to route them properly. Seems like the same number of "routing" nodes are needed in either case, equal to the number of measurements you want to display.
A simpler way I've used is to use the wildcard mqtt node to receive all measurements, and then use a function
or change
node to "merge" the 1 new reading into a flow context "object" which holds ALL the measurements that have been received. Then on a separate flow you can use an inject
node set to send the context object periodically, which updates each widget on the dashboard. As Colin suggested, each gauge or meter just displays a single property from the same context object -- so no msg routing is needed.
The logic that stores each incoming reading will depend upon your topic/message structure. For instance, if your msg.topic
was "module/12/temperature" and your JSON msg.payload
included was { "temperature": 27 }
, you could use this JS code in a function to merge it with your flow context object (untested):
let readings = flow.get("AllReadings") || {}; // get any existing flow readings
let {prefix, module, type} = msg.topic.split("/"); // split the topic into module and type
let reading = readings[module] || {}; // get or init the new reading for this module
reading[type] = msg.payload[type]; // set the new reading value for this module
flow.set("AllReadings", readings); // save all readings back into flow context
(I'm sure someone will point out any errors in this code ...)
The equivalent way of doing that is to use a change
node to set flow.AllReadings
to the output of this JSONata expression:
(
$parts := topic.$split("/");
$readings := $flowContext("AllReadings") ? $flowContext("AllReadings") : {};
$readings[$parts[1]] := $merge($readings[$parts[1]], payload);
$readings
)