[gelöst:]DOIF Perl Modus - erster Versuch - dynamische Anzahl Readings versenden

Begonnen von shamal2008, 27 Mai 2020, 11:10:14

Vorheriges Thema - Nächstes Thema

shamal2008

Hallo zusammen,

ich versuche mich seit einigen Tagen an einer Verbesserung meiner Perl-Kenntnisse und gleichzeitig meinen Doifs.

Problemstellung:
Das Modul UWZ gibt Wetterwarnungen aus, die je nach Anzahl "dynamisch" (von 0 bis x) sind und mit WarnCount (=Gesamtanzahl) versehen ist. Ich hatte bis jetzt ein wenig elegantes Doif, welches einfach abgefragt hat, ob WarnCount > 0 und dann im Doelseif jeden Befehl einzeln (eine Telegram-Push Nachricht) einzeln versendet hat.

Die Readings der Warntexte sind aufgebaut Warn_X_Longtext.

Ich habe nun (mein erstes) DOIF im Perl versucht und scheitere, trotz einigen Stunden Forum und CommandRef an zwei Punkten:

1. Readingsnum erwartet lt. DOIF Fehlermeldung einen "Timestamp"??? - hab auch Readingsval versucht, aber gleiche Fehlermeldung.
2. Wie kann ich das Reading Warn_X_Longtext in der Schleife richtig zusammensetzen? der Reine Perlcode funktioniert, aber das mit den Readings will mir nicht in den Kopf.

Hier mal der Beispielcode:
{{if (uwz.neusiedl:WarnCount) ne "0")}

{my $max=[{ReadingsNum("uwz.neusiedl","WarnCount",0)}];
for (my $i = 0; $i <= $max-1; $i++)
{
## first message with graphic
    if $i=1; fhem_set (MaLaBot sendImage @#Smart-MaLa-Home /tmp/neusiedl.png)
## all others only reading
myreading$="Warn_$i_LongText";
{fhem_set (MaLaBot sendImage @#Smart-MaLa-Home set MaLaBot message @#Smart-MaLa-Home WETTERWARNUNG FÜR NEUSIEDL am SEE: [uwz.neusiedl:$myreading])}
}}}


Gibt es eine for/foreach Variante eigentlich im "FHEM" Modus auch - gefunden hätte ich darüber nichts...

Danke für eure Hilfe...
lg Shamal
FHEM auf RasPiI 3+, MapleCUL 868+433MhZ, MAX! via CUL, LD686 LED-Controller, GHoma Plugins,, Shelly, ConbeeII + IKEA + Xiaomi, div. Infodienste & Google Assistant via FHEM;

amenomade

{{if ([uwz.neusiedl:WarnCount, 0] ne "0")}                #somit hast Du ein Trigger...

{my $max= ReadingsNum("uwz.neusiedl","WarnCount",0);      #entweder
{my $max=[uwz.neusiedl:WarnCount:d, 0];                   #oder. Somit sollte er nicht mehr ein Timestamp verlangen


    if ($i == 1) { fhem_set (MaLaBot sendImage @#Smart-MaLa-Home /tmp/neusiedl.png) }            #syntaxisch besser...


$myreading ="Warn_$i_LongText";                #syntaxisch besser...
{fhem_set ("MaLaBot sendImage @#Smart-MaLa-Home set MaLaBot message @#Smart-MaLa-Home WETTERWARNUNG FÜR NEUSIEDL am SEE: ".ReadingsVal("uwz.neusiedl",$myreading, "")}
Pi 3B, Alexa, CUL868+Selbstbau 1/2λ-Dipol-Antenne, USB Optolink / Vitotronic, Debmatic und HM / HmIP Komponenten, Rademacher Duofern Jalousien, Fritz!Dect Thermostaten, Proteus

amenomade

Wegen for/foreach: es gibt die Aggregationsfunktionen:

https://fhem.de/commandref_DE.html#DOIF_aggregation. Z.B. in Perl Modus:
Zitat von: CommandRefdefine di_Fenster DOIF {if (["^Window:open"]) {foreach (AggrDoIf('@','^windows','state','"open"')) {Log3 "di_Fenster",3,"Das Fenster $_ ist noch offen"}}}

define di_Temperature DOIF {if (["^room:temperature"]) {foreach (AggrDoIf('@','^room','temperature','$_ < 15')) {Log3 "di_Temperatur",3,"im Zimmer $_ ist zu kalt"}}

Und es gibt noch andere Möglichkeiten, dein DOIF zu realisieren... aber dann sind wir noch in einem Monat da ;)
Pi 3B, Alexa, CUL868+Selbstbau 1/2λ-Dipol-Antenne, USB Optolink / Vitotronic, Debmatic und HM / HmIP Komponenten, Rademacher Duofern Jalousien, Fritz!Dect Thermostaten, Proteus

shamal2008

Hallo Amenomade,

zuerst ein herzliches Danke für deine Hilfe. Hab das DOIF mal umgebaut, und "warte" auf die nächste Wetterwarnung. Das alte ist sicherheitshalber noch aktiv.

Das mit Aggregationsfunktion habe ich durchgelesen, aber ehrlich - es hat mich mehr verwirrt, als erhellt. In den Beispielen ist (soweit ich das entziffern konnte) eigentlich nur von einer Aggregation der Devices die Rede, dass ich mit dieser Funktion ein Reading auswerten und danach eine "For" im FHEM-Modus machen kann, hat sich mir nicht erschlossen.

Soweit ich das aus der Doku verstanden hatte, kann ich zwar einen Wert auslesen bzw. "berechnen", diesen aber nur in den State des DOIF schreiben. Den höchsten Wert berechnen muss ich ja nicht, weil der in WarnCount steht.

Um dann eine Schleife zu machen, muss ich ja doch ins Perl, oder?

PS:Ehrlich - das Beispiel mit den offenen Fenstern hab ich nicht im geringsten kapiert:
define di_Fenster DOIF {if (["^Window:open"]) {foreach (AggrDoIf('@','^windows','state','"open"')) {Log3 "di_Fenster",3,"Das Fenster $_ ist noch offen"}}}  - wo ist da der Zähler? - den ich ja noch um 1 erniedrigen muss, weil die Readings mit 0 beginnen..

lg - und einen Monat mag ich dich nicht beschäftigen :)
Shamal
FHEM auf RasPiI 3+, MapleCUL 868+433MhZ, MAX! via CUL, LD686 LED-Controller, GHoma Plugins,, Shelly, ConbeeII + IKEA + Xiaomi, div. Infodienste & Google Assistant via FHEM;

amenomade

In einem foreach Loop enthält $_ nach und nach jedes Element.

Sicherer und lesbarer wäre:
define di_Fenster DOIF {if (["^Window:open"]) {foreach $element (AggrDoIf('@','^windows','state','"open"')) {Log3 "di_Fenster",3,"Das Fenster $element ist noch offen"}}}

Aber bleib erstmal bei deiner Schleife  bis zu Ende (bis es funktioniert). Danach wirst Du evtl. spielen können ;)
Pi 3B, Alexa, CUL868+Selbstbau 1/2λ-Dipol-Antenne, USB Optolink / Vitotronic, Debmatic und HM / HmIP Komponenten, Rademacher Duofern Jalousien, Fritz!Dect Thermostaten, Proteus

shamal2008

Hallo Amenomade,

genau das mache ich mal - jetzt warte ich mal auf die nächste Warnung - zur Sicherheit ist das "alte" noch aktiv. Wenn das neue auch klappt, dann spiele ich mal mit den Funktionen.

Danke für deine Hilfe!

lg Shamal
FHEM auf RasPiI 3+, MapleCUL 868+433MhZ, MAX! via CUL, LD686 LED-Controller, GHoma Plugins,, Shelly, ConbeeII + IKEA + Xiaomi, div. Infodienste & Google Assistant via FHEM;

shamal2008

Hallo nocheinmal,

ich kämpfe jetzt schon seit dem letzten Mal mit dem DOIF. Jetzt hätten wir gerade wieder Warnungen. Trotz allem Lesen steig ich noch nicht dahinter, wann welche Klammer im Perl-Modus sein muss.

Mein letzter Versuch war jetzt so, allerdings macht das DOIF genau gar nichts. Ich kann nur enablen, disablen - bekomme aber auch keinerlei Info, was nicht passt. Könnt ihr mir mal einen letzten Schubs geben :)

{ if ([uwz.neusiedl:WarnCount, 0] ne "0")}
{my $max=([uwz.neusiedl:WarnCount:d,0]);
for (my $i = 0; $i <= $max-1; $i++);
$myreading="Warn_$i_LongText";
if ($i == 1);
{ fhem_set (MaLaBot sendImage @#Smart-MaLa-Home /tmp/neusiedl.png)};
{fhem_set("MaLaBot message @#Smart-MaLa-Home PERL-WETTERWARNUNG FÜR NEUSIEDL am SEE: ".ReadingsVal("uwz.neusiedl",$myreading, ""))
};
}


Danke,
Shamal
FHEM auf RasPiI 3+, MapleCUL 868+433MhZ, MAX! via CUL, LD686 LED-Controller, GHoma Plugins,, Shelly, ConbeeII + IKEA + Xiaomi, div. Infodienste & Google Assistant via FHEM;

MadMax-FHEM

Ich nutze ja kein/kaum DOIF ABER:

Zitat
{ if ([uwz.neusiedl:WarnCount, 0] ne "0")}

KANN ja nur NICHTS machen... ;)

Also:

geschweifte Klammer auf -> Perl (nehme an auch bei DOIF-Perl)

dann if "irgendwas" -> dann kommt was passieren soll "wenn"...

ABER: dann machst du geschweifte Klammer zu -> fertig!

Also EGAL was auch beim "if" rauskommt: du "sagst" es SOLL NICHTS passiern (und genau das tut es ja auch laut deiner Aussage ;)  )...

Also mindestens mal die geschweifte "Klammer zu" gleich nach dem "if" weg!

Ob der Rest so stimmt siehst du dann...

EDIT: und evtl. Zahlen nicht als "String-Vergleich"... (kann auch mal "unerwartete" Ergebnisse liefern ;)  ) Also X < Y / X > Y / X == Y / X != Y vs. TextX lt TextY / TextX gt TextY / TextX eq TextY / TextX ne TextY

Gruß, Joachim
FHEM PI3B+ Bullseye: HM-CFG-USB, 40x HM, ZWave-USB, 13x ZWave, EnOcean-PI, 15x EnOcean, HUE/deCONZ, CO2, ESP-Multisensor, Shelly, alexa-fhem, ...
FHEM PI2 Buster: HM-CFG-USB, 25x HM, ZWave-USB, 4x ZWave, EnOcean-PI, 3x EnOcean, Shelly, ha-bridge, ...
FHEM PI3 Buster (Test)

shamal2008

Hallo MadMax-FHEM,

hab ich mal so gemacht - funkt allerdings immer noch nicht. Hab jetzt auch schon mit ";;" herumprobiert, zugebenermaßen schon recht verzweifelt und vermutlich deshalb auch "wahllos"... :)

Danke mal vorab,
Shamal
FHEM auf RasPiI 3+, MapleCUL 868+433MhZ, MAX! via CUL, LD686 LED-Controller, GHoma Plugins,, Shelly, ConbeeII + IKEA + Xiaomi, div. Infodienste & Google Assistant via FHEM;

amenomade

Zitat von: MadMax-FHEM am 08 Juni 2020, 10:12:52
Ich nutze ja kein/kaum DOIF ABER:

KANN ja nur NICHTS machen... ;)

Genauso für die for Schleife und das 2. if, die sofort mit einem Semikolon geschlossen werden...

Ich vermute übrigens, dass es in der Log schon schreit, und zwar mit sinnvollen Fehlermeldungen...

Wenn man DOIFs auf Perl schreiben möchtet, sollte man vielleicht ein bisschen Perl Syntax lernen
Pi 3B, Alexa, CUL868+Selbstbau 1/2λ-Dipol-Antenne, USB Optolink / Vitotronic, Debmatic und HM / HmIP Komponenten, Rademacher Duofern Jalousien, Fritz!Dect Thermostaten, Proteus

shamal2008

Hallo Amenomade,

a) Das Eventlog zeigt (trotz Verbose 5) nichts aus "enabled" und "disabled", sonst hätte ich mir weiterhelfen können.

2020-06-08 12:29:14 DOIF di.msg.uwztest mode: enabled
2020-06-08 12:29:14 Global global MODIFIED di.msg.uwztest
2020-06-08 12:29:20 DOIF di.msg.uwztest mode: enabled


b) im Log selbst steht überhaupt nichts dazu. Nicht eine Silbe vom uwz oder vom DOIF selbst.

c) ja, Perl Syntax ist gut, die Kombination mit FHEM ist vielleicht für Anfänger ein wenig gewöhnungsbedürftig. Und ganz ehrlich: Der Rat hilft mir leider nicht weiter. Nach sicher 20 Stunden div. CommandRefs, 140 Seitige Threads, etc. lesen ist irgendwann das mühsam aufgebaute Verständnis wieder vorbei. Und auch irgendwann sieht man den Wald vor lauter Bäumen nicht.

lg Shamal
FHEM auf RasPiI 3+, MapleCUL 868+433MhZ, MAX! via CUL, LD686 LED-Controller, GHoma Plugins,, Shelly, ConbeeII + IKEA + Xiaomi, div. Infodienste & Google Assistant via FHEM;

MadMax-FHEM

#11
Ja verständlich...
...hilft aber (auf Dauer) nix ;)

Da "musst" du durch... ;)

Wie geschrieben: ich nutze kein DOIF und damit auch kein DOIF-Perl ;)

Was in einer Sub in myUtils (nur um zu "demonstrieren" wo das so geht ;)  gut, bis auf "set-Magic-Zeugs" vermutlich aber auch das nutze ich nicht ;) ) gehen sollte:


{ # Perl "Anfang" (vermute ich)
  if ([uwz.neusiedl:WarnCount, 0] ne "0")
  {
    my $max=([uwz.neusiedl:WarnCount:d,0]);
    for (my $i = 0; $i <= $max-1; $i++)
    {
      $my reading="Warn_$i_LongText"; # Leerzeichen zwischen my und reading eingefügt ;)

      if ($i == 1)
      {
        fhem_set ("MaLaBot sendImage @#Smart-MaLa-Home /tmp/neusiedl.png"); # fhem_set korrigiert ;)  ABER: ich nutze ja kein DOIF, daher kenne ich auch fhem_set nicht ;)  Nur fhem(" ") in Perl-Sub, ok dann giltet die "Ausrede" nicht ;)
      } # damit wird aber NUR dieser fhem-Befehl bei ==1 ausgeführt! Wenn auch der 2te NUR bei ==1 ausgeführt werden soll, dann eben den 2ten Aufruf "eine Ebene höher", also auch "innerhalb der Klammer" (kannst ja nur du wissen ;)  )
      fhem_set("MaLaBot message \@#Smart-MaLa-Home PERL-WETTERWARNUNG FÜR NEUSIEDL am SEE: ".ReadingsVal("uwz.neusiedl",$reading, "")); # hier muss dann nat. statt $myreading "nur" $reading hin... ;)
    } # ende: for / d.h. alles von "for" bis "hier" wird in der Schleife bearbeitet
  } # ende: "erstes" if. D.h. das vom 1. if bis hier wird nur ausgeführt, wenn uwz.neusiedl:WarnCount != 0 ist... Und nat. das DOIF überhaupt getriggert wird ;)
} # Perl "Ende" (vermute ich)


Und wie du siehst habe ich auch (deutlich) "umstrukturiert", so sieht man (besser) was "zusammenhǵehört" etc.

EDIT: <= $max-1 macht dasselbe wie < $max ;)

EDIT: ob das hier tatsächlich geht weiß ich nicht $myreading="Warn_$i_LongText"; ich würde (sicherheitshalber) so schreiben: $myreading="Warn_" . $i . "_LongText";

EDIT: du siehst auch, dass einige Strichpunkte entfernt wurden (ich hoffe, ich habe alle "erwischt", die "zu viel sind")... Ein Strichpunkt "beendet" einen Perl-Befehl/-Zeile. Ein Strichpunkt OHNE irgendwas ist wie ein "Null-Befehl"... Daher macht ein if(irgendwas); quasi NIE "etwas" (also zumindest nicht abhängig von "irgendwas" ;)  ), weil ja nach der Bedingung gleich der "Leerbefehl" kommt, welcher schon abhängig von der Bedingung ausgeführt wird... Aber: halt "nichts macht" ;)

Gruß, Joachim
FHEM PI3B+ Bullseye: HM-CFG-USB, 40x HM, ZWave-USB, 13x ZWave, EnOcean-PI, 15x EnOcean, HUE/deCONZ, CO2, ESP-Multisensor, Shelly, alexa-fhem, ...
FHEM PI2 Buster: HM-CFG-USB, 25x HM, ZWave-USB, 4x ZWave, EnOcean-PI, 3x EnOcean, Shelly, ha-bridge, ...
FHEM PI3 Buster (Test)

shamal2008

Hallo Joachim,

dein Post hat schon mal ein wenig Licht in die Sache gebracht, und sollte meiner Meinung nach auch funktionieren. WarnCount ist derzeit 2, und somit sollte das DOIF ja funktionieren. Ich war bis jetzt der Meinung, dass ein syntaktisch richtiges DOIF auch die checkall, sowie die CMD Zweige zur Verfügung stellt, damit ich hier weiter testen kann.

Auch in deinem Beispiel gibt es nur "enable" und "disable" und das war's dann auch. Log leer, Eventmonitor leer... leider gar nix, wo ich mich anhalten oder vortasten könnte.

EDIT: Die Strichpunkte waren schon echte "Verzweiflungstaten", weil ich zahlreichen Bespielen und Posts immer wieder andere Varianten gefunden habe, wie es "jetzt" funktioniert... da gibts auch die ";;" Varianten...

Danke auf jeden Fall,
lg Shamal
FHEM auf RasPiI 3+, MapleCUL 868+433MhZ, MAX! via CUL, LD686 LED-Controller, GHoma Plugins,, Shelly, ConbeeII + IKEA + Xiaomi, div. Infodienste & Google Assistant via FHEM;

amenomade

Also... ehrlich?

Hab ein DOIF namens testDOIF mit genau deiner Definition erstellt
{ if ([uwz.neusiedl:WarnCount, 0] ne "0")}
{my $max=([uwz.neusiedl:WarnCount:d,0]);
for (my $i = 0; $i <= $max-1; $i++);
$myreading="Warn_$i_LongText";
if ($i == 1);
{ fhem_set (MaLaBot sendImage @#Smart-MaLa-Home /tmp/neusiedl.png)};
{fhem_set("MaLaBot message @#Smart-MaLa-Home PERL-WETTERWARNUNG FÜR NEUSIEDL am SEE: ".ReadingsVal("uwz.neusiedl",$myreading, ""))
};
}

Dann folgendes:
define uwz.neusiedl dummy
setreading uwz.neusiedl WarnCount 1


Und sofort kommt im DOIF:

   READINGS:
     2020-06-08 13:11:53   Device          uwz.neusiedl
     2020-06-08 13:11:53   block_01        condition c01: syntax error, line 1, at EOF

     2020-06-08 13:11:53   block_02        condition c02: syntax error at (eval 159) line 2, at EOF
Global symbol "$myreading" requires explicit package name (did you forget to declare "my $myreading"?) at (eval 159) line 3.
Global symbol "$myreading" requires explicit package name (did you forget to declare "my $myreading"?) at (eval 159) line 6.
Pi 3B, Alexa, CUL868+Selbstbau 1/2λ-Dipol-Antenne, USB Optolink / Vitotronic, Debmatic und HM / HmIP Komponenten, Rademacher Duofern Jalousien, Fritz!Dect Thermostaten, Proteus

MadMax-FHEM

Mist, stimmt, da ist dann doch was "durchgerutscht"...
...aber so ist das, wenn man "fremden" Code versucht "gerade zu biegen" ;)

Hab diesen Fehler auch grad "korrigiert"...
...mal sehen was ich noch so "übersehen" hab... ;)

Gruß (und sorry), Joachim
FHEM PI3B+ Bullseye: HM-CFG-USB, 40x HM, ZWave-USB, 13x ZWave, EnOcean-PI, 15x EnOcean, HUE/deCONZ, CO2, ESP-Multisensor, Shelly, alexa-fhem, ...
FHEM PI2 Buster: HM-CFG-USB, 25x HM, ZWave-USB, 4x ZWave, EnOcean-PI, 3x EnOcean, Shelly, ha-bridge, ...
FHEM PI3 Buster (Test)