Telegram-Benachrichtigungen nur an Personen schicken, die zu Hause sind

Hallo zusammen,

ich lasse mich über Telegram darüber benachrichtigen, wenn ein Fenster länger als 10 Minuten geöffnet ist, damit es händisch geschlossen wird.
Grundsätzlich funktioniert das auch sehr gut, allerdings ist die Benachrichtigung meistens nur dann sinnvoll ist, wenn man auch zu Hause ist. Personen, die unterwegs sind, interessiert es dann ja nicht.

Die Automatisierung sieht dafür wie folgt aus:

alias: "Telegram: Benachrichtigung - Bürofenster schließen"
description: ""
trigger:
  - type: opened
    platform: device
    device_id: 31a75f6bf3b71d1a98d6052d42f5b2c8
    entity_id: binary_sensor.sensor_buerofenster_contact
    domain: binary_sensor
    for:
      hours: 0
      minutes: 10
      seconds: 0
condition:
  - condition: state
    entity_id: input_boolean.fensterkontakte_aktiv
    state: "on"
action:
  - data:
      target:
        - TELEGRAM-ID-PERSON-1
        - TELEGRAM-ID-PERSON-2
      title: <strong>Bürofenster schließen!</strong>
      message: Das Fenster im Büro ist seit 10 Minuten geöffnet.
      parse_mode: html
      inline_keyboard: ⌨️ Menü öffnen:/start
    alias: Telegram - Bürofenster schließen!
    action: telegram_bot.send_message
mode: single

Meine Idee ist es jetzt, das dynamisch umzusetzen, ohne dabei jede Automatisierung in Zukunft(!) bei möglichen Änderungen der Personen nochmal anpassen zu müssen.

Jede Person bei mir hat einen HA-Benutzer.
Ob die Person in der “home”-Zone ist, ermittel ich über Google Maps. Dadurch haben die Benutzer (zum Beispiel die Entität “person.julian”) den Zustand “home”, wenn diese zu Hause sind.

Das Ziel ist jetzt, dass nur jene Telegram-IDs benachrichtigt werden, die in der Zone “home” sind.

Ich habe schon einiges versucht, wie zum Beispiel mit Templates und Skripten zu arbeiten, aber das hat bisher alles nicht funktioniert.

Vielleicht hat ja jemand von euch eine Idee, wie ich das am flexibelsten umgesetzt bekomme :slight_smile:

LG
Julian

Ich wüsste nur den Weg über Bedingungen:

if:
  - condition: state
    entity_id: person.misterx
    state: home
then:
  - action: notify.notify
    metadata: {}
    data: {}

Halt für jede Person und mit dem richtigen Benachrichtigungsdienst.

Hey Gunter,

ja, diese Möglichkeit ist mir auch bekannt, allerdings ist das dann statisch in jeder einzelnen Automation hinterlegt, was einen sehr hohen Wartungsaufwand bedeutet.
Deswegen möchte ich das möglichst dynamisch gestalten.

LG
Julian

Du könntest ein Script erstellen, in dem du für jede Person die von Gunter gezeigte Bedingung einbaust und die Message eine Variable ist.
In deiner Automation rufst du dann das Script auf und übergibst deinen Benachrichtigungstext an das Script
Automation:

  - action: script.benachrichtigung_universell
    data:
      message_text: "Was auch immer"   

Script:

if:
  - condition: state
    entity_id: person.misterx
    state: home
then:
  - action: notify.notify
    metadata: {}
    data:
      message: |
        {{ message_text }}

Dann hast du nur eine Stelle, an der du Personen ergänzen oder ändern musst.

Ich bin aktuell am Basteln, da ich die Fragestellung interessant finde. Aktuell habe ich einen Template-Sensor erstellt, der mir die alle ID der anwesenden Personden ausgibt. Meine Idee ist, dann daraus in der Automation eine Liste zu erstellen, die Aktion entsprechend der Elemente in der Liste zu wiederholen und den Service dementsprechend anzupassen. Also das im ersten Durchlauf bspw. notify.person1 und im zweiten notify.person2 steht. Ob das möglich ist, weiß ich nicht. Werde ich im späteren Verlauf mal Testen.

Über den hausinternen notify Dienst geht es so:

action:
  - service: notify.iphones
    data:
      message: Fenster ist offen!
      data:
        mode: only_home

Hier kommt die funktionierende Lösung (zumindest verliefen die Tests bei mir positiv :wink: ).

  1. Erstelle dir einen Template-Sensor über die GUI mit folgendem Inhalt:
{% set personen = states.person | selectattr('state','eq', 'home') | map(attribute='attributes.id') | list %}
{{ personen | join(', ') }}
  1. Füge folgenden Code mit den für dich passenden Anpassungen in deine Automation ein:
action:
  - variables:
      anwesende_personen_list: "{{ states('sensor.personen_zu_hause').split(', ') }}"
  - repeat:
      count: "{{ anwesende_personen_list | length }}"
      sequence:
        - action: |
            notify.{{ anwesende_personen_list[repeat.index - 1] }}
          metadata: {}
          data:
            title: Test Test
            message: >-
              Hallo {{ anwesende_personen_list[repeat.index - 1] }}! Du bist
              anwesend.
mode: single

Nur um sicher zu gehen, sollte für Telegram folgendes in der configuration.yaml stehen (natürlich mit den passenden Daten):

# Telegram Bot
telegram_bot:
  - platform: polling
    api_key: "DEINE API"
    allowed_chat_ids:
      - *die erlaubten CHAT-IDs*

notify:
- platform: telegram
  name: "person1"
  chat_id: 1234567

- platform: telegram
  name: "person2"
  chat_id: 7654321

Wichtig ist, dass die Notifier-Namen mit den Personen übereinstimmen. Heißt: Wenn eine Person Julian heißt, muss es wie folgt ausschauen:

- platform: telegram
  name: "Julian"
  chat_id: 1234567

Dank geht an mjkvaak mit seinem Beitrag aus der HA-Community. Ein wenig hat auch ChatGPT dazu beigesteuert. In Summe werden somit automatisch alle anwesenden Benutzer benachrichtigt, für die Telegram eingerichtet ist. Eine einmalige Einrichtung in der configuration.yaml genügt und es bekommen alle anwesenden Personen via Telegram eine Benachrichtigung.

nur interessenhalber. Warum nicht die einfache version über notify der companion app?

Vielen Dank für eure Unterstützung! :blush:

@Gunter:
Das funktioniert schon sehr gut!
Es gibt nur eine Kleinigkeit, bei der ich gerade noch Probleme habe, und zwar scheinen in diesem Fall weitere Parameter wie inline_keyboard nicht mehr zu funktionieren.

Mein Code dazu sieht wie folgt aus:

action: |
  notify.{{ anwesende_personen_list[repeat.index - 1] }}
metadata: {}
data:
  title: '*Bürofenster schließen!*'
  inline_keyboard: '⌨️ Menü öffnen:/start'
  message: Das Fenster im Büro ist seit 10 Minuten geöffnet.

Sobald ich inline_keyboard hinzufüge, funktioniert die Benachrichtigung nicht mehr.
Gibt es dafür eine Lösung?

@Burnz:
Mein Home Assistant ist von extern aus bewusst nicht erreichbar und eventuell möchte ich später auch Personen in anderen Automationen benachrichtigen können, die gerade unterwegs sind. :slight_smile:

LG
Julian

action:
  action: notify.NOTIFIER_NAME
  data:
    title: "*Send a message*"
    message: "That's an example that _sends_ a *formatted* message with a custom inline keyboard."
    data:
      inline_keyboard:
        - 'Task 1:/command1, Task 2:/command2'
        - 'Task 3:/command3, Task 4:/command4'

In der offiziellen Doku zu Telegram von HA ist noch ein data: und dann das inline_keyboard inkl. der Commands. Vielleicht hilft das?

Das habe ich jetzt versucht und mir dazu auch die Doku angeschaut, aber leider bringt das auch keine Veränderung.

action: notify.{{ anwesende_personen_list[repeat.index - 1] }}
data:
  title: "*Bürofenster schließen!*"
  message: Das Fenster im Büro ist seit 10 Minuten geöffnet.
  data:
    inline_keyboard: 'ok:/test'

LG
Julian

Deine Version weicht aber leicht von der offiziellen ab. Die offizielle macht:

inline_keyboard:
        - 'Task 1:/command1

Du:

