Fritz DECT

Z.B. HomeMatic, MAX! und andere
Antworten
Bstar
Beiträge: 36
Registriert: Mo 2. Jan 2017, 11:05
Wohnort: Düsseldorfer Gegend

Fr 3. Feb 2017, 12:06

Hallo,

wie im Thread viewtopic.php?f=4&t=721&start=10 erwähnt, habe ich mir ein Fritz (genauer Eurotronic) Comet Heizkörperthermostat geholt und möchte über Erfahrungen und Einbindung berichten. Erst mal vorweg: ich bin hochzufrieden und habe gleich noch ein paar zum Preis von 39€ nachgekauft. Die Einbindung in LM geht aber nur über Umwege.

Die Thermostate werden von der Fritzbox gesteuert, die Einbindung ist sehr einfach und schnell, die Montage hat auch an Ventilen unterschiedlichen Typs (vorher waren Heimeier und irgendein altes Danfoss-Ventil drauf) problemlos geklappt.

Erstmal wurde alles unter der Fritzbox-Oberfläche unter der Punkt "Smart Home" eingestellt. Man kann für jedes Thermostat einen eigenen wöchentlichen Plan einstellen, wann es heizen soll und wann abgesenkt wird. Zusätzlich kann man jedes Thermostat auch manuell auf einen Wert zwischen 8 und 28 oder ganz Ein/Aus einstellen, dieser Wert hält bis der nächste Übergang im wöchentlichen Plan dran ist. Außerdem kann man noch Urlaubszeiten oder Zeiten eintragen, in denen die Heizung sowieso aus ist.

Praktisch ist auch die Rückmeldung der Temperatur, so dass man auch was von den Geräten hat, wenn im Sommer nicht geheizt wird. Ebenso die "Fenster-Auf" Erkennung, man kann einstellen, wie lange dann das Ventil zubleibt.

Wenn der Stellmotor des Thermostats läuft, hört man das durchaus, aber ich finde nicht, dass es unangenehm laut ist. Das folgende Rauschen, wenn das Ventil aufgemacht wird, ist fast genauso laut.

Der Empfang des verwendeten DECT ULE Funks ist aus meiner Sicht sehr gut. Ich habe ein Thermostat irgendwo tief im Keller eingebaut, da muss das Signal durch mehrere Betonwände. Das WLAN-Signal (das von derselben Fritzbox kommt) ist hier nicht mehr empfangbar, das Thermostat arbeitet problemlos.

Nun aber zur Einbindung in den LM Air, schließlich möchte ich alles, was im Smart Home läuft unter einer Oberfläche finden.

