Life360 Device Tracker Platform

Thanks for the info. I haven’t really looked at the code for most of those, but I have looked at the code for Google Maps Location Sharing. I’ll take a look at the others as well. Maybe I have missed something.

But one important point is, the device tracker component level code (i.e., the “higher level” code used for all device trackers) treats GPS-based platforms differently than network (aka router) and bluetooth platforms. The reason is that GPS-based platforms can report locations both in the home zone and out of it, whereas all the others can only report that the device is “home”. And more importantly for network and bluetooth platforms, the reverse is also true – i.e., they cannot report that a device is “not home.” Therefore, to make network & bluetooth platforms useful at all, the component level code implements a “consider home time” algorithm for them. I.e., if they haven’t reported for longer than that configured time period, then the component code makes them 'not_home'. If it didn’t do that then network and bluetooth platforms would be useless. And this algorithm is just a guess at best (and, BTW, is often wrong.) Also note that the component level code does not apply the same algorithm to GPS-based platforms.

So, for all your network (asuswrt, nmap, ping) and bluetooth trackers, they are actually not determining that the device is 'not_home'; that’s being done by the component level code based on the algorithm mentioned above when they stop reporting that the device is home.

Believe me, I hear you. It does seem as though the Life360 server can report that the device is “disconnected” (although it would seem it takes a long time before that happens – maybe several hours.) And the platform code could have some sort of timeout if the “last seen” timestamp hasn’t changed. But I think you keep missing the point – there’s no defined way for a platform to tell the component level code this, other than via the see() method, and simply by calling that method it’s effectively telling the component level code that the device has been seen – that’s what calling it means. And even if if that is done with a “location” (aka state) of something like 'offline', and/or with an attribute that indications a lost connection, again, simply by calling the function that will mess up the component level’s algorithms. That’s why I keep saying, if you want this to change, don’t tell me. Tell the HA developers by opening an issue on the device tracker component.

There’s a BIG difference with most of those components (asuswrt, nmap, ping, bluetooth). Those components check if a device is in one specific place (home) by seeing if the device is connected to a specific network (Wi-Fi, Bluetooth). They do not report where a device is in the world like GPS does, so they’re much more limited in scope and basically a binary/boolean type sensor. With that type or sensor, they HAVE to be either home or not_home, so if they aren’t connected to the network the assumption HAS to be they are not_home. I don’t think device trackers like those can be compared to GPS trackers in terms of state behavior.

Jinx! :smile: You definitely express the same ideas much more succinctly and eloquently.

:grin: @Mariusthvdb I hope you don’t feel like we’re ganging up on you, I think you have valid arguments I’m just not sure we’ve come up with a good solution yet!

1 Like

well, i hear both of you, and even understand what you’re saying. really. For me as and end-user though, it comes across somewhat as highly theoretical discussion.

In the end, I just need a tracker to be correct, not probably correct. As much as possible. The advantage of these non-binary trackers is they can be much more precise and elaborate. Thats why I am so happy with this component!
As we now experience, they can leave us even more in the mist than the binaries… they could be home, but they could be anywhere for that matter…I would think a truly intelligent implementation of that would be to signal it was last seen here and there, at that time, but we can’t say for sure, cause connection is lost.

So easy to implement if stepped over the theoretical boundaries of component definition… but that’s me, purely speaking as an end-user… so don’t take it bad please.

1 Like

No worries, Im good. hope you are too :wink: @pnbruckner is one of my main tutors here, so I am very grateful for all contributions!

1 Like

back again, for something completely different. Must be missing the obvious, but here goes:
for testing purposes Ive disabled all Custom components, also the life360 device_tracker and sensor.

However after restarting the host, and clearing cache et all, I still can see the life360 entities in my frontend. There’s only the basic info now, no driving , moving, etc, but the device_tracker is displayed, with correct icon from the life platform, and given the fact it also shows long/lat (next to source type, gps_accuracy and battery), it even shows the device is in a zone… Probably not up to date, but still.

How is this even possible??

This is a feature of the device tracker component. When platform code first “sees” a device the component level code will create the device_tracker entity and add a corresponding entry to the known_devices.yaml file (including any picture data provided by the platform level code.) When HA is restarted, the component level code will read known_devices.yaml and create a device_tracker entity for each entry (whose states should get at least partially restored from the database by the recorder.) This happens without any involvement by the platform level code.

Bottom line - if you want to get rid of a device_tracker entity, you need to change your configuration, and you need to remove the entity from known_devices.yaml (or at least comment it out.)

ok, thanks, I wasn’t aware of that at all. learn each and every day. cool.

1 Like

if I may, please let me ask what would be the best way to create an ‘overdue’ sensor on the individual devices? Should we do that based in the event overdue (I take it you havent re-considered adding an attribute overdue: true/false…) and if so how, or should we start calculating templates based on the ‘last_seen’ attribute maybe?

I know we must be able to create and set a binary sensor, but kind find it in my head…

- alias: Life360 Overdue Update
  trigger:
    platform: event
    event_type: device_tracker.life360_update_overdue
  action:
    service: .....

The device_tracker.life360_update_overdue event is probably easier to use for this. There’s an example on the doc page. It sends a notification in the action, but you could update in input_boolean instead.

If you’d rather create a template binary sensor, the problem will be you’ll need it to change some amount of time after last_seen doesn’t change, but template sensors update when something does change. You can work around this by using sensor.time to “drive” the updating of the sensor (i.e., it will cause the sensor to update every minute.) Maybe something like this:

