Script writing journey to alert for a/c cooling issues

I’ve been having an issue with my a/c recently where it will just randomly stop blowing air even though all my thermostats are on and I’ve been trying to get it fixed for a month now, but its been super irritating to discover that the a/c hasn’t been working for the last hour+ , so I wrote a script to alert me if the temperature isn’t dropping like it should. I’ve read hundreds of forum posts over the last day or two trying to figure out how the scripting works in home assistant and have bounced between trying to get a trend helper to watch the temperature, trying to expose more entities off a device, trying to make a modular script with a return_value, and just trying to incorporate basic use of variables, but there isn’t any decent documentation on this stuff. The official documentation is very lacking when it comes to the underlying behavior of how a script is evaluated and variables have some critical undocumented rules.

That said, here are some of the most useful things I’ve learned while researching all of this:

  • Variables are NOT defined where you specify them, they are defined at the beginning of the scope they’re currently in. If you want to force a variable to be defined, it seems like you can do this by defining a new scope with a sequence.
    Incorrect, they are defined where they are written. A variable after a delay calculates the variable once the delay completes.

  • Typing an open bracket into the value section of the IF/ELSE script gui crashes my browser, but that doesn’t mean you cant use dynamic values in conditions. Using the Edit script in YAML at the top of the page is much nicer overall, and using the gui is a helpful way to doublecheck syntax or search for autocomplete.

  • If using a dynamic value in a conditional, the condition type should be “template” and the value_template should evaluate to a truthy value. I wasn’t able to use variables in any way but this.

  • The trend helper seems to only be useful if you know exactly how often the device is being polled for change, otherwise I have no idea how you’re supposed to figure out any of the parameters to configure it.

  • You can’t simply stick a sensor into a variable, you have to use states(‘sensor.sensor_name’) and then you have to cast the type of that. In my case I was trying to access a temperature so I had to pipe it to “float” before doing any comparison, otherwise you get an esoteric error message about a dictionary (since a string is an array of characters I would assume)

  • EDIT: You should never use the template editor as a debugger for whether a script is parsable. The variables just wont work.

Anyway, here’s the script. I couldn’t find anything like it online so I’m sharing it here. I have it kicked off by an automation when the a/c gets set to “cooling” and It checks every 15 minutes while the a/c is on to make sure the temperature isn’t rising and if it is it sends out a notification, although once I confirm there aren’t any bugs I’ll probably just have it shut the a/c off automatically so i’m not wasting electricity.

alias: loft temp sensor
sequence:
  - repeat:
      while:
        - condition: state
          entity_id: climate.loft
          attribute: hvac_action
          state: cooling
      sequence:
        - variables:
            temp: "{{ states('sensor.loft_current_temperature') }}"
        - delay:
            hours: 0
            minutes: 15
            seconds: 0
            milliseconds: 0
        - if:
            - condition: template
              value_template: "{{ ((states('sensor.loft_current_temperature')|float) - (temp|float)) > 0 }}"
            - condition: and
              conditions:
                - condition: state
                  entity_id: climate.loft
                  attribute: hvac_action
                  state: cooling
          then:
            - action: notify.mobile_app_cph2551
              data:
                message: A/C fucked
                title: Warning!
description: ""
icon: mdi:air-conditioner

Anyway I just got a notification that my a/c is fucked so I gotta go fix it. Hope this helps anyone in a similar situation.

YAML variables can be defined in multiple locations in a script. Regarding setting variables in the sequence; while it is common practice to define variables at the beginning of a block, it is not required. The action variables is just like any other action, it can be called anywhere in the sequence.

HA Script Docs - Scope of Variables

Variables in automations follow a similar schema with some small differences.

Most automation in HA is event-based so repetitive polling is usually unnecessary. Keep in mind that repeats are not restart-proof, so your current construction will likely fail in that situation.

You will likely need to include additional triggers and conditions to your automation to handle restarts.

FWIW, the and condition in you if isn’t doing anything and is surplus to requirements. The and only applies to the list of conditions nested under it like:

- if:
    - condition: and
      conditions: 
        - condition: template
          value_template: "{{ states('sensor.loft_current_temperature')|float > temp|float }}"   
        - condition: state
          entity_id: climate.loft
          attribute: hvac_action
          state: cooling

But, there is no need to use an and condition unless it is inside an or or not condition.

YAML variables can be defined in multiple locations in a script. Regarding setting variables in the sequence; while it is common practice to define variables at the beginning of a block, it is not required. The action variables is just like any other action, it can be called anywhere in the sequence.

I see, maybe my issue then was I was trying to debug in the template editor where it tell me my variable was undefined when I tried to use it

Most automation in HA is event-based so repetitive polling is usually unnecessary. Keep in mind that repeats are not restart-proof, so your current construction will likely fail in that situation.

I agree, and my automation right now is set to kill existing monitor scripts and kick this script off to monitor the a/c. When the a/c shuts off I have another automation to kill this script. The idea is that I couldn’t find a satisfactory way to create an event that tracks state over time and the trend helper wasn’t a good solution for me

FWIW, the and condition in you if isn’t doing anything and is surplus to requirements. The and only applies to the list of conditions nested under it like:

Thank you!!! I set it up through the gui and I think it mixed up the conditions somehow. I moved it around so it should be doing what I was hoping for now.

Ok, I’ve updated it with the feedback. The real issue I was having was that the template parser that I was using to check my code syntax was telling me my variables weren’t defined because it didnt know how to parse them. Here’s the updated script:

alias: loft temp sensor
sequence:
  - repeat:
      while:
        - condition: state
          entity_id: climate.loft
          attribute: hvac_action
          state: cooling
      sequence:
        - variables:
            temp: "{{ states('sensor.loft_current_temperature') }}"
        - delay:
            hours: 0
            minutes: 5
            seconds: 0
            milliseconds: 0
        - variables:
            updatedTemp: "{{ states('sensor.loft_current_temperature') }}"
        - if:
            - condition: and
              conditions:
                - condition: template
                  value_template: "{{ ((updatedTemp|float) - (temp|float)) >= 0 }}"
                - condition: state
                  entity_id: climate.loft
                  attribute: hvac_action
                  state: cooling
          then:
            - action: notify.ntfy_message
              metadata: {}
              data:
                message: A/C fucked
                title: Warning!
            - action: script.bedroomclimatecooldown
              data: {}
description: ""
icon: mdi:air-conditioner

Having the variable set not only makes it a bit more readable, but it also records the variables value in the trace on each loop, making it much easier to debug.

For the automations, I have it so that every time the thermostat changes state it cancels previous runs of this script, waits a couple seconds, then calls this script again. The script tracks the temperature if it’s in cooling mode and if it notices that the a/c isn’t working it shoots out a notification and calls a second script which shuts off all a/c and tries turning it back on after a 30 minute cooldown.

Obviously fixing the a/c is preferable, but I’m going out of town and don’t want my cat to be miserable in a 90 degree house so I think this will keep him happy while I’m gone