Smarthome: Anrufer-Name bei Fritz!Box bei Anruf via TTS auf Webradio ansagen

Nachdem ich kürzlich mein Smarthome mit einer Sprachausgabe versehen habe wollte ich es dazu bringen, mir anzusagen, wer anruft, wenn das Telefon klingelt.

Zuerst dachte ich daran, direkt die Google-API anzuzapfen, aber dann habe ich mir gedacht, eigentlich liegen die Daten ja schon synchronisiert auf meiner Fritz!Box und damit im Haus, daher wollte ich nun diese Quelle nehmen.

Und das klappt auch ganz gut, wenn das Telefon klingelt wird nun immer angekündigt, wer dran ist.

Um das Telefon selbst erst einmal mit openhab zu koppeln habe ich das Fritz!Box Binding genutzt. Um „nur“ Telefonanrufe auslesen zu können, ist es hierzu nötig, den Call-Monitor zu aktivieren.

Dazu einfach an einem an die Fritz!Box angeschlossenen Telefon die #96*5* wählen. Zudem die Fritz!Box mit der IP in der openhab.cfg eintragen:

fritzbox:ip=192.168.188.1

Zum Auslesen der Telefonbücher habe ich etwas gegoogelt und bin dann dank dieses Forenbeitrags recht schnell auf ein Script gestoßen, welches das Telefonbuch bzw. die Telefonbücher der Fritzbox auslesen kann. Danke hierfür erst einmal!

Das Script ist recht selbsterklärend. In meinem Fall nutze ich das Telefonbuch der Fritzbox selbst gar nicht sondern greife lediglich auf zwei Google-Telefonbücher zu, welche die Fritzbox regelmäßig synchronisiert.

Fritz Box - Telefonbuch-ID herausfinden
Telefonbuch-ID herausfinden

Das Script sieht hierfür Parameter vor. Diese findet man ganz leicht über die Weboberfläche / Telefonbuchverwaltung der Fritzbox heraus. Einfach hier das Telefonbuch mit der rechten Maustaste im Firefox anklicken und mit „Q“ die Webentwickler-Tools aufrufen, anhand der URL erkennt man sofort die ID.

Am Script selbst habe ich lediglich die ID und den Exportnamen ausgetauscht sowie den Dateinamen des Exports selbst, so dass man per weiterem Shellscript beliebig viele Exporte anstoßen kann.

Hat man bei der Fritzbox ein Passwort gesetzt oder hat man die Konfiguration geändert, so dass die FritzBox nicht unter fritz.box (=Standard) erreichbar ist, muss das entsprechend angepasst werden.

Shell-Skript export_fritzbox_telefonbuch.sh

#!/bin/bash
# Telefonbuch der Fritzbox in XML-Datei auslesen
set -x
PATH=/usr:/usr/bin:/bin
ziel_pfad=/home/pi/test
ziel_datei=fritzexport-$1-$2.xml

# FritzBox credentials
_FBOX="fritz.box"
Passwd=""
_PhonebookId=$1%
_PhonebookExportName=$2%

# get challenge key from FB
Challenge=`wget -O - "http://${_FBOX}/login_sid.lua" 2>/dev/null | sed 's/.*<Challenge>\(.*\)<\/Challenge>.*/\1/'`

# login aufbauen und hashen
CPSTR="$Challenge-$Passwd"
MD5=`echo -n $CPSTR | iconv -f ISO8859-1 -t UTF-16LE | md5sum -b | awk '{print substr($0,1,32)}'`
RESPONSE="$Challenge-$MD5"
POSTDATA="?username=&response=$RESPONSE"

# login senden und SID herausfischen
_SID=`wget -O - --post-data="$POSTDATA" "http://${_FBOX}/login_sid.lua" 2>/dev/null | sed 's/.*<SID>\(.*\)<\/SID>.*/\1/'`

# get configuration from FB and write to STDOUT
curl -s \
     -k \
     --form 'sid='${_SID} \
     --form 'PhonebookId='${_PhonebookId} \
     --form 'PhonebookExportName='${_PhonebookExportName} \
     --form 'PhonebookExport=' \
     http://${_FBOX}/cgi-bin/firmwarecfg \
     -o ${ziel_pfad}/${ziel_datei}

