Zone Detection

I am using the following code to detect when entering and leaving zones.

- id: "eb06e6ff-4908-4837-8e2b-dfa9cb8ef3cb"
  alias: "CWB Zone Notification"
  description: "CWB Zone Notification"  
  trigger:
  - platform: zone
    entity_id:    
    - device_tracker.cwb_phone
    zone: zone.xyz
    event: enter
  - platform: zone
    entity_id:    
    - device_tracker.cwb_phone
    zone: zone.xyz
    event: leave  
  - platform: zone
    entity_id:    
    - device_tracker.cwb_phone
    zone: zone.home
    event: enter
  - platform: zone
    entity_id:    
    - device_tracker.cwb_phone
    zone: zone.home
    event: leave
  action:
  - service: notify.brooks5123
    data:
      message: " {% if trigger.event == \"leave\" %}\n  {{ trigger.from_state.attributes.friendly_name\
        \ }} left {{ trigger.zone.attributes.friendly_name }}\n{% else %}\n  {{ trigger.from_state.attributes.friendly_name\
        \ }} arrived {{ trigger.zone.attributes.friendly_name }}\n{% endif %}\n"
  mode: queued  

The automation sort of works.
It detects me entering and leaving the zone but it will send about 10 to 20 notices in the space of two to three minutes. It also hase me constantly entering and leaving my home zone as well.

What item needs to be refined, or maybe someone can explain what is happening.
Any help would be greatly appreciated.

@carltonb
First thing I would add is this:

  condition:
    condition: template
    value_template: "{{ trigger.from_state.state != trigger.to_state.state }}"

Simple enough. Just makes sure that any trigger MUST be to another zone or ‘away’ (and will not trigger if you enter/exit a particular zone, such as HOME over and over) which can happen if you have bad signals or spotty connections.

If you still have issues with too many notifications add this as a second condition:

  - condition: template
    # Only run if more than 5 minutes since it last ran
    value_template: >-
      this.attributes.last_triggered is not defined or now() - this.attributes.last_triggered >= timedelta(minutes=5)

This will add a timeout of 5 minutes before another message is sent. You can change the value to whatever fits you needs.

Hope this helps.

Thank you, I will try it out for the next few days and let you know what happens.

With only a day’s testing seems to be better.
I have two questions though if you are able to answer them.

First is what causes this. Is it the phone constantly seeking through a router or constantly trying to connect.

The second part is so that I can understand, what does the code do. Can you explain the code. I sort of understand that last attribute the phone found is being redefined and a timer is being set.

Appreciate the help.

@carltonb
Although I can’t answer the WHY part with any authority or specific knowledge, my guess is that the HA app continues to seek out the best service, and in the process may fail to recognize that you haven’t actually moved from your WORK zone to AWAY, triggering another message. The first condition:

{{ trigger.from_state.state != trigger.to_state.state }}

forces the automation to look for a change in locations. For example from WORK to AWAY. If there was a drop of signal or a change in cell towers, the automation would not fire if your location went from WORK to WORK, but will fire for WORK to AWAY.
The second condition put a time delay in how often the automation can actually fire.

this.attributes.last_triggered is not defined or now() - this.attributes.last_triggered >= timedelta(minutes=5)

can be made a little more readable (and functionally equal) by changing it to this:

# Only run if more than 5 minutes (900 sec) since it last ran
value_template: >-
  {{(as_timestamp(now(),0) - as_timestamp(state_attr("automation.NAMEOFYOURAUTOMATION", "last_triggered"),0) | int > 900 )}}
# Now as a timestamp value MINUS the timestamp value of the last trigger of your automation.
# The resulting number (as an INT) is the seconds elapsed. If Greater than COMPARISON VALUE (900) then TRUE. Automation continues. If FALSE, automation STOPS.

As you may notice, there are some subtle differences between the newer way and the old way of writing this, but both work the same for what you are trying to do. There are also two ways to write the older version, which can be seen in the two other examples below. I prefer the second way, for both readability and not having to enclose everything in quotes. Beware of using ’ to enclose the template and ’ to define entity and attributes. See the " in the example above.

'{{(as_timestamp(now(),0) - as_timestamp(state_attr('automation.NAMEOFYOURAUTOMATION', 'last_triggered'),0) | int > 900 )}}'

The above line WILL FAIL! Single quote enclose the entire template AND single quotes define the entity and attribute.

Using both should greatly reduce the number of False notifications but may block a notification if you move from zone to zone with a short interval of staying at any location. Do keep in mind, if you drive in and out of a zone, you will get the ENTER notification but NOT the EXIT (unless your drive is greater than 5 minutes). Personally, I do not use the delay on all my zone automations for that reason, but I think it is a useful tool if you get way too many triggers.

There are also many opportunities to use this condition to your advantage. Consider this Rain Nearby notification:

  - condition: template
    # Only run if more than 2 hours (7,200 sec) since it last ran
    value_template: '{{(as_timestamp(now(),0) - as_timestamp(state_attr("automation.its_raining_nearby", "last_triggered"),0)> 7200 )}}'

or this HVAC automation

    - condition: template
      # Only run if more than 60 seconds since it last ran, eliminates repeat trigger events
      value_template: >-
        {{(as_timestamp(now(),0) - as_timestamp(state_attr("automation.hvac_set_mode_1", "last_triggered"),0) | int > 60 )}}

I hope this explanation helps you build a better automation experience in your home. I have learned many of these gems from other users here, so I am not the guru, but I do like trying to give back when I can. If my answers have helped you fix your problem, please remember to make it as a solution so others can benefit from it.

Thank you sooo much for taking the time to explain this.
This will come in handy. Last night we had a storm and I have setup an automation to notify of lightning strikes. Got 15 of them in a matter of two minutes.
With the code you displayed this should mitigate seeing more than one message per coded set time period.

@kartcon The first condition I could insert into the automations.yaml.
but the second condition, is not working for me. or it tells me the wrong indentiation and I can’t get it to work. sometimes it tells me duplicate value.


can you show me the correct way to insert into the yaml code?

condition:
  - condition: template
    value_template: "{{ your code }}"
  - condition: template
    value_template: >-
      "{{ more of your code }}"

Thank you.
No errors , but second condition does not work🥲

Can you paste your template code? It’s hard to work off an image. :blush:

- id: '1712923370598'
  alias: reg_googleSheets
  description: ''
  trigger:
  - platform: zone
    entity_id: person.one
    zone: zone.oft
    event: enter
    id: Frank Entered
  - platform: zone
    entity_id: person.one
    zone: zone.oft
    event: leave
    id: Frank Left
  condition:
  - condition: template
    value_template: '{{ trigger.from_state.state != trigger.to_state.state }}'
  - condition: template
    # Only run if more than 5 minutes since it last ran
    value_template: >-
      this.attributes.last_triggered is not defined or now() - this.attributes.last_triggered >= timedelta(minutes=5)
  action:
  - if:
    - condition: trigger
      id:
      - Frank Entered
    then:
    - service: google_sheets.append_sheet
      metadata: {}
      data:
        data:
          action: Entered
        config_entry: e7d021d32a03c842496bf47f1c7a991b
    else:
    - service: google_sheets.append_sheet
      metadata: {}
      data:
        config_entry: e7d021d32a03c842496bf47f1c7a991b
        data:
          action: Left
  mode: single