Last active
January 6, 2021 15:27
-
-
Save derglow/67fa00282f9963d07ca29ece98e12bd9 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#substitutions is a list of variables basically. here you can easily change the high/low limits and setpoints | |
substitutions: | |
temperature_setpoint: '25.5' | |
temperature_alarm_low: '23.3' | |
temperature_alarm_high: '27.5' | |
temperature_hysteresis: '0.3' | |
esphome: | |
name: reefbrain | |
platform: ESP32 | |
board: nodemcu-32s | |
on_boot: | |
priority: -10 | |
# ... | |
then: | |
#on boot we turn the thermostat on ("HEAT" mode in my case) and set the desired setpoint | |
- climate.control: | |
id: reef_temp_control | |
mode: HEAT | |
target_temperature: ${temperature_setpoint} | |
#This script begins the monitor that makes sure we receive a new temperature measurement at least every 2 minutes | |
#If this script isn't called every 2 minutes it will start the high temperature alarm | |
#Everytime we call the script the timer resets. I call this the temperature "heartbeat" | |
- script.execute: temperature_heartbeat | |
wifi: | |
ssid: "Wifi" | |
password: "Wifi_Password" | |
# Enable fallback hotspot (captive portal) in case wifi connection fails | |
ap: | |
ssid: "Reefbrain Fallback Hotspot" | |
password: "MRF8tFN7ooul" | |
#use_address: 192.168.1.20 | |
#You can delete the manual IP config if you want IP address to be assigned automatically | |
manual_ip: | |
static_ip: 192.168.1.41 | |
gateway: 192.168.1.1 | |
subnet: 255.255.255.0 | |
captive_portal: | |
# Enable logging | |
logger: | |
# Enable Home Assistant API | |
api: | |
#I highly recommend passwords! It will prevent you from sending the wrong firmware to the wrong device. | |
ota: | |
password: reefbrain | |
dallas: | |
#Temperature sensors | |
- pin: GPIO32 | |
update_interval: 15s | |
sensor: | |
#Temperature Sensor 1 | |
- platform: dallas | |
address: 0xB1031297794BF628 | |
id: reef_temp_1 | |
name: "Reef Temperature 1" | |
filters: | |
#I manually calibrated my temperature sensors and figured out this offset | |
- offset: 1.14 | |
- filter_out: nan | |
- sliding_window_moving_average: | |
window_size: 4 | |
send_every: 4 | |
#the next section triggers alarms and the temperature heartbeat | |
#every time a valid value is received (anything besides NaN) this section is called | |
on_value: | |
then: | |
- if: #if temperature is in range, go ahead and reset the temperature heartbeat timer | |
condition: | |
sensor.in_range: | |
id: reef_temp_1 | |
above: ${temperature_alarm_low} | |
below: ${temperature_alarm_high} | |
then: | |
- script.execute: temperature_heartbeat | |
- if: #if temperature is below the low limit then trigger the low alarm | |
condition: | |
sensor.in_range: | |
id: reef_temp_1 | |
below: ${temperature_alarm_low} | |
then: | |
- switch.turn_on: alarm_temperature_low | |
- if: #if temperature is above the high limit then trigger the high alarm | |
condition: | |
sensor.in_range: | |
id: reef_temp_1 | |
above: ${temperature_alarm_high} | |
then: | |
- switch.turn_on: alarm_temperature_high | |
#Temperature Sensor 2 | |
- platform: dallas | |
address: 0x86031497798E6228 | |
id: reef_temp_2 | |
name: "Reef Temperature 2" | |
filters: | |
#I manually calibrated my temperature sensors and figured out this offset | |
- offset: 2.04 | |
- filter_out: nan | |
- sliding_window_moving_average: | |
window_size: 4 | |
send_every: 4 | |
#for the second (redundant) temperature sensor I only monitor for the high temperature alarm | |
on_value: | |
then: | |
- if: | |
condition: | |
sensor.in_range: | |
id: reef_temp_2 | |
above: ${temperature_alarm_high} | |
then: | |
- switch.turn_on: alarm_temperature_high | |
switch: | |
#Heater SSR | |
- platform: gpio | |
id: heater_ssr | |
pin: GPIO0 | |
#I made this internal because the user shouldn't manually manipulate the heater - just the thermostat controller and alarms | |
internal: true | |
name: "Heater SSR" | |
#Making the alarms switches means the microcontroller can trigger the switch on and do the appropriate behavior while | |
#the user can easily turn it off via Home Assistant | |
#High Temperature Alarm | |
- platform: template | |
name: "High Temperature Alarm" | |
id: alarm_temperature_high | |
#if you don't set optimistic to true then the switch automatically turns itself off | |
optimistic: true | |
on_turn_on: | |
- logger.log: "High Temperature Alarm Turned On!" | |
#change climate control mode to "OFF" | |
- climate.control: | |
id: reef_temp_control | |
mode: "OFF" | |
#not sure if this is 100% necessary but just to be safe turn off the SSR | |
- switch.turn_off: heater_ssr | |
#this while loop runs for as long as the alarm is left on. | |
#once the user turns the alarm switch off it will exit the while loop | |
- while: | |
condition: | |
switch.is_on: alarm_temperature_high | |
then: | |
- logger.log: "High Temperature Alarm Still On!" | |
- script.execute: triple_siren_short | |
- delay: 90s | |
#once the user turns the alarm off we turn the thermostat controller back on i.e. "HEAT" | |
#the siren script just gives a nice audible feedback that the alarm has been acknowledged/shut off | |
on_turn_off: | |
- logger.log: "High Temperature Alarm Turned Off!" | |
- script.execute: single_siren_short | |
- climate.control: | |
id: reef_temp_control | |
mode: "HEAT" | |
#Low Temperature Alarm | |
#This alarm doesn't stop the thermostat, it just sets off a siren. | |
#One state you might run into is when the system is starting up you may be significantly below the low alarm | |
#In that case you still want the thermostat to control, so we don't turn off the thermostat here. | |
#For now this has to be acknowledged before turning off (rather than automatically turning off when in range) | |
- platform: template | |
name: "Low Temperature Alarm" | |
id: alarm_temperature_low | |
optimistic: true | |
on_turn_on: | |
- logger.log: "Low Temperature Alarm Turned On!" | |
- while: | |
condition: | |
switch.is_on: alarm_temperature_low | |
then: | |
- logger.log: "Low Temperature Alarm Still On!" | |
- script.execute: triple_siren_short | |
- delay: 90s | |
on_turn_off: | |
- logger.log: "Low Temperature Alarm Turned Off!" | |
- script.execute: single_siren_short | |
#Siren Output | |
- platform: gpio | |
pin: GPIO15 | |
id: siren | |
name: "Siren" | |
#I made this internal because there's no real usefulness in the user turning it on/off | |
#The alarms and scripts manage turning it on/off. | |
internal: true | |
climate: | |
- platform: thermostat | |
id: reef_temp_control | |
#Note that here the same temperature sensor that has all of the alarms configured is used to control the thermostat | |
sensor: reef_temp_1 | |
default_target_temperature_low: ${temperature_setpoint} | |
hysteresis: ${temperature_hysteresis} | |
heat_action: | |
- switch.turn_on: heater_ssr | |
idle_action: | |
- switch.turn_off: heater_ssr | |
script: | |
#the single siren is useful as an acknowledge noise. just one simple chirp | |
#the scirpt mode has to be queued or else you can't use it properly in the next script | |
- id: single_siren_short | |
mode: queued | |
then: | |
- switch.turn_on: siren | |
- delay: 50ms | |
- switch.turn_off: siren | |
- delay: 50ms | |
#the triple chirp is used as the alarm and always implies something is wrong | |
- id: triple_siren_short | |
then: | |
- script.execute: single_siren_short | |
- script.execute: single_siren_short | |
- script.execute: single_siren_short | |
#this script monitors the frequency that we receive new temperature measurements | |
#if a temperature sensor fails we don't want the thermostat to be stuck high and cook the aquarium | |
#so the "heartbeat" idea is is that we want a consistent flow of incoming temperature measurements | |
#if not we should safely shut down and turn on an alarm. | |
#this script is basically always running. everytime we execute the script is restarts. | |
#but if we go 2 minutes without restarting it then it will successfully complete and turn on the high alarm | |
#so everytime the sensor reads a value it will restart this timer. | |
- id: temperature_heartbeat | |
mode: restart | |
then: | |
- delay: 2 min | |
- switch.turn_on: alarm_temperature_high | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment