FTUI FUIP - ReadingsGroup "Nachbauen"

Begonnen von bismosa, 28 November 2018, 22:17:41

Vorheriges Thema - Nächstes Thema

bismosa

Hallo!
Ich mache gerade meine ersten Versuche mit dem FUIP / FTUI. Ich nutze als Anfänger den FUIP, allerdings bei fast allen Widgets die Möglichkeit eigenes HTML einzufügen.
Echt klasse! Dank FUIP traut man sich da etwas eher ran. Da kann man doch wesentlich schneller das Layout anpsasen...und die Elemente einfach hin und herschieben  8)
Ich habe bereits einiges fertig. Die Heizkörper, div. Funksteckdosen, Rolläden, Wetter...es wird also schon!

Nun habe ich gerade das Problem, das ich sowohl eine (Leer)-Batterieanzeige als auch eine Anzeige der wichtigsten Heizkörper auf der Hauptseite tabellarisch darstellen möchte.
Bei den Heizkörpern ist es noch relativ einfach. Hier kann ich mir eine Tabelle bauen und mit einzelnen Labels die Readings anzeigen. Habe ich zwar schon fertig als ReadingsGroup...aber ich habe jetzt immer wieder gelesen, dass diese nicht (richtig) unterstützt wird. Bei mir ist es so, dass sich die Were der Readingsgroup nur verändern, wenn ich die Ganze Seite neu lade. Ist mit etwas Aufwand problemlos lösbar.

Das schwierigere Problem ist die Anzeige der Geräte, die eine leere Batterie haben. Hier habe ich auch eine Readingsgroup, die mir das in FHEM super anzeigt....aber wie kann ich eine Tabelle aufbauen, die Dynamisch erzeugt wird? Es kommen ja auch immer wieder neue GEräte hinzu, die als Reading "battery" besitzen. Da ist das mit der Readingsgroup echt praktisch. Gibt es da bereits eine "fertige" Lösung? Vermutlich fehlt mir nur der richtige Ansatz...denn eigentlich werde ich das Problem vermutlich nochmal haben, wenn ich meine eigenen  "Fehlermeldungen" wie z.B. ein ausgelöster Wassermelder, ein nicht erreichbares Gerät, abgefallene Fenstersensoren, ausgefallene Heizung etc. auch darstellen möchte. Wie macht ihr das? MIr fehlt hier gerade eine passende Idee...

Gruß
Bismosa
1x nanoCUL 433MHz (SlowRF Intertechno) für Fenstersensoren
1x nanoCUL 868Mhz für MAX (9x HT 1xWT)
1x ZigBee CUL
Weiteres: Squeezebox server, Kindle Display, ESP8266, Löterfahrung, ...

Thorsten Pferdekaemper

Hi,
danke erstmal für die positive Rückmeldung zu FUIP!

Für die Anzeige der Batterien gibt es den View "Batteries". Ich glaube, dass das so ziemlich genau das ist, was Du brauchst. Inzwischen kann man bei dem Teil auch die Anzahl der Spalten wählen und die Größe selbst bestimmen. Wenn man das Flex-Layout verwendet, dann passt das Ding sogar u.U. seine Größe selbst an.
Der View wählt automatisch alle Devices aus, die bestimmte Readings haben (wie z.B. "battery"). Allerdings reicht kein Browser-Refresh, um neue Devices zu finden. Man muss entweder FHEM neu starten oder ein "set <FUIP-Device> refreshBuffer" absetzen (und dann ein Browser-Refresh machen). Das ist deswegen so, weil das Ermitteln der Devices relativ teuer (laufzeitintensiv) sein kann und ich es deshalb nicht jedesmal mache.

Jetzt könnte man sich überlegen, das ganze zu etwas Allgemeinerem zu erweitern. Das ist aber gar nicht so einfach, insbesondere wenn man die ganze Mächtigkeit der ReadingsGroup im Auge hat. Vielleicht könnte ich etwas bauen, welches eine Tabelle aufbaut, deren Zellen aus gleichartigen Views besteht, nur halt für unterschiedliche Devices. Allerdings müsste man dann das Device als RegEx angeben, was nicht unbedingt der Philosophie von FUIP entspricht.
Auf der anderen Seite gibt es vielleicht gar nicht so viele Fälle, in denen so etwas sinnvoll ist. Hast Du noch einen Fall außer das mit den Batterien?

Jetzt noch die Sache mit den "Fehlermeldungen". Hier hat man ja erst einmal das Problem, diese Meldungen in ein allgemeines Format zu bringen. Ein ausgelöster Wassermelder sieht ja erst einmal anders aus als ein nicht erreichbares Gerät. Da bräuchte man erst einmal etwas (im "Backend"), was diese Meldungen erzeugt und sie z.B. in spezielle Readings schreibt. (Vielleicht gibt es so etwas in der Art schon.) Dafür könnte man dann ein FUIP-View basteln, der die Meldungen entsprechend anzeigt.
Natürlich gibt es auch andere vorstellbare Möglichkeiten, aber das fällt mir dazu als erstes ein.

Meinungen?

Gruß,
   Thorsten
FUIP

bismosa

Hallo!
Ja. Die Anzeige "Batteries" habe ich natürlich probiert. Das sieht aber so aus wie im Anhang (In meiner Testumgebung...in der Live-Umgebung sind da noch 15 Sensoren mehr aufgelistet).
Da ich es gerne auf der "Hauptseite" hätte (und zwar nur die die Leer sind) könnte ich ein Dummy erstellen, mir ein paar Readings ausdenken und über eine Funktion in myUtils.pm diese bei einem Event ausfüllen. Das ist natürlich ein hoher Aufwand...
Dabei Fällt mir spontan ein, man könnte auch auf der Hauptseite nur ein Symbol mit Warnsymbol machen (mit der Anzahl der leeren Batterien). Da dann ein Popup mit entweder allen Batterien (wobei die Anzeige auf meinem 8" Tab schon kanpp wird) oder dann halt "nur" die Geräte mit leeren Batterien.
Eigentlich wäre es schön, wenn es eine Option in FUIP geben würde "nur leere Batterien"...aber dann sind wir wieder beim RegEx...
Zusätzlich würde ich mir auch gerne eine Funktion einbauen "Bestätigen". Z.B. meine Fensterkontakte melden nur eine leere Batterie. Zurücksetzen muss ich das manuell. Da wäre ein Knopf ideal.

Ja...ich habe sogar noch einen weiteren Fall. Der ist eigentlich noch viel spannender als leere Batterien. Offene Fenster! Ich möchte beim verlassen des Hauses sehen, welche Fenster noch geöffnet sind. Hier reicht mir eine Anzeige der Anzahl allerdings nicht aus. Im Sommer kann im OG ein Fenster offen stehen bleiben wenn man nur kurz weg ist...aber im EG ist es besser, wenn sie geschlossen sind. Auch im Keller steht häufiger ein Fenster gewollt auf (Einbruch nicht möglich).
Eine Anzeige aller Fenster macht keinen Spaß und ist nicht übersichtlich. Ich habe 33 Fensterkontakte am Start...puh.
Bisher nutze ich zur Visualisierung ein E-Book reader. Aktualisierung nur alle 2 Minuten...und erzeuge den Text für die offenen Fenster in der myUtils.pm. Da ist etwas wie eine Readingsgroup natürlich einfacher und bei einem neuen Device nicht Wartungsintensiv.

Eigentlich weiß ich selbst noch nicht, wie ich das alles am besten darstellen soll/kann. Die Möglichkeiten sind ja nun so vielfältig...und wesentlich besser als beim EBook Display.
Ich habe zusätzlich noch Fehlermeldungen eingebaut wie
- Raspberry Online/Temperatur/Speicherkartenplatz/HDD Platz/Temperatur/
- Heizungsstörung/Ölstand niedrig
- Fenstersensor abgefallen
- Wassermelder ausgelöst
- Überlauf Heizung
- ....

Alles manuell einprogrammiert. Ich frage mich nur ob es da nicht eine elegantere Lösung gibt. Letztendlich brauche ich wohl ein Modul "Störmeldeliste". Mit der Möglichkeit des Zurücksetzens. Schwierig...und vermutlich nicht so umsetzbar.

Ich glaube es läuft auf folgenden Plan hinaus:
Dummy mit Div. Eigenschaften:
DeviceName_01 - Meldung_01 - MeldeDatum_01 - ...
DeviceName_0x - Meldung_0x - MeldeDatum_0x - ...

Und in der myUtils.pm ein Script, das zuerst die Fehlermeldungen durchgeht, danach die Meldungen und dies dann jeweils in die readings einträgt.
Im FUIP / FTUI dann einfach eine Tabelle...wo dann nur das angezeigt wird, was auch vorhanden ist.

Aufpassen muss ich dann nur, dass auch von jedem Gerät ein Event erzeugt wird, worauf eine Triggerung stattfindet.

Könnte man hier eine "Schweinerei" einbauen, dass HTML-Code in der myUtils.pm erzeugt wird, dass ich z.B. ein Icon in einer Tabellenzeile hinzufüge, das mit einer bestimmten Aktion verknüpft ist?

Danke für die Denkanstösse!

Gruß
Bismosa
1x nanoCUL 433MHz (SlowRF Intertechno) für Fenstersensoren
1x nanoCUL 868Mhz für MAX (9x HT 1xWT)
1x ZigBee CUL
Weiteres: Squeezebox server, Kindle Display, ESP8266, Löterfahrung, ...

Thorsten Pferdekaemper

Hi,
das sind alles interessante Ideen. Allerdings müsste man das mal ein bisschen sortieren, denke ich.

1. View Batteries mit "nur leer"
Zuerst dachte ich, dass man hier das Problem der Entscheidung hat, wann eigentlich eine Batterie leer ist. Allerdings entscheidet der View das jetzt im Prinzip auch schon. Diese Entscheidung ist zumindest unabhängig vom Anzeigeproblem.
Für die Anzeige müsste man im Prinzip ein komplett neues FTUI-Widget bauen. Ansonsten könnte ich vielleicht etwas hinbekommen, was zumindest ein Browser-Refresh braucht, um die Anzeige bei Änderungen entsprechend neu aufzubauen. Wie auch immer die Lösung dazu genau aussehen wird: Man wird es vielleicht auch verallgemeinern können für andere "Alerts".
Machst Du mir dazu einen neuen Thread? (Außer: siehe den Punkt über die Störmeldeliste.)

2. Das Warnsymbol ist ggf. auch interessant, aber wahrscheinlich tatsächlich einfacher im Backend zu erledigen. Ein Popup draufzulegen geht mit FUIP ja heute schon.

3. Wenn die Anzeige auf einem 8'' Tab knapp wird, dann einfach die Zelle (oder den View) kleiner machen. Beim Batteries-View müssten dann Scrollbars erscheinen.

4. Zu Fenstern habe ich bisher gar nichts spezielles bei FUIP. Das liegt vor Allem daran, dass ich selbst noch gar keine produktiv im Einsatz habe. Gerne würde ich da etwas bauen, vielleicht so ähnlich wie das Batteries-Teil. Wenn wir das für die Batterien schaffen, dann erst recht für die Fenster.
Machst Du mir einen eigenen Thread dafür? (Außer: siehe den Punkt über die Störmeldeliste.)

5. Das mit der Störmeldeliste müsste man meiner Meinung nach erstmal im Backend erledigen. Am besten ein eigenes Modul "Alerts" oder so, welches eine solche Liste verwaltet. Vielleicht gibt es so etwas auch schon. Das gehört aber eher ins Unterforum "Automatisierung". (Oder so?) Hast Du dort schon einmal danach gefragt?
Sehr schwierig sollte das nicht sein. Einfach ein Device, welches ein "set ... <device> <meldung>" kann und das dann entsprechend in ein Reading schreibt. Die Anzahl der Readings ist dann natürlich dynamisch.
Im Frontend muss man dann einfach die Liste der Readings anzeigen.
Möglicherweise kann man damit dann auch die Batterie- und Fensterproblematik erschlagen. Dann wären die Klimmzüge für die Batterien und Fenster nicht mehr notwendig. Natürlich bräuchte man dann noch irgendwie Icons und eine erledigt-Funktion, aber das kann ja nicht die Welt kosten.

6. Die Schweinerei im der myUtils wäre dann ein neuer View für FUIP. Wenn wir das machen, dann können wir auch gleich einen eigenen View dafür bauen.

Gruß,
   Thorsten
FUIP

bismosa

Hallo,

vielen Dank für die ausführliche Antwort!
Ich versuche hier auch erst einmal zu sortieren. Bitte fange nicht gleich an alles umzubauen oder neue Widgets zu entwerfen. Finde dein Engagement wirklich super...aber ich glaube ich bin zu kompliziert für einfache Widgets  :)

Ich habe gerade die zeit genutzt und habe meine "Anzeigetabelle" für die Heizkörper fertig gestellt. Natürlich gleich mit unterschiedlichen Farben, blinken bei Modus "manual" und "boost" in unterscheidlicher Farbe etc. Das lässt sich wohl kaum verallgemeinern...
Gar nicht so einfach ein Screenshot bei blinkenden Werten zu machen....siehe Anhang.

<div align="left">
<table>
<tbody>
<tr>
<td>
<div>Wohnzimmer</div>
</td>
<!--Modus-->
<td style="padding-left: 3px;">
<div class="blink" data-type="label" data-device="Max_WT_Wohnzimmer" data-get="mode" data-hide-off="manual" data-hide-on="!manual" data-color="yellow"></div>
<div class="blink" data-type="label" data-device="Max_WT_Wohnzimmer" data-get="mode" data-hide-off="boost" data-hide-on="!boost" data-color="#ff0000"></div>
<div data-type="label" data-device="Max_WT_Wohnzimmer" data-get="mode" data-hide-off="auto" data-hide-on="!auto" data-color="green"></div>
</td>
<!--Soll-Temperatur-->
<td style="padding-left: 3px;">
<div data-type="label" data-device="Max_WT_Wohnzimmer" data-get="desiredTemperature" data-unit="°C"  data-limits='[0,16,21,23]' data-colors='["blue","#b877f9","#ff5151","#ff0000"]' data-hide-on="off"></div>
<div class="blink" data-type="label" data-device="Max_WT_Wohnzimmer" data-get="desiredTemperature"  data-color="blue" data-hide-off="off" data-hide-on="!off"></div>
</td>
<!--Ventilposition (nicht möglich beim Wandthermostaten)-->
<td style="padding-left: 3px;">
<div></div>
</td>
<!--IST-Temperatur-->
<td style="padding-top: 0px; padding-bottom:0px; padding-left: 3px;">
<div class="big" data-type="label" data-device="Max_WT_Wohnzimmer" data-get="temperature" data-unit="°C"  data-limits='[0,16,21,23]' data-colors='["blue","#b877f9","#ff5151","#ff0000"]'></div>
</td>
</tr>
<tr>
<td>
<div>Bad unten</div>
</td>
<!--Modus-->
<td style="padding-left: 3px;">
<div class="blink" data-type="label" data-device="Max_HT_Bad_Unten" data-get="mode" data-hide-off="manual" data-hide-on="!manual" data-color="yellow"></div>
<div class="blink" data-type="label" data-device="Max_HT_Bad_Unten" data-get="mode" data-hide-off="boost" data-hide-on="!boost" data-color="#ff0000"></div>
<div data-type="label" data-device="Max_HT_Bad_Unten" data-get="mode" data-hide-off="auto" data-hide-on="!auto" data-color="green"></div>
</td>
<!--Soll-Temperatur-->
<td style="padding-left: 3px;">
<div data-type="label" data-device="Max_HT_Bad_Unten" data-get="desiredTemperature" data-unit="°C"  data-limits='[0,16,21,23]' data-colors='["blue","#b877f9","#ff5151","#ff0000"]' data-hide-on="off"></div>
<div class="blink" data-type="label" data-device="Max_HT_Bad_Unten" data-get="desiredTemperature"  data-color="blue" data-hide-off="off" data-hide-on="!off"></div>
</td>
<!--Ventilposition (nicht möglich beim Wandthermostaten)-->
<td style="padding-left: 3px;">
<div data-type="label" data-device="Max_HT_Bad_Unten" data-get="valveposition" data-unit="%"></div>
</td>
<!--IST-Temperatur-->
<td style="padding-top: 0px; padding-bottom:0px; padding-left: 3px;">
<div class="big" data-type="label" data-device="Max_HT_Bad_Unten" data-get="temperature" data-unit="°C"  data-limits='[0,16,21,23]' data-colors='["blue","#b877f9","#ff5151","#ff0000"]'></div>
</td>
</tr>
<tr>
<td>
<div>Kind1</div>
</td>
<!--Modus-->
<td style="padding-left: 3px;">
<div class="blink" data-type="label" data-device="Max_HT_Kind1" data-get="mode" data-hide-off="manual" data-hide-on="!manual" data-color="yellow"></div>
<div class="blink" data-type="label" data-device="Max_HT_Kind1" data-get="mode" data-hide-off="boost" data-hide-on="!boost" data-color="#ff0000"></div>
<div data-type="label" data-device="Max_HT_Kind1" data-get="mode" data-hide-off="auto" data-hide-on="!auto" data-color="green"></div>
</td>
<!--Soll-Temperatur-->
<td style="padding-left: 3px;">
<div data-type="label" data-device="Max_HT_Kind1" data-get="desiredTemperature" data-unit="°C"  data-limits='[0,16,21,23]' data-colors='["blue","#b877f9","#ff5151","#ff0000"]' data-hide-on="off"></div>
<div class="blink" data-type="label" data-device="Max_HT_Kind1" data-get="desiredTemperature"  data-color="blue" data-hide-off="off" data-hide-on="!off"></div>
</td>
<!--Ventilposition (nicht möglich beim Wandthermostaten)-->
<td style="padding-left: 3px;">
<div data-type="label" data-device="Max_HT_Kind1" data-get="valveposition" data-unit="%"></div>
</td>
<!--IST-Temperatur-->
<td style="padding-top: 0px; padding-bottom:0px; padding-left: 3px;">
<div class="big" data-type="label" data-device="Max_HT_Kind1" data-get="temperature" data-unit="°C"  data-limits='[0,16,21,23]' data-colors='["blue","#b877f9","#ff5151","#ff0000"]'></div>
</td>
</tr>
<tr>
<td>
<div>Kind2</div>
</td>
<!--Modus-->
<td style="padding-left: 3px;">
<div class="blink" data-type="label" data-device="Max_HT_Kind2" data-get="mode" data-hide-off="manual" data-hide-on="!manual" data-color="yellow"></div>
<div class="blink" data-type="label" data-device="Max_HT_Kind2" data-get="mode" data-hide-off="boost" data-hide-on="!boost" data-color="#ff0000"></div>
<div data-type="label" data-device="Max_HT_Kind2" data-get="mode" data-hide-off="auto" data-hide-on="!auto" data-color="green"></div>
</td>
<!--Soll-Temperatur-->
<td style="padding-left: 3px;">
<div data-type="label" data-device="Max_HT_Kind2" data-get="desiredTemperature" data-unit="°C"  data-limits='[0,16,21,23]' data-colors='["blue","#b877f9","#ff5151","#ff0000"]' data-hide-on="off"></div>
<div class="blink" data-type="label" data-device="Max_HT_Kind2" data-get="desiredTemperature"  data-color="blue" data-hide-off="off" data-hide-on="!off"></div>
</td>
<!--Ventilposition (nicht möglich beim Wandthermostaten)-->
<td style="padding-left: 3px;">
<div data-type="label" data-device="Max_HT_Kind2" data-get="valveposition" data-unit="%"></div>
</td>
<!--IST-Temperatur-->
<td style="padding-top: 0px; padding-bottom:0px; padding-left: 3px;">
<div class="big" data-type="label" data-device="Max_HT_Kind2" data-get="temperature" data-unit="°C"  data-limits='[0,16,21,23]' data-colors='["blue","#b877f9","#ff5151","#ff0000"]'></div>
</td>
</tr>
<tr>
<td>
<div>Spielzimmer</div>
</td>
<!--Modus-->
<td style="padding-left: 3px;">
<div class="blink" data-type="label" data-device="Max_HT_Spielzimmer" data-get="mode" data-hide-off="manual" data-hide-on="!manual" data-color="yellow"></div>
<div class="blink" data-type="label" data-device="Max_HT_Spielzimmer" data-get="mode" data-hide-off="boost" data-hide-on="!boost" data-color="#ff0000"></div>
<div data-type="label" data-device="Max_HT_Spielzimmer" data-get="mode" data-hide-off="auto" data-hide-on="!auto" data-color="green"></div>
</td>
<!--Soll-Temperatur-->
<td style="padding-left: 3px;">
<div data-type="label" data-device="Max_HT_Spielzimmer" data-get="desiredTemperature" data-unit="°C"  data-limits='[0,16,21,23]' data-colors='["blue","#b877f9","#ff5151","#ff0000"]' data-hide-on="off"></div>
<div class="blink" data-type="label" data-device="Max_HT_Spielzimmer" data-get="desiredTemperature"  data-color="blue" data-hide-off="off" data-hide-on="!off"></div>
</td>
<!--Ventilposition (nicht möglich beim Wandthermostaten)-->
<td style="padding-left: 3px;">
<div data-type="label" data-device="Max_HT_Spielzimmer" data-get="valveposition" data-unit="%"></div>
</td>
<!--IST-Temperatur-->
<td style="padding-top: 0px; padding-bottom:0px; padding-left: 3px;">
<div class="big" data-type="label" data-device="Max_HT_Spielzimmer" data-get="temperature" data-unit="°C"  data-limits='[0,16,21,23]' data-colors='["blue","#b877f9","#ff5151","#ff0000"]'></div>
</td>
</tr>
</tbody>
</table>
</div>

Damit bin ich schon mal sehr zufrieden! Ob das jetzt alles korrekt umgesetzt ist...keine Ahnung..aber es funktioniert! Und sooo kompliziert war es nun auch nicht.

Zu den anderen Sachen mache ich mir jetzt als nächstes Gedanken. Mit den Scrollbalken war mir noch gar nicht aufgefallen. Das ist ja praktisch. Lässt sich so etwas auch bei einer "eigenen" Tabelle machen? Das probiere ich mal aus. Könnte für die "Störmeldeliste" interessant sein.

Ich melde mich dann wieder....kann aber auch ein paar Tage dauern...die Zeit ist immer schnell weg.

Gruß
Bismosa
1x nanoCUL 433MHz (SlowRF Intertechno) für Fenstersensoren
1x nanoCUL 868Mhz für MAX (9x HT 1xWT)
1x ZigBee CUL
Weiteres: Squeezebox server, Kindle Display, ESP8266, Löterfahrung, ...

bismosa

#5
Hallo,

ich bin endlich wieder ein stückchen weiter gekommen  :)

Ich habe mich nun an die Problematik der Fenster gemacht. Dafür habe ich jetzt ein DOIF.
Ich musste mich erst einmal mit hash-Funktionen in Perl auseinandersetzen...das war alles neu für mich. Ob das so korrekt ist...keine Ahnung...aber es funktioniert!
Kurze Erklärung:
- Ausführung immer wenn ein Fenster betätigt wird oder nach 1Min. wenn mind. ein Fenster offen ist.
- Alle offenen Fenster raussuchen (devspec2array)
- Einen Hash mit den Daten "befüllen"
- Diesen dann nach ReadingsAge sortieren (Ich möchte das zuletzt geöffnete Fenster oben in der Liste haben)
- Die Sortierten Werte (+ zusätzlich einen Text mit der Öffnungsdauer) in Readings des DOIF speichern
- Den eigenen Timer nur aktivieren, wenn auch ein Fenster offen ist
- Die Anzahl der offenen Fenster auch gleich erfassen...

