Filter für "flatternde" boolsche Meldungen

Hallo zusammen,

nach dem ich schon längere Zeit viele Lösungen und Tricks aus dem Forum erfolgreich nutze, möchte ich der Gemeinschaft auch gerne wieder etwas zurück geben.

Für die Anzeige der aktuellen Wetterdaten meines HM-Kombisensors, der unter anderem eine Meldung für Regen/Kein Regen hat, konnte ich beobachten, das diese Meldung bei leichtem Niederschlag des öfteren im Rythmus der Update-Telegramme hin und her springt. Um diese Meldung zu beruhigen habe ich ein kleines Skript erstellt, welches das zurückfallen der Meldung solange verzögert, bis zwei Update-Telegramme des Kombisensors hintereinander „Kein Regen“ liefern. Die umgekehrte Richtung (also der Wechsel von „Kein Regen“ nach „Regen“) wird dagegen sofort in die Zielvariable übernommen.
Um die Darstellung z.B. im Webfront transparent zu erhalten führt das Skript bei der Installation automatisch folgende Schritte aus:

[ul]
[li] Umbenennen der Quellvariable durch anhängen von „_RAW“[/li][/ul]

[ul]
[li]Verbergen der Quellvariable (Hidden-Eigenschaft auf TRUE setzen)[/li][/ul]

[ul]
[li]Verbergen des Skripts (Hidden-Eigenschaft auf TRUE setzen)[/li][/ul]

[ul]
[li]Anlegen einer neuen Variable (mit Übernahme des Profils der Quellvar.) mit dem originalen Namen an gleicher Stelle[/li][/ul]

[ul]
[li]Erzeugen eines Ereignisses, welches bei Var.-Update das Skript triggert.[/li][/ul]

Zur Anwendung einfach das Skript als Unterobjekt zu der Variable anlegen, die „gefiltert“ werden soll und danach einmal starten (Execute Skript).
Mehrmaliges Starten des Skriptes hat keine nachteiligen Auswirkungen, außer das die Objekt-ID’s der Zielvariable und des Events sich ändern, da beies bei jedem Lauf neu angelegt wird.

Und hier das Skript:


$me = $IPS_SELF;

// Start durch Execute (Installation)
if ($IPS_SENDER == "Execute") {
    // ID der Quellvariable ermitteln
    $sourceVarID = IPS_GetParent($me);

    // Typ der Quellvariable prüfen, im Fehlerfall das Skript mit Fehler abbrechen
    $sourceObjInfo = IPS_GetObject($sourceVarID);
    if ($sourceObjInfo['ObjectType'] != 2)
       die("Dieses Funktionsskript kann nur als Unterobjekt einer Boolean-Variable angelegt werden!");
    $sourceVarInfo = IPS_GetVariable($sourceVarID);
    if ($sourceVarInfo['VariableValue']['ValueType'] !== 0) {
       die("Dieses Funktionsskript arbeitet nur mit einer Variable vom Typ Boolean!");
    }

    echo "sourceObjectInfo:
".print_r($sourceObjInfo, true)."
";
    echo "sourceVariableInfo:
".print_r($sourceVarInfo, true)."
";

    // ID des übergeordneten Objects (Instanz) ermitteln
    $sourceParentID = IPS_GetParent($sourceVarID);
    // Name der Quellvariable ermitteln
    $sourceVarName = $sourceObjInfo['ObjectName'];
    // Profil der Quellvariable ermitteln
    $sourceVarProfile = $sourceVarInfo['VariableProfile'];
    // Neuen Namen für die Ziel- und die Quellvariable erzeugen
    if (substr($sourceVarName, -4) == '_RAW') {
        $newSourceVarName = $sourceVarName;
        $newTargetVarName = substr($sourceVarName, 0, -4);
    } else {
       $newSourceVarName = $sourceVarName.'_RAW';
       $newTargetVarName = $sourceVarName;
    }
    // Jetzt die Quellvariable umbennen um Probleme bei der Ermittlung der targetVarID zu vermeiden
    IPS_SetName($sourceVarID, $newSourceVarName);

    // Prüfen ob die TargetVariable existiert. Wenn ja, die ID ermitteln,
    // sonst eine neue Variable anlegen und unterhalb von sourceParent einordnen
    $targetVarID = @IPS_GetVariableIDByName($newTargetVarName, $sourceParentID);
    if ($targetVarID !== FALSE) {
       // Die Existierende Variable löschen
       IPS_DeleteVariable($targetVarID);
    }
   // Eine neue Ziel-Variable anlegen
   $targetVarID = IPS_CreateVariable(0);
   IPS_SetParent($targetVarID, $sourceParentID);
   IPS_SetName($targetVarID, $newTargetVarName);
   // Und die Quellvariable gleich umbennen
   IPS_SetName($sourceVarID, $newSourceVarName);
    // Das Skript und die Quellvariable unsichtbar (hidden) setzen
    IPS_SetHidden($me, true);
    IPS_SetHidden($sourceVarID, true);
    // Das Variablenprofil der Quellvariable auf die Zielvariable übertragen
    IPS_SetVariableCustomProfile($targetVarID, $sourceVarProfile);
    // Jetzt noch das Trigger-Event erzeugen
    $eventID = @IPS_GetEventIDByName($newSourceVarName.'_OnUpdate', $me);
    if ($eventID !== FALSE) {
       // Das Vorhandene Event-Objekt löschen
       IPS_DeleteEvent($eventID);
    }
    $eventID = IPS_CreateEvent(0);
    IPS_SetName($eventID, $newSourceVarName.'_OnUpdate');
    IPS_SetEventTrigger($eventID, 0, $sourceVarID);
    IPS_SetParent($eventID, $me);
    IPS_SetEventActive($eventID, true);
    IPS_SetHidden($sourceVarID, true);
    IPS_SetName($sourceVarID, $newSourceVarName);
    SetValueBoolean($targetVarID, GetValueBoolean($sourceVarID));
    echo "Das Funktionsskript wurde installiert und in Betrieb gesetzt.";
}
elseif ($IPS_SENDER == 'Variable') {
    $sourceVarID    = $IPS_VARIABLE;
    $sourceParentID = IPS_GetParent($sourceVarID);
    $sourceObjInfo  = IPS_GetObject($sourceVarID);
    $sourceVarName  = $sourceObjInfo['ObjectName'];
    list($resultVarName, $ext) = explode("_", $sourceVarName);
    $resultVarID    = IPS_GetVariableIDByName($resultVarName, $sourceParentID);
    $newValue       = $IPS_VALUE;
    $oldValue       = $IPS_OLDVALUE;
    $smoothedValue  = GetValueBoolean($resultVarID);

    // Wenn der Wert des aktuellen Updates vom Wert der beruhigten Variablen abweicht
    if ($newValue != $smoothedValue) {
        if ($newValue) {
            // Meldung ist TRUE, sofort in die beruhigte Variable übernehmen
            SetValueBoolean($resultVarID, true);
        } else {
           if ($oldValue == false) {
                // Das letzte und das aktuelle Update sind FALSE, jetzt diesen Wert in die beruhigte Variable übernehmen
                SetValueBoolean($resultVarID, false);
            }
        }
    }
}