[AppDaemon] Control Thermostat via Slider!

Hi all!

I sat back down to convert a lot of my automations to AppDaemon. I really like sliders, I think they are a neat UI element that can help simplify and elevate your cards/views for the average user that might be unfamiliar with your setup. At the end of the day, I like the build things that are both practical and intuitive.

Code below, but also can be found here, if you prefer to see the syntax highlighted.

import appdaemon.appapi as appapi

class SliderTemperature(appapi.AppDaemon):

    def initialize(self):
        current_temp = int(self.get_state('climate.hallway_hallway', attribute='current_temperature'))
        self.call_service('input_slider/select_value', 
                          entity_id='input_slider.target_temp', value=current_temp)
        
        self.listen_state(self.adjust_temperature, 'input_slider.target_temp')

    def adjust_temperature(self, entity, attribute, old, new, kwargs):
        operation_mode = self.get_state('climate.hallway_hallway')
        current_temp = self.get_state('climate.hallway_hallway', attribute='current_temperature')
 
        # Nest thermo has 4 modes: heat, cool, auto (range), and eco (away)
        if operation_mode == 'auto':
            current_temp, new = int(float(current_temp)), int(float(new))

            if current_temp < new:
                lower, upper = new, new+3
            else:
                lower, upper = new-3, new

            self.call_service('climate/set_temperature',
                              target_temp_low=lower,
                              target_temp_high=upper)
        elif operation_mode == 'eco':
            self.error('Setting the temperature is not allowed when no one is home!')
        else:
            self.call_service('climate/set_temperature',
                              temperature=int(new))

Most of this should be pretty self-explanatory, but let’s go over it briefly anyway! I like to group my settings of objects with the code that they will be affecting, so instead of having a general startup file that sets a bunch of “defaults” on the UI elements and variables, I put them in the AppDaemon app’s initialize function.

We start off by setting the value of the slider to the current_temp and then setting a state listener to keep tabs on the target_temp slider. Since we want to adjust the temperature every time the slider is changed, we aptly name our callback function adjust_temperature. Remember people, Python should be beautiful!

On line 13 and 14, you’ll see we set two variables to grab out operation_mode and current_temp. The thermostat I am using, Nest, has 4 different modes to it, and so we’ll want to account for all of these in our code to cover all different scenarios. Since the slider leaves us with a final or new value, operation_mode == heat and operation_mode == cool are effectively the same type of mode. We receive input, and set the temperature to that input. You’ll find that that code is very simple to write, and is lines 31 and 32. When we are in operation_mode == eco, we don’t, or more accurately can’t set the temperature, so we’ll raise an error and do nothing else.

The difficult part comes into play when we have operation_mode == auto, or the thermostat is told to stay within a specific range. Nest requires the temperature setting to stay at least 3° apart from each other. The input_slider can only specify one value, and until it can have two controls on it, we’ll have to jimmy-rig this automation up.

To solve this problem, I first asked myself “when will I manually change the thermostat?” and to that I simply answered “when I’m too cold, and want to turn the heat on”. So from this interaction, we know two bits of information.

  • The current temperature --> “It’s too cold”
  • The target temperature direction --> “I want to turn the heat on”

So someone will go to turn the slider up past the current temperature. Then we want the lowest temperature to be that slider value, and the highest temperature to be at least 3 higher than the slider value. The converse can be said about the opposite situation – and this is exactly what we are doing in lines 20 - 23. The rest is simply calling the climate/set_temperature service to do what we want, and you’ve got your automation!

This automation is still pretty simple, but I found myself wanting to change the temperature quickly from my dashboard without a way to do it. I’m positive this code can be used as a base for other thermostats as well, feel free to comment below and I’ll do my best to help. More to come!

Thanks for reading,
SupahNoob

4 Likes

i think i see a problem.

if your operation-mode is set to eco and your slider is moved you only get an error.
the user doesnt get anything in respons but sees that the slider is changed.
if after that the operation mode is set to cool or heat, the slider doesnt respresent any usefull value.
so i think that the slider should be set back to old value after the error.

unless off course the slider doesnt represent a target temp.
but then again you set your slider to the actual temp, but only when hass or appdaemon are restarted?

edit: misread the part about automode.

edit2: if i was a user and i set the slider from 50 to 60 degrees i would 60 degrees the maximum or the center, but not the bottom.
so i would set the lines to:

            if current_temp < new:
                lower, upper = new-3, new
            else:
                lower, upper = new, new+3

or

            lower, upper = new - 1.5, new+1.5

Rene – you’re correct and you’re incorrect! My uses cases are fairly specific.

  • Eco Mode only results in an error

I currently have the luxury of living by myself. Eco Mode is only set when I am out of the house and do not currently have a guest at home. There is not an instance where I’d like to set the mode to Eco, but also have the temperature at a specific instance. This will change in the future, I’m sure. I did want to have the operation_mode == 'eco' accounted for in some way, however. It would make more sense to have the user see some sort of feedback, either tts or notify.

  • Slider does not represent a useful value

Unfortunately, you’re correct here. When initalize'd, the program sets it to the current value. Since updating the value of the slider would cause it to change (and subsequently, for an automation to trigger), I was afraid of an infinite loop occurring, or a frustrating user experience. Since sliders don’t show their current value UNTIL you go to move/select them, I am happy with the implementation. The user has feedback of current values right below the slider however, so I am not worried.

Great questions comments though! It shows how you should think through many possible scenarios when going to code up a new automation. :slight_smile:

see my second edit :wink:

the looping can be prevented by implementing an inputboolean
set it to on before you change the slider and to off after you have changed it.
in the callback check if the boolean is on, then dont activate the code.

edit2: if i was a user and i set the slider from 50 to 60 degrees i would 60 degrees the maximum or the center, but not the bottom.

What happens when the current temperature is 59, and you set the temp to 60? Low would be 58.5, high would be 60.5 and the heather would not kick on! This is not the desired outcome. We are cold, and want the heat on!

the looping can be prevented by implementing an inputboolean

Simply put, so-called flag variables are messy and I hate them. :slight_smile: This is one way to achieve the effect though. “There has to be a better way!”

if you are cold and you know that you set a range (and not a specific point) you wouldnt change it only for 1 degree.
in that case you should tell the users to change at least 2 degrees.
but i must say that i wouldnt want a heating mode which 3 degrees range :wink:

i would use the cool or heat mode only and create an thermostat in appdaemon itself with a range from 0.5 above or below the slider.

i dont like flagvars myself. but i dont see a better way. it isnt possible to change an entity in hass on which you have a listen state without it triggering the callback.

by the way, even better is it to make your automations so that the users dont have a need to change the heating at all :wink:
mine are adjusted a few times every day according to who is where and the time off day and sort of location, all automaticly. :slight_smile:

so if we arent home it is set lower, if it is evening it is set higher, the bedroom only heats around the time we go to bed, the kitchen is heated more around cooking time, etc.

How can i add slider for control temperature.

climate:
  - platform: generic_thermostat
    name: Living_room
    heater: switch.neo_coolcam_power_plug_12a_switch
    target_sensor: sensor.fibaro_system_fgms001_motion_sensor_temperature
    min_temp: 21
    max_temp: 28
    target_temp: 24
    tolerance: 0.3
    min_cycle_duration:
      seconds: 5
    keep_alive:
      minutes: 3

like SN did.
by creating a slider in HA and use appdaemon.

but then you cant use the generic thermostat.

which component can i use for temrature ? Can u please help me.

what do you mean?

you have a temperature sensor and a switch to turn on your heating device.
you turned that into a generic thermostat, so you can set the temp, or not?

with the app you can do the same with those 2 enities. and a slider.

do u mean i must install appdaemon on HA for use slider.

only if you want to use an app that uses a slider.

but doesnt your generic thermostat have a slider?

no i am not using app, just use internet browser to control my switches.

sorry, i dont think i am able to help you.
probably my english is to bad, to be able to communicate with you.

I know what you mean, anyway thanks for helpâ˜ș