An Impossible Zigbee Tile Card?

I have a lot of Zigbee contact sensors around the home and use the Tile Card to show their state, and last opened.
image
Using the Card-Mod, the Icon color changes according to the state of the contact (open=red, closed=green, unknown=yellow). And with a Trigger Sensor, it keeps track of the last time the sensor was opened.

But these Zigbee sensors expose more information that I’d like to track in the same compact tile card:
Battery Level
Signal Strength

I tried the Entites card with just a single entity, but the last trigger time only updates every few minutes, I could only show either battery level or signal strength on the right (not both), and that card is a lot taller than a Tile Card.

Mushroom-card is slightly better with templatable primary and secondary info, but it seems to be a resource hog and updated really slowly.

Anyone have ideas where/what to try next?

Thanks!

Can’t you just add these attributes as part of a list under the state_content key (if editing the raw YAML code - not sure what that looks like in the UI Edit view) on the Tile card?

The documentation has a couple of examples that look similar to what you want to achieve at least.

Something like:

type: tile
entity: binary_sensor.your_entity
state_content:
  - last_changed
  - battery_level
  - signal_strength
1 Like

I previously read that in the Tile card docs and it flew right over my head!
This ‘almost’ works now. Problem is the last-open timestamp reports last reboot as well as last time contact was opened.

Tile on left shows actual time the contact was opened, while the one on the right shows time of last reboot.

This is my trigger template for last_opened:

  # Test Contact Sensor Last Opened
  - trigger:
      - platform: state
        entity_id:
          - binary_sensor.test_contact_sensor_contact
        to:
          - "on"
    sensor:
      - name: "Test_Contact_Sensor_Last_Open"
        device_class: timestamp
        state: "{{ now() }}"

This is my sensor template to roll up everything into a single sensor with multiple attributes:

  - platform: template
    sensors: 
      my_test_contact:
        friendly_name: "My Test Contact"
        value_template: "{{ states('sensor.test_contact_sensor_last_open') }}"
        attribute_templates:
          battery: "{{ states('sensor.test_contact_sensor_battery') }}"
          open: "{{ states('binary_sensor.test_contact_sensor_contact') }}"
          last_open: "{{ states('sensor.test_contact_sensor_last_open') }}"

And finally the ui-lovelace.yaml for displaying all the info:

          - type: tile
            entity: sensor.my_test_contact
            icon: mdi:exit-run
            name: Test Contact Sensor
            state_content:
              - last_changed
              - open
              - battery
            card_mod:
              style: |
                ha-state-icon {
                  {% if is_state('binary_sensor.test_contact_sensor_contact','off') %}
                    color: green;
                  {% elif is_state('binary_sensor.test_contact_sensor_contact','on') %}
                    color: red;
                  {% else %}
                    color: yellow;
                  {% endif %}
                }

Gotta be something stupid I’m missing.

Thanks!

Apologies if this is another deadend, but does it work the way you want if you use last_updated instead of last_changed?

Both last_changed and last_updated appear to behave exactly the same:

  • Shows time since sensor was ‘on’ (opened) between HA Restarts
  • On reboot, shows time since last HA Restart

Default Tile Card always shows time since last ‘on’ (open) contact:

          - type: tile
            entity: sensor.test_contact_sensor_last_open
            icon: mdi:exit-run
            name: Test Contact Sensor
            card_mod:
              style: |
                ha-state-icon {
                  {% if is_state('binary_sensor.test_contact_sensor_contact','off') %}
                    color: green;
                  {% elif is_state('binary_sensor.test_contact_sensor_contact','on') %}
                    color: red;
                  {% else %}
                    color: yellow;
                  {% endif %}
                }

I should have known this really - the difference between the 2 is explained very clearly in this thread, but both values get reset when you restart HA, the reason for which is explained here.

Sorry, I don’t think I have a solution for this.

Thanks for your help!

It is odd, because if I remove the ‘state_content’ lines from the Tile, then it shows the correct time since the contact was last opened.

And both the sensor.test_contactor_sensor_last open and sensor.my_test_contact have matching timestamps in their states.

But, since I have ‘last_open’ as an attribute in ‘sensor.my_test_contact’, is it possible for format it in the ‘state_content’ list to match the output of the simple Tile card?

This almost works, it only updates about every minute instead of the default Tile behavior of updating every second for the first 45 seconds, then every minute, hours, etc…

  - platform: template
    sensors: 
      my_test_contact:
        friendly_name: "My Test Contact"
        value_template: "{{ states('sensor.test_contact_sensor_last_open') }}"
        device_class: timestamp
        attribute_templates:
          battery: "{{ states('sensor.test_contact_sensor_battery') }}"
          open: "{{ states('binary_sensor.test_contact_sensor_contact') }}"
          link_quality: "{{ states('sensor.test_contact_sensor_linkquality') }}"
          last_open: >-
             {% with mytime = (as_timestamp(now()) - as_timestamp(states('sensor.test_contact_sensor_last_open'))) | int  %}
               {% if (mytime // 2419200) > 0 %}
                 {{ '{} months ago '.format(mytime // 2419200) }}
               {% elif (mytime // 604800) > 0 %}
                 {{ '{} weeks ago'.format(mytime // 604800) }}
               {% elif (mytime // 86400) > 0 %}
                 {{ '{} days ago'.format(mytime // 86400) }}
               {% elif (mytime // 3600) > 0 %}
                 {{ '{} hours ago'.format(mytime // 3600) }}
               {% elif (mytime // 60) > 0 %}
                 {{ '{} minutes ago'.format(mytime // 60) }}
               {% elif (mytime // 1) > 0 %}
                 {{ '{} seconds ago'.format(mytime // 1) }}
               {% else %}
                 {{ 'Unknown' }}
               {% endif %}
             {% endwith %}
1 Like

There’s a time_since function/filter in Home Assistant templates which might help you make your code a little more compact

1 Like