Der Export klappt dann mit

sh export_fritzbox_telefonbuch.sh <ID> <Bezeichnung>

Die Bezeichnung dient nur für den Dateinamen des Exports und ist eigentlich nicht relevant für irgendwelche Funktionalität.

Nun gilt es, ein weiteres Script zu erstellen, welches als Parameter die anrufende Nummer erhält, welches dann einen Export erstellt (aus performancegründen kann man den Schritt natürlich auslassen und das z.B. via Cronjob erledigen lassen) und nachliest, ob es zur Nummer einen Treffer gibt.

Zum Treffer wird dann der Name zurück gegeben oder – wenn kein Treffer vorhanden war – die Nummer selbst.

Hierzu habe ich ein kleines lookup.php File angelegt und unter /var/www/html/fritzpi/lookup.php abgelegt:

<?php

/**
 * This script checks all fritzbox exports in the same directory
 * against a given number and returns the number owner if found
 * Otherwise number is returned again.
 */
$absolutePath = realpath(dirname(__FILE__)) . '/';
$xmlPath = $absolutePath;
$exportSchema = 'fritzexport';
$lookup = str_replace(array('+49', ' ', '/'), array('0', '', ''), $_REQUEST['nr']);

$files = array();
if (is_dir($absolutePath)) {
    if ($handle = opendir($absolutePath)) {
        // einlesen der Verzeichnisses
        while (($file = readdir($handle)) !== false) {
            if (substr($file, 0, strlen($exportSchema)) === $exportSchema) {
                $files[] = $file;
            }
        }
        closedir($handle);
    }
}
foreach ($files as $file) {
    $xml = simplexml_load_file($xmlPath . $file);
    if ($xml === FALSE) {
        echo "Fehler beim Laden des XML";
        foreach (libxml_get_errors() as $error) {
            echo "<br>", $error->message;
        }
    } else {

        foreach ($xml->phonebook->contact as $element) {
            $name = $element->person->realName;
            $numbers = array();
            foreach ($element->telephony as $e) {
                foreach ($e->number as $number) {
                    // Remove +49 and replace with 0
                    $number = str_replace(array('+49', ' ', '/'), array('0', '', ''), $number);
                    if ($number == $lookup) {
                        echo $name;
                        exit;
                    }
                }
            }
        }
    }
}
echo $lookup;
?>

Dieses kann nun per Web aufgerufen werden und führt einen Lookup aus dem Telefonbuch durch. Zum Testen kann das einfach einmal mit ein paar Nummern im Browser getestet werden:

http://<IP>/fritzpi/lookup.php?nr=09411234556

Im Browserfenster steht nun der aufgelöste Name oder, wenn das nicht möglich war, die übergebene Nummer.

Nun muss in die streampi.php aus vorherigem Beitrag dies noch integriert werden. Hier greifen wir einfach auf das Script über den Webserver zu. und den Output übergeben wir dann an das tts-Script zum Erstellen des MP3.

Um die Nummer in Text zu übergeben muss der Platzhalter NUMMER im Text groß vorkommen, die aufzulösende Telefonnummer wird einfach per HTTP-Parameter übergeben:

http://<IP>/streampi/streampi.php?type=tts&prio=1&volume=110&text=Anruf von NUMMER&tel=0941234566

Mit diesem Aufruf wird nun der Name aufgelöst, das MP3 erzeugt und auch gleich abgespielt. Und genau das können wir nun als Rule integrieren und openHAb wird uns nun jedes Mal, wenn das Telefon klingelt, sagen, wer uns erreichen will:

rule "Telefon klingelt"
when Item Incoming_Call changed from OFF to ON
then
    var List<String> anrufer = Incoming_Call_No.state.toString().split('##')
    logInfo('rules','Anruf von Nummer: ' + anrufer.get(0));
    sendHttpPostRequest(TTS_URL,'application/x-www-form-urlencoded','type=tts&prio=1&volume=110&text=Anruf von NUMMER&tel='+ anrufer.get(0))
end

TTS_URL ist bei mir einfach die einmal global festgelegte streampi.php Datei.

Und immer noch warten viele Ideen auf meinen Raspberry 😉

Viel Spaß beim ausprobieren!

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.