FritzBox Aktor von KNX aus schalten: irgendwas fehlt noch...

Hallo zusammen,

wieder mal eine Anfänger-Frage, da ich jetzt an einem Punkt bin, wo ich nicht weiter komme…:confused:
Hintergrund: Ich habe eine KNX-Installation im Haus, die ich über IP Symcon visualisiere und auch gelegentlich schalte. Nun sollen an Stellen, wo kein KNX verfügbar ist, auch einige Sachen geschalten werden, z.B. ein weiter vom Haus entferntes Außenlicht. Das ganze will ich gern über eine Fritz!DECT 210 realisieren.

Was ich bereits gemacht habe - Teil 1:

  • Kategorie für meine DECT-Installation angelegt
  • Darunter Variablen definiert, u.a. für Definition der zu schaltenden AIN und für den Status der Steckdose (DECT_S01)
  • in der Variable verwende ich das Profil ~Switch und eine eigene Aktion „Schalten AIN“
  • diese ist als Skript definiert - (Danke an tdressler für das Fritz AHA-Beispiel !!!)
  • und das ganze habe ich auch so weit am laufen, dass ich über das WebFront die Steckdose tatsächlich schalten kann.

Teil 2

  • zu einer Instanz, die mir per KNX Licht schaltet
  • habe ich hierunter ein Ereignis definiert
  • welcher bei einer Änderung des Wertes zur obigen Instanz
  • ein kleines PHP-Skript ausführt
  • und dabei den Wert der Variable (DECT_S01) umsetzt.
  • das ganze wird durch Kontrollausgaben im MessageLog dokumentiert und ist demnach auch erfolgreich.

Jetzt hätte ich eigentlich gedacht, dass bei Änderung des Variablenwertes (zu DECT_S01) auch die Aktion „Schalten AIN“ ausgeführt wird - aber das ist leider nicht der Fall. Die Variablenänderung führe ich mit SetValue durch und frage die Änderung auch hinterher mit GetValue wieder ab - und da passt alles.

Und jetzt die Gretchenfrage: was fehlt noch - oder was mache ich falsch?

Noch eine weitere Frage:
Im Skript von tdressler gibt es folgenden Passus:

switch ($sender) {
case "WebFront":
  $me=$_IPS['VARIABLE'];
  $val=$_IPS['VALUE'];
  //IPS_LogMessage("FritzAHA Switch","FRONT: Switch ID ".$me." to ".($val?'ON':'OFF')."(->".$val.")");
  $result=SetValue($me, $val); //doing will be done by variable change ??
  IPS_LogMessage("FritzAHA Switch","FRONT: Switch ID ".$me." to ".($val?'ON':'OFF')."(->".$val."), Result:".$result);
//  return;  // <<=========XXXXXXXXXXXXX
  break; //not reached
case "Variable":
  $me=$_IPS['VARIABLE'];
  $val=$_IPS['VALUE'];
  IPS_LogMessage("FritzAHA Switch","VARIABLE: Switch ID ".$me." to ".($val?'ON':'OFF')."(->".$val.")");
  break;
case "Execute":
  $me=$id;
  $val=@GetValue($me);
  break;
default:
  IPS_LogMessage("FritzAHA Switch", "Error: unknown Sender '$sender'");
  return;
}

Ich gehe davon aus, dass beim Aufruf über das WebFront in der mit den vielen XXX gekennzeichenten Zeile eigentlich das Skript verlassen werden und erneut über die Änderung des Variablenwertes wieder aufgerufen werden sollte. Das tut aber nicht - daher habe ich den „return“ auskommentiert und alles läuft fein.
Und das gleiche Problem scheint es beim Aufruf der Variablenänderung zu geben, sonst sollte eigentlich alles laufen…

Schon mal vielen Dank vorab!

ps. hier das gesamte, leicht geänderte Skript von tdressler, mit welchem ich den Aktor bereits schalten kann - und dahinter das Skript zur Aktion…

<?php

