How to make sure climate call services are completed?

This is my current script, and i realized today that for some reason the set_temperature call service doesn’t change my hvac_mode which is really weird. Therefore, i created a follow up call service for set_hvac_mode to make sure it changes it. The good morning temp is triggered when an input boolean is turned off, and i just noticed that i have to toggle the sensor about 4 times for it to set the 2 thermostats to the right temp (73) and the right mode (heat).
I have z wave thermostats and that may be why they are slow. What can i add in my python script to fix this?

I know i am not suppose to put a wait, so wondering what can i do to send a call service one at a time to make sure home assistant reacts to them all and doesn’t skip one.

import appdaemon.plugins.hass.hassapi as hass

class Climate(hass.Hass):

    def initialize(self):
        
        # Morning
        self.listen_state(self.home, "input_boolean.sleep_mode", new="off")
        
        # Arriving home
        self.listen_state(self.home, "alarm_control_panel.ring_alarm", old="armed_away", new="disarmed")
        
        # Night
#        self.listen_state(self.night, "input_boolean.sleep_mode", new="on")
        
        # Away
#        self.listen_state(self.away, "binary_sensor.house_occupied", new="off")

    def home(self, entity, attribute, old, new, kwargs):
        #todays_high = float(self.get_state("sensor.dark_sky_daytime_high_apparent_temperature_0d"))
        todays_high = float(self.get_state("sensor.nws_temperature_high_today"))

        if todays_high >= 80:
            # set thermostat to 72 cool
            self.log("Setting thermostat to 72 cool")
            # Upstairs thermostat
            self.call_service("climate/set_temperature", entity_id = "climate.trane_corporation_model_tcont624as42daa_mode_2", temperature = 72)
            self.call_service("climate/set_hvac_mode", entity_id = "climate.trane_corporation_model_tcont624as42daa_mode_2", hvac_mode = "cool")
            # Downstairs thermostat
            self.call_service("climate/set_temperature", entity_id = "climate.trane_corporation_model_tcont624as42daa_mode", temperature = 72)
            self.call_service("climate/set_hvac_mode", entity_id = "climate.trane_corporation_model_tcont624as42daa_mode", hvac_mode = "cool")
        elif todays_high < 80 and todays_high >= 70:
            # set thermostat to 74 cool
            self.log("Setting thermostat to 74 cool")
            # Upstairs thermostat
            self.call_service("climate/set_temperature", entity_id = "climate.trane_corporation_model_tcont624as42daa_mode_2", temperature = 74)
            self.call_service("climate/set_hvac_mode", entity_id = "climate.trane_corporation_model_tcont624as42daa_mode_2", hvac_mode = "cool")
            # Downstairs thermostat
            self.call_service("climate/set_temperature", entity_id = "climate.trane_corporation_model_tcont624as42daa_mode", temperature = 74)
            self.call_service("climate/set_hvac_mode", entity_id = "climate.trane_corporation_model_tcont624as42daa_mode", hvac_mode = "cool")
        else:
            # set thermostat to 73 heat
            self.log("Setting thermostat to 73 heat")
            # Upstairs thermostat
            self.call_service("climate/set_temperature", entity_id = "climate.trane_corporation_model_tcont624as42daa_mode_2", temperature = 73)
            self.call_service("climate/set_hvac_mode", entity_id = "climate.trane_corporation_model_tcont624as42daa_mode_2", hvac_mode = "heat")
            # Downstairs thermostat
            self.call_service("climate/set_temperature", entity_id = "climate.trane_corporation_model_tcont624as42daa_mode", temperature = 73)
            self.call_service("climate/set_hvac_mode", entity_id = "climate.trane_corporation_model_tcont624as42daa_mode", hvac_mode = "heat")

Maybe verify the change before moving forward.
If true move on
If false retry
If fail (3) notify problem

Just so I’m following are you suggesting to simply do a get_state call and verify that those changes have been made else loop again?

I could put the call service calls under a function this way I’m not repeating code and just have it call the function again and check again.

Actually seems in the API docs I have these two additional options

Sequences

Run_in

Yes.

Also Yes

This is outside of me. I not use appdeamon ever but several ways to skin a cat right!!

I have a similar issue with a Nest thermostat (first floor) and a radiotherm thermostat on the second floor. It seems to take a few moments (not exactly sure how many seconds – yet) for the mode to change. The “fail” condition is when the outside temps trigger the thermostats to go from off to cool. I also tried to do it all in one call, but it must be separated into two separate calls in HA - the temp doesn’t change because the climate still reports it is off. Hence, the temp doesn’t get changed.

At this point, I’m looking to add a loop of some kind to check when the thermostat actually changes from off mode to cool mode. Then I’ll send the temperature change service call.

Still seems a little clunky because the python script is sitting there looping until something happens.

Any other thoughts on how to manage this? In the long run, it should be a check that’s included in the HA climate/set_temperature call.

I “solved” my problem by using sequences. I’m Appdaemon sequences is a way to add delays without doing a wait. It is not exactly what I wanted to do but it seems to work much better as you add a delay of 2 seconds and everything has enough time to go through.

Another method I was going to try was to schedule a callback. My understanding of this was that you can have a listen even schedule another callback based on another event, I think trying to recall from memory.

Thanks, @HA_fanatic. I was trying to move my climate controls out of AD - but I may try to get that working again. AD does have nice callback features! Again, thanks for the response.

In the meantime I added a time.sleep() in a loop, checking the state to make sure it changes. The Nest thermostat changes fairly quickly (within a couple seconds), but the radiotherm thermostat seems to take about 10 sec to report the mode change… I separated the delay into chunks by using the following loop:

  iterator = 1
  clim_mode = hass.states.get(climate_systems[1]).state
  while (clim_mode != hvacModeSecondTarget) and (iterator < 21):
    iterator = iterator + 1
    logger.info("Waiting for 2nd floor mode change {} out of 20 -- mode is {} should be {}".format(iterator, clim_mode.upper(), hvacModeSecondTarget.upper()))
    time.sleep(0.5)
    clim_mode = hass.states.get(climate_systems[1]).state

In the loop, hvacModeSecondTarget is the go-to mode (cool, heat). I get a warning in the log that tells me using time.sleep() can reduce HA performance… :upside_down_face:

What is the script written into? AD or HA Python Script? If AD then I think that maybe you aren’t suppose to use the time.sleep function…

This one is a python_script. I’ve waffled back and forth between python_scripts and AD. Presently, I’m in python_script. Maybe I have too much time on my hands with all the stay-at-home stuff going on :slight_smile:, so I rewrote the AD code into an automation and python_script.

While using AD (and I still do for tracking info), I use callbacks, not the time.sleep function.

Hmm never knew that you could use a typical python script. I saw Ha supports scripts but they are all still similar to YAML.

This should get you started. It’s a little limited for, I assume, good reason. But I’ve been able to use it for most things.