Creating a string from Number items to send over MQTT?


I have been slowly automating my home heating and am using Moes BRT-100 electronic TRV actuators, currently linked to a Sonoff Zigbee hub running Tasmota. The TRV’s are set in manual mode and the current rules are changing the manual setpoint of each actuator as and when heat is required.

There are limitations with the integration of the BRT-100 with the Tasmotized bridge, and I’ve started experimenting with Zigbee2MQTT running on another PI. This approach makes all atrributes of the TRV available, including the possibility of having each TRV working off its own time program.

To be able to use this function I need to be able to create a string to send over MQTT like

"programming_mode": "08:00/18°C  11:30/18°C  18:00/5°C  22:30/5°C  06:00/5°C  11:00/18°C  14:30/18°C  17:30/5°C  09:00/18°C  12:30/18°C  14:30/18°C  18:00/5°C"

The first four time / temperature pairs in the above example are for the weekdays Monday to Friday, the second four are for Saturday and the final four are for Sunday.

My thought process is that I could create number items as setpoints for each element, i.e 08 for hours, 00 for minutes, and Occupied and unoccupied temperature setpoints then create the string to be able to send over MQTT, but I haven’t got a clue where to start! I have done some research but most of what I have doesn’t explain adequately to my limited knowledge understanding!

I suppose I should explain that whilst my current solution does work, it is rather digital in its approach where the valves either open or close to 100%. If I can utilise the inbuilt program function of the TRV head, they modulate as they get close to setpoint, reducing LPHW flow and thus energy input and heat output which will increase system efficiency giving more linear temperature control for minimum cost. With the cost of Gas and Electricity in the UK at the moment, this can only be a good thing!

Any advice or suggestions gratefully received.

  • Platform information:
    • Hardware: Raspberry Pi model 3B
    • OS: Linux openHABPI 4.19.66-v7+
    • Java Runtime Environment: OpenJDK Runtime Environment Zulull.43+88-CA (build 11.0.9+11-LTS)
    • openHAB version: 3.0.1

Using multiple Items is a good plan. People sometimes avoid that, as though it costs money. It comes with advantages like easy to persist-restore across reboots. We can Group them up to make them easier to handle, perhaps a Group of temps and a Group of times per valve, and a Group of Groups for the whole sub-system

Because it involves multiple Items, that’s a job for a rule. It’s just formatting Item states and assembling into a long string.
You can send that directly from rule with MQTT Action, or create a string channel to be more consistent with other ins/outs and command that via intermediate Item.
Trigger the rule from any controlling Items changing.

A refinement would be to add a delay, so that it didn’t send on every UI click.

Making a nice UI widget for this array of times/temps should be an interesting challenge :smiley:

Definitely create separate Items and take advantage of Groups. I’d use one Group for the times and another one for the setpoints. And make sure to name the setpoints so you can easily construct the name based on the time Item’s name.

I’d use DateTime Items to store the times and just ignore the date part.

Name the Items so they can be sorted by name. Then you can sort and loop through them in order and not have to write a lot of repetitive code.

We can’t start an Item’s name with a number I think (unless that’s been changed) so I’d use names like: aMonday_HeaterTime, bTuesday_HeaterTime and so on. The Setpoint Items would use aMonday_HeaterSetpoint and so on.

Assuming Rules DSL and DateTime Items for the times the code would look something like (the setpoint Group is named “HeaterSetpoints” and the times Group is named “HeaterTimes”:

val formatter = new java.time.DateTimeFormatter('HH:mm');
val program = HeaterTimes.members
                             .sortBy[ i | ]
                             .reduce[ pgm, sp | 
                                 val spItemName ='Time', 'Setpoint')
                                 val spValue = HeaterSetpoints.members.findFirst[ i | == spItemName ]
                                 pgm = pgm + (sp.state as DateTimeType).getZonedDateTime().format(formatter) + '/' + spValue + '°C '

val message = '"programming_mode": "' + program + '"'
// send message via MQTT

See Design Pattern: Working with Groups in Rules for details on the reduce and sortBy and such.

The way that works is it gets the members of the HeaterTimes, sorts them by name (hence the naming convention. Then it reduces the members down to a single String. In the reduce, first we generate the name for the Setpoint Item using the name of the time Item by replacing the “Time” part with “Setpoint” (again the naming convention). Then we get the Setpoint Item so we can get it’s state.

Finally we add the time/sepoint to the pgm which is the variable the states are being reduced into.

We need to trim that last space off the string and then send the program string.

Thank you for the quick responses, Gentlemen.

I am going to read up on the Design Pattern and try to understand the elements of the rule example, then have an experiment.

Unfortunately it’s going to take a few days as I am rather busy workwise until the end of the week, but I will report back and hopefully mark as solved with a working example of the rule I have created.