Newbie mit TR064

JoeMuc2014

Neuer User
Mitglied seit
12 Jun 2014
Beiträge
2
Punkte für Reaktionen
0
Punkte
1
Hi zusammen,

leider finde ich den Einstieg in die Programmierung der TR064-Schnittstelle alles andere als intuitiv und hoffe, Ihr könnt mir ein paar Tipps geben.
Ich bastle an einem VB6-Client-Programm, das das Wählen über die Fritz!Box ermöglichen soll. Also quasi das, was man bei einer "richtigen" Telefonanlage als Fremdwahl bezeichnet. Es soll die Möglichkeit geben, die Nebenstelle anzugeben, für die gewählt werden soll, und natürlich die Nummer des Teilnehmers.
Das geht seit der Einstellung des Fritz!Box TAPI-Treibers nur noch über TR064. Ich habe eigentlich schon einige Jahre IT / Programmieren auf dem Buckel, aber was AVM da macht, ist für mich "böhmische Dörfer".
Die Dokumentation von AVM, wenn man sie denn so nennen will, habe ich gelesen und bin daraus nicht schlau geworden. Die dünn gesäten Beispiele sagen an keiner Stelle, ob das, was da beispielhaft beschrieben wird, unbedingt erforderlich ist für einen erfolgreichen Ablauf oder optional.
Ich habe die Discovery hinbekommen und auch das Erlangen einer SID, aber nun geht es ans Senden von SOAP-Befehlen und da komme ich nicht weiter.
Habe Fiddler4 im Einsatz, um die Kommunikation mitzuschneiden, aber es hilft nicht wirklich.
Für die Netzwerkkommunikation nutze ich die WinHTTP-Services. Das Microsoft SOAP Interface kommt eigentlich nicht in Frage, weil es mit SCPD-Definitionen nicht klarkommt (kann nur WSDL, soweit ich weiß), und ich möchte meine Lösung auch möglichst unabhängig machen von Voraussetzungen im System. WinHTTP ist eben immer an Bord, SOAP zumindest nicht sicher immer in derselben Version.

Beispielsweise schicke ich folgende selbstformulierte SOAP-Abfrage (meine Fritz!Box ist unter 192.168.74.1 im Netz permanent erreichbar), sie entstammt dem Beispiel aus dem TR-064: First Steps PDF von AVM:

Code:
<?xml version="1.0" encoding="UTF-8"?>
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
  <s:Header>
    <h:InitChallenge xmlns:h="http://soap-authentication.org/digest/2001/10/" s:mustUnderstand="1">
      <UserID>johannes</UserID>
    </h:InitChallenge>
  </s:Header>
  <s:Body>
    <u:GetClients xmlns:u="urn:X_VoIP-com:serviceId:X_VoIP1"></u:GetClients>
  </s:Body>
</s:Envelope>

In RAW sieht das lt. Fiddler so aus:

Code:
POST http://192.168.74.1:49000/upnp/control/x_voip?sid=13d4de74618cee81 HTTP/1.1
SOAPACTION: urn:X_VoIP-com:serviceId:X_VoIP1#GetClients
USER-AGENT: AVM UPnP/1.0 Client 1.0
Content-Length: 423
Accept: */*
[B][COLOR=#ff8c00]Host: 192.168.74.1:49000[/COLOR][/B]
Proxy-Connection: Keep-Alive

<?xml version="1.0" encoding="UTF-8"?><s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"><s:Header><h:InitChallenge xmlns:h="http://soap-authentication.org/digest/2001/10/" s:mustUnderstand="1"><UserID>johannes</UserID></h:InitChallenge></s:Header><s:Body><u:GetClients xmlns:u="urn:X_VoIP-com:serviceId:X_VoIP1"></u:GetClients></s:Body></s:Envelope>

Es ist eigentlich egal, welche Anfrage ich an welchen Dienst schicke, zurück kommt IMMER:

Code:
HTTP/1.1 500 Internal Server Error
Connection: close
Content-Length: 1226
Content-Type: text/html

<HTML><HEAD><TITLE>500 Internal Server Error (ERR_INVALID_REQ)</TITLE></HEAD><BODY><H1>500 Internal Server Error</H1><BR>ERR_INVALID_REQ<HR><B>Webserver</B> Mon, 05 Sep 2016 16:43:02 GMT</BODY></HTML>

... gefolgt von mehr oder weniger tonnenweise Leerzeichen, um die angegebene unsinnig lange Content-Length zu erreichen. Ich habe schon so gut wie alles versucht, u.a. auch, ob bei absichtlichen Falschangaben der Fehler vielleicht anders aussieht. Tut er aber nicht. Das einzige, was sich jemals ändert, ist die Uhrzeit, manchmal auch die Content-Length, da variiert aber nur die Anzahl an Leerzeichen, die an der Antwort hinten dranhängen. Es scheint grundsätzlich was zu klemmen, keine Ahnung was. Folgendes habe ich probiert:


  • SOAP-XML absichtlich ungültig gemacht durch Einfügen ungültiger Zeichen / Namen
  • Header-Angaben falsch geschrieben
  • Fiddler4 als Proxy (Port 8888) ist testweise eingerichtet, aber auch wenn ich ihn umgehe, bleibt das Problem. Am Fiddler liegt es definitiv nicht

Was mir auffällt ist, dass im Request-Header hinter POST die volle Serveradresse kommt, wo normalerweise nur das Segment ab dem Servernamen folgt (beginnend mit einem Slash). Da ich aber einem WinHTTP-Request keinen Host vorgeben kann, sondern alles nur in einem URL verpackt weitergeben kann, wüsste ich nicht, wie ich den Servernamen hier loswerde. Zumindest scheint WinHTTP ihn zu erkennen, denn der "Host:"-Header-Eintrag, den Fiddler mitschneidet (oben in orange markiert), wird nicht durch mich explizit gesetzt. Ich setze lediglich die Werte SOAPACTION und USER-AGENT.

Ein Test im Browser, ob der angesprochene URL funktioniert, bringt übrigens ebenfalls immer dasselbe Ergebnis:

Code:
<HTML><HEAD><TITLE>404 Not Found (ERR_NOT_FOUND)</TITLE></HEAD><BODY><H1>404 Not Found</H1><BR>ERR_NOT_FOUND<HR><B>Webserver</B> Mon, 05 Sep 2016 17:11:01 GMT</BODY></HTML>

z.B. als Resultat, wenn ich die Adresse

Code:
http://192.168.74.1:49000/upnp/control/x_voip

aufrufe.

Irgendwie habe ich den Eindruck, dass auf meiner Fritz!Box die TR-064-Dienste gar nicht vorhanden sind. Man sieht aber eine lange Liste von Diensten, wenn man http://192.168.74.1:49000/tr64desc.xml aufruft.
Die internen Logs des Fritz!Box-Webservers, falls er welche erzeugt, könnten spannend sein. Aber wie kommt man an die ran?

Herzlichen Dank schon einmal!

Grüße
Johannes

- - - Aktualisiert - - -

So, bin etwas weiter gekommen, dank eines c't-Artikels (2015, Heft 6), da wird einiges klarer.

Demnach folgende Erkenntnisse:


  • die SID scheint man nicht zu benötigen - weiß nicht, wieso AVM das dann sogar in einer eigenen Dokumentation so genau beschreibt
  • beim Kopieren aus PDFs werden Minuszeichen verschluckt, wenn sie bei einem Zeilenumbruch standen. So wurde aus urn:dslforum-org dann urn:dslforumorg
  • als erstes muss man unter /upnp/control/deviceinfo den GetSecurityPort-Befehl ausführen, um an den SSL-Port zu kommen. Alle weitere Kommunikation geht dann nicht mehr mit http, sondern https=SSL, und unter Verwendung dieser Portnummer (normalerweise 49443 statt http-Port 49000)
  • der Versuch, die Schnittstelle ohne https zu verwenden, scheint wohl grundsätzlich mit 500 Internal Server Error beantwortet zu werden
  • das Verfahren, einen SOAP-Request mit einem <s:Header>-Element und darin einem <h:ClientAuth>-Element zu versehen, scheint man ebenfalls nicht zu benötigen
  • statt dessen werden Benutzername und Kennwort beim WinHTTP-Request per SetCredentials()-Befehl gesetzt. Kennwort im Klartext, was zumindest unterwegs wegen der Transportverschlüsselung nicht gefährlich sein sollte
  • Den USER-AGENT-Wert im Header kann man weglassen
  • Als Content-Type muss im Header ganz exakt text/xml; charset="utf-8" angegeben werden. Alles andere funktioniert nicht
  • Im Request-Body muss die erste Zeile lauten <?xml version="1.0"?>. Kein Encoding angeben!
  • bei der Request.Open-Methode NUR den Fritz!Box-URL und die Serviceadresse angeben, z.B. https://fritz.box:49443/upnp/control/wanpppconn1. Auf keinen Fall hier so was wie ?sid={SID} anhängen! Sonst gibt's Fehler 401 Invalid Action.
  • dem WinHTTP-Request muss man noch beibringen, dass er sich nicht um Zertifikatsfehler kümmern soll - das Zertifikat, das die Fritz!Box selbst für SSL ausstellt, ist natürlich nicht wirklich vertrauenswürdig:

Code:
oReq.Option(WinHttpRequestOption_SslErrorIgnoreFlags) = SXH_SERVER_CERT_IGNORE_UNKNOWN_CA Or SXH_SERVER_CERT_IGNORE_WRONG_USAGE Or SXH_SERVER_CERT_IGNORE_CERT_CN_INVALID Or SXH_SERVER_CERT_IGNORE_CERT_DATE_INVALID


  • Windows 2003 R2 bzw. Windows XP kann man offenbar wegen der unsicheren Kommunikation gar nicht mehr verwenden
  • die Fritz!Box gibt unter http://fritz.box:49000/tr64desc.xml die Daten zu den Services aus. Zu X_VoIP gibt es hier sowohl den ServiceType urn:dslforum-org:service:X_VoIP:1 als auch die ServiceID urn:X_VoIP-com:serviceId:X_VoIP1. Nur der ServiceType ist von Bedeutung und muss sowohl in der SOAPACTION als auch innerhalb des RequestBody verwendet werden. Nicht versehentlich die ServiceID verwenden

Das ist im Ergebnis weniger als Halbwissen, aber immerhin funktioniert jetzt das eine oder andere. Ich finde es erschreckend, dass auf all diese Umstände in der AVM-"Dokumentation" nicht hingewiesen wird. Es hätte mir diverse Stunden Frickelei und frustrierendes Rumprobieren erspart. Ich hoffe, ich kann vielleicht dazu beitragen, dass andere das nicht durchmachen müssen.
Nun aber zur Fremdwahl: mein Eindruck ist, dass sämtliche Befehle in X_VoIP sich tatsächlich nur auf SIP-Konten beziehen. Laut AVM-Marketing soll es aber auch möglich sein, für klassische Anschlüsse (analog / ISDN) über X_VoIP zu wählen und das Gespräch an ein angeschlossenes Festnetztelefon zu übergeben. Ich habe nicht den Eindruck, dass die Schnittstelle das hergibt. Ich verwende selbst die Fritz!Box mit einem analogen DECT-Telefon mit zugewiesener externer MSN, über die das Telefon erreichbar ist und auch rauswählen kann. Kein SIP-Account. Diese Konfiguration dürfte bei vielen Standard sein, und das würde ich gerne per Software unterstützen.
Aber X_AVM-DE_GetNumberOfClients gibt mir eine 0 (Null) zurück, ebenso GetExistingVoIPNumbers, und X_AVM-DE_GetClients bringt eine leere Liste. Also werden die analogen und ISDN-Nebenstellen sowie die verfügbaren klassischen Telefonleitungen offenbar gar nicht über das X_VoIP-Interface verwaltet, sonst hätte ja irgendwo mal irgendetwas wiedererkennbar stehen müssen von meiner derzeitigen Konfiguration, ergo wird es wohl nicht möglich sein, für diese Nebenstellen eine Fremdwahl zu implementieren, oder?
Und nein, urn:X_AVM-DE_Dect-com:serviceId:X_AVM-DE_Dect1 hilft da auch nicht, zumindest nicht jedem, weil da wohl nur die direkt an der Fritz!Box angemeldeten DECT-Geräte gesteuert werden können, aber keine mit eigener Basisstation.

Hat mich AVM's Marketing in die Irre geschickt? ich fürchte fast...
Würde mich freuen, wenn hier eine konstruktive Diskussion entsteht.
 
https://avm.de/service/schnittstellen/
https://avm.de/fileadmin/user_upload/Global/Service/Schnittstellen/X_voipSCPD.pdf

X_AVM-DE_GetPhonePort
X_AVM-DE_DialGetConfig
X_AVM-DE_DialSetConfig
X_AVM-DE_DialNumber
X_AVM-DE_DialHangup

Beispiele aus dem IPPF:
http://www.ip-phone-forum.de/showthread.php?t=285557 (da wird dann auch der c't-Artikel irgendwann erwähnt)
http://www.ip-phone-forum.de/showthread.php?t=279513 (liegt noch näher an dem, was Du wohl machen willst, die Quellen von @kruemelino sind frei zugänglich, die Aufzählung der Schnittstellen von oben findest Du da auch schon)

Alles nicht großartig "versteckt" ... für mich persönlich will ich festhalten, daß "eine (weitere) konstruktive Diskussion" bei konkreten Problemen mit der Implementierung vielleicht interessant wäre, aber eine allgemeine "wie mache ich das"-"Unterhaltung" der Allgemeinheit wohl eher nichts bringen wird (die gibt es ja durchaus schon) - abgesehen davon würde wohl niemand unter einem Thread-Titel "Newbie mit TR-064" eine derartige Diskussion vermuten. Ich habe am Beginn auch eher überlegt, was denn "Newbie" für ein Gerät sein könnte und was man dort über TR-064 nun steuern kann.
 
Wahnsinn, vielen Dank für diese Infos! Das bringt mich sicher weiter. Ich werde es bei nächster Gelegenheit ausprobieren und melde mich dann wieder. Natürlich berichte ich auch gerne über die Entwicklung und meine Ergebnisse.

Grüße
Joe
 
Moins & weils hier grad reinpasst...

Unter Linux hab ich mal ein Shellskript gebastelt, welche die aktuellen XML SCPD-Daten einer Fritz!Box ermittelt (tr64desc.xml) und daraus eine HTML mit den Links zu den einzelnen SCPD-XML erstellt.

scpd.sh
Code:
#!/bin/bash
fb='http://fritz.box:49000/'
lastxml='dummy.xml'

[ ! -e ${1}.txt ] && (wget -q -O- ${fb}tr64desc.xml | grep -E -o "[-_0-9a-zA-Z]{1,32}[.]xml" > ${1}.txt) || (rm ${1}.txt ; exit)
echo '<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="application/xhtml+xml; charset=utf-8">
<link rel="shortcut icon" type="image/x-ico" href="favicon.ico" />
<title>SCPD</title>
</head>
<body>' >${2}.html
for xml in $(cat ${1}.txt) ; do
if [ ${xml} != ${lastxml} ]
then
 printf "<a href=\"view-source:${fb}%s\">%s</a><br/>\n" ${xml} ${xml} >> ${2}.html
 printf "."
fi
lastxml=${xml}
done
echo '</body>
</html>
' >>${2}.html
printf "\n"
#EOF
Aufruf: bash scpd.sh scpd scpd
Ergebnis: scpd.txt scpd.html

Screenshot_2016-11-24-10-37-19.jpg
Screenshot der scpd.html einer 7560 mit Fritz!OS 6.69 BETA
 
Zuletzt bearbeitet:

Zurzeit aktive Besucher

Statistik des Forums

Themen
246,159
Beiträge
2,247,074
Mitglieder
373,678
Neuestes Mitglied
brainkennedy
Holen Sie sich 3CX - völlig kostenlos!
Verbinden Sie Ihr Team und Ihre Kunden Telefonie Livechat Videokonferenzen

Gehostet oder selbst-verwaltet. Für bis zu 10 Nutzer dauerhaft kostenlos. Keine Kreditkartendetails erforderlich. Ohne Risiko testen.

3CX
Für diese E-Mail-Adresse besteht bereits ein 3CX-Konto. Sie werden zum Kundenportal weitergeleitet, wo Sie sich anmelden oder Ihr Passwort zurücksetzen können, falls Sie dieses vergessen haben.