Leider gibt es keine serienmäßige Integration in den LM, dabei hat AVM die HTTP Schnittstelle (AHA-API) recht gut beschrieben (https://avm.de/fileadmin/user_upload/Gl ... erface.pdf). Es scheint mir recht einfach, sowas in Javascript zu realisieren, es gibt sogar eine API zum herunterladen (https://www.npmjs.com/package/fritzapi). Auf diesem Weg könnte man sogar Fritzbox-Funktionen wie "Gastnetz Einschalten" direkt im LM aufrufen.

Solange es das nicht gibt, müssen wir uns anders helfen.

Eigentlich kann Prinzip kann man über einen einfachen Webrequest alle Funktionen aufrufen. Z. B. würde man mit
"http://fritz.box/webservices/homeautosw ... 3456789012"
die Temperatur eines Thermostats einstellen können. "param=48" wird dabei durch 2 geteilt, stellt also die Tempertaur auf 24 ein (somit sind auch "Halbe" möglich, z. B. 41 für 20,5 Grad). "ain" ist die Identifizierung des Thermostats, die kann man von der Smart Home-Seite auf der Fritzbox abschreiben (oder durch einen anderen http-Request-Befehl als Liste bekommen).

Die einfache Einbindung als http-Request in den LM scheitert aber am Paramter "sid": Das ist eine Session-ID, die über ein nicht ganz einfaches Verfahren gebildet wird, und nur eine Stunde gültig ist. AVM hat dies aus Sicherheitsgründen eingeführt, der Vorteil ist, dass das Passwort nicht im http-Request lesbar auftaucht. Aber im Moment haben wir m. W. keine Möglichkeit, als Anwender sowas direkt auf dem LM Air selbst zu generieren.

Also brauchen wir nun doch eine weitere Box, in meinem Fall ein Raspberry mit Rasbian Jessie als Betriebssystem.

(Nur so nebenbei: recht einfach auf dem Raspberry ist die Einbindung in FHEM. Hier muss nur das Modul "FBAHAHTTP" definiert werden und User+Passwort eingestellt werden. Wer FHEM gut findet, der wird so wohl am ehesten glücklich.)

Die oben erwähnte API unter Javascript bzw. Node.js sah vielversprechend aus, leider habe ich kaum Ahnung von Javascript, so dass ich einen anderen Weg gegangen bin.

Bei Github gibt es ein spannendes Shellscript (https://github.com/fbartels/scripts/blo ... x-login.sh), das die Session-ID generiert. Alle weiteren Befehle aus der AHA-Spezifikation können dann einfach mit dem "curl"-Kommando als Webrequest ausgeführt werden, die Skripten dazu waren schnell erstellt.

Die Skripte habe ich dann auf dem ebenfalls auf dem Raspberry laufenden Webserver als PHP-Skripte aufrufbar gemacht, so dass ich nun aus dem LM per Webrequest tatsächlich meine Thermostate ein- und ausstellen kann. Leider weiss ich noch keinen Weg, wie man die Temperatur im LM rückmelden kann.

In Imperihome klappt die Einbindung aber schon prima. Per crontab generiere ich alle 5 Minuten eine kleine Grafik der Temperaturen der Thermostate als SVG, die in Imperihome direkt als Webseite eingebunden und dargestellt wird.

Im Prinzip bin ich damit am Ziel, hätte mir aber gewünscht, dass die Einbindung einfacher ist :-)
--
LM Air und überwiegend GIRA
Bstar
Beiträge: 36
Registriert: Mo 2. Jan 2017, 11:05
Wohnort: Düsseldorfer Gegend

Di 14. Feb 2017, 10:40

So, nun ist die Rückmeldung der Thermostate auch in die JBMedia-Seite eingebunden. Dazu die "index.htm" in "c:\programme (x86)\airstudio\Theme 1" (bzw. "...Theme 2") nach "myindex.htm" im selben Verzeichnis kopieren und in dann einfach <img src="http://<raspberryip>/svggrafik.svg" /> an passender Stelle einfügen.

Das muss dann leider immer wieder neu gemacht werden, wenn sich die Seite ändert.

Wenn man nun statt der Standardseite die "myindex.htm" aufruft, sieht das so aus:
screendect.jpg
screendect.jpg (83.04 KiB) 2174 mal betrachtet
--
LM Air und überwiegend GIRA
Bstar
Beiträge: 36
Registriert: Mo 2. Jan 2017, 11:05
Wohnort: Düsseldorfer Gegend

Fr 7. Apr 2017, 14:53

Inzwischen geht es auch über JavaScript auf dem Raspberry. Auch wenn ich kaum Ahnung von JS habe, gibt es bei mir nun ein Skript (lmfritz.js), welches die Fritzbefehle direkt ausführt, man muss sich also keine Session-ID besorgen.

Voraussetzung ist, dass "node" installiert ist. "node" ist sozusagen ein JavaScript, dass nicht im Browser läuft, sondern auf dem Server (d. h. dem Raspberry) ausgeführt wird.

Wenn ich auf meinem Raspberry nun das unten angehängte Skript ausführe mit

# node lmfritz.js "ain=123456789012&switchcmd=gettemperature"

wird mir die aktuelle Raumtemperatur zurückgegeben. Den genauen Wert für die Zahl hinter ain hole ich mir vom Identifier für das Thermostat aus dem Fritzboxmenü für die Smart Home Geräte.

Genauso kann ich die anderen Kommandos der Fritz-AHA-Dokumentation ausführen und z. B. die Zieltemperatur setzen.

Der nächste Schritt wäre nun, dieses "node"-Programm auf den LM Air zu portieren, man kann ja eigene Oberflächen auf dem LM kopieren (siehe viewtopic.php?f=21&t=56&p=4965&hilit=javascript#p4965).

Im Moment stören aber noch die beiden node-"require"-Bibliotheken. Soweit ich das sehe, müssten nur noch ersetzt werden:
1. Die "http"-Aufrufe müssten durch die "minrequest"-Funktionen aus dem "lightman.js" ersetzt und
2. der Source zum "crypt"-Aufruf aus der node-Bibliothek kopiert und in den Code eingesetzt werden.

Danach wäre der Raspberry nicht mehr nötig und man könnte direkt per http-Request die AHA-Fritz-Befehle ausführen, das könnte dann z. B. wie folgt aussehen. In der Aktorenverwaltung unter "Netzwerk" als GET eingetragen würde

http://<lm-ip-address>/lmfritz.htm "ain=123456789012&sethktrsoll=40"

dann die Zieltemperatur auf 40/2= 20 Grad Celsius stellen. Die lmfritz.js müsste natürlich dazu in lmfritz.htm integriert sein.

Code: Alles auswählen

/**
* Light Manager Fritz Box Home Automation Interface (lmfritz.js)
*
* SETUP: 
* set fbusername and fbpassword to your Fritz!Box-login (line 26 of this code)
* 
* USAGE:  node lmfritz.js <fritzcommandstring>
*
* where <fritzcommandstring> contains a AHA-command according to the 
* AVM-Documentation:
*        http://www.avm.de/de/Extern/files/session_id/AHA-HTTP-Interface.pdf
* without the "session"-parameter which is automatically added by this 
* interface.
*
*
* Example:  
*  # node lmfritz.js "ain=123456789012&switchcmd=gettemperature"
* Returns measured temperature of a thermostate. Get 12-digit ain from your 
* fritzbox interface submenu "Home Network/Smart Home", omit the space. 
* Divide temperature by ten for temperature in Celsius.
*
* Implementation based on works from "thk4711" 
* (see code at https://github.com/pimatic/pimatic/issues/38)
*
*
* April 2017
*
**/

var fbusername = "fbuser";
var fbpassword = "fbpassword";

// All Requirements here:
var http = require('http');
var crypto = require('crypto');

// #############################################################################
var fritzGetSessionID = function(username, password, callback, options)
{
    if (typeof username != 'string') throw new Error('Invalid username');
    if (typeof password != 'string') throw new Error('Invalid password');

    options || (options = {});
    options.url || (options.url = 'fritz.box');

    var sessionID = "";
    try {

        http.request({host:options.url, path:'/login_sid.lua'}, function(response) {
            var str = '';
            response.on('data', function (chunk) {
                str += chunk;
            });

            response.on('end', function () {

                var challenge = str.match("<Challenge>(.*?)</Challenge>")[1];
var httpcommand = "/login_sid.lua?username=" + username + "&response="+challenge+"-" + crypto.createHash('md5').update(Buffer(challenge+'-'+password, 'UTF-16LE')).digest('hex')

                http.request({host:options.url,
path:httpcommand
},function(response){
                    var str = '';
                    response.on('data', function (chunk) {
                        str += chunk;
                    });
                    response.on('end', function () {
                        sessionID = str.match("<SID>(.*?)</SID>")[1];
                        callback(sessionID);
                    })
                }).end();
            });
        }).end();
    } catch (e) {
        throw new Error('Error getting sid from FritzBox. Please check login and url');
    }
};

// check if session id is OK
var fritzLogoutSession = function( callback, options)
{
    options || (options = {});
    options.url || (options.url = 'fritz.box');
    try {

        http.request({host:options.url, path:'/login_sid.lua?logout=1'}, function(response) {
            var str = '';
            response.on('data', function (chunk) {
                str += chunk;
            });
            response.on('end', function () {
                if (str.match("<SID>(.*?)</SID>")[1] == "0000000000000000") 
                  callback("logout successful") 
                else
                  callback("logout failed");
            });

        }).end();
    } catch (e) {
        throw new Error('Error loggin out from FritzBox.');
    }
};

// ######################## General Command ###########################################

var fritzAhaCommand = function(sid, command, callback, options)
{
    if (typeof command != 'string') throw new Error('Invalid command');

    options || (options = {});
    options.url || (options.url = 'fritz.box');

    http.request({host:options.url, path:'/webservices/homeautoswitch.lua?sid='+sid+'&'+command},function(response){
        var data = '';

        response.on('data', function (chunk) {
            data += chunk;
        });
        response.on('end', function () {
            var state = '';
            state = data.trim()
            callback(state);
        });
    }).end();
};


// ##################### main ##########################################


var command=" ";
var i=0;

process.argv.forEach((val, index) => {
  if (index==2) 
   command = val;
  i = index;
});

if ((i!=2) && (i!=3)) {
    throw new Error ('Usage: node lmfritz.js "ain=123456789012&switchcmd=<ahacommand>" [fritbox ip-address]');  
};

fritzGetSessionID(fbusername, fbpassword, function(sid){
    console.log(sid);

    fritzAhaCommand (sid, command , function (answer) {
       console.log(answer);
    });

    fritzLogoutSession (function (message) {
       console.log (message);
    }); 
   
});

Ich fürchte nur, ich habe jetzt im Frühling keine Zeit mehr für weitere Experimente...
--
LM Air und überwiegend GIRA
greensails
Beiträge: 5
Registriert: Fr 8. Dez 2017, 19:10

Sa 9. Dez 2017, 17:25

Hey Bstar oder wer mir helfen kann,

du sagtest wenn du

Code: Alles auswählen

# node lmfritz.js "ain=123456789012&switchcmd=gettemperature"
auf dem Raspberry ausführst wird dir die Temetratur zurückgegeben. Das kann ich noch nicht testen da meine Comet dect erst bestellt sind.

Aber wie sieht denn dein Befehl im Lightmanager aus?? Da bin ich selbst noch rechter Noob... :-)

Danke für deine Antwort
exmerci
Beiträge: 57
Registriert: Mo 23. Jan 2017, 19:56
Wohnort: Hildesheim

Do 11. Jan 2018, 18:54

Ich weiß nicht, ob hier noch gelesen wird, aber wenn ich das versuche:
Eigentlich kann Prinzip kann man über einen einfachen Webrequest alle Funktionen aufrufen. Z. B. würde man mit
"http://fritz.box/webservices/homeautosw ... 3456789012"
dann bekomme ich angezeigt, das der Zugriff verweigert wird.

EDIT:

Okay, jetzt habe ich Zugriff, aber das hilft mir nicht denn ich bekomme immer die Anzeige:
Erst mal der Aufruf mit gültiger SID:
wget --no-check-certificate 'https://xxx:450/webservices/homeautoswi ... ?ain=08761 0382489&switchcmd=setswitchoff&sid=e2a85326e794a6c0'

Ergebnis:
HTTP-Anforderung gesendet, warte auf Antwort... 403 Forbidden
2018-01-11 20:10:38 FEHLER 403: Forbidden.

EDIT:

Habe es jetzt ganz anders gemacht und es läuft jetzt. Antwort nicht mehr nötig.
Antworten