MyStrom

Hallo zusammen, ist es schwierig ein Modul zu programmieren? Die Funktion ist folgende:
Stromadapter von myStrom | myStrom zu steuern. ON und OFF sowie Watt auslesen. Wird direkt über IP angesprochen;-) ich finde den Adapter recht günstig und Preisleistung stimmt ist auch in der Schweiz entwickelt :wink:

Lg

Manuela

so wie es aussieht ist der aber nur für die „Schweizer“ Steckdosen.
Wenn du natürlich in der Schweiz wohnst, sollte das wohl kein Hindernis sein :slight_smile:

Hi

Das Ding hat ja eh eine simple REST API.

Wozu ein Modul ?
Paar Zeilen Code in einem Script tuns doch auch.

gruß
bb

Verstehe den Hype nicht. zzt. muß für alles und jedes ein Modul geschrieben werden.

Hallo zusammen,

hab die eben mal angeschrieben (21:07):
Frage: Könntet Ihr Euch dazu überreden lassen, das Teil auch für deutsche SchukoStecker zu bauen? …

Antwort (21:37):
Wir sind dran - wird komplett neu - neuer wifi chip, homekit, etc.

Hab dann noch für eine weiterhin offene API geworben.

Mal sehn was dabei raus kommt.

Antwort 21:49:
dauert aber noch bis q2/2017.

Hier der Link zur API:

myStrom API | myStrom

Habe es mal über einfaches HTTP Ansprechen gelöst. Die Watt auszulesen naja kein Plan…

Guten Abend,

Nun gibt es von MyStrom auch Wifi Buttons, auch diese verfügen über eine API. jedoch ist mir nicht klar wie ich den Button einbinden kann?!?

Muss ich dazu mit einem Intervall den Button Wert überprüfen? den die WLAN Verbindung wir ja erst bei Drücken aufgebaut…

Bin um jeden Hinweis dankbar!

Hier der Link zur API:
https://mystrom.ch/wp-content/uploads/REST_API_WBP.txt

Grüsse YB1898

Jetzt mal ins blaue geschossen, da ich das so nicht testen kann :smiley:
Aber vielleicht hilft es ja ein bisschen weiter.


	$ip = "1.1.1.1";

	// Schaltbefehle
	switch($_IPS['VALUE']){
		case 0:	$command = "relay?state=0"; break;
		case 1: $command = "relay?state=1"; break;
		case 2: $command = "relay?toggle"; break;
		default: return; break;
		} 

	$ch = curl_init();
		curl_setopt($ch, CURLOPT_URL, "http://".$ip."/".$command);
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
		curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 2);
		curl_setopt($ch, CURLOPT_TIMEOUT, 2);
 		curl_exec($ch);
 	curl_close($ch);


	// Status und Leistung auslesen
	$ch = curl_init();
		curl_setopt($ch, CURLOPT_URL, "http://".$ip."/report");
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
		curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 2);
		curl_setopt($ch, CURLOPT_TIMEOUT, 2);
 		$result = curl_exec($ch);
 	curl_close($ch);
	
	$data = json_decode($result, true);
	
	echo "Leistung: ".$data['power']." W";
	echo "Status: ".$data['relay']?"an":"aus";

Die beiden Befehle müsstest Du dann halt kombinieren.
Wenn ein Schaltbefehl gesendet wurde danach gleich den Status abfragen.
Und dann mit einem Timer schön poolen um den aktuellen Status aktuell zu halten :cool:

Auch wieder ein Schuss ins Blaue, ungetestet.
Wenn ich das so richtig verstanden habe, wie die das da schreiben.
Dann wird der Button programmiert, indem man dem den Befehlsaufruf für den Switch schickt.
Das wird dann einmalig gemacht und dann wird eben beim drücken (einmal, doppelt, lang oder touch) der Befehl ausgeführt.
Vom Button direkt an den Switch.


	$ip_button = "1.1.1.1";
	$mac_button = "mac-adresse";
	$ip_switch = "1.1.1.1";
	
	$typ = "single";	// oder double, long, touch || oder kombiniert mit &double=http://......&long=http://...
	
	$mac_button = strtoupper(preg_replace('/[^A-Za-z0-9]/', '', $mac_button));
	
	// Config senden
	$ch = curl_init();
		curl_setopt($ch, CURLOPT_URL, "http://".$ip_button."/api/v1/device/".$mac_button."?".$typ."=http://".$ip_switch."/toggle");
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
		curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 2);
		curl_setopt($ch, CURLOPT_TIMEOUT, 2);
 		curl_exec($ch);
 	curl_close($ch);

	// Button auslesen
	$ch = curl_init();
		curl_setopt($ch, CURLOPT_URL, "http://".$ip."/api/v1/device/".$mac_button);
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
		curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 2);
		curl_setopt($ch, CURLOPT_TIMEOUT, 2);
 		$result = curl_exec($ch);
 	curl_close($ch);
	
	$data = json_decode($result, true);	
	
	echo $data[$mac_button]['battery']."
";
	echo $data[$mac_button]['reachable']."
";
	echo $data[$mac_button]['voltage']."
";
	// and so on

Hallo Manfred

Danke für deine Antwort.

Ich möchte aber mit dem Button ein Script in IP Symcon auslösen.
Dazu muss ich den Aufruf im Button programmieren.
Aber dazu müsste ich a. ein Script direkt über http aufrufen können, oder b. per api eine variable veränder können und das per http befehl…

Leider habe ich keine Ahnung ob eines von beiden funktioniert.

Danke für euer Hilfe

Grüsse
YB1898

Das sollte auch gehen über einen Webhook zum Beispiel.

Gesendet von meinem D6633 mit Tapatalk

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

Hallo

Ich versuche per WWW-Reader und Textparser die Temperatur der Steckdose auszulesen.
Dazu trage ich im WWW-Reader die Url „http://192.168.8.119/temp“ ein. Bei dem Vorgang „Seite aktualisieren“ bekomme ich aber sofort einen
„Error 500, Error500 Internal Server Error“
Rufe ich die Seite im Browser auf bekomme ich den Inhalt in der folgenden Form angezeigt:


{
	"measured":	44.375000,
	"compensation":	21.000006,
	"compensated":	23.374994
}

Eine Authentifizierung ist nicht erforderlich, wie bekomme ich den Fehler weg?

Danke schön im Voraus für jeden Tip.
Gruss Schubi

Hast Du mal myStrom Modul ausprobiert?

Ja, aber da bekomme ich nur Power und Status.

Ok, die Temperatur gibt es nur bei der Steckdose, ja? Das kann ich noch im Modul ergänzen. Melde mich wenn es online ist.

ja, die Temperatur gibt es nur bei der Steckdose und nur bei der neuen Firmware, Die alte Hardwareversion mit der Firmware 2.60 hat dieses Feature noch nicht, jedenfalls ist es bei der CH-Version so.
Wäre wirklich super, wenn du das mit in dein Modul integrieren könntest,

Vielen Dank und frohe Pfingsten.
Schubi

Kannst mal ein Modul Update machen und dann Temperatur im Konfigurationsformular ankreuzen und Rückmeldung geben ob die Temperatur ausgelesen und abgespeichert wird.

Hallo Fonzo

Variable wird angelegt, Temperatur bleibt aber immer bei 0,0 C

Gruss Schubi

Liefert die Methode


MyStrom_GetTemperature($instanceid);

denn einen Wert zurück?

Da kommt der Fehler „Error404 Not Found“