//Start writing your code here
/*
switch a Fritz AHA Device (Fritz Powerline 546E, Fritz Dect200) from IPSymcon
http://www.tdressler.net/ipsymcon
V2.2 16.01.2016
see also
http://avm.de/fileadmin/user_upload/Global/Service/Schnittstellen/AVM_Technical_Note_-_Session_ID.pdf
http://avm.de/fileadmin/user_upload/Global/Service/Schnittstellen/AHA-HTTP-Interface.pdf
*/
if (!function_exists('mb_convert_encoding')) {
   IPS_LogMessage ("FritzAHA Switch","Error:Need mbstring_extension!
");
   return;
}
if (!function_exists('simplexml_load_string')) {
   IPS_LogMessage("FritzAHA Switch","Error:Need SimpleXML functions(simplexml_load_string)!
");
   return;
}

/* config section, pls adopt this for your device
credential array array('<1.host/ip>' =>array('user'=>'<login name1>','password'=>'<secret>')
                      ,'<2.host/ip>' =>array('user'=>'<login name2>','password'=>'<secret2>')
                      ,..
                     );
if no login name is needed/applicable, set the name to an empty string ('')!
*/
$logins=array('192.168.10.1'=>array('user'=>'dect','password'=>'passwort') //sample entry for fritzbox
/*           ,'192.168.170.211'=>array('user'=>'','password'=>'xyz123') //sample entry for another host,maybe fritz546 */
        );

$id=54004; /*[FRITZ Smarthome\Steckdose\Status]*/ //test variable for execute
/* end config section */

//check caller
$sender=$_IPS['SENDER'];
IPS_LogMessage("FritzAHA Switch", "================================");

switch ($sender) {
case "WebFront":
  $me=$_IPS['VARIABLE'];
  $val=$_IPS['VALUE'];
  //IPS_LogMessage("FritzAHA Switch","FRONT: Switch ID ".$me." to ".($val?'ON':'OFF')."(->".$val.")");
  $result=SetValue($me, $val); //doing will be done by variable change ??
  IPS_LogMessage("FritzAHA Switch","FRONT: Switch ID ".$me." to ".($val?'ON':'OFF')."(->".$val."), Result:".$result);
//  return;
  break; //not reached
case "Variable":
  $me=$_IPS['VARIABLE'];
  $val=$_IPS['VALUE'];
  IPS_LogMessage("FritzAHA Switch","VARIABLE: Switch ID ".$me." to ".($val?'ON':'OFF')."(->".$val.")");
  break;
case "Execute":
  $me=$id;
  $val=@GetValue($me);
  break;
default:
  IPS_LogMessage("FritzAHA Switch", "Error: unknown Sender '$sender'");
  return;
}

$state=$val;
IPS_LogMessage("FritzAHA Switch","Switch ID ".$me." to ".($state?'ON':'OFF')."(->".$state.")");

/*
//check varable is right
$name='fritz_aha_reader';
if ($name != "Switch Status") {
  IPS_LogMessage("FritzAHA Switch","Error: Action from wrong variable ".$_IPS['VARIABLE']);
  return;
}
*/
//get parameter from IPS
$parent  = IPS_GetParent($me);
$grandpa = IPS_GetParent($parent);
//$grandpa = '34243'; //FIX!

$host    = getVarValue('Host',$grandpa);
$log     = getVarValue('LogLevel',$grandpa);
$ain     = getVarValue('AIN',$parent);
if ($log > 1) {
    IPS_LogMessage("FritzAHA Switch", "Parent ID '$parent', GrandPa: '$grandpa'");
}

//checks
if (!$host || !$ain) {
  IPS_LogMessage("FritzAHA Switch","Error: Parameter host($host) or AIN($ain) missed");
  return;
}

//get password using ID host
$username=$logins[$host]['user'];
$password=$logins[$host]['password'];

if (!$password) {
  IPS_LogMessage("FritzAHA Switch","Error: password for '$host' not defined");
  return;
}

//build urls and login
$loginurl="http://".$host."/login_sid.lua";//login_sid.lua for fritzos 5.50+
$ahaurl="http://".$host."/webservices/homeautoswitch.lua";//api url
$sid=get_sid($loginurl,$username,$password);
if (!isset($sid)) {
  IPS_LogMessage("FritzAHA Switch", "Error: Login invalid or failed");
  return;
}

//query actual state
$url=$ahaurl.'?ain='.rawurlencode($ain).'&sid='.$sid.'&switchcmd=getswitchstate';
$answer=chop(@file_get_contents($url));
$response=$http_response_header[0];
if (!preg_match("/200\s+OK$/",$response)){
  IPS_LogMessage("FritzAHA Switch", "Error: Query ($url) failed, Response: $response ");
  return;
}
if ($log > 2) {
  IPS_LogMessage("FritzAHA Switch", "Actor $ain actual state:".($answer?"ON":"OFF").", Answer: ".$answer.",State: ".$state);
}

if ((($answer=="1")!=$state) || ($sender == "Execute")) {
//execute query
//$cmd=($state==true)?'setswitchon':'setswitchoff';
  $cmd=($answer)?'setswitchoff':'setswitchon';
  if ($log > 0) {
      IPS_LogMessage("FritzAHA Switch", "Actor $ain execute cmd:".$cmd);
  }
  $url=$ahaurl.'?ain='.rawurlencode($ain).'&sid='.$sid.'&switchcmd='.$cmd;
//$answer=@file_get_contents($url);
  $answer=chop(@file_get_contents($url));
  $response=$http_response_header[0];
  if (!preg_match("/200\s+OK$/",$response)) {
     IPS_LogMessage("FritzAHA Switch", "Error: Update Actor $ain failed, Response: $response");
     return;
  }
    if ($log > 1) {
        IPS_LogMessage("FritzAHA Switch", "New Status for Actor $ain:".($answer?"ON":"OFF"));
    }
}else{
   IPS_LogMessage("FritzAHA Switch", "No need to switch Actor $ain");
}

//-------------------------------------------------------------------------------
/**
  * login into fritz and get sid
  * @param string loginurl url for accessing device
  * @param string username Username to login, if needed or empty
  * @param string password password for login
  * @return string sid
  */
function get_sid ($loginurl,$username,$password) {

 if (is_null($username)) $username='';
 $sid='';
 // get challenge string
 $http_response = file_get_contents($loginurl);
 $response=$http_response_header[0];
 if (preg_match("/200\s+OK$/",$response)) {
  $xml = simplexml_load_string($http_response);
  $challenge=(string)$xml->Challenge;
  $sid=(string)$xml->SID;
 }else{
   IPS_LogMessage("FritzAHA Switch", "Error: GetSid with $loginurl failed, Response: $response");
 }
 if ((strlen($sid)>0) && (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."?username=".$username."&response=".$challenge_response;
   $http_response = file_get_contents($url);
   //check answer
   $xml = simplexml_load_string($http_response);
   $sid=(string)$xml->SID;
   if ((strlen($sid)>0) && !preg_match("/^[0]+$/",$sid)) {
            //is not null, bingo!
            return $sid;
   }

 }else {
  //use existing sid if $sid matches an hex string
  if ((strlen($sid)>0) && (preg_match("/^[0-9a-f]+$/",$sid))) return $sid;
 }
 return null;
}//function

//-------------------------------------------------------------------------------
/**
* get varable value by name referencing parent
* @param string $name Name of variable
* @param integer $par ID of parent (category)
* @return variant value of selected variable or null
*/
function getVarValue($name,$par) {
  $value=null;
  $vid = @IPS_GetVariableIDByName($name, $par);
  if ($vid)
    $value=GetValue($vid);
  return $value;
}
?>

…und hier noch das Aktonssklript aus dem Ereignis:


<?
  IPS_LogMessage("FritzAHA Switch", "===EREIGNIS===");
  $val=$_IPS['VALUE'];
  $id='59186'; // ID der Variable DECT_S01
  $result=SetValue($id, $val); //doing will be done by variable change
  IPS_LogMessage("FritzAHA Switch", "Variable '$id' ändern auf '$val', Result: '$result'");
  $result=GetValue($id);
  IPS_LogMessage("FritzAHA Switch", "Wert Variable: '$result'")
?>

SetValue setzt einfach nur die Variable, führt allerdings nicht die Aktion aus. Das beliebte Beispiel an dieser Stelle ist das Tacho des Autos. Verschiebst du den Pfeil, wird dein Auto noch lange nicht schneller. Das „Gaspedal“ ist an dieser Stelle die Funktion RequestAction. Diese führt die gleiche Aktion aus, wie ein Schalten im WebFront. Wenn du in deinem Skript also einfach nur SetValue durch RequestAction ersetzt, dann sollte das klappen.

Hallo Dr. Niels,
das wars… Vielen Dank für den Tipp!!
Dazu musste ich dann zwar das Skript von tdressler etwas anpassen, aber das war jetzt nur eine Kleinigkeit.
Gibt es eigentlich irgendwo so was wie eine FAQ „Wie mache ich…“?
Schöne Grüsse aus dem Vogtland…

Meinst du sowas? Wie kann ich…? — IP-Symcon :: Automatisierungssoftware

ja, so in der Art :slight_smile:
Da könnte man vielleicht noch ergänzen, wie man bei Änderung so eine „externes“ Objekt anspricht…