Trigger automation when state_changed event fires but only if one specific attribute changes

Hello,

I’m trying to trigger an automation when a device tracker updates its state to a new state, but only if the new state has different GPS coordinates in comparison to the old state. I read a lot about events, old_state vs. new_state, event triggers but I couldn’t find the right hint.

Currently I’m stuck at this point:

- alias: "Get new parking position"
  trigger:
    - platform: event 
      event_type: state_changed
      event_data: 
        entity_id: device_tracker.audi_car
  condition:
    - condition: template
      # Only look at GPS Position Change
      # this is not working
      value_template: >
        {{ trigger.event.data.old_state.attributes.latitude is not trigger.event.data.new_state.attributes.latitude
           and trigger.event.data.old_state.attributes.longitude is not trigger.event.data.new_state.attributes.longitude }}
  action:
#notify

My trigger is working fine - every 10 minutes the device tracker is updated. But the condition is not working. I want to compare the GPS position of the old_state to the GPS position of the new_state in order to determine if there is a difference and I need to push the notification to my phone.
I know that the current code in the condition is completely wrong, but that’s where I’m stuck - I have an idea how to proceed but not the know-how to do it :frowning:

states.device_tracker.audi_car.attributes.latitude
states.device_tracker.audi_car.attributes.longitude

This is working fine to get the current GPS position of the car.
How do I get acces to the old_state vs. new_state event in the condition? Is there a better way to do this?

They’re called from_state and to_state. Oops! We’re talking about events here …

Have you used Developer Tools > Events > Listen to Events? It allows you to examine an event’s details.

Try:

      value_template: >
        {{ trigger.event.data.old_state.attributes.latitude !=
           trigger.event.data.new_state.attributes.latitude and
           trigger.event.data.old_state.attributes.longitude !=    
           trigger.event.data.new_state.attributes.longitude }}

Thank you @123 for your help!
Unfortunately it is still not working. My guess is the trigger.event.data… part as I’m not sure if this is even possible. How does the ‘value_template’ know which event it needs to access as no ‘entity_id’ is provided within the condition.

These are the event’s details:

{
    "event_type": "state_changed",
    "data": {
        "entity_id": "device_tracker.audi_car",
        "old_state": {
            "entity_id": "device_tracker.audi_car",
            "state": "not_home",
            "attributes": {
                "source_type": "gps",
                "latitude": 00.639696,
                "longitude": 00.332544,
                "gps_accuracy": 0,
                "model": "Audi",
                "model_year": "2020",
                "model_family": "Audi",
                "title": "Audi",
                "csid": "xxxxx",
                "vin": "xxxxx",
                "friendly_name": "Audi Position",
                "icon": "mdi:car"
            },
            "last_changed": "2020-10-03T16:41:21.592775+00:00",
            "last_updated": "2020-10-03T16:41:21.592775+00:00",
            "context": {
                "id": "xxxxx",
                "parent_id": null,
                "user_id": null
            }
        },
        "new_state": {
            "entity_id": "device_tracker.audi_car",
            "state": "not_home",
            "attributes": {
                "source_type": "gps",
                "latitude": 00.639696,
                "longitude": 00.332545,
                "gps_accuracy": 0,
                "model": "Audi",
                "model_year": "2020",
                "model_family": "Audi",
                "title": "Audi",
                "csid": "xxxx",
                "vin": "xxxx",
                "friendly_name": "Audi Position",
                "icon": "mdi:car"
            },
            "last_changed": "2020-10-03T16:51:25.082832+00:00",
            "last_updated": "2020-10-03T16:51:25.082832+00:00",
            "context": {
                "id": "xxxx",
                "parent_id": null,
                "user_id": null
            }
        }
    },
    "origin": "LOCAL",
    "time_fired": "2020-10-03T16:51:25.082925+00:00",
    "context": {
        "id": "xxxx",
        "parent_id": null,
        "user_id": null
    }
}

The automation is triggered when an event occurs with the following criteria:

      event_type: state_changed
      event_data: 
        entity_id: device_tracker.audi_car

That information is passed along as part of the Trigger State Object. In other words, the condition receives information only when the event is for entity_id: device_tracker.audi_car.

What do you mean exactly when you day “it is still not working”?

  • Is the automation never triggered?
  • If it is triggered, is the action always executed or never executed?

Sorry - my fault. To be more specific: the trigger works and always has - it is the condition that is either not working properly or I cannot really test this from the inside of home assistant.

How I test the automation:

  1. start listening to state_changed events in the developer event section
  2. load the device_tracker.audi_car entity in the service section.
  3. Change the GPS position to a new one and press: “set state”
  4. observe that event listener has recorded a state_changed, but the push notification is very inconsistent (there is no problem with push notifications - they are working fine)

I will evaluate this further during the day and try to fix this. Right now, sometimes I get a push notification, sometimes not. Right now, there is no pattern.
Thank you so much for your support so far!

If I understand what you are trying to do, you do not want to be notified if the car’s location remains unchanged, only if it changes.

Based on my experience with GPS receivers (for hiking), even when stationary the readings drift. For consumer-level GPS, best accuracy is simply a high probability of being within a 10 meter diameter area (and a dizzying array of environmental conditions can negatively impact the measurement). So if you were to examine the raw data from a stationary GPSR, the lat and long values would change over time.

You understood that completely right. Currently it seems to work fine with real car data - that’s all I need :slight_smile:
I think during my initial testing there was an issue with the Audi API so that no new state_changed events were created and somehow the internal testing within Home Assistant only triggered the first time a state was changed.

Interesting fact about the GPS receivers, I need to remember that for my next GPS automations. Based on the design of the car service I think I won’t be having the problem with GPS readings drifts. The car uploads its position one time when it is turned off. Every new request to update the GPS position of the car is only answered by the cached value at the Audi backend and not directly by the car, until you start driving again and new data is sent to the backend.

They probably use a technique to suppress drifting measurements when there’s no obvious velocity detected. The same algorithm is available for handheld GPSR and navigation apps for phones. Without it engaged, the recorded track looks like a “hairball” wherever you stopped moving (as if you were constantly shifting position by a few meters).

Anther curiosity of GPS navigation is that, for a given location on the earth’s surface, there are times of the day when accuracy is better … or worse. It has to do with the number of satellites available at that time and their orientation with respect to you (closely “bunched” or widely spaced). These times are predictable because each satellite’s orbit is available (downloaded to your GPSR when loading the satellite’s ephemeris data) and so it’s possible to calculate and determine the best/worst time based on their location.

In addition, vertical accuracy (more important to hikers and cyclists than motorists) isn’t nearly as good as horizontal accuracy. For elevation, a calibrated barometric altimeter is superior to a consumer-grade GPSR. That’s why some backcountry navigation apps offer the option to map your track to a 3D terrain model and use that to calculate your overall elevation gain (as opposed to what the track recorded for elevation at each track point). In practice, I’ve found this to produce results similar to a barometric altimeter. However, the accuracy of the calculated result depends on the accuracy of the 3D terrain model (so it may vary from one geographic location to another).

It happens to be one of those subjects that, when you scratch the surface, it reveals so much complexity that it’s a wonder GPS works as well as it does. :slight_smile:

… and I didn’t even touch upon SBAS (WAAS in North America).

1 Like