[gelöst] offene Fenster zählen und auflisten

Begonnen von Christian80, 13 November 2020, 16:12:07

Vorheriges Thema - Nächstes Thema

Christian80

Hallo zusammen,

ich habe hier im Forum ein DOIF gefunden, welches offene Fenster zählt und habe es für mein Setup angepasst.


defmod d_FK_Anzahl DOIF ([#"Fensterkontakt_.*":state:"open"] > 0)\
(\
  set $SELF openWindowsCount [#"Fensterkontakt_.*":state:"open"],\
  set $SELF openWindowsState open\
)\
DOELSE\
(\
  set $SELF openWindowsCount 0,\
  set $SELF openWindowsState closed\
)
attr d_FK_Anzahl alias d_FK_Anzahl
attr d_FK_Anzahl do always
attr d_FK_Anzahl group Fensterkontakte
attr d_FK_Anzahl readingList openWindowsCount  openWindowsState
attr d_FK_Anzahl room Logik
attr d_FK_Anzahl stateFormat openWindowsState (openWindowsCount)

setstate d_FK_Anzahl open (1)
setstate d_FK_Anzahl 2020-11-13 16:02:02 Device Fensterkontakt_Wohnen1
setstate d_FK_Anzahl 2020-11-13 16:02:02 cmd 1
setstate d_FK_Anzahl 2020-11-13 16:02:02 cmd_event Fensterkontakt_Wohnen1
setstate d_FK_Anzahl 2020-11-13 16:02:02 cmd_nr 1
setstate d_FK_Anzahl 2020-09-05 11:12:44 mode enabled
setstate d_FK_Anzahl 2020-11-13 16:02:02 openWindowsCount 1
setstate d_FK_Anzahl 2020-11-13 16:02:02 openWindowsState open
setstate d_FK_Anzahl 2020-11-13 16:02:02 state cmd_1


Das funktioniert auch soweit.

Gibt es eine Möglichkeit die Namen aller offenen Fenster aufzulisten und in einem Reading zu schreiben?

Danke und schöne Grüße
Christian

Damian

Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF

xenos1984

Macht das nicht genau das Beispiel aus der CommandRef?

http://fhem.de/commandref_DE.html#DOIF_aggregation

define di_Fenster DOIF (["^Window:open"])
(push "Fenster $DEVICE wurde geöffnet. Es sind folgende Fenster offen: [@"^Window":state:"open"]")
DOELSEIF ([#"^Window:closed":state:"open"] == 0)
(push "alle Fenster geschlossen")

attr di_Fenster do always
attr di_Fenster cmdState [$SELF:Device] zuletzt geöffnet|alle geschlossen



Christian80

Ich habe mir nun folgendes DOIF gebaut:


Internals:
   DEF        ([#"Fensterkontakt_.*":state:"open"] > 0)
(
  set $SELF openWindowsCount [#"Fensterkontakt_.*":state:"open"],
  set $SELF openWindowsState open
)
DOELSE
(
  set $SELF openWindowsCount 0,
  set $SELF openWindowsState closed
)
   DOIFDEV    ^global$|Fensterkontakt_.*
   FUUID      5f53445e-f23f-dffb-48d3-87603c
   MODEL      FHEM
   NAME       d_FK_Anzahl
   NR         273
   NTFY_ORDER 50-d_FK_Anzahl
   STATE      open (2)
   TYPE       DOIF
   VERSION    23235 2020-11-25 22:42:28
   CHANGED:
     windows: Fensterkontakt_Essen2 Fensterkontakt_Wohnen3
   CHANGEDWITHSTATE:
     windows: Fensterkontakt_Essen2 Fensterkontakt_Wohnen3
   DOIF_Readings:
     windows    ::AggregateDoIf($hash,'@as( )','Fensterkontakt_.*','state','"open"','"keine"')
   READINGS:
     2020-12-20 13:04:52   Device          Fensterkontakt_Essen2
     2020-12-20 13:04:52   cmd             1
     2020-12-20 13:04:52   cmd_event       Fensterkontakt_Essen2
     2020-12-20 13:04:52   cmd_nr          1
     2020-09-05 11:12:44   mode            enabled
     2020-12-20 13:04:52   openWindowsCount 2
     2020-12-20 13:04:52   openWindowsState open
     2020-12-20 13:04:52   room_FK         Fensterkontakt_Essen2 Fensterkontakt_Wohnen3
     2020-12-20 13:04:52   state           cmd_1
     2020-12-20 13:04:52   windows         Fensterkontakt_Essen2 Fensterkontakt_Wohnen3
   Regex:
     DOIF_Readings:
       :
         windows:
           "Fensterkontakt_.*" Fensterkontakt_.*
       d_FK_Anzahl:
     accu:
     cond:
       :
         0:
           "Fensterkontakt_.*" Fensterkontakt_.*
   attr:
     cmdState:
     wait:
     waitdel:
   condition:
     0          ::AggregateDoIf($hash,'#','Fensterkontakt_.*','state','"open"') > 0
   do:
     0:
       0             set d_FK_Anzahl openWindowsCount [#"Fensterkontakt_.*":state:"open"],   set d_FK_Anzahl openWindowsState open
     1:
       0             set d_FK_Anzahl openWindowsCount 0,   set d_FK_Anzahl openWindowsState closed
   helper:
     DEVFILTER  ^global$|Fensterkontakt_.*
     NOTIFYDEV  global|.*Fensterkontakt_.*.*
     event      open
     globalinit 1
     last_timer 0
     sleeptimer -1
     timerdev   Fensterkontakt_Essen2
     timerevent open
     triggerDev Fensterkontakt_Essen2
     DOIF_eventa:
       cmd_nr: 1
       cmd: 1
       cmd_event: Fensterkontakt_Essen2
       cmd_1
     DOIF_eventas:
       cmd_nr: 1
       cmd: 1
       cmd_event: Fensterkontakt_Essen2
       state: cmd_1
     timerevents:
       open
     timereventsState:
       state: open
     triggerEvents:
       open
     triggerEventsState:
       state: open
   internals:
   perlblock:
   readings:
   trigger:
   uiState:
   uiTable:
Attributes:
   DOIF_Readings windows:[@as( )"Fensterkontakt_.*":state:"open","keine"]
   alias      d_FK_Anzahl
   do         always
   group      Fensterkontakte
   readingList openWindowsCount  openWindowsState
   room       Logik
   stateFormat openWindowsState (openWindowsCount)
   userReadings room_FK {(ReadingsVal($name,"windows",""));;}


Zählen und Auflisten funktioniert nun.

Ich habe im Reading windows z.B folgenden Wert stehen: Fensterkontakt_Essen2 Fensterkontakt_Wohnen3

Kann ich das Reading mittels userReadings so bearbeiten, dass ich "Fensterkontakt_" entfernen kann?

Danke und schönen 4. Advent

Grüße
Christian

Damian

Teilausdrücke kann man nicht auslagern, aber du kannst ein DOIF_Reading anlegen, auf welches zu zugreifen kannst:

attr DOIF_Readings Fensteranzahl: [#"Fensterkontakt_.*":state:"open"]

Auf Fensteranzahl kannst du dann in DOIF überall zugreifen über:

[$SELF:Fensteranzahl]
Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF

Christian80

Die Fensteranzahl habe ich bereits.

ich bräuchte ein Reading, welches anstelle von "Fensterkontakt_Essen2 Fensterkontakt_Wohnen3"  den Inhalt "Essen2 Wohnen3" besitzt.

Grüße
Christian

Sany

das kannst Du folgendermaßen lösen:

[@as(<br>)"Fensterkontakt_.*":state:"open"]

statt # nimmst Du @as(<br>)
@: Liste der Namen
a: verwende den alias (wenn gesetzt, hier kannst Du deine Essen2, Wohnen3 nutzen, wenn der alias im Device entsprechend gesetzt ist
s(<br>): schreibt eine Liste, also alle Einträge werden untereinander geschrieben. Kannst Du weglassen, dann stehts alles in einer Zeile.

und wie Damian es schon geschrieben hat würde ich hier auch DOIF_Readings verwenden (so habe ich das bei mir auch gelöst).


Viel Erfolg!
fhem auf nipogi Mini PC als LXC auf Proxmox, weitere LXC mit ZigBee2MQTT, MariaDB und Grafana. Homematic, FS20, mySensors, MQTT2, Tasmota, Shelly, Z-Wave  ....

Christian80

Ich danke euch für eure Tipps.

Der Ansatz mit dem "Alias" funktioniert für mich perfekt.

Danke und schöne Weihnachten.
Christian

teichtaucher

#8
Ich muss den Threat mal kapern, weil ich ein ähnliches Problem habe. Ich habe ein kleines E-Ink Display and einem ESP8266 mit ESPEasy am laufen. Über den http Command
http://192.168.178.46/control?cmd=epd,txl,1,Zeile1,2,Zeile2kann ich das Display ansteuern. Ich kann dabei bis zu 24 Zeilen ansteuern. Ich hätte es gern so, dass ab einem Fenster offen folgender Text auf dem Display angezeigt wird:

Fenster offen:
Bad

Also jedes Fenster in eine Zeile, in Zeile 1 statisch "Fenster offen:"
Ich habe mir überlegt dass es mit einer Schleife gut gehen würde. Also sowas wie

my $string = "http://192.168.178.46/control?cmd=epd,txl,"
for each $win in @"^Window":state:"open" $string + "," + $index +"," + $win
Hat einer von euch eine Idee wie man das schön in Code gießen kann?

So sieht mein Doif zurzeit aus:

(["^*.fk.*:open"]) {GetHttpFile("192.168.178.46","/control?cmd=epd,txl,1,Test,2,offen")}
DOELSE
{GetHttpFile("192.168.178.46","/control?cmd=epd,clear")}

Bin mir auch nicht sicher ob ich GetHttpFile verwenden soll, dass es ja blocking ist. Ach ja, der DoElse Zweig hat gar nicht funktioniert.

teichtaucher

#9
Ich muss mir mal selbst antworten. Ich hatte bei dem Thema den Perl-Modus in der Commandref nicht gesehen/gefunden. Steht aber alles hier weiter unten in bei den Beispielen im Perl-Modus

Perl-Modus:
define di_Fenster DOIF {if (["^Window:open"]) {foreach (AggrDoIf('@','^windows','state','"open"')) {Log3 "di_Fenster",3,"Das Fenster $_ ist noch offen"}}}

So sieht jetzt mein Doif aus:

define di_FensterDisplay DOIF (["^*.fk.*:open"])
{my $str = "http://192.168.178.46/control?cmd=epd,txl,1,Fenster,2,offen:";; my $idx=2;; foreach (AggrDoIf('@','^*.fk.*','state','"open"')) {$idx++;;$str=$str.",".$idx.',%22'.uri_escape(AttrVal($_,"alias",$_)).'%22'}system("wget -q $str &");;Log(3, $str)}
DOELSEIF (["^*.fk.*:closed"] and [#"^*.fk.*":state:"open"]>0)
{my $str = "http://192.168.178.46/control?cmd=epd,txl,1,Fenster,2,offen:";; my $idx=2;; foreach (AggrDoIf('@','^*.fk.*','state','"open"')) {$idx++;;$str=$str.",".$idx.',%22'.uri_escape(AttrVal($_,"alias",$_)).'%22'}system("wget -q $str &");;Log(3, $str)}
DOELSEIF (["^*.fk.*:closed"] and [#"^*.fk.*":state:"open"]==0)
{system("wget -q http://192.168.178.46/control?cmd=epd,clear &")}
DOELSE
{system("wget -q http://192.168.178.46/control?cmd=epd,clear &")}

Wenn ein Fenster geöffnet wurde, zeige Info auf dem Display an. Dabei wird der Alias jedes Fensters in einer separaten Zeile angezeigt.
Wenn ein Fenster geschlossen wurde aber noch wenigstens eins offen, update Display komplett
Wenn kein Fenster mehr offen ist, lösche Displayinhalt

Bei Displayupdate wird eine URL beim ESPEasy aufgerufen (war die einfachste Variante). Besser hätte ich eigentlich gefunden wenn ESPEasy zyklisch jede Minute aufwacht und sich die Infos von FHEM holt. Pull von ESPEasy von FHEM geht aber nicht.

Ach ja, habe ein Waveshare 2.9" Display an einem Wemos D1 laufen. Leider unterstützt ESPEasy das 2.9 Waveshare nativ ist. Ich habe aber den Treiber angepasst, so dass es jetzt läuft. Für wen es interessiert kann ich gern das Binary für den Wemos D1 hochladen.

Damian

#10
Nur ein kleiner Tipp am Rande:

Beim DOIF wird nicht $ am Ende der Regex-Angabe gemacht, daher ist .* am Ende der Device-Regex nicht erforderlich.

statt

["^*.fk.*:open"]
kann man auch angeben:

["^*.fk:open"]

und ^* macht irgendwie keinen Sinn, bedeutet , beliebige Wiederholung des Anfangs ???
Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF

teichtaucher

Danke für den Tipp. Du hast natürlich recht, ich war irgendwie beim "*" für any character, habe es getestet und es hat funktioniert. Bei mir haben alle Fensterkontakte ein ".fk." im Namen. Richtig wäre daher

[".+\.fk\..+:open"]

oder?

Damian

#12
Zitat von: teichtaucher am 16 Mai 2024, 19:26:47Danke für den Tipp. Du hast natürlich recht, ich war irgendwie beim "*" für any character, habe es getestet und es hat funktioniert. Bei mir haben alle Fensterkontakte ein ".fk." im Namen. Richtig wäre daher

[".+\.fk\..+:open"]

oder?

Beim DOIF würde auch schon reichen:

["\.fk\.:open"]
da kein ^ vorangestellt wird und auch kein $ angehängt wird, wie beim notify.

Der Doppelpunkt unterteilt die Regex vom Device und Regex vom restlichen Event
Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF

teichtaucher

Danke, hat funktioniert. Kann ich aus

[#"^*.fk.*":state:"open"]>0

auch das hier machen?

[#"\.fk\.:open"]>0

Zudem habe ich noch was komisches beobachtet: Teilweise wird mein Display auch aktualisiert obwohl gar kein Fenster mehr geöffnet wurde. In den Readings unter cmd_event sehe ich dann Fenster die schon offen sind. Warum reagiert das DOIF dann immer noch darauf? Ich hätte erwaret dass es nur auslöst wenn ein Fenster geöffnet wurde und nicht wenn es schon offen ist. Ich habe kein attr do always gesetzt.

Damian

Zitat von: teichtaucher am 17 Mai 2024, 08:51:04Danke, hat funktioniert. Kann ich aus

[#"^*.fk.*":state:"open"]>0

auch das hier machen?

ja, die Regex-Angaben werden im DOIF immer gleich behandelt.

[#"\.fk\.:open"]>0

ZitatZudem habe ich noch was komisches beobachtet: Teilweise wird mein Display auch aktualisiert obwohl gar kein Fenster mehr geöffnet wurde. In den Readings unter cmd_event sehe ich dann Fenster die schon offen sind. Warum reagiert das DOIF dann immer noch darauf? Ich hätte erwaret dass es nur auslöst wenn ein Fenster geöffnet wurde und nicht wenn es schon offen ist. Ich habe kein attr do always gesetzt.

Bei den Readings mit "e_" im Namen sieht man welches Event zur Ausführung geführt hat. Eigentlich sollte nur ein öffnendes Fenster zur Ausführung führen.
Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF