Plugwise-Integration in IP-Symcon

Hallo liebe IPS’ler,

heute möchte ich auch mal was zur Community beitragen und mein Plugwise-IPS-Integrations-Script veröffentlichen :-). Aber erst mal kurz die Grundlagen: was ist Plugwise überhaupt?

Plugwise ist eine Firma, die nette kleine Zwischenstecker herstellt die

  • geschaltet werden können
  • und nebenbei noch den Stromverbrauch messen.

Diese Zwischenstecker kommunizieren untereinander über ein Zigbee-Netz, mit den gleichen Vor- und Nachteilen. Ein wesentlicher Nachteil ist sicherlich die geringe maximale Reichweite die zwischen den einzelnen Circles möglich ist. Einzelheiten findet ihr aber zu genüge auf der Plugwise-Homepage (z.B. hier: Wie funktioniert das Plugwise System? | Plugwise), da muss ich sicherlich nicht weiter drauf eingehen.

Plugwise selber benötigt einen USB-Stick (Bestandteil des Home-Start-Sets), dieser sowie eine Client-Software stellen das Interface für IP-Symcon zur Verfügung. Folge: Stick muss immer verbunden sein, die Software (es gibt auch einen Server-Part) muss laufen.

Idee / Motivation der Scripte:
Weder Plugwise noch IP-Symcon bieten eine echte Integration, neue Circles müssen von Hand in IP-Symcon eingebunden werden, die Variablen angelegt werden, Schaltscripte angelegt & ggf. Links für’s Webfront erzeugt werden. Mit meinem Plugwise-Script habe ich alle anfallenden Aufgaben automatisiert, jetzt müssen nur noch die Circles in der Plugwise-Software (Plugwise Source) angelegt werden, diese werden dann beim nächsten Script-Lauf automatisch in IP-Symcon übernommen & die nötigen Variablen / Scripte / Links automatisch angelegt.

Doku des Scripts / der Funktionen
Die öfters geforderte Doku des Scripts bzw. der Funktionen ist in Arbeit, ich ergänze diese in absehbarer Zeit.
Bis dahin bleibt euch wohl nur übrig, einen Blick in die Scripte zu werfen - ich denke sie sind einigermaßen klar geschrieben & sollten ohne weiteres verständlich sein :wink:

IP-Symcon Hilfsfunktionen
In meinen Scripten / Funktionen verwende ich immer mal wieder Hilfsfunktionen aus meiner persönlichen Funktionsbibliothek. Diese kleinen Helferlein machen mir das Scripten etwas leichter & nehmen nervige, wiederkehrende Aufgaben ab.
Hier eine hoffentlich vollständige Übersicht der Hilfsfunktionen die in meinen Plugwise-Scripten verwendet werden: http://www.ip-symcon.de/forum/f53/plugwise-integration-ip-symcon-17330/#post152234


Nach der Installation aktiviert man den Webserver in der Software und legt folgende Scripte im Webserver-Pfad von Plugwise an:

ipsymcon.xml

<items type="array"> 
<% foreach Plugwise.Rooms %>    
   <%$room = .Name %> 
   <% foreach .Appliances %>    
      <% 
        if (.Module == null) 
          continue; 
      /if 
        if (.Room == null) 
          echo "No Room"; 
      /if 
      $state=.StatusImageName.Replace("_locked",""); 
         $state=$state.SubString($state.LastIndexOf("_")+1); 
      %> 
   <appliance> 
      <id><%=.Id%></id> 
      <device><%=.Name%></device> 
      <devicetype><%=.TypeText%></devicetype> 
      <locked><%=.DoNotSwitchOff%></locked> 
      <realstate><%=$state%></realstate> 
      <powerstate><%=.PowerState%></powerstate> 
      <powerusage><%=.PowerUsage%></powerusage> 
      <totalusage><%=.TotalUsage%></totalusage> 
      <moduleid><%=.Module.Id%></moduleid> 
      <moduleid_bc><%=.module%></moduleid_bc> 
      <macaddr><%=.Module.MacAddress%></macaddr> 
      <moduletype><%=.Module.TypeText%></moduletype> 
      <room><%=$room%></room> 
      <totalusagetoday><%=.TotalUsageToday%></totalusagetoday> 
      <isonline><%=.IsOnline%></isonline>          
      <lastseendate><%=.LastSeenDate%></lastseendate> 
      <lastseenseconds><%=.LastSeenSeconds%></lastseenseconds>    
      <firstseendate><%=.FirstSeenDate%></firstseendate>    
   </appliance> 
   <% /foreach %> 
<% /foreach %> 
</items>  

cc.html

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> 
<? header("HTTP/1.0 204 No Content"); ?> 
<html> 
  <head> 
  <title>Bwired Plugwise example</title> 
  </head> 
  <body> 
    <% 
    //Response.Status = "204 no content" 
    $cmd=Request.get.containsKey("cmd")?Request.get["cmd"]:"" 
    $applid=Request.get.containsKey("applid")?Request.get["applid"]:0 
    $modid=Request.get.containsKey("modid")?Request.get["modid"]:0 
    
    if ($applid>0) 
      With Appliance($applid) 
        //echo "<br>",.Name,": " 
        if $cmd=="on" 
          .SwitchOn() 
          //echo " ingeschakeld" 
        elseif $cmd=="off" 
          .SwitchOff() 
          //echo " uitgeschakeld"  
        /if 
      /With 
    /if 
    if ($modid>0) 
      With Module($modid) 
        //echo "<br>",.Name,": " 
        if $cmd=="on" 
          .CloseRelay() 
          //echo " ingeschakeld" 
        elseif $cmd=="off" 
          .OpenRelay() 
          //echo " uitgeschakeld"  
        /if 
      /With 
    /if 

    echo "<hr>" 
    foreach Plugwise.Appliances 
      //echo '<br>',.Name,': <a href="?applid=',.Id,'&cmd=on">Aan</a> <a href="?applid=',.Id,'&cmd=off">Uit</a>'  
    /foreach 
        //echo "<hr>" 
    foreach Plugwise.Modules 
          //echo '<br>',.Name,': <a href="?modid=',.Id,'&cmd=on">Aan</a> <a href="?modid=',.Id,'&cmd=off">Uit</a>'  
    /foreach 
    %> 
  </body> 
</html>

So, nun aber zum eigentlichen interessanten Teil: die Integration in IP-Symcon. Der Plugwise-Webserver stellt uns nun zwei Interfaces zur Verfügung: eins zum Auslesen der Verbrauchswerte, und eins zum Schalten der Stecker. Um jetzt eine möglichst gute Integration in IP-Symcon hin zu bekommen, hab ich mir (als Quick-and-Dirty-Lösung) folgendes Script zusammen gebastelt:

create_update_circles

<?php
/**
  create_update_circles
  Ersteller: Markus Kromberg
  Version 1.0.2

  Aufgabe:
     Dieses Script
	  - registriert automatisch neue Plugwise-Circles im IP-Symcon
	  - legt nötige Variablen, Scripte und Events an
	  - aktualisiert die Messwerte

  Trigger:
     Dieses Script sollte autmatisch per Timer-Event alle 5 Minuten getriggert werden.
	 Bei jedem Lauf werden dann die Circle-Stati sowie die Verbrauchswerte ausgelesen und in IP-Symcon übernommen.
	 Öfters Triggern (also unter 1 Minute) macht meistens keinen Sinn, da sich die Circles im Schnitt alle 60 Sekunden beim Circle+ / Source melden.
	 Nachteil: Sollten auch Schaltsysteme von Plugwise zum Einsatz kommen, wird ein manuelles Schalten erst nach 5 Minuten erkannt.

  Updates:
  15.02.2012: Config-Block um einige Parameter erweitert
  14.02.2012: Zeichensatz-Konvertierung der Device- und Raumnamen
  02.05.2011: initiale Erstellung des Scriptes
**/


/*********************** Config-START ***********************/
$Steckdosen_OnOff_Link_ID = 37370;			// Eltern-Element, unter dem der Link angelegt wird
$Power_State_Link_ID = 42209;					// Eltern-Element, unter dem der Link angelegt wird
$IPS_SCRIPT_ID = 24267;		    				// IP-Symcon ID dieses Scripts

$pw_ip = "127.0.0.1";							// IP-Adresse zum Plugwise-Server
$pw_port = "8080";	    						// Webserver-Port des Plugwise-Servers
$pw_username = GetValueString(23880);		// Username, falls das Plugwise-Webfront geschützt ist
$pw_password = GetValueString(30828);		// Passwort, falls das Plugwise-Webfront geschützt ist

$pw_room_root = 45206; 							// Hier werden von Plugwise die Raum-Kategorien automatisch angelegt
$pw_health = 27555;								// Boolean-Variable, enthält eine Vermutung ob das Plugwise-System läuft (Werte vom Plugwise Webfront)

$pw_akt_verbrauch = 28707;               	// Float-Variable, enthält den aktuellen Verbrauch aller Circles
$pw_ges_verbrauch = 39620;						// Float-Variable, enthält den Tages-Verbrauch aller Circles

$pw_wft_detail_script = 30269; 				// Script-ID welches aus dem Webfront aufgerufen kann & zur Detail-Seite verlinkt. Der Script-Namen wird immer in den aktuellen Verbrauch umbenannt
/*********************** Config-ENDE ***********************/


if ($pw_username <> "") $var_loginstr = $pw_username.":".$pw_password."@";
$xml_source = file_get_contents('http://'.$var_loginstr.$pw_ip.':'.$pw_port.'/ipsymcon.xml');
$xml = simplexml_load_string($xml_source);

$c = 0;
$akt_gesamtverbrauch = 0;
$insg_gesamtverbrauch = 0;

$check_socket = 0;

while(isset($xml->appliance[$c]))
{
  /* Variablen auslesen / erzeugen */
	$devid = intval($xml->appliance[$c]->id);
	$modid = strval($xml->appliance[$c]->moduleid_bc);
	$device = strval($xml->appliance[$c]->device);
	$device = iconv('UTF-8', 'ISO-8859-1', $device);
	$lastseendate  = strval($xml->appliance[$c]->lastseendate);
	$lastseenseconds = intval($xml->appliance[$c]->lastseenseconds);
	$powerstate = $xml->appliance[$c]->powerstate;
    if ($powerstate == "on")  $powerstate_bool = TRUE;
    if ($powerstate == "off") $powerstate_bool = FALSE;
    if ($powerstate == "unknown") $powerstate_bool = FALSE;
    if ($powerstate_bool == TRUE) $check_socket = 1;
	$devlocked = $xml->appliance[$c]->locked;
    if ($devlocked == "True")  $devlocked_bool = TRUE;
    if ($devlocked == "False") $devlocked_bool = FALSE;
	$powerusage = floatval($xml->appliance[$c]->powerusage);
	$totalusagetoday = floatval($xml->appliance[$c]->totalusagetoday);
	$room = strval($xml->appliance[$c]->room);
	$room = iconv('UTF-8', 'ISO-8859-1', $room);
	$isonline = $xml->appliance[$c]->isonline;
    if ($isonline == "True")  $isonline_bool = TRUE;
    if ($isonline == "False") $isonline_bool = FALSE;
  // Plugwise Modul-ID auslesen
  $modid = substr($modid, -8, 6);

  // Gesamtverbrauch berechnen
  $akt_gesamtverbrauch  = $akt_gesamtverbrauch + $powerusage;
  $insg_gesamtverbrauch = $insg_gesamtverbrauch + $totalusagetoday;

  // Verbrauch des Raumes berechnen
  if (isset($arr_verbrauch["$room"]))
  {
  	$arr_verbrauch["$room"]["akt_gesamtverbrauch"]  = floatval($arr_verbrauch["$room"]["akt_gesamtverbrauch"])+$powerusage;
   $arr_verbrauch["$room"]["insg_gesamtverbrauch"] = floatval($arr_verbrauch["$room"]["insg_gesamtverbrauch"])+$totalusagetoday;
  }
  else
  {
  	$arr_verbrauch["$room"]["akt_gesamtverbrauch"]  = $powerusage;
   $arr_verbrauch["$room"]["insg_gesamtverbrauch"] = $totalusagetoday;
  }

  // Anlegen einer neuen Kategorie mit dem Raum-Namen für die Devices
  $RoomID  = create_plugwise_category($room, $pw_room_root);

  // Anlegen einer neuen Kategorie mit dem Plugwise-Namen
  $CatID   = create_plugwise_category($device, $RoomID);

  // Variablen zurücksetzen
  $pss_id     = 0;
  $psl_id     = 0;
  $pslsync_id = 0;

  // Anlegen der Variablen
  /* ID                  */ $pid_id = create_plugwise_device($CatID,                 "ID",      1, $devid,           "",        "", 1, $devlocked_bool);
  /* module ID           */ $mod_id = create_plugwise_device($CatID, "moduleid",        3, $modid,           "",        "", "", $devlocked_bool);
  /* lastseendate        */ $lsd_id = create_plugwise_device($CatID, "lastseendate",    3, $lastseendate,    "",        "",  1, $devlocked_bool);
  /* lastseenseconds     */ $lss_id = create_plugwise_device($CatID, "lastseenseconds", 1, $lastseenseconds, "Seconds", "",  1, $devlocked_bool);
  /* locked              */ $lck_id = create_plugwise_device($CatID, "locked",          0, $devlocked_bool,  "",        "",  1, $devlocked_bool);
  /* powerstate          */ $pst_id = create_plugwise_device($CatID, "powerstate",      0, $powerstate_bool, "~Switch", $devid, 1, $devlocked_bool);
  /* powerstate_set      */ $pss_id = create_plugwise_device($CatID,           "powerstate_set", 0, $powerstate_bool, "~Switch", $modid, 0, $devlocked_bool);
  /* powerstate_set_lnk  */ $psl_id = create_link($pss_id, $room.": ".$device, 0, $Steckdosen_OnOff_Link_ID);
  /* powerstate_set_sync */ if ($devlocked_bool == FALSE) $pslsync_id = sync_plugwise_powerstate($pst_id, $pss_id);
  /* powerusage          */ $pus_id =      create_plugwise_device($CatID,  "powerusage", 2, $powerusage, "~Watt.3680", "", 1, $devlocked_bool);
  /* powerusage_room     */ $pus_room_id = create_plugwise_device($RoomID, "powerusage", 2, $powerusage, "~Watt.3680", "", 0,  $devlocked_bool);
  /* powerusage_lnk      */ $pul_id =      create_link($pus_id, $room.": ".$device, 0, $Power_State_Link_ID);
  /* totalusagetoday     */ $tut_id =      create_plugwise_device($CatID, "totalusagetoday", 2, $totalusagetoday, "~Electricity", "", 1, $devlocked_bool);
  /* totalusagetoday_room*/ $tut_room_id = create_plugwise_device($RoomID, "totalusagetoday", 2, $totalusagetoday, "~Electricity", "", 0, $devlocked_bool);
  /* $threshold          */ $tsh_id =      create_plugwise_device($CatID, "threshold", 1, 0, "", "", 0, $devlocked_bool);
  /* room                */ $rom_id =      create_plugwise_device($CatID, "room", 3, $room, "", "", 1, $devlocked_bool);
  /* isonline            */ $onl_id =      create_plugwise_device($CatID, "isonline", 0, $isonline_bool, "HM_online_offline", "", 1, $devlocked_bool);
  /* akm_anw             */ $akmanw_id =   create_plugwise_device($CatID, "akm_anw", 1, TRUE, "AKM", $modid, 0, $devlocked_bool);
  /* akm_abw             */ $akmabw_id =   create_plugwise_device($CatID, "akm_abw", 1, TRUE, "AKM", $modid, 0, $devlocked_bool);

  //Stromverbrauch-Links ausgeschalteter Geräte ausblenden
  if ($powerstate == "off") { IPS_SetHidden($pul_id, true); }
  if ($powerstate == "on")  { IPS_SetHidden($pul_id, false); }

  // Statusvariablen gelockter Geräte ausblenden
  if ($devlocked == "True")  { IPS_SetHidden($psl_id, true); }
  if ($devlocked == "False") { IPS_SetHidden($psl_id, false); }

  //Stromverbrauch-Links & Statusvariablen nicht erreichbarer Geräte ausblenden
  if ($isonline == "False") { IPS_SetHidden($pul_id, true); }
  if ($isonline == "False") { IPS_SetHidden($psl_id, true); }

  //Datenbank-Logging einschalten
  ipssql_logging($pus_id       /* powerusage          */, TRUE, 0);
  ipssql_logging($pus_room_id  /* powerusage_room     */, TRUE, 0);
  ipssql_logging($tut_id       /* totalusagetoday     */, TRUE, 1);
  ipssql_logging($tut_room_id  /* totalusagetoday_room*/, TRUE, 1);
  ipssql_logging($onl_id       /* isonline            */, TRUE, 0);
  $c++;
}

// Socket-Status speichern
if ($check_socket == 0) SetValueBoolean($pw_health, FALSE);
if ($check_socket == 1) SetValueBoolean($pw_health, TRUE);

// Gesamtverbrauch speichern
SetValueFloat($pw_akt_verbrauch,$akt_gesamtverbrauch);
$var_filename = "akt. Stromverbr.:  ".$akt_gesamtverbrauch."W";
IPS_SetName ($pw_wft_detail_script, $var_filename);
SetValueFloat($pw_ges_verbrauch,$insg_gesamtverbrauch);

// Gesamtverbrauch der Räume speichern
$plugwiseraeume = IPS_GetChildrenIDs($pw_room_root);
$anzahl_raeume = count($plugwiseraeume);
for ($ir = 0; $ir < $anzahl_raeume; $ir++) {
	$VarID = @IPS_GetVariableIDByName("powerusage", $plugwiseraeume[$ir]);
   if ($VarID === false)
   {}
   else
	{
	  $var_room = IPS_GetName($plugwiseraeume[$ir]);
	  SetValueFloat($VarID,floatval($arr_verbrauch["$var_room"]["akt_gesamtverbrauch"]));
	}
}
for ($ir = 0; $ir < $anzahl_raeume; $ir++) {
	$VarID = @IPS_GetVariableIDByName("totalusagetoday", $plugwiseraeume[$ir]);
   if ($VarID === false)
   {}
   else
	{
	  $var_room = IPS_GetName($plugwiseraeume[$ir]);
	  SetValueFloat($VarID,floatval($arr_verbrauch["$var_room"]["insg_gesamtverbrauch"]));
	}
}
?>

Zusätzlich werden noch einige Funktionen benötigt, die ich bei mir in eine eigene Funktions-Bibliothek ausgelagert habe:

create_plugwise_category

<?
/**
  create_plugwise_category
  Ersteller: Markus Kromberg
  Version 1.0.1

  Aufgabe:
     Diese Funktion erstellt Kategorien für das Plugwise-System, allerdings nur
	 wenn diese Kategorie noch nicht existiert.
	 
  Trigger:
    Diese Funktion wird getriggert, sobald neue Kategorien (beim Hinzufügen von neuen Circles)
	angelegt werden sollen.
  
  Parameter:
	$name:		Name der Kategorie
    $Master_ID:	"Mutter"-Kategorie, unter der die neue Kategorie angelegt werden soll

  Historie:
    15.02.2012: Kommentar-Block
    02.05.2011: initiale Erstellung der Funktion	
**/

if (!function_exists('create_plugwise_category'))
{
function create_plugwise_category($name, $Master_ID)
{
	/* prüfen ob Kategorie existiert */
	$does_exist   = "FALSE";
	$ips_children = IPS_GetChildrenIDs($Master_ID);
	for($i=0; $i < count($ips_children); $i++)
  {
  	$var_name = IPS_GetName($ips_children[$i]);
  	if ($var_name == $name)
  	{
  		$does_exist = "TRUE";
  		$CatID = intval($ips_children[$i]);
  	}
  }

  /* ggf. Kategorie anlegen */
  if ($does_exist == "FALSE")
  {
	  /* Kategorie anlegen */
    $CatID = IPS_CreateCategory();    	  // Kategorie anlegen
    IPS_SetName($CatID, $name);  		  // Kategorie benennen
    IPS_SetParent($CatID, $Master_ID);	  // Kategorie einordnen
  }
  return $CatID;
}
}
?>

create_plugwise_device

<?
/**
  create_plugwise_device
  Ersteller: Markus Kromberg
  Version 1.0.1

  Aufgabe:
     Diese Funktion 
	   - registriert neue Plugwise-Geräte in IP-Symcon & erzeugt die nötigen Variablen
	   - Prüft die dem Gerät zugehörigen Variablen auf Vollständigkeit, und legt ggf. fehlende Variablen an
	   - übernimmt die neuen Werte von Plugwise Source in die IPS-Variablen
	 
  Trigger:
    Diese Funktion sollte auf Grund der großen Anzahl an Parametern nur vom Hauptscript aus getriggert werden
  
  Parameter:
    $category_id:	Kategorie-ID
	$name:			Name der Variable
	$typ=0:			Variablen-Typ: Boolean
	$typ=1:			Variablen-Typ: Integer
	$typ=2:			Variablen-Typ: Float
	$typ=3:			Variablen-Typ: String
	$value:			Wert
	$profilename:	Profil, welches auf die Variable angewendet werden soll
	$pwid:			Plugwise-ID
	$doupdate:		Soll der Wert gleich von Plugwise-Source übernommen werden?
    $devlocked_bool: Ist das Gerät gesperrt?

  Historie:
    15.02.2012: Kommentar-Block
    02.05.2011: initiale Erstellung der Funktion	
**/

if (!function_exists('create_plugwise_device'))
{
function create_plugwise_device($category_id, $name, $type, $value, $profilename, $pwid, $doupdate = 1, $devlocked_bool = FALSE)
{
  // Pre-Checks
  if ($name == "moduleid")
  {
  	$name = "PWID".$value;
  	$value = $value;
  }

	/* prüfen ob Variable existiert */
	$does_exist   = "FALSE";
	$ips_children = IPS_GetChildrenIDs($category_id);
	for($i=0; $i < count($ips_children); $i++)
  {
  	$var_name = IPS_GetName($ips_children[$i]);
  	if ($var_name == $name)
  	{
  		$does_exist = "TRUE";
  		$VarID_ID = intval($ips_children[$i]);
  	}
  }

  /* ggf. Variable anlegen */
  if ($does_exist == "FALSE")
  {
	  /* Variable anlegen */
	 $VarID_ID = IPS_CreateVariable($type);
    IPS_SetName($VarID_ID, $name); 							// Kategorie benennen
    IPS_SetParent($VarID_ID, $category_id);			// Variable einordnen
    if ($profilename <> "") IPS_SetVariableCustomProfile($VarID_ID, $profilename);

    /* ggf. Trigger-Script anlegen */
    if ($name == "powerstate_set")
    {
    	global $IPS_SCRIPT_ID;
    	/* Switch-Script */
    	$ScriptTEXT =  '<?php switch_plugwise_device(4, "PWID'.$pwid.'"); ?>';
    	$on_script = CreateScriptByName("switch_device", $VarID_ID, $ScriptTEXT);
    	$eid = IPS_CreateEvent(0);        				//Ausgelöstes Ereignis
      IPS_SetEventTrigger($eid, 0, $VarID_ID); 	//Bei Änderung von Variable mit ID 15754
      IPS_SetParent($eid, $on_script); 					//Ereignis zuordnen
      IPS_SetEventActive($eid, true);    				//Ereignis aktivieren
    	$ScriptTEXT =  '<?php switch_plugwise_device(3, "PWID'.$pwid.'"); ?>';
    	$toggle_script = CreateScriptByName("toggle_device", $VarID_ID, $ScriptTEXT);
      IPS_SetVariableCustomAction($VarID_ID, $toggle_script);
      $ScriptTEXT_on =  '<?php switch_plugwise_device(1, "PWID'.$pwid.'"); ?>';
    	$script_on = CreateScriptByName("switch_on", $VarID_ID, $ScriptTEXT_on);
    	$ScriptTEXT_off =  '<?php switch_plugwise_device(2, "PWID'.$pwid.'"); ?>';
    	$script_off = CreateScriptByName("switch_off", $VarID_ID, $ScriptTEXT_off);
    }
  }

  /* Wert übernehmen */
  if ($doupdate != 0)
  {
    if ($type == 0 AND is_bool($value) == true) 	SetValueBoolean($VarID_ID, $value);     // Wert übernehmen
    if ($type == 1) 											SetValueInteger($VarID_ID, $value);     // Wert übernehmen
    if ($type == 2) 											SetValueFloat($VarID_ID, $value);       // Wert übernehmen
    if ($type == 3) 											SetValueString($VarID_ID, $value);      // Wert übernehmen
  }
  return $VarID_ID;
}
}
?>

get_plugwise_variable

<?
/**
  get_plugwise_variable
  Ersteller: Markus Kromberg
  Version 1.0.1

  Aufgabe:
     Diese Funktion liefert den Wert einer Plugwise-Variable, ohne das man die genaue IPS-ID kennen muss
  
  Parameter:
	$variablename:	Name der Variable
	$pwid:			Plugwise-ID

  Historie:
    15.02.2012: Kommentar-Block
    02.05.2011: initiale Erstellung der Funktion	
**/

if (!function_exists('get_plugwise_variable'))
{
function get_plugwise_variable($variablename, $pwid)
{
  /*********************** Config-START ***********************/
  $pw_room_root = 45206; 		// Hier werden von Plugwise die Raum-Kategorien automatisch angelegt
  /*********************** Config-ENDE ***********************/
  
  // Räume finden
  $plugwiseraeume = IPS_GetChildrenIDs($pw_room_root);
  $anzahl_raeume = count($plugwiseraeume);
  for ($ir = 0; $ir < $anzahl_raeume; $ir++) {
  	// Devices finden
    $plugwisedevices = IPS_GetChildrenIDs($plugwiseraeume[$ir]);
    $anzahl_devices = count($plugwisedevices);
    for ($iv = 0; $iv < $anzahl_devices; $iv++) {
    	// Variablen finden
    	$plugwisevariables = IPS_GetChildrenIDs($plugwisedevices[$iv]);
    	$anzahl_variables = count($plugwisevariables);
      $VarID = @IPS_GetVariableIDByName($pwid, $plugwisedevices[$iv]);
      if ($VarID === false)
        $nf = 0;
      else
	    {
	      $VarID2 = @IPS_GetVariableIDByName($variablename, $plugwisedevices[$iv]);
	      if ($VarID2 === false)
	      $nf = 0;
	      else
	      {
	    	  return GetValue($VarID2);
	      }
	    }
	  }
  }
}
}
?>

get_plugwise_variable_id

<?
/**
  get_plugwise_variable_id
  Ersteller: Markus Kromberg
  Version 1.0.1

  Aufgabe:
     Diese Funktion liefert die IPS-ID einer Plugwise-Variable, ohne das man die genaue IPS-ID kennen muss
  
  Parameter:
	$variablename:	Name der Variable
	$pwid:			Plugwise-ID

  Historie:
    15.02.2012: Kommentar-Block
    02.05.2011: initiale Erstellung der Funktion	
**/

if (!function_exists('get_plugwise_variable_id'))
{
function get_plugwise_variable_id($variablename, $pwid)
{
  /*********************** Config-START ***********************/
  $pw_room_root = 45206; 		// Hier werden von Plugwise die Raum-Kategorien automatisch angelegt
  /*********************** Config-ENDE ***********************/
	// Räume finden
  $plugwiseraeume = IPS_GetChildrenIDs($pw_room_root);
  $anzahl_raeume = count($plugwiseraeume);
  for ($ir = 0; $ir < $anzahl_raeume; $ir++) {
  	// Devices finden
    $plugwisedevices = IPS_GetChildrenIDs($plugwiseraeume[$ir]);
    $anzahl_devices = count($plugwisedevices);
    for ($iv = 0; $iv < $anzahl_devices; $iv++) {
    	// Variablen finden
    	$plugwisevariables = IPS_GetChildrenIDs($plugwisedevices[$iv]);
    	$anzahl_variables = count($plugwisevariables);
      $VarID = @IPS_GetVariableIDByName($pwid, $plugwisedevices[$iv]);
      if ($VarID === false)
        $nf = 0;
      else
	    {
	      $VarID2 = @IPS_GetVariableIDByName($variablename, $plugwisedevices[$iv]);
	      if ($VarID2 === false)
	      $nf = 0;
	      else
	      {
	    	  return $VarID2;
	      }
	    }
	  }
  }
}
}
?>

switch_plugwise_device

<?
/**
  switch_plugwise_device
  Ersteller: Markus Kromberg
  Version 1.0.1

  Aufgabe:
     Diese Funktion schaltet Plugwise-Circles.
	 Über Parameter kann man dabei mehrere Schalt-Arten auswählen, diese sind im Kommentarblock "Parameter" näher aufgeführt.
	 
  ToDo:
     Auswerten, ob der Schaltvorgang erfolgreich durchgeführt wurde. Der Plugwise Webserver quittiert soweit ich weiß
     den Schaltvorgang mit OK oder mit Fehler, dieser könnte noch ausgewertet werden.	 
	 
  Trigger:
    Diese Funktion wird über die Aktions-Scripte der "powerstate_set"-Variablen aufgerufen
  
  Parameter:
    $pwid:		Plugwise-ID
	$state = 1:	ON
	$state = 2:	OFF
	$state = 3:	TOGGLE
	$state = 4:	gemäß "powerstate_set"

  Historie:
    15.02.2012: Kommentar-Block
    02.05.2011: initiale Erstellung der Funktion	
**/

if (!function_exists('switch_plugwise_device'))
{
function switch_plugwise_device($state, $pwid)
{
	/*********************** Config-START ***********************/
	$IPS_SCRIPT_ID = 24267;		    			// IP-Symcon ID des Haupt-Scripts "create_update_circles"
	$pw_ip = "127.0.0.1";						// IP-Adresse zum Plugwise-Server
	$pw_port = "8080";	    					// Webserver-Port des Plugwise-Servers
	$pw_username = GetValueString(23880);		// Username, falls das Plugwise-Webfront geschützt ist
	$pw_password = GetValueString(30828);		// Passwort, falls das Plugwise-Webfront geschützt ist
	/*********************** Config-ENDE ***********************/

	if ($state == "") $state = 3;
	$switchdev = TRUE;
	$current_state  = get_plugwise_variable("powerstate", $pwid);
	$powerstate_set = get_plugwise_variable("powerstate_set", $pwid);
	$current_power = get_plugwise_variable("powerusage", $pwid);
	$threshold = get_plugwise_variable("threshold", $pwid);
	$locked = get_plugwise_variable("locked", $pwid);
	$deviceid = get_plugwise_variable("ID", $pwid);
	if ($state == 1) $state_bool = TRUE;
	if ($state == 2) $state_bool = FALSE;
	if ($state == 3 AND $current_state == FALSE) $state_bool = TRUE;
	if ($state == 3 AND $current_state == TRUE)  $state_bool = FALSE;
	if ($state == 4) $state_bool = $powerstate_set;

  if ($deviceid <> "" AND $current_state != $state_bool)
  {
	  if ($threshold == 0) $threshold = 1000;
	  if ($threshold < $current_power) $switchdev = FALSE;
	  if ($locked == TRUE)             $switchdev = FALSE;

	  if ($switchdev == TRUE)
	  {
		  if ($state == 1) $setstate = "on";
		  if ($state == 2) $setstate = "off";
		  if ($state == 3 AND $current_state  == TRUE)  $setstate = "off";
		  if ($state == 3 AND $current_state  == FALSE) $setstate = "on";
		  if ($state == 4 AND $powerstate_set == TRUE)  $setstate = "on";
		  if ($state == 4 AND $powerstate_set == FALSE) $setstate = "off";

		  if ($setstate == "off") $setstate_bool = false;
		  if ($setstate == "on" ) $setstate_bool = true;

        $powerstate_setvar = get_plugwise_variable_id("powerstate_set", $pwid);
		if ($pw_username <> "") $var_loginstr = $pw_username.":".$pw_password."@";
		if (GetValueBoolean($powerstate_setvar) <> $setstate_bool) SetValueBoolean($powerstate_setvar,$setstate_bool);
		file_get_contents('http://'.$var_loginstr.$pw_ip.':'.$pw_port.'/cc.html?applid='.$deviceid.'&cmd='.$setstate);
	    sleep(1); // Sicherheitshalber den Schaltbefehlt nochmal schicken, wird aber normalerweise nicht benötigt
	    file_get_contents('http://'.$var_loginstr.$pw_ip.':'.$pw_port.'/cc.html?applid='.$deviceid.'&cmd='.$setstate);

	    IPS_RunScript($IPS_SCRIPT_ID); // "create_update_circles" starten, um die geänderten Werte wieder zu bekommen
	    SetScriptRun($IPS_SCRIPT_ID, time() + 30); // Nach 30 Sekunden erneut starten, um den neuen Stromverbrauch zu bekommen
	  }
  }
}
}
?>

