Heaty - a flexible heating control, facilitating schedules and manual intervention

I added the cooling entity back to the Thermostat card, so it has both “Set Heating” and “Set Cooling.” That, and set the mode to Auto and I’m good to go.

Exactly. And with Heaty you just need to group both entities into one room and set opmode_heat: Auto.

Hi Robert,

A couple of days ago I updated Hass as well as Appdaemon and Heaty and thus am running all the latest and greatest versions. Everything seems to be running fine, but Heaty is giving me some grief.

In AD’s log I found several of these entries :
2018-02-28 16:45:02.005254 INFO heaty: --- --- Skipping rule with faulty temperature expression: OFF if app.get_state("group.track_family") == "not_home" else Ignore()
This is not a rule I changed recently, and it never before provoked an error ?

Furthermore, AD’s errorlog gets spammed with following entries :

2018-02-28 17:24:00.014881 WARNING AppDaemon: Unexpected error in worker for App heaty:
2018-02-28 17:24:00.015808 WARNING AppDaemon: Worker Ags: {'type': 'timer', 'name': 'heaty', 'function': <bound method HeatyApp.publish_state_timer_cb of <hass_apps.heaty.app.HeatyApp object at 0x6b021090>>, 'id': UUID('63d40499-8e3c-4491-97be-7b4ac4da3f30'), 'kwargs': {}}
2018-02-28 17:24:00.016827 WARNING AppDaemon: ------------------------------------------------------------
2018-02-28 17:24:00.019030 WARNING AppDaemon: Traceback (most recent call last):
  File "/srv/homeassistant/lib/python3.5/site-packages/appdaemon/appdaemon.py", line 501, in worker
    funcref(self.sanitize_timer_kwargs(app, args["kwargs"]))
  File "/srv/homeassistant/lib/python3.5/site-packages/hass_apps/heaty/app.py", line 244, in publish_state_timer_cb
    self.publish_state()
  File "/srv/homeassistant/lib/python3.5/site-packages/hass_apps/heaty/app.py", line 923, in publish_state
    self.set_app_state(entity_id, state)
  File "/srv/homeassistant/lib/python3.5/site-packages/hass_apps/common.py", line 106, in set_app_state
    super().set_app_state(entity_id, state)  # pylint: disable=no-member
AttributeError: 'super' object has no attribute 'set_app_state'

I’m not sure whether this causes any real trouble, but it sure looks suspicious …

IMPORTANT

I won’t answer to any bug report posted in this thread anymore. This sort of posts just spams the thread with noise and won’t help at all when someone (or even me) wants to trace what resolved a specific issue some weeks, months or years later.

Open issues on Github and include:

  • Versions of Home Assistant, AppDaemon and hass_apps
  • A full log, with debug: true
  • Your apps.yaml
  • Explain what you did and how to reproduce the error.

Thanks.

1 Like

Is it possible to exclude (or include) a specific room in the schedule_prepend rules? I want all rooms to follow the rule, but not my bedroom.

This is what I have now:

schedule_prepend:
- temp: Add(-3.5) if app.get_state("binary_sensor.home") == "off" else Ignore()

And I would like something like this:

schedule_prepend:
    livingroom:
    - temp: Add(-3.5) if app.get_state("binary_sensor.home") == "off" else Ignore()
    kitchen:
    - temp: Add(-3.5) if app.get_state("binary_sensor.home") == "off" else Ignore()

@ashwin No, that’s not possible.

You could use schedule snippets and IncludeSchedule.

EDIT:
Or check for the room name in the temperature expression:

schedule_prepend:
- temp: Add(-3.5) if room_name in ("foo", "bar") and app.get_state("binary_sensor.home") == "off" else Ignore()
1 Like

Hi!

I am new to Heaty. I am not using HASS.io, but a venv installation on an Ubuntu server. At the moment, my rooms are equipped with Homematic thermostats on the radiators + a Homematic wall thermostat for every room. This is because the reading on a wall thermostat opposing the radiators is much more accurate than the reading directly from the radiator valves.

