Hallo Harry,
ich habe mittlerweile auch die gesamte Kommunikation auf den Stretch 2.0 umgestellt, und ziehe in diesem Zug Schritt-für-Schritt alles auf den Banana-Pi um…
Ich hänge dir einfach mal meine Schalt-Funktionen rund um die Plugwise-Kommunikation an - wenn ich was vergessen / übersehen habe, einfach melden :-). Ansonsten können wir uns gerne bei der weiteren Einbindung zusammen tun und gemeinsam weiter entwickeln…
Viele Grüße vom Bodensee,
Markus
<?
IF (GetValueBoolean(47322 /*[_System\ Global Config\System\IPS_Plugwise_Enable]*/ ) == FALSE)
{
exit;
}
/**
Plugwise Circle schalten
Verwendung: PlugwiseSwitchCircle("005512A5", "on")
PlugwiseSwitchCircle("005512A5", "off")
**/
if (!function_exists('PlugwiseSwitchCircle'))
{
function PlugwiseSwitchCircle($CircleID, $STATE)
{
/*********************** Config-START ***********************/
global $_IPS;
$s = IPS_GetScript(get_module_config_include_ID("Plugwise"));
include($s['ScriptFile']);
/*********************** Config-ENDE ***********************/
// Switch setup (circle)
$ApplianceID = get_plugwise_variable("Appliance_ID", $CircleID);
$ApplianceName = get_plugwise_variable("Appliance_Name", $CircleID);
$SwitchStatus = $STATE; // on/off
// Kernel
$AuthBase64 = base64_encode($pw_username.":".$pw_password);
$Postdata = "<relay><state>".$SwitchStatus."</state></relay>";
if ($pw_EnableLogging==TRUE)
{
IPSUtils_Include ("IPSLogger.inc.php", "IPSLibrary::app::core::IPSLogger");
$LogContext = "Plugwise";
$LogMessage = "Switch_Circle ".$CircleID." (".$ApplianceName."): ... Verbindung zu Plugwise-Gateway aufbauen ...";
IPSLogger_Not($LogContext, $LogMessage);
}
$HTTPHandle = fsockopen($pw_ip, 80, $errno, $errstr, 30);
if (!$HTTPHandle) {
if ($pw_EnableLogging==TRUE)
{
IPSUtils_Include ("IPSLogger.inc.php", "IPSLibrary::app::core::IPSLogger");
$LogContext = "Plugwise";
$LogMessage = "Switch_Circle ".$CircleID." (".$ApplianceName."): $errstr ($errno)";
IPSLogger_Err($LogContext, $LogMessage);
}
} else {
$Data = "POST /core/appliances;id=".$ApplianceID."/relay HTTP/1.1
";
$Data .= "Host: ".$pw_ip."
";
$Data .= "Content-Type: application/xml
";
$Data .= "Content-length: ".strlen($Postdata)."
";
$Data .= "Authorization: Basic ".$AuthBase64."
";
$Data .= "Connection: Close
";
$Data .= $Postdata;
fwrite($HTTPHandle, $Data);
while (!feof($HTTPHandle)) {
echo fgets($HTTPHandle, 128);
}
fclose($HTTPHandle);
if ($pw_EnableLogging==TRUE)
{
IPSUtils_Include ("IPSLogger.inc.php", "IPSLibrary::app::core::IPSLogger");
$LogContext = "Plugwise";
$LogMessage = "Switch_Circle ".$CircleID." (".$ApplianceName."): ".$STATE;
IPSLogger_Not($LogContext, $LogMessage);
}
}
}
}
?>
Der Status wird durch folgendes Script synchronisiert:
<?php
IF (GetValueBoolean(47322 /*[_System\ Global Config\System\IPS_Plugwise_Enable]*/ ) == FALSE)
{
exit;
}
/**
sync_plugwise_device
Ersteller: Markus Kromberg
Version 1.0.0
Aufgabe:
Dieses Script
- registriert automatisch neue Plugwise-Circles im IP-Symcon
- legt nötige Variablen, Scripte und Events an
- aktualisiert die Messwerte
- bei Bedarf kann auch nur ein einzelner Circle aktualisiert werden
Updates:
05.12.2014: initiale Erstellung des Scriptes
**/
if (!function_exists('sync_plugwise_state'))
{
function sync_plugwise_state($IPS_SCRIPT_ID, $pw_ip, $pw_username, $pw_password, $pw_circle_root, $pw_UpdateCircleDetails, $pw_CircleID="" )
{
/*********************** Config-START ***********************/
global $_IPS;
$s = IPS_GetScript(get_module_config_include_ID("Plugwise"));
include($s['ScriptFile']);
/*********************** Config-ENDE ***********************/
/**
CACHING-STATUS prüfen
**/
// Cache-Status noch Okay, kein Refresh nötig
$OpenCURL = FALSE;
$output = GetValueString($PW_CacheModulesID);
$oXML = new SimpleXMLElement($output);
/* Globale Variablen - Circle-Unabhängig */
$glob_powerusage = 0.0;
for($i = 0;$i < count($oXML);$i ++)
{
/* Variablen initialisieren */
$devid = "";
$mac_adr = "";
$lastseendate = "";
$powerstate = "";
$powerusage = 0.0;
$appliance_id = "";
$CatID = 0;
$pid_id = 0;
$apl_id = 0;
$ana_id = 0;
$pmc_id = 0;
$lsd_id = 0;
$pst_id = 0;
$pss_id = 0;
$pus_id = 0;
$plugwise_type = 0;
$ApplianceName = "";
$View_PowerstateLabel = "";
/* Variablen auslesen / erzeugen */
$devid = strval($oXML->module[$i]->name);
$plugwise_type = intval($oXML->module[$i]->type);
$mac_adr = strval($oXML->module[$i]->mac_address);
$powerstate = strval($oXML->module[$i]->power_state);
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;
$powerusage = floatval($oXML->module[$i]->current_power_usage);
// Nur Circles / Stealth an dieser Stelle abarbeiten:
IF ($plugwise_type == 1 OR $plugwise_type == 2)
{
// Appliance-Attribute auslesen
if (isset($oXML->module[$i]))
{
if (isset($oXML->module[$i]->appliance))
{
foreach($oXML->module[$i]->appliance->attributes() as $a => $b) {
if ($a == "id") $appliance_id = strval($b);
}
}
}
IF (($pw_circle_root == 0) OR (!ISSET($pw_circle_root)))
{
exit;
}
IF (($pw_view_root == 0) OR (!ISSET($pw_view_root)))
{
exit;
}
// Anlegen einer neuen Kategorie mit dem Plugwise-Namen
$CatID = create_plugwise_category($devid, $pw_circle_root);
IF (($CatID == 0) OR (!ISSET($CatID)))
{
exit;
}
// Anlegen der Variablen
/* powerstate */ $pst_id = create_plugwise_device($CatID, "powerstate", 0, $powerstate_bool, "~Switch", $devid, $devid, 1);
/* powerusage */ $pus_id = create_plugwise_device($CatID, "powerusage", 2, $powerusage, "~Watt.3680", "", $devid, 1);
}
}
}
}
?>
Dazu habe ich mir einige Hilfs-Funktionen geschrieben:
<?
/**
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 ***********************/
global $_IPS;
$s = IPS_GetScript(get_module_config_include_ID("Plugwise"));
include($s['ScriptFile']);
/*********************** Config-ENDE ***********************/
// Circles finden
$CircleID = @IPS_GetObjectIDByName(trim(strval($pwid)), intval($pw_circle_root));
if ($CircleID === false)
echo "Error, Circle:".trim(strval($pwid))." in Root:".$pw_circle_root." nicht gefunden";
else
{
$VariableID = @IPS_GetObjectIDByName($variablename, $CircleID);
if ($VariableID === false)
echo "Error (varname:*".$variablename."*, CircleID:*".$CircleID."*";
else
{
return GetValue($VariableID);
}
}
}
}
?>
<?
IF (GetValueBoolean(47322 /*[_System\ Global Config\System\IPS_Plugwise_Enable]*/ ) == FALSE)
{
exit;
}
/**
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, $ApplianceId, $CircleId, $doupdate = 1, $devlocked_bool = FALSE)
{
/*********************** Config-START ***********************/
global $_IPS;
$s = IPS_GetScript(get_module_config_include_ID("Plugwise"));
include($s['ScriptFile']);
/*********************** Config-ENDE ***********************/
/*********************** Config-START ***********************/
$IPS_INCLUDE_SYNC_CIRCLE_ID = get_plugwise_include_id("sync_circle", $gPlugwise_Root);
$IPS_INCLUDE_SWITCH_CIRCLE_ID = get_plugwise_include_id("switch_circle", $gPlugwise_Root);
/*********************** Config-ENDE ***********************/
// 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 $pw_MasterScriptID;
$ScriptTEXT_switch = '
<?php
/* Dieses Script wurde automatisch durch Script "'.$pw_MasterScriptID.'" erzeugt.
Es dient zum Schalten der Circles sowie zur Überwachung des erfolgreichen
Schaltvorgangs */
/* START Konfiguration */
$CircleID = "'.$CircleId.'";
$ApplianceID = "'.$ApplianceId.'";
$pw_ip = "'.$pw_ip.'";
$pw_username = "'.$pw_username.'";
$pw_password = "'.$pw_password.'";
$pw_circle_root = '.$pw_circle_root.';
$pw_MasterScriptID = "'.$pw_MasterScriptID.'";
/* ENDE Konfiguration*/
$s = IPS_GetScript('.$IPS_INCLUDE_SWITCH_CIRCLE_ID.');
include($s["ScriptFile"]);
?>';
$script_switch = CreateScriptByName("switch_circle", $VarID_ID, $ScriptTEXT_switch);
$eid = IPS_CreateEvent(0); //Ausgelöstes Ereignis
IPS_SetEventTrigger($eid, 0, $VarID_ID); //Bei Änderung von Variable mit ID 15754
IPS_SetEventTriggerValue($eid, false); //Nur bei "TRUE" auslösen
IPS_SetParent($eid, $script_switch); //Ereignis zuordnen
IPS_SetEventActive($eid, true); //Ereignis aktivieren
}
/* Nach Variablen-Neuanlage Wert immer übernehmen */
$doupdate = 1;
}
/* Wert übernehmen */
if ($doupdate != 0)
{
/* ggf. Appliance-Name abfragen */
if ($name == "Appliance_Name")
{
/**
CACHING-STATUS prüfen
**/
IF (get_plugwise_cachevar_stateOK("Appliances", $PW_Master_ID) == TRUE)
{
// Cache-Status noch Okay, kein Refresh nötig
$PW_CacheVarID = get_plugwise_cachevar_id("Appliances", $PW_Master_ID);
$output = GetValueString($PW_CacheVarID);
} else
{
if ($pw_EnableLogging==TRUE)
{
IPSUtils_Include ("IPSLogger.inc.php", "IPSLibrary::app::core::IPSLogger");
$LogContext = "Plugwise";
$LogMessage = "Create_Plugwise_Device: ... Verbindung zu Plugwise-Gateway aufbauen ...";
IPSLogger_Not($LogContext, $LogMessage);
}
$chname = curl_init();
curl_setopt($chname, CURLOPT_URL, "http://".$pw_ip."/minirest/appliances");
curl_setopt($chname, CURLOPT_USERPWD, $pw_username . ":" . $pw_password);
curl_setopt($chname, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($chname, CURLOPT_HEADER, 0);
$output = curl_exec($chname);
/**
CACHING: Wenn kein Filter aktiv, dann Array-Inhalt in Variable zwischenspeichern
**/
set_plugwise_cachevar("Appliances", $PW_Master_ID, $output);
curl_close($chname);
}
$tmpXML = new SimpleXMLElement($output);
$oXML = $tmpXML->xpath("//*[@id='".$ApplianceId."']");
$value = strval(convertToUTF8($oXML[0]->name));
}
switch ($type)
{
case 0:
if (is_bool($value) == true)
{
if (GetValueBoolean($VarID_ID) != $value)
{
SetValueBoolean($VarID_ID, $value); // Wert übernehmen
if ($pw_EnableLogging==TRUE)
{
IPSUtils_Include ("IPSLogger.inc.php", "IPSLibrary::app::core::IPSLogger");
$LogContext = "Plugwise";
$LogMessage = "Create_Plugwise_Device: Update Variable ".IPS_GetName(IPS_GetParent($VarID_ID))."[".IPS_GetName($VarID_ID)."]: ".var_export($value, true);
IPSLogger_Not($LogContext, $LogMessage);
}
}
}
break;
case 1:
if (GetValueInteger($VarID_ID) != $value) SetValueInteger($VarID_ID, $value); // Wert übernehmen
break;
case 2:
if (GetValueFloat($VarID_ID) != $value) SetValueFloat($VarID_ID, $value); // Wert übernehmen
break;
case 3:
if (GetValueString($VarID_ID) != $value) SetValueString($VarID_ID, $value); // Wert übernehmen
break;
}
}
return $VarID_ID;
}
}
?>
<?
/**
get_plugwise_cachevar_id
Ersteller: Markus Kromberg
Version 1.0.1
Aufgabe:
Diese Funktion liefert die ID einer Caching-Variable zurück
Parameter:
$variablename: Name der Variable
$pwid: Plugwise-Master-ID
Historie:
09.12.2014: initiale Erstellung der Funktion
**/
if (!function_exists('get_plugwise_cachevar_id'))
{
function get_plugwise_cachevar_id($variablename, $pwid)
{
/*********************** Config-START ***********************/
global $_IPS;
$s = IPS_GetScript(get_module_config_include_ID("Plugwise"));
include($s['ScriptFile']);
/*********************** Config-ENDE ***********************/
// Circles finden
$CircleCacheFolderID = @IPS_GetObjectIDByName("Caching", $pw_circle_root);
if ($CircleCacheFolderID === false)
echo "Error, CacheFolder *Caching* not found!";
else
{
$VariableID = @IPS_GetObjectIDByName($variablename, $CircleCacheFolderID);
if ($VariableID === false)
echo "CacheVariable *".$variablename."* not found!";
else
{
return $VariableID;
}
}
}
}
?>
<?
/**
get_plugwise_cachevar_stateOK
Ersteller: Markus Kromberg
Version 1.0.1
Aufgabe:
Diese Funktion liefert den Cache-Status einer Caching-Variable zurück
Parameter:
$variablename: Name der Variable
$pwid: Plugwise-Master-ID
Historie:
09.12.2014: initiale Erstellung der Funktion
**/
if (!function_exists('get_plugwise_cachevar_stateOK'))
{
function get_plugwise_cachevar_stateOK($variablename, $pwid)
{
/*********************** Config-START ***********************/
global $_IPS;
$s = IPS_GetScript(get_module_config_include_ID("Plugwise"));
include($s['ScriptFile']);
/*********************** Config-ENDE ***********************/
// Circles finden
$CircleCacheFolderID = @IPS_GetObjectIDByName("Caching", $pw_circle_root);
if ($CircleCacheFolderID === false)
return FALSE;
else
{
$VariableID = @IPS_GetObjectIDByName($variablename, $CircleCacheFolderID);
if ($VariableID === false)
return FALSE;
else
{
$Variable = IPS_GetVariable($VariableID);
$VariableTimeStamp = $Variable["VariableUpdated"];
$VariableAge = time()-$VariableTimeStamp;
$PW_MaxAgeID = get_plugwise_configvar_id("Cache_MaxAge", $pw_circle_root);
$PW_ForceUpdateID = get_plugwise_configvar_id("Update_CircleCache", $pw_circle_root);
$PW_ForceUpdate = GetValueBoolean($PW_ForceUpdateID);
$PW_MaxAge = GetValueInteger($PW_MaxAgeID);
/**
Variable auf MaxAge prüfen, alternativ Update Forcen wenn $PW_ForceUpdate=TRUE.
Ausnahme: letztes Update wurde vor weniger als 2 Sekunden durchgeführt, dann kein Update (Denial of Service-Schutz)
**/
IF (($VariableAge <= $PW_MaxAge AND $PW_ForceUpdate==FALSE) OR $VariableAge <= 10)
{
return TRUE;
} else
{
return FALSE;
}
}
}
}
}
?>
<?
/**
set_plugwise_cachevar
Ersteller: Markus Kromberg
Version 1.0.1
Aufgabe:
Diese Funktion schreibt eine Plugwise Cache-Variable & legt diese sowie
alle Child-Variablen notfalls automatisch an
Parameter:
$variablename: Name der Variable
$pwid: Plugwise-Master-ID
$content: Inhalt der geschrieben werden soll
Historie:
09.12.2014: initiale Erstellung der Funktion
**/
if (!function_exists('set_plugwise_cachevar'))
{
function set_plugwise_cachevar($variablename, $pwid, $content)
{
$pw_circle_root = $pwid;
// Cache-Variable finden
$CircleCacheFolderID = @IPS_GetObjectIDByName("Caching", $pw_circle_root);
if ($CircleCacheFolderID === false)
echo "Error!";
else
{
$VariableID = CreateVariableByName($CircleCacheFolderID, $variablename, 3, $profile = "", $icon = "", $pos = 0, $hidden=true);
SetValueString($VariableID, $content);
return $VariableID;
}
}
}
?>
Include-Scripte:
<?php
/** SWITCH_CIRCLE **/
// max. Scriptlaufzeit definieren
ini_set('max_execution_time', get_module_configvar("Plugwise", "SYS_max_execution_time_switch_circle"));
IF (get_module_configvar("Plugwise", "000_Enable") == FALSE)
{
Echo "Aborting update_modules";
exit;
}
/*********************** Config-START ***********************/
global $_IPS;
$s = IPS_GetScript(get_module_config_include_ID("Plugwise"));
include($s['ScriptFile']);
/*********************** Config-ENDE ***********************/
/*********************** Functions-START ***********************/
/* Include eines Scriptes über die IPS-ID */
if (!function_exists('includeScript'))
{
function includeScript($scriptID)
{
$s = IPS_GetScript($scriptID);
include($s['ScriptFile']);
}
}
/*********************** Functions-ENDE ***********************/
/*********************** Includes Einbinden-START ***********************/
/* Kategorien laden */
$funct_arr = IPS_GetChildrenIDs($pw_MasterFunctionID);
for($j=0; $j < count($funct_arr); $j++)
{
includeScript($funct_arr[$j]);
}
/*********************** Includes Einbinden-ENDE ***********************/
$SyncRefreshInt = get_module_configvar("Plugwise", "Sync_Refresh_Interval", $GetID=FALSE);
$SyncSwitchInt = get_module_configvar("Plugwise", "Sync_Switch_Interval", $GetID=FALSE);
$SyncMaxRetry = get_module_configvar("Plugwise", "Sync_Max_Retry", $GetID=FALSE);
$PowerState = get_plugwise_variable("powerstate", $CircleID);
$SetPowerState = get_plugwise_variable("powerstate_set", $CircleID);
$ApplianceName = get_plugwise_variable("Appliance_Name", $CircleID);
$ErrorCountID = CreateVariableByName($_IPS["SELF"], "error_count", 1, $profile = "", $icon = "", $pos = 0, $hidden=true);
$UpdateNameID = CreateVariableByName($_IPS["SELF"], "update_name", 0, $profile = "", $icon = "", $pos = 0, $hidden=true);
$UpdateName = GetValueBoolean($UpdateNameID);
$SetPowerStateID = get_plugwise_variable_id("powerstate_set", $CircleID);
$ErrorCount = GetValueInteger($ErrorCountID);
// Schalt-Anforderung auf jeden Fall an Plugwise übertragen
IF ($SetPowerState == TRUE)
{
PlugwiseSwitchCircle($CircleID, "on");
}
else
{
PlugwiseSwitchCircle($CircleID, "off");
}
IF ($PowerState == $SetPowerState)
{
SetValueInteger($ErrorCountID, 0);
if ($pw_EnableLogging==TRUE)
{
IPSUtils_Include ("IPSLogger.inc.php", "IPSLibrary::app::core::IPSLogger");
$LogContext = "Plugwise";
$LogMessage = "switch_circle: $ApplianceName Powerstate passt, keine Aktion nötig ($CircleID)";
IPSLogger_Dbg($LogContext, $LogMessage);
}
//Timer ausschalten
IPS_SetScriptTimer($_IPS['SELF'], 0);
}
IF (($PowerState != $SetPowerState) AND ($ErrorCount <= $SyncMaxRetry))
{
IF ($SetPowerState == TRUE)
{
if ($pw_EnableLogging==TRUE)
{
IPSUtils_Include ("IPSLogger.inc.php", "IPSLibrary::app::core::IPSLogger");
$LogContext = "Plugwise";
$LogMessage = "switch_circle: $ApplianceName Powerstate fehlerhaft, $CircleID einschalten";
IPSLogger_Dbg($LogContext, $LogMessage);
}
}
IF ($SetPowerState == FALSE)
{
if ($pw_EnableLogging==TRUE)
{
IPSUtils_Include ("IPSLogger.inc.php", "IPSLibrary::app::core::IPSLogger");
$LogContext = "Plugwise";
$LogMessage = "switch_circle: $ApplianceName Powerstate fehlerhaft, $CircleID ausschalten";
IPSLogger_Dbg($LogContext, $LogMessage);
}
}
$ErrorCount = $ErrorCount+1;
SetValueInteger($ErrorCountID, $ErrorCount);
IPS_SetScriptTimer($_IPS['SELF'], $SyncSwitchInt);
}
includeScript(22155 /*[_System\ Global Includes\include_footer]*/ );
?>
Was mir negativ aufgefallen ist:
[ul]
[li] Teilweise dauert das Abrufen der XML-Seite vom Stretch 2.0 relativ lange, aus diesem Grunde speicher ich mir die Seiten in einer Caching-Variable zwischen, die zyklisch automatisch aktualisiert wird. Dadurch können selbst mehrere parallele Script-Aufrufe relativ gut abgearbeitet werden (z.B. bei vielen Schaltaktionen durch Wechsel Anwesenheit)
[/li][li] Wir bekommen keine aktive Benachrichtigung über Status-Wechsel, der Circle-Status muss jederzeit aktiv angefragt werden
[/li][/ul]