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.
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!