Hallo,
Ich hab eine neue Version des Fritz!Box Interfaces getippt.
Diese Version verwendet TR-064 zum auslesen der Anruferliste,
das ist ein Protokoll das nahe am UPnP Standard ist (SOAP).
Der Vorteil ist hier das XML zurück kommt und man angeben kann wie viel
Einträge man max. haben möchte.
Beim alten CSV Download mussten immer alle 400 Einträge übertragen und verarbeitet werden.
Das sind beim alten Skript 81,4 KB an Daten und der raspberry benötigt dazu 1547 ms.
Das Neue holt standardmäßig nur die letzen 20 Einträge und das sind 4,32 KB
bei einer Verarbeitungszeit von 328ms.
Da das Interface standardisiert ist sollte sich das auch nicht mit jeder Fritz!Box Firmware ändern
und mit den Internationalen (English) Versionen der Boxen klar kommen.
Getestet hab ich es mit einer 7390 Version v6.03 und v6.20
Weiterhin hab ich alle drei Möglichkeiten der Anmeldung getestet (ohne PWD, nur PWD, User mit PWD).
Auf der Box muss halt nur TR-064 aktiv sein.
Das ist meines Wissens mit allen Modellen die nach 2009
auf dem Markt gekommen sind und die jeweils aktuelle Firmware haben möglich.
Genug gequatscht - Version im Anhang.
Einfach ins Verzeichniss "smartvisu\lib\phone\service" legen und in der Weboberfläche auswählen. "Zugriff für Anwendungen zulassen" muss in der FB aktiviert sein. Hiezu steht mehr in der PHP Datei.
Grüße Stefan
Datei: "fritz!box_via_TR-064.php"
Ich hab eine neue Version des Fritz!Box Interfaces getippt.
Diese Version verwendet TR-064 zum auslesen der Anruferliste,
das ist ein Protokoll das nahe am UPnP Standard ist (SOAP).
Der Vorteil ist hier das XML zurück kommt und man angeben kann wie viel
Einträge man max. haben möchte.
Beim alten CSV Download mussten immer alle 400 Einträge übertragen und verarbeitet werden.
Das sind beim alten Skript 81,4 KB an Daten und der raspberry benötigt dazu 1547 ms.
Das Neue holt standardmäßig nur die letzen 20 Einträge und das sind 4,32 KB
bei einer Verarbeitungszeit von 328ms.
Da das Interface standardisiert ist sollte sich das auch nicht mit jeder Fritz!Box Firmware ändern
und mit den Internationalen (English) Versionen der Boxen klar kommen.
Getestet hab ich es mit einer 7390 Version v6.03 und v6.20
Weiterhin hab ich alle drei Möglichkeiten der Anmeldung getestet (ohne PWD, nur PWD, User mit PWD).
Auf der Box muss halt nur TR-064 aktiv sein.
Das ist meines Wissens mit allen Modellen die nach 2009
auf dem Markt gekommen sind und die jeweils aktuelle Firmware haben möglich.
Genug gequatscht - Version im Anhang.
Einfach ins Verzeichniss "smartvisu\lib\phone\service" legen und in der Weboberfläche auswählen. "Zugriff für Anwendungen zulassen" muss in der FB aktiviert sein. Hiezu steht mehr in der PHP Datei.
Grüße Stefan
Datei: "fritz!box_via_TR-064.php"
PHP-Code:
<?php
require_once '../../../lib/includes.php';
require_once const_path_system . 'phone/phone.php';
/**
* This class reads the phonelist of an fritz!box phonesystem via TR-064 protocol
* This can only work if you enable "Zugriff für Anwendungen zulassen".
* you can found this config switch inside the web console -> Home network -> Network -> Network Settings
* It is required that "Extented View" of the web console is enabled - that this checkbox is shown.
*
*/
class phone_fritzbox_via_TR064 extends phone
{
private $max_calls_to_fetch;
private $challenge;
private $call_list_url;
public function __construct($http_vals)
{
parent::init($http_vals);
// maximum number of records fetched from phonesystem.
$this->max_calls_to_fetch = 20;
// use some default user if only password is set on smartvisu
if (strlen($this->user) == 0 && strlen($this->pass) > 0)
$this->user = 'admin';
}
/**
* DoSOAPCall: issues a http post to the phone system on port 49000
*/
private function DoSOAPCall($content)
{
$header[] = 'Content-type: text/xml;charset="utf-8"\r\n';
$header[] = 'SOAPAction: urn:dslforum-org:service:X_AVM-DE_OnTel:1#GetCallList';
$header[] = sprintf('Content-Length: %d', strlen($content));
$context = array(
'http' => array(
'method' => 'POST',
'header' => implode("\r\n", $header),
'content' => $content
)
);
$url = 'http://' . $this->server . ':49000/upnp/control/x_contact';
return (file_get_contents($url, false, stream_context_create($context)));
}
/**
* InitChallenge: the phone systems responds to this SOAP message
* always with "Unauthenticated" if a password is set
* This is only used for getting the Nonce and Realm like :
* <Nonce>A025059762AFE268</Nonce> <Realm>F!Box SOAP-Auth</Realm>
*/
private function InitChallenge()
{
// define soap message
$soap_msg_InitChallenge = '
<?xml version="1.0" encoding="utf-8"?>
<s:Envelope s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" >
<s:Header><h:InitChallenge xmlns:h="http://soap-authentication.org/digest/2001/10/" s:mustUnderstand="1">
<UserID>' . $this->user . '</UserID>
</h:InitChallenge ></s:Header><s:Body><u:GetCallList xmlns:u="urn:dslforum-org:service:X_AVM-DE_OnTel:1">
</u:GetCallList></s:Body></s:Envelope>';
if (($response = $this->DoSOAPCall($soap_msg_InitChallenge)) === FALSE)
return FALSE;
$this->debug($response, "Fritz RAW response InitChallenge (Unauthenticated is OK at this point!)");
if (preg_match_all("(\<.+\>(.+)\<\/.+\>)U", $response, $this->challenge) === FALSE) {
$this->error('Phone: fritz!box', 'SOAP Challenge parsing error!');
}
$this->debug($this->challenge, "preg_matched InitChallenge (Unauthenticated is OK at this point!)");
}
/**
* GetCallListURL: Create a authentication hash and use that with the real request to get the callList URL
*/
private function GetCallListURL()
{
//create authentication sting
$Auth = MD5(MD5($this->user . ':' . $this->challenge['1']['2'] . ':' . $this->pass) . ':' . $this->challenge['1']['1']);
// define soap message
$soap_msg_GetCallList = '
<?xml version="1.0" encoding="utf-8"?>
<s:Envelope s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" >
<s:Header><h:ClientAuth xmlns:h="http://soap-authentication.org/digest/2001/10/" s:mustUnderstand="1">
<Nonce>' . $this->challenge['1']['1'] . '</Nonce>
<Auth>' . $Auth . '</Auth>
<UserID>' . $this->user . '</UserID>
<Realm>' . $this->challenge['1']['2'] . '</Realm>
</h:ClientAuth></s:Header>
<s:Body><u:GetCallList xmlns:u="urn:dslforum-org:service:X_AVM-DE_OnTel:1"></u:GetCallList></s:Body>
</s:Envelope>';
$this->debug($soap_msg_GetCallList, "send GetCallList");
$response = $this->DoSOAPCall($soap_msg_GetCallList);
if (($response = $this->DoSOAPCall($soap_msg_GetCallList)) === FALSE)
return FALSE;
//$this->debug($response, "Fritz RAW response GetCallListURL");
if (preg_match_all("(\<.+\>(.+)\<\/.+\>)U", $response, $response_parts) === FALSE) {
$this->error('Phone: fritz!box', 'SOAP parsing error!');
}
$this->debug($response_parts, "preg_matched GetCallListURL");
if (substr($response_parts['1']['3'], 0, 4) === 'http') {
$this->call_list_url = $response_parts['1']['3'];
} else {
$this->error('Phone: fritz!box', 'GetCallList / Login failed!');
return FALSE;
}
}
/**
* TransformCallList: Download the callList limited by "calls_to_fetch" variable
* and align the xml data to the standard format of smartvisu
*/
private function TransformCallList()
{
// build download url
$url = $this->call_list_url . '&max=' . $this->max_calls_to_fetch;
$this->debug($url, "URL for call_list");
// download xml file and put it to xml parser
$GetCallListXml = file_get_contents($url);
$simplexml = simplexml_load_string($GetCallListXml);
$this->debug($GetCallListXml, "GetCallListXml");
/*
[Id] => 1767
[Type] => 1
[Caller] => 0175000000
[Called] => Amt ISDN 123456789
[Name] => Mustermann, Max
[Numbertype] => isdn
[Device] => Wohnzimmer
[Port] => 10
[Date] => 08.02.14 12:43
[Duration] => 0:32
*/
// map fritz box xml values to the smartvisu standart
foreach ($simplexml->xpath('//Call') as $call) {
// check if we got german date format and translate to ISO date
//(smartvisu is using strtotime later on)
if (preg_match("/[0-3]\d\.[0-1]\d\.\d{2}\s([0-1][0-9]|[2][0-3]):([0-5][0-9])/", $call->Date)) {
$date = DateTime::createFromFormat('d.m.y H:i', $call->Date);
$call->Date = $date->format('Y-m-d H:i');
}
// bulid data array for smartvisu
$this->data[] = array(
'pos' => (string) $call->Id,
'dir' => (string) ($call->Type == 1 ? 1 : ($call->Type == 2 ? 0 : -1)),
'date' => (string) $call->Date,
'number' => (string) $call->Caller,
'name' => (string) $call->Name,
'called' => (string) $call->Called,
'duration' => (string) $call->Duration
);
$call = '';
}
}
public function run()
{
$this->debug( 'smartvisu settings Server:"'.$this->server.'" User:"'.$this->user.'" Password:"'.$this->pass.'"' );
// try to get Realm and Nonce from Box - this is required for login
if ($this->InitChallenge() === FALSE) {
$this->error('Phone: fritz!box', 'Error Connecting - check IP Address and TR-064 setting');
return FALSE;
// when no password is set - InitChallenge returns CallList URL directly
} elseif (substr($this->challenge['1']['0'], 0, 4) == 'http') {
$this->call_list_url = $this->challenge['1']['0'];
$this->TransformCallList();
// login and gather login url
} else {
if ($this->GetCallListURL() !== FALSE) {
// get xml call data and transform to smartvisu format
$this->TransformCallList();
}
}
// cleanup
$this->challenge = '';
$this->call_list_url = '';
}
} // class end
// -----------------------------------------------------------------------------
// call the service
// -----------------------------------------------------------------------------
$service = new phone_fritzbox_via_TR064(array_merge($_GET, $_POST));
echo $service->json();
?>
Kommentar