Sorry, multiple things at work here, so it’s going to be a lengthy post.
First off, you need life360 and places. Then the images, my wife and I use an app called Bitmoji for those, and using the below png template and photoshop I created the different state images. You’ll want to set the circles to your lovelace background color and the rest to your default card color. Put them all in /www/images/person/
so that the Person_Status
sensor can reference them.
Then the sensors:
binary_sensors:
platform: template
sensors:
person_moving:
friendly_name: "Person Moving"
value_template: >-
{% if state_attr('device_tracker.life360_person', 'place') == state_attr('device_tracker.life360_person', 'address') %}
off
{% elif is_state_attr('device_tracker.life360_person', 'driving', true) %}
on
{% elif is_state_attr('device_tracker.life360_person', 'moving', true) %}
on
{% else %}
off
{% endif %}
sensors:
platform: template
sensors:
person_location:
friendly_name: "Person Location"
value_template: >-
{% if state_attr('device_tracker.life360_person', 'place') == state_attr('device_tracker.life360_person', 'address') %}
{{ state_attr('device_tracker.life360_person', 'place') }}
{% elif states.sensor.person.attributes.place_name != "-" %}
{{ state_attr('sensor.person', 'place_name') }}
{% else %}
{% if is_state('binary_sensor.person_moving', 'on') %}
{% if state_attr('sensor.person', 'street_number') != '-' %}{{ state_attr('sensor.person', 'street_number')}} {% endif %}{% if state_attr('sensor.person', 'street') != '-' %}{{state_attr('sensor.person', 'street')}}{% endif %}{% if state_attr('sensor.person', 'city') != '-' %}, {{state_attr('sensor.person', 'city')}}, {% if state_attr('sensor.person', 'state_province') != '-' %}{{state_attr('sensor.person', 'state_province')}}{% endif %}{% endif %}
{% else %}
{{ state_attr('sensor.michael', 'street_number') + " " + state_attr('sensor.michael', 'street')}}
{% endif %}
{% endif %}
person_status:
friendly_name: "Person Status"
value_template: >-
{% if is_state_attr('device_tracker.life360_person', 'driving', true) %}
Driving near {{ states('sensor.person_location') }}
{% elif is_state_attr('device_tracker.life360_person', 'moving', true) %}
Moving near {{ states('sensor.person_location') }}
{% else %}
{{ states('sensor.person_location') }}
{% endif %}
entity_picture_template: >-
{% if state_attr('sensor.person', 'place_type') == 'supermarket' %}
/local/images/person/grocery.png
{% elif state_attr('device_tracker.life360_person', 'place') == 'Work' %}
/local/images/person/work.png
{% elif state_attr('device_tracker.life360_person', 'place') == 'Home' %}
/local/images/person/home.png
{% elif state_attr('device_tracker.life360_person', 'driving') == true %}
/local/images/person/driving.png
{% elif state_attr('device_tracker.life360_person', 'moving') == true %}
/local/images/person/moving.png
{%else %} /local/images/person/home.png{%endif%}
person_at_loc_since:
friendly_name: "At Location Since"
value_template: >-
{% if (as_timestamp(now()) - as_timestamp(states.sensor.person_location.last_changed)) / 3600 < 24 %}
Since {{ (states.sensor.person_location.last_changed.strftime("%s") | int ) | timestamp_custom("%-I:%M %p") }}
{% else %}
Since {{ (states.sensor.person_location.last_changed.strftime("%s") | int ) | timestamp_custom("%a, %b %-d at %-I:%M %p") }}
{% endif %}
person_battery:
friendly_name: "Battery"
unit_of_measurement: '%'
value_template: "{{states.device_tracker.life360_person.attributes.battery }}"
icon_template: >-
mdi:battery{% if is_state_attr('device_tracker.life360_person', 'battery_charging', true) %}-charging{% else %}{% endif %}{% if 0<(state_attr('device_tracker.life360_person', 'battery') | float / 10 ) | round(0) * 10 < 100%}-{{ (state_attr('device_tracker.life360_person', 'battery') | float / 10 ) | round(0) * 10 }}{% else %}{% if (state_attr('device_tracker.life360_person', 'battery') | float / 10 ) | round(0) * 10 == 0%}-outline{%else%}{% if is_state_attr('device_tracker.life360_person', 'battery_charging', true) %}-100{% endif %}{% endif %}{% endif %}
person_wifi:
friendly_name: "WiFi"
value_template: >-
{% if is_state_attr('device_tracker.life360_person', 'wifi_on', true) %}
on
{% else %}
off
{% endif %}
icon_template: >-
{% if is_state_attr('device_tracker.life360_person', 'wifi_on', true) %}
mdi:wifi
{% else %}
mdi:wifi-off
{% endif %}
person_height:
value_template: >-
{% if is_state('binary_sensor.person_moving', 'on') %}
70px
{% else %}
40px
{% endif %}
Then the frontend code:
cards:
- card:
cards:
- elements:
- entity: '${''device_tracker.life360_'' + vars[0]}'
image: >-
"${states['sensor.' + vars[0]
+'_status'].attributes['entity_picture']}"
style:
left: 50%
top: 50%
width: 100%
type: image
- entity: '${''sensor.'' + vars[0] +''_battery''}'
style:
'--paper-item-icon-color': >-
${'hsl(' + (states['sensor.' + vars[0] +'_battery'].state*1.1
)*((states['sensor.' + vars[0] +'_battery'].state/100)) +
',90%,40%)'}
left: 4.5%
top: 3.5%
transform: 'scale(1.2,1.2)'
type: state-icon
- entity: '${''sensor.'' + vars[0] +''_wifi''}'
style:
'--paper-item-icon-color': '#2b9af9'
left: 80.5%
top: 3.5%
transform: 'scale(1.2,1.2)'
type: state-icon
image: '${''/local/images/'' + vars[0] +''/home.png''}'
type: 'custom:hui-picture-elements-card'
- color_type: icon
entity: '${''sensor.'' + vars[0] +''_status''}'
show_icon: false
show_name: false
show_state: true
tap_action:
action: url
url: '${states[''sensor.'' + vars[0]].attributes[''map_link'']}'
styles:
card:
- height: '${states[''sensor.'' + vars[0] +''_height''].state}'
state:
- padding-top: '${vars[2]}'
- padding-left: 14px
- padding-right: 14px
- white-space: '${vars[1]}'
- text-overflow: '${vars[1]}'
- word-break: break-word
type: 'custom:button-card'
- card:
color_type: icon
entity: '${''sensor.'' + vars[0] +''_at_loc_since''}'
show_icon: false
show_name: false
show_state: true
tap_action:
action: url
url: '${states[''sensor.'' + vars[0]].attributes[''map_link'']}'
styles:
card:
- height: 30px
state:
- padding-bottom: 14px
- font-size: 12px
type: 'custom:button-card'
conditions:
- entity: '${''binary_sensor.'' + vars[0] + ''_moving''}'
state: 'off'
type: conditional
type: 'custom:vertical-stack-in-card'
type: 'custom:config-template-card'
variables:
- '''person1'''
- >-
{if (states['sensor.' + vars[0] +'_height'].state ===
'70px')'unset';else 'nowrap'}
- >-
{if (states['sensor.' + vars[0] +'_height'].state === '70px')'4px';else
'14px'}
- card:
cards:
- elements:
- entity: '${''device_tracker.life360_'' + vars[0]}'
image: >-
"${states['sensor.' + vars[0]
+'_status'].attributes['entity_picture']}"
style:
left: 50%
top: 50%
width: 100%
type: image
- entity: '${''sensor.'' + vars[0] +''_battery''}'
style:
'--paper-item-icon-color': >-
${'hsl(' + (states['sensor.' + vars[0] +'_battery'].state*1.1
)*((states['sensor.' + vars[0] +'_battery'].state/100)) +
',90%,40%)'}
left: 4.5%
top: 3.5%
transform: 'scale(1.2,1.2)'
type: state-icon
- entity: '${''sensor.'' + vars[0] +''_wifi''}'
style:
'--paper-item-icon-color': '#2b9af9'
left: 80.5%
top: 3.5%
transform: 'scale(1.2,1.2)'
type: state-icon
image: '${''/local/images/'' + vars[0] +''/home.png''}'
type: 'custom:hui-picture-elements-card'
- color_type: icon
entity: '${''sensor.'' + vars[0] +''_status''}'
show_icon: false
show_name: false
show_state: true
tap_action:
action: url
url: '${states[''sensor.'' + vars[0]].attributes[''map_link'']}'
styles:
card:
- height: '${states[''sensor.'' + vars[0] +''_height''].state}'
state:
- padding-top: '${vars[2]}'
- padding-left: 14px
- padding-right: 14px
- white-space: '${vars[1]}'
- text-overflow: '${vars[1]}'
- word-break: break-word
type: 'custom:button-card'
- card:
color_type: icon
entity: '${''sensor.'' + vars[0] +''_at_loc_since''}'
show_icon: false
show_name: false
show_state: true
tap_action:
action: url
url: '${states[''sensor.'' + vars[0]].attributes[''map_link'']}'
styles:
card:
- height: 30px
state:
- padding-bottom: 14px
- font-size: 12px
type: 'custom:button-card'
conditions:
- entity: '${''binary_sensor.'' + vars[0] + ''_moving''}'
state: 'off'
type: conditional
type: 'custom:vertical-stack-in-card'
type: 'custom:config-template-card'
variables:
- '''person2'''
- >-
{if (states['sensor.' + vars[0] +'_height'].state ===
'70px')'unset';else 'nowrap'}
- >-
{if (states['sensor.' + vars[0] +'_height'].state === '70px')'4px';else
'14px'}
type: horizontal-stack
Hopefully you can follow all of that. Essentially it’s a horizontal stack with two configurable vertical-stack-in cards where if you’re life360 name and sensors names are all the same the only thing you need to do is drop in your name in the variables:
area.
I know there’s probably some cool ways to clean this up or do it better and am open to suggestions. If you have any additional questions feel free to ask.