AVM Smarthome Devices wie Fritz!Powerline 546e Auslesen und Schalten

'ne Kleinigkeit ist mir noch nicht klar. Wie ändere ich die ID:

Hallo Tommi,

ich habe einfach am ende des actor scripts ein IPS_RunScript mit read_fritz gehangenen, dann wird es auch ziemlich zeitnah aktualisiert.

Das ist der Name, der in der Weboberfläche des Fritz546(Powerline->Bezeichnung) bzw in der Fritzbox (Smarthome-Profil Name) eingestellt ist. Zum Ändern also dort einstellen. Der Name wird mit der API-Funktion „getswitchname“ abgeholt und in das ID-Feld gepackt.

Tommi

Hallo Tommi,

das steht bei mir in der Bezeichnung.

bezeichnung.jpg

Ist aber was anderes als in der ID steht :confused:

welches Script ist das? Schau doch bitte noch einmal auf meiner Webseite nach, ob dort evtl. eine neuere Version steht. Bei mir klappt das Problemlos.

Tommi

Hallo Tommi,

das Script habe ih gestern von Deiner Seite geladen, evtl. habe ichj auch was verkehrt gemacht.

<?php
/*
readout a Fritz Powerline 546E
http://www.tdressler.net/ipsymcon/fritz_aha.html
V0.4 12.10.2013
see also
http://www.avm.de/de/Extern/files/session_id/AVM_Technical_Note_-_Session_ID.pdf
http://www.avm.de/de/Extern/files/session_id/AHA-HTTP-Interface.pdf
*/
if (!function_exists('mb_convert_encoding')) {
   die ("Need mbstring_extension!
");
}

/* config section, pls adopt this for your device */
$catname='Fritz Powerline';
$sensorname='Waschmaschine'; //will be expanded with host name
$host='192.168.1.*';
$password = '****'; //login password
$GLOBALS['autocreate']=true;
/* end config section */

//api urls
$loginurl="http://".$host."/login_sid.lua";//login_sid.lua for fritzos 5.50+
$ahaurl="http://".$host."/webservices/homeautoswitch.lua";//api url
$actorurl="http://".$host."/net/home_auto_overview.lua";//actorurl
//Variable definitions
$vartypes=array(	'ID'=>array('type'=>3,'profile'=>''),
               	'AIN'=>array('type'=>3,'profile'=>''),
               	'Host'=>array('type'=>3,'profile'=>''),
						'Status'=>array('type'=>0,'profile'=>'~Switch'),
						'Total Energy'=>array('type'=>2,'profile'=>'~Electricity'),
						'Last Energy'=>array('type'=>2,'profile'=>'~Electricity'),
						'Actual Power'=>array('type'=>2,'profile'=>'Power_W.3')
					);

//define profile for actual usage (getswitchpower) value
check_profile('Power_W.3',2,null,' W',0,null,1,3,false);

//login to switch
$sid=get_sid($loginurl,$password);
if (!isset($sid)) {
   IPS_LogMessage("Fritz546", "Login failed");
   return;

}

//get AIN
$ain=get_ain($actorurl,$sid);
if (!$ain) {
		IPS_LogMessage("Fritz546", "No AIN found,cancel");
		return;
}
//prepare url for this actor
$url=$ahaurl.'?ain='.$ain.'&sid='.$sid;
//retrieve actor name
$name = chop(file_get_contents($url."&switchcmd=getswitchname"));
if (!$name) {
	IPS_LogMessage("Fritz546", "No Answer for name query on $host");
	return;
}
//query device values
$status = chop(file_get_contents($url."&switchcmd=getswitchstate"));
$power = chop(file_get_contents($url."&switchcmd=getswitchpower"));
$new_total = chop(file_get_contents($url."&switchcmd=getswitchenergy"));

//get IPS Variable IDS and Values below defined section
$varids=get_ips_vars($name,$vartypes,$catname,$sensorname);
if (is_null($varids)) {
  //no vars available, maybe autocreate disabled
  IPS_LogMessage("Fritz546", "get_ips_vars failed");
   return;
}


//retrieve
$total=$varids['Total Energy']['val'];

//prepare output
if (preg_match("/^\d+$/",$power)) {
	$actual=$power/1000; //mW->W
}else{
   $actual="?";
   print "Error:".$name." getswitchpower=".$power;
   return;
}
if (preg_match("/^\d+$/",$new_total)) {
   $new_total=$new_total/1000; //Wh ->KWh
   $energy=$new_total-$total;
}else{
   $energy="?";
   print "Error:".$name." getswitchenergy=".$new_total;
   return;
}

//store in IPS
SetValue($varids['Total Energy']['id'],$new_total);
SetValue($varids['Last Energy']['id'],$energy);
SetValue($varids['Actual Power']['id'],$actual);
if ($status !=$varids['Status']['val']) SetValue($varids['Status']['id'],$status);
if ($ain!=$varids['AIN']['val']) SetValue($varids['AIN']['id'],$ain);
if (($varids['Host']['val']==0) || ($host!= $varids['Host']['val']))  SetValue($varids['Host']['id'],$host);

//logging
IPS_LogMessage("FRITZ546", $name.":".(($status=="1")?"On":"Off")." (Act:".$actual." W, Diff: ".$energy." Wh Power: $power mW, Total:$new_total Kwh)");

/* end */
//-------------------------------------------------------------------------------
 /**
  * login into fritz and get sid
  * @param string loginurl url for accessing device
  * @param string password password for login
  * @return string sid
  */
function get_sid ($loginurl,$password) {

 // get challenge string
 $http_response = file_get_contents($loginurl);
 if(preg_match("/<Challenge>(\w+)<\/Challenge>/i",$http_response, $res)) {
   $challenge=$res[1];
 }
 //get SID
 if(preg_match("/<SID>([\da-f]+)<\/SID>/i",$http_response, $res)) {
   $sid=$res[1];
 }

 if ($sid && (preg_match("/^[0]+$/",$sid)) && $challenge) {
     //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
    if(preg_match("/<SID>([\da-f]+)<\/SID>/i",$http_response, $res)) {
         //got answer with sid
         $sid=$res[1];
         if (!preg_match("/^[0]+$/",$sid)) {
            //is not null, bingo!
            return $sid;
        }
    }

 }
 return null;
}//function

//-------------------------------------------------------------------------------
/**
 * retrieve actor AIN from smarthome overview page
 * @param string actorurl Smarthome overview page url
 * @param string sid SID to be used in query
 * @retun string AIN (or undef)
 */
function get_ain( $actorurl,$sid) {
	$ain=null;
	$actorhtml=file_get_contents($actorurl."?sid=".$sid);
	if (preg_match('/>(([a-fA-F0-9]{2}[:|\-]?){6})</',$actorhtml,$res)) {
		$ain=$res[1];
	}
	return $ain;
}
//-------------------------------------------------------------------------------
/**
* IPS Variablen handler
* creates variables as needed
* returns assoc. Array with IPS Variable ID and Value
* @param integer Sensor Address
* @param array Array with Variable Names, Types and Profiles
* @param string Sensor Group Master Categorie Name
* @param string Sensor default name, will be extended with $addr
*/
function get_ips_vars($addr,$vartypes,$cat,$sens) {

   $varids=null;
   $master=@IPS_GetObjectIDByName($cat,0);
   //no master cat, create new
   if (!$master) {
      $master=IPS_CreateCategory();
      IPS_SetName($master,$cat);
      IPS_SetParent($master,0);
      if ($master>0) {
         IPS_LogMessage('CUL', "Master category created, ID=$master
");
      }else{
         IPS_LogMessage('CUL', "Can't create Master Category
");
	return null;
      }
   }

  $id=0;
  if ($master>0) {
      //get chilren sensors
      $Sensors=IPS_GetChildrenIDs($master);
      foreach($Sensors as $sid) {
         $name=IPS_GetName($sid);
         $vars=IPS_GetChildrenIDs($sid);
         foreach($vars as $vid) {
            $obj=IPS_GetObject($vid);
            $vname=$obj['ObjectName'];
            $typ=$obj['ObjectType'];
            if ($typ==2) { //Variable
            //if ID, here is the address
               if ($vname="ID") {
                  $i=GetValue($vid);
                  //go out if matches, $id returns the sensor categorie id
                  if ($i===$addr) {
                     $id=$sid;
                     break;
                  }
               }
            }
         }
         if ($id>0) break;
      }
      if ($id==0) {
   	//Sensor with address $addr not found in IPS
         if ($GLOBALS['autocreate']==false) {
         //autocreate disable, ignore new device
            return null;
         }
         //create new sensor
         $id=ips_createCategory();
         ips_setName($id,$sens.' '.$addr);
         ips_setParent($id,$master);
         //creates all needed variables for the new sensor
         foreach (array_keys($vartypes) as $name) {
            $typ=$vartypes[$name]['type'];
            $profile=$vartypes[$name]['profile'];
            $vid=IPS_CreateVariable($typ);
            ips_setname($vid,$name);
            ips_setParent($vid,$id);
            IPS_SetVariableCustomProfile($vid,$profile);
            //preload variables
            SetValue($vid,0);
            $varids[$name]['id']=$vid;
            $varids[$name]['val']=0;
            //Store address in $ID for next time
            if ($name=='ID') {
               SetValue($vid,$addr);
               $varids[$name]['val']=$addr;
            }
        }
	}else{
         //found matching cat, collect ids and vals for this sensor
		$vars=IPS_GetChildrenIDs($id);
		foreach($vars as $vid) {
            $obj=IPS_GetObject($vid);
            $name=$obj['ObjectName'];
            $typ=$obj['ObjectType'];
            if ($typ==2) { //Variable
               $val=GetValue($vid);
               $varids[$name]['id']=$vid;
               $varids[$name]['val']=$val;
            }
		}
	}
    //returns IDs and Values of this Sensor, Name is Key
	return $varids;
   }
}
//-------------------------------------------------------------------------------
/**
* Get ID by name if exists, else create
* @Param String Name
* @param integer Parent-ID
* @return integer ID
*/
function getVid($name,$par) {
	$vid = @IPS_GetVariableIDByName($name, $par);
	if ($vid === false) {
		$vid=IPS_CreateVariable(3);
		ips_setname($vid,$name);
		ips_setParent($vid,$par);
		setValue($vid,'');
	}
	return $vid;
}
//-------------------------------------------------------------------------------
/**
* Check profile by name if exists, else create
* @Param String Name
* @param integer Variable Typ (0..3)
* @param String prefix befor value
* @param String suffix after value
* @param integer min value
* @param integer max value
* @param integer step value
* @param integer digits for formatting
* @param boolean drop existing profile first
*/

function check_profile($pname,$typ,$prefix,$suffix,$min,$max,$step,$digit=0,$drop=false) {
	if (IPS_VariableProfileExists($pname) && $drop) IPS_DeleteVariableProfile($pname);
	if (!IPS_VariableProfileExists($pname)) {
		if (IPS_CreateVariableProfile($pname,$typ)) {
		   	IPS_SetVariableProfileText($pname,$prefix,$suffix);
			if (isset($min) && isset($max) && isset($step)) {
		   		IPS_SetVariableProfileValues($pname,$min,$max,$step);
		   	}
	  		if (isset($digit)) {
		   		IPS_SetVariableProfileDigits($pname,$digit);
		   	}
 		}
	}
}
?>

Hm, merkwürdig.
Werf’ doch bitte mal die ganze Actor-Kategorie weg und lasse sie neu anlegen. Wenn das nicht hilft, bitte das Script temporär editieren und lass Dir damit den vom Aktor zurückgegeben Namen mal ausgeben

//retrieve actor name
$name = chop(file_get_contents($url."&switchcmd=getswitchname")); 
//test print
echo "Name: $name <br>
";

Mein Fritz 546 hat übrigens FritzOS 5.53

Tommi

Hallo Tommi,

das ist die Echo Ausgabe:
Name: FRITZ!Powerline 546E

Und hier meine OS Version:

version.jpg

Ist ja wirklich merkwürdig. Die Ausgabe des Standard-Namens passt überhaupt nicht zu den Screenshots. Somit ist verständlich, das in IPS nur dieser Name ankommt.

Kannst Du testweise bitte den Sensornamen am Anfang auf „“ setzen, einen einfachen kürzeren Namen ohne Leer- und Sonderzeichen dem Fritz546 über seine Weboberfläche vergeben, die Kategeorie in IPS wieder löschen und das Script noch einmal laufen lassen? Die Test-Ausgabe sollte identisch mit dem Value der ID-Variable sein und letztendlich auch den Namen von der Weboberfläche enthalten.

Tommi

Hallo Tommi,

ich habe den (meinen) Fehler gefunden.

Der Name wurde von mir unter dem Reiter -> Powerline -> Bezeichnung eingegeben.
Ich musste es aber unter dem Reiter -> Heimnetz -> Smarthome -> Konfiguration -> Name, machen.

Jetzt wird der Name auch übernommen.

Danke für Deine Hilfe.

Alles wird gut…:smiley:

Danke für die Rückmeldung

Hi,

ich habe auch versucht die Scripte ans laufen zu bekommen. Das auslesen funktioniert einwandfrei. Nur habe ich keine Möglichkeit die Aktoren zu schalten. Es wird im Webfront ein oder aus angezeigt nur keine Schaltfläche zum ändern von ein oder aus.

Getestet habe ich mit AVM 7490 OS 6.01 und AVM 546 OS 5.53
IPS 3.1

Hab ich was übersehn?

GELÖST
Ich habe den Fehler gefunden. Bei den Status Variablen muss man das „fritz_aha_actor.php“ Script als eigene Aktion hinzufügen.
Funktioniert bestens mit den oben genannten Firmware Ständen.

Gruß DerHüsi

Hallo Zusammen,

ich bin neu hier. Habe mittlerweile die IP-Symcon installiert. Das Fritzbox Skribt zum auslesen funktioniert, nur das chalten der Fritz 546 Steckdose bekomme ich nicht hin.

Es kommt der Fehler:

Warning: Variable #52745 existiert nicht in C:\IP-Symcon\scripts\47946.ips.php on line 28

Warning: Objekt #52745 existiert nicht in C:\IP-Symcon\scripts\47946.ips.php on line 35

Notice: Undefined index: VARIABLE in C:\IP-Symcon\scripts\47946.ips.php on line 37

Kann mir jemand helfen?

Vielen Dank

praktischerweise solltest Du die ID in Zeile 17 durch die ID Deiner eigenen Status-Variable austauschen. Weiterhin ist das Actor Script dazu gedacht, als Event bei Variablenänderung der vom Reader Script angelegten Status-Variable ausgeführt zu werden, dann wird auch $_IPS[‚Variable‘] gesetzt. Die Steckdose des Fritz546 wird also dann geschaltet, in dem man die Status-Variable z.B. im Webfrontend ändert.

Tommi

Hallo zusammen,

ich hab das Script heute auch installiert. Super danke.

Was sich mir im Moment nicht erschließt (vielleicht ist es auch schon zu spät):
Warum wird der Zustand(AN/AUS) des Schaltes nicht aktualisiert? (analog Switch)

Gruß Konny

Hi tommi,

ich habe das script gestern zum laufen bekommen. Daraufhin habe ich mir ganz vorfreudig einen zweiten Powerline 546e gekauft. Habe alle Skribte dopplet angelegt und nur die jeweilige IP des 546e angepasst.
Nun gibt es folgendes Problem: Beim auslesen der ersten IP wird in der Ausgabe die Daten von der 2. IP angegeben???
Es schein irgendwie Probleme beim Auslesen zu geben wenn mehrere 546e im Spiel sind?

Hast du da einen Idee?

Gruß

die freuschaltung für die Fritzkomponenten im Heimnetz mus deaktiviert werden, und ggf die anderen im lan aus der Liste entfernt werden

Hallo matterazi,

danke für die Info, nun geht es :wink:
Allerdings sehe ich nun aber keine Einträge mehr bei der myfritz weboberfläche?

Kann ich beides haben?

Gruß

die oberfläche nutze ich nicht, sorry da weiß ich nichts drüber :frowning:

Habe alle Skribte dopplet angelegt und nur die jeweilige IP des 546e angepasst.

Mehrere Geräte gehen natürlich genauso klaglos in einem Script. Sie legen für jedes Gerät entsprechend dem Namen eine eigene Kategorie mit eigenen Variablen an. Die Device-Namen (in der FB/546e) sollten deshalb unterschiedlich sein. Ich benutze zum Auslesen die Fritzbox. Dort habe ich alle Devices schön zusammen, auch die DECT-Steckdosen.
Wenn man nicht die Fritzbox nutzt muss man natürlich für jede 546e die richtigen Daten wie Host und Password hinterlegen. Dafür ist das Array am Anfang.

Das Abschalten der Smarthome-Integration ist genau der Weg, die für das Script und von der Fritzbox benötigte API sowohl auf dem 546e als auch auf der FB zu verbieten.

Tommi