Script that reads state and computes based on it

I’m new to HA, and I’m sure this is easier than I am making it out to be, but after trying to find an answer by searching, I thought I would just ask.

I want to create a script that increases (or decreases) the HVAC setpoint by a fixed amount. So, I need to be able to get the current setpoint as a variable, so I can adjust it then use it to create the current setpoint.

Can someone point me in the right direction?

You can use a template in the climate.set_temperature action to calculate the new setpoint based on the old one.

action: climate.set_temperature
target:
  entity_id: climate.your_hvac
data:
  temperature: "{{ state_attr('climate.your_hvac','temperature') + 2 }}"

I struggling with HA as it seems that everything requires a level of complexity that doesn’t make sense to me. As I stated, I want to do this via a script. So, from a script, how can I trigger a template? And, can I pass in a parm (I have two thermostats and want to have scripts that increase/decrease the setpoint by 1/2/3 degrees. Do I have to create a separate template for each of these? I just wish that scripts were more complete so that this could just be done in the script itself.

Hi Dan Hinsley,

Look for something someone has already written for you in Blueprints Exchange - Home Assistant Community.

BTW all user programming in Home Assistant is scripts. They take the form of scriipts, automations, templates, and dashboards.

In HA, Scripts are a series of actions. What atlflyer posted above is an action that could be placed in a script. If you need help translating YAML configuration to use in the Script Editor, there is a slightly dated, but still informative video primer on Youtube.

The way you get the current setpoint is through templates that query the state object of the entity you are interested in. Many types of actions allow the use of templates as a means to produce dynamic values in scripts and automations.

Performing Actions
Passing variables to scripts

What was confusing me was the requirement to do this in a template. I added it as an action, which makes much more sense (to me at least). But when I run the script, it doesn’t do anything (note that I can control this thermostat from the built-in thermostat card). Is there a way to turn on any debugging so I can get some more info? Here is the script I am trying to run:

up_one_degree:
  alias: Up one degree
  sequence:
    action: climate.set_temperature
    target:
      entity_id: climate.touchscreen_comfort_control_thermostat
    data:
      temperature: "{{ state_attr('climate.touchscreen_comfort_control_thermostat','temperature') + 2 }}"
  description: "up 2 degrees"
  icon: mdi:air-conditioner

That’s what traces does…

It will tel you what was triggered and each step of your actions along the way.

Great! I think this will tell me what I need to know (even though I am still confused on a higher plane, but I think I’m getting there).

I spoke too quickly. One of the things I want to see is what the script thinks the state of a thermostat is. So I created a variable with that value, but don’t see it listed in the trace. Here is the script:

up_two_degrees:
  alias: Up two degrees
  variables:
    front_therm_setpoint: '{{ state_attr(''climate.touchscreen_comfort_control_thermostat'',''temperature'')}}'
  sequence:
    action: climate.set_temperature
    target:
      entity_id: climate.touchscreen_comfort_control_thermostat
    data:
      temperature: front_therm_setpoint + 2
  description: up 2 degrees
  icon: mdi:air-conditioner

I changed the variable definition to:

front_therm_setpoint: state_attr('climate.touchscreen_comfort_control_thermostat','temperature')

as that seemed more correct. What I am getting in the trace is (I have two thermostats, and neither of them has the cool setpoint set to 80):

Executed: November 15, 2024 at 12:08:27 PM
Result:

params: domain: climate service: set_temperature service_data: temperature: 80 device_id: - 5b25792b58dc925f3ae529eff6033500 target: device_id: - 5b25792b58dc925f3ae529eff6033500 running_script: false

Step ConfigChanged VariablesRelated logbook entries

1

2

3

4

5

6

⌄

⌄

action: climate.set_temperature

metadata: {}

data:

temperature: 80

target:

device_id: 5b25792b58dc925f3ae529eff6033500

The following line is invalid:

All templates need to be enclosed in quotes and the appropriate Jinja delimiters:

temperature: "{{ front_therm_setpoint + 2}}"

Be aware that not all climate entities will have a temperature attribute depending on their functionality and the integration that creates them. If your thermostat is using the heat_cool mode or you are using something like ESPHome’s Bang-Bang controller you will need to use the target_temp_high or target_temp_low attribute and action variable. Check your entity in the States tab of Developer Tools to see which you should be using.

Also, FWIW, if want to share a debug trace, the best way to do so is to download the trace json (option can be found in the 3-dot expansion menu) then post the contents of that file.

Now it tells me that it expects a float for temperature. Script and trace below:

up_two_degrees:
  alias: Up two degrees
  variables:
    front_therm_setpoint: state_attr('climate.touchscreen_comfort_control_thermostat','temperature') + 2
    test_setpoint: 82
  sequence:
    action: climate.set_temperature
    target:
      entity_id: climate.touchscreen_comfort_control_thermostat
    data:
      temperature: "{{ front_therm_setpoint }}"
  description: up 2 degrees
  icon: mdi:air-conditioner

{
  "trace": {
    "last_step": "sequence/0",
    "run_id": "b87859f1b0dbe97bf02e91577a72ffa9",
    "state": "stopped",
    "script_execution": "error",
    "timestamp": {
      "start": "2024-11-15T21:28:04.270712+00:00",
      "finish": "2024-11-15T21:28:04.280224+00:00"
    },
    "domain": "script",
    "item_id": "up_two_degrees",
    "error": "expected float for dictionary value @ data['temperature']",
    "trace": {
      "sequence/0": [
        {
          "path": "sequence/0",
          "timestamp": "2024-11-15T21:28:04.272320+00:00",
          "changed_variables": {
            "front_therm_setpoint": "state_attr('climate.touchscreen_comfort_control_thermostat','temperature') + 2",
            "test_setpoint": 82,
            "this": {
              "entity_id": "script.up_two_degrees",
              "state": "off",
              "attributes": {
                "last_triggered": "2024-11-15T21:27:03.726114+00:00",
                "mode": "single",
                "current": 0,
                "icon": "mdi:air-conditioner",
                "friendly_name": "Up two degrees"
              },
              "last_changed": "2024-11-15T21:27:50.744475+00:00",
              "last_reported": "2024-11-15T21:27:50.744475+00:00",
              "last_updated": "2024-11-15T21:27:50.744475+00:00",
              "context": {
                "id": "01JCRVK9PRA9DM8XP629ZWB3QS",
                "parent_id": null,
                "user_id": null
              }
            },
            "context": {
              "id": "01JCRVKPXED9FQR52BDBQVGHHC",
              "parent_id": null,
              "user_id": "c0d2fe7812da474195e3950d945b961c"
            }
          },
          "error": "expected float for dictionary value @ data['temperature']",
          "result": {
            "params": {
              "domain": "climate",
              "service": "set_temperature",
              "service_data": {
                "temperature": "state_attr('climate.touchscreen_comfort_control_thermostat','temperature') + 2",
                "entity_id": [
                  "climate.touchscreen_comfort_control_thermostat"
                ]
              },
              "target": {
                "entity_id": [
                  "climate.touchscreen_comfort_control_thermostat"
                ]
              }
            },
            "running_script": false
          }
        }
      ]
    },
    "config": {
      "alias": "Up two degrees",
      "variables": {
        "front_therm_setpoint": "state_attr('climate.touchscreen_comfort_control_thermostat','temperature') + 2",
        "test_setpoint": 82
      },
      "sequence": {
        "action": "climate.set_temperature",
        "target": {
          "entity_id": "climate.touchscreen_comfort_control_thermostat"
        },
        "data": {
          "temperature": "{{ front_therm_setpoint }}"
        }
      },
      "description": "up 2 degrees",
      "icon": "mdi:air-conditioner"
    },
    "blueprint_inputs": null,
    "context": {
      "id": "01JCRVKPXED9FQR52BDBQVGHHC",
      "parent_id": null,
      "user_id": "c0d2fe7812da474195e3950d945b961c"
    }
  },
  "logbookEntries": [
    {
      "state": "on",
      "entity_id": "script.up_two_degrees",
      "icon": "mdi:air-conditioner",
      "when": 1731706084.2714305,
      "context_user_id": "c0d2fe7812da474195e3950d945b961c"
    },
    {
      "state": "off",
      "entity_id": "script.up_two_degrees",
      "icon": "mdi:air-conditioner",
      "when": 1731706084.2794733,
      "context_user_id": "c0d2fe7812da474195e3950d945b961c",
      "context_state": "on",
      "context_entity_id": "script.up_two_degrees"
    }
  ]
}

Again, you cannot exclude the quotes and delimiters…

Don’t say we never did anything for you… :smile:

Yeah, that seems to work. I need to work on understanding the jinja2 syntax better. I’ve been to their page, since that seems to be where I’m getting tripped up.

Let me ask you a question. After I edit a script’s YAML, do I need to reload the YAML before it takes effect (probably a dumb question).

That depends on whether you are editing directly in the configuration, or using the “Edit in YAML” option of the UI Script Editor. If done directly in the configuration, you need to reload the Script config or do a restart from the YAML tab of Developer Tools. When using any of the UI editors clicking the “Save” button will automatically reload the appropriate configuration.