Hauptmenü

Probleme mit der Ausklammerung

Begonnen von Superposchi, 25 Oktober 2021, 09:24:27

Vorheriges Thema - Nächstes Thema

Superposchi

Hallo,

ich möchte mir gere ein DOIF erstellen, bei dem meine NEST-Geräte die Lautstärke resetten, sobald der mediaplayer auf IDLE spring.
Da ich mehrere NEST-Geräte habe möchte ich es natürlich Generisch erstellen.
Ich bekomme es auch hin, den Devicenamen des auszulösenden Events auszulesen.

Aber ich schaffe es nicht, diesen Devicenamen in einen Perl-Aufruf für mein Reset-Script in der 99_myUtilities.pm einzubauen.
Entweder meckert er mir fehlende Anführungenzeichen an, oder es sind zu viele oder er erkennt die Variable nicht als Variable sondern als Text.

Der Aufruf der Funktion lautet sinngemäß "{ResetVolume("Schlafzimmerlautsprecher")}", im DOIF wird das Schlafzimmerlautsprecher dann durch die Variable getauscht, also {ResetVolume($DEVICE)}.
Aber so fehlen in der Funktion die Anführungszeichen. Wie lautet die korekte Schreibweise, damit er mir den Devicenamen in Anführungszeichen in die Funktion schreibt?

Hier das List des DOIF's:
Internals:
   CFGFN     
   DEF        (["lautsprecher:^mediaPlayerState:.IDLE$"])
{ResetVolume("/"$DEVICE"")}
   DOIFDEV    ^global$|lautsprecher
   FUUID      6176545f-f33f-6c14-a1b2-77cd67e2e818ed31
   MODEL      FHEM
   NAME       Reset_Volume
   NR         123272
   NTFY_ORDER 50-Schlafzimmerlautsprecher_DOIF_1
   STATE      cmd_1
   TYPE       DOIF
   VERSION    24905 2021-09-01 18:35:54
   READINGS:
     2021-10-25 09:15:19   Device          Schlafzimmerlautsprecher
     2021-10-25 09:15:19   cmd             1
     2021-10-25 09:15:19   cmd_event       Schlafzimmerlautsprecher
     2021-10-25 09:15:19   cmd_nr          1
     2021-10-25 09:15:19   error           {ResetVolume("/"Schlafzimmerlautsprecher"")}: syntax error at (eval 907428) line 1, near ""/"Schlafzimmerlautsprecher"

     2021-10-25 09:15:07   mode            enabled
     2021-10-25 09:15:19   state           cmd_1
   Regex:
     accu:
     collect:
     cond:
       :
         0:
           "lautsprecher:^mediaPlayerState:.IDLE$" lautsprecher:^mediaPlayerState:.IDLE$
   attr:
     cmdState:
     wait:
     waitdel:
   condition:
     0          ::EventDoIf('lautsprecher',$hash,'^mediaPlayerState:.IDLE$',0)
   do:
     0:
       0          {ResetVolume("/"$DEVICE"")}
     1:
   helper:
     DEVFILTER  ^global$|lautsprecher
     NOTIFYDEV  global|.*lautsprecher.*
     event      mediaPlayerState: IDLE
     globalinit 1
     last_timer 0
     sleeptimer -1
     timerdev   Schlafzimmerlautsprecher
     timerevent mediaPlayerState: IDLE
     triggerDev Schlafzimmerlautsprecher
     DOIF_eventa:
       cmd_nr: 1
       cmd: 1
       cmd_event: Schlafzimmerlautsprecher
       error: {ResetVolume("/"Schlafzimmerlautsprecher"")}: syntax error at (eval 907428) line 1, near ""/"Schlafzimmerlautsprecher"

       cmd_1
     DOIF_eventas:
       cmd_nr: 1
       cmd: 1
       cmd_event: Schlafzimmerlautsprecher
       error: {ResetVolume("/"Schlafzimmerlautsprecher"")}: syntax error at (eval 907428) line 1, near ""/"Schlafzimmerlautsprecher"

       state: cmd_1
     timerevents:
       mediaPlayerState: IDLE
       mediaCurrentPosition:
       mediaCurrentPosPercent:
       online
     timereventsState:
       mediaPlayerState: IDLE
       mediaCurrentPosition:
       mediaCurrentPosPercent:
       state: online
     triggerEvents:
       mediaPlayerState: IDLE
       mediaCurrentPosition:
       mediaCurrentPosPercent:
       online
     triggerEventsState:
       mediaPlayerState: IDLE
       mediaCurrentPosition:
       mediaCurrentPosPercent:
       state: online
   internals:
   readings:
   trigger:
   uiState:
   uiTable:
Attributes:
   do         always
   room       Test


P.S.
Um Fragen vorzubeugen warum ein DOIF statt eines Notifys - Ganz einfach deshalb, weil ich im DOIF mit "samewait" über eine Zeit prüfen kann, dass keine weitere Ansage hinterherkommt.

Sany

Moin,

dein Versuch zu "escapen" liefert einen syntaxfehler, weil er einfach falsch geschrieben ist. Escapen geht mit \  (=Backslash).
Wenn also der Funktionsaufruf in Anführungszeichen stehen muss und Du willst aber auch welche übergeben müsste es so aussehen:
{ResetVolume("\"$DEVICE\"")}
Zumindest würde ich das so versuchen, da ich da auch eher rumprobiere als es "genau" zu wissen  ;)
Interessant wäre noch die Funktion, ob die Übernahme dort richtig stattfinden kann.

Und nun mal generell: du nutzt viel DOIF, und die sind z.T. sehr komplex mit Timern und/oder Zuständen. Das geht zwar (bis zu einem gewissen grad) mit fhem-DOIF, aber versuch doch mal Perl-DOIF. Du musst nur wirklich unterscheiden und nicht mischen! im Perl-DOIF hast Du die meisten Attribute nicht (wait, do) die bisher wichtig waren, sondern Du mußt Timer z.B. selbst definieren und den state setzen (wenn daran Bedarf besteht), aber Du hast auch die volle Kontrolle. Um bei Deinem Beispiel zu bleiben brauchst Du auch keine Funktion in der 99_myUtils, sondern schreibst das einfach im DOIF mit rein. Du kannst auch Funktionen im Perl-DOIF definieren, die von anderen DOIFs aus nutzbar sind, das ist hier aber wohl nicht der Fall.
Ich würde den Versuch mal wagen. Bedeutet halt nochmal die commandref zu Perl-DOIF studieren und dann am besten mal einen Versuch starten.
Ich würde mal so sagen: Je komplexer die Aufgabenstellung desto einfacher ist es mit Perl-DOIF im Vergleich zu fhem-DOIF.
Und ja: es ist Perl, aber in der 99_myUtils ist doch auch Perl drin, oder?

Viel Erfolg!

Sany
fhem auf Zotac ZBox nano als LXC auf Proxmox, weitere LXC mit ZigBee2MQTT, MariaDB und Grafana. Homematic, FS20, mySensors, MQTT2, Tasmota, Shelly, Z-Wave  ....

Superposchi

Also leider funktioniert deine Lösung offenbar nicht.
Ich kann nachvollziehen, dass das DOIF auslöst und wenn ich statt der Variable den Klartext einfüge wird es auch ausgeführt. Es hängt definitiv an der Schreibweise der Variablen. Der Inhat ist auch korrekt, wird zuindest in einer der Fehlermeldung richtig ausgelesen.

Was deinen Hinweis angeht, so sind ja genau diese Attribute der Grund warum ich DOIF bevorzuge. Wenn ich diese im Perl-Modus nicht mehr habe, warum sollte ich mir die Arbeit dann künstlich erschweren?
Und eine solche Funktion in einem DOIF, dazu ist doch gerade die 99_myUtils für da oder habe ich die letzten 2 Jahre nur MMist gelernt?
Ich weiß, dass man im Perl-Modus etwas mehr Möglichkeiten hat, aber ehrlich gesagt, habe ich bisher noch keine dieser Mehrsachen vermisst. Im Umkehrschluss würde ich aber do, wait, waitsame etc. extrem vermissen.

MadMax-FHEM

#3
Also bei einem notify wenn ich den Devicenamen übergeben will, mache ich das einfach so:


define nTest notify Triggerdev:Regex {Subname($NAME)}

(bei notify ist das auslösende Device eben $NAME)

Also einfach ohne nix was...
...deine Aufgabe (wenn das wirklich "alles" ist), ginge ganz einfach auch mit einem notify... 8)

EDIT: in der sub dann my ($Device) = @_; (jaja, böse Prototypen ;) oder halt mit shift [sollte ja auch gehen])


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)

Superposchi

Ich weiß, hatte ich auch bisher in einem Notify gelöst.
Aber da hat es den Reset immer wieder mal zu früh rausgehauen - frag mich nicht warum.

Mit dem DOIF kann ich einfach per wai eine zusätzliche Wartezeit implementieren in der der IDLE-Wert sich nicht verändern darf.

Die korekte Schreibweise ist
({ResetVolume("$DEVICE")})
Habs mit weiterem Ausprobieren schließlich gefunden.