IF...ELSIF..ELSE und FOREACH zusammen???

Begonnen von Blackmore, 08 Juli 2015, 21:26:37

Vorheriges Thema - Nächstes Thema

Blackmore

Hi,

ich bin gerade dabei, mir eine WhatsApp Notify zu schreiben, bei der ich wie damals bei den Mailboxen per Befehl irgendwas senden lassen kann...


define WA_Wetter notify 491522xxxxx:message.* {\
if ($EVTPART1 eq "TempGraph") {\
   fhem ("set WhatsApp image $NAME /opt/fhem/log/wetter.jpg")\
} elsif ($EVTPART1 eq "Temp") {\
   fhem ("set WhatsApp send $NAME aktuelle Temperaturen\r\rBalkon1: "\
. ReadingsVal('LaCrosse_23', 'temperature', 0). "°C - ".  ReadingsVal('LaCrosse_23', 'humidity', 0). "%rel.\n\rBalkon2: "\
. ReadingsVal('HMS100TF_e657', 'temperature', 0). "°C - ".  ReadingsVal('HMS100TF_e657', 'humidity', 0).  "%rel.\n\rBüro: "\
. ReadingsVal('HMS100TF_5f86', 'temperature', 0). "°C - ". ReadingsVal('HMS100TF_5f86', 'humidity', 0)."%rel.")\
} elsif ($EVTPART1 eq "Nummer") {\
   fhem ("set WhatsApp send $NAME Deine Nummer lautet: $NAME")\
} elsif ($EVTPART1 eq "FHT") {\
   fhem ("set WhatsApp send $NAME FHT-Status:")\
} elsif ($EVTPART1 eq "PCA301") {\
   fhem ("set WhatsApp send $NAME PCA301-Status:")\
} elsif ($EVTPART1 eq "Bat") {\
   fhem ("set WhatsApp send $NAME Batterie-Status:")\
} elsif ($EVTPART1 eq "Help") {\
   fhem ("set WhatsApp send $NAME mögliche Befehle:\r\rTempGraph - Temp - Help - Nummer - FHT - PCA301 - Bat")\
} else {\
   fhem ("set WhatsApp send $NAME keine weiteren Infos")\
}\
}


nun würde ich gerne in einigen Gruppen eine Funktion wie diese einbinden:


} elsif ($EVTPART1 eq "PCA301") {\
   my $text = list TYPE=PCA301;
   foreach ($text) {
      $msg = $msg . ReadingsVal($_, 'state', 0) . "  " . ReadingsVal($_, 'power', 0) . "  " . ReadingsVal($_, 'consumption', 0)
   }
   fhem ("set WhatsApp send $NAME PCA301-Status: $msg")\
}


aber irgendwie klappt das nicht so ganz...

Wer kann mir helfen???

Gruß Blacky

justme1968

#1
das was du versuchst geht nicht weil:
- das list ist ein fhem kommando ist und es muss mit fhem("...") aufgerufen werden
- zurück kommt kein array sondern ein string den string könnte man an zeilenenden splitten und dann erst hättest du ein array
- es würde auch schief gehen wenn es nur ein device gibt will das das komplette device gelistet wird.

für das was du möchtes gibt es devspec2array:foreach my $d (devspec2array("TYPE=PCA301")) {...}

gruss
  andre

ps: der code für so etwas langem ist besser in 99_myUtils untergebracht und aus dem notify nur aufgerufen.
hue, tradfri, alexa-fhem, homebridge-fhem, LightScene, readingsGroup, ...

https://github.com/sponsors/justme-1968

Blackmore


} elsif ($EVTPART1 eq "PCA301") {
   my $msg = "";
   foreach my $devi (devspec2array("TYPE=PCA301")) {
    my $msg = "State: ". ReadingsVal($devi, 'state', 0). "  Power:". ReadingsVal($devi, 'power', 0). "W  Leistung:". ReadingsVal($devi, 'consumption', 0). "kW";
   fhem ("set WhatsApp send $NAME PCA301-Status: ". $msg)
   }


Funktioniert...

aber - wenn ich nun den fhem("...")-Part hinter die foreach Schleife hänge, bekomme ich keinen Text mehr...

also: so funktioniert es nicht:

} elsif ($EVTPART1 eq "PCA301") {
   my $msg = "";
   foreach my $devi (devspec2array("TYPE=PCA301")) {
    my $msg = $msg. "State: ". ReadingsVal($devi, 'state', 0). "  Power:". ReadingsVal($devi, 'power', 0). "W  Leistung:". ReadingsVal($devi, 'consumption', 0). "kW";
   }
   fhem ("set WhatsApp send $NAME PCA301-Status: ". $msg)


und - wie kann ich am Anfang der ganzen Zeile den Alias des derzeit geparsten Gerätes einfügen???
also in etwa so:


    my $msg = $msg. ReadingsVal($devi, 'alias', 0). ":\rState: ". ReadingsVal($devi, 'state', 0). "  Power:". ReadingsVal($devi, 'power', 0). "W  Leistung:". ReadingsVal($devi, 'consumption', 0). "kW";

justme1968

innerhalb der schleife muss das my vor $msg weg.

mit dem my deklarierst du eine lokale variable die nur innerhalb der schleife gilt. sobald die schleife verlassen wird ist der wert vergessen und das $msg das du vor der schleife deklariert hast ist wieder gültig.

ohne das my wird an das $msg immer weiter angehängt. das ist das was du willst.

alias ist ein attribut und kein reading. dafür gibt es AttrVal

insgesamt also etwa so:} elsif ($EVTPART1 eq "PCA301") {
   my $msg = "";
   foreach my $devi (devspec2array("TYPE=PCA301")) {
     $msg .= AttrVal($devi, 'alias', $devi). ":\rState: ". ReadingsVal($devi, 'state', 0). "  Power:". ReadingsVal($devi, 'power', 0). "W  Leistung:". ReadingsVal($devi, 'consumption', 0). "kW  ";
   }
   fhem ("set WhatsApp send $NAME PCA301-Status: ". $msg);
}


das ganze in eine einzige nachritt zu stecken ist aber problematisch weil es keinen zeilenumbruch gibt. die erste variante mit einem send pro device ist also eigentlich besser:} elsif ($EVTPART1 eq "PCA301") {
   foreach my $devi (devspec2array("TYPE=PCA301")) {
     my $msg = AttrVal($devi, 'alias', $devi). ":\rState: ". ReadingsVal($devi, 'state', 0). "  Power:". ReadingsVal($devi, 'power', 0). "W  Leistung:". ReadingsVal($devi, 'consumption', 0). "kW";
     fhem ("set WhatsApp send $NAME PCA301-Status: ". $msg);
   }
}


gruss
  andre
hue, tradfri, alexa-fhem, homebridge-fhem, LightScene, readingsGroup, ...

https://github.com/sponsors/justme-1968

Blackmore

#4
Klappt - super und vielen Dank....

