Hallo Zusammen
Ich habe ein wenig mit den mystrom Button herumgespielt…
Ich möchte euch meine Lösung nicht vorenthalten. Gelöst habe ich es wie folgt:
Ich habe für den Button ein Serversocket mit dem Port 9998 angelegt, danach eine Registervariable mit dem Serversocket als übergeordnete Instanz, das Ziel ist mein SocketScript. Das Socketscript schreibt das auszuführende Script ein eine Variable welches dann durch das Steuerscript ausgeführt wird und die Variable wieder auf 0 setzt.
Das Socketscript sendet die Antwort an den Button welcher wieder schlafen geht.
Damit die Befehle auf den Button geschrieben werden können habe ich ein WriteConfig Script angelegt, wo die auszuführenden Scripts hinterlegt werden können.
Ihr benötigt somit:
-ServerSocket
-RegisterVariable
-SocketScript
-Steuerscript
-Variable
-WriteConfig Script
und natürlich die Scripts die Ihr ausführen wollt.
Hier die Scripts:
SocketScript
<?
if(!function_exists('Debug')){function Debug($data){if($_IPS['SENDER']=='Execute')echo $data.PHP_EOL;else IPS_LogMessage('ServerDataHandler:',$data);}}
if ($_IPS['SENDER'] == "RegisterVariable"){
$Handler=new IPSServerDataHandler( $_IPS['INSTANCE'], $_IPS['VALUE']);
$ok=$Handler->CheckData(function($event) {
$data='Alles wird GUT...';
switch($event['method']){
case 'GET': break;
case 'POST': break;
case 'NOTIFY': break;
case 'CALL' :
$FunctionName=$event['content']['name'];
if(!function_exists($FunctionName)){
$data.="oder auch nicht.
Unbekannte Funktion: $FunctionName
";
break;
}
$Arguments=&$event['content']['arguments'];
$result=null;
switch(count($Arguments)){
case 0: $result=$FunctionName(); break;
case 1: $result=$FunctionName($Arguments[0]);break;
case 2: $result=$FunctionName($Arguments[0]);SetValueInteger(29867 /*[Geräte\myStrom\Script]*/,$Arguments[1]); break;
//case 3: $result=$FunctionName($Arguments[0],$Arguments[1],$Arguments[2]); break;
//case 4: $result=$FunctionName($Arguments[0],$Arguments[1],$Arguments[2],$Arguments[3]); break;
case 5: $result=$FunctionName($Arguments[0],$Arguments[1],$Arguments[2],$Arguments[3],$Arguments[4]); break;
// .... usw.
}
$e=error_get_last();
if($result===false||$e)
$data.="oder auch nicht....
Fehler beim Aufruf von: $FunctionName {$e['message']}
";
else if(is_null($result)!==true)
$data=json_encode($result);
break;
}
return $data;
});
}
class IPSServerDataHandler {
private $INSTANCE_ID=0;
private $CALLBACKURL='';
private $LAST_EVENT=null;
function __construct($InstanceId, $value){
$this->INSTANCE_ID=$InstanceId;
$this->DATA = RegVar_GetBuffer($InstanceId).$value;
$this->DEBUG= $this->__read('DEBUG',0);
if($this->DEBUG)Debug('GET :'.$this->DATA);
}
function CheckData($CallBack=null){
$sendData=[];
while($ev=$this->parseHeader()){
$sendData=($CallBack)?$CallBack($ev):array('status'=>'200 OK','content'=>'');
$this->__SendHttpResponse($sendData);
$this->LAST_EVENT=$ev;
}
$this->__write('LAST_REQUEST',"{$this->LAST_EVENT['method']}: ".ArrayToStr($this->LAST_EVENT['content']));
$this->__write('LAST_RESPONSE',ArrayToStr($sendData,0,''));
RegVar_SetBuffer($this->INSTANCE_ID, $this->DATA);
return ($CallBack)?(bool)$this->LAST_EVENT:$this->LAST_EVENT;
}
public function LastEvent(){
return $this->LAST_EVENT;
}
private function parseHeader(){
@list($head, $body) = explode("
", $this->DATA, 2);
if(!$head)return false;
$hsize=strlen($head);
$head=explode("
",$head);
list($r['method'], $r['data'],$r['type']) = explode(' ', array_shift($head), 3);
if (($r['method']=='GET'||$r['method']=='POST'||$r['method']=='NOTIFY')===false)return false;
if($r['data'] && $r['data'][0]=='/')$r['data']=substr($r['data'],1);
$len=0;
foreach($head as $b){
list($k,$v) = explode(':',$b,2);
$k=strtoupper(trim($k));
if($k=='CONTENT-LENGTH')$len=(int)$v;
$r['head'][$k]=trim($v);
}
$r['compled']=($len)?(strlen($body)==$len):1;
if($r['compled']===false)return false;
$this->DATA=trim(substr($this->DATA,$hsize+$len));
if($r['method']=='NOTIFY')return $r;
if($r['data']&&($r['data'][0]=='?'||$r['data'][0]=='&'))
$pa=explode('&',substr($data,1));
elseif($r['method']=='POST')
$pa=explode('&',$r['body']);
elseif($r['method']=='GET'){
if(preg_match('/(.*)\((.*)\)/',$r['data'],$matches)){
array_shift($matches);
$r['method']='CALL';
$da['name']=array_shift($matches);
$aa=array_shift($matches);
if($aa!=''){
$tmp=explode(',',$aa);
for($j=0;$j<count($tmp);$j++){
$v=$tmp[$j];
if(is_bool($v)===true)
$v=(bool)$v;
else if(is_numeric($v)===true){
if(is_double($v)===true)$v=(double)$v;
else $v=(integer)$v;
}
$tmp[$j]=$v;
}
$da['arguments']=$tmp;
}else $da['arguments']=[];
$body=$da;
}
}
$r['content']=$body;
return $r;
}
private function __SendHttpResponse($Data=null){
$id=@IPS_GetInstance($this->INSTANCE_ID)['ConnectionID'];
if(!$id)return false;
if(!$Data)$Data=array('status'=>'200 OK');
if(!is_array($Data))$Data=array('content'=>$Data);
if(!isSet($Data['status']))$Data['status']='200 OK';
if(!isSet($Data['content']))$Data['content']='';
$res[]="HTTP/1.1 {$Data['status']}";
if($Data['content']){
if(!isSet($Data['size']))$Data['size']=strlen($Data['content']);
if(!isSet($Data['type']))$Data['type']='text/plain';
$res[]="CONTENT-TYPE: {$Data['type']}";
$res[]="CONTENT-LENGTH: {$Data['size']}";
$res[]="";
$res[]=$Data['content'];
}
$content=implode("
",$res).PHP_EOL;
$this->__write('LAST_STATE',$Data['status']);
if($this->DEBUG)Debug('SEND: '.$content);
return SSCK_SendText($id, $content);
}
private function __write($VarIdent, $VarData, $VarType=3){
$id=@IPS_GetObjectIdByIdent($VarIdent,$this->INSTANCE_ID);
if(!$id){$id=IPS_CreateVariable($VarType);IPS_SetParent($id,$this->INSTANCE_ID);IPS_SetIdent($id,$VarIdent);IPS_SetName($id,$VarIdent);}
SetValue($id,$VarData);
}
private function __read($VarIdent, $VarType=3){
$id=@IPS_GetObjectIdByIdent($VarIdent,$this->INSTANCE_ID);
if(!$id){$id=IPS_CreateVariable($VarType);IPS_SetParent($id,$this->INSTANCE_ID);IPS_SetIdent($id,$VarIdent);IPS_SetName($id,$VarIdent);}
return GetValue($id);
}
}
function ArrayToStr($a,$step=0, $cr="
"){
if(!$a)return 'null';else if(!is_array($a))return $a;
$r='';$sp=str_repeat(' ',$step);
foreach($a as $k=>$v)$r.="$sp'$k'=".(is_array($v)?"[$cr{$sp}".ArrayToStr($v,$step+2)."$sp$sp]":"$v")."$cr";
return $r;
}
?>
SetValueInteger in Zeile 26 müsst Ihr auf die Variable anpassen.
SteuerScript
<?
$script = GetValue(29867 /*[Geräte\myStrom\Script]*/);
IPS_RunScript($script);
SetValueInteger(29867 /*[Geräte\myStrom\Script]*/,0);
?>
Auch hier die GetValue und SetValueInteger auf die Variable anpassen.
WriteConfig
<?
$Single="single=get://10.0.0.151:9998/IPS_RunScript(27495,45000)&";
$Double="double=&";
$Long="long=get://10.0.0.151:9998/IPS_RunScript(27495,37697)&";
$ip_button = "10.0.0.155";
$mac_button = "5CCF7F0CBC9D";
$typ = "single"; // oder double, long, touch || oder kombiniert mit &double=http://......&long=http://...
//$mac_button = strtoupper(preg_replace('/[^A-Za-z0-9]/', '', $mac_button));
//echo $mac_button;
// Config senden
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "http://".$ip_button."/api/v1/device/".$mac_button);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS,$Single.$Double.$Long);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 2);
curl_setopt($ch, CURLOPT_TIMEOUT, 2);
$server_output=curl_exec($ch);
$error=curl_errno($ch);
curl_close($ch);
echo $server_output;
if($error ==28)
{
echo "Server Timeout";
}
else
{
echo $error;
}
?>
Hier die Befehle für single ,double und long anpassen. Dazu einfach die ID des Steuerscriptes als erstes und die ID des auszuführenden Scripts als zweites eintragen. IP und MAC Adresse des Button müssen ebenfalls angepasst werden.
Am besten den Button nicht voll geladen an den USB Port anschliessen kurz drücken und das Script ausführen.
Danach solltet ihr in der Ausgabe die Befehle für die einzelnen Aktionen sehen.
Ich hoffe es ist soweit klar, ansonsten einfach Fragen…
Durch diese Lösung ist es nicht notwendig den Button Befehl irgend über eine externe Seite auszuführen sondern es läuft alles ausschliesslich im eigenen Netzwerk.
Viel Spass und Grüsse aus der Schweiz
YB1898