sync_plugwise_powerstate

<?
/**
  sync_plugwise_powerstate
  Ersteller: Markus Kromberg
  Version 1.0.1

  Aufgabe:
     Diese Funktion synchronisiert den Schaltzustand der Plugwise-Circles.
	 Im Objektbaum befindet sich unter dem jeweiligen Device eine "Powerstate" und eine "Powerstate_Set" Variable.
	 Powerstate_Set enthält den Zustand (TRUE / FALSE) wie ihn die IPS-Scripte vorgeben. Wird allerdings auf Grund eines
	 Stromausfalls oder "ausstecken & einstecken" der Zustand ausserhalb von IP-Symcon verändert, weicht der Inhalt
	 der beiden Variablen ab. Durch einen Aufruf dieser Funktion wird der Zustand synchronisiert & den Inhalt von Powerstate_Set
	 übernommen.

  Trigger:
    Diese Funktion kann manuell aufgerufen werden, ist aber fester Bestandteil des Hauptscripts "create_update_circles".
	Ein zusätzlicher, manueller Aufruf sollte normalerweise nicht nötig sein.
  
  Parameter:
    $powerstate_id: IPS-ID der Variable "powerstate"
	$powerset_id:   IPS-ID der Variable "powerstate_set"

  Historie:
    15.02.2012: Kommentar-Block
    02.05.2011: initiale Erstellung der Funktion	
**/

if (!function_exists('sync_plugwise_powerstate'))
{
function sync_plugwise_powerstate($powerstate_id, $powerset_id)
{
	if (GetValueBoolean($powerstate_id) <> GetValueBoolean($powerset_id))
	{
		$upd_powerstate_arr = IPS_GetVariable($powerstate_id);
		$upd_powerstate     = $upd_powerstate_arr["VariableUpdated"];
		$upd_powerset_arr = IPS_GetVariable($powerset_id);
		$upd_powerset     = $upd_powerset_arr["VariableUpdated"];
		if ($upd_powerstate <= $upd_powerset) SetValueBoolean($powerstate_id, GetValueBoolean($powerset_id));
		else if ($upd_powerstate >= $upd_powerset) SetValueBoolean($powerset_id, GetValueBoolean($powerstate_id));
	}
}
}
?>

akm_switch_plugwise

<?
/**
  akm_switch_plugwise
  Ersteller: Markus Kromberg
  Version 1.0.1

  Aufgabe:
     Diese Funktion wird bei Statusänderung der Anwesenheit ausgeführt.
	 Sie geht den kompletten Plugwise-Baum durch, analaysiert die Variablen "akm_abw" und "akm_anw"
	 und führt ggf. die gewünschte Schaltaktion aus 
	 
  Trigger:
    Diese Funktion wird durch ein Script bei AKM-Statusänderung (anwesend / abwesend) getriggert
  
  Parameter:
	$var_anw_abw = "abw":	Abwesend, die Wohnung ist leer
	$var_anw_abw = "anw":	Anwesend, es ist jemand zu Hause	

  Historie:
    15.02.2012: Kommentar-Block
    02.05.2011: initiale Erstellung der Funktion	
**/

if (!function_exists('akm_switch_plugwise'))
{
function akm_switch_plugwise($var_anw_abw)
{

  /*********************** Config-START ***********************/
  $pw_room_root = 45206; 		// Hier werden von Plugwise die Raum-Kategorien automatisch angelegt
  /*********************** Config-ENDE ***********************/
	
  // Räume finden
  $plugwiseraeume = IPS_GetChildrenIDs($pw_room_root);
  $anzahl_raeume = count($plugwiseraeume);
  for ($ir = 0; $ir < $anzahl_raeume; $ir++) {
  	// Devices finden
    $plugwisedevices = IPS_GetChildrenIDs($plugwiseraeume[$ir]);
    $anzahl_devices = count($plugwisedevices);
    for ($iv = 0; $iv < $anzahl_devices; $iv++)
	 {
      /* akm_abw finden */
      $AKM_VarID = @IPS_GetVariableIDByName("akm_".$var_anw_abw, $plugwisedevices[$iv]);
      $PW_VarID  = @IPS_GetVariableIDByName("powerstate", $plugwisedevices[$iv]);
		$PWS_VarID = @IPS_GetVariableIDByName("powerstate_set", $plugwisedevices[$iv]);
		if ($AKM_VarID != false)
		{
		  $PWS_StatusID = "";
        switch (GetValueInteger($AKM_VarID))
		  {
            case 0:
                break;
            case 1:
                $PWS_StatusID = TRUE;
                SetValueBoolean($PWS_VarID, TRUE);
                break;
            case 2:
                $PWS_StatusID = FALSE;
                SetValueBoolean($PWS_VarID, FALSE);
                break;
        }
		}
	 }
  }
}
}
?>

CreateRoomPower
Mit dieser Funktion können aus dem Webfront Highcharts-Graphen erzeugt werden, die alle Verbraucher des gewählten Raumes beinhalten. Wird in Plugwise Source ein neuer Verbraucher einem Raum hinzugefügt, legt mein IPS-Script den Verbraucher an & die unten stehende Funktion erzeugt beim nächsten Aufruf den aktualisierten Graphen im Webfront.

der Aufruf im Webfront geht über ein Script (Script welches im Webfront angeklickt / gestartet werden kann) mit folgendem Inhalt:

<?
$var_room = "Wohnzimmer";
echo CreateRoomPower($var_room, $_IPS['SELF'], $_IPS['SENDER']);
?>

so, aber nun zur Funktion:

