Dynamic list of Destinations based on Zones, and useable by Waze

This does not trigger the automation when I add/edit/delete Zones in HA.
Nor does it trigger if I execute an HA YAML configuration reloading of ZONES

Then pare back the event_data to see all call_services that occur when you reload or add zones. I was making a guess on the trigger based on other reload services.

I watched call_service in Dev Tools and did not see anything when I edited a zone name…

I’ve been trying to figure out if I might be able to add something like trigger.event.data to reduce the trigger frequency but I am concerned that zone add/delete/edit just isn’t visible as a trigger since I cannot see anything in Listen to events. I’m also thinking now that my condition: {{ trigger.event.data.new_state.domain == “zone” }} isn’t catching what I want but something else and is actioning the input_select.set_options as a result.

alias: Update Destinations
description: ''
trigger:
  - platform: event
    event_type: state_changed

I have tried this but it doesn’t trigger:

trigger:
  - platform: event
    event_type: state_changed
    event_data:
      new_state:
        domain: zone
condition: []

what does the state_changed event look like for zone?

I cannot see a state_changed for zone yet the condition:{{ trigger.event.data.new_state.domain == "zone" }} is executing the service: input_select.set_options. I’ve been trying to spit out some data using service: notify.persistent_notification. If I add a zone or edit a zone the automation executes but not if I delete a zone since there is no state change involved.

trigger:
  - platform: event
    event_type: state_changed
    event_data: {}
condition:
  - condition: template
    value_template: '{{ trigger.event.data.new_state.domain == "zone" }}'
action:
  - service: input_select.set_options
    target:
      entity_id: input_select.destination
    data:
      options: |
        {%- set ns = namespace(items=[]) -%}
        {% for entity in states.zone -%}
          {%- set ns.items = ns.items + [entity.name] -%}
        {%- endfor %}
        {{ ns.items }}
  - service: notify.persistent_notification
    data:
      title: '{{ trigger.event.data.new_state.domain }}'
      message: '{{ trigger.event.data.new_state.entity_id }}'

image

The HA built-in events don’t cover an entity being deleted but I did find this while peeking and poking:

Event 1 fired 10:22 AM:
{
    "event_type": "entity_registry_updated",
    "data": {
        "action": "remove",
        "entity_id": "zone.test"
    },
    "origin": "LOCAL",
    "time_fired": "2022-01-19T18:22:15.619767+00:00",
    "context": {
        "id": "5563eb5670053802675b7e33f3645d87",
        "parent_id": null,
        "user_id": null
    }
}
Event 0 fired 10:20 AM:
{
    "event_type": "entity_registry_updated",
    "data": {
        "action": "create",
        "entity_id": "zone.test"
    },
    "origin": "LOCAL",
    "time_fired": "2022-01-19T18:20:52.276968+00:00",
    "context": {
        "id": "ebf39de40a23b5548a643b3c37412f84",
        "parent_id": null,
        "user_id": null
    }
}

The registry is not updated when I edit a zone name though so I will need two triggers, one for state_changed where entity_id is in domain zone and another for entity_registry_updated where entity_id is in domain zone. Now to figure out the syntax for the triggers so they are limited to the zone domain…

You only need to update the zone list when things are created or deleted, so you have all the info you need.

alias: Update Destinations
description: ''
trigger:
  - platform: event
    event_type: entity_registry_updated
condition:
  - condition: template
    value_template: "{{ trigger.event.data.action in ['create', 'delete'] and trigger.event.data.entity_id.startswith('zone.') }}"
action:
  - service: input_select.set_options
    target:
      entity_id: input_select.destination
    data:
      options: "{{ states.zone | map(attribute='name') | list }}"
mode: parallel
max: 25

I hobbled this together:

trigger:
  - platform: event
    event_type: entity_registry_updated
    event_data:
      action: remove
  - platform: event
    event_type: entity_registry_updated
    event_data:
      action: create
condition: []
action:
  - service: input_select.set_options
    target:
      entity_id: input_select.destination
    data:
      options: |
        {%- set ns = namespace(items=[]) -%}
        {% for entity in states.zone -%}
          {%- set ns.items = ns.items + [entity.name] -%}
        {%- endfor %}
        {{ ns.items }}
  - service: notify.persistent_notification
    data:
      title: '{{ trigger.event.event_type }}'
      message: '{{ trigger.event.data.action }} {{ trigger.event.data.entity_id }}'

image
which has two triggers and no condition but I like your trigger + condition better!

And thank you for this piece of tidy code!

I still need a state_changed trigger to cover when a zone name is edited…

That’s probably still a entity_registry_updated change. Personally I wouldn’t bother, how often are you changing zone names?

Not very often! I am looking more now to just conquering this!!

It did not trigger an entity_registry_updated but I managed to find the state_changed this time through:

Event 20 fired 10:53 AM:
{
    "event_type": "state_changed",
    "data": {
        "entity_id": "zone.select_express",
        "old_state": {
            "entity_id": "zone.select_express",
            "state": "zoning",
            "attributes": {
                "latitude": 49.23289236942634,
                "longitude": -122.82306556407177,
                "radius": 30.48013447922684,
                "passive": false,
                "editable": true,
                "icon": "mdi:map-marker",
                "friendly_name": "Select Express Courier"
            },
            "last_changed": "2022-01-19T14:03:08.927911+00:00",
            "last_updated": "2022-01-19T18:51:37.039820+00:00",
            "context": {
                "id": "f5827c044eb772a94b1ece43e2ee7206",
                "parent_id": null,
                "user_id": null
            }
        },
        "new_state": {
            "entity_id": "zone.select_express",
            "state": "zoning",
            "attributes": {
                "latitude": 49.23289236942634,
                "longitude": -122.82306556407177,
                "radius": 30.48013447922684,
                "passive": false,
                "editable": true,
                "icon": "mdi:map-marker",
                "friendly_name": "Select Express"
            },
            "last_changed": "2022-01-19T14:03:08.927911+00:00",
            "last_updated": "2022-01-19T18:53:24.294448+00:00",
            "context": {
                "id": "66c7272b369176903756c4dd84ee3f3a",
                "parent_id": null,
                "user_id": null
            }
        }
    },

Is there a way to define the trigger without a condition such that it only triggers on entity_id.startswith(‘zone.’)?

No, you trigger on everything and conditionally run the actions based on the event data. You can’t partially check data as a trigger.

Okay, thank you!
So now I have this

alias: Update Destinations (state_changed)
description: ''
trigger:
  - platform: event
    event_type: state_changed
    event_data: {}
condition:
  - condition: template
    value_template: '{{ trigger.event.data.entity_id.startswith("zone.") }}'
action:
  - service: input_select.set_options
    target:
      entity_id: input_select.destination
    data:
      options: |
        {%- set ns = namespace(items=[]) -%}
        {% for entity in states.zone -%}
          {%- set ns.items = ns.items + [entity.name] -%}
        {%- endfor %}
        {{ ns.items }}
  - service: notify.persistent_notification
    data:
      title: '{{ trigger.event.data.new_state.domain }}'
      message: Edited {{ trigger.event.data.new_state.entity_id }}

image

and this

alias: Update Destinations (entity_registry_updated)
description: ''
trigger:
  - platform: event
    event_type: entity_registry_updated
    event_data:
      action: remove
  - platform: event
    event_type: entity_registry_updated
    event_data:
      action: create
condition: []
action:
  - service: input_select.set_options
    target:
      entity_id: input_select.destination
    data:
      options: |
        {%- set ns = namespace(items=[]) -%}
        {% for entity in states.zone -%}
          {%- set ns.items = ns.items + [entity.name] -%}
        {%- endfor %}
        {{ ns.items }}
  - service: notify.persistent_notification
    data:
      title: '{{ trigger.event.event_type }}'
      message: '{{ trigger.event.data.action }} {{ trigger.event.data.entity_id }}'

After an edit, a create new and then a delete I got 5 notifications

I disabled the (entity_registry_updated) automation and did another edit, add, delete and got all three notifications via the (state_changed) automation, and the input_select of course was updated.

Thanks for the assistance and knowledge!

please allow me to piggyback here, because I also had plans to add these zone creation deletion events to the dynamic input_select automation.

How come this works at all, because zones aren’t listed in the entity_registry? duh, ofc they are but only when created in the UI. I had all my zones in yaml…

btw I now use this template

{{expand(states.zone, states.person)|map(attribute='name')|list}}

which I find useful to be able to plan travels to my family :wink:

edited

made a user error before so edited the post.

btw2:

2022-01-20 11:17:58 ERROR (MainThread) [homeassistant.helpers.template] Template variable error: 'str object' has no attribute 'data' when rendering 'Zones were update because of {{trigger.id}}. latest action:
  - {{ trigger.event.data.action }} {{ trigger.event.data.entity_id }}'
2022-01-20 11:17:58 ERROR (MainThread) [homeassistant.components.automation.update_travel_options] Update travel options: Error executing script. Error for call_service at pos 2: Error rendering data template: UndefinedError: 'str object' has no attribute 'data'
2022-01-20 11:18:02 ERROR (MainThread) [homeassistant.components.automation.update_travel_options] Error while executing automation automation.update_travel_options: Error rendering data template: UndefinedError: 'str object' has no attribute 'data'

using:

 - alias: Update travel options
    id: Update travel options
    mode: restart
    max: 50
    trigger:
      - platform: homeassistant
        event: start
        id: ha
      - platform: event
        event_type: entity_registry_updated
        event_data:
          action: create
        id: create
      - platform: event
        event_type: entity_registry_updated
        event_data:
          action: remove
        id: remove
    condition:
      condition: template
      value_template: >
        {{ (trigger.id in ['create','remove'] and
            trigger.event.data.entity_id.startswith('zone.')) or
            trigger.id == 'ha'}}
    action:
      - service: input_select.set_options
        target:
          entity_id:
            - input_select.destination
            - input_select.origin
        data:
          options: >
            {{expand(states.zone, states.person)|map(attribute='name')|list}}
      - service: system_log.write
        data:
          message: >
            Zones were update because of {{trigger.id}}.
            latest action:
              - {{ trigger.event.data.action }} {{ trigger.event.data.entity_id }}

could this be the homassistant start event not having that data?

Yes, I discovered that last night and added the input.select update to my HA Startup automation:

alias: HA Startup
description: ''
trigger:
  - platform: homeassistant
    event: start
condition: []
action:
  - delay:
      hours: 0
      minutes: 0
      seconds: 5
      milliseconds: 0
  - service: python_script.domains_in_use
  - service: python_script.entities_in_use
  - service: input_boolean.turn_off
    target:
      entity_id: input_boolean.reset_multisensor
  - delay:
      hours: 0
      minutes: 0
      seconds: 5
      milliseconds: 0
  - service: notify.alexa_media_last_called
    data:
      message: Home Assistant has started
      title: Home Assistant
      data:
        type: tts
  - choose:
      - conditions:
          - condition: device
            type: is_off
            device_id: f177253ec75b1464a93bef4e329770ac
            entity_id: switch.plug_1
            domain: switch
        sequence:
          - type: turn_on
            device_id: f177253ec75b1464a93bef4e329770ac
            entity_id: switch.plug_1
            domain: switch
      - conditions:
          - condition: device
            type: is_off
            device_id: f177253ec75b1464a93bef4e329770ac
            entity_id: switch.plug_2
            domain: switch
        sequence:
          - type: turn_on
            device_id: f177253ec75b1464a93bef4e329770ac
            entity_id: switch.plug_2
            domain: switch
      - conditions:
          - condition: device
            type: is_off
            device_id: f177253ec75b1464a93bef4e329770ac
            entity_id: switch.plug_3
            domain: switch
        sequence:
          - type: turn_on
            device_id: f177253ec75b1464a93bef4e329770ac
            entity_id: switch.plug_3
            domain: switch
    default: []
  - service: input_select.set_options
    target:
      entity_id: input_select.destination
    data:
      options: "{{ states.zone | map(attribute='name') | list }}"
mode: single

This should be action: 'delete':

      - platform: event
        event_type: entity_registry_updated
        event_data:
          action: remove
        id: remove

So this…

can then be

    trigger:
      - platform: event
        event_type: entity_registry_updated
    condition:
      - condition: template
        value_template: "{{ trigger.event.data.action in ['create', 'delete'] and trigger.event.data.entity_id.startswith('zone.') }}"

or

    trigger:
      - platform: event
        event_type: entity_registry_updated
        event_data:
          action: create
      - platform: event
        event_type: entity_registry_updated
        event_data:
          action: delete
    condition:
      condition: template
      value_template: "{{ trigger.event.data.entity_id.startswith('zone.') }}"

no:

{
    "event_type": "entity_registry_updated",
    "data": {
        "action": "remove",
        "entity_id": "zone.buurt"
    },
    "origin": "LOCAL",
    "time_fired": "2022-01-20T19:03:35.551667+00:00",

it’s really ‘remove’

as is in my log:

2022-01-20 20:03:35 WARNING (MainThread) [ZONE EDITOR] Zones were updated because of 'remove'. latest action: entity_registry_updated

  - remove zone.buurt

Ive ended up with:

  - alias: Update travel options
    id: Update travel options
    mode: restart
    max: 50
    trigger:
      - platform: homeassistant
        event: start
        id: ha
      - platform: event
        event_type: entity_registry_updated
        event_data:
          action: create
        id: create
      - platform: event
        event_type: entity_registry_updated
        event_data:
          action: remove
        id: remove
    condition:
      condition: template
      value_template: >
        {{ (trigger.id in ['create','remove'] and
            trigger.event.data.entity_id.startswith('zone.')) or
            trigger.id == 'ha'}}
    action:
      - service: input_select.set_options
        target:
          entity_id:
            - input_select.destination
            - input_select.origin
        data:
          options: >
            {{expand(states.zone, states.person)|map(attribute='name')|list}}
      - condition: template
        value_template: >
          {{trigger.platform != 'homeassistant'}}
      - service: system_log.write
        data:
          message: >
            {{trigger.event.event_type|replace('_',' ')|capitalize}}
            Zones were updated because of '{{trigger.id}}'.
            latest action:

              - {{trigger.event.data.action}} {{trigger.event.data.entity_id}}
          level: warning
          logger: ZONE EDITOR

and filter out the startup event for the logging.

You’re right!

Event 1 fired 11:23 AM:
{
    "event_type": "entity_registry_updated",
    "data": {
        "action": "remove",
        "entity_id": "zone.test"
    },
    "origin": "LOCAL",
    "time_fired": "2022-01-20T19:23:15.602323+00:00",
    "context": {
        "id": "d5de7fbf52ec61dc889258be85b01aba",
        "parent_id": null,
        "user_id": null
    }
}

I now have the previous state of my input_select.destination being restored when HA starts up.
The problem I had was that the initial state would be Home since that’s the only option that HA saves with the input_select.destination; it doesn’t seem to save the dynamically created options.
So, I’m using a simple var. from HACS Variable integration

var:
  saved_destination:
    friendly_name: Saved Destination

The var gets updated here:

alias: Waze - Update Travel time to destination
description: ''
trigger:
  - platform: state
    entity_id: input_select.destination
condition: []
action:
  - service: homeassistant.update_entity
    target:
      entity_id: sensor.waze_select_destination
  - service: var.set
    data:
      entity_id: var.saved_destination
      value: '{{ states("input_select.destination") }}'
mode: single

and I restore the state of input_select.destination in my HA Startup automation which also triggers an update of the travel time:

alias: HA Startup
description: ''
trigger:
  - platform: homeassistant
    event: start
condition: []
action:
  - service: input_select.set_options
    target:
      entity_id: input_select.destination
    data:
      options: '{{ states.zone | map(attribute="name") | list }}'
  - service: input_select.select_option
    target:
      entity_id: input_select.destination
    data:
      option: '{{ states("var.saved_destination") }}'
  - service: python_script.domains_in_use
  - service: python_script.entities_in_use
  - choose:
      - conditions:
          - condition: device
            type: is_off
            device_id: f177253ec75b1464a93bef4e329770ac
            entity_id: switch.plug_1
            domain: switch
        sequence:
          - type: turn_on
            device_id: f177253ec75b1464a93bef4e329770ac
            entity_id: switch.plug_1
            domain: switch
      - conditions:
          - condition: device
            type: is_off
            device_id: f177253ec75b1464a93bef4e329770ac
            entity_id: switch.plug_2
            domain: switch
        sequence:
          - type: turn_on
            device_id: f177253ec75b1464a93bef4e329770ac
            entity_id: switch.plug_2
            domain: switch
      - conditions:
          - condition: device
            type: is_off
            device_id: f177253ec75b1464a93bef4e329770ac
            entity_id: switch.plug_3
            domain: switch
        sequence:
          - type: turn_on
            device_id: f177253ec75b1464a93bef4e329770ac
            entity_id: switch.plug_3
            domain: switch
    default: []
  - service: notify.alexa_media_last_called
    data:
      message: Home Assistant has started
      title: Home Assistant
      data:
        type: tts
  - service: homeassistant.update_entity
    target:
      entity_id: sensor.waze_select_destination
mode: single

I found that if I placed the homeassistant.update_entity for Waze too early in the startup automation, the update did not occur. I played with it quite a bit restarting HA while watching Dev Tools Template in another window so I could see things updating as HA processed startup…

{{states('sensor.ha_current_version') == states('sensor.ha_latest_version')}}
{{states('sensor.ha_current_version')}}

{{ states.media_player|selectattr('attributes.last_called','eq',true)|map(attribute='entity_id')|join }}
{{ states('sensor.last_alexa') }}

Domains in use: {{ states("sensor.overview_domains") }}
Travel time: {{ states("sensor.waze_select_destination") }}m
Saved: {{ states("var.saved_destination") }}
Current: {{ states("input_select.destination") }}
Options: {{ state_attr("input_select.destination","options")|list }}

what’s that? I dont see that on my media_players…

a for the restore, yes Ive encountered that too ofc, but set 1 option in the config of the input_select, to have it always startup with me and my better half, so I can spot the most important travel time right away :wink:

I dont have a zone Home, and the system defaults to my configuration gps coordinates, and those seem not to be useable in this travel time, throwing an error no lat/long is available.

If I create a Home zone in Yaml, as the docs suggest to override the auto zone, its messes up all other logic in my system where trackers and home is required… a lot of trouble over something not worht the while. Why bother restoring this in the first place.

Second to that, could we use a core input entity for that, those are restored at startup, and I suppose you could use that in your automation?

last_called is an attribute on Alexa Media Players.

I don’t see an option like that through the UI…

My Home zone is the built-in zone


What is your auto zone called?

Yes, you could use a core input_text rather the custom var to save the last targeted destination. I chose var since I already am using it…

With the HA 2022.4 enhancement adding a state to zones, I found my automation to update waze was triggering every time a zone state changed. I fumbled around a bit with my automation that was triggered on event state_changed with the condition value_template: ‘{{ trigger.event.data.entity_id.startswith(’‘zone.’’) }}’ to eliminate running actions where it was a zone state that changed. I ended up abandoning that and now have:

sensor:
  - name: Zones
    unique_id: zone_list
    state: '{{ states.zone | count }}'
    attributes:
      entities: >
       {{ states.zone | map(attribute='entity_id')|select|list }}

automation:

  alias: Update Destinations from Zones
  description: ''
  trigger:
  - platform: state
    entity_id: sensor.zones
    id: state_changed
  condition: []
  action:
  - service: input_select.set_options
    target:
      entity_id: input_select.destination
    data:
      options: '{{ states.zone | map(attribute="name") | list }}'
  - service: notify.persistent_notification
    data:
      title: Zones
      message: Waze destination list updated
  mode: parallel
  max: 20

This triggers if a zone is added or deleted or if a zone’s entity_id has changed.