But I want to switch from my Homematic infrastructure to Z-Wave thermostats. Am I understanding correctly, that I can rebuild my scenario with Heaty? So a room’s temperature is read from a wall thermostat and Heaty controls the radiator thermostats appropriately? Furthermore, can anyone recommend cheap wall and / or radiator thermostats with Z-Wave?

Thanks!

Hi @qrioniclabs

As long as your wall thermostats are recognized as climate entities with setpoint and operation mode in Home Assistant, you can use the replication feature of Heaty to propagate changes at one thermostat to all other ones in the same room. Whether a thermostat is a wall or a real radiator thermostat shouldn’t make any difference in this case.

BTW. Maybe you can just keep the Homematic components and control them via Home Assistant? I’ve got no idea whether Homematic thermostats are supported by the homematic component or not, but it should be easy to find this out.

Best regards
Robert

Hi Robert, thanks for your reply!

Yes, the HomeMatic components are supported, and they are working pretty well. The schedules can be configured via their gateways webinterface which might be substituted with Heaty. But there are 2 slight advantages as I can see at the moment:

A - The HomeMatic devices will run standalone, even if HA or even their gateway is disconnected (less important)

B - The radioator thermostats are opening / closing depending on the wall thermostats reading, not their own. This is, what I was looking to find in Z-Wave thermostats combined with Heaty, but I am not sure, Heaty is quite as suffisticated. Let me explain a bit further:

Here is the heating graph of a room with 2 controlled radiators and a wall mounted thermostat on the wall opposing the radiators:

Compared to that, this is the heating graph of only a single radiator valve thermostat controlling istself using its own temperature reading:

The yellow line is the set temperature, the green line represents the actual temperature. As you can clearly see, in the upper example the actual temperature curve is much really smooth whereas in the room with the radiator valve being controlled depending on the reading directly with the thermostat (second graph), it looks much more “saw-toothy”. This example would be even clearer if the set temperature in the first room would be consistent. Also, imagine the radiator valve being slightly “protected” by a curtain drawn to the side - the room temperature would never be in any real relation to the temperature measured by the radiator valve.


Anyway, I hope you can now better understand what I am looking for and maybe someone can give me a definite answer if this can be achieved using Home Assistant and Z-Wave devices alone.

Still, thanks for your work! I am sure I can embed it in my existing setup, maybe just doing the scheduling for the rooms while the HomeMatic devices figure out the rest…

Thanks

-qrionic labs

@qrioniclabs

  1. Z-Wave thermostats won’t follow any scheduling actions commited by Heaty when they have no connection to Home Assistant, nor do Homematic thermostats.

  2. There is no standard way to configure an external temperature sensor to be used by Z-Wave thermostats. Some do support it via a propritary protocol, some don’t. In either case, there is nothing Heaty can do about it. Heaty just sets a thermostat’s target temperature at specific times of the day or when certain events occur. How the thermostat actually determines the current temperature can’t be controlled.

  3. Just as a side note… I’ve got some Eurotronic Spirit Z-Wave Plus thermostats that are achieving the temperature pretty well. But I think they don’t support external temperature sensors.

1 Like

Hi all,

I added a section about prerequisites for using Heaty to the docs. It also explains what Heaty does and what not. This should be useful for adopters and those who want to become one.

http://hass-apps.readthedocs.io/en/latest/apps/heaty/index.html#what-can-heaty-do-and-what-not

Best Regards
Robert

1 Like

Hello Robert

I have to take slight issue with your opening requirement - You need at least one radiator thermostat in each room you want to control. I don’t think this is quite true as written.

I have zero radiator thermostats and think Heaty is going to be great for my situation. My thermostats (I have two, plus a hot water timer) each control a zone of multiple rooms. My intention is to introduce intelligent radiator thermostats in certain rooms in the future, but my use of Heaty is undiminished right now

PS My adoption of Heaty is still on hold until my plumbing FINALLY gets repaired - hopefully - tomorrow

