Ich versuche folgende Funktion von Martin Schmid ans Laufen zu bekommen.
sub
WindowsOpenString() {
my $OpenString = "Bitte folgende Fenster schließen: ";
my $OpenCount = 0;
if (ReadingsVal("GZ.Fenster","state","") eq "open") {
$OpenString = $OpenString."Gästezimmer";
$OpenCount = $OpenCount + 1;
}
if (ReadingsVal("WZ.Fenster.li","state","") eq "open") {
if ($OpenCount > 0) {
$OpenString = $OpenString.", ";
}
$OpenString = $OpenString."Wohnzimmer links";
$OpenCount = $OpenCount + 1;
}
if (ReadingsVal("WZ.Fenster.re","state","") eq "open") {
if ($OpenCount > 0) {
$OpenString = $OpenString.", ";
}
$OpenString = $OpenString."Wohnzimmer rechts";
$OpenCount = $OpenCount + 1;
}
if (ReadingsVal("SZ.Fenster.li","state","") eq "open") {
if ($OpenCount > 0) {
$OpenString = $OpenString.", ";
}
$OpenString = $OpenString."Schlafzimmer links";
$OpenCount = $OpenCount + 1;
}
if (ReadingsVal("SZ.Fenster.re","state","") eq "open") {
if ($OpenCount > 0) {
$OpenString = $OpenString.", ";
}
$OpenString = $OpenString."Schlafzimmer rechts";
$OpenCount = $OpenCount + 1;
}
if (ReadingsVal("Jon.Fenster","state","") eq "open") {
if ($OpenCount > 0) {
$OpenString = $OpenString.", ";
}
$OpenString = $OpenString."Jonathan";
$OpenCount = $OpenCount + 1;
}
if (ReadingsVal("EZ.Fenster","state","") eq "open") {
if ($OpenCount > 0) {
$OpenString = $OpenString.", ";
}
$OpenString = $OpenString."Esszimmer";
$OpenCount = $OpenCount + 1;
}
if (ReadingsVal("KU.Fenster","state","") eq "open") {
if ($OpenCount > 0) {
$OpenString = $OpenString.", ";
}
$OpenString = $OpenString."Küche";
$OpenCount = $OpenCount + 1;
}
else {
$OpenString = "Guten Tag!";
}
fhem ("set Sonos_Kueche Speak 20 de $OpenString");
}
1;
Leider lande ich immer im else Fall. Kann mir jemand sagen wieso es nicht klappt?
Vielen Dank
Viel kürzer und effektiver:
sub WindowsOpenString()
{
my $text;
my @devs = devspec2array("GZ.Fenster,WZ.Fenster.li,WZ.Fenster.re,SZ.Fenster.li,SZ.Fenster.re,Jon.Fenster,EZ.Fenster,KU.Fenster:FILTER=state=open");
if (@devs > 0)
{
my @aliases;
foreach (@devs)
{
push @aliases,AttrVal($_,"alias",$_);
}
$text = "Folgende Fenster sind offen: ".join(", ",@aliases);
}
else
{
$text = "Guten Tag";
}
fhem "set Sonos_Kueche Speak 20 de $text";
}
Es empfiehlt sich dem Attribut alias die sprechenden Namen zu geben.
Gruß
Dan
Oder als Sub mit Rückgabewert
sub statusFensterOffen() {
my @monitored=devspec2array("(FensterKontakt.*):FILTER=STATE!=closed");
my $cnt_devs=@monitored;
my $i = 0;
my $msgtext = "";
foreach(@monitored) {
$msgtext .= AttrVal($_,"alias",$_);
if ($i < $cnt_devs - 2) {
$msgtext .= ", ";
}
if ($i == $cnt_devs - 2) {
$msgtext .= " und ";
}
$i++;
}
return $msgtext if ($cnt_devs > 0);
}
Und auch hier gilt. Sprechende Namen für die Fensterkontakte wählen
Geht auch wunderbar mit dem monitoring Modul (http://commandref.fhem.de/commandref_DE.html#monitoringexamples)
Zitat von: igami am 11 Mai 2017, 21:41:42
Geht auch wunderbar mit dem monitoring Modul (http://commandref.fhem.de/commandref_DE.html#monitoringexamples)
:o Was es (inzwischen) nicht alles gibt.
Erstmal vielen Dank für die schnellen und zahlreichen Antworten.
Ich habe mich zunächst für die Lösung von DeeSPe entschieden. Jetzt sagt er mir immer alle Fenster an. Egal ob offen oder geschlossen. In der Küche funktioniert es. In der Küche habe ich einen Drehgriffkontakt von Homematic. An den anderen Fenstern habe ich Homematic Magnet Kontakte. Hier mal ein Listing des Gästezimmer Kontaktes. Was mache ich falsch?
Internals:
CUL_0_MSGCNT 8
CUL_0_RAWMSG A0CFBA24130E81B001255017E00::-83:CUL_0
CUL_0_RSSI -83
CUL_0_TIME 2017-05-16 10:40:21
DEF 30E81B
IODev CUL_0
LASTInputDev CUL_0
MSGCNT 8
NAME GZ.Fenster
NOTIFYDEV global
NR 172
NTFY_ORDER 50-GZ.Fenster
STATE closed
TYPE CUL_HM
lastMsg No:FB - t:41 s:30E81B d:001255 017E00
peerList GZ.Heizung_WindowRec,
protLastRcv 2017-05-16 10:40:21
protSnd 4 last_at:2017-05-16 10:40:21
protState CMDs_done
rssi_at_CUL_0 avg:-81.93 lst:-83 cnt:8 min:-83.5 max:-80.5
Readings:
2017-05-16 10:31:39 Activity alive
2016-11-21 21:07:17 CommandAccepted yes
2016-11-21 21:07:16 D-firmware 2.4
2016-11-21 21:07:16 D-serialNr LEQ1086568
2016-11-21 21:07:18 PairedTo 0x001255
2016-11-21 21:07:19 R-GZ.Heizung_WindowRec-expectAES off
2016-11-21 21:07:19 R-GZ.Heizung_WindowRec-peerNeedsBurst on
2016-11-21 21:07:18 R-cyclicInfoMsg off
2016-11-21 21:07:18 R-eventDlyTime 0 s
2016-11-21 21:07:18 R-pairCentral 0x001255
2016-11-21 21:07:18 R-sabotageMsg on
2016-11-21 21:07:18 R-sign off
2016-11-21 21:07:18 RegL_00. 02:01 09:00 0A:00 0B:12 0C:55 10:01 14:06 00:00
2016-11-21 21:07:18 RegL_01. 08:00 20:60 21:00 22:64 30:06 00:00
2016-11-21 21:07:18 RegL_04.GZ.Heizung_WindowRec 01:01 00:00
2016-11-21 21:08:20 alive yes
2017-05-16 10:40:21 battery ok
2017-05-16 10:40:21 contact closed (to VCCU)
2017-05-16 10:31:39 peerList GZ.Heizung_WindowRec,
2016-11-21 21:08:20 recentStateType info
2016-11-21 21:08:20 sabotageError off
2017-05-16 10:40:21 state closed
2017-05-16 10:40:21 trigger_cnt 126
Helper:
HM_CMDNR 251
mId 002F
rxType 4
supp_Pair_Rep 0
Ack:
Expert:
def 1
det 0
raw 1
tpl 0
Io:
newChn +30E81B,00,00,00
nextSend 1494924021.64811
rxt 0
vccu VCCU
p:
30E81B
00
00
00
prefIO:
CUL_0
Mrssi:
mNo FB
Io:
CUL_0 -81
Prt:
bErr 0
sProc 0
Rspwait:
Q:
qReqConf
qReqStat
Role:
chn 1
dev 1
Rpt:
IO CUL_0
flg A
ts 1494924021.55184
ack:
HASH(0x39f8688)
FB800200125530E81B0101C800
Rssi:
At_cul_0:
avg -81.9375
cnt 8
lst -83
max -80.5
min -83.5
Attributes:
IODev CUL_0
IOgrp VCCU:CUL_0
actCycle 028:00
actStatus alive
alias Fenster Gästezimmer
autoReadReg 4_reqStatus
expert 2_raw
firmware 2.4
model HM-SEC-SC
peerIDs 00000000,440BD203,
room CUL_HM,Gästezimmer
serialNr LEQ1086568
stFenster struct.fenster
subType threeStateSensor
userattr stFenster stFenster_map structexclude
Sind es alles die selben Kontaktsensoren?
Wenn ja, kannst Du als Devspec auch:
my @devs = devspec2array("model=HM-SEC-SC:FILTER=state!=closed");
benutzen.
Diese Sensoren sollten möglichst auch alle über event-on-change-reading verfügen um nicht mehrfach auszulösen.
Einfach zu setzen mit:
attr model=HM-SEC-SC event-on-change-reading .*
Gruß
Dan
EDIT: Gerade nochmal gelesen dass es unterschiedliche Sensoren sind. Macht sich aber auch bei 2 verschiedenen Modellen besser über "model=HM-SEC-SC|HM-SEC-XXXXX" zu gehen.
Danke. Das Attribut werde ich schon mal setzen. Ich benutze die Kontakte auch noch in mehreren Schränken. Daher vermute ich deine Lösung wird bei mir nicht funktionieren. Ich möchte keine Ansage von offenen Schranktüren. ;D Dein ursprünglicher code müsste doch gehen. Die readings zeigen ja closed. Habe ich beim Anlegen der Magnetkontakte einen Fehler gemacht?
Eigentlich kann man da ja kaum etwas verkehrt machen beim Anlernen.
Solange im Reading state open/closed kommt sollte das so funktionieren wie es ist.
Gruß
Dan
OK. Danke.
Das reading ist ja closed wie im Listing zu sehen. Dennoch wird mir das Fenster als geöffnet angesagt. Hast du noch eine Idee was ich noch prüfen kann? An der structure,in der ich alle Fenster zusammengefasst habe, kann es nicht liegen?
Zitat von: willib am 16 Mai 2017, 11:44:10
OK. Danke.
Das reading ist ja closed wie im Listing zu sehen. Dennoch wird mir das Fenster als geöffnet angesagt. Hast du noch eine Idee was ich noch prüfen kann? An der structure,in der ich alle Fenster zusammengefasst habe, kann es nicht liegen?
Solange Du nicht das structure abfragst sollte es daran nicht liegen.
Devspec "GZ.Fenster,WZ.Fenster.li,WZ.Fenster.re,SZ.Fenster.li,SZ.Fenster.re,Jon.Fenster,EZ.Fenster,KU.Fenster:FILTER=state!=closed" sollte nur Kontakte liefern die nicht closed sind, also z.B. open oder tilted.
Das kannst Du auch super in der FHEM Eingabezeile testen:
list GZ.Fenster,WZ.Fenster.li,WZ.Fenster.re,SZ.Fenster.li,SZ.Fenster.re,Jon.Fenster,EZ.Fenster,KU.Fenster:FILTER=state!=closed
Gruß
Dan
devspec2array("(*.Fenster.*)
So sollte es auch gehen solange das Wort Fenster vor kommt. und zwar Groß geschrieben.
Alle Fenster sind geschlossen.
Der Test liefert folgende Liste:
GZ.Fenster
WZ.Fenster.li
WZ.Fenster.re
SZ.Fenster.li
SZ.Fenster.re
Jon.Fenster
EZ.Fenster
Und das obwohl state und STATE closed ist. Ich kapiere es nicht. :-\
Hier noch ein Listing der Küche. Hier funktioniert es:
Internals:
CUL_0_MSGCNT 2
CUL_0_RAWMSG A0CCFA64136A2B500125501CC00::-72:CUL_0
CUL_0_RSSI -72
CUL_0_TIME 2017-05-16 10:36:45
DEF 36A2B5
IODev CUL_0
LASTInputDev CUL_0
MSGCNT 2
NAME KU.Fenster
NOTIFYDEV global
NR 257
NTFY_ORDER 50-KU.Fenster
STATE closed
TYPE CUL_HM
lastMsg No:CF - t:41 s:36A2B5 d:001255 01CC00
protLastRcv 2017-05-16 10:36:45
protSnd 2 last_at:2017-05-16 10:36:45
protState CMDs_done
rssi_at_CUL_0 lst:-72 avg:-73.75 max:-72 min:-75.5 cnt:2
Readings:
2017-05-16 10:31:40 Activity alive
2017-04-29 15:10:01 CommandAccepted yes
2017-04-29 15:10:00 D-firmware 2.4
2017-04-29 15:10:00 D-serialNr MEQ0220618
2017-04-29 15:10:01 PairedTo 0x001255
2017-04-29 15:08:25 R-cyclicInfoMsg off
2017-04-29 15:10:01 R-eventDlyTime 1 s
2017-04-29 15:08:25 R-pairCentral 0x001255
2017-04-29 15:09:19 R-sign off
2017-04-29 15:43:41 alive yes
2017-05-16 10:36:45 battery ok
2017-05-16 10:36:45 contact closed (to VCCU)
2017-04-29 15:43:41 cover closed
2017-04-29 15:43:41 recentStateType info
2017-05-16 10:36:45 state closed
2017-05-16 10:36:45 trigger_cnt 204
Helper:
HM_CMDNR 207
mId 0030
rxType 4
supp_Pair_Rep 0
Expert:
def 1
det 0
raw 0
tpl 0
Io:
newChn +36A2B5,00,00,00
nextSend 1494923805.4561
rxt 0
vccu VCCU
p:
36A2B5
00
00
00
prefIO:
CUL_0
Mrssi:
mNo CF
Io:
CUL_0 -70
Prt:
bErr 0
sProc 0
Rspwait:
Q:
qReqConf
qReqStat
Role:
chn 1
dev 1
Rpt:
IO CUL_0
flg A
ts 1494923805.35994
ack:
HASH(0x3be4aa0)
CF800200125536A2B500
Rssi:
At_cul_0:
avg -73.75
cnt 2
lst -72
max -72
min -75.5
Attributes:
IODev CUL_0
IOgrp VCCU:CUL_0
actCycle 028:00
actStatus alive
alias Fenster Küche
autoReadReg 4_reqStatus
expert undefined
firmware 2.4
model HM-SEC-RHS
peerIDs 00000000,
room CUL_HM,Küche
serialNr MEQ0220618
stFenster struct.fenster
stFenster_map tilted:open open:open
subType threeStateSensor
userattr stFenster stFenster_map structexclude
Könnte an Deinen Punkten im Namen liegen. Ich schaue mir das heute Abend mal auf meiner Testumgebung an.
Zitat von: CoolTux am 16 Mai 2017, 12:20:09
devspec2array("(*.Fenster.*)
So sollte es auch gehen solange das Wort Fenster vor kommt. und zwar Groß geschrieben.
Müsste es nicht eher so aussehen:
devspec2array('.*Fenster.*')
Dann muss man das zurückgelieferte Array aber auch noch durchlaufen und die geöffneten Fenster rauspicken.
Ja Benni hast Recht. Hatte mich auf dem Handy vertippt.
Habe ja oben den Durchlauf durchs Array mit aufgezeigt.
oder neuerdings als Einzeiler:
DOIF (["Fenster:closed"]) (set Sonos_Kueche Speak 20 Folgende Fenster Schließen [@:as( )"Fenster":state:"open","keine"])
übersetzt heißt das:
wenn ein Device mit "Fenster" im Namen geschlossen wird, werden alle offenen Fenster mit Aliasnamen angesagt.
Genaueres dazu siehe hier: https://fhem.de/commandref_DE.html#DOIF_aggregation
Und? Wenn's funktioniert bitte auf [Gelöst] setzen (Subject des ersten Posts ändern)
Ich habe das devspec2array angepasst. Jetzt werden mir auch die Log files der Fenster Sensoren mit angesagt. Alle Varianten liefern im Prinzip das gleiche Ergebnis. Es werden immer alle Fenster bis auf die Küche angesagt. Bei der Küche funktioniert es. Irgendwie wird sate nicht richtig erfasst. Ich versuche mal die Sensoren umzubenennen um den Punkt los zu werden.
Oder gibt es noch Ideen zur Fehlersuche?
Zeige doch mal bitte was Du jetzt an Code hast. Und zwar bitte alles.
Ich habe mit dem code nicht weiter experimentiert nachdem ich festgestellt habe dass bereits
list GZ.Fenster,WZ.Fenster.li,WZ.Fenster.re,SZ.Fenster.li,SZ.Fenster.re,Jon.Fenster,EZ.Fenster,KU.Fenster:FILTER=state!=closed
nicht die korrekten Ergebnisse liefert.
Es werden dann alle Fenster bis auf die KU.Fenster angezeigt obwohl State und state closed ist.
list (GZ.Fenster,WZ.Fenster.li,WZ.Fenster.re,SZ.Fenster.li,SZ.Fenster.re,Jon.Fenster,EZ.Fenster,KU.Fenster):FILTER=state!=closed
Danke.
Die Klammern scheinen nicht korrekt zu sein:
No device named (GZ.Fenster,WZ.Fenster.li,WZ.Fenster.re,SZ.Fenster.li,SZ.Fenster.re,Jon.Fenster,EZ.Fenster,KU.Fenster):FILTER=state!=closed found
Sorry mein Fehler. Statt , bitte | nehmen
list (GZ.Fenster|WZ.Fenster.li|WZ.Fenster.re|SZ.Fenster.li|SZ.Fenster.re|Jon.Fenster|EZ.Fenster|KU.Fenster):FILTER=state!=closed
Aber wieso machst Du es nicht so wie gesagt wurde
list (.*Fenster.*|.*Fenster):FILTER=state!=closed
So und wenn Du jetzt noch LogFiles mit drin hast dann filterst die auch raus
list (.*Fenster.*|.*Fenster):FILTER=state!=closed:FILTER=TYPE!=LogFile
Bitte selber noch mal schauen ob der TYPE wirklich LogFile von den Logfiles heisst
Danke Danke
FileLog ist der TYPE.
Das ist der korrekte Code:
sub WindowsOpenString()
{
my $text;
my @devs = devspec2array("(.*Fenster.*|.*Fenster):FILTER=state!=closed:FILTER=TYPE!=FileLog");
if (@devs > 0)
{
my @aliases;
foreach (@devs)
{
push @aliases,AttrVal($_,"alias",$_);
}
$text = "Folgende Fenster sind noch geöffnet: ".join(", ",@aliases);
}
else
{
$text = "Guten Tag";
}
fhem "set Sonos_Kueche Speak 20 de $text";
}