Extract mqtt topic json

Hey guys,

I am using node-red to extract a mqtt message to write the values into influxdb.
It works very well and looks like this:

let thisRoom = msg.topic.split("/")[2]
msg.payload = [{temp: msg.payload.temp, hum: msg.payload.hum},{room: thisRoom}]
return msg

Now, I have a new sensor which is not transmitting humidity. but the topic structure have to be the same.
So, at the moment, I get an error because no hum value exists.
Is it possible to change this script to make it able to do both kinds of mqtt messages?
If it is possible, I won't like to use a seperate flow or a new topic structure.

screenshot|254x500

In a function node

let hum = msg.payload.[0]hum

if(typeof hum === "undefined"){
    hum = 0
}

msg.payload.[0]hum = hum
1 Like

If there is no humidity value then preferably you should not save it to a Measurement that normally includes temp and hum as this means that your db is full of empty holes, which is inefficient. Possibly the best way would be to split it into two measurements, temp and hum, and feed values to both measurements for those sensors that have humidity and only to the temp one for those without humidity.

still this error:

Error: A 400 Bad Request error occurred: {"error":"unable to parse 'sensormeasure,room=sau hum=undefined,temp=7.01': invalid boolean"}

is this correct:

let thisRoom = msg.topic.split("/")[2]
if(typeof hum == "undefined"){
    hum = 0
}
msg.payload = [{temp: msg.payload.temp, hum: msg.payload.hum},{room: thisRoom}]
return msg

If you feed the output of that into a function node you will see that it is still showing hum: undefined. It is always best when testing to add a debug node to the output of the node you are changing to see what comes out.

I think, if you do want them all to go to the same measurement even though you will end up with a db full of holes, then you need something like

let thisRoom = msg.topic.split("/")[2]
const hum = msg.payload.hum
msg.payload = [{temp: msg.payload.temp},{room: thisRoom}]
// add the humidity into the message if it exists
if(typeof hum != "undefined"){
    msg.payload[0].hum = hum
}
return msg

Check in a debug node that this gives what you expect before connecting it to the db.

2 Likes

that's it, thank you!

yeah, maybe it is not absolutly clean. but hey, I planed to do the humidity measurement in that room too. I have just messed up the order for the sensor. So my sensor is not able to do the humidity measurement. Maybe I replace it sometime.

Or do you think it's better to write a "0" instead of just nothing like now?

Is the humidity in that room 0 or unknown? My take would be that the answer to that question determines what should go in the database.

unknown...

It was intended to be a rhetorical question, to suggest whether zero or nothing should go in the db. I would say don't put zero in the db unless the value is zero. If you don't know what it is then don't put anything in.

:slight_smile:
thank you colin,
I know you are an expert and you did help me a lot in the past and also this time. but i am not sure if it is worth to change my db that much just because of this guinea pig barn sensor.... :confused:

or do I just have to add some kind of measurement2 and ask you for the filtering function? I can do a bit C++ Arduino programming but I am not into this function scripting in node-red so I have to ask for everything. feels bad man.

If you are intending to add the humidity sensor at some point then don't worry about it, keep it as you have it.

lol
I fear the will never happen. to be honest, i placed that device in the barn and as long as it is working well, the motivation to replace it is not really existant :thinking:

maybe I should give it a try.
So you suggest not to change the temp/hum sensors. Just to add a new flow in node-red which filters the room "sau" and write only the temp.

1.) So, therefore I have to change the function of my temp/hum flow in that kind, that they do not try to process date from the topic "sensors/room/sau".
at the moment they respond on "sensors/room/#". So before I switched to your code today, they throw an error everytime the message to "sensors/room/sau" arrived. That was not a desaster but it is also not very clean.

2.) I have to add a flow only for "sensors/room/sau". I think I am able to do that by myself. at least I hope so.

Is that correct or do I misunderstood you maybe?

You just need one flow, but it should send all temperature data to one measurement and humidity to another. You can do that by making it send one or two messages.

let thisRoom = msg.topic.split("/")[2]
const hum = msg.payload.hum
const temp = msg.payload.temp
let messages = []
if(typeof temp != "undefined"){
  let newMsg1= {}
  newMsg1.payload = [{value: msg.payload.temp},{room: thisRoom}]
  newMsg1.measurement = "temp"
  messages.push(newMsg1)
}
if(typeof hum != "undefined"){
  let newMsg2= {}
  newMsg2.payload = [{value: msg.payload.hum},{room: thisRoom}]
  newMsg2.measurement = "hum"
  messages.push(newMsg2)
}
return [messages]

That will cope with either one of both values present, passing on one or two messages as appropriate. The convention if you just have one value in a measurement is to call the value 'value' as what it is is identified by the measurement name. You will need to clear the measurement name in the influx node so that it will use the measurement name from the messages.

I got curious and played around with the code a bit.
sorry :flushed:

let thisRoom = msg.topic.split("/")[2] ?? "other room"
msg.payload = [{temp: msg.payload?.temp, hum: msg.payload?.hum},{room: thisRoom}]
return msg

it still returns "undefined", but without an error in the debug window

Hey, that seems to work and I can add it to my existing graphs.

Let's wait one or two days. I'll let you know!

:heartbeat:

The Optional Chaining operator ?. tests the preceding property to see if it exists, so in that code you are testing msg.payload, which will always exist (in this context). So that line is exactly the same as
msg.payload = [{temp: msg.payload.temp, hum: msg.payload.hum},{room: thisRoom}]

yeah :innocent:. It will remain undefined, but it will suppress the error output to the debug window.
Sorry, just a bad joke.

Which error?