Need help with mqtt an to create a json string

Hello,

I hope to ask my questions here at the right place, because I'm a newbie in working with node-RED.

I'm trying to implement the following project:
I got a Zigbee Thermostat Radiator Value (TRV) and a separate temperature sensor in my room, communicating both via MQTT.
The TRV has an own thermometer, that measures the temperature near the radiator and an offset function, to calibrate the local temperature manually. But this offset is quite inaccurate, because between the cold and the hot radiator the respective offset to the room temperature differs a lot.

Now, my aim is to send a dynamic offset value to the TRV, so that it always uses the right room temperature for heating.
The steps I want to implement with node-RED are:

  1. Subscribe a JSON string from the TRV and the temperature sensor
  2. Compare the temperature values
  3. Calculate the necessary offset Value = [Temperature Sensor] - [Temperature TRV]
  4. Create a new JSON-String and publish it to MQTT

Where I need most help is how to work with a function-node and how to create a new JSON-string for the Output to MQTT.

It would be great if anyone could show me an example of a project similar to the described before. Actually, I do not know how to start and how to go the first steps. I would be grateful about every kind of help.

Thanks and best regards - Daniel

It would be helpful if you shared examples of the data msgs so that we can help directly. As you are dealing with multiple messages, you will need to keep track of the last inputs using context variables.

To output JSON, you can just send a msg.payload object and it will become a stringified JSON value in MQTT.

The offset should only be set once, as it will always be the same offset. The offset on mine are like -5C compared versus the room temperature. When heating, the room and TRV are somewhat in the same ballpark when at the target/desired temperature.

Hi, and thanks for your help. The msg.payload of the thermostat looks like this:

{"battery_low":false,"boost_timeset_countdown":0,"child_lock":"UNLOCK","comfort_temperature":21,"current_heating_setpoint":21,"eco_temperature":21,"error_status":0,"frost_protection":"OFF","heating_stop":"OFF","holiday_start_stop":"2021/01/01 01:01 | 2021/01/01 01:01","holiday_temperature":17,"linkquality":239,"local_temperature":21,"local_temperature_calibration":0,"online":"ON","open_window":"OFF","open_window_temperature":5,"preset":"auto","schedule":{"schedule":"06:00/17 12:00/18 14:00/17 17:00/18 24:00/17","week_day":"sunday"},"schedule_friday":"06:00/17 12:00/18 14:00/17 17:00/18 24:00/17","schedule_monday":"06:00/17 12:00/18 14:00/17 17:00/18 24:00/17","schedule_saturday":"06:00/17 12:00/18 14:00/17 17:00/18 24:00/17","schedule_sunday":"06:00/17 12:00/18 14:00/17 17:00/18 24:00/17","schedule_thursday":"06:00/17 12:00/18 14:00/17 17:00/18 24:00/17","schedule_tuesday":"06:00/17 12:00/18 14:00/17 17:00/18 24:00/17","schedule_wednesday":"06:00/17 12:00/18 14:00/17 17:00/18 24:00/17"...

And the msg.payload of the temperature sensor is here:

{"battery":100,"humidity":89.68,"linkquality":255,"power_outage_count":25,"pressure":1002,"temperature":20.24,"voltage":3005}

I thought to use the 'json' Node to convert the string to separate objects. And then to use "local_temerapture" and "local_temperature_calibration" from the thermostat and the "temperature" object from the sensor in a 'function' node. So that the offset value will not be constantly changed, I would like to include the condition that a new "local_temperature_calibration" is always set if the difference is lager than 2.5%.

At that point I'm sorry, that I don't know how to start coding the function and how to bring the things together. - Would be great to get some further advices.

Hi, thanks for your advice. In generous, I guess that your assumtion is true, especially, if you have a good air circulation in your room. Unfortunately, my radiator is installed in a small corner, so that I got quickly hot temperature around the TRV, but not in the rest of the room.

Just to clarify: I mean that the offset at the target room temperature will always the same. If you heat your room to the desired temperature and compare the temp of the TRV you can set the offset to the difference. Depending on the TRV you are using, you could also use valve opening % instead and set the offset to the max value available. TRV's internal temperature sensors suck.

Maybe but if there is poor air circulation or a draft, they might take a long time to equalise or may never do so.

Actually, the ones on the Wiser TRV's are remarkably reliable. I have several rooms with TRV's and my own sensors and they match very well.

First thing to do is make sure that you know the msg.topic values of the 2 messages. I'll make them up here.

let lastThermo = context.get('thermo') || -99 // ensures you have a value to work with
let lastSensor = context.get('sensor') || -99 // ensures you have a value to work with
if (msg.topic === 'thermostat') {
    // Update the thermo value
    lastThermo = msg.payload.local_temperature
    context.set('thermo', lastThermo)
}
if (msg.topic === 'sensor') {
    lastSensor = msg.payload.temperature
    context.set('sensor', lastSensor)
}

if (lastSensor === -99 || lastThermo === -99) {
    return // exits the fn without sending on a msg
}

let calib = lastSensor - lastThermo  // I might have that the wrong way around, test it

if (calib > 1) { // sorry, you'll have to put that in % terms yourself if you want that.
   msg.newCalibration = calib
}

return msg

I don't know what message you need to output to change the calibration so you will need to change that last part yourself.

Untested of course but should let you get started anyway.

Hi, thanks a lot for your help and the example. I'm very pleased! :wink: I guess I will need some days to implement the steps, because I'm just starting with node-RED. I will give a next response, if I could achieve the first results.