Emerald Reverie

Gwmngilfen's blog - Tech, cooking, walking and other randomness from the heart of Scotland

OpenHAB & HestiaPi Classic, Heating Rules

| Comments

(This is part 4 of my home automation blog series. See the automation category for the whole set)

So, we have control of the HestiaPi Classic from OpenHAB, now it’s time to add some sensors and automate the control of the heating.

OK, OK, it’s been a really long break from posting. What can I say, life kinda smacked me with a bunch of family issues. That’s all settled down now, and with winter coming on fast, it’s time to sort out the last mile of my open source heating system - responding to temperature sensors.

Logic design

Lets start with our constraints:

  • Given the location of the Classic (in a cupboard), the on-board temp sensor isn’t very useful
    • it’s always 4-5C warmer there, and not with a linear relationship to the rest of the house
  • Heating schedules on Hestia depend on the on-board sensor
  • The on-board sensor overrides even boosts - if it’s too low, the heating won’t come on

So to start with, I’ve disabled all heating schedules - as far as Hestia is concerned, the heating should never be on. We also set the Classic’s setpoint temperature to 30C so that it will always come on when OpenHAB tells it to.

We can then use the boost heating API in my MQTT bindings to trigger a 30 min heating boost (from OpenHAB) if the other sensor(s) say it’s needed - and we can check this as often as we like (I’m using every 5 min).

We don’t cancel the heating when we reach the desired temperature though - that can cause a hysteresis loop where the heating is switching on/off every 5 min. Instead, we only test for turning the heating on. Once the heating reaches the desired temperature, the heating shuts down about 25min later (based on a 30min boost. This avoids the hysteresis loop, and the 30min value is easily changed in the rule if your home heats quicker / slower.

Rules

Currently I have 2 sensors, a Sonoff TH10 and a home-built Arduino DHT22 sensor from MysSensors.org. This allows me to react to the temperature in my child’s bedroom, and in the lounge.

We’ll break this down into a script and a rule to call it, just to separate out the code. You could factor this down further into separate scripts if you wanted. Let’s start with the really simple rule that just calls the script.

1
2
3
4
5
6
7
# /etc/openhab2/rules/hestia_heating.rules
rule "Check Temperature"
when
  Time cron "0 0/5 * ? * * *"
then
  callScript("hestia_temp_check")
end

Simple enough, every 5 min, call the script. Adjust the cron string if you want it faster / slower. Now the script - let’s build this up in stages.

Variables

First we’ll need some variables to refer to. We need the values of the sensors, cast to Numbers, a setpoint to compare of each of them to (so that you can request different temps in different rooms), and a flag to test later.

1
2
3
4
5
6
7
var     BedroomTemp     = sonoff_temp_c.state as Number
var int BedroomSetpoint = 20

var     LoungeTemp      = mysensors_dht_lounge.state as Number
var int LoungeSetpoint  = 20

var boolean need_heating = false

Lounge

I only really care about controlling the temperature in the lounge during the evening, so lets set up time boundaries for that:

1
2
var DateTime lounge_start = new DateTime(now.getYear(), now.getMonthOfYear(), now.getDayOfMonth(), 17, 0, 0)
var DateTime lounge_end   = new DateTime(now.getYear(), now.getMonthOfYear(), now.getDayOfMonth(), 23, 0, 0)

Now I can check both the time and the setpoint in one go:

1
2
3
4
if((now.isAfter(lounge_start)) && now.isBefore(lounge_end) && (LoungeTemp < LoungeSetpoint)) {
  logInfo("hestia", "Hestia: Lounge evening: " + LoungeTemp + " < " + LoungeSetpoint)
  need_heating = true
}

You can see I’m doing some logging here, this is so that I can go look in the logs if I want to see if the heating fired up. You could log this to another system if you wanted to. I’m also just setting a flag for now, we’ll fire up the heating at the end.

Bedroom

For my child, I can’t predict when naps / sleep will be happening. So, I need a consistent temperature all the time. That makes the rule very simple:

1
2
3
4
if ( BedroomTemp < BedroomSetpoint ) {
  logInfo("hestia", "Hestia: Bedroom: " + BedroomTemp + " < " + BedroomSetpoint)
  need_heating = true
}

Go!

Finally, we test the flag:

1
2
3
4
if ( need_heating == true ) {
  logInfo("hestia", "Hestia: setting 30 min boost")
  publish("openhab", "hestia/boost_heat", "30")
}

Thanks to the logging, you’d then see something like this is /var/log/openhab2/openhab.log:

1
2
2017-10-31 22:15:00.043 [INFO ] [clipse.smarthome.model.script.hestia] - Hestia: Lounge evening: 19.9 < 20
2017-10-31 22:15:00.050 [INFO ] [clipse.smarthome.model.script.hestia] - Hestia: setting 30 min boost

Conclusion

This is now an open, flexible, and highly extensible heating system. My future plans include:

  • More sensors (temperature and presence/motion), at least one per room
  • Time & presence-based heating of rooms
    • Ideally battery-powered ones from MySensors.org
  • Global “away” switch in the UI:
    • Disables all normal tests/rules
    • Instead checks every sensor is > 10C
  • Longer-term, potentially write some learning algorithms about pre-emptively turning on heating

I’m pretty pleased with this project, and it’s only going to improve. Hope it goes well for you too!

Comments