so gelöst:

} elsif ($EVTPART1 eq "PCA301") {
   my $msg = "";
   foreach my $devi (devspec2array("TYPE=PCA301")) {
    my $ali = fhem ("displayattr $devi alias ");
    $msg = $msg. $ali. ":\rState: ". ReadingsVal($devi, 'state', 0). "\rPower: ". ReadingsVal($devi, 'power', 0). "W  \rLeistung: ". ReadingsVal($devi, 'consumption', 0). "kW\r\r";
   }
   fhem ("set WhatsApp send $NAME ". $msg);


die "\r" sind der Zeilenumbruch.... ;D ;D ;D

AttrVal($devi, 'alias', $devi)

werde ich morgen testen...
Gruß Blacky

justme1968

wo hast du das mit dem \r her? ich hatte schon alles mögliche probiert. aber darauf bin ich nicht gekommen...

hab im modul eingebaut das zeilenumbrüche (\n) automatisch durch \r ersetzt werden.

gruss
  andre
hue, tradfri, alexa-fhem, homebridge-fhem, LightScene, readingsGroup, ...

https://github.com/sponsors/justme-1968

Blackmore

#6
Das kenn ich noch aus Pascal-Zeiten - jetzt schon über 20 Jahre her...

da war mal was mit <crlf> - und das ging damals nicht... da musste man irgendwie dann mit \n\r arbeiten...

Ist mir irgendwie im Kopp hängengeblieben...


AttrVal($devi, 'alias', $devi)
funktioniert - sogar besser als wie meine Variante...

Kann man das Notify irgendwie triggern???
also - wenn eine Batterie aus einem Funkmodul ausfällt, das ich dann direkt trigger: trigger WA_Status Bat oder so ähnlich???
dann soll der mir gleich den Batteriestatus schicken, und danach auch noch, welche Batterie eigentlich Low ist...

Jetzt muss ich nur noch rausfinden, wie ich das notify so umschreiben kann, das alle TYPE=yowsup das notify auslösen, und nicht nur meine Handynummer...
Dann kann meine Freundin auch des Zeug abrufen...
Und dann muss ich noch wissen, wie ich dann die Nummern begrenzen kann, also das NUR meine Freundin und ich abrufen können...
von dem, was ich vergessen hab, könnten andere studieren

Und ich muss herausfinden, wie ich die if-Abfragen ändern kann...
das ich auch mit Regex arbeite...

} elsif ($EVTPART1 eq "[Pp][Cc][Aa]301") {



Gruß Blacky

Wuppi68

Zitat von: justme1968 am 08 Juli 2015, 22:40:11
wo hast du das mit dem \r her? ich hatte schon alles mögliche probiert. aber darauf bin ich nicht gekommen...

hab im modul eingebaut das zeilenumbrüche (\n) automatisch durch \r ersetzt werden.

gruss
  andre

schau mal hier

http://perldoc.perl.org/perlrebackslash.html

ich meine noch im Kopf zu haben, dass es auch einen "NewLine" Escapten Character gibt, der automatisch zwischen Unix und Windows als Wirtssystem unterscheidet
FHEM unter Proxmox als VM

justme1968

@Wuppi68: das kenne ich und das hilft nicht. die frage war wie Blackmore rausgefunden hat das es mit \r geht. das hängt nicht von perl ab und auch nicht vom modul. das \r als zeilenumbuch akzeptiert wird liegt einzig und alleine am whatsapp client auf dem handy. und es rauszufinden war ein glücklicher zufall. es gibt keine aktuellen systeme die das sonst noch machen.

@Blackmore: notify kannst du mit trigger triggern oder in dem du das reading mit setreading umsetzt. zurück setzen nicht vergessen.

mit acceptFrom kannst du auf modul ebene einschränken wer senden darf.

am besten lagerst du den code in 99_myUtils aus, führst einen übergab parameter ein den du abhängig vom auslösenden device setzt und machst daran die berechtigungen fest.

wenn es nur um die gross der klein schreibung geht kannst du mit uc oder lc eine klein bzw gross geschriebene version von $EVTPART1 zum vergleichen verwenden:} elsif ( uc($EVTPART1) eq "PCA301") {

vielleicht ist es auch sinnvoll wenn du nicht alle elsif von hand hin schreibst sondern dir eine datenstruktur überlegst in der du das kommando, die rechte, die devices und readings konfigurierst und dann in einer einzigen generischen schleife diese auswertest. das macht das erweitern einfacher.

gruss
  andre
hue, tradfri, alexa-fhem, homebridge-fhem, LightScene, readingsGroup, ...

https://github.com/sponsors/justme-1968

Blackmore

Herausgefunden hab ich es, in dem ich einfach nur probiert habe... Grins...
Wissen war da keins hintendran...  :P

Die Idee mit dem erweitern ist mir heute Morgen auch gekommen...
Ich muss mal gucken, wie ich das realisiere...

Würde gerne - so, wie ich es schon hab - mit PCA301 die Hauptinfos ALLER Steckdosen senden, und mit PCA301 KIZI zum Bleistift alle Infos zu den KinderZimmer-Steckdosen, oder so ähnlich...

Dazu muss ich alles umbauen, ansonsten wird's zu unübersichtlich...


Kann ich eigentlich mit einem Befehl herausfinden, welche Hardware-Geräte Fhem kennt??? Also list TYPE=Hardware kommt dann: FHT, HMS, PCA301, FHTTK, LaCrosse

Dann könnte man - zumindest die Übersichten - mit nur einem If abhandeln...

Gruß Blacky

justme1968

die geladenen module bekommst du z.b. mit my @loaded = grep {$modules{$_}->{LOADED}} keys %modules;

da ist aber erstens alles dabei. auch nicht hardware und zweitens auch geladene module zu denen es kein device gibt.

ersteres kann man nicht verhindern, letzteres könnte man vermeiden in dem man über alle definierten module geht. am ende ist es aber vermutlich einfacher die liste der unterstützten module fest zu definieren und zu schauen ob es dazu ein device gibt.

alles in einer schleife bekommst du wenn du dir wie oben vorschlagen eine datenstruktur definierst in der die unterstützen geräte mit den zugehörigen readings stehen. z.b. so:my %devices = ( { PCA301 => [ { state => '' },
                              { power => 'W'},
                              { consumption => 'kWh' }, ] },
                { FHT => ... } );


und dannin einer schleife die readings da raus holen.

gruss
  andre
hue, tradfri, alexa-fhem, homebridge-fhem, LightScene, readingsGroup, ...

https://github.com/sponsors/justme-1968