inline_keyboard: 'ok:/test'

Aktuell bin ich unterwegs und kann es nicht testen. Aber Kleinigkeiten können manchmal den Unterschied machen.

Ja, das habe ich auch schon versucht, leider erfolglos :sweat_smile:

Du kannst die Zone Home verwenden um die anwendenden Personen zu ermitteln.

{{ state_attr('zone.home', 'persons') }}

Das Ergebnis ist eine Liste aller Personen in der Zone Home.
Jetzt musst Du nur noch die Person Entitäten gegen die zugehörigen Telegramm-ID ersetzen. Und kannst Diese Liste als Target Template verwenden.

{{ state_attr('zone.home', 'persons') | replace("person.1","Id-1") | replace("person.2","ID-2") | replace("person.3","ID-3")}}

So sehe dann die Automatisierung aus:

alias: "Telegram: Benachrichtigung - Bürofenster schließen"
description: ""
trigger:
  - type: opened
    platform: device
    device_id: 31a75f6bf3b71d1a98d6052d42f5b2c8
    entity_id: binary_sensor.sensor_buerofenster_contact
    domain: binary_sensor
    for:
      hours: 0
      minutes: 10
      seconds: 0
condition:
  - condition: state
    entity_id: input_boolean.fensterkontakte_aktiv
    state: "on"
action:
  - data:
      target_template: |
        {{ state_attr('zone.home', 'persons') | replace("person.1","Id-1") | replace("person.2","ID-2") | replace("person.3","ID-3")}}
      title: <strong>Bürofenster schließen!</strong>
      message: Das Fenster im Büro ist seit 10 Minuten geöffnet.
      parse_mode: html
      inline_keyboard: ⌨️ Menü öffnen:/start
    alias: Telegram - Bürofenster schließen!
    action: telegram_bot.send_message
mode: single

Gruß
Osorkon

Hey @Osorkon ,

deine Automatisierung ist zwar auch smart gelöst. allerdings müsste ich dann jede einzelne Automation, die ähnlich aufgebaut wäre, zukünftig nochmal bearbeiten, wenn weitere Personen benachrichtigt werden sollen, oder übersehe ich da etwas?

LG
Julian

Gibt es mehrere Möglichkeiten, wenn das Template an mehreren Stellen Verwendung findet.

Entweder erstellst Du Dir ein macro.
Zusätzliche Personen passt Du dann nur noch ausschließlich über das marco an

#/custom_templates/personen_zone.jinja
{% macro telegramm_id(zone_id) %}
{{ state_attr(zone_id, 'persons') | replace("person.1","Id-1") | replace("person.2","ID-2") | replace("person.3","ID-3")}}
{% endmacro %}

Und verwendest dann dieses in Deinen Automatisierungen.

  target_tempalte: |
    {% from 'personen_zone.jinja' import telegram_id %}
    {{ telegram_id('zone.home') }}

Wenn Du neue macros erstellen tust oder ändern tust, musst Du entweder alle Konfigurationen neu laden oder die Aktion homeassistant.reload_custom_templates ausführen.

Oder Du erstellst Dir einen Template Sensor, dann musst Du nur den Template Sensor anpassen. Und rufst als Target, dann den Template Sensor auf.

Das macro, würde ich persönlich vorziehen. Dann kannst Du auch andere Zonen als nur die home Zone verwenden.

Gruß
Osorkon

Hey Osorkon, danke für deinen Code!

Leider funktioniert es bei mir noch nicht so richtig. Das bedeutet:
Die Benachrichtigung funktioniert inkl. inline_keyboard, jedoch erhalte ich die Benachrichtigung auch, wenn ich nicht zu Hause bin.

Das Template habe ich als Datei in /homeassistant/custom_templates/notify_telegram_users_at_home.jinja abgelegt und die YAML-Konfigurationen anschließend neu geladen:

{% macro telegram_id('zone.home') %}
{{ state_attr('zone.home', 'persons') | replace("person.julian","Meine-Telegram-ID") | replace("person.person2","Zweite-Telegram-ID")}}
{% endmacro %}

Die Automatisierung sieht zum Test wie folgt aus:

alias: Test1
description: ""
trigger:
  - platform: device
    type: changed_states
    device_id: 5940884a2cf1488363346df5b730a525
    entity_id: 0edb89a663c84bf7b5896af7ddf87265
    domain: switch
