:: fischer-net.de

Vielleicht steht der Eine oder die Andere vor dem Problem, mehrere Geräte in FHEM in einem Status zusammen fassen zu wollen. Dieser Artikel beschreibt einen möglichen Weg.

 

Hintergrund

HM-OU-LED16HM-OU-LED16
Quelle: eq-3
Vor Kurzem habe ich mir mehrere HomeMatic Statusanzeigen zugelegt um den den Zustand diverser Geräte zu visualisieren.

Eine erste Idee war, den Zustand aller Fenster / Türen auf dem Display zu visualisieren. Zusätzlich sollten noch weitere Geräte angezeigt werden, wie z.B. der Zustand meiner Zentralheizung (siehe dazu auch den Artikel: FHEM Modul zur (erweiterten) Heizungssteuerung). Doch schnell stellt man fest: Es gibt mehr Fenster und Türen als das es LEDs auf dem Display gibt.

Nun Stand ich also vor dem Problem das mir je Statusanzeige genau 16 LEDs zur Verfügung stehen, ich aber weitaus mehr Zustände auf einem Display angezeigt haben wollte. Mehrere Displays nebeneinander zustellen kam als Lösung nicht in Frage. Auch der Verzicht auf den einen oder anderen Gerätezustand sollte keine Alternative darstellen.

So kam mir der Gedanke, das es mir ausreicht darzustellen ob irgendein beliebiges Fenster z.B. im Obergeschoß geöffnet ist. Aber auch bei drei vorhandenen Fenstern im Badezimmer, reicht es mir aus zu sehen, ob irgendein Fenster geöffnet ist.

Es mußte also eine Funktion her um den Zustand mehrerer Geräte zusammen zu fassen.

 

Zustände aggregieren

 

Funktionsweise 

In regelmäßigen Abständen wird der Zustand definierter devices überwacht. Ändert sich der Zustand eines device, so wird der Status eines virtuellen devives (das den aggregierten Zustand darstellt) verändert.

 

Voraussetzungen schaffen 

Neben dem weiter unten beschriebenem Funktion sind in FHEM weitere Schritte notwendig.

Zur Darstellung des aggregierten Zustands wird ein dummy-device angelegt:

define EG.bz.SEC.SC.grp dummy
attr   EG.bz.SEC.SC.grp alias EG Badezimmer, Fenster (alle)
attr   EG.bz.SEC.SC.grp setList state:open,closed

In dem obigen Beispiel heißt das device "EG.bz.SEC.SC.grp" und bekommt noch einen alias sowie eine setList zugewiesen.

Die Überwachung wird mit Hilfe einer at-Definition vorgenommen:

define EG.bz.SEC.SC.grp.job at +*00:01:00 { stateFHTTK("EG.bz.*","EG.bz.SEC.SC.grp") }

Der Job mit dem Namen "EG.bz.SEC.SC.grp.job" ruft jede Minute ("+*00:01:00") die in "geschweiften Klammern" stehende Funktion "stateFHTTK" auf. Diesem Funktionsaufruf folgen zwei weitere Angaben: "EG.bz.*" sowie "EG.bz.SEC.SC.grp".

Der erste Parameter (hier also "EG.bz.*") ist eine Liste der zu überwachenden devices. Da die Funktion "stateFHTTK" nur devices vom Typ "CUL_FHTTK" auswertet, kann hier mit einer gezielten Regular Expression gearbeitet werden. Alternativ könnte man auch alle abzufragenden devices mit einer Leerstelle getrennt aufführen, also z.B. "EG.bz.SEC.SC.01 EG.bz.SEC.SC.02 EG.bz.SEC.SC.03". 

Der zweite Parameter (im obigen Beispiel also "EG.bz.SEC.SC.grp") bezeichnet das zuvor angelegte dummy-device, dessen Status durch die Funktion "stateFHTTK" gesetzt werden soll.

 

Die Funktion stateFHTTK 

Die hier vorgestellte Funktion "stateFHTTK" faßt den Zustand mehrerer FHT80TF-2  Tür-/Fenstermelder zusammen, die in Kombination mit einer FHT80b Heizungsregelung eingebunden sind. 

Um die Funktion in FHEM einzubinden, wird (sofern noch nicht vorhanden) diese in der Datei "99_myUtils.pm" (die sich im Modulpfad von FHEM befinden muß) bereitgestellt.

Der Vollständigkeit halber besteht das folgende Beispiel aus der kompletten Datei "99_myUtils.pm", da vielleicht noch nicht jeder Interessierte, diese (oder eine andere "99_*Utils.pm" Datei) in seiner FHEM Installation angelegt hat. Andere nutzen bitte nur die Funktion "stateFHTTK" um diese in eine vorhandenen Datei zu übertragen.

Eine kurze Anmerkung an dieser Stelle für den "Neueinsteiger":

FHEM bindet u.a. automatisch Dateien aus dem Modulpfad (da wo alle anderen Module wie z.B. "09_CUL_FHTTK.pm", "90_at.pm" oder "98_dummy.pm" liegen) ein, die mit "99_" anfangen und mit "Utils.pm" enden. Über diese "99_*Utils.pm" Dateien hat man also die Möglichkeit FHEM um eigene Funktionen zu erweitern. Dies macht z.B. Sinn, wenn man wie in diesem Beispiel eigene Routinen nutzen möchte, die kein Bestandteil von FHEM sind oder werden. Aber auch unübersichtliche Anweisungen in z.B. notifys können hier strukturiert und wiederverwendbar hinterlegt werden. Man sollte allerdings "Perl sprechen" können ;-) Starte FHEM ggf. nicht, dann sollte man auch eine Überprüfung seiner "99_*Utils.pm" Dateien in Betracht ziehen.

Hier nun die Funktion "stateFHTTK" in einer Datei namens "99_myUtils.pm":

##############################################
# vim: ts=2:et
package main;
use strict;
use warnings;
use POSIX;
sub
myUtils_Initialize($$)
{
  my ($hash) = @_;
}
########################################
sub stateFHTTK($$) {
  my ($search,$device) = @_;
  my $name = "stateFHTTK";
  my $ret;
  if(!$defs{$device}) {
    $ret = "device $device does not exists. Please define it first!";
    Log 1, "$name $ret";
    return $ret;
  }
  my $c = 0;
  my $cOpen = 0;
  my $cClosed = 0;
  my $cUnknown = 0;
  my $state = "closed";
  my $oldState = Value($device);
  foreach my $dev (sort keys %defs) {
    if($dev =~ m/^$search$/ && $defs{$dev}{TYPE} eq "CUL_FHTTK") {
      my $devState = ReadingsVal($defs{$dev}{NAME},"Window","");
      if($devState eq "Open") {
        $state = "open";
        $cOpen++;
      } elsif ($devState eq "Closed") {
        $cClosed++;
      } else {
        Log 0, "DEBUG unknown:$dev";
        $cUnknown++
      }
      $c++;
      Log 5, "stateFHTTK $dev: $devState";
    }
  }
  Log 4, "stateFHTTK Found $c devices ($search): open: $cOpen closed: $cClosed unknown: $cUnknown";
  if($state ne $oldState) {
    my $cmdret = CommandSet(undef, "$device $state");
  }
}
1;

Kurze Beschreibung der Funktion:

Gleich zu Beginn wird überprüft ob das übergebene device (zweiter Parameter aus dem Funktionsaufruf) überhaupt vorhanden ist. Ist dies nicht der Fall, wird an dieser Stelle abgebrochen und ein Log-Eintrag geschrieben.

Als nächstes werden ein paar Zähler definiert um am Ende eines jeden Intervalls eine kleine Statistik über die gefundenen devices sowie deren Status zu erhalten.

Der derzeitige Status des zu schaltenden devices wird ausgelesen ("$oldState = Value($device);") um den Status nur dann zu ändern, wenn er sich auch tatsächlich verändert hat. Dies reduziert den Aufruf von weiteren Triggern.

Schließlich werden alle in FHEM definierten devices durchlaufen und sofern sie vom Typ "CUL_FHTTK" sind und deren Name im Suchstring (erster Parameter aus dem Funktionsaufruf), der "Window" Status abgefragt. "Window" entspricht dabei einem Eintrag in den jeweiligen readings des devices und beinhaltet den Wert "Open" oder "Closed".

Das Ergebnis der Suche wird am Ende in einem Log-Eintrag zusammengefasst.

Zu guter Letzt erfolgt das eigentliche Setzen des aggregierten Status in dem zurvor definiertem dummy-devices. Wie schon erwähnt, wird dieser über "CommandSet" nur dann ausgeführt, sofern sich der Status auch verändert ("$state ne $oldState") hat.

 

Visualisierung mit Hilfe der Statusanzeige HM-OU-LED16

Bleibt zum Schluß noch die Darstellung in der eingangs erwähnten Statusanzeige zu definieren:

define EG.fl.OU.LED16.01.09.n1 notify EG.bz.SEC.SC.grp:open set EG.fl.OU.LED16.01.09 led red
define EG.fl.OU.LED16.01.09.n2 notify EG.bz.SEC.SC.grp:closed set EG.fl.OU.LED16.01.09 led green

Über zwei notify Definitionen wird der Zustand des dummy-devices "EG.bz.SEC.SC.grp" auf "open" oder "closed" überwacht. Je nach Zustand wird die LED 09 der Statusanzeige dann auf "red" oder "green" gesetzt.

 

Zusammenfassung

Dieses Beispiel zeigt, wie man in diesem Fall den Zustand drei unterschiedlicher Fenster in einem Status zusammen fassen kann. Die Darstellung über die Statusanzeige ist in diesem Beispiel optional. 

Das Beispiel kann dazu genutzt werden um den Status anderer Geräte zusammen zu fassen. Hierzu bedarf es dann eigener Anpassungen, wie z.B. des device-Typs "CUL_FHTTK", des readings "Window" und der Zustände "Open" / "Closed".

Natürlich könnte man den Funktionsaufruf auch leicht erweitern und den device-Typ, das reading und die abzufragenden Zustände gleich mit übergeben. Dadurch wäre die Funktion (die dann sinnvollerweise nicht mehr "stateFHTTK" heissen sollte ;-) ) flexibel auf mehrere unterschiedliche devices wie z.B. Schaltaktoren, Rollläden, etc. anwendbar.

Aber das überlasse ich an dieser Stelle mal dem interessiertem Leser. Die eine oder andere Herausforderung außer "Cut n' Paste" sollte ja dann schon noch vorhanden sein ;-)

Powered by ...

 

 

reichelt elektronik – Elektronik und PC-Technik