Fritzbox Anrufliste mit online Rufnummerabfrage

Für welche Projekte verwendet Ihr OpenHAB? Was habt Ihr automatisiert? Stellt eure Projekte hier vor.

Moderatoren: Cyrelian, seppy

Antworten
DrJJ
Beiträge: 3
Registriert: 1. Okt 2020 10:50

Fritzbox Anrufliste mit online Rufnummerabfrage

Beitrag von DrJJ »

Ich wollte im Openhab eine schöne Tabelle mit einer Anrufliste aus meiner Fritzbox die unbekannte Rufnummern per dasoertliche auflöst und bei Anrufen in Abwesenheit mich per Pushover informiert.

Im Netz habe ich zwar schöne Anleitungen und Möglichkeiten gefunden aber keine erfüllte meine Anforderungen. Da ich etwas PHP Programmieren kann habe ich mir ein eigenes Script erstellt was genau meine Wünsche erfüllt und eine HTML Datei erstellt die ich per Webview einbinden kann.

Voraussetzung ist, dass auf dem Gerät wo Openhab läuft auch PHP installiert ist.

Hier mein Script welches unter /etc/openhab2/scripts/fritzbox.php abgelegt wird

Code: Alles auswählen

<?php
/**
 * Skript welches von der Fritzbox die Callliste lädt und eine HTML Datei erstellt
 * die in Openhab als Webview eingebunden werden kann.
 * 
 * Zusätzlich werden Telefonnummern die nicht über das Fritztelefonbuch aufgelöst werden über dasoertliche.de aufgelöst
 * Diese Anfragen werden in einer Cache Datei zwischengespeichert um mehrfach abfragen der gleichen Nr zu unterbinden.
 * 
 * Einstellungen ab hier anpassen:
 */
// Url zur Fritzbox
$fb_url = 'http://172.16.10.2:49000';
// Benutzer für Fritzbox
$fb_user = 'openhab';
// Passwort für Fritzbox
$fb_pass = 'openhabpw';
// Anzahl der Anrufe die dargestellt werden sollen
$rows_cl = 6;

// Speicherort für Cache File
$call_cache = '/etc/openhab2/scripts/CacheReverseCallSearch.txt';
// Speicherort für HTML Datei die erstellt wird
$html_file = '/etc/openhab2/html/fb_calls.html';

// Datei die als Template zum erstellen der HTML Datei dient
$html_tmpl = '/etc/openhab2/html/fb_list.tmpl.html';
// Datei die als Template für eine Telefonzeile dient
$item_tpl = '/etc/openhab2/html/fb_item.tmpl.html';

// Icons für die Unterschiedlichen Calls als html
$icons['1'] = '<svg viewBox="0 0 100 100"><use xlink:href="/static/fritzbox.svg#phone-in_100"></use></svg>';
// 2 missed
$icons['2'] = '<svg viewBox="0 0 100 100"><use xlink:href="/static/fritzbox.svg#phone-missed_100"></use></svg>';
// 3 outgoing
$icons['3'] = '<svg viewBox="0 0 100 100"><use xlink:href="/static/fritzbox.svg#phone-out_100"></use></svg>';
// 9 active incoming
$icons['9'] = '';
// 10 rejected incoming
$icons['10'] = '';
// 11 active outgoing
$icons['11'] = '';

/**
 * Ende Einstellungen
 */
$calls = get_calls($fb_url, $fb_user, $fb_pass, $rows_cl);
$html = get_HTML($calls);
//Letzten Anruf ausgeben
$string = '{%TYPE%}|{%DATE%}|{%NAME%}|{%TEL%}';
echo parse_html($string, $calls[0]);

function get_calls($fb_url, $fb_user, $fb_pass, $rows_cl) {
    $client = new SoapClient(
            null,
            array(
        'location' => $fb_url . '/upnp/control/x_contact',
        'uri' => 'urn:dslforum-org:service:X_AVM-DE_OnTel:1',
        'noroot' => True,
        'login' => $fb_user,
        'password' => $fb_pass
            )
    );
    $result = $client->GetCallList();
    $xml = @simplexml_load_file($result);
    $i = 0;
    foreach ($xml->children() as $child) {
        if ($child->Id) {
            $list[$i] = (array) $child;
            //Löschen unnötige Einträge
            unset($list[$i]['Device']);
            unset($list[$i]['Count']);
            unset($list[$i]['Path']);
            if (strpos($list[$i]['Name'], $list[$i]['Caller']) !== false) {
                $list[$i]['Name'] = getDasOertliche($list[$i]['Caller']);
            }
            if ($list[$i]['Type'] == 3) {
                $list[$i]['Tel'] = $list[$i]['Called'];
            } else {
                $list[$i]['Tel'] = $list[$i]['Caller'];
            }
            $i++;
            if ($i == $rows_cl)
                break;
        }
    }
    return $list;
}

/**
 * Suche im dasoertliche nach dem Anrufer
 * wenn kein Treffer gefunden wurde, wird Unbekannt zurückgegeben.
 *
 * @param string Telefonnummer
 * @return string Anrufer
 */
function getDasOertliche($number) {
    global $call_cache;
    //im Cache suchen
    $cache = file($call_cache);
    foreach ($cache as $line) {
        // prüfen ob die Nummer in der Zeile gefunden wird
        if (strpos($line, $number) !== false) {
            $match = explode("|", $line);
            return $match[1];
        }
    }
    $url = "https://www.dasoertliche.de/Controller?form_name=search_inv&ph=" . $number;
    $page = file_get_contents($url);
    if (preg_match('/<span class="st-treff-name">(.*?)<\/span>/', $page, $match) == 1) {
        file_put_contents($call_cache, PHP_EOL . $number . "|" . $match[1], FILE_APPEND);
        return $match[1];
    } else {
        return 'Unbekannt';
    }
}

/**
 * Erstellt und speichert die HTML Datei
 *
 * @param array Liste der Anrufe
 */
function get_HTML($calls) {
    global $html_tmpl, $item_tpl, $icons, $html_file;
    $tmpl = file_get_contents($html_tmpl);
    $tmpl_item = file_get_contents($item_tpl);
    $items = '';
    foreach ($calls as $line) {
        $line['icon'] = $icons [$line['Type']];
        $items .= parse_html($tmpl_item, $line);
    }
    $out = parse_html($tmpl, array('callist' => $items));
    file_put_contents($html_file, $out);
}

function parse_html($html, $args) {
    foreach ($args as $key => $val) {
        $html = str_replace("{%" . strtoupper($key) . "%}", $val, $html);
    }
    return $html;
}


Datei für Template: /etc/openhab2/html/fb_list.tmpl.html

Code: Alles auswählen

<!doctype html>
<html>

<head>
    <title>Anrufliste</title>
    <link rel="manifest" href="/basicui/manifest.json">
    <link rel="stylesheet" type="text/css" href="/basicui/mdl/material.min.css" />
    <link rel="stylesheet" type="text/css" href="/basicui/material-icons.css" />
    <link rel="stylesheet" type="text/css" href="/basicui/roboto.css" />
    <link rel="stylesheet" type="text/css" href="/basicui/smarthome.css" />
    <style>
        body {
            background-color: white !important;
        }

        table {
            margin-left: auto;
            margin-right: auto;
            border-collapse: collapse;
            width: 98%;
        }

        th,
        td {
            border-bottom: 1px solid #ccc;
            text-align: left;
            color: var(--container-text-color, #616161) !important;
        }

        svg {
            height: 32px;
            width: 32px;
        }
    </style>
</head>

<body>
    <table>
        <tr>
            <th>Typ</th>
            <th>Datum</th>
            <th>Name</th>
            <th>Nummer</th>
            <th>Dauer</th>
        </tr>
        {%CALLIST%}
    </table>
</body>

</html>
Datei für /etc/openhab2/html/fb_item.tmpl.html

Code: Alles auswählen

<tr>
    <td>{%ICON%}</td>
    <td>{%DATE%}</td>
    <td>{%NAME%}</td>
    <td>{%TEL%}</td>
    <td>{%DURATION%}</td>
</tr>
Meine Rule die alles Steuert:

Code: Alles auswählen

rule "Anrufliste"
when
   Item fboxIncomingCall changed or
   Item fboxOutgoingCall changed 
then
   if ((fboxIncomingCall.state.toString == ",") && (fboxOutgoingCall.state.toString == ",") && (previousState.toString != ",")) {
      Thread::sleep(3000) //Zeit für die Fritzbox zum updaten der XML
      val output = executeCommandLine("php /etc/openhab2/scripts/fritzbox.php", 30000)
      //Format Antwort: Type|Datum|Name|Tel
      var CallData = output.toString.split('\\|')
      if (CallData.get(0) == "2") {
        sendPushoverMessage(pushoverBuilder("Anruf verpasst von: "+ CallData.get(2) +" Tel: "+ CallData.get(3)).withTitle("Telefon"))
      }
   }
end
In der Sitemap:

Code: Alles auswählen

Frame label="Anrufliste" { 
		Webview url="/static/fb_calls.html" height=7 icon=none
	}
Falls jemand es Testet und Verbesserungen sieht gerne melden.
Du hast keine ausreichende Berechtigung, um die Dateianhänge dieses Beitrags anzusehen.

Benutzeravatar
udo1toni
Beiträge: 4538
Registriert: 11. Apr 2018 18:05
Answers: 47
Wohnort: Darmstadt

Re: Fritzbox Anrufliste mit online Rufnummerabfrage

Beitrag von udo1toni »

Sehr schick! Vielen Dank dafür!

Benutzeravatar
Trashware
Beiträge: 16
Registriert: 27. Jun 2019 14:12

Re: Fritzbox Anrufliste mit online Rufnummerabfrage

Beitrag von Trashware »

Hier mal was von mir zum TR064-Binding. Verbindungsdaten, Anzeige von Datum und Nummer des letzten Anrufs, Reverse-Lookup im Telefonbuch der Fritz!Box und bei fehlendem Rückgabewert Online-Suche über einen Bash-Script... Ich hoffe, es gefällt. :-)

Screenshot.jpg
Items:

Code: Alles auswählen

Group gFritzBox "Fritz!Box" <fritzbox> 
String fboxDslStatus "DSL Status [%s]" <dslstatus> (gFritzBox) { fritzboxtr064="dslStatus" }
String fboxWanIP "Externe IP [%s]" <dslip> (gFritzBox) { fritzboxtr064="wanip" }
Number fboxDslUpstreamCurrRate "DSL Upload [%s mbit/s]" <dslup> (gFritzBox) { fritzboxtr064="dslUpstreamCurrRate" }
Number fboxDslDownstreamCurrRate "DSL Download [%s mbit/s]" <dsldown> (gFritzBox) { fritzboxtr064="dslDownstreamCurrRate" }
Switch fboxRinging "Anruf [%s]" <phone> (gFritzBox) { fritzboxtr064="callmonitor_ringing" }
Call fboxIncomingCall "Anrufer [%1$s bei %2$s]" <phone> (gFritzBox) { fritzboxtr064="callmonitor_ringing" }
Call fboxIncomingCallResolved "Anrufer [%1$s bei %2$s]" <phone> (gFritzBox) { fritzboxtr064="callmonitor_ringing:resolveName" }
Number fboxMissedCalls "Verpasste Anrufe [%s]" <phone> (gFritzBox) { fritzboxtr064="missedCallsInDays:1" }
String fboxLastCaller "Letzter Anrufer [%s]" <phone> (gFritzBox)
String fboxLastCallerResolved "Anrufername [%s]" <phone> (gFritzBox)
DateTime fboxLastCallerTime "Anrufzeit [%1$ta, %1$td.%1$tm.%1$tY, %1$tH:%1$tM]" <phone> (gFritzBox)
Sitemap:

Code: Alles auswählen

Group item=gFritzBox {
	Frame label="Internet" {
		Text item=fboxDslStatus
		Text item=fboxWanIP
		Text item=fboxDslUpstreamCurrRate
		Text item=fboxDslDownstreamCurrRate
	}
	Frame label="Telefon" {
		Text item=fboxMissedCalls
		Text item=fboxLastCaller
		Text item=fboxLastCallerResolved
		Text item=fboxLastCallerTime visibility=[fboxLastCallerTime!=NULL]
	}
}
Rule:

Code: Alles auswählen

rule "Telefonanruf"
when
    Item fboxRinging changed to ON
then
    val incCall = fboxIncomingCall.state as StringListType
    var callernumber = incCall.getValue(1)
    val incCallResolved = fboxIncomingCallResolved.state as StringListType
    var callername = incCallResolved.getValue(1)
    if (callernumber.length == 0) {
	callernumber = "unbekannt"
	callername = "unbekannt"
    }
    else if (callername.length == 0 || callername.startsWith("Name not found for")) {
	var LookupCommand = '/etc/openhab2/scripts/reverselookup.sh ' + callernumber
	callername = executeCommandLine(LookupCommand, 10000)
    }
    else {
	callername = callername.split(" \\(").get(0)
    }
    sendBroadcastNotification("Fritz!Box: Anruf von " + callernumber + " (" + callername + ")")
    postUpdate(fboxLastCaller, callernumber)
    postUpdate(fboxLastCallerTime, new DateTimeType())
    postUpdate(fboxLastCallerResolved, callername)
end
Bash-Script "/etc/openhab2/scripts/reverselookup.sh":

Code: Alles auswählen

#!/bin/sh
#
# Reverse Lookup of Fritz!Box callers on dastelefonbuch.de
# CopyLeft Trashware
#
##########################################################

CALLERNAME=`curl -Ls "www.dastelefonbuch.de/R%C3%BCckw%C3%A4rts-Suche/$1" | \
		grep 'class="name"' -m 1 | \
		awk -F '"' '{print $4}'`
if [ -z "$CALLERNAME" ]; then
    CALLERNAME="unbekannt"
fi
echo "$CALLERNAME"
exit
Du hast keine ausreichende Berechtigung, um die Dateianhänge dieses Beitrags anzusehen.

Antworten