Hmmm, good point. So do you think changing “room” to “zone” would explain it better?

EDIT: I’ve updated the docs again. Can you please have a look at it?

Hey - personally I would have point 2 saying -

You need at least one thermostat in each room you want to control. Such a thermostat must be recognized as a climate entity in Home Assistant, and setting the target temperature from the Home Assistant web interface should work reliably. Additional thermostats can be controlled the same way, as long as they fulfill these conditions as well. If you only have a switchable heater and an external temperature sensor, have a look at Home Assistant’s Generic Thermostat platform to build a virtual thermostat first.

Ah, I see. The problem was the phrase “radiator thermostat”.

I’ve now changed it to just “thermostat”.

Thanks for mentioning this.

1 Like

Hi,
just upgraded to appdeamon 3 (released today) and now it crashes due to heaty throwing errors:

2018-03-18 16:43:27.012949 INFO AppDaemon: Initializing app heaty_full using class HeatyApp from module hass_apps_loader
2018-03-18 16:43:28.406443 INFO heaty_full: --- heaty v0.12.3 initialization started
2018-03-18 16:43:28.538713 INFO heaty_full: --- Heaty id is: 'default'
2018-03-18 16:43:28.614274 INFO heaty_full: --> [Büro] [Thermostat] Received target temperature 21.0.
2018-03-18 16:43:28.821389 INFO heaty_full: --- Initialization done
2018-03-18 16:43:28.824886 INFO AppDaemon: App initialization complete
2018-03-18 16:43:29.016271 WARNING AppDaemon: ------------------------------------------------------------
2018-03-18 16:43:29.017226 WARNING AppDaemon: Unexpected error in worker for App heaty_full:
2018-03-18 16:43:29.018405 WARNING AppDaemon: Worker Ags: {'name': 'heaty_full', 'id': UUID('8ae4abda-9919-4c06-9390-54753dc728cb'), 'type': 'timer', 'function': <bound method HeatyApp._publish_state_timer_cb of <hass_apps.heaty.app.HeatyApp object at 0x74d55d30>>, 'kwargs': {}}
2018-03-18 16:43:29.019290 WARNING AppDaemon: ------------------------------------------------------------
2018-03-18 16:43:29.021401 WARNING AppDaemon: Traceback (most recent call last):
  File "/usr/local/lib/python3.6/site-packages/appdaemon/appdaemon.py", line 529, in worker
    funcref(self.sanitize_timer_kwargs(app, args["kwargs"]))
  File "/usr/local/lib/python3.6/site-packages/hass_apps/heaty/app.py", line 120, in _publish_state_timer_cb
    self.publish_state()
  File "/usr/local/lib/python3.6/site-packages/hass_apps/heaty/app.py", line 276, in publish_state
    self.set_app_state(entity_id, state)
  File "/usr/local/lib/python3.6/site-packages/hass_apps/common.py", line 105, in set_app_state
    self.AD.set_app_state(entity_id, state)
TypeError: set_app_state() missing 1 required positional argument: 'state'
2018-03-18 16:43:29.022362 WARNING AppDaemon: ------------------------------------------------------------

It worked fine with appdaemon 3 beta 5 .

Hello Robert

At long last I have both a working heating system and some time to spare on my use of heaty. I have a couple of questions I’d like to ask.

  1. I have now upgraded to Appdaemon3, and heaty seems happy. However, it has been a few weeks since I updated heaty, and I suspect that you have released a new version by now. I cannot seem to find update instructions in the docs - do you have any?
  2. (On a related note, you may want to edit the top post of this thread to make it easier for newcomers to find the heaty code. The number of times I have clicked through the obsolete link … :slight_smile: )
  3. I have put my current heaty.yaml below. You will see that I am yet to include a hot water heating schedule. The reason for this is that in HA my heating has modes {“heat”, “auto”, “off”} but my hot water has modes {“on”, “auto”, “off”}. Do you have any suggestions how I can cope with this difference in heaty?

As ever, thank you for any thoughts you may have.

heaty_full:
  module: hass_apps_loader
  class: HeatyApp

#  master_switch: input_boolean.heating_master

  thermostat_defaults:
    set_temp_retries: 10
    set_temp_retry_interval: 60

    temp_service: climate/set_temperature
    opmode_heat: "heat"
    opmode_off: "off"

  schedule_snippets:
    downstairs_winter_default:
      - { weekdays: 1-5, start: "05:00", end: "06:00", temp: "23 if app.get_state('sensor.temperature__outside_front_hall') <= '-2' else Ignore()" }   # Boost if chilly now
      - { weekdays: 1-5, start: "06:00", end: "08:30", temp:  23   }
      - { weekdays: 1-5, start: "08:30", end: "16:30", temp: "23 if app.get_state('group.someone_is_home') == 'on' else 21" }                          # Boost if someone at home
      - { weekdays: 1-5, start: "16:30", end: "22:00", temp:  23   }

      - { weekdays: 6,   start: "05:00", end: "06:00", temp: "23 if app.get_state('sensor.temperature__outside_front_hall') <= '-2' else Ignore()" }   # Boost if chilly now
      - { weekdays: 6,   start: "06:00", end: "10:30", temp:  23   }
      - { weekdays: 6,   start: "08:30", end: "16:30", temp: "23 if app.get_state('group.someone_is_home') == 'on' else 21" }                          # Boost if someone  at home
      - { weekdays: 6,   start: "16:30", end: "22:00", temp:  23   }

      - { weekdays: 7,   start: "05:00", end: "06:00", temp: "23 if app.get_state('sensor.temperature__outside_front_hall') <= '-2' else Ignore()" }   # Boost if chilly now
      - { weekdays: 7,   start: "06:00", end: "22:00", temp:  23   }

      - {                                              temp: "20 if app.get_state('sensor.pws_weather_1n_metric') <= '-2' else 18"  }                  # Boost if probably chilly tonight

    downstairs_shoulder_default:
      - { weekdays: 1-5, start: "06:30", end: "07:30", temp:  22   }
      - { weekdays: 1-5, start: "07:30", end: "16:30", temp: "22 if app.get_state('input_boolean.janeathome') == 'on' else 20" }                       # Boost if wife at home
      - { weekdays: 1-5, start: "16:30", end: "22:00", temp:  23   }

      - { weekdays: 6,   start: "06:30", end: "09:00", temp:  22   }
      - { weekdays: 6,   start: "09:00", end: "16:30", temp: "22 if app.get_state('group.someone_is_home') == 'on' else 20" }                          # Boost if someone at home
      - { weekdays: 6,   start: "16:30", end: "22:00", temp:  23   }

      - { weekdays: 7,   start: "06:30", end: "22:00", temp:  22   }

      - {                                              temp:  17   }

    downstairs_summer_default:
      - {                                              temp:  15   }



    upstairs_winter_default:
      - { weekdays: 1-5, start: "05:00", end: "08:30", temp:  20.5 }
      - { weekdays: 1-5, start: "16:30", end: "21:30", temp:  21   }

      - { weekdays: 6-7, start: "05:00", end: "06:00", temp: "21 if app.get_state('sensor.temperature__outside_front_hall') <= '-2' else Ignore()" }   # Boost if chilly now
      - { weekdays: 6-7, start: "06:00", end: "10:00", temp:  21   }
      - { weekdays: 6-7, start: "16:30", end: "22:00", temp:  21   }

      - {                                              temp:  18.5 }

    upstairs_shoulder_default:
      - { weekdays: 1-5, start: "05:00", end: "08:00", temp:  20.5 }
      - { weekdays: 1-5, start: "18:00", end: "21:30", temp:  21   }

      - { weekdays: 6-7, start: "06:00", end: "10:00", temp:  21   }
      - { weekdays: 6-7, start: "16:30", end: "22:00", temp:  21   }

      - {                                              temp:  18.5 }

    upstairs_summer_default:
      - {                                              temp:  15   }



  rooms:
    downstairs:
      friendly_name: Downstairs