binary_sensor:
  - platform: template
    sensors:
      my_tracker_overdue:
        friendly_name: My device tracker is overdue for an update
        entity_id: sensor.time
        device_class: problem
        value_template: >
          {{ as_timestamp(now()) -
             as_timestamp(state_attr('device_tracker.life360_me', 'last_seen')) >
             30*60 }}

EDIT: And since now() and last_seen are both timezone aware datetime.datetime objects, the value_template could also be:

        value_template: >
          {{ (now() - state_attr('device_tracker.life360_me', 'last_seen'))
             .total_seconds() > 30*60 }}

cool, both very good ideas!, the latter is what I specifically thought about indeed. Thanks. Had my head set at has.states.set(‘sensor.life360_overdue’, true) … thought to have seen something like that in yaml-syntax, but this would do just fine of course.
will try and test both boolean and binary.

**max_update_wait** ( *Optional* ): If you specify it, then if Life360 does not provide an update for a member within that maximum time window, the life360 platform will fire an event named device_tracker.life360_update_overdue with the entity_id of the corresponding member's device_tracker entity. Once an update does come it will fire an event named device_tracker.life360_update_restored with the entity_id of the corresponding member's device_tracker entity and another data item named wait that will indicate the amount of time spent waiting for the update. You can use these events in automations to be notified when they occur.

one couldn’t write a template based on the event overdue? The automations can use this {{ trigger.event.data.new_state }}based on the

  trigger: 
    platform: event
    event_type: device_tracker.life360_update_overdue

{{ trigger.event.data.new_state }} ?

That is something you’d have to do in a python_script, which I considered as another potential answer. E.g., if you had this python_script (let’s call it set_state.py, which I actually provided in another topic :slight_smile: ):

entity_id = data.get('entity_id')
if not entity_id:
    logger.error('No entity_id provided')
state = data.get('state')
if not state:
    logger.error('No state provided')
if entity_id and state:
    old_state = hass.states.get(entity_id)
    if old_state:
        attrs = old_state.attributes
    else:
        attrs = None
    hass.states.set(entity_id, state, attrs)

Then you could call it like this from an automation:

  action:
    service: python_script.set_state
    data_template:
      entity_id: "binary_sensor.overdue_{{ trigger.event.data.entity_id.split('.')[1] }}"
      state: 'on'

And of course another automation when the update is restored to turn the binary_sensor off.

1 Like

that would be the perfect template to change the color of the device_tracker into Problem-code. nice.and simple. was looking for a way to have the comparison evaluate the variable max_update_wait… but I don’t think that is available in the device_trackers state isnt it?

The device_tracker.life360_update_overdue event does not have new_state as event data, only entity_id. You’re thinking of a state_changed event.

No, it’s not exposed in a device_tracker attribute. Only the “usual” ones, and these additional attributes.

would this go also, and allow for only 1 automation:

- alias: Life360 connected
trigger:
- platform: event
event_type: device_tracker.life360_update_overdue
- platform: event
event_type: device_tracker.life360_update_restored
condition:
action:
service: python_script.set_state
data_template: >
{% set connected = trigger.event.data.entity_id.split(‘.’)[1] %}
entity_id: ‘binary_sensor.overdue_’ + connected
state: >
{{‘on’ if connected = ‘overdue’ else ‘off’}}

forget about that, didn’t realize it was the entity_id filtered out… back to rebuilding

I think you’d need to write it this way:

  - alias: Life360 connected
    trigger: 
      - platform: event
        event_type: device_tracker.life360_update_overdue
      - platform: event
        event_type: device_tracker.life360_update_restored
    action:
      service: python_script.set_state
      data_template:
        entity_id: >
          binary_sensor.overdue_{{ trigger.event.data.entity_id.split('.')[1] }}
        state: >
          {{ 'on' if trigger.event.event_type.endswith('overdue') else 'off' }}

EDIT: I think trigger.event.type needs to be trigger.event.event_type instead. Automation above updated accordingly.

1 Like

yes! thats what I was conjuring up indeed! nice. quick and clean. automatic binary_sensor creation, always something special.

I like it when something clean and a bit elaborate can shrink into something even cleaner and compact:

##########################################################################################
  - alias: Life360 disconnected
    trigger:
      platform: event
      event_type: device_tracker.life360_update_overdue
    condition: []
    action:
      service: python_script.set_state
      data_template: 
        entity_id: "binary_sensor.connected_{{ trigger.event.data.entity_id.split('.')[1] }}"
        state: 'on'

  - alias: Life360 reconnected
    trigger:
      platform: event
      event_type: device_tracker.life360_update_restored
    condition: []
    action:
      service: python_script.set_state
      data_template:
        entity_id: "binary_sensor.connected_{{ trigger.event.data.entity_id.split('.')[1] }}"
        state: 'off'

- alias: Life360 connected
    trigger: 
      - platform: event
        event_type: device_tracker.life360_update_overdue
      - platform: event
        event_type: device_tracker.life360_update_restored
    action:
      service: python_script.set_state
      data_template:
        entity_id: >
          binary_sensor.overdue_{{ trigger.event.data.entity_id.split('.')[1] }}
        state: >
          {{ 'on' if trigger.event.event_type.endswith('overdue') else 'off' }}

and, with these binary_sensors, we can color the device_trackers in to problem_color even easier!