Zuerst hatte ich nur die Readings  angelegt und wieder gelöscht. Das macht in FTUI jedoch "probleme"...gelöschte readings erscheinen immer noch in der Liste. Dies kann man mit
class="autohide"
umgehen...aber nicht in "Echtzeit". Das fand ich nicht so prickelnd.
Daher fülle ich die restlichen Readings mit "&nbsp;" bzw. Alter 0 und die Readings werden sofort ausgeblendet. Die Anzahl lässt sich über
my $Max=50
steuern.

defmod di_Fenster_Liste DOIF (["^Fenster_.*"] \
or [$SELF:Timer] eq 1 and [+00:01:00]\
)({\
##Listenaufbau:\
##Nur offene Fenster auflisten\
##Name_x\
##Age_x\
##Date_x\
##Time_x\
##TTSName_x\
##Anzahl\
##TextLang_x\
my $Max=50;;\
##Alle Fenster durchgehen -> Liste Sortieren -> Neuste Öffnung zuerst\
my %hash;;\
my @Devices=devspec2array("NAME=Fenster_.*:FILTER=STATE=Offen");; \
foreach my $Device (@Devices){\
$hash{$Device}{"Age"}=ReadingsAge("$Device", "state", 0);;\
$hash{$Device}{"Date"}=(split / /, ReadingsTimestamp("$Device", "state", 0))[0];;\
$hash{$Device}{"Time"}=(split / /, ReadingsTimestamp("$Device", "state", 0))[1];;\
$hash{$Device}{"TTSName"}=AttrVal("$Device", "TTSName", "unbekannt");;\
}\
##Log 1, Dumper(\%hash);;\
\
##Sortieren\
my $i=0;;\
for (sort { $hash{$a}->{Age} <=>  $hash{$b}->{Age} } keys %hash){\
    ##Log 1, "$_ ".$hash{$_}{"Date"}." ".$hash{$_}{"Time"};;\
\
##Readings setzen\
fhem("sleep 1;; setreading $SELF Name_".sprintf("%02d", $i)." ".$_);;\
fhem("sleep 1;; setreading $SELF Age_".sprintf("%02d", $i)." ".$hash{$_}{"Age"});;\
##fhem("sleep 1;; setreading $SELF Date_".sprintf("%02d", $i)." ".$hash{$_}{"Date"});;\
##fhem("sleep 1;; setreading $SELF Time_".sprintf("%02d", $i)." ".$hash{$_}{"Time"});;\
fhem("sleep 1;; setreading $SELF TTSName_".sprintf("%02d", $i)." ".$hash{$_}{"TTSName"});;\
my $Text;;\
my $Age=$hash{$_}{"Age"};;\
if ($Age >= 86400){\
my $Tage=int($Age/86400);;\
$Text=$Tage." Tage ";;\
$Age=$Age-$Tage*86400;;\
}\
my $HasHour=false;;\
if ($Age >= 3600){\
my $Stunden=int($Age/3600);;\
$Text.=sprintf("%02d:", $Stunden);;\
$Age=$Age-$Stunden*3600;;\
$HasHour=true;;\
}\
if ($Age >= 60){\
my $Minuten=int($Age/60);;\
if ($HasHour eq false){\
$Text.=$Minuten;;\
$Text.=" Min.";;\
} else {\
$Text.=sprintf("%02d", $Minuten);;\
}\
} else {\
if ($HasHour eq true){\
$Text.="00"\
} else {\
$Text.="0 Min."\
}\
}\
fhem("sleep 1;; setreading $SELF TextLang_".sprintf("%02d", $i)." $Text");;\
$i=$i+1;;\
}\
fhem("sleep 1;; setreading $SELF Anzahl $i");;\
if ($i eq 0){\
fhem("sleep 1;; setreading $SELF Timer 0");;\
}else{\
fhem("sleep 1;; setreading $SELF Timer 1");;\
}\
##Die restlichen Einträge entfernen (leerzeichen) ohne löschen\
while ($i < $Max){\
fhem("sleep 1;; setreading $SELF Name_".sprintf("%02d", $i)." "."&nbsp;;");;\
fhem("sleep 1;; setreading $SELF Age_".sprintf("%02d", $i)." "."0");;\
fhem("sleep 1;; setreading $SELF TTSName_".sprintf("%02d", $i)." "."&nbsp;;");;\
fhem("sleep 1;; setreading $SELF TextLang_".sprintf("%02d", $i)." "."&nbsp;;");;\
$i=$i+1;;\
}\
})
attr di_Fenster_Liste do always


Dazu dann noch die Umsetzung in FUIP/FTUI
Symbol:

<div data-type="symbol"
data-states='["0","!0"]'
data-colors='["green","#FF0000"]'
data-icons='["oa-fts_window_1w_open warn","oa-fts_window_1w_open warn"]'
data-get="Anzahl"
data-device="di_Fenster_Liste"
data-warn-off="0"
data-warn-on="[1-9][0-9]*"
>
</div>

Tabelle:

<div align="left">
<table>
    <tbody>
        <tr>
            <td>
<div class="autohide" data-type="label" data-device="di_Fenster_Liste" data-get="TTSName_00" data-limits-get="Age_00" data-limits='[0,900,3600]' data-colors='["green","yellow","#FF0000"]'></div>
            </td>
<td>
<div class="autohide" data-type="label" data-device="di_Fenster_Liste" data-get="TextLang_00"data-limits-get="Age_00" data-limits='[0,900,3600]' data-colors='["green","yellow","#FF0000"]'></div>
            </td>
</tr>
<tr>
            <td>
<div class="autohide" data-type="label" data-device="di_Fenster_Liste" data-get="TTSName_01" data-limits-get="Age_01" data-limits='[0,900,3600]' data-colors='["green","yellow","#FF0000"]'></div>
            </td>
<td>
<div class="autohide" data-type="label" data-device="di_Fenster_Liste" data-get="TextLang_01" data-limits-get="Age_01" data-limits='[0,900,3600]' data-colors='["green","yellow","#FF0000"]'></div>
            </td>
</tr>
<tr>
            <td>
<div class="autohide" data-type="label" data-device="di_Fenster_Liste" data-get="TTSName_02" data-limits-get="Age_02" data-limits='[0,900,3600]' data-colors='["green","yellow","#FF0000"]'></div>
            </td>
<td>
<div class="autohide" data-type="label" data-device="di_Fenster_Liste" data-get="TextLang_02" data-limits-get="Age_02" data-limits='[0,900,3600]' data-colors='["green","yellow","#FF0000"]'></div>
            </td>
</tr>
<tr>
            <td>
<div class="autohide" data-type="label" data-device="di_Fenster_Liste" data-get="TTSName_03" data-limits-get="Age_03" data-limits='[0,900,3600]' data-colors='["green","yellow","#FF0000"]'></div>
            </td>
<td>
<div class="autohide" data-type="label" data-device="di_Fenster_Liste" data-get="TextLang_03" data-limits-get="Age_03" data-limits='[0,900,3600]' data-colors='["green","yellow","#FF0000"]'></div>
            </td>
</tr>
<tr>
            <td>
<div class="autohide" data-type="label" data-device="di_Fenster_Liste" data-get="TTSName_04" data-limits-get="Age_04" data-limits='[0,900,3600]' data-colors='["green","yellow","#FF0000"]'></div>
            </td>
<td>
<div class="autohide" data-type="label" data-device="di_Fenster_Liste" data-get="TextLang_04" data-limits-get="Age_04" data-limits='[0,900,3600]' data-colors='["green","yellow","#FF0000"]'></div>
            </td>
</tr>
<tr>
            <td>
<div class="autohide" data-type="label" data-device="di_Fenster_Liste" data-get="TTSName_05" data-limits-get="Age_05" data-limits='[0,900,3600]' data-colors='["green","yellow","#FF0000"]'></div>
            </td>
<td>
<div class="autohide" data-type="label" data-device="di_Fenster_Liste" data-get="TextLang_05" data-limits-get="Age_05" data-limits='[0,900,3600]' data-colors='["green","yellow","#FF0000"]'></div>
            </td>
</tr>
<tr>
            <td>
<div class="autohide" data-type="label" data-device="di_Fenster_Liste" data-get="TTSName_06" data-limits-get="Age_06" data-limits='[0,900,3600]' data-colors='["green","yellow","#FF0000"]'></div>
            </td>
<td>
<div class="autohide" data-type="label" data-device="di_Fenster_Liste" data-get="TextLang_06" data-limits-get="Age_06" data-limits='[0,900,3600]' data-colors='["green","yellow","#FF0000"]'></div>
            </td>
</tr>
<tr>
            <td>
<div class="autohide" data-type="label" data-device="di_Fenster_Liste" data-get="TTSName_07" data-limits-get="Age_07" data-limits='[0,900,3600]' data-colors='["green","yellow","#FF0000"]'></div>
            </td>
<td>
<div class="autohide" data-type="label" data-device="di_Fenster_Liste" data-get="TextLang_07" data-limits-get="Age_07" data-limits='[0,900,3600]' data-colors='["green","yellow","#FF0000"]'></div>
            </td>
</tr>
<tr>
            <td>
<div class="autohide" data-type="label" data-device="di_Fenster_Liste" data-get="TTSName_08" data-limits-get="Age_08" data-limits='[0,900,3600]' data-colors='["green","yellow","#FF0000"]'></div>
            </td>
<td>
<div class="autohide" data-type="label" data-device="di_Fenster_Liste" data-get="TextLang_08" data-limits-get="Age_08" data-limits='[0,900,3600]' data-colors='["green","yellow","#FF0000"]'></div>
            </td>
</tr>
<tr>
            <td>
<div class="autohide" data-type="label" data-device="di_Fenster_Liste" data-get="TTSName_09" data-limits-get="Age_09" data-limits='[0,900,3600]' data-colors='["green","yellow","#FF0000"]'><div>
            </td>
<td>
<div class="autohide" data-type="label" data-device="di_Fenster_Liste" data-get="TextLang_09" data-limits-get="Age_09" data-limits='[0,900,3600]' data-colors='["green","yellow","#FF0000"]'></div>
            </td>
</tr>
<tr>
            <td>
<div class="autohide" data-type="label" data-device="di_Fenster_Liste" data-get="TTSName_10" data-limits-get="Age_10" data-limits='[0,900,3600]' data-colors='["green","yellow","#FF0000"]'></div>
            </td>
<td>
<div class="autohide" data-type="label" data-device="di_Fenster_Liste" data-get="TextLang_10" data-limits-get="Age_10" data-limits='[0,900,3600]' data-colors='["green","yellow","#FF0000"]'></div>
            </td>
</tr>
<tr>
            <td>
<div class="autohide" data-type="label" data-device="di_Fenster_Liste" data-get="TTSName_11" data-limits-get="Age_11" data-limits='[0,900,3600]' data-colors='["green","yellow","#FF0000"]'></div>
            </td>
<td>
<div class="autohide" data-type="label" data-device="di_Fenster_Liste" data-get="TextLang_11" data-limits-get="Age_11" data-limits='[0,900,3600]' data-colors='["green","yellow","#FF0000"]'></div>
            </td>
</tr>

    </tbody>
</table>
</div>


Das sieht dann so aus wie im Screenshot. Mir gefällt es...

Gruß
Bismosa

[edit]
Kaum geschrieben...schon wieder geändert! Habe das DOIF noch angepasst, dass die Readings mit einem sleep vorweg ausgeführt werden. Dann werden auch Events generiert.
[/edit]
1x nanoCUL 433MHz (SlowRF Intertechno) für Fenstersensoren
1x nanoCUL 868Mhz für MAX (9x HT 1xWT)
1x ZigBee CUL
Weiteres: Squeezebox server, Kindle Display, ESP8266, Löterfahrung, ...

bismosa

Hallo!

Der obige Code ist irgendwie müll!
FHEM hängt sich auf meinem Raspberry für 30-45sek. vollständig auf sobald ein Fenster geöffnet wird. Siehe auch https://forum.fhem.de/index.php/topic,93998.0.html

Also habe ich das nochmal verändert. Ich erzeuge den HTML-Code nun vollständig im DOIF und fülle nur ein Reading. Im FTUI brauche ich dann nur noch ein Label:

defmod di_Fenster_Liste DOIF (["^Fenster_.*"] \
    or ([$SELF:Timer] eq 1 and [+00:01:00])\
)({\
my $Max=8;;\
    my %hash;;\
my %hashKaputt;;\
my %hashBatt;;\
    my @Devices=devspec2array("NAME=Fenster_.*:FILTER=STATE=Offen");; ##Offen|Kaputt\
my @DevicesKaputt=devspec2array("NAME=Fenster_.*:FILTER=STATE=Kaputt");; \
my @DevicesBatt=devspec2array("NAME=Fenster_.*:FILTER=battery=low");; \
    foreach my $Device (@Devices){\
        $hash{$Device}{"Age"}=ReadingsAge("$Device", "state", 0);;\
        $hash{$Device}{"Date"}=(split / /, ReadingsTimestamp("$Device", "state", 0))[0];;\
        $hash{$Device}{"Time"}=(split / /, ReadingsTimestamp("$Device", "state", 0))[1];;\
        $hash{$Device}{"TTSName"}=AttrVal("$Device", "TTSName", "unbekannt");;\
##Log 1, (split / /, ReadingsTimestamp("$Device", "state", 0))[1];;\
        ##my @words = split / /, ReadingsTimestamp("$Device", "state", 0);;\
        ##Log 1, Dumper(\@words);;\
    }\
foreach my $Device (@DevicesKaputt){\
$hashKaputt{$Device}{"Age"}=ReadingsAge("$Device", "state", 0);;\
        $hashKaputt{$Device}{"Date"}=(split / /, ReadingsTimestamp("$Device", "state", 0))[0];;\
        $hashKaputt{$Device}{"Time"}=(split / /, ReadingsTimestamp("$Device", "state", 0))[1];;\
        $hashKaputt{$Device}{"TTSName"}=AttrVal("$Device", "TTSName", "unbekannt");;\
}\
foreach my $Device (@DevicesBatt){\
$hashBatt{$Device}{"Age"}=ReadingsAge("$Device", "battery", 0);;\
        $hashBatt{$Device}{"Date"}=(split / /, ReadingsTimestamp("$Device", "battery", 0))[0];;\
        $hashBatt{$Device}{"Time"}=(split / /, ReadingsTimestamp("$Device", "battery", 0))[1];;\
        $hashBatt{$Device}{"TTSName"}=AttrVal("$Device", "TTSName", "unbekannt");;\
}\
    ##Log 1, Dumper(\%hash);;\
    \
    ##Sortieren\
my $htmlKurz='<div align="left"><table><tbody>';;\
my $html='<div align="left"><table><tbody>';;\
    my $i=0;;\
\
for (sort { $hash{$a}->{Age} <=>  $hash{$b}->{Age} } keys %hash){\
my $Age=$hash{$_}{"Age"};;\
my $Text=Sekunden2TextKurz($Age);;\
\
##Farbe beachten!\
##0 900 3600\
my $color="";;\
##Log 1, "Alter $Age";;\
if ($Age > 3600){\
$color="#FF0000";;\
} elsif ($Age > 900){\
$color="yellow";;\
} else { \
$color="green";;\
}\
##Log 1, "Color: $color";;\
##Kein Symbol:\
$html.="<tr><td></td>";;\
$html.='<td><div style="color:'.$color.'">'.$hash{$_}{"TTSName"}.'</div></td>';;\
$html.='<td><div style="color:'.$color.'">'.$Text.'</div></td>';;\
$html.="</tr>";;\
\
if ($i < $Max){\
##Log 1, "Anzahl $i $Max";;\
$htmlKurz.="<tr><td></td>";;\
$htmlKurz.='<td><div style="color:'.$color.'">'.$hash{$_}{"TTSName"}.'</div></td>';;\
$htmlKurz.='<td><div style="color:'.$color.'">'.$Text.'</div></td>';;\
$htmlKurz.="</tr>";;\
}\
$i=$i+1;;\
}\
fhem("sleep 1;; setreading $SELF Anzahl $i");;\
\
my $iKaputt=0;;\
for (sort { $hashKaputt{$a}->{Age} <=>  $hashKaputt{$b}->{Age} } keys %hashKaputt){\
my $Age=$hashKaputt{$_}{"Age"};;\
my $Text=Sekunden2TextKurz($Age);;\
\
my $color="";;\
if ($Age > 3600){\
$color="#FF0000";;\
} elsif ($Age > 900){\
$color="yellow";;\
} else { \
$color="green";;\
}\
\
##Symbol Kaputt:\
$html.="<tr><td> <div class=\"tiny compressed\" data-type=\"symbol\" data-icon=\"oa-message_attention\" data-on-color=\"#FF0000\" data-off-color=\"#FF0000\"></div></td>";;\
$html.='<td><div style="color:'.$color.'">'.$hashKaputt{$_}{"TTSName"}.'</div></td>';;\
##Abgelaufene Zeit:\
$html.='<td><div style="color:'.$color.'">'.$Text.'</div></td>';;\
$html.="</tr>";;\
\
if ($i < $Max){\
##Symbol Kaputt:\
$htmlKurz.="<tr><td> <div class=\"tiny compressed\" data-type=\"symbol\" data-icon=\"oa-message_attention\" data-on-color=\"#FF0000\" data-off-color=\"#FF0000\"></div></td>";;\
$htmlKurz.='<td><div style="color:'.$color.'">'.$hashKaputt{$_}{"TTSName"}.'</div></td>';;\
##Abgelaufene Zeit:\
$htmlKurz.='<td><div style="color:'.$color.'">'.$Text.'</div></td>';;\
$htmlKurz.="</tr>";;\
}\
\
$i=$i+1;;\
$iKaputt=$iKaputt+1;;\
}\
fhem("sleep 1;; setreading $SELF AnzahlKaputt $iKaputt");;\
\
my $iBatt=0;;\
for (sort { $hashBatt{$a}->{Age} <=>  $hashBatt{$b}->{Age} } keys %hashBatt){\
my $Age=$hashBatt{$_}{"Age"};;\
my $Text=Sekunden2TextKurz($Age);;\
\
my $color="";;\
if ($Age > 3600){\
$color="#FF0000";;\
} elsif ($Age > 900){\
$color="yellow";;\
} else { \
$color="green";;\
}\
\
##Symbol Kaputt:\
$html.="<tr><td> <div class=\"tiny compressed\" data-type=\"symbol\" data-icon=\"oa-measure_battery_0  fa-rotate-90\" data-on-color=\"#FF0000\" data-off-color=\"#FF0000\"></div></td>";;\
$html.='<td><div style="color:'.$color.'">'.$hashBatt{$_}{"TTSName"}.'</div></td>';;\
##Abgelaufene Zeit:\
$html.='<td><div style="color:'.$color.'">'.$Text.'</div></td>';;\
$html.="</tr>";;\
\
if ($i < $Max){\
##Symbol Kaputt:\
$htmlKurz.="<tr><td> <div class=\"tiny compressed\" data-type=\"symbol\" data-icon=\"oa-measure_battery_0  fa-rotate-90\" data-on-color=\"#FF0000\" data-off-color=\"#FF0000\"></div></td>";;\
$htmlKurz.='<td><div style="color:'.$color.'">'.$hashBatt{$_}{"TTSName"}.'</div></td>';;\
##Abgelaufene Zeit:\
$htmlKurz.='<td><div style="color:'.$color.'">'.$Text.'</div></td>';;\
$htmlKurz.="</tr>";;\
}\
\
$i=$i+1;;\
$iBatt=$iBatt+1;;\
}\
fhem("sleep 1;; setreading $SELF AnzahlBatt $iBatt");;\
\
$html.="</tbody></table></div>";;\
$htmlKurz.="</tbody></table></div>";;\
fhem("setreading $SELF HTML $html");;\
fhem("setreading $SELF HTMLKURZ $htmlKurz");;\
    \
    ##Bei Bedarf Timer setzen\
if ($i eq 0){\
        fhem("setreading $SELF Timer 0");;\
    }else{\
        fhem("setreading $SELF Timer 1");;\
    }\
})
attr di_Fenster_Liste do always
attr di_Fenster_Liste room IT
attr di_Fenster_Liste verbose 0


Ich denke ein ähnlicher Weg für die Störmeldeliste wäre gar nicht so falsch...oder?

Gruß
Bismosa
1x nanoCUL 433MHz (SlowRF Intertechno) für Fenstersensoren
1x nanoCUL 868Mhz für MAX (9x HT 1xWT)
1x ZigBee CUL
Weiteres: Squeezebox server, Kindle Display, ESP8266, Löterfahrung, ...

Thorsten Pferdekaemper

Hi,
ich habe übrigens inzwischen das readingsgroup-Widget in einen View gepackt. Siehe auch hier:
https://forum.fhem.de/index.php/topic,95477.0.html
Gruß,
   Thorsten
FUIP