<?php
if (!function_exists('CreateRoomPower'))
{
function CreateRoomPower($var_room, $_IPS_self, $_IPS_sender)
{
	// => ab V1.0004, damit kann der Script auch von anderen Scripten aufgerufen werden und bereits mit CfgDaten vorkonfiguriert werden
	Global $CfgDaten; //$CfgDaten = array();

	// Überschriften
	$CfgDaten["Title"]= $var_room;
	$CfgDaten["SubTitle"]= ""; // "" = Automatisch über Zeitraum

	// IPS Variablen ID´s
	$CfgDaten["ArchiveHandlerId"]= 13860 /*[Archive Handler]*/; 	// Archive Handler
	$CfgDaten["ContentVarableId"]= 50446 /*[_System\Interfaces\Highcharts\content]*/;  // ID der Content-Variable
	$CfgDaten["HighChartScriptId"]= 37206 /*[_System\Interfaces\Highcharts\Highcharts]*/; // ID des Highcharts Scripts

	// Zeitraum welcher dargestellt werden soll
	$CfgDaten["StartTime"] = mktime(0,0,0,    date("m", time()), date("d",time()), date("Y",time())); // ab heute 00:00 Uhr
	$CfgDaten["EndTime"]   = mktime(date("G", time()),59,59, date("m", time()), date("d",time()), date("Y",time())); // ab heute 23:59 Uhr, oder //$CfgDaten["EndTime"] = time();   // = bis jetzt

	// => ab V1.0003
	$CfgDaten["RunMode"]= "files"; 	//oder script

	// => ab V1.0003
	// Serienübergreifende Einstellung für das Laden von Werten
	$CfgDaten["AggregatedValues"]["HourValues"] = 3;      // ist der Zeitraum größer als X Tage werden Stundenwerte geladen
	$CfgDaten["AggregatedValues"]["DayValues"] = 14;       // ist der Zeitraum größer als X Tage werden Tageswerte geladen
	$CfgDaten["AggregatedValues"]["NoLoggedValues"] = 60; // ist der Zeitraum größer als X Tage werden keine Boolean Werte mehr geladen, diese werden zuvor immer als Einzelwerte geladen
	$CfgDaten["AggregatedValues"]["MixedMode"] = false;     // alle Zeitraumbedingungen werden kombiniert

	// Die Parameter für die einzelnen Chart Serien (Achtung! unbedingt auf Groß-Kleinschreibung achten)
	// Name: Name der Kurve (Anzeige in Legende und Tooltip)
	// Unit: NULL = Einheit wird aus Suffix des eingestellten Profils übernommen
	//       "string" = string wird als Einheit eingetragen
	//       array(0=>'String für 0',1=>'String für 1', usw.) = Ist der Wert 0 wird 'Strung für 0' im Tooltip angezeigt, usw
	// ReplaceValues: false = Werte werden wie geloggt übernommen
	//			array(0=>0.2,1=>10, usw.) = der Wert 0 wird in 0.2 geändert, der Wert 1 wird in 10 geändert
	//       das macht für die Darstellung von Boolean Werte Sinn, oder für Drehgriffkontakte (Werte 0,1,2) Sinn
	// Param: Einstellungen der Kurve (hier können werden exakt Einstellungen aus Higcharts.com eingegeben) hier ein paar Beispiele
	//    type: Art der Kurve: Sinn machen [area, areaspline, line, spline, pie], noch nicht sinnvoll dargestellt werden [scatter, bar, column]
	//    step: true oder false - jeder Werte bildet eine Stufe (sinnvoll für Heizungsteller, oder Sollwertvorgaben)
	//    yAxis: Nummer welche Y-Achse verwendet werden soll (ab 0)
	//    shadow: true oder false - Darstellung mit oder ohne Schatten
	//    lineWidth: Linienstärke
	//    alles weitere bitte aus der Higcharts-Referenz entnehmen -> http://www.highcharts.com/ref/
	// und so könnte für eine Achse seperate Einstellungen für die AggregattedValues getroffen werden

	//$AggregatedValuesForSeries["HourValues"] = 3;
	//$AggregatedValuesForSeries["DayValues"] = 2;
	//$AggregatedValuesForSeries["DayValues"] = 2;
	//$AggregatedValuesForSeries["Combined"] = true;
	//,"AggregatedValues"=>$AggregatedValuesForSeries
	
	// Plugwise Raum finden
	$plw_room = @IPS_GetObjectIDByName($var_room, 45206 /*[_System\Aktoren & Geräte\Plugwise\Räume]*/);
	// Plugwise Devices finden
	$plugwisedevices = IPS_GetChildrenIDs($plw_room);
   $anzahl_devices = count($plugwisedevices);
 
   for ($iv = 0; $iv < $anzahl_devices; $iv++)
	{
      $plw_powerusage = @IPS_GetObjectIDByName("powerusage", $plugwisedevices[$iv]);
      $plw_devname = IPS_GetName($plugwisedevices[$iv]);
      $CfgDaten["Series"][] = array("Id"=>$plw_powerusage, "Name" =>$plw_devname, "Unit"=>"Watt", "ReplaceValues"=>false,
		                              "Param" =>"type:'line', step:true, yAxis: 0, shadow: true,lineWidth: 1 , states: {hover:{lineWidth: 2}}, marker: { enabled: false, states: { hover: { enabled: true, radius: 4}}}");
	}
	
	$plw_powerusage_room = @IPS_GetObjectIDByName("powerusage", $plw_room);
	$CfgDaten["Series"][] = array("Id"=>$plw_powerusage_room, "Name" =>"gesamt", "Unit"=>"Watt", "ReplaceValues"=>false,
		                              "Param" =>"type:'area', step:true, yAxis: 0, shadow: true,lineWidth: 1 , states: {hover:{lineWidth: 2}}, marker: { enabled: false, states: { hover: { enabled: true, radius: 4}}}");

	// Y-Achsen
	$CfgDaten["yAxis"][0] = array("Name" =>"Stromverbrauch", "Unit"=>" W","Opposite"=>false);
	//oder direkt den String für die Achsen übergeben $CfgDaten["yAxis"][] = "title: { text: 'Heizungssteller / Luftfeuchte' }, min:0";

	// X-Achse ist autom. Time-Format

	// => ab V1.0002
	// HighchartConfig String
	$CfgDaten["HighChartCfg"]= false;  // false = default String wird verwendet
	$CfgDaten["HighChart"]["Theme"]="ips.js";   // von Highcharts mitgeliefert: dark-green.js, dark-blue.js, gray.js, grid.js

	// Abmessungen des erzeugten Charts
	$CfgDaten["HighChart"]["Width"] = 0; 	// in px,  0 = 100%
	$CfgDaten["HighChart"]["Height"] = 500; 	// in px

	// und jetzt los ......
	$s=IPS_GetScript($CfgDaten["HighChartScriptId"]);      // Id des Highcharts-Scripts
	include($s['ScriptFile']);

  	// => ab V1.0003
  	// hier werden die CfgDaten geprüft und bei Bedarf vervollständigt
	$CfgDaten = CheckCfgDaten($CfgDaten);

	// => ab V1.0003
	if (isset($CfgDaten["RunMode"]) && $CfgDaten["RunMode"] == "script")
	{
		// Variante1: Übergabe der ScriptId. Daten werden beim Aufruf der PHP Seite erzeugt und direakt übergeben. Dadurch kann eine autom. Aktualisierung der Anzeige erfolgen
		if ($_IPS['SENDER'] != "WebInterface")
		{
			WriteContentWithScriptId ($CfgDaten, $_IPS['SELF']);     	// und jetzt noch die ContentTextbox
			return;                                               // Ende, weil durch die Zuweisung des Script sowieso nochmals aufgerufen wird
		}

		$sConfig = CreateConfigString($CfgDaten);             	// erzeugen und zurückgeben des Config Strings
	}
	else
	{
		//Variante2: Übergabe des Textfiles. Daten werden in tmp-File gespeichert. Eine automatische Aktualisierung beim Anzigen der Content-Textbox erfolgt nicht
		$sConfig = CreateConfigString($CfgDaten);             // erzeugen und zurückgeben des Config Strings
		$tmpFilename = CreateConfigFile($sConfig, $_IPS['SELF']);            // und ab damit ins tmp-Files
		if ($_IPS['SENDER'] != "WebInterface")
		{
			WriteContentWithFilename ($CfgDaten, $tmpFilename);        // und jetzt noch die ContentTextbox
		}
	}
	return GetValueString($CfgDaten["ContentVarableId"]);
}
}
?>

Ich weiß das diese Scripte ziemlich quick-and-dirty dahin geschrieben sind und das die fest codierten IPS-ID’s nicht wirklich einem guten Programmier-Stil entsprechen… :rolleyes:
Letztendlich denke ich aber doch, dass es sicherlich für den einen oder andere eine gute Inspiration ist & eventuell Anregungen für eine möglichst gute Integration in IP-Symcon bietet.

Wenn jemand an den Scripten arbeitet & sie verbessert / optimiert würde ich mich über eine Veröffentlichung hier im Thread freuen - damit die ganze Community davon profitieren kann.

Viele Grüße & viel Spaß mit den Script-Bausteinen,
Markus


Versionshistorie
006 2012-02-15: File-Header mit Versionshistorie, Kurzbeschreibung, Trigger- und Parameterübersicht bei allen Files hinzugefügt
005 2012-02-15: create_update_circles: Config-Block, zur einfacheren Anpassung an bestehende Systeme
004 2012-02-15: create_update_circles: Namenskonvertierung / Charset-Konvertierung beim Anlegen der Circles (äöü etc)
003 2012-02-14: Ergänzung CreateRoomPower (Verbrauchs-Graphen im Webfront mit HighCharts)
002 2012-02-14: Ergänzung akm_switch_plugwise (Schaltvorgänge bei An- und Abwesenheit)
001 2012-02-14: Initiale Veröffentlichung der Scripte

Weiterführende Links:
Plugwise Homepage: http://www.plugwise.com
Wie funktioniert das Plugwise System? http://www.plugwise.com/de/idplugtype-f/wie-funktioniert-das-plugwise-system

IPS-Links:
Funkmodul Strommessung: http://www.ip-symcon.de/forum/f23/funkmodul-strommessung-16032/?highlight=Plugwise

Hi,

vielen Dank für Deine Scripte und Deine Arbeit. Könntest Du vielleicht noch etwas dokumentieren was genau die einzelnen Module machen ? Eventuell wäre auch ein Screenshot des Objektbaumes ganz interessant…

Auf den ersten Blick kann ich den Unterschied hierzu: http://www.ip-symcon.de/forum/f23/funkmodul-strommessung-16032/index6.html#post140794 nicht so genau erkennen, könntest Du das eventuell auch noch einmal klarmachen ? Also mir zumindest ^^

Was ich mir ja grundsätzlich für Plugwise wünschen würde: Nicht mehr den blöden webserver laufen haben zu müssen :-/

Vielen Dank und viele Grüße
Martin

Hallo Martin,

ah - vielen Dank für den Hinweis auf das fertige Script, das war mir gar nicht so bewusst g.

Zusätzliche Funktionen meines Scriptes:
>> Plugwise Raumzuordnungen werden aus Plugwise Source übernommen und der Kategoriebaum in IP-Symcon entsprechend aufgebaut

>> es werden automatisch Verbrauchszähler angelegt, somit erhält man eine Übersicht über den Stromverbrauch pro Gerät / pro Raum / insgesamt. Wird ein neues Gerät dem Raum zugeordnet erkennt das Script das automatisch, und berücksichtigt es beim Zählen der Verbrauchswerte

>> es werden automatisch Schaltscripte angelegt, mit deren Hilfe (z.B. über Timer-Events etc) das Gerät geschaltet werden kann

>> Über die Threshold-Variable kann der maximale Verbrauch angegeben werden, bis zu dem geschaltet werden darf. Hintergrund: IP-Symcon darf z.B. eine Steckdose nicht ausschalten, solange der PC / Server noch aktiv läuft. Im Prinzip ist das ein dynamischer Softwareschutzschalter.

>> Die Schalt-Funktion wird automatisch disabled, wenn das Gerät in Plugwise „gelockt“ (nicht händisch schaltbar) gesetzt wird. Die Scripte werden verborgen & die Schaltfuntion im Webfront gesperrt

>> Sollten nach einem Stromausfall / Serverreboot etc. die Schaltzustände von den IP-Symcon-„powerstat_set“-Variablen abweichen, erfolgt automatisch eine Synchronisation & die Plugwise-Circles schalten wieder gemäß den IPS-Vorgaben

>> Über die AKM-Variablen kann hinterlegt werden, was bei Abwesenheit passieren soll. Die entsprechende Funktion / Script zur Verarbeitung der AKM-Variablen ergänze ich später noch im ersten Thread.

>> Zusätzlich werden noch automatisch Schalt-Links sowie Status-Links für das Webfront angelegt, so bekommt man automatisch die Möglichkeit, die neuen Plugwise-Stecker im Webfront zu schalten & den derzeitigen Verbrauch einzusehen.

>> über die Funktion switch_plugwise_device kann relativ schnell & einfach ein Gerät geschaltet werden:

switch_plugwise_device(1, "PWID5525AE");

Man kann relativ einfach einzelne Variablen in Scripten verwenden, ohne die IPS-ID kennen zu müssen:

get_plugwise_variable("powerstate", "PWID5525AE")

So, mehr fällt mir momentan nicht ein - ich bin sicher ich hab noch was vergessen ;-). Doku: ja, die ist Mangelhaft - ich gelobe Besserung & pflege die Scripte mitsamt Doku-Header im Verlauf des Tages hier nach :-).

Wegen dem Webserver: ich fürchte aktuell gibt’s keine andere Möglichkeit, da Plugwise keinen Direktzugriff auf die Circles wünscht. Mich persönlich stört das Ganze aber überhaupt nicht, bei Homematic gehen wir über den BidCos als Vermittler, bei Plugwise über den Webserver der Software. Ob wir jetzt XML-Requests (BidCos XML-RPC-Schnittstelle) oder HTTP-Requests absetzen ist ziemlich wurscht, da das Übertragungsprotokoll das Gleiche ist… Wo ist also das Problem am Plugwise-Webserver?

Viele Grüße,
Markus

Verbrauchszähler.jpg

Klasse vielen Dank !

Das ist ja doch erheblich umfangreicher als das bisherige Skript - wenn ich nachher dazu komme, werde ich es auf jeden Fall testen ! Spätestens morgen. Meine Frau sagte, dass heute irgendein besonderer Tag ist, keine Ahnung…^^

Mein Problem mit dem webserver (im Gegensatz zum BidCos) ist, dass der Webserver als aktive Software laufen muss (zumindest die Servervariante). Das führt dazu, dass mein Server immer wieder mal die Verbindung zum Stick verliert und ich die Software abschiessen muss und neu starten. Im Moment läuft das nachts skriptgesteuert - aber ganz ohne Webserver wäre mir lieber. Aber gut, da kann man wohl momentan nichts machen…

Eine Frage noch zur „powerstat_set“ Variable (sehr gute Idee übrigens): Wenn ich den Circle manuell schalte (Steckdosenleiste aus/ein), geht der Circle ja auf „an“ (was in dem Fall der gewünschte Status ist), in IPS wird er aber als „aus“ gesehen. Das gleiche wenn ich über die Source Software schalte. Beides sind leider bei mir sporadische Anwendungsfälle (Source hat sich aufgehängt und empfängt keine Befehle mehr, ich bin nicht zu Hause, also kann meine Frau mit der Steckdosenleiste den Fernseher einschalten - die übliche Fallback Notlösung :slight_smile: ). Greift in dem Fall auch die „powerstat_set“ und setzt den IPS Zustand oder gilt das wirklich nur bei Stromausfall/Reboot ?

Ansonsten: Klasse Arbeit !

Gerne - freut mich ja wenn ich auch mal wieder was zur Community beitragen kann :slight_smile: :loveips:

Jep, da hast du Recht. Ich habe mir aber gerade nochmal mein Beitrag durchgelesen, das liest sich fast wie ZENSUR-Vergleich von Programmierer-Männern :rolleyes:;):smiley:

das tritt bei mir nicht auf, die Plugwise-Server-Software läuft super stabil. einzige Voraussetzung: am Server muss ein User angemeldet sein, das hab ich allerdings per Auto-Login sichergestellt.

Mein Script lasse ich bei mir alle 5 Minuten laufen, dass heißt nach spätestens 5 Minuten erkennt IP-Symcon (egal ob Stromausfall, Server-Reboot etc) das eine Abweichung zu Plugwise da ist & setzt seinen Dickschädel durch. Folge: Wenn die Threshold-Variable nicht richtig gesetzt wird, wird das laufende Gerät ausgeschaltet. Alternativ kann man aber die Funktion auch deaktivieren & immer den Wert der Plugwise-Variablen übernehmen, dann bleiben die Circles geschaltet & nach spätestens 5 Minuten wird automatisch der richtige Schaltzustand im Webfront angezeigt…

Danke schön :slight_smile:

Viele Grüße,
Markus

Ich habe gerade gesehen, dass in den Scripten noch IPS-Hilfsfunktionen verwendet werden, die eventuell der eine oder andere schon in seiner persönlichen Funktions-Library hat:

CreateScriptByName

<?
/* IP Symcon-Script anlegen */

if (!function_exists('CreateScriptByName'))
{
function CreateScriptByName($ScriptNAME, $ParentID, $ScriptTEXT, $SetHidden = TRUE)
{
   global $_IPS;
    $ScriptID = @IPS_GetScriptIDByName($ScriptNAME, $ParentID);
    if ($ScriptID == 0){

       $ScriptID = IPS_CreateScript(0);
       IPS_SetName($ScriptID, $ScriptNAME);
       IPS_SetParent($ScriptID, $ParentID);
       IPS_SetInfo($ScriptID, "This script was created by: #".$_IPS['SELF']."#");
        $fh = fopen(IPS_GetKernelDir()."scripts\\".$ScriptID.".ips.php", 'w') or die("can't open file");
        fwrite($fh, $ScriptTEXT);
        fclose($fh);
        $ScriptPath = $ScriptID.".ips.php";     //Skriptdatei
        IPS_SetScriptFile($ScriptID, $ScriptPath);
        IPS_SetHidden($ScriptID, $SetHidden);
       // echo "Die Skript-ID lautet: ". $ScriptID;
       return $ScriptID;
    }
}
}
?>

SetScriptRun

<?
 // Diese Funktion ermöglicht das einmalige, zeitverzögerte Starten eines IPS-Scripts
 // SetScriptRun($_IPS['SELF'], time() + 5 * 60); //in 5 Minuten starten

if (!function_exists('SetScriptRun'))
{
function SetScriptRun($scriptID, $startTime)
{
    $eid = @IPS_GetEventIDByName("ScriptRun", $scriptID);
    if($eid === false)
    {
        $eid = IPS_CreateEvent(1);
        IPS_SetParent($eid, $scriptID);
        IPS_SetName($eid, "ScriptRun");
        IPS_SetEventCyclic($eid, 1, 0, 0, 0, 0, 0);
    }
    if($startTime > 0)
    {
        IPS_SetEventCyclicDateBounds($eid, $startTime, 0);
        IPS_SetEventCyclicTimeBounds($eid, $startTime, 0);
    }
    IPS_SetEventActive($eid, $startTime > 0);
}
}
?>

create_link

<?
if (!function_exists('create_link'))
{
function create_link($obj_id, $name, $pos, $parent_id)
{
	// prüfen ob Link existiert
	$does_exist = "false";
	$ips_children = IPS_GetChildrenIDs($parent_id);
	for($i=0; $i < count($ips_children); $i++) {
		$var_name = IPS_GetName($ips_children[$i]);
		if ($var_name == $name) {
			$does_exist = "true";
			$link_id = intval($ips_children[$i]);
		}
	}
	// ggf. Link anlegen
	if ($does_exist == "false") {
		// Link anlegen
		$link_id = IPS_CreateLink();				// Link anlegen
		IPS_SetLinkChildID($link_id, $obj_id);	// Link verknüpfen
		IPS_SetParent($link_id, $parent_id);	// Link einordnen
		IPS_SetName($link_id, $name);				// Link benennen
		IPS_SetPosition($link_id, $pos);			// Position einordnen
	}
	return $link_id;
}
}
?>

ipssql_logging

<?
/**
  $varid =      ObjectID der IPS-Variable
  $do_logging = True / False
  $agg_type =   0 (Standard) / 1 (Zähler)
**/

if (!function_exists('ipssql_logging'))
{
  function ipssql_logging($varid, $do_logging, $agg_type)
  {
    $varid_int = intval($varid);
    AC_SetLoggingStatus(13860 /*[Archive Handler]*/ , $varid_int, $do_logging);
    if ($do_logging == TRUE) AC_SetAggregationType(13860 /*[Archive Handler]*/ , $varid_int, intval($agg_type));
    if(IPS_HasChanges(13860 /*[Archive Handler]*/))
    {
	   IPS_ApplyChanges(13860 /*[Archive Handler]*/);
	 }
  }
}
?>

Ich habe gerade gesehen, dass in den Scripten noch IPS-Hilfsfunktionen verwendet werden, die eventuell der eine oder andere schon in seiner persönlichen Funktions-Library hat:

Hi.

Bin gerade am ausprobieren…

Kann es sein, dass Du die Funktion „create_link“ bei Deinen Helferlein noch posten müsstest?

Grüsse.

Ist erledigt - habe ich wohl übersehen…
Wenn man ständig mit den Hilfsfunktionen arbeitet, vergisst man irgendwann was Standard und was Eigenentwicklung ist :eek::wink:

Viele Grüße & viel Erfolg beim Testen,
Markus

Passt schon. Jetzt brauche ich noch die „ipssql_logging“…

:smiley:

:eek: PEINLICH :eek:

schäm,
Markus

Seit der 2.5 gibt es übrigens SetIdent… Das ist cooler als SetName, da portabler und ihr könnt dann die Namen der Variablen nach belieben verändern :slight_smile:

Übrigens scheint einer das Protokoll rausgetüftelt zu haben. Mit RegisterVariable und ein paar Skripten könntet ihr also wahrscheinlich das ganze direkt in IPS integrieren: http://www.maartendamen.com/2010/01/plugwise-protocol-unleashed-part-1-introduction/

paresy

Danke Paresy, das hört sich gut an. Ergänzende Infos zum Protokoll sind in folgendem PDF zusammen gefasst: http://www.maartendamen.com/wp-content/uploads/downloads/2010/08/Plugwise-unleashed-0.1.pdf

Ich kann halt nicht abschätzen, ob Firmwareupdates auch Auswirkungen auf das Protokoll haben…

Viele Grüße und einen schönen Abend,
Markus

Das passiert eigentlich nie. Wenn das wird es erweitert. Somit ist das Risiko m.E. sehr gering, im Vergleich zum Vorteil, dass die Geräte direkt im System integriert sind.

paresy

Hallo Markus.

Das sieht doch schon viel besser aus. :slight_smile: Und Anmerkungen sind hier immer konstruktiv gemeint. :wink:

Was mir auf den ersten Blick aufgefallen ist:

  • Ich finde es gut, dass Du auch Dinge wie „lastseendate“, „locked“ usw. eingebunden hast. Das geht über die bisherigen Ansätze hinaus.

  • Es gibt ein Problem mit Umlauten bei den Kategorien und Device-Namen. Das könntest Du vermeiden wenn im Script create_update_circles ab Zeile 78 der Teil


  // Anlegen einer neuen Kategorie mit dem Raum-Namen für die Devices
  $RoomID  = create_plugwise_category($room, 45206 /*[_System\Aktoren & Geräte\Plugwise\Räume]*/);

  // Anlegen einer neuen Kategorie mit dem Plugwise-Namen
  $CatID   = create_plugwise_category($device, $RoomID);

durch


  // Anlegen einer neuen Kategorie mit dem Raum-Namen für die Devices
  $room    = htmlentities($room);
  $umlaute = array("ä","ö","ü","Ä","Ö","Ü","ß");
  $replace = array("ä","ö","ü","Ä","Ö","Ü","ß");
  $room    = str_replace($replace, $umlaute, $room);
  $RoomID  = create_plugwise_category($room, 22014 /*[Spielwiese\PlugWise Boyscout\Räume]*/);

  // Anlegen einer neuen Kategorie mit dem Plugwise-Namen
  $device  = htmlentities($device);
  $umlaute = array("ä","ö","ü","Ä","Ö","Ü","ß");
  $replace = array("ä","ö","ü","Ä","Ö","Ü","ß");
  $device  = str_replace($replace, $umlaute, $device);
  $CatID   = create_plugwise_category($device, $RoomID);

ersetzt werden würde. Natürlich ginge das auch mit einer Funktion aber bei zwei Aufrufen lohnt sich das wohl nicht.

  • Es fehlen noch die Variablenprofile Seconds, AKM und HM-Online_Offline. Ist zwar nur ein Schönheitsfehler aber wirft im Skript halt Fehler aus.

Ich spiele da heute abend mal weiter, Feedback garantiert.

Grüsse.

Du - ich finde es ja klasse wenn konstruktive Anmerkungen kommen :-). Also: nur zu - und nicht zurück halten.

Aber zur Charset-Konvertierung: Ich habe das in meinem Script seit gestern so gelöst:

$room = iconv('UTF-8', 'ISO-8859-1', $room);

Da ich es allerdings noch nicht testen konnte, hab ich das Script im Thread noch nicht aktualisiert. Die Zeile hab ich aus dem von Martin verlinkten Script entnommen :smiley:

Ich aktualisiere gleich mal meine neue „create_update_circles“ im ersten Thread.

Ja, die Variablenprofile muss ich mir mal ansehen - vor allem wie ich die vernünftig für’s Forum „exportiert“ bekomme… Sobald ich ne Lösung habe stelle ich diese natürlich auch zur Verfügung!

Viele Grüße,
Markus

$room = iconv('UTF-8', 'ISO-8859-1', $room);  

Das ist natürlich eleganter - wieder acht Zeilen gespart.

So, die wichtigsten Sachen sind direkt im Script kommentiert… ich hoffe das ist so ausreichend?

Gruß,
Markus

P.S.: @all: Na, wo bleiben die Verbesserungsvorschläge…??? :wink:

Danke, das ist super so !

Verbesserungsvorschläge: Meine stille Hoffnung ist, das grad jemand an einer Integration hiervon:http://www.ip-symcon.de/forum/f53/plugwise-ohne-server-direkt-auslesen-schalten-17348/ mit deinen Skripten arbeitet^^

lach ich wusste das das jetzt kommt… :rolleyes:

Na ja, muss dann wohl mal tief in mich gehen… Charme hätte das Ganze ja schon g. Kann man eigentlich per Registervariable auf den Stick zugreifen, solange Source läuft? Geht das für die Übergangszeit parallel?

Wenn ja, dann mach ich mir mal über eine Integration Gedanken. Wenn nein, dann darf es jemand anders machen, da bei mir das ganze Plugwise-System produktiv läuft :slight_smile:

Gruß,
Markus

EDIT:
Mir hat sich gerade ne ziemlich gute Idee ins Hirn gesetzt: Wie wäre es, wenn meine Scripte erkennen ob Source läuft? Wenn ja, dann lade die Info’s über Source (Circle anlegen etc, also die ganze Konfig). Wenn nein, dann geht halt nur ne Light-Variante wie Schalten & Messwerte abfragen… Also wird für die Konfiguration Source benötigt, muss aber anschließend nicht mehr dauerhaft laufen…