Soderla,
meine Inputs sind drin.
Funktion ist so wie ichs zwei Posts weiter oben beschrieben habe.
Meine Teile hab ich zwischen //BB: Begin - //BB:End tags gesetzt.
Wichtig: der Script Timer sollte nicht um 00:00:00 sonderen ein paar Sekunden danach starten also zb: Begin 00:00:15 gesetzt haben.
Ich denke das ist notwendig um evtl. Abweichungen der Circle-Zeit von der IPS-Zeit aufzufangen. Keine Ahnung wie genau die Circle Uhr im Langzeitverhalten ist. evtl. sollte man die regelmäßig nachstellen.
Vorschlag für Recover wenn 1 Circle mal nicht erreichbar war ist auch drin, aber nicht getestet.
Da immer die Werte vom Circle genommen werden sollte es eigentlich sehr robust sein und immer mit den Daten von Sense übereinstimmen.
Ich hoffe mal es funktioniert so wie geplant, Langzeittest konnte ich aus verständlichen Gründen noch nicht machen.
Was bei einem komplett jungfäulichen Circle (also einer der noch keine History im Buffer hat, passiert weiß ich leider auch nicht. evtl. muß man den nach einer Stunde Laufzeit löschen und weider neu anlegen.
Wäre nett wenn du es mal ausprobieren könntest, aber wie gesagt VORSICHT ! Der Code wurde erst vor einer Stunde fertig. Nicht das du dir irgendwelchen wichtigen Daten zersägst…
gruß
bb
<?
/*
Plugwise Skript Version 0.5
Von: Axel Philippsn
Datum: 22.04.2012
Basiert auf der Vorarbeit von
1) Maarten Damen (http://www.maartendamen.com/wp-content/uploads/downloads/2010/08/Plugwise-unleashed-0.1.pdf) und
2) Jannis (http://www.ip-symcon.de/forum/f53/plugwise-ohne-server-direkt-auslesen-schalten-17348/)
3) Brownsons IPSInstaller (http://www.ip-symcon.de/forum/f74/ipsinstaller-einige-hilfreiche-scripts-autom-installation-13228/)
*/
/*
Noch zu lösende Probleme der Plugwise-Skripte:
- Befehl 0018 meldet mir immer nur genau 11 Circles - ich habe aber 18. In Zeile 104 habe ich die Abfrage auf 20 begrenzt, sollte 100 sein. Wie sieht das bei euch aus?
- Anlegen des Netzwerks immer noch mit der 'Source' (hab keine Zeit zum testen)
- Einbindung in IPSLibrary
*/
/* Some patches by BB to read energy consumption direct from Circle Buffer !!! Highly Experimental, use at your own risk !!!
*/
include("PW_Include.ips.php");
include("IPSInstaller.ips.php");
$idCatCircles = CreateCategory("Circles",IPS_GetParent($IPS_SELF),0);
Switch ($_IPS['SENDER'])
{
Default:
// PRINT "PW: ".$_IPS['SENDER'];
break;
Case "RunScript":
Case "Execute":
Case "TimerEvent":
// Alle Circles durchlaufen, Status und Verbrauch lesen
foreach(IPS_GetChildrenIDs($idCatCircles) as $item){ // alle Unterobjekte durchlaufen
$id_info = IPS_GetObject($item);
PW_SendCommand("0012".$id_info['ObjectIdent']);
PW_SendCommand("0023".$id_info['ObjectIdent']);
// BB: begin
// ask for Circle energy buffer only within first 3minutes to reduce trafic
if (date("i", time()) < 03) {
$logvar = GetValueString(IPS_GetVariableIDByName("LogAddress", $id_info['ObjectID']));
PW_SendCommand("0048".$id_info['ObjectIdent'].$logvar);
}
}
// BB: End
break;
Case "Variable":
// PRINT "PW Variable: ".$_IPS['VARIABLE'].", Value: ".$_IPS['VALUE'];
// break;
Case "WebFront": // Zum schalten im Webfront
// PRINT "PW Schalten: ".$_IPS['VARIABLE'].", Value: ".$_IPS['VALUE'];
$id = IPS_GetParent($_IPS['VARIABLE']);
$id_info = IPS_GetObject($id);
if ($_IPS['VALUE'] == 1) {$action = 1;} else {$action = 0;}
$cmd = "0017".$id_info['ObjectIdent']."0".$action;
PW_SendCommand($cmd);
// Sofort Feedback geben - aber besser auskommentieren und auf Rückmeldung des Circles warten
// SetValueBoolean($_IPS['VARIABLE'], $_IPS['VALUE']);
break;
Case "RegisterVariable": //
$buf = $IPS_VALUE;
switch ((substr($buf,0,4)))
{
case "0000": //Befehl vom Stick empfangen
switch ((substr($buf,8,4)))
{
case "00C1": //Schauen ob alles empfangen wurde
// print "Befehl von Stick empfangen";
break;
case "00D8": //eingeschaltet
// print "Eingeschaltet MAC".substr($buf,12,16);
$myCat = IPS_GetObjectIDByIdent(substr($buf,12,16), $idCatCircles);
SetValue(IPS_GetVariableIDByName ("State", $myCat),True);
// Sofort Verbrauch abfragen
// PW_SendCommand(substr($buf,12,16));
break;
case "00DE": //ausgeschaltet
// print "Ausgeschaltet MAC".substr($buf,12,16);
$myCat = IPS_GetObjectIDByIdent(substr($buf,12,16), $idCatCircles);
SetValue(IPS_GetVariableIDByName ("State", $myCat),False);
// Sofort Verbrauch abfragen
// PW_SendCommand(substr($buf,12,16));
break;
case "00E1":
print "Achtung: ein Circle ist nicht erreichbar: ".$buf;
break;
case "00D7": // Antwort auf 003E - Bestätigung für Uhrzeit stellen
$mac = substr($buf,12,16);
$myCat = IPS_GetObjectIDByIdent($mac, $idCatCircles);
// print "Uhrzeit gestellt auf ".substr($buf,12,16);
print "Uhrzeit gestellt auf ".IPS_GetName($myCat);
break;
case "00DD": // Antwort auf 0008 - Anfrage nach Circle+
$macplus = substr($buf,12,16);
// Dummy Instanz für Circle+ anlegen
$myCat = @IPS_GetObjectIDByIdent($macplus, $idCatCircles);
if ($myCat == false) createCircle($macplus, $idCatCircles);
PRINT "PW MC+:".$macplus.", Now searching for Circles...";
for ($i = 1; $i < 20; $i++) {
PW_SendCommand("0018".$macplus.str_pad($i, 2 ,'0', STR_PAD_LEFT));
}
break;
default:
print "Fehler von Stick: ".$buf; //bei allem anderen
break;
}
break;
case "0011": // Init
// print "Die Sequenznr: ".substr($buf,4,4)."
";
// print "MC Adresse: ".substr($buf,8,16);
// MC Adresse: 000D6F0000C3CA8E
// Stick: C3CE5C
// Kalibrierungsdaten aller Circles abrufen
foreach(IPS_GetChildrenIDs($idCatCircles) as $item){ // alle Unterobjekte
$id_info = IPS_GetObject($item);
PW_SendCommand("0026".$id_info['ObjectIdent']);
}
break;
case "0013": // Aktueller Verbrauch
$mcID = substr($buf,8,16);
$myCat = IPS_GetObjectIDByIdent($mcID, $idCatCircles);
// $pulse = substr($buf,28,4);
$pulse = substr($buf,28,4);
If ($pulse == "FFFF") {
// Circle ausgeschaltet, meldet FFFF
SetValue(CreateVariable("Watt", 2, $myCat, 0, "~Watt.3680", 0), 0);
} else {
// print IPS_GetName ($myCat)."
";
// 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)."
";
$gainA = GetValueFloat(IPS_GetVariableIDByName("gaina", $myCat));
$gainB = GetValueFloat(IPS_GetVariableIDByName("gainb", $myCat));
$offTotal = GetValueFloat(IPS_GetVariableIDByName("offTotal", $myCat));
$offNoise = GetValueFloat(IPS_GetVariableIDByName("offNoise", $myCat));
// Aktueller Verbrauch in Watt ermitteln
$value = hexdec($pulse)/8; ///8;
$out = (pow(($value+$offNoise),2)*$gainB)+(($value+$offNoise)*$gainA)+$offTotal;
$watt = (($out ) / 468.9385193)*1000;
$watt = round($watt,0);
SetValueFloat(CreateVariable("Watt", 2, $myCat, 0, "~Watt.3680", 0), $watt);
// BB: Total energy consumption kWh within actual hour
$Pulses = hexdec(substr($buf,32,8)); //Pulse in aktueller Stunde
$Pulses = $Pulses /3600;
$timestamp = time();
$sek_akthour = (60*(date("i", $timestamp))+date("s", $timestamp)); //Sekunden in aktueller Stunde
// $temp = 3600* (((pow($Pulses + $offNoise, 2.0) * $gainB) + (($Pulses + $offNoise) * $gainA)) + $offTotal);
// $result = ($temp / $sek_akthour) / 468.9385193;
// $result = (($result / 3600)* $sek_akthour);
$temp = ((pow($Pulses + $offNoise, 2.0) * $gainB) + (($Pulses + $offNoise) * $gainA)) + $offTotal;
$result = (($temp / $sek_akthour) / 468.9385193)*$sek_akthour;
SetValueFloat(CreateVariable("Summe_akt_Stunde", 2, $myCat, 0, "~Electricity", 0),$result );
// add to cumulated energy consumtion
$total_consumption = $result + GetValueFloat(IPS_GetVariableIDByName("Gesamtverbrauch_log", $myCat));
SetValueFloat(CreateVariable("Gesamtverbrauch",2,$myCat,0,""),$total_consumption);
//BB: End
/*
// Gesamtverbrauch in kWh
$oldPulses = GetValue(IPS_GetVariableIDByName("Pulses Stunde", $myCat));
$newPulses = hexdec(substr($buf,32,8));
// PRINT IPS_GetName($myCat)." - Pulses Neu: ".$newPulses.", Alt: ".$oldPulses."
";
if ($newPulses > $oldPulses)
$delta = $newPulses - $oldPulses;
else if ($newPulses == $oldPulses)
$delta = 0;
else if ($newPulses < $oldPulses)
$delta = $newPulses;
// $a = IPS_GetVariable(IPS_GetVariableIDByName("Pulses Stunde", $myCat));
// $seconds = time() - $a["VariableUpdated"];
$kWh = pulsesToKwh($delta, $offNoise, $offTotal, $gainA, $gainB);
// PRINT IPS_GetName($myCat)." - Pulses Neu: ".$newPulses.", Alt: ".$oldPulses.", Delta: ".$delta.", kWh: ".$kWh."
";
SetValueFloat(CreateVariable("Pulses Stunde", 2, $myCat, 0, "", 0), $newPulses);
$oldGesamtverbrauch = GetValue(IPS_GetVariableIDByName("Gesamtverbrauch", $myCat));
SetValueFloat(CreateVariable("Gesamtverbrauch", 2, $myCat, 0, "~Electricity", 0), $oldGesamtverbrauch + $kWh);
// PRINT IPS_GetName($myCat)." - Gesamtverbrauch Neu: ".$oldGesamtverbrauch + $delta.", Alt: ".$oldGesamtverbrauch.", Delta: ".$delta;
*/
}
break;
case "0019": //Adressen abfragen
// print "Die Sequenznr: ".substr($buf,4,4)."
";
// print "MC Circle+: ".substr($buf,8,16)."
";
$mac = substr($buf,24,16);
if (!($mac == "FFFFFFFFFFFFFFFF")) {
$myCat = @IPS_GetObjectIDByIdent($mac, $idCatCircles);
if ($myCat == false){
createCircle($mac, $idCatCircles);
} else {
// print "PW Node ".substr($buf,40,2).": ".IPS_GetName($myCat).", MAC:".$mac;
}
};
break;
case "0024": //Status
$mcID = substr($buf,8,16);
$myCat = IPS_GetObjectIDByIdent($mcID, $idCatCircles);
// echo IPS_GetName ($myCat).": ".substr($buf,41,1);
SetValue(CreateVariable("State", 0, $myCat, 0, "~Switch", $IPS_SELF), substr($buf,41,1));
// SetValueString(CreateVariable("LogAddress", 3, $myCat,0,""),intval((hexdec(substr($buf,32,8)) - 278528) / 32));
$logadr=(substr($buf,32,8)); //BB: keine Ahnung ob dies immer funktioniert. 0x20 = 32 = 8*4 = letzten 4 Stunden
$logadr = strtoupper(dechex((hexdec($logadr))-32)); //so gehts sicher, doppelte Conversion ist halt nicht schön
$logadr = str_pad($logadr,8,'0',STR_PAD_LEFT);
SetValueString(CreateVariable("LogAddress", 3, $myCat,0,""),$logadr);
// PRINT "LogAddress ".IPS_GetName($myCat).": ".intval((hexdec(substr($buf,32,8)) - 278528) / 32);
// PRINT "LogAddress ".IPS_GetName($myCat).": Hex ".substr($buf,32,8).", Dez ".((hexdec(substr($buf,32,8)) - 278528) / 32);
// 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)."
";
// PRINT "Zeit ".IPS_GetName($myCat).": ".date('c',pwtime2unixtime(substr($buf,24,8)));
// PRINT "Zeit ".IPS_GetName($myCat)." - Hex: ".substr($buf,24,8);
// print "log Adresse: ".substr($buf,32,8)."
";
// 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)."
";
break;
case "0027": //Kalibrierung
$myCat = IPS_GetObjectIDByIdent(substr($buf,8,16), $idCatCircles);
SetValueFloat(CreateVariable("gaina",2,$myCat,0,""),bintofloat(substr($buf,24,8)));
SetValueFloat(CreateVariable("gainb",2,$myCat,0,""),bintofloat(substr($buf,32,8)));
SetValueFloat(CreateVariable("offTotal",2,$myCat,0,""),bintofloat(substr($buf,40,8)));
if (substr($buf,48,8)=="00000000")
SetValueFloat(CreateVariable("offNoise",2,$myCat,0,""),0);
else
SetValueFloat(CreateVariable("offNoise",2,$myCat,0,""),bintofloat(substr($buf,48,8)));
break;
case "0049": // Antwort auf 0048 - historischen Verbrauch lesen (Buffer)
$mcID = substr($buf,8,16);
$myCat = IPS_GetObjectIDByIdent($mcID, $idCatCircles);
$gaina = GetValueFloat(IPS_GetVariableIDByName("gaina", $myCat));
$gainb = GetValueFloat(IPS_GetVariableIDByName("gainb", $myCat));
$offTotal = GetValueFloat(IPS_GetVariableIDByName("offTotal", $myCat));
$offNoise = GetValueFloat(IPS_GetVariableIDByName("offNoise", $myCat));
// PRINT "Buffer: ".$buf."
";
// print "Die Sequenznr: ".substr($buf,4,4)."
";
// print "MC Adresse: ".substr($buf,8,16)."
";
// PRINT IPS_GetName($myCat)."
";
/* print "Logdate 1: ".date("d.m.Y H:i", pwdatetodate(substr($buf,24,8))).": ";
print "Pulse 1: ".pulsesToKwh(hexdec(substr($buf,32,8)), $offNoise, $offTotal, $gaina, $gainb)."
";
// print "Pulse 1: ".substr($buf,24,8)."
";
print "Logdate 2: ".date("d.m.Y H:i", pwdatetodate(substr($buf,40,8))).": ";
print "Pulse 2: ".pulsesToKwh(hexdec(substr($buf,48,8)), $offNoise, $offTotal, $gaina, $gainb)."
";
//print "Pulse 2: ".substr($buf,40,8)."
";
print "Logdate 3: ".date("d.m.Y H:i", pwdatetodate(substr($buf,56,8))).": ";
print "Pulse 3: ".pulsesToKwh(hexdec(substr($buf,64,8)), $offNoise, $offTotal, $gaina, $gainb)."
";
// print "Pulse 3: ".substr($buf,56,8)."
";
print "Logdate 4: ".date("d.m.Y H:i", pwdatetodate(substr($buf,72,8))).": ";
print "Pulse 4: ".pulsesToKwh(hexdec(substr($buf,80,8)), $offNoise, $offTotal, $gaina, $gainb)."
";
*/ // print "Pulse 4: ".substr($buf,80,8)."
";
//BB: Begin
//Read last hour energy consumption from Circle Buffer, then add up to IPS Gesamtverbrauch
$var_id = IPS_GetVariable(IPS_GetVariableIDByName("Gesamtverbrauch_log", $myCat));
$time_diff = time() - $var_id['VariableChanged'];
if ($time_diff >= 3600) { // make shure only log once within each hour
$total_consumption = GetValueFloat(IPS_GetVariableIDByName("Gesamtverbrauch_log", $myCat));
$lasthour = pulsesToKwh(hexdec(substr($buf,80,8)), $offNoise, $offTotal, $gaina, $gainb);
$total_consumption = $total_consumption + $lasthour;
// log this value to Database
SetValueFloat(CreateVariable("Gesamtverbrauch_log",2,$myCat,0,""),$total_consumption);
}
/* --------------
To recover in case circle or IPS was offline during last request we can take care about last two hours
experimental, but I think it will work:
if ($time_diff > 3600 *2) { // make shure only log if last log was two ago
$total_consumption = GetValueFloat(IPS_GetVariableIDByName("Gesamtverbrauch_log", $myCat));
$lasthour = pulsesToKwh(hexdec(substr($buf,80,8)), $offNoise, $offTotal, $gaina, $gainb);
$2ndlasthour = pulsesToKwh(hexdec(substr($buf,64,8)), $offNoise, $offTotal, $gaina, $gainb);
$total_consumption = $total_consumption + $lasthour + $2ndlasthour;
// log this value to Database
SetValueFloat(CreateVariable("Gesamtverbrauch_log",2,$myCat,0,""),$total_consumption);
// add energy consumtion from actual hour to get correct value for Webfront
$total_consumption = $total_consumption + GetValueFloat(IPS_GetVariableIDByName("Summe_akt_Stunde", $myCat));
SetValueFloat(CreateVariable("Gesamtverbrauch",2,$myCat,0,""),$total_consumption);
}
.... to be continued for 3rdlasthour, ... 4thlasthour
----------------
*/
//BB: end
break;
case "003F": // Uhrzeit auslesen
$mcID = substr($buf,8,16);
$myCat = IPS_GetObjectIDByIdent($mcID, $idCatCircles);
date_default_timezone_set('UTC');
$myTime = mktime(hexdec(substr($buf,24,2)), hexdec(substr($buf,26,2)), hexdec(substr($buf,28,2)), 0,0,0);
date_default_timezone_set('Europe/Berlin');
// print "PW Uhrzeit: ".IPS_GetName($myCat).": "..":".).":".).", Tag der Woche: ".."
";
// print "PW Uhrzeit - ".IPS_GetName($myCat).": ".date("H:i:s", $myTime)."
";
// print $buf."
";
// print "Die Sequenznr: ".substr($buf,4,4)."
";
// print "MC Adresse: ".substr($buf,8,16)."
";
// print "Stunde : ".hexdec(substr($buf,24,2))."
";
// print "Min: ".hexdec(substr($buf,26,2))."
";
// print "Sek : ".hexdec(substr($buf,28,2))."
";
// print "Tag der Woche: ".substr($buf,30,2)."
";
// print "Rest : ".substr($buf,32,2)."
";
// print "Rest2: ".substr($buf,34,10)."
";
break;
}
break;
}
function createCircle($mac, $parentID){
// print "PW Create Circle: ".$mac;
$item = CreateInstance($mac, $parentID, "{485D0419-BE97-4548-AA9C-C083EB82E61E}", $Position=0);
$id_info = IPS_GetObject($item);
IPS_SetIdent ($item, $mac);
// CreateVariable ($Name, $Type, $Parent, $Position, $Profile, $Action=0, $ValueDefault='', $Icon="")
CreateVariable("State", 0, $item, 0, "~Switch", $IPS_SELF, false);
CreateVariable("Watt", 2, $item, 0, "~Watt.3680", 0, 0);
$myVar = CreateVariable("Gesamtverbrauch_log",2,$item,0,"",0);
IPS_SetHidden($myVar, True);
CreateVariable("Gesamtverbrauch", 2, $item, 0, "~Electricity", 0, 0); //~Electricity
$myVar = CreateVariable("Pulses Stunde", 2, $item, 0, "", 0);
IPS_SetHidden($myVar, True);
// $myVar = CreateVariable("LogAddress", 3, $item, 0, "", "");
// IPS_SetHidden($myVar, True);
$myVar = CreateVariable("gaina",2,$item,0,"",0);
IPS_SetHidden($myVar, True);
$myVar = CreateVariable("gainb",2,$item,0,"", 0);
IPS_SetHidden($myVar, True);
$myVar = CreateVariable("offTotal",2,$item,0,"",0);
IPS_SetHidden($myVar, True);
$myVar = CreateVariable("offNoise",2,$item,0,"",0);
IPS_SetHidden($myVar, True);
// Kalibrierungsdaten vom Circle abrufen
PW_SendCommand("0026".$mac);
// Zeit stellen
PW_SendCommand("0016".$mac.pwdatum());
PW_SendCommand("0012".$mac);
PW_SendCommand("0023".$mac);
}
?>