Reliable heating schedule using input boolean occupancy detection.
objective:
Home assistant automation to control a Millivolt (mV) thermostat controlled gas or wood pellet heater. having a setback schedule with variable temperatures depending on time of day and occupancy of home. Able to manually override, view and be notified of unwanted conditions when away from home. voice commands through Google home.
Advantages of using Shedy for me.:
Always works and does not turn off thermostat on card after a HA restart.
Instant changes and constantly polls state of temperature, times, days, input selects and boolean changes.
Unlike I have noticed with standard Front end automatons that only trigger at the exact time a state topic changes to a set value. Then it will only make any changes when it reaches the min or max temperature readings.
Has rescheduling_delay:
so if for some reason someone wanted to turn up or down the temperature on the thermostat card or turn on the relay in lovelace or with a voice command that setting will stay for your set amount of time set in SCHEDY and then automatically go back to scheduled mode.
Devices: (currently used)
- Shelly1 relay.
- Xiaomi zigbee temperature temperature/ humidity Sensor (integrated with Combee II and deconz)
Home assistant setup:
- Home assistant hassIO on a PI4/SD card.
- Home Assistant Cloud
- Add-ons: AppDaemon 4
- hass-app Schedy
- liffe360
- home assistant android app for presence detection and remote access.
Set up Temperature sensors of your choice integrated into home assistants you can link into automations.
Set up device relay
Shelly1 relay is a very versatile wifi relay that can be powered with AC or DC.
The OUTPUT connections are DRYcontact (open and closed switch loop) and voltage is isolated from the relay power so it can be use with high voltage or millivolt.
This box was from my original setup with a sonoff low volt relay so its a little ugly.
I set this up with a 3 position switch so the gas appliance could be in Home assistant mode / manually tuned on or turned off. (the gas stove works without power so it’s handy to have a switch for power outages.)
Power the shelly1 with your desired voltage AC or DC. to L and N connections.
(see link for instructions how to integrate to HA and wire a shelly1.)Shelly-1-x2 - The smallest Wi-Fi-operated relay switch.
At this time im using 120v ac
You can use a sonoff 5v dry contact relay also.
here is a photo of the old style 5v self locking relay from sonoff i connected to a pellet stove thermostat connections. I printed a box that can be found on thingaverse
here is a link to the old style with connections no soldering needed but a little harder to flash to tazmota. can be found for about 3$ on other sites.
older DC 5V Sonoff Wifi Switch Module Inching Self Locking Wireless Relay Switch Smart
here is a link to the new style sonoff relay. some soldering needed
new style sonoff 5v dry contact relay.
Making your own wifi relay board and thermostat is cheep and easy with esphome
I got my feet wet with Esphome.
and a ultrasonic pellet level sensor.
Updated the pellet stove Using a d1 mini, relay sheild for thermostat, and a ultrasonic sensor for pellet level. Write up here
Device connection to 750MV gas valve:
connection of wires to TH and TH\TP
To Shelly1 each wires to the I and 0 connection of the shelly1 polarity does not matter its just a switch that will connect the two connections together when the relay is closed.
You can edit, create, download and upload files with HA File editor or on remotely using samba share or your desired method of dealing with files to HA…
The following is added into my configuration.yaml file
climate: !include climate.yaml
(skip the YAML below if you use HA configuration helpers in front end)
/config/configuration.yaml
input_select: !include input_select.yaml
input_boolean: !include input_boolean.yaml
To have a thermostat card in Lovelace
Create or edit a climate.yaml file in /config folder with the following:
name anything you want your thermostat card called.
heater is the HA entity ID name of the Relay connected to the appliance running in HA.
the below temperature setting will not be used but will be a fall back if AppDaemon or python has a failure. (had some short term failures during Daylight savings and leap year.)
target_sensor the HA entity ID of your desired temperature sensor running in HA.
you may want to adjust the HOT and COLD tolerance for a swing so heater will not cycle off and off quickly. here is more info on generic thermostat HA generic thermostat
/config/climate.yaml
- platform: generic_thermostat
name: Kozy Heat
heater: switch.factory_shelly2_mqtt_1
target_sensor: sensor.temperature_5_living_temp #zigbee
min_temp: 50.0
max_temp: 90.0
ac_mode: False
target_temp: 70.0
cold_tolerance: 0.0
hot_tolerance: 0.0
initial_hvac_mode: "off"
away_temp: 55
If you have more heaters set up just duplicate and set IDs to relays and sensors.
Heating Mode:
This gives you a input select to turn heating mode to set the target temperature and ignoring the scheduled temperature if you are home at an unusual time or vacation when the schedule would normally be at idle (schedule_append:)
You can now make input selects and input booleans with configuration/HELPERS on the front end of HA without making yaml entries.
(skip the YAML below if you use HA configuration helpers in front end)
/config/input_select.yaml
heating_mode:
name: Heating Mode
options:
- Normal
- Home early
input_boolean.nothome:
To have a presence/occupancy automation to a input boolean that will set your thermostat to a desired energy savings temperature when house is not occupied. My setting is 50F in the winter.
You will need to set up your own automation to set the input_ boolean. On or off
Create or edit a input_boolean.yaml file in /config folder with the following:
(skip the YAML below if you use HA configuration helpers in front end)
/config/input_boolean.yaml
nothome:
name: nobody is home
initial: off
icon: mdi:home-thermometer-outline
Appdaemon Setup:
Install and setup Appdaemon from the Home Assistant Community Add-ons
in HA as per add-on instructions. Here is my Appdaemon Config for the add-on:
Appdaemon 4 Add-on config
*only thing really need to be sure to add the -hass_apps in the Appdaemon 4 config as shown below.
system_packages: []
python_packages:
- hass-apps
init_commands: []
After appdeamon is installed it will create a file
/config/appdaemon/appdaemon.yaml
Edit the /config/appdaemon/appdaemon.yaml with your info.
IE change to your lat and lon, your time zone, and URL of HA and port 5050 at the end.
/config/appdaemon/appdaemon.yaml
---
secrets: /config/secrets.yaml
appdaemon:
latitude: 37.314417
longitude: -119.658383
elevation: 2800
time_zone: America/Los_Angeles
plugins:
HASS:
type: hass
http:
url: http://192.168.86.47:5050
admin:
api:
hadashboard:
Hass-Apps Schedy Setup:
install and setup the basic hass-apps Schedy ADD_ON (Schedy — hass-apps 0.20200319.0 documentation 35)
This is the part that really tripped me up because the references to docker install and HASSIO install are mixed in.
It’s not as difficult/complicated as the wording in the doc sound because you are not really installing anything just setting up/uploading A .py file. so read the instructions all the way through and ignore the parts about manual docker install unless you are using docker.
On this page is what confused me Getting Started — hass-apps 0.20200319.0 documentation
What was needed was to just make sure FIRST that I had the config info I have above in the Appdaemon Setup config in this format.
It did not work when I tried it with the format on the getting started link above.
This is what worked for me:
system_packages: []
python_packages:
- hass-apps
init_commands: []
If you are using hassIO have appdaemon running and not manually configuring docker your next step is this.
https://hass-apps.readthedocs.io/en/stable/getting-started.html#getting-started-configuration
Im not a expert at this stuff so the way they wrote it and linked to the .py file confused me on what to store or do.
“Store the file hass_apps_loader.py in your AppDaemon’s apps directory. This is just a stub which imports the real app’s code.”
Hmmm???
**All you need to do is create a file **
Hass_apps_loader.py
In HA like this
/config/appdaemon/apps/hass_apps_loader.py
In that file paste in this and save.
/config/appdaemon/apps/hass_apps_loader.py
# This is just a stub which makes the app classes available for AppDaemon.
from hass_apps.loader import *
**Check config and **
Restart your home assistant.
Adding controls to Lovelace.Lovelace
At this time go ahead and make a Climate control tab or just add your thermostat card to any tab on lovelace.
Where the Magic happens your custom Heating schedule:
In the appdaemon folder update the hass-apps file created during setup.
I created a new one called schedy_heating.yaml in this directory.
/config/appdaemon/apps/schedy_heating.yaml
schedy_heating: # This is our app instance name.
module: hass_apps_loader
class: SchedyApp
actor_type: thermostat
expression_environment: |
def heating_mode():
return state("input_select.heating_mode")
watched_entities:
- input_select.heating_mode
- input_boolean.nothome
schedule_append:
- v: "66"
rooms:
living:
rescheduling_delay: 15
actors:
climate.kozy_heat:
schedule:
- x: "50 if is_on('input_boolean.nothome') else Next()"
- v: 70
rules:
- weekdays: 1-5
rules:
- rules:
- x: "Next() if heating_mode() == 'Normal' else Break()"
- { start: "06:30", end: "07:30" }
- { start: "18:00", end: "22:30" }
- rules:
- x: "Next() if heating_mode() != 'Normal' else Break()"
- { start: "06:00", end: "23:00" }
- weekdays: 6-7
rules:
- { start: "07:00", end: "23:00" }
#
#
A little explanation of what settings in script.
**return state("input_select.heating_mode")**
this is the input select if you want heater to run at Scheduled or Scheduled_apend heat setting when home at an unusual time or day.
If input is set to Normal it will run schedule as usual.
If input is Home early if will set temperature to your . - v: 70 set in the schedule below (comfort zone)
watched_entities:
- input_select.heating_mode
- input_boolean.nothome
this is the entity that is always checked and will change schedule according to value.
schedule_append:
** - v: “63”**
#this is the temperature that will be set when NO scheduled rules are in effect. Your idle mode as I say.
rooms:
if you have several heaters and rooms you can add different rooms. Im only doing one.
living:
**rescheduling_delay: 15**
this is the delay that schedy will let a manual override run for if you change setting in lovelace or voice control. It will resume schedule after your set time.
**actors:**
** climate.kozy_heat:**
this is /config/climate.yaml and your thermostat card in lovelace.
The name is the name: you gave in the Climate.yaml file Mine was kozy heat.
input it in the script with underscore between two words.
**schedule:**
- x: "**50** if is_on('input_boolean.nothome') else Next()"
**schedule:**
- x: "50 if is_on('input_boolean.nothome') else Next()"
- v: 70
the 50 is the temp I want set when house is not occupied and input_boolean.nothome is ON.
this 70 value is the temperature I want when the below schedules are in effect our Kozy and warm time netflix and chill. Then set to a lower schedule append time at bedtime.
rules:
**- weekdays: 1-5**
rules:
- rules:
- x: "Next() if heating_mode() == 'Normal' else Break()"
- { start: "**06:30", end: "07:30**" }
- { start: "**18:00", end: "22:30**" }
the two times above are the times we want the house to be at the set value of 70 above
All other times on the days set will be the schedule_append: - v: "63"
unless the input_select.heating_mode is set to home then it will set to our Rule of 70 or input_boolean.nothome is set to on and it will be set 50.
- rules:
- x: "Next() if heating_mode() != 'Normal' else Break()"
- { start: "06:00", end: "23:00" }
**- weekdays: 6-7**
rules:
- { start: "07:00", end: "23:00" }
This is the same but our weekend not at school or work rules. They have the same effect as the first rule with inputs.
My Lovelace for climate control .
thermostat card (actor)
another setup in another home. with a relay on a Evaporative cooler and a low volt relay on a pellet stove.
my Video of how it all works on my page
Facebook video
Updated 1/15/2003
Here is my App(s) for our main home.
I have done a lot of HA automation in another home since I posted this topic.
We have a Pellet stove for our main heat. Evaporative cooler for our Main cooling and a whole house HVAC heating and cooling. so I have 3 Scheady heating Apps to schedule our heating and cooling needs.
Pellet stove schedule and rules.
schedy_heating: # This is our app instance name.
module: hass_apps_loader
class: SchedyApp
actor_type: thermostat
expression_environment: |
def heating_mode():
return state("input_select.heating_mode")
watched_entities:
- input_select.heating_mode
# - input_boolean.nothome
- input_boolean.heat_boost
- input_boolean.occupied
- input_boolean.party_climate
- input_boolean.heater
- input_boolean.heat_boost_pellet
schedule_append:
- v: "65" #the temperature if none of the rules in schedule below are active.
rooms:
living:
rescheduling_delay: 40 # the time every thing will go back to schedule if someone changes heating settings.
actors:
climate.heat:
schedule:
#######################################################################################
# this line breaks the house not occupied rule for a morning to pre heat house
# after not being home for days.
# - { x: "Break()", weekdays: "5", start: "06:00", end: "07:00" }
#####################################################################################
- x: "63 if is_off('input_boolean.occupied') else Next()" # sets to 63deg if no one home
- x: "69 if is_on('input_boolean.party_climate') else Next()" # sets to 69deg if we have lots of guest
- x: "74 if is_on('input_boolean.heat_boost_pellet') else Next()" # sets to 74deg if boost automation or manually set to boost.
- v: 74 #the temperature if everything fall into below schedule.
rules:
- weekdays: 1-7
rules:
- rules:
- x: "Next() if heating_mode() == 'Normal' else Break()"
- { start: "06:30", end: "22:30" }
- rules:
- x: "Next() if heating_mode() != 'Normal' else Break()"
- { start: "06:00", end: "22:30" }
# - { start: "18:00", end: "22:30" }
# - weekdays: 6-7
# rules:
# - { start: "07:30", end: "23:00" }
Whole house HVAC only used when sleeping and for a heat boost to get house warm in morning or activating boost with voice assist or button.
schedy_furnace_heating: # This is our app instance name.
module: hass_apps_loader
class: SchedyApp
actor_type: thermostat
expression_environment: |
def heating_mode():
return state("input_select.heating_mode")
watched_entities:
- input_select.heating_mode
# - input_boolean.nothome
- input_boolean.occupied
- input_boolean.party_climate
# - input_boolea.heater
- input_boolean.heat_boost
schedule_append:
- v: "off"
rooms:
Whole_house:
rescheduling_delay: 15
actors:
climate.house_a_c:
schedule:
#######################################################################################
# this line breaks the house not occupied rule for a morning to pre heat house
# after not being home for days.
# - { x: "Break()", weekdays: "5", start: "06:00", end: "07:00" }
#####################################################################################
- x: "74 if is_on('input_boolean.heat_boost') else Next()"
- x: "off if is_off('input_boolean.occupied') else Next()"
- x: "65 if is_on('input_boolean.party_climate') else Next()"
- v: 67
rules:
- weekdays: 1-7
rules:
- rules:
- x: "Next() if heating_mode() == 'Normal' else Break()"
- { start: "06:45", end: "07:15", v: 74 }
- { start: "23:00", end: "06:45" }
#- { start: "00:00", end: "06:30" }
- rules:
- x: "Next() if heating_mode() != 'Normal' else Break()"
- { start: "23:00", end: "06:30" }
# - { start: "18:00", end: "22:30" }
# - weekdays: 6-7
# rules:
# - { start: "06:30", end: "22:35" }
Evaporative cooler has rules to shut off if HVAC is active.
schedy_cooling: # This is our app instance name.
module: hass_apps_loader
class: SchedyApp
actor_type: thermostat
hvac_mode_on: cool
expression_environment: |
def cooling_mode():
return state("input_select.heating_mode")
def tv_mode():
return state("input_select.tv_mode")
watched_entities:
- input_select.heating_mode
- input_boolean.a_c_on
- input_boolean.party_climate
# - input_boolean.occupied
schedule_append:
- v: "81"
rooms:
living:
rescheduling_delay: 40
actors:
climate.cooler:
hvac_mode_on: cool
schedule:
- x: "off if is_on('input_boolean.a_c_on') else Next()"
# - x: "88 if is_off('input_boolean.occupied') else Next()"
- x: "88 if is_on('input_boolean.party_climate') else Next()"
- v: 75
rules:
- weekdays: 1-7
rules:
- rules:
- x: "Next() if cooling_mode() == 'Normal' else Break()"
- { start: "9:00", end: "18:00" }
- { start: "18:00", end: "19:00", v: 78 }
- { start: "19:00", end: "23:00", v: 77 }
# - { start: "18:30", end: "23:00", v: 79 }
# - x: "Next() if cooling_mode() == 'Normal' else Break()"
# # - x: "Next() if tv_mode() == 'TV time' else Break()"
# - { start: "9:00", end: "18:30" }
# # - { start: "9:00", end: "18:30", v: 78 }
# - { start: "18:30", end: "23:00", v: 80 }
# - rules:
# - x: "Next() if tv_mode() != 'TV time' else Break()"
# - { start: "09:00", end: "21:00", v: 90}
# - weekdays: 1-7
# rules:
# - { start: "09:00", end: "23:00", v: 90 }
You can see another example of what I did but with more rooms and heaters here.
Matthewjporter is the one who helped me out and pointed me to the right direction to get the automation I wanted. Thanks Matthew.
My background. I have been using sonoff devices and ewelink with IFTTT for about 3 years to automate my home and heating and evaporative cooler. I made the jump to HA and I have been playing with Home assistant for about 6 months now. I’m enjoying playing with WLED I made a automatic fish feeder also.
Over 30 years I have been installing and servicing Hearth products specializing in Gas and wood pellet burning stoves.
Home automation is a hobby I needed.
my Facebook page diyredneck.thestovedoc.com