Smart Vent HVAC automation with Keen (or others) dimmable vents

Hello.

So in the past, I had been running my Keen vents connected to my SmartThing hub with a cloud app built by Barry Burke running the configuration and automations required. With SmartThing essentially shutting apps down, this is no longer an option.
So I decided to try to replicate the features I was using, natively in Home Assistant and have it run in a “set it and forget it” mode: automation rather than remote control.
This is not about saving money, so there’s no presence detection (my thermostat does that already), no open windows/doors disabling of zones or anything like that. At this point, this is just a basic framework to bridge the gap left in SmartThings without going back to the native Keen app. The major hinderance in HA was that virtual thermostat implementations only control switch type devices

My requirements:

  • Automated
  • Run native, no need for node red
  • Least amount of custom components
  • Temperature equalization (I live in a 3 levels house with a central source of heat)
  • Adjustable
  • Easy on vent batteries (avoid unwarranted movements of the vents as the more vents move the more battery energy usage)

My setup physical:

  • I have vents on 3 floors, 1 for the basement zone, 2 on the ground floor zone where the thermostat is (aka the master zone), and 1 each in the office and two bedrooms.
  • Not all the vents are smart vents, and that wouldn’t be necessary or even recommended to avoid an “all closed” situation as this is a recipe to kill your furnace.
  • Each room/zone has at least a temperature sensor.
  • I did some duct work to allow for better air circulation, insulation/air sealing work and all that good stuff but I’m still not there, so this setup compensates for the badly designed vent system.

The automations, devices and helpers
Automations

  • Automation to open specific vents when thermostat goes into fan mode/circulate mode
  • Automation to open all vents when I want to disable everything (aka kill switch)
  • Automations to synchronize the target temperatures for each zone whenever the target temperature is change on the thermostat and an hourly automation that does the same thing, just in case
  • Automations that link virtual thermostats for each zone to the zone vents

Devices

  • Generic thermostat for each zone, currently using out of the box device but will migrate to “Dual Smart Thermostat” custom integration. These devices take care of triggering the on/off of the virtual heat source based on target temperatures. Avoid a bunch of automations.

Helpers

  • the kill switch, to stop all automation around HVAC
  • Master thermostat target temperature, just makes my life easier to have in a helper/easier visualization in HA
  • Target temperature offset for master zone, allow me to “slow down” the effect of the HVAC in the master zone slowing down the effect on the thermostat temperature sensor. In my case, my main issue is that the other zones tend to not always reach target temperatures in the winter.

Notes and future enhancements;

  • create helpers for each zone representing the low and high range of the vents. Right now this is hard coded in each automation.
  • Vents and safety: I’m being cautious so not all vents are automated and I never fully close vents. I have temperature sensors in the ducts, at the source to monitor the effects. I will probably automate an automation kill switch based on excessive temperatures at some point.
  • Keen vents tend to be noisy at 0 and 100% opening, so backing off 5 percent cuts down the noise.
  • Out of scope for temperature management, but I also monitor air pollution level (co2, pm2.5) and turn on the HVAC fan to dilute CO2 and filter particles).
  • HA schedules could be used to modify the temperatures in certain zones to save on heating.

To get this implemented, you will need a zoning plan and the following integrated in HA:

  • a smart thermostat, need to be able to read target and current temperature as well as fan mode
  • at least one smart vent, needs to show up as a dimmable device
  • a temperature sensor in each zone, the ones in the vents are not useful

So this turned out to be longer than expected. I’ll follow up with the step by step to get you there.

I know this is mostly conceptual, but feel free to comment/question.

2 Likes

To get started, you will need to create helpers for a few things. Go under Settings, Devices & Services, Helpers for that.

  1. Create a master enable/disable toggle, I’ve named mine HVAC Automations enabled

  2. Create a demand toggle for each zone you plan to use (You need at least a temperature sensor and a smart vent in each zone). These will hold the demand value used by the thermostats. For example, HVAC Basement Heat demand

  3. Create Number type helpers, for your HVAC Target temperature and HVAC Target Heat temp offset. For both select, a step size (the amount of degrees or fraction of degrees you can adjust manually; a minimum and maximum value, and a unit of measurement. Here’s what my offset and target temp helpers look like:


Once the helpers are created, you’ll be able to create the generic thermostats. You’ll need one for each “zone” minus the physical smart thermostat for your master zone.
To create the generic thermostats, you’ll need to edit your configuration.yaml file.

Here’s a sample of two of my thermostats:

climate:
  - platform: generic_thermostat
    name: Ground_thermostat
    heater: input_boolean.hvac_ground_floor_heat_demand
    target_sensor: sensor.thermostat_temperature
    ac_mode: false
    target_temp: 22
    sleep_temp: 19
    cold_tolerance: 0.5
    hot_tolerance: 0.0
    min_cycle_duration:
      seconds: 300
    initial_hvac_mode: "heat"
    target_temp_step: 0.5
    
  - platform: generic_thermostat
    name: Office_thermostat
    heater: input_boolean.hvac_office_heat_demand
    target_sensor: sensor.office_temp_sensor_temperature_measurement
    ac_mode: false
    target_temp: 22
    sleep_temp: 19
    cold_tolerance: 0.5
    hot_tolerance: 0.5
    min_cycle_duration:
      seconds: 300
    initial_hvac_mode: "heat"
    target_temp_step: 0.5

The ground thermostat is my master zone. It uses the thermostat temperature as its sensor. Also notice, the cold_tolerance and heat_tolerance values. It reduces swing around the temperature. Closer to zero, the closer to the target temperature the vents are going to close or open.

So, for my master zone, once the thermostat senses let’s say 22C, it will turn off the input_boolean.hvac_ground_floor_heat_demand and turn it on once it hits 21.5C. Right now, you can test this out but it does nothing without the automation.

Once the helpers and generic thermostats are created, we can jump in the core of the automation… the automations.

First the master automation toggle. If the toggle is set to off, all the vents are fully opened: I set the vents to 98% to avoid unnecessary noise. The state of the toggle is also used as a condition in other automations to prohibit an automation from running.

alias: HVAC Master Automation toggle
description: ""
trigger:
  - platform: state
    entity_id:
      - input_boolean.hvac_automations_enabled
condition: []
action:
  - if:
      - condition: state
        entity_id: input_boolean.hvac_automations_enabled
        state: "off"
    then:
      - service: light.turn_on
        data:
          brightness_pct: 98
        target:
          entity_id:
            - light.basement_vent
            - light.living_room_vent_ne
            - light.living_room_vent_nw
            - light.small_bedroom_vent
            - light.office_vent
            - light.keen_home_vent_plug
mode: single

Then I use an automation that synchronizes the temperature of each generic thermostat to the physical thermostat. I helps equalize the temperature and keeps the scheduling on the physical smart thermostat. You could absolutely set schedules for each generic thermostat to have independent schedules, or even set each thermostat manually but the latter would be automation :wink: but rather micro-management IMO.
The automation below sets a helper for the target temperature, then sets each generic thermostat target temperature to the value of the helper. I like having the helper around to test or do occasional manual changes.
Do note the last action of the automation refers to the generic thermostat for the master zone and the value is set to the target temperature of the physical thermostat + the offset set in the helper. As mentioned initially, I do that because my non-master zones tend to miss the mark below the target so I close the master zone (not 0% but around 20%) before it hits the temperature. This way the physical thermostat stays one for a while.

alias: HVAC Update target helper on temp change
description: ""
trigger:
  - platform: state
    entity_id:
      - climate.thermostat
    attribute: temperature
condition:
  - condition: state
    entity_id: input_boolean.hvac_automations_enabled
    state: "on"
action:
  - service: input_number.set_value
    data_template:
      entity_id: input_number.hvac_target_temp
      value: "{{ trigger.to_state.attributes.temperature }}"
    alias: Update helper
  - service: climate.set_temperature
    data_template:
      temperature: "{{ trigger.to_state.attributes.temperature }}"
    target:
      entity_id: climate.office_thermostat
  - service: climate.set_temperature
    data_template:
      temperature: "{{ trigger.to_state.attributes.temperature }}"
    target:
      entity_id: climate.master_bedroom_thermostat
  - service: climate.set_temperature
    data_template:
      temperature: "{{ trigger.to_state.attributes.temperature }}"
    target:
      entity_id: climate.basement_thermostat
  - service: climate.set_temperature
    data_template:
      temperature: >-
        {{ states('input_number.hvac_target_temp') | float +
        states('input_number.hvac_target_heat_temp_offset') | float}}
    target:
      entity_id: climate.ground_thermostat
mode: single

Finally, the magic happens when the following automations that wait for the helper to change state and adjust the smart vents. These automation are also the ones you’ll probably tweak a little bit more to find the open and close percentage that work best for each zone. You need one automation like this for each zone.

Here’s how it works: whenever the demand switch changes state, the automation is triggered. If the master automation help is off, it aborts. If the demand switch is set to on, then the vents are opened up. If the demand switch is set to off, then the vents are closed. You’ll also notice it is super easy to have two or more smart vent in a zone.

alias: HVAC link vent switch ground floor
description: ""
trigger:
  - platform: state
    entity_id:
      - input_boolean.hvac_ground_floor_heat_demand
condition:
  - condition: state
    entity_id: input_boolean.hvac_automations_enabled
    state: "on"
action:
  - if:
      - condition: state
        entity_id: input_boolean.hvac_ground_floor_heat_demand
        state: "on"
    then:
      - service: light.turn_on
        data:
          brightness_pct: 55
        alias: Vent to 55%
        target:
          entity_id:
            - light.living_room_vent_ne
            - light.living_room_vent_nw
    else:
      - service: light.turn_on
        data:
          brightness_pct: 20
        target:
          entity_id:
            - light.living_room_vent_ne
            - light.living_room_vent_nw
        alias: Vent to 20%
mode: single

So with all this in place, you should have a functional system.

Bonus

Open vents when the thermostat is asking for ventilation

alias: HVAC FAN ON, open vent
description: ""
trigger:
  - platform: state
    entity_id:
      - climate.thermostat
    attribute: hvac_action
    to: fan
condition:
  - condition: state
    entity_id: input_boolean.hvac_automations_enabled
    state: "on"
action:
  - service: light.turn_on
    data:
      brightness_pct: 95
    target:
      entity_id:
        - light.office_vent
        - light.small_bedroom_vent
        - light.basement_vent
mode: single

Turn on ventilation for an hour when certain air contaminant targets are attained

alias: HVAC CO2/pm25/iaq high, circulate FAN ventilation
description: When co2>800 or pm2.5>15 or IAQ>150 for 1 minute, turn fan on for 1 hour
trigger:
  - platform: numeric_state
    entity_id: sensor.aq_sensor_1_co2
    for:
      hours: 0
      minutes: 30
      seconds: 0
    above: 800
  - platform: numeric_state
    entity_id: sensor.aq_sensor_1_pm2_5
    for:
      hours: 0
      minutes: 1
      seconds: 0
    above: 15
  - platform: numeric_state
    entity_id: sensor.bme680_iaq
    for:
      hours: 0
      minutes: 1
      seconds: 0
    above: 150
condition:
  - condition: state
    entity_id: input_boolean.hvac_automations_enabled
    state: "on"
action:
  - service: climate.set_fan_mode
    target:
      device_id: 29e5f7aa36561d036ded2517f0d20916
    data:
      fan_mode: "on"
  - delay:
      hours: 1
      minutes: 0
      seconds: 0
      milliseconds: 0
  - service: climate.set_fan_mode
    data:
      fan_mode: auto
    target:
      device_id: 29e5f7aa36561d036ded2517f0d20916
mode: queued
max: 3

If you have a temperature sensor on the hot side of your plenum, you can implement a safety automation that disables all automations, opens the vents and sends a notification. In the case below, one to the app on my phone and a persistent one to the console. Note the design temperature for my furnace is 70C and that is where the safety limit would engage and turn off the furnace. I go 5C lower to give myself some wiggle room

alias: HVAC Outlet temp is above 65c, stop auto and vent
description: >-
  Open all vents when outlet temp is above 65c, design temp is 70c. Does this by
  switching helper and calling automation
trigger:
  - platform: numeric_state
    entity_id: sensor.hvac_air_hot
    above: 65
condition: []
action:
  - service: input_boolean.turn_off
    data: {}
    target:
      entity_id: input_boolean.hvac_automations_enabled
  - service: automation.trigger
    data:
      skip_condition: true
    target:
      entity_id: automation.hvac_master_automation_toggle
  - service: notify.mobile_app_sm_a326w
    data:
      message: HVAC High temperature, automations disabled, vents open
      title: HVAC High temp!
  - service: persistent_notification.create
    data:
      message: HVAC High temperature, automations disabled, vents open
      title: HVAC High temp!
mode: single

Finally, I recently noticed that when my thermostat was in smart recovery to hit the target temperature at the programmed time, the temperature passed to home assistant stayed the same and there was nothing in the attributes that was showing that it was in recovery.
If you don’t have a temperature sensor in the plenum like me, you can:

  • live with it
  • turn off smart recovery
  • add a temperature sensor and use the following automation.

The automation is far from perfect. I basically looked at the higher temperature my furnace (a 2 stage furnace) was hitting and used that as a trigger to open all the vents (indirectly by disabling all automations) and wait for for up to two hours for the supply temperature to go below 32C.

alias: HVAC thermostat in recovery
description: |-
  Open all vents when outlet temp is above 50c, stage 2 heat. Assume recovery. 
  wait up to two hours for vent to go back down 32c
trigger:
  - platform: numeric_state
    entity_id: sensor.hvac_air_hot
    above: 50
condition:
  - condition: state
    entity_id: input_boolean.hvac_automations_enabled
    state: "on"
action:
  - service: input_boolean.turn_off
    data: {}
    target:
      entity_id: input_boolean.hvac_automations_enabled
  - wait_for_trigger:
      - platform: numeric_state
        entity_id: sensor.hvac_air_hot
        below: 32
    timeout:
      hours: 2
      minutes: 0
      seconds: 0
      milliseconds: 0
  - service: input_boolean.turn_on
    data: {}
    target:
      entity_id: input_boolean.hvac_automations_enabled
mode: single

I’ve been looking for something like this for awhile. I was trying to implement it but I’m having a problem with the automation to set the generic thermostat target temps. I’m getting this error.

Error: Error rendering data template: UndefinedError: ‘dict object’ has no attribute ‘to_state’

This is as far as I have made it with the automation.

alias: HVAC Thermostat Room Set
description: ""
trigger:
  - platform: state
    entity_id:
      - climate.thermostat
    attribute: temperature
condition: []
action:
  - service: input_number.set_value
    data_template:
      entity_id: input_number.hvac_cool_target_temp
      value: "{{ trigger.to_state.attributes.temperature }}"
    alias: Update helper
mode: single

I’ve been trying to figure out how to offset the set point for a long time. I’ve never been able to get the math part to work. I tried yours and I get the same error as above.

Any ideas on what I’m doing wrong?

Hi. Sorry, I have been away for a while.
I can’t be sure but tris to replace the trigger attribute with the current thermostat temperature like below, assuming your thermostat is climate.thermostat

      value: "{{ state_attr('climate.thermostat','temperature') }}"

You can also check in the Developper Tools/template that the template renders correctly.