Morgen Alex und die anderen
Als erstes ein kurzer Bericht über 2 Wochen Plugwise nur mit Ip-symcon.
Zum Einrichten braucht man wohl auch in Zukunft noch die Orginalsoftware aber seitdem hab ich sie nicht mehr gestartet.
Den Verbrauch frage ich seit 2 Wochen alle 2 min ab und bis auf ein paar kleine Empfangsprobleme/Funkaussetzer und am Anfang Wattzahlen über 17000W obwohl der Circle ausgeschaltet war(ist jetzt aber behoben) sehe ich kein Problem mehr Plugwise direkt aus IP-Symcon abzufragen, bzw. zu schalten.
Das Schalten aus dem Webfront heraus und mit Rückmeldung ob der Circle wirklich an/aus ist klappt einwandfrei.
Die Rückmeldung vom Circle ob er sich ein/aus geschalten wird ausgewertet.
Was mir beim Schalten noch fehlt ist das Automatische nochmal senden wenn der Circle den Befehl nicht empfangen hat. Die Idee wie ich das mache ist schon da nur zur Umsetzung bin ich noch nicht gekommen.
Das ein Befehl nicht ankommt passiert bei mir nur noch sehr selten aber ich hab einen Circle im Obergeschoss da ist es kritisch ob der Befehl ankommt(ich denke einer von hundert befehlen kommt nicht an. Wird dann abervom Stick mitgeteilt das der Befehl nicht ankam bzw. die Rückmeldung ausgeblieben ist). Zum Vergleich ich frage ja alle 2 min 22 Circle ab, schalte noch ein paarmal und es kam in der letzten Stunde nur 2 mal die Meldung das ein Circle nichts zurückgemeldet hat.
Die Uhrzeit der Circle abfragen geht und auch das stellen funktioniert schon, muss aber noch ausreifen.
Die Circle selber speichern auch den Verbrauch von 4 Stunden und das der letzten 16 Stunden. Hier bin ich aber auch noch auf der Suche nach einem Muster das ich was gescheites rausbekomme.
So das war erstmal der überblick was zur Zeit geht.
Alex nimm statt der 6 stelligen ID lieber die gesamte Adresse, bei mir haben 6 Plugs eine 7stellige Nummer. Scheinen also schon jede Menge an Plugs verkauft zu haben wenn ihnen 6 Stellen nicht mehr ausreichen.
Zum Abfragen der Adressen muss man „nur“ 0018 +Adresse des Circle + Nummer des Node (Also von 00 bis FF je nachdem wieviele Plugs man hat) senden
Als Antwort 0019 bekommt man die Adresse des Circle+ und die Adresse des Circle zurück, bzw. FFFFFFFFFFFFFFFF falls da kein Circle dahinter steckt.
(siehe mein Empfangsscript weiter unten)
Wie schon geschrieben hatte ich ein Paar falsche Wattzahlen wenn der Circle ganz aus war bzw. wirklich nichts angeschlossen war.
Das erste Problem war, das wenn der Circle 0000 Pulse verbraucht hat hat die Funktion trotzdem etwas zurückgegeben, wegen der Kalibrierung. Also die Abfrage wenn 0000 dann kw = 0 eingebaut.
Aber immernoch bekam ich Watt jenseits von 17000W und hab dann rausbekommen das der Circle statt 0000 gerne mal FFFF schickt was aber nicht gerade warscheinlich ist(ausser ihr habt den Circle wirklich bis zum Maximum ausgereizt). Also auch diesen Fall ausgeklammert und seit ner Woche keine falschen Werte mehr gefunden.
Der Gesamtverbrauch ist „nur“ der Verbrauch seit Beginn der aktuellen Stunde, kann aber ansonsten wie die Pulse pro s bzw. 8 Sek ausgewertet werden.
Zum Anlegen der einzelnen Circle hab ich mir ein Script geschrieben das mir ne Kategorie anlegt, der Kategorie den Ident der Macadresse zuweist und darin verschiedene Variablen anlegt auch wieder mit den dazugehörigen Ident.
Das Script muss man halt für jeden Circle anpassen und einmal ausführen. Achtung hab noch keine Überprüfung eingebaut ob die Kategorie/Variablen/Ident schon da sind.
Den oberen Teil müsst ihr halt noch anpassen (soll eigentlich auch nur zeigen was mit Plugwise geht und euch auf die Sprünge helfen, bzw. ihr könnt mir tips geben was man einfacher, besser, anders machen kann).
<?
//kategorie anlegen
$cid="1A400C9";
$Katname = "Drucker ".$cid;
$Plugwiseid = 48691 /*[Test neu\Plugwise]*/;
$Archiveid = 33828 /*[Archive Handler]*/;
$schaltscript = 39141 /*[Test neu\Plugwise\Plugschalten Webfront]*/;
// ********************************************
$KatID = IPS_CreateCategory(); // Kategorie anlegen
IPS_SetName($KatID, $Katname); // Kategorie benennen
IPS_SetParent($KatID, $Plugwiseid); //Kategorie euerer Plugwise
$MAC="000D6F000".$cid;
IPS_SetIdent($KatID, $MAC);
//Gaina anlegen
$type = 2;
$name = "Gaina";
$VarID = IPS_CreateVariable($type);
IPS_SetName($VarID, $name);
IPS_SetIdent($VarID, $name); // Kategorie benennen
IPS_SetParent($VarID, $KatID); // Variable einordnen
//Gainb anlegen
$type = 2;
$name = "Gainb";
$VarID = IPS_CreateVariable($type);
IPS_SetName($VarID, $name);
IPS_SetIdent($VarID, $name); // Kategorie benennen
IPS_SetParent($VarID, $KatID); // Variable einordnen
//Offot anlegen
$type = 2;
$name = "Offot";
$VarID = IPS_CreateVariable($type);
IPS_SetName($VarID, $name);
IPS_SetIdent($VarID, $name); // Kategorie benennen
IPS_SetParent($VarID, $KatID); // Variable einordnen
//offruis anlegen
$type = 2;
$name = "Offruis";
$VarID = IPS_CreateVariable($type);
IPS_SetName($VarID, $name);
IPS_SetIdent($VarID, $name); // Kategorie benennen
IPS_SetParent($VarID, $KatID); // Variable einordnen
//Watt anlegen
$type = 2;
$name = "Watt";
$VarID = IPS_CreateVariable($type);
IPS_SetName($VarID, $name);
IPS_SetIdent($VarID, $name); // Kategorie benennen
IPS_SetParent($VarID, $KatID); // Variable einordnen
IPS_SetVariableCustomProfile($VarID, "~Watt.3680");
AC_SetLoggingStatus($Archiveid , $VarID, true);
IPS_ApplyChanges($Archiveid);
//Pulsegesamt anlegen
$type = 2;
$name = "Pulsegesamt";
$VarID = IPS_CreateVariable($type);
IPS_SetName($VarID, $name);
IPS_SetIdent($VarID, $name); // Kategorie benennen
IPS_SetParent($VarID, $KatID); // Variable einordnen
//Wh anlegen
$type = 2;
$name = "Wh";
$VarID = IPS_CreateVariable($type);
IPS_SetName($VarID, $name);
IPS_SetIdent($VarID, $name); // Kategorie benennen
IPS_SetParent($VarID, $KatID); // Variable einordnen
IPS_SetVariableCustomProfile($VarID, "~Watt.3680");
AC_SetLoggingStatus($Archiveid , $VarID, true);
IPS_ApplyChanges($Archiveid);
$type = 0;
$name = "Status";
$VarID = IPS_CreateVariable($type);
IPS_SetName($VarID, $name);
IPS_SetIdent($VarID, $name); // Kategorie benennen
IPS_SetParent($VarID, $KatID); // Variable einordnen
IPS_SetVariableCustomAction($VarID,schaltscript);
IPS_SetVariableCustomProfile($VarID,"~Switch");
$type = 0;
$name = "Schalten gesperrt";
$ident ="gesperrt";
$VarID = IPS_CreateVariable($type);
IPS_SetName($VarID, $name);
IPS_SetIdent($VarID, $ident); // Kategorie benennen
IPS_SetParent($VarID, $KatID); // Variable einordnen
?>
Mein Auslese Script ist dann das hier
<?
$Plugwisekat = 48691 /*[Test neu\Plugwise]*/;
function bintofloat($in)
{
$in=hexdec($in);
$binary = str_pad(decbin($in),32,"0", STR_PAD_LEFT);
$fb = $binary[0];
$exp = bindec(substr($binary, 1, 8));
$m = bindec(substr($binary, 9, 23));
return pow(-1,$fb) * (1+$m/(pow(2,23))) * pow(2,$exp-127);
}
function pulsetowatt($pu,$s,$ga,$gb,$offr,$offo) //Pulse,Sekunden,gaina,b,offruis,offtot
{
if (($pu>0))
{
$va = $pu/$s;
$out = (pow(($va+$offr),2)*$gb)+(($va+$offr)*$ga)+$offo;
$kw = (($out ) / 468.9385193)*1000;
}
else
$kw=0;
return $kw;
}
if ($IPS_SENDER == "RegisterVariable")
$buf = $IPS_VALUE;
switch ((substr($buf,0,4)))
{
case "0000": //Befehl vom Stick empfangen
switch ((substr($buf,8,4)))
{
case "00C1": //alles empfangen
print "Befehl von Stick empfangen";
break;
case "00D8": //eingeschaltet
print "Eingeschaltet MAC".substr($buf,12,16);
$KatID = IPS_GetObjectIDByIdent(substr($buf,12,16),$Plugwisekat);
setvalueboolean(IPS_GetObjectIDByIdent("Status",$KatID),true);
//IPS_RunScript(54091 /*[Test neu\Plugwise\Plug Strom auslesen lassen]*/);
break;
case "00DE": //ausgeschaltet
print "Ausgeschaltet MAC".substr($buf,12,16);
$KatID = IPS_GetObjectIDByIdent(substr($buf,12,16),$Plugwisekat);
setvalueboolean(IPS_GetObjectIDByIdent("Status",$KatID),false);
//IPS_RunScript(54091 /*[Test neu\Plugwise\Plug Strom auslesen lassen]*/);
break;
case "00E1": //Befehl nicht am Circle angekommen
print "Achtung Befehl nicht vom Circle bestätigt";
break;
default:
print "Fehler von Stick"; //bei allem anderen
}
break;
case "0011": // Init
print "Die Sequenznr: ".substr($buf,4,4)."
";
print "MC Adresse: ".substr($buf,8,16);
break;
case "0013": //Verbrauch
// print "Die Sequenznr: ".substr($buf,4,4)."
";
// print "MC Adresse: ".substr($buf,8,16)."
";
// print "Pulse/s : ".substr($buf,24,4)."
";
print "Pulse/8s: ".substr($buf,28,4)."
";
print "Pulse gesamt: ".substr($buf,32,8)."
";
$KatID = IPS_GetObjectIDByIdent(substr($buf,8,16),$Plugwisekat);
$gaina = getvaluefloat(IPS_GetObjectIDByIdent("Gaina",$KatID));
$gainb = getvaluefloat(IPS_GetObjectIDByIdent("Gainb",$KatID));
$offot= getvaluefloat(IPS_GetObjectIDByIdent("Offot",$KatID));
$offruis=getvaluefloat(IPS_GetObjectIDByIdent("Offruis",$KatID));
$pulse = hexdec(substr($buf,28,4));
if ($pulse==65535 /*[Objekt #65535 existiert nicht]*/)
$kw=0;
else
$kw= pulsetowatt($pulse,8,$gaina,$gainb,$offruis,$offot);
setvaluefloat(IPS_GetObjectIDByIdent("Watt",$KatID),$kw);
$pulsegesamt = hexdec(substr($buf,32,8));
setvaluefloat(IPS_GetObjectIDByIdent("Pulsegesamt",$KatID),$pulsegesamt);
$kwh= pulsetowatt($pulsegesamt,3600,$gaina,$gainb,$offruis,$offot);
setvaluefloat(IPS_GetObjectIDByIdent("Wh",$KatID),$kwh);
if ($kw>1000) //WEnn mehr als 1000W dann ins log schreiben
{
$zustand = date("d.m.y H:i ").$buf." Pulse/8s".substr($buf,28,4)." Watt ".$kw."
";
IPS_RunScriptEx(33144 /*[Diverse\Hilfsprogramme\Log schreiben]*/, Array("log" => "Plugwise.txt" , "daten" => $zustand ));
}
break;
case "0019": //Auslesen der MAC adressen
print "Die Sequenznr: ".substr($buf,4,4)."
";
print "MC Circle+: ".substr($buf,8,16)."
";
print "MAC Circle : ".substr($buf,24,16)."
";
print "Node ID: ".substr($buf,40,2)."
";
break;
case "0024": //Info
print "Die Sequenznr: ".substr($buf,4,4)."
";
print "MC Adresse: ".substr($buf,8,16)."
";
print "Jahr : ".substr($buf,24,2)."
";
print "Monat: ".substr($buf,26,2)."
";
print "Minuten : ".substr($buf,28,4)."
";
$logAddress = ((hexdec(substr($buf, 32, 8)) - 278528) / 32);
print "log Adresse: ".$logAddress."
";
print "An/aus: ".substr($buf,40,2)."
";
print "Herz (85=50H): ".substr($buf,42,2)."
";
print "Hardwareversion: ".substr($buf,44,12)."
";
print "Softwareversion: ".substr($buf,56,8)."
";
print "Stick 00,Cir+ 01 Cir 02: ".substr($buf,64,2)."
";
$KatID = IPS_GetObjectIDByIdent(substr($buf,8,16),$Plugwisekat);
if(substr($buf,40,2)=="01") //gerät an/aus
setvalueboolean(IPS_GetObjectIDByIdent("Status",$KatID),true);
else
setvalueboolean(IPS_GetObjectIDByIdent("Status",$KatID),false);
break;
case "0027": //Kalibrierung
print "Die Sequenznr: ".substr($buf,4,4)."
";
print "MC Adresse: ".substr($buf,8,16)."
";
print "gaina : ".substr($buf,24,8)."
";
print "gainb: ".substr($buf,32,8)."
";
print "offtot : ".substr($buf,40,8)."
";
print "offnoise: ".substr($buf,48,8)."
";
$KatID = IPS_GetObjectIDByIdent(substr($buf,8,16),$Plugwisekat);
setvaluefloat(IPS_GetObjectIDByIdent("Gaina",$KatID),bintofloat(substr($buf,24,8)));
setvaluefloat(IPS_GetObjectIDByIdent("Gainb",$KatID),bintofloat(substr($buf,32,8)));
setvaluefloat(IPS_GetObjectIDByIdent("Offot",$KatID),bintofloat(substr($buf,40,8)));
if (substr($buf,48,8)=="00000000")
setvaluefloat(IPS_GetObjectIDByIdent("Offruis",$KatID),0);
else
setvaluefloat(IPS_GetObjectIDByIdent("Offruis",$KatID),bintofloat(substr($buf,48,8)));
break;
case "0049": //Logauslesen
print "Die Sequenznr: ".substr($buf,4,4)."
";
print "MC Adresse: ".substr($buf,8,16)."
";
print "logdate1: ".substr($buf,24,8)."
";
print "logvalue1 : ".substr($buf,32,8)."
";
print "logdate2: ".substr($buf,40,8)."
";
print "logvalue2 : ".substr($buf,48,8)."
";
print "logdate3: ".substr($buf,56,8)."
";
print "logvalue3 : ".substr($buf,64,8)."
";
print "logdate4: ".substr($buf,72,8)."
";
print "logvalue4 : ".substr($buf,80,8)."
";
print "Logadresse: ".substr($buf,88,8)."
";
break;
case "003F": //Uhrzeit auslesen
print $buf."
";
print "Die Sequenznr: ".substr($buf,4,4)."
";
print "MC Adresse: ".substr($buf,8,16)."
";
print "Stunde : ".substr($buf,24,2)."
";
print "Min: ".substr($buf,26,2)."
";
print "Sek : ".substr($buf,28,2)."
";
print "Tag der Woche: ".substr($buf,30,2)."
";
print "Rest : ".substr($buf,32,2)."
";
print "Rest2: ".substr($buf,34,4)."
";
break;
}
?>
Zum schalten der Circle hab ich mir noch ne Variable angelegt mit der ich den Circle sperren kann, ansonsten könnte ausversehen der Kühlschrank oder ein auch ein gesamter Raum ausgeschaltet werden.
Fürs schalten aus dem Webfront heraus hab ich das Script hier, wurde beim anlegen der Circle als $schaltscript hinterlegt.
<?
if ($IPS_SENDER=="WebFront")
{
$array = (IPS_GetObject($IPS_VARIABLE));
$idgesperrt=IPS_GetObjectIDByIdent("gesperrt",$array['ParentID']);
if (!getvalue($idgesperrt))
{
IPS_RunScriptEx(20458 /*[Test neu\Plugwise\Plugwise schalten]*/, Array("id" => $IPS_VARIABLE , "an" => $IPS_VALUE ));
//setvalue($IPS_VARIABLE,$IPS_VALUE);
//$mac=IPS_GetObject("
}
else
echo "Gesperrt";
}
?>
Das schaltscript ist dann das hier
<?
// this function is used to calculate the (common) crc16c for an entire buffer
function calculate_common_crc16c($buffer)
{
$crc16c = 0x0000; // the crc initial value laut www.maartendamen.com
$buffer_length = strlen($buffer);
for ($i = 0; $i < $buffer_length; $i++)
{
$ch = ord($buffer[$i]);
$crc16c = update_common_crc16c($ch, $crc16c);
}
return $crc16c;
}
// this function is used to calculate the (common) crc16c byte by byte
// $ch is the next byte and $crc16c is the result from the last call, or 0xffff initially
function makeCrcCheckSum($string)
{
$crc = 0x0000;
for ($i = 0, $j = strlen($string); $i < $j; $i++) {
$x = (($crc >> 8) ^ ord($string[$i])) & 0xFF;
$x ^= $x >> 4;
$crc = (($crc << 8) ^ ($x << 12) ^ ($x << 5) ^ $x) & 0xFFFF;
}
//$ausgabe = str_pad($ausgabe, 4 ,'0', STR_PAD_LEFT); //Mit Nullen auffüllen
return str_pad(strtoupper(dechex($crc)), 4 ,'0', STR_PAD_LEFT);
}
$array = (IPS_GetObject($id));
($macarray=IPS_GetObject($array['ParentID']));
$mac=$macarray['ObjectIdent'];
$befehl = "0017";
if ($an)
$mac.="01";
else
$mac.="00";
$text=$befehl.$mac;
$ausgabe=makeCrcCheckSum($text);
$text.= $ausgabe;
RegVar_SendText(56849 /*[Test neu\Plugwise\Register Variable Cutter Plug]*/,"\x05\x05\x03\x03".$text."\x0D\x0A");
?>
aufruf mit
IPS_RunScriptEx(20458 /*[Test neu\Plugwise\Plugwise schalten]*/, Array("id" => $IPS_VARIABLE , "an" => $IPS_VALUE ));
Und hier mein Script zum anfragen des Verbrauches
<?
// this function is used to calculate the (common) crc16c for an entire buffer
function calculate_common_crc16c($buffer)
{
$crc16c = 0x0000; // the crc initial value laut www.maartendamen.com
$buffer_length = strlen($buffer);
for ($i = 0; $i < $buffer_length; $i++)
{
$ch = ord($buffer[$i]);
$crc16c = update_common_crc16c($ch, $crc16c);
}
return $crc16c;
}
// this function is used to calculate the (common) crc16c byte by byte
// $ch is the next byte and $crc16c is the result from the last call, or 0xffff initially
function makeCrcCheckSum($string)
{
$crc = 0x0000;
for ($i = 0, $j = strlen($string); $i < $j; $i++) {
$x = (($crc >> 8) ^ ord($string[$i])) & 0xFF;
$x ^= $x >> 4;
$crc = (($crc << 8) ^ ($x << 12) ^ ($x << 5) ^ $x) & 0xFFFF;
}
//$ausgabe = str_pad($ausgabe, 4 ,'0', STR_PAD_LEFT); //Mit Nullen auffüllen
return str_pad(strtoupper(dechex($crc)), 4 ,'0', STR_PAD_LEFT);
}
// init
//$befehl="000A";
//$mac="";
$anfang="000D6F000";
$id_array=array( "0B1D99F",
"0Dxxx5",
"0Dxxxx8",
"0DxxxxC",
"0DxxxxB",
"0Dxxxx6",
"0DxxxxB",
"0Dxxxx0",
"0Dxxxx5",
"0Dxxxx7",
"1Axxxx6",
"1Axxxx8",
//"0DxxxxA",
"1Axxxx6",
//"1Axxxx4",
"1AxxxxA",
"0Dxxxx6",
//"1Axxxx8",
"1Axxxx9",
//"0DxxxxE",
"0BxxxxA");
$anzahl = count($id_array);
for ($i=0;$i<$anzahl;$i++)
{
$mac=$anfang.$id_array[$i];
$befehl = "0012";//Verbrauch auslesen
//$befehl = "0026"; //Kalibrierung auslesen
//$befehl="0023";//Infos auslesen
$text=$befehl.$mac;
$ausgabe=makeCrcCheckSum($text);
$text.= $ausgabe;
IPS_sleep(300);
RegVar_SendText(56849 /*[Test neu\Plugwise\Register Variable Cutter Plug]*/,"\x05\x05\x03\x03".$text."\x0D\x0A");
}
?>
Die Adressen der einzlnen Circle könnte man natürlich auch jedesmal aus den Ident der Kategorien auslesen lassen aber ich denke hier schreibt man lieber einmal alle Adressen rein und gut ist.
Jetzt habt Ihr was zum ausprobieren.
Und Alex, ich bin gespannt auf dein Script also immer her damit.
Gruß Jannis