Folgendes (alltagsübliches) Problem: Du befindest dich in deinem 314 Zimmer großen Schloss und möchtest eine Person zu dir rufen. Du kannst nicht einfach durch das Schloss schreien, da es zu groß ist und die Person dich nicht hören würde. Stattdessen greifst du zu deinem Telefon, rufst einen Anrufbeantworter an, diktierst deine Nachricht und diese wird über das Schloss verbreitet, damit die Person sie hören kann.

Dieses – sehr realistische – Problem gehen wir heute in HomeAssistant an.

Hier ein kurzes Video, wie das Ganze am Ende aussehen wird:

Klick mich, um zum Video zu gelangen!

Voraussetzungen

Folgende Voraussetzungen müssen erfüllt sein, damit du dieses Projekt umsetzen kannst:

  • HomeAssistant in der aktuellsten Version (ich habe 2026.5.0)
  • Schreibzugriff auf das config-Verzeichnis (bzw. /homeassistant-Verzeichnis bei HASS OS) von HomeAssistant (z.B. über Samba oder den File Editor)
  • Schreibzugriff auf das www-Verzeichnis im config-Verzeichnis
  • Eine Fritz!Box (oder eine andere SIP-fähige Telefonanlage / VoIP-Anbieter)
  • Ein Telefon, das auf die Telefonanlage zugreifen kann (z.B. ein Smartphone mit einer SIP-App oder ein Festnetztelefon)
  • SONOS (oder Ikea Symfonisk) Lautsprecher (oder andere HomeAssistant Media Player, die announce unterstützen)
  • Einen Jingle – Ich habe den ÖBB-Jingle verwendet, da es sehr kurz ist und in guter Qualität zum Download bereitsteht: https://www.unsereoebb.at/de/downloads [“ÖBB Gong” ganz unten]

Es hindert euch niemand daran, eine von außen erreichbare Telefonnummer zu nutzen, aber ich würde das absolut nicht empfehlen.

Einrichtung

Fritz!Box

Die Einrichtung in der Fritz!Box ist relativ einfach. Ihr klickt euch einfach durch die Oberfläche, erstellt eine VoIP-Nummer und wählt (so gut es geht) alle Rufnummern ab. Nutzername + Passwort vergeben und gut ist. Wer weiß, wie das funktioniert, kann gerne zu SIP-Integration springen.

Dennoch hier die wichtigsten Schritte in Bildern:

WICHTIG: Ich habe einige Schritte übersprungen, da es quasi nur ein paar “Weiter”-Klicks sind und ich zu faul zum zensieren meiner Nummer bin. Wenn ihr euch unsicher seid, schaut einfach in die Fritz!Box-Dokumentation.

fb-telefon-0
Übersicht Telefoniegeräte

In der Übersicht der Telefoniegeräte (Telefonie -> Telefoniegeräte) klickt ihr auf „Neues Gerät einrichten“ und wählt „Telefon (mit und ohne Anrufbeantworter)“ aus.

fb-telefon-1
Telefon (mit und ohne Anrufbeantworter) auswählen

Danach wählt ihr „LAN/WLAN (IP-Telefon)“ aus und gebt dem Gerät einen Namen (z.B. „PA-System“).

fb-telefon-2
LAN/WLAN (IP-Telefon) auswählen

Im nächsten Schritt wählt ihr „Neue SIP-Zugangsdaten“ aus und gebt einen Benutzernamen und ein Passwort ein. Die Zugangsdaten solltet ihr euch merken, da ihr sie später für die SIP-Integration in HomeAssistant benötigt.

fb-telefon-3
Zugangsdaten vergeben und merken

SIP-Integration

HomeAssistant selbst unterstützt SIP nicht nativ, aber es gibt ein tolles Addon namens ha-sip.

Die Installation hier beschreibt die Installation auf einem HomeAssistant OS System. Falls irgendwelche Menüpunkte bei euch anders heißen oder fehlen, schaut am besten in der Installationsanleitung des Repos: https://github.com/arnonym/ha-plugins#installation

Installation

An sich ziemlich straightforward: Ihr geht in den Einstellungen auf “Apps” und klickt auf “Install App”. Anschließend klickt ihr auf das Kebab-Menü oben rechts und wählt “Repositories” aus. Auf der nächsten Seite klickt ihr auf “Add” und gebt die URL des Repositories ein: https://github.com/arnonym/ha-plugins. Danach sollte das Repository in der Suche auftauchen und ihr könnt das Addon installieren.

hass-1
Settings -> Apps
hass-2
Install App
hass-3
Kebab-Menü -> Repositories
hass-4
Add (Repository Liste)
hass-5
Repository URL eingeben + Add
hass-6
Nach 'sip' suchen und installieren

Basis-Konfiguration

In den Einstellungen der App müsst ihr zunächst die globalen SIP-Einstellungen vornehmen, bevor ihr euren ersten SIP-Account anlegen könnt.

Am wichtigsten war erst einmal das cache-Verzeichnis, damit der sip-client TTS korrekt cachen kann. Hierfür habe ich ein Verzeichnis namens audio_cache in meinem config-Verzeichnis angelegt und das hier eingegeben.

hass-7
Globale SIP-Einstellungen

Danach gebt ihr eure SIP-Zugangsdaten ein, die ihr in der Fritz!Box vergeben habt. Wichtig ist hier, dass ihr als Domain die IP-Adresse eurer Fritz!Box eingebt (z.B. 192.168.178.1). Theoretisch geht auch fritz.box, aber bei mir gab es damit Probleme mit der Registrierung, weshalb ich die IP-Adresse verwendet habe.

hass-8
SIP-Account anlegen

Wichtig ist, dass ihr als answer_mode accept auswählt, dass die Anrufe automatisch angenommen werden. (listen wäre sinnvoll für andere Automatisierungen wie bspw. einen Türöffner bei eingehenden Anrufen, oder blinkende Lichter, wenn euer Telefon klingelt.)

Zusätzlich müsst ihr noch den Dateinamen angeben, der für die weitere Konfiguration genutzt wird. In meinem Fall habe ich /config/sip-1-incoming.yaml angegeben. Ihr könnt hier aber auch mehrere Accounts anlegen und verschiedene Dateien für eingehende Anrufe nutzen, um sie besser zu unterscheiden.

hass-9
Datei für eingehende Anrufe angeben

Für die tts empfehle ich euch, picotts zu nutzen, da es komplett offline läuft und eine gute deutsche Stimme hat.

hass-10
Konfiguration für picotts

Idealerweise startet ihr die App danach einmal neu, damit die Konfiguration korrekt geladen wird. Das könnt ihr über die Benutzeroberfläche machen.

Sip-incoming-Konfiguration

Die folgende Konfiguration ist relativ selbsterklärend.

Folgendes steht in der /homeassistant/sip-1-incoming.yaml – der Konfiguration für eingehende Anrufe auf sip-1:

answer_after: 0 # Anruf wird sofort angenommen
webhook_to_call: # Webhooks für die Automatisierungen
  call_disconnected: ha_sip_call_disconnected
  entered_menu: ha_sip_entered_menu
  playback_done: ha_sip_playback_done
menu:
  message: 'Bitte Ziel wählen. 1 Küche, 2 Bad, 3 Wohnzimmer, 0 Alle' # Begrüßungsansage
  language: de-DE
  post_action: noop 
  choices:
    '1':
      id: target_kuche # ID für die Zielauswahl; wird später in den Automatisierungen ausgewertet
      message: 'Küche.' # Ansage für die Zielauswahl
      language: de-DE # Sprache für die Ansage
      wait_for_audio_to_finish: true # Wichtige Einstellung, damit die Aufnahme nicht startet, bevor die Ansage zu Ende ist
      post_action: noop # Keine Aktion nach der Ansage, da alles Weitere in den Automatisierungen geregelt wird
    '2':
      id: target_badezimmer
      message: 'Bad.'
      language: de-DE
      wait_for_audio_to_finish: true
      post_action: noop
    '3':
      id: target_wohnzimmer
      message: 'Wohnzimmer.'
      language: de-DE
      wait_for_audio_to_finish: true
      post_action: noop
    '0':
      id: target_all
      message: 'Alle.'
      language: de-DE
      wait_for_audio_to_finish: true
      post_action: noop

Wichtig ist hierbei, dass an jedem Eintrag die Sprache mit de-DE definiert ist und wait_for_audio_to_finish auf true steht, damit die Sprachausgabe korrekt funktioniert und die Aufzeichnung nicht startet, bevor die Ansage zu Ende ist.

Auf die Webhooks in webhook_to_call reagieren wir später in den Automatisierungen, um die Aufnahme zu starten und die Zielauswahl zu speichern.

Automatisierungen

Nun kommen wir in die heiße Phase: Die finale konfiguration der Automatisierungen, damit das Ganze auch tatsächlich funktioniert.

Ihr benötigt zunächst zwei Helper-Entitäten, um die Zielauswahl zu speichern: input_text.pa_call_id und input_text.pa_target.

In der ersten Automatisierung speichert ihr die call-ID und die gewählte Zielgruppe in den Helpern:

alias: PA – Ziel merken
triggers:
  - webhook_id: ha_sip_entered_menu
    trigger: webhook
actions:
  - target:
      entity_id: input_text.pa_call_id
    data:
      value: "{{ trigger.json.internal_id }}"
    action: input_text.set_value
  - target:
      entity_id: input_text.pa_target
    data:
      value: "{{ trigger.json.menu_id }}"
    action: input_text.set_value

Danach wird die Aufnahme gestartet und in. /config/www/pa_recording.wav zwischengespeichert:

alias: PA – Aufnahme starten nach Ansage
description: ""
triggers:
  - webhook_id: ha_sip_playback_done
    trigger: webhook
actions:
  - data:
      addon: c7744bff_ha-sip
      input:
        command: start_recording
        number: "{{ trigger.json.internal_id }}"
        recording_file: /config/www/pa_recording.wav
    action: hassio.addon_stdin

Nach dem Auflegen wird die dritte Automatisierung getriggert, die die Ziele auswertet und zunächst den Jingle, dann die Aufnahme auf den entsprechenden Lautsprechern abspielt:

alias: PA – Abspielen nach Auflegen
triggers:
  - webhook_id: ha_sip_call_disconnected
    trigger: webhook
actions:
  # Hier wird die Zielgruppe aus der vorherigen Automatisierung ausgewertet und die entsprechenden Media Player ausgewählt. Falls aus irgendeinem Grund keine Zielgruppe gefunden wird, werden standardmäßig alle drei Media Player ausgewählt.
  - variables:
      target_map:
        target_kuche:
          - media_player.kuche
        target_badezimmer:
          - media_player.badezimmer
        target_wohnzimmer:
          - media_player.wohnzimmer
        target_all:
          - media_player.kuche
          - media_player.badezimmer
          - media_player.wohnzimmer
      targets: |
        {{ target_map.get(states('input_text.pa_target'), ['media_player.kuche', 'media_player.badezimmer', 'media_player.wohnzimmer']) }}        
  - delay:
      seconds: 1
  - target:
      entity_id: "{{ targets }}"
    data:
      media:
        media_content_id: http://192.168.178.22:8123/local/jingle.wav # Ich habe hier meine interne IP-Adresse verwendet. Theoretisch ginge auch homeassistant.local, aber das hat bei mir nicht korrekt aufgelöst.
        media_content_type: music
        metadata: {}
      announce: true
      extra:
        volume: 30  # Wunschlautstärke für die Ansage. Je nach Lautsprecher kann es sein, dass ihr hier etwas experimentieren müsst, damit die Ansage laut genug ist, aber der Jingle nicht zu laut ist.
    action: media_player.play_media
  - delay:
      hours: 0
      minutes: 0
      seconds: 1 # Warten, damit der Jingle nicht direkt von der Ansage überlagert wird. Kommt auf die Länge eures Jingles an, aber 1-2 Sekunden sollten in den meisten Fällen ausreichen.
      milliseconds: 0
  - target:
      entity_id: "{{ targets }}"
    data:
      media:
        media_content_id: http://192.168.178.22:8123/local/pa_recording.wav # Ich habe hier meine interne IP-Adresse verwendet. Theoretisch ginge auch homeassistant.local, aber das hat bei mir nicht korrekt aufgelöst.
        media_content_type: music
        metadata: {}
      announce: true # Wichtig, damit die Lautsprecher die aktuelle Wiedergabe unterbrechen und die Aufnahme direkt abspielen, ohne den Jingle zu Ende spielen zu müssen
      extra:
        volume: 30 # Wunschlautstärke für die Ansage. Je nach Lautsprecher kann es sein, dass ihr hier etwas experimentieren müsst, damit die Ansage laut genug ist, aber der Jingle nicht zu laut ist.
    action: media_player.play_media

Und das war’s dann auch schon! Ihr könnt jetzt anrufen, die Zielgruppe auswählen und eure Ansage wird auf den entsprechenden Lautsprechern abgespielt.

Ihr braucht jetzt nur noch ein verbundenes DECT-Telefon oder die Fritz!FON-App auf eurem Smartphone, um das Ganze zu testen.

Fazit

Braucht man das? Höchstwahrscheinlich nicht. Ich finde es in meiner Wohnung praktisch, weil sie extrem verwinkelt ist und man sich gegenseitig kaum hört.

Aber es macht unglaublich Spaß, so einen Schwachsinn zu basteln und eventuell kann es ja doch für irgendwen anderes nütlich sein.

Grüße!