condition:
  - condition: state
    entity_id: input_boolean.fensterkontakte_aktiv
    state: "on"
action:
  - data:
      target_template: |
        {% from 'notify_telegram_users_at_home.jinja' import telegram_id %}
        {{ telegram_id('zone.home') }}
      title: <strong>Bürofenster schließen!</strong>
      message: Das Fenster im Büro ist seit 10 Minuten geöffnet.
      parse_mode: html
      inline_keyboard: ⌨️ Menü öffnen:/start
    alias: Telegram - Bürofenster schließen!
    action: telegram_bot.send_message
mode: single

Die Entität person.julian hat aktuell den Zustand not_home, wird aber trotzdem benachrichtigt.

Woran könnte das liegen?

LG
Julian

Wenn sich eine Person nicht in der Home Zone befindet, wird sie auch nicht unter persons aufgeführt.

Das kannst Du auch einfach testen

Einfach mal für eine bestimmte Person unter Entwicklungswerkzeuge → Zustände
den Zustand not_home setzen.

Gruß
Osorkon

Eventuell übersehe ich ja etwas ganz Einfaches, aber ich werde aktuell benachrichtigt, wenn mein User auch “not_home” ist.

Entität als Screenshot:
grafik

Ich habe bei dem Macro auch schon versucht, zone_id durch ‘zone.home’ (inkl. einfache Anführungszeichen) zu ersetzen, jedoch erfolglos. So wie ich es verstanden habe, muss es ja mit zone_id funktionieren, damit ich auch andere Zonen abfragen kann.

Macro als Screenshot:

Macro als Code:

# 1: Julian
# 2: ...
# 3: ...
{% macro telegram_id(zone_id) %}
{{ state_attr(zone_id, 'persons') | replace("person.julian","Meine-Telegram-ID") | replace("person.person2","Zweite-Telegram-ID")}}
{% endmacro %}

Automation als Screenshot:
grafik

Automation als Code:

data:
  target_template: |
    {% from 'notify_telegram_users_at_home.jinja' import telegram_id %}
    {{ telegram_id('zone.home') }}
  title: <strong>Bürofenster schließen!</strong>
  message: Das Fenster im Büro ist seit 10 Minuten geöffnet.
  parse_mode: html
  inline_keyboard: ⌨️ Menü öffnen:/start
alias: Telegram - Bürofenster schließen!
action: telegram_bot.send_message

Wo liegt der Fehler?

LG
Julian

Sorry!! Mein Fehler!
Verwende bitte:

      target: |
        {% from 'notify_telegram_users_at_home.jinja' import telegram_id %}
        {{ telegram_id('zone.home') }}

Und nicht!

target_template:

Dann musst Du noch sicherstellen, dass alle Personen in der Home Zone eine korrekte Chat-ID zugewiesen ist. Wenn diese ungültig ist oder fehlt, wird immer die erste erlaubte Chat-ID verwendet.

Damit keine Benachrichtigung raus geht an die erste Chat-ID, wenn alle nicht zu Hause sind, solltest Du als zusätzliche Bedingung verwenden:
Wenn zone.home > 0

alias: "Telegram: Benachrichtigung - Bürofenster schließen"
description: ""
trigger:
  - type: opened
    platform: device
    device_id: 31a75f6bf3b71d1a98d6052d42f5b2c8
    entity_id: binary_sensor.sensor_buerofenster_contact
    domain: binary_sensor
    for:
      hours: 0
      minutes: 10
      seconds: 0
condition:
  - condition: state
    entity_id: input_boolean.fensterkontakte_aktiv
    state: "on"
  - condition: numeric_state
    entity_id: zone.home
    above: 0
action:
  - data:
      target: |
        {% from 'notify_telegram_users_at_home.jinja' import telegram_id %}
        {{ telegram_id('zone.home') }}
      title: <strong>Bürofenster schließen!</strong>
      message: Das Fenster im Büro ist seit 10 Minuten geöffnet.
      parse_mode: html
      inline_keyboard: ⌨️ Menü öffnen:/start
    alias: Telegram - Bürofenster schließen!
    action: telegram_bot.send_message
mode: single

Gruß
Osorkon