Hat der Postbote schon wieder nicht geklingelt und einfach abgelegt? (Markdown Karte/Templating/last_changed/HA Neustart)

Wir bestellen viel und die Qualität der Zusteller schwankt. Sogar in der Papiertonne draußen hatten wir schon mal ein Päckchen abgelegt bekommen. Selten wird geklingelt. Leider schwächelt mittlerweile auch DHL und das obwohl wir sogar einst einen Paketkasten zugelegt hatten. Ich ärgere mich jedes Mal.

Wie auch immer, ich hab mir eine Karte auf dem Dashboard platziert, die mir die 3 wichtigsten Zeiten anzeigt.

Screenshot 2024-12-18 220948

Die Zeiten beziehen sich auf last_changed. Was mir nicht bewußt war (aber eigentlich logisch), daß ein HA Neustart diese Zeit verändert und dann der letzte Zeitzpunkt des Neustarts angezeigt wird und nicht die der letzten Bewegung.
Ich hab mir dann so beholfen, daß ich sage prüfe ob die Zeit mit dem letzten Neustart zusammenfällt in einem +/- 5 min Zeitfenster.

Für Template Willige zum Experementieren:

{% set now = now().astimezone() -%}
{% set uptime_time = states('sensor.uptime') | as_datetime | as_local -%}
{% set last_boot_time = states('sensor.system_monitor_last_boot') | as_datetime | as_local -%}
{% set time_window_restart_sec = 300 -%}
{% set color_active = 'green' -%}
{% set color_inactive = 'grey' -%}

{% macro format_time(entity) -%}
  {% set last_changed = states[entity].last_changed.astimezone() -%}
  {% set days_diff = (now.date() - last_changed.date()).days -%}
  {% set output = "" -%}

  {# Relative Zeit #}
  {% if days_diff == 0 -%}
    {% set output = "Heute" -%}
  {% elif days_diff == 1 -%}
    {% set output = "Gestern" -%}
  {% elif days_diff == 2 -%}
    {% set output = "Vorgestern" -%}
  {% else -%}
    {% set output = "Vor " ~ days_diff ~ " Tagen" -%}
  {% endif -%}

  {# HA Neustarts #}
  {% set uptime_diff = (last_changed - uptime_time).total_seconds() -%}
  {% set boot_diff = (last_changed - last_boot_time).total_seconds() -%}
  {% if (uptime_diff | abs <= time_window_restart_sec) or (boot_diff | abs <= time_window_restart_sec) -%}
    {% set output = output ~ "*" -%}
  {% endif -%}
  {{ output }}
{% endmacro %}

{% set last_changed_a = states.binary_sensor.hue_beweg_draussen_gartenhuette_occupancy.last_changed %}
{% set a = last_changed_a.strftime('%H:%M Uhr') | trim ~ ' (' ~ format_time('binary_sensor.hue_beweg_draussen_gartenhuette_occupancy') | trim ~ ')' %}
{% set my_color = color_inactive if '*' in a else color_active %}
<b>Letzte Bewegung in der Gartenhütte:</b>
<font size=4 color="{{ my_color }}">  {{ a }}</font>

{% set last_changed_b = states.binary_sensor.hue_beweg_draussen_rasen_occupancy.last_changed %}
{% set b = last_changed_b.strftime('%H:%M Uhr') | trim ~ ' (' ~ format_time('binary_sensor.hue_beweg_draussen_rasen_occupancy') | trim ~ ')' %}
{% set my_color = color_inactive if '*' in b else color_active %}
<b>Letzte Bewegung am Rasen:</b>
<font size=4 color="{{ my_color }}">{{ b }}</font>

{% set last_changed_c = states.binary_sensor.aqara_vibration_unten_klingel_vibration.last_changed %}
{% set c = last_changed_c.strftime('%H:%M Uhr') | trim ~ ' (' ~ format_time('binary_sensor.aqara_vibration_unten_klingel_vibration') | trim ~ ')' %}
{% set my_color = color_inactive if '*' in c else color_active %}
<b>🔔 Letzte Mal geklingelt:</b>
<font size=4 color="{{ my_color }}">  {{ c }}</font>


<font color="{{color_inactive}}">
{{'(*) Zeit entstand eher durch einen Neustart von Homeassi' if '*' in a or '*' in b or '*' in c }}
</font>

PS1: Eigentlich sollte ich noch die invaliden Stati {% set invalid_stati = [‘unknown’, ‘none’, ‘unavailable’] -%} abfangen aber mache ich später.

PS2: Die beiden grünen Zeiten entstanden als ich mir vorhin ein kaltes Bier geholt habe. Mit nur einem Bier kommen mir immer Ideen, Prost :beers:

PS3: Ich rede auch nett mit Postboten aber die ändern sich ständig.

Vorschläge zum Code / Herangehensweise sind immer willkommen!

3 „Gefällt mir“

Nachtrag (da ich den Beitrag nicht mehr editieren kann)

| as_local fehlt oben bei den Sensoren.

zum Beispiel:

{% set last_changed_a = states.binary_sensor.aqara_vibration_unten_klingel_vibration.last_changed | as_local %}

Sry aber der Alltag schleift alles rund.

Um das Problem mit dem Neustart und last_changes zum umgehen, könntest du das nicht in einen oder mehrere Trigger Based Template Sensor umbauen? Dieser behält nämlich die Werte bei, auch nach einem Neustart oder wenn das Gerät aussteigt.

Ich nutze die für die Tintenstände meines Druckers, so dass die angezeigt werden auch wenn der Drucker aus ist und dadurch die IPP-Integration nicht verfügbar.

Ja, eine gute Idee. Ich hätte dann in meinem Fall 3 neue Sensoren. Ich laß mir das mal durch den Kopf gehen.

Falls du mit meiner Idee etwas anfangen konntest, dann halte mich gerne auf dem Laufenden.

Ja, mache ich. Ich habs auch wirklich verstanden. Nutze bereits in einem Fall (bereinigter Stromverbrauch) ein trigger based Template Sensor in der configuration.yaml. Wenn ich es mache, würde ich wohl eher eine Automatisation nehmen, da nicht so häufig getriggert wird als bei jeder Wattänderung.
Was die Lehre aus obigen Beispiel war, daß man last_changed nicht einfach als richtig hinnehmen kann. Du löst es über Zwischenspeichern der letzten Sensorwerte bzw. Zeiten und obige über Prüfung gegen Zeitpunkt des letzten HA Neustarts.

Prima, es interessiert mich auch um meiner selbst willen, ob meine Ideen funktioniert haben.

Evtl. habe ich einen Denkfehler, aber du brauchst doch eigentlich keine zusätzliche Automatisierung? Als Trigger des jeweiligen Trigger Based Template Sensor kannst du doch direkt die Änderung der “echten” Sensoren verwenden. Klingeln oder Bewegung. Dadurch aktualisieren sich deine 3 zusätzlichen Sensoren doch automatisch.

Jetzt ist meine Neugierde mehr erwacht :slight_smile: Zeig doch bitte ein Beispiel um auszuschließen, daß wir nicht aneinander vorbeireden.

Ja, gerne. Hier am Beispiel eines Sensors für die schwarze Tinte. In der templates.yaml (ist aus der configuration.yaml mit !include ausgelagert):


## Sensor zum speichern des Tintenfüllstands schwarz ##
- trigger:
    - trigger: state
      entity_id:
        - sensor.ORIGINAL_black_ink
  sensor:
    - name: Tinte 405 Schwarz
      unique_id: ink-405-black
      state: |
        {{ iif(is_state('sensor.ORIGINAL_series_black_ink', 'unavailable'), states('sensor.tinte_405_schwarz'), states('sensor.ORIGINAL_black_ink')) }}
      state_class: measurement
      unit_of_measurement: "%"
      icon: >
        {% if states('sensor.tinte_405_schwarz') | float(0) < 11 %}
          mdi:water-percent-alert
        {% else %}
          mdi:water
        {% endif %}

Das State Template bestimmt, dass wenn der „Original“ Sensor nicht verfügbar ist, der State des Trigger Based Template Sensor angezeigt wird. Dessen State wird bei jeder Änderung des States des „Original“ Sensors aktualisiert. Ich hoffe es ist verständlich ausgedrückt. Du müsstest dann noch das Template entsprechend anpassen, dass der Neustart den State nicht wieder überschreibt. Da wüsste ich aktuell leider nicht wie.

Ja, wir reden vom Gleichem. Danke

Hier wird der neue Sensor “sensor.tinte_405_schwarz” angelegt zusätzlich zu dem altem “sensor.ORIGINAL_black_ink”. Das meinte ich vorhin.

Als Vorteil von so einem trigger based template senor Ansatz sehe ist:

  • Es ist performanter als eine Automation getriggerte Befüllung des neuen Sensors.

Nachteile:

  • Editieren in der config.yaml ist fehlernafälliger und wenn man mal durchstartet ohne vorige Prüfung, starte HA nicht im ungünstigen Fall (leider eigene Erfahrung)
  • Die Auswirkungen von Fehler in einem eigenem UI Sensor oder in der Automatisation bleiben auf sich beschränkt. Es sei denn man macht ganz großen Unfug :wink:
  • Alle Sensoren in die config.yaml verlangsamt irgendwann den Start (geraten)
  • Selbst kleine Änderungen brauchen immer einen Neustart.

Ich denke, der trigger based template sensor Ansatz macht Sinn, wenn das Triggern sekündlich oder mehrfach die Minute stattfindet.

PS: Laß Deinen Sensor so wie er ist. Er funktioniert. Wir reden hier nur über Ansätze.

Ja, ich verwende diesen für alle Farben. Dann habe ich noch einen für benutzerdefinierte Tageszeiten und für die Zeitumstellung. Bisher laufen alle ohne Probleme. Ich bin sehr zufrieden.

Nach dem anlegen und vor dem Neustart kann man ja die yaml-Konfiguration prüfen. Das bewahrt einen vor unnötigen Fehlern, falls man beim anlegen geschlampt hat.

War ja auch nur eine Idee für deinen Fall.