Home Automation on STEROIDS #2 (Home Assistant, AppDaemon, FloorPlan, Influx, Grafana, Powerwall)

Hi Everyone, please check out my home automation using Home Assistant and AppDaemon. It’s been a very fulfilling journey for me using HA, so thanks to all of you and the team at HA.

I would love your feedback and any suggestions and ideas you may have. Thanks for watching :slight_smile:

My Home Automation on Steroids Video Walkthrough on YouTube

My Home Assistant on Steroids Configuration on GitHub

3 Likes

How did you get Alexa to play the Jetson’s doorbell? I’ve been trying to figure that one out for a while.

That’s not Alexa, that the Aeotec Doorbell Gen5, i Just uploaded the mp3 file into it and configured the parameters so the default play is the Jetsons file …

1 Like

Great work, please consider sharing your app daemon files, especially the HVAC ones!

Terry

okay, I’ll create an AppDaemon app in HACS and update you soon :slight_smile:

import appdaemon.plugins.hass.hassapi as hass
import datetime

#
# HVAC Thermostat Controller App
#
# Args:
# hvac_living_room:
#   module: hvac_controller
#   class: HVACController
#   min_cool_temp: 67
#   max_heat_temp: 71
#   thermostat: climate.thermostat_living_room_mode
#   doors_windows:
#   alexa: media_player.living_room_alexa
#   air_cycle_minute: 3

class HVACController(hass.Hass):

  def initialize(self):
    self.thermostat = self.args["thermostat"]
    self.min_cool_temp = self.args["min_cool_temp"]
    self.max_heat_temp = self.args["max_heat_temp"]
    self.doors_windows = self.args["doors_windows"]
    self.alexa = self.args["alexa"]
    self.air_cycle_minute = int(self.args["air_cycle_minute"]) if "air_cycle_minute" in self.args else None
    self.air_cycling = False
    
    self.run_daily(self.turn_off_in_the_morning, datetime.time(8, 0, 0))
    self.listen_state(self.set_fan_mode_auto, self.thermostat, attribute = "fan_mode")
    self.listen_state(self.enforce_temp_limits, self.thermostat, attribute = "temperature")
    self.listen_state(self.enforce_temp_limits, self.thermostat, attribute = "target_temp_high")
    self.listen_state(self.enforce_temp_limits, self.thermostat, attribute = "target_temp_low")
    
    # if a door or window is open for 60 seconds then shut of thermostat
    if self.doors_windows:
      for door_window_sensor in self.doors_windows:
        self.listen_state(self.open_door_window_wait_for_shut_off, door_window_sensor, old = "off", new = "on", duration = 60)
        # TODO: Add the attribute = "state" in the above listen_state call as there is a bug right now
        # https://github.com/home-assistant/appdaemon/issues/185

    if self.air_cycle_minute is not None:
      now = datetime.datetime.now()
      next = now.replace(minute=self.air_cycle_minute, second=0)
      next = next + datetime.timedelta(hours=1) if now > next else next
      self.run_every(self.air_cycle, next, 60 * 30)
    
    #self.run_daily(self.decrease_heating_temp_after_midnight, datetime.time(2, 0, 0))
    #self.run_daily(self.decrease_heating_temp_after_midnight, datetime.time(3, 0, 0))
    #self.run_daily(self.increase_heating_temp_before_morning, datetime.time(4, 0, 0))
    #self.run_daily(self.increase_heating_temp_before_morning, datetime.time(5, 0, 0))


  def turn_off_in_the_morning(self, kwargs):
    self.log("MORNING_SHUT_OFF")
    self.call_service("climate/turn_off", entity_id = self.thermostat)


  def set_fan_mode_auto(self, entity, attribute, old, new, kwargs):
    
    if new != 'Auto Low' and self.air_cycling == False:
      self.log("FAN_MODE_AUTO")
      self.call_service("climate/set_fan_mode", entity_id = self.thermostat, fan_mode = 'Auto Low')
      self.call_service("notify/alexa_media", data = {"type":"tts", "method":"all"}, target = self.alexa, message = "Your attention please. AC fan mode has been set to auto.")


  def enforce_temp_limits(self, entity, attribute, old, new, kwargs):
    
    hvac_mode = self.get_state(self.thermostat)
    
    if hvac_mode is None:
      return
    
    if hvac_mode == 'heat':
      temp = self.get_state(self.thermostat, attribute = "temperature")
      if temp > self.max_heat_temp:
        self.log("ENFORCED_MAX_HEAT_TEMP_LIMIT")
        self.call_service("climate/set_temperature", entity_id = self.thermostat, temperature = self.max_heat_temp)
        self.call_service("notify/alexa_media", data = {"type":"tts", "method":"all"}, target = self.alexa, message = "Your attention please, the maximum heating temperature limit in this room is " + str(self.max_heat_temp))

    if hvac_mode == 'cool':
      temp = self.get_state(self.thermostat, attribute = "temperature")
      if temp < self.min_cool_temp:
        self.log("ENFORCED_MIN_COOL_TEMP_LIMIT")
        self.call_service("climate/set_temperature", entity_id = self.thermostat, temperature = self.min_cool_temp)
        self.call_service("notify/alexa_media", data = {"type":"tts", "method":"all"}, target = self.alexa, message = "Your attention please, the minimum cooling temperature limit in this room is " + str(self.min_cool_temp))

    if hvac_mode == 'heat_cool':
      temp_high = self.get_state(self.thermostat, attribute = "target_temp_high")
      temp_low = self.get_state(self.thermostat, attribute = "target_temp_low")
      
      if temp_low < self.min_cool_temp or self.max_heat_temp > temp_low or temp_high < self.min_cool_temp or self.max_heat_temp > temp_high:
        self.log("ENFORCED_AUTO_TEMP_LIMIT")
        self.call_service("climate/set_temperature", entity_id = self.thermostat, target_temp_high = self.max_heat_temp, target_temp_low = self.min_cool_temp)
        self.call_service("notify/alexa_media", data = {"type":"tts", "method":"all"}, target = self.alexa, message = "Your attention please, the temperature range limit in this room is " + str(self.min_cool_temp) + " to " + str(self.max_heat_temp))
    
    
  def open_door_window_wait_for_shut_off(self, entity, attribute, old, new, kwargs):
    operation_mode = self.get_state(self.thermostat)
    if operation_mode != 'off':
      self.log("DOOR_WINDOW_SHUT_OFF")
      self.call_service("climate/turn_off", entity_id = self.thermostat)
      self.call_service("notify/alexa_media", data = {"type":"tts", "method":"all"}, target = self.alexa, message = "Your attention please, this room's door or window has been open since the past 60 seconds. I've turned off the air conditioning.")


  def air_cycle(self, kwargs):
    self.log("AIR_CYCLE_ON")
    self.air_cycling = True
    self.call_service("climate/set_fan_mode", entity_id = self.thermostat, fan_mode = 'On Low')
    self.run_in(self.air_cycle_off, 75)


  def air_cycle_off(self, kwargs):
    self.log("AIR_CYCLE_OFF")
    self.call_service("climate/set_fan_mode", entity_id = self.thermostat, fan_mode = 'Auto Low')
    self.air_cycling = False


#  def decrease_heating_temp_after_midnight(self, kwargs):
#    temp = self.get_state(self.thermostat_heating, attribute = "temperature")
#    new_temp = temp - 1
#    self.call_service("climate/set_temperature", entity_id = self.thermostat_heating, temperature = new_temp)
#    self.log("AUTO_DECREASE_TEMP") 
  
  
#  def increase_heating_temp_before_morning(self, kwargs):
#    temp = self.get_state(self.thermostat_heating, attribute = "temperature")
#    new_temp = temp + 1
#    self.call_service("climate/set_temperature", entity_id = self.thermostat_heating, temperature = new_temp)
#    self.log("AUTO_INCREASE_TEMP")

I apologize I havent been able to get to posting my config on github, but above is the HVAC code for appdaemon :slight_smile:

my entire home assistant configuration. I hope this helps you. If you like what you see, please consider starring the repo :star2: :. It would be very encouraging :slight_smile: