From State when device isn't the trigger

HI am trying to turn off an hvac device when a window is open, I want to turn the hvac back on in it’s previous mode when the window is closed again. how do I store the original HVAC mode to use it later.

I am using the room’s light switch here so I can test it without being in the room / house

alias: test bedroom HVAC
description: If window is open, turn heating off
trigger:
  - platform: device
    type: turned_on
    device_id: 0f1c7bf88077d873223e6844600cab03
    entity_id: light.bedroom_light
    domain: light
condition: []
action:
  - repeat:
      while:
        - condition: device
          type: is_on
          device_id: 0f1c7bf88077d873223e6844600cab03
          entity_id: light.bedroom_light
          domain: light
      sequence:
        - device_id: b1d08f630c3978e8c08aa0f184710b36
          domain: climate
          entity_id: climate.bedroom
          type: set_hvac_mode
          hvac_mode: "off"
  - device_id: b1d08f630c3978e8c08aa0f184710b36
    domain: climate
    entity_id: climate.bedroom
    type: set_hvac_mode
    hvac_mode: ?????
mode: single
Message malformed: value must be one of ['auto', 'cool', 'dry', 'fan_only', 'heat', 'heat_cool', 'off'] for dictionary value @ data['hvac_mode']

Store the information in a text helper.

1 Like

Create a snapshot scene. Your intended application (storing/restoring states when a window is opened/closed) is the subject of an example in the documentation.

Creating scenes on the fly

Let me know if you need help implementing it.

2 Likes

Thank you, it kind of works. It works if the HVAC mode wasn’t “full auto” (heat) If it was full auto then it does get reset to full auto (heat) but immediately changes to “temporary manual” (fan only) I think this is the thermostat itself deciding there has been a manual entry. but IDK

alias: test bedroom HVAC
description: If window is open, turn heating off
trigger:
  - platform: device
    type: turned_on
    device_id: 0f1c7bf88077d873223e6844600cab03
    entity_id: light.bedroom_light
    domain: light
condition: []
action:
  - service: scene.create
    data:
      scene_id: before
      snapshot_entities:
        - climate.bedroom
  - repeat:
      while:
        - condition: device
          type: is_on
          device_id: 0f1c7bf88077d873223e6844600cab03
          entity_id: light.bedroom_light
          domain: light
      sequence:
        - device_id: b1d08f630c3978e8c08aa0f184710b36
          domain: climate
          entity_id: climate.bedroom
          type: set_hvac_mode
          hvac_mode: "off" 
  - service: scene.turn_on
    target:
      entity_id: scene.before 
mode: single

I don’t know if you are aware of it but the repeat loop you have created is repeatedly executing the Device Action as fast as your host machine allows for it. In other words, it’s sending a rapid, continuous stream of commands to your thermostat.

At a bare minimum, add a delay statement, set to 10 or 15 seconds, just after the Device Action. It will make each iteration run at 10 second intervals (instead of every few milliseconds or microseconds).

BTW, I assume you’re using a repeat to ensure that if someone attempts to turn the thermostat back on, while the window is open, it will be promptly turned off again.

1 Like

Thanks, yes in the live automation it is set to 30 seconds. this automation was a prototype that I resurrected to try and not have the resultant hvac mode hardcoded like in the live automation. And yes, it’s to stop the HVAC being turned back on and overriding the automation :smiley:

  - repeat:
      while:
        - type: is_open
          condition: device
          device_id: 5d1462e165b640c556e60afb54c2ff50
          entity_id: binary_sensor.contact_sensor_3
          domain: binary_sensor
      sequence:
        - device_id: ea4059467048852d9de7f0067c09a47e
          domain: climate
          entity_id: climate.small_bedroom
          type: set_hvac_mode
          hvac_mode: "off"
        - delay:
            hours: 0
            minutes: 0
            seconds: 30
            milliseconds: 0

Just add an automation that sets the helper when the mode is changed, but condition it to NOT be “Off”.

1 Like

If you’re interested, here’s how to ensure the thermostat remains off while the window is open without employing repeat and delay.

alias: example
mode: queued
trigger:
  - id: window
    platform: state
    entity_id: binary_sensor.contact_sensor_3
    from:
      - 'off'
      - 'on'
    to:
      - 'on'
      - 'off'
  - id: hvac
    platform: state
    entity_id: climate.small_bedroom
    from: 'off'
condition: []
action:
  - choose:
      - conditions: "{{ trigger.id == 'window' }}"
        sequence:
          - if: "{{ trigger.to_state.state == 'on' }}"
            then:
              - service: scene.create
                data:
                  scene_id: before
                  snapshot_entities:
                    - climate.small_bedroom
              - service: climate.set_hvac_mode
                target:
                  entity_id: climate.small_bedroom
                data:
                  hvac_mode: 'off'
            else:
              - service: scene.turn_on
                target:
                  entity_id: scene.before
      - conditions:
          - "{{ trigger.id == 'hvac' }}"
          - "{{ is_state('binary_sensor.contact_sensor_3', 'on') }}"
        sequence:
          - service: climate.set_hvac_mode
            target:
              entity_id: climate.small_bedroom
            data:
              hvac_mode: 'off'
    default: []

The advantages are:

  • Turns off the thermostat immediately as opposed to waiting until the delay expires.
  • It’s driven exclusively by state-changes so the automation doesn’t remain in a busy state while looping through a repeat.
1 Like

that’s just words tbh, I’m not an expert and having to work from examples, can you pad it out a bit, also text helpers

thank you

thank you that has the same functionality :slight_smile: but it also fails at the same place. When turning the thermostat back on in HEAT (full auto) mode it sets the mode to FAN ONLY (temporary manual)

the scene_id before seems to be changed at light off / window closed … before changed to 29 March 2023 at 17:27

Bedroom changed to Fan only triggered by automation window test 2 triggered by state of Bedroom light
17:27:12 - In 1 second
window test 2 triggered by state of Bedroom
17:27:12 - In 1 second
Bedroom changed to Heat triggered by automation window test 2 triggered by state of Bedroom light
17:27:12 - In 1 second
before changed to 29 March 2023 at 17:27 triggered by automation window test 2 triggered by state of Bedroom light
17:27:10 - Now
window test 2 triggered by state of Bedroom light
17:27:10 - Now
Bedroom light turned off
17:27:10 - Now

I think there is a blueprint for this already…

2 Likes

The example I posted wasn’t meant to fix that.

That behavior appears to be a limitation of how your thermostat responds to the restoration of its previous state.

1 Like

That blueprint monitors the window’s state but not the thermostat’s state. So if someone turns the thermostat back on while the window is open, it won’t turn the thermostat back off.

1 Like

It’s OK, it’s much better than I had before. I can use HA to set the mode hardcoded but just not dynamically from the scene .

But not good enough to be the solution. Apparently ‘sets the helper when the mode is changed, but condition it to NOT be “Off”’ is all you needed to do to solve it?

I don’t know what that means, what helper?

You tell me. You marked that post with the Solution tag.

I guess I set that as the solution by accident :open_mouth: you may not understand how much I’m winging-it here :smiley:

so I know this works fine

    domain: climate
    entity_id: climate.bedroom
    type: set_hvac_mode
    hvac_mode: Heat

so is there a way to replace heat with a variable = original state? or do scenes have properties like scene.state I can reference instead of whole scene, like scene.before.hvac_mode ?

That’s a Device Action and it doesn’t support templating (i.e. none of its options can be assigned a variable’s value or some other entity’s value).

However, a service call, like the climate.set_hvac_mode service call I used in my example above, does support templates. So if you have stored the thermostat’s original state in an Input Text (let’s call it input_text.small_bedroom) then you can reference its value like this:

          - service: climate.set_hvac_mode
            target:
              entity_id: climate.small_bedroom
            data:
              hvac_mode: "{{ states('input_text.small_bedroom') }}"

Reference: Templating