How to save entities state in persistent storage then restore it using scenes.apply?

The goal: Create a “Extended Away” button that when switched on will save the state of a set of entities on persistent storage, then will restore these when the button is switched off.

The approach:
1 - Use a trigger sensor to save the data - Done (may require changes)
2 - Build a dynamic scene and apply it using the scene.apply service - Having trouble.

This is the Trigger Sensor. The entities list will be a somewhat longer though. Notice there are different types of entities that the script takes into account (and more can be supported):

- trigger:
    - platform: event
      event_type: away_mode_save_state
  sensor:
    - unique_id: d29aa7e2-62e1-4836-b94c-657666c9c4b8
      name: away_mode_saved_state
      state: data
      attributes:
        data: >
          {% set ns = namespace(
            entities=[
              'climate.living_room',
              'switch.front_door_light',
            ],
            items=[],
          ) %}
          {% for entity in ns.entities %}
            {% set type = entity.split('.')[0] %}
            {% if type == 'climate' %}
              {% set attrs = { 'temperature': state_attr(entity, 'temperature') } %}
            {% elif type == 'switch' %}
              {% set attrs = {} %}
            {% endif %}
            {% set ns.items = ns.items + [ dict({ 'entity': entity, 'state': states(entity) }, **attrs) ] %}
          {% endfor %}
          {{ns.items }}

This works well. The entity will look like this:

Now, I’m trying to restore the state using an automation that uses scene.apply, but I can’t make it work.

- id: "away_mode_restore_state_automation"
  alias: Away Mode Restore State
  description: Restore state saved when enabling Away Mode
  trigger:
    - platform: event
      event_type: away_mode_restore_state
  action:
    - service: scene.apply
      data:
        entities: >
          {% for entry in state_attr('sensor.away_mode_saved_state', 'data') %}
          {% set type = entry.entity.split('.')[0] %}
          {{ entry.entity }}:
            state: {{ entry.state }}
            {% if type == 'climate' %}
            temperature: {{ entry.temperature }}
            {% endif %}
          {% endfor %}
  mode: single

When triggered, it fails with:

expected dict for dictionary value @ data['entities']

What am I missing here?

I also considered using a python script for the restore part, but I’m still a beginner on the matter. Let me know if that sounds like a better choice.

I also considered using a dictionary instead of an array for items (keys being the entity and the values being all the rest of the state/attributes). But I’m having a bit of trouble achieving it, as the keys are dynamic (entry.entity). Let me know if anyone knows how to do it as well.

I also considered using scene.create, but that’s won’t survive reboots. Maybe I could create the scene, and use it to save to the trigger entity above. But seems very convoluted.

Thanks a lot for your help!

Create the scene.

- service: scene.create
  data:
    scene_id: away_mode
    entities: >
      {{ state_attr('sensor.away_mode_saved_state', 'data') }}

Then apply it

- service: scene.turn_on
  target:
    entity_id: scene.away_mode

I tried it like this:

- id: "away_mode_restore_state_automation"
  alias: Away Mode Restore State
  description: Restore state saved when enabling Away Mode
  trigger:
    - platform: event
      event_type: away_mode_restore_state
  action:
    - service: scene.create
      data:
        scene_id: away_mode
        entities: >
          {{ state_attr('sensor.away_mode_saved_state', 'data') }}
    - service: scene.turn_on
      target:
        entity_id: scene.away_mode
  mode: single

It didn’t work. It fails on the creation step:

Executed: 18 March 2024 at 11:14:58
Result:
params:
  domain: scene
  service: create
  service_data:
    scene_id: away_mode
    entities:
      - entity: climate.hallway
        state: heat
        temperature: 22.5
      - entity: switch.front_door_light
        state: 'off'
  target: {}
running_script: false

Trace timeline:

Triggered by the event 'away_mode_restore_state' at 18 March 2024 at 11:14:58

Call a service 'Scenes: Create' on

Stopped because an error was encountered at 18 March 2024 at 11:14:58 (runtime: 0.00 seconds)

expected dict for dictionary value @ data['entities']

I believe the issue is the syntax is not correct. The entities should be like this:

    entities:
      climate.hallway:
        state: heat
        temperature: 22.5
      switch.front_door_light:
        state: 'off'

Which is the same issue with my initial approach, but at a different step.

change your original sensor to…

- trigger:
    - platform: event
      event_type: away_mode_save_state
  sensor:
    - unique_id: d29aa7e2-62e1-4836-b94c-657666c9c4b8
      name: away_mode_saved_state
      state: data
      attributes:
        data: > 
          {% set entities = [
                  'climate.living_room_thermostat',
                  'switch.front_trees',
                ] %}
          {% set ns = namespace(items=[], attrs=[]) %}
          {% for obj in entities | expand %}
            {% set ns.attrs = [('state', obj.state)] %}
            {% if obj.domain == 'climate' %}
              {% set ns.attrs = ns.attrs + [('temperature', obj.attributes.temperature)] %}
            {% endif %}
            {% set ns.items = ns.items + [ (obj.entity_id, dict.from_keys(ns.attrs)) ] %}
          {% endfor %}
          {{ dict.from_keys(ns.items) }}
1 Like

That worked perfectly!
Can’t thank you enough.