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

Finally have this working the way I had envisioned and hoped I could!
I am using Waze but that is somewhat beside the fact.
I tried all sorts of ways and means but this is the final working result which seems simple now!
First I created a new drop-down helper input_select.destination and preset it with Home.
Second is an automation to update the list based on Zones’ friendly names, and triggered by a state change in zones:

alias: Update Destinations
description: ''
trigger:
  - platform: event
    event_type: state_changed
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 | trim(",")] -%}
        {%- endfor %}
        {{ ns.items }}
mode: parallel
max: 25

The other part is a Waze selectable sensor destination:

sensor:
  - name: Destination address
    unique_id: dest_address
    state: "{{ states('input_select.destination') }}"
select:
  - name: Select Destination
    unique_id: select_destination
    state: "{{ states('input_select.destination') }}"
    options: "{{ state_attr('input_select.destination','options') }}"
    select_option:
      service: input_select.select_option
      target:
        entity_id: input_select.destination
      data:
        option: "{{ option }}"

image

image

1 Like

why do you have a trim there? There shouldn’t be a comma at the end of any zone name.

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

EDIT: I’d also probably change the trigger, but that’s just me. You can change it to occur on home assistant restart, zone reloading, and automation reloading.

You’re right, the trim(",") isn’t required. It was code I got from another thread. It was late and it worked so I didn’t test it further.

But how do I trigger on zone/automation reloading? I couldn’t find an answer to that…

  - platform: event
    event_type: call_service
    event_data:
      domain: zone
      service: reload

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
    }
}