Fritz!DECT 200 - Einbindung in IPS

ja, ich auch auch noch nicht ganz.

Die $sid ist wie gesagt gefüllt. Aus der Funktion get_sid meldet sich das script aber mit leerem Inhalt zurück (über „Return null“). Dann meldet er lgosicherweise „login failed“. Durch die funktion get_sid steig ich noch nicht ganz durch.

In folgender Abfrage (aus der get_sid-Funnktion) scheitert der Inhalt der sid (in meinem Fall „a78477932d6e6871“). Verstehen tue ich die Abfrage leider noch nicht: Müßte wenn es bei euch geht am Inhalt der sid liegen…?

if ($sid && (preg_match("/^[0]+$/",$sid)) && $challenge) {

gruß
hardlog

Hallo, ok, dann nehmen wir die Funktion mal auseinander.

Wir wollen uns einloggen und fragen als erstes nach der „Challenge“.


// get challenge string
 $http_response = file_get_contents($loginurl);
 $xml = simplexml_load_string($http_response);
 $challenge=(string)$xml->Challenge;
 $sid=(string)$xml->SID;

Im Feld SID sollen dabei nur „0000000“ stehen, in Challenge ein Hex-String/Zahl
Jetzt prüfen wir

  1. steht in $sid überhaupt was
  2. Der String in $sid besteht von Anfang bis Ende nur aus „0“
  3. Die challenge ist nicht null.
    Um das zu testen, könnte man sich $sid und $challenge vorher mal ausgeben zusammen mit print_r($xml) lassen.

 if ($sid && (preg_match("/^[0]+$/",$sid)) && $challenge) {

korrekter Weise sollte man schreiben

 if (isset($sid) && (strlen($sid)>0) && (preg_match("/^[0]+$/",$sid)) && (isset($challenge)) && (strlen($challenge)>0) && (hexdec($challenge)>0)) {

Dann wird die erhaltene Challenge mit dem Password verknüpft, abgesendet und die Antwort ausgewertet.

     //sid is null, got challenge
    $sid="";
    //build password response
    $pass=$challenge."-".$password;
    //UTF-16LE encoding as required
    $pass=mb_convert_encoding($pass, "UTF-16LE");
    //md5hash on top
    $md5 = md5($pass);
    //final answer string
    $challenge_response = $challenge."-".$md5;
    //send to box
   $url=$loginurl."?response=".$challenge_response;
   $http_response = file_get_contents($url);
   //check answer
   $xml = simplexml_load_string($http_response);
   $sid=(string)$xml->SID;

Das Ergebnis wird gepüft, ob in $sid ein Wert drin steht, der nicht nur Nullen hat. Wenn ja, wird der Wert als Ergebnis der Funktion zurückgegeben, wenn nicht, ist das Funktionsergebniss NULL. Das führt zu der von Dir beobachteten Fehlermeldung.

Zum Testen bitte auch hier mal einen print auf auf $sid vor dem If einbauen +print_r($xml)


if ($sid && !preg_match("/^[0]+$/",$sid)) {
            //is not null, bingo!
            return $sid;
   }

 }
 return null;
}//function

Schicke mir doch mal das Ergebnis der beiden neuen Prints bei If1 und If2.

Tommi

Hallo Tommi

ich hab als Kommentar in den code die werte eingetragen:

// get challenge string
 $http_response = file_get_contents($loginurl); 
    print_r($http_response); // Ergebniss: 40d227337ab6c65cf49ca4ee0Phone2NAS2HomeAuto2BoxAdmin2
 $xml = simplexml_load_string($http_response);
   print_r($xml); // Ergebniss: siehe unten
$challenge=(string)$xml->Challenge;
   print_r($challange); // Ergebniss: c20c512b
 $sid=(string)$xml->SID; 
   print_r($sid); // Ergebniss: f11c4f8fb6164901

Ausgabe von $xml:

SimpleXMLElement Object
(
    [SID] => eacbca905139e8de
    [Challenge] => d46e75f3
    [BlockTime] => 0
    [Rights] => SimpleXMLElement Object
        (
            [Name] => Array
                (
                    [0] => Phone
                    [1] => NAS
                    [2] => HomeAuto
                    [3] => BoxAdmin
                )
 
            [Access] => Array
                (
                    [0] => 2
                    [1] => 2
                    [2] => 2
                    [3] => 2
                )
 
        )
 
)

Die folgende IF-Bedinung wird scheinbar mit zuvor genannten Daten nicht erfüllt:

 if ($sid && (preg_match("/^[0]+$/",$sid)) && $challenge) {  

Da ich diese Zeile nicht ganz verstehe weiß ich nicht woran es liegen kann.

hardlog

ich verstehe nicht, woher das kommen kann:


[SID] => eacbca905139e8de 
zu 
$sid=(string)$xml->SID;  
 print_r($sid); // Ergebniss: f11c4f8fb6164901  

oder auch


[Challenge] => d46e75f3
zu
$challenge=(string)$xml->Challenge; 
   print_r($challenge); // Ergebniss: c20c512b 

Im ersten Kontakt sollte in SID nur „00000000“ stehen. Das wird geprüft. Bei Dir steht ein bereits ein Wert drin. Seltsam.
man könnte natürlich versuchen, auch gleich den ersten Wert zu nehmen



if ($sid && (preg_match("/^[0]+$/",$sid)) && $challenge) {  
...
}else { //neu
  if ((strlen($sid)>0) && (preg_match("/^[0-9a-f]+$/",$sid))) return $sid;//neu
}
return null;
}//function

Hallo Tommi,

wenn ich die SID direkt zurückgeben. Geht es!
Danke.

Gruß
hardlog

Habe mir die Scripte von Tommi (tolle Arbeit!) angeschaut und natürlich auch getestet. Schrittweises Verstehen brachte mich zu diesem kleinen Script, was natürlich nicht den ganzen Umfang wie fritz_aha_reader2 bietet, aber die Funktionen des Auslesens deutlich macht. Als erster Überblick für ein Gerät reicht es mir jedoch:

<?

include "fritzboxlogin.php"; // Fritzbox-Login - IPS-ID 37048
IPS_SetHidden($_IPS['SELF'], true);

// -----------------------------------------------------------------------------

/* Infos von AVM: http://avm.de/fileadmin/user_upload/Global/Service/Schnittstellen/AHA-HTTP-Interface.pdf

Kommando 				Aktion 																						Antwort

getswitchlist 			Liefert die kommaseparierte AIN/MAC Liste aller bekannten Steckdosen 	kommaseparierte AIN/MAC-Liste, leer wenn keine Steckdose bekannt
setswitchon 			Schaltet Steckdose ein 																	"1"
setswitchoff 			Schaltet Steckdose aus  																"0"
setswitchtoggle 		Toggeln der Steckdose ein/aus 														"0" oder "1" (Steckdose aus oder an)
getswitchstate 		Ermittelt Schaltzustand der Steckdose 												"0" oder "1" (Steckdose aus oder an), "inval" wenn unbekannt
getswitchpresent 		Ermittelt Verbindungsstatus des Aktors												"0" oder "1" für Gerät nicht verbunden bzw. verbunden. Bei Verbindungsverlust wechselt der Zustand erst mit einigen Minuten Verzögerung zu "0".
getswitchpower 		Ermittelt aktuell über die Steckdose												entnommene Leistung Leistung in mW, "inval" wenn unbekannt
getswitchenergy 		Liefert die über die Steckdose														entnommene Ernergiemenge seit Erstinbetriebnahme oder Zurücksetzen der Energiestatistik Energie in Wh, "inval" wenn unbekannt
getswitchname 			Liefert Bezeichner des Aktors 														Name
getdevicelistinfos 	Liefert die grundlegenden Informationen aller SmartHome-Geräte          XML-Format mit grundlegenden und funktionsspezifischen Informationen
*/

$ain = "087610110033";  // Aktor ID (Geräterückseite)
$cmd = "getdevicelistinfos"; // Kommando aus der API s.o.
$url = "http://fritz.box/webservices/homeautoswitch.lua?ain={$ain}&switchcmd={$cmd}&sid={$SID}";

if ($cmd != "getdevicelistinfos")
	{
	$content = Sys_GetURLContent($url);
	echo $content;
	}

else
	{
	$xmlstring=chop(file_get_contents($url));
	$xml = simplexml_load_string($xmlstring);
	//print_r ($xml);


		  foreach ($xml->device as $device) {
			 //attributes
			$ain=(string)$device->attributes()['identifier'];
			echo "AIN: 					" . str_replace(" ","", $ain)."
";

			$id=(string)$device->attributes()['id'];
			echo "ID: 					" . $id."
";

			$fwversion=(string)$device->attributes()['fwversion'];
			echo "Firmware: 			" . $fwversion."
";

			$produkt=(string)$device->attributes()['productname'];
			echo "Produktname: 		" . $produkt."
";

			$conn=(integer)$device->present;
			echo "Gerätepräsenz: 	" . (($conn==1) ? 'angemeldet':'abgemeldet')."
";

			$name=(string)$device->name;
			echo "Bezeichnung: 		" . $name."
";

			$state=(string)$device->switch->state;
			echo "Status: 				" . (($state==1) ? 'eingeschaltet':'ausgeschaltet')."
";

			$power=(string)$device->powermeter->power;
			echo "akt. Leistung: 	" . $power . " W
";

			$energy=(string)$device->powermeter->energy;
			echo "Gesamtleistung: 	" . $energy . " Wh
";

			$temp=(string)$device->temperature->celsius;
			echo "Temperatur: 		" . ($temp/10)." °C
";

		}
	}
	
?>

Das Logon-Script, was included wird:

<?

//$fritzbox 		= GetValue(15851 /*[EDV\Fritzbox\Basisdaten\Fritzbox 7390\Netzwerk\Fritzbox - Hostname]*/);
$fritzbox 		= GetValue(49286 /*[EDV\Fritzbox\Basisdaten\Fritzbox 7390\Netzwerk\Fritzbox - IP]*/);
$fritzpasswort	= GetValue(48902 /*[EDV\Fritzbox\Basisdaten\Fritzbox 7390\Netzwerk\Fritzbox - Passwort]*/);

// -----------------------------------------------------------------------------
// Beginn - Login in die Fritzbox

$ch = curl_init('http://' . $fritzbox . '/login_sid.lua');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$login = curl_exec($ch);

$session_status_simplexml = simplexml_load_string($login);


if ($session_status_simplexml->SID != '0000000000000000')
{
   $SID = $session_status_simplexml->SID;
}
else
{
   $challenge = $session_status_simplexml->Challenge;
   $response = $challenge . '-' . md5(mb_convert_encoding($challenge . '-' . $fritzpasswort, "UCS-2LE", "UTF-8"));

   curl_setopt($ch, CURLOPT_POSTFIELDS, "response={$response}&page=/login_sid.lua");
   $sendlogin = curl_exec($ch);
   curl_close($ch);
   $session_status_simplexml = simplexml_load_string($sendlogin);

   if ($session_status_simplexml->SID != '0000000000000000')
   {
   $SID = $session_status_simplexml->SID;
   }
   else
   {
      echo "Fehler: Login fehlgeschlagen";
      return;
    }
}
// Ende - Login in die Fritzbox
// -----------------------------------------------------------------------------

?>

Moin,

ich arbeite auch grade an einer Umsetzung für die DECT 200 und bin dabei auf ein Problem gestoßen und wollte mal hören wie ihr das geregelt habt.

Ich schreibe mir eine Software unter C# für Windows und Linux, die dann abhängig von einer gewissen Logik meine Aktoren schalten soll. Die Logik bezieht sich auf meine Photovoltaik Anlage, vereinfacht gesagt lese ich die momentanen Werte meiner PV Anlage aus und versuche dann durch intelligentes Schalten der Dosen möglichst viel Strom,
den ich selber produziere auch selber zu nutzen und nicht einspeisen zu müssen.

Soweit - so gut,…nun habe ich aber festgestellt das das AHA zwar munter über den Response der HTTP Seite mitteilt Dose wurde eingeschaltet „1“ oder ausgeschaltet „0“, habe aber nach einigen Tests festgestellt, das das gar keine Rückmeldung der Aktoren ist, sondern die Fritzbox selber das sendet und teilweise erst Minuten später „merkt“
wenn ein Aktor defekt ist oder nicht mehr in der Dose sitzt.

Das führt in meinem Fall dann zu teils argen Problemen, wenn ich bspw. den Eisschrank nachts deaktivere, ihn morgens bei den ersten Sonnenstrahlen dann einschalte, die Fritzbox „1“ zurück gibt, die Dose aber gar nicht
aktiviert wurde, weil irgendwas nicht stimmt.

Wie kann man das denn umgehen … kann mir da einer einen Tip geben ? ich habe schon überlegt die Verbrauchswerte abzufragen in regelmäßigen Intervallen, aber auch hier ist es so das das teilweise erst minuten später „auffällt“ das der Verbrauch „0“ oder „inval“ ist,…

Würde mich über ein paar Tips freuen

Gruß
fahrstuhl

Moin,

ich habs jetzt gelöst, für die die vielleicht auch mal drüber stolpern:

Unmittelbar nach aktivieren des Aktors über JSON die Fritzbox Energieanzeigeseite auslesen, die dem aktor zugeordnet ist, dort gibt es den wert „MM_Value_Amp“, der die Stromstärke in A angibt. die steht nach aktivieren immer bei mindestens bei ca. 60, auch wenn - so wie in meinem Fall - das Gerät 0,00 Watt zieht (sonst hätte ich das über AHA lösen können).

Nebenbei bemerkt erhält man so auch die letzten 60 Werte Wattverbrauch von der Dose geliefert und kann so auch bspw. gleitende Durchschnitte besser berechnen.

wenn die Dose deaktiviert ist, pendelt dieser Wert immer zwischen 11 und 16.

Ist zwar etwas umständlicher, aber so kann ich wirklich sicher sein, das die Dose eingeschaltet ist und mit gutem Gewissen in die DB eintragen, das das Gerät aktiviert ist :wink:

gruß
fahrstuhl

Hallo zusammen,

erst einmal vielen Dank an Tommi für die viele Arbeit, die in den FritzDect PHP Skripten steckt!!! :slight_smile:
Ich habe heute meine IP-Symcon Umgebung auf die aktuelle 3.3 Version geupdated und danach gleich versucht nun meine FritzDECT 200 Steckdosen mittels meiner FritzBox auszulesen. Hierfür habe ich das Fritz_aha_reader2 Skript entsprechend in IP-Symcon angelegt und versucht auszuführen. Leider tritt hierbei jedoch immer wieder folgende Fehlermeldung auf:

Fatal error: Call to undefined function mb_convert_encoding() in C:\IP-SYMCON\scripts\fritz_aha_reader2.phps on line 172

Diese wird wiederum durch folgende IF-Abfrage zu Beginn des Skripts erzeugt:

if (!function_exists('mb_internal_encoding')) {
   die ("Need Multibyte functions (mb_string_convert)!
");
}

Daher wäre meine Frage an euch, wie ich die Mulitbyte functions in IP-Symcon nachinstalliert bekomme bzw. ob von euch schon jemand dieses Problem hatte? :wink:

Habt vielen Dank schon im Voraus für eure Unterstützung und viele Grüße aus dem hohen Norden,
Akio

Ich habe das Update auf 3.3. gemacht und hatte anschliessend keine Probleme mit der Extension. Im ext Ordner sollte eine php_mbstring.dll vom 13.2.2014 liegen.

Tommi

Hallo Tommi,

klasse, hab ganz lieben Dank für die schnelle Hilfe! Genau daran hat es gelegen, dass mir in meinem IP-Symcon ext Ordner die „php_mbstring.dll“ fehlte, die ich dann einfach aus dem PHP gesamt Package herauskopiert habe. Nun funktioniert alles tadellos und ich kann endlich meine kleine Gartenhaussolaranlage mit loggen. :smiley:
Vielen Dank nochmal für die tollen AHA Skripte, Tommi!

Viele Grüße und let’s connect,
Akio

Morgen,

hat von euch zufällig jemand ein funktionierendes Script auf nem Raspberry laufen? Bei mir gehts nicht.

Liegt es an den php-Extensions?

Gruß
hardlog

Morgen,

ist stehe mal wieder auf besagter Leitung…
Ich nutze folgendes script (aus diesem Beitrag):

function Fritzbox_DECT200_Energie($device, $Zeit)
    {
    $Daten="";
     $SID=FritzBox_login();

    If ($SID <> "Fehler: Login fehlgeschlagen")
        {
        Switch($Zeit)
           {
           case 1:      // Abfrage der Messwerte der letzten 10 min
           $Daten= file("http://fritz.box/net/home_auto_query.lua?sid=". $SID. "&command=EnergyStats_10&id=". $device. "&xhr=1");
            break;
            
            case 2:      // Abfrage der Messwerte der letzten 24h
            $Daten= file("http://fritz.box/net/home_auto_query.lua?sid=". $SID. "&command=EnergyStats_24h&id=". $device. "&xhr=1");
            break;
            }
            
        If ($Daten <>"")
            {
            $Daten=explode('" , "', $Daten[1]);
            $x=count($Daten)-1;
            $temp=explode('" ,"', $Daten[$x]);
            Foreach ($temp as $tem)
                    {
                    $Daten[$x]=$tem;
                    $x++;
                    }
            }
          else
            {
            $Daten[0]="Keine Werte vorhanden";
            }
        return ($Daten);
        }
    }
/*
        Ergebnis bei EnergyStats_10:

        Array[0] = Anzahl der Leistungsmessungen (hier 60)
        Array[1] = Timer der Leistungsmessung (hier 10= alle 10s)
        Array[2]-Array[61] = Messwerte
        Array[62] = minimaler Messwert in Zeitspanne (60x10s = 10 min)
        Array[63] = maximaler Messwert in Zeitspanne (60x10s = 10 min)
        Array[64] = Durchschnitts Messwert in Zeitspanne
        Array[65] = Anzahl der Spannungsmessungen
        Array[66] = Timer der Spannungsmessung (hier 10 = alle 10s)
        Array[67]-Array[126] = Messwerte
        Array[127] = Status (an / aus)
        Array[128] = ID
        Array[129] = Verbinddungsstatus (hier 2= OK)
        Array [130]  RequestResult ????


        Ergebninis bei EnergyStats_24h:

        Array[0] = Anzahl der Leistungsmessungen (hier 96 = alle 15 min = 4*15*24)
        Array[1] = Timer der Leistungsmessung (hier 900= alle 900s = 15min)
        Array[2]-Array[97] = Messwerte
        Array[98] = minimaler Messwert in Zeitspanne (60x10s = 10 min)
        Array[99] = maximaler Messwert in Zeitspanne (60x10s = 10 min)
        Array[100 = Durchschnitts Messwert in Zeitspanne
        Array[101] = Status (an / aus)
        Array[102] = ID
        Array[103] = Verbinddungsstatus (hier 2= OK)
        Arry [104]  RequestResult ????

        */


Wie komme ich von dort auf den Verrauch (kWh)? die 96 werte addieren oder wie?

Dank
hardlog

Hi,

ich habe mal eine Frage zu der DECT200:

Sobald ich die Scripte von Swifty (Danke dafür) einbinde und den loginbereich mit meinem Passwort ausführe bekomme ich den Fehler, dass das Result der Funktionen, welche die Funktion "Fritzbox_DECT200_Status abfragen, leer ist.
Es wird auf den Arrayeintrag [1] geschaut, der bei mir nicht vorhanden ist. Mit [0] komme ich zwar weiter, habe aber ein paar Zeilen weiter beim füllen der Daten schon wieder Probleme.

Ergo => das Result ist fehlerhaft. Ich habe mir auch den Zählwert $count ausgeben gelassen. Dieser ist ebenfalls 0.

Der login scheint aber, so wie ich das sehe zu funktionieren.
Dort habe ich lediglich diese Zeilen geändert, bzw auskommentiert:

       //curl_setopt($ch, CURLOPT_POSTFIELDS, "response={$response}&page=/login_sid.lua&username={$fritzbox_Username}");
	   curl_setopt($ch, CURLOPT_POSTFIELDS, "response={$response}&page=/login_sid.lua");

Ich bekomme auch eine vernünftige SID ausgegeben, welche bei jedem aufruf eine andere ist, aufgrund des jeweiligen logins.

kann mir da jemand weiterhelfen??

function Fritzbox_DECT200_Status()
    {

    $SID=FritzBox_login();
    If ($SID <> "Fehler: Login fehlgeschlagen")
        {
        $Result=file("http://fritz.box/net/home_auto_query.lua?sid=". $SID. "&command=AllOutletStates&xhr=0");
        $Result=explode('" ,"', $Result[1]);		

        $count=substr($Result[0],-1);
		
      for ($i = 1; $i <= $count; $i++)
            {
            $Daten[$i][]=explode('" : "', $Result[(3*$i)-3+1]);
            $Daten[$i][]=explode('" : "', $Result[(3*$i)-3+2]);
            $Daten[$i][]=explode('" : "', $Result[(3*$i)-3+3]);
            }
        }
    return($Daten);

    }

Das ist das betreffende Script. Ich habe anschließend auch folgefehler, die u.U. aus dem genannten resultieren.

Vielen Dank,

Sven

das ist übrigends mein ergebnis in $result:

Array
(
    [0] => {"RequestResult":false}

)

mfg sven

wäre absolut dankbar um jede hilfestellung!

Wenn Du IP-Symcon 4 nutzt würde ich einfach das PHP Modul von Tommi nutzen, das erspart Dir jegliche Arbeit bzw. Skripte.
ipsymcon-phpmodule-by-Tommi/README.md at 4.4 · Tommi2Day/ipsymcon-phpmodule-by-Tommi · GitHub

sehr cool vielen dank!

hab etwas gebraucht, aber es läuft!!!

Ich habe mir das Modul von Tommi geholt -> vielen Dank dafür
Ich würde gerne den gesamten Verbrauch eines bestimmten Tages (z.b. gestern) erhalten.
Gibts es dafür eine Möglichkeit?

Danke

Hallo
ich habe mir das ganze Thema jetzt x-mal durchgelesen aber irgendwie stehe ich noch im dunkeln:confused:

Aus dem Modul von Thommi werde ich leider auch nicht schlau…
Installiert habe ich es, aber dann…:confused:

Wäre es möglich hier vll eine Anleitung zu bekommen?
Welche Skripte brauch ich wirklich und welche müssen wo hin?

Vll gibt es ja auch ein komplettes mit wo ich nur die Aktor-ID und PW ergänzen müsste