#      thermostats:
#        climate.downstairs_heating:
      schedule:
      - start_date: { month: 1,  day: 1  }
        end_date:   { month: 3,  day: 15 }
        temp: IncludeSchedule(schedule_snippets["downstairs_winter_default"])

      - start_date: { month: 3,  day: 31 }
        end_date:   { month: 5,  day: 30 }
        temp: IncludeSchedule(schedule_snippets["downstairs_shoulder_default"])

      - start_date: { month: 6,  day: 1  }
        end_date:   { month: 9,  day: 15 }
        temp: IncludeSchedule(schedule_snippets["downstairs_summer_default"])

      - start_date: { month: 9,  day: 16 }
        end_date:   { month: 10, day: 30 }
        temp: IncludeSchedule(schedule_snippets["downstairs_shoulder_default"])

      - start_date: { month: 11, day: 1  }
        end_date:   { month: 12, day: 31 }
        temp: IncludeSchedule(schedule_snippets["downstairs_winter_default"])


      friendly_name: Upstairs
#      thermostats:
#        climate.upstairs_heating:
      schedule:
      - start_date: { month: 1,  day: 1  }
        end_date:   { month: 3,  day: 15 }
        temp: IncludeSchedule(schedule_snippets["upstairs_winter_default"])

      - start_date: { month: 3,  day: 31 }
        end_date:   { month: 5,  day: 30 }
        temp: IncludeSchedule(schedule_snippets["upstairs_shoulder_default"])

      - start_date: { month: 6,  day: 1  }
        end_date:   { month: 9,  day: 15 }
        temp: IncludeSchedule(schedule_snippets["upstairs_summer_default"])

      - start_date: { month: 9,  day: 16 }
        end_date:   { month: 10, day: 30 }
        temp: IncludeSchedule(schedule_snippets["upstairs_shoulder_default"])

      - start_date: { month: 11, day: 1  }
        end_date:   { month: 12, day: 31 }
        temp: IncludeSchedule(schedule_snippets["upstairs_winter_default"])


      friendly_name: Hot water
#      thermostats:
#        climate.hot_water:
      schedule:

@PianSom

Good to hear that your heating setup works now.

Regarding points 1 and 2, there are upgrade instructions in the Getting started section in the docs. But you’re right, I should split them up into separate pages.

Regarding point 3, the purpose of a default value is that you can overwrite it for any specific thermostat. Just set the operation modes for your hot water thermostats directly instead.

BTW, I already tried to edit the first post, but for some reason there is no edit button… Maybe editing is disabled after a certain amount of time or a certain number of answers…

Best regards
Robert

@PianSom BTW, I’d suggest you reinstall in a virtualenv. The docs have been rewritten to explain how to do that. And don’t use appdaemon 3.0.0 right now, it has a known bug that wasn’t present in the 3.0.0b5, so please install that after you installed hass-apps.

Thanks @roschi - I had not spotted the upgrade instructions. And thanks also for pointing out that I need to override the thermostat default.

OK, I will leave this until Appdeamon 3 is mended. At that point I’ll look to set up heaty in a virtualenv.

But, while I am looking at this, one other question - for my hot water the state attributes for that climate are

{
  "aux_heat": "off",
  "unit_of_measurement": "°C",
  "custom_ui_state_card": "state-card-custom-ui",
  "temperature": null,
  "mode": "SCHEDULE",
  "min_temp": null,
  "supported_features": 2177,
  "max_temp": null,
  "operation_mode": "auto",
  "current_temperature": null,
  "friendly_name": "Hot Water",
  "operation_list": [
    "auto",
    "on",
    "off"
  ]
}

(FYI only aux_heat is a mode which turns on the hot water (or heating) for a certain fixed period of time.)

You will note that the temperature for climate.hot_water is null. Given that, I am a little unsure as to whether Heaty will be able to help me with a hot water program - do you have any thoughts?