[Gelöst] If Bedingung in einer sub

Begonnen von dk3572, 23 Dezember 2020, 13:52:02

Vorheriges Thema - Nächstes Thema

dk3572

Hallo,

je nachdem wo Bewegung erkannt wurde, möchte ich auch dort die Sprachausgabe.
Hierfür rufe ich eine sub auf in der ich das cmd-event des DOIF auswerte.
Leider gibt es mir immer nur über das 1. if (BM_Wohnzimmer) die Sparche aus.

Ist jemand so nett und hilft mir auf die Sprünge?

Danke im Voraus und VG
Dieter

DEF        ([?Bewohner] eq "zuhause" && [?du_TTS:cnt] > 0 && ([BM_Wohnzimmer] eq "motion" or [BM_Kueche_Motion] eq "motion")) ({TTSSayQueue()}) DOELSE
   FUUID      5e3eed05-f33f-cd72-3f12-16920cbfa0495499
   FVERSION   98_DOIF.pm:0.234030/2020-12-22
   MODEL      FHEM
   NAME       di_TTSQueue
   NOTIFYDEV  BM_Wohnzimmer,BM_Kueche_Motion,global
   NR         350
   NTFY_ORDER 50-di_TTSQueue
   STATE      cmd_2
   TYPE       DOIF
   VERSION    23403 2020-12-22 15:43:36
   READINGS:
     2020-12-23 13:39:56   Device          BM_Wohnzimmer
     2020-12-23 13:39:56   cmd             2
     2020-12-23 13:39:56   cmd_event       BM_Wohnzimmer
     2020-12-23 13:39:56   cmd_nr          2
     2020-12-23 13:39:42   e_BM_Kueche_Motion_STATE nomotion
     2020-12-23 13:39:56   e_BM_Wohnzimmer_STATE nomotion
     2020-12-23 11:57:43   mode            enabled
     2020-12-23 13:39:56   state           cmd_2
   Regex:
     accu:
     cond:
       BM_Kueche_Motion:
         0:
           &STATE     ^BM_Kueche_Motion$
       BM_Wohnzimmer:
         0:
           &STATE     ^BM_Wohnzimmer$
   attr:
     cmdState:
     wait:
     waitdel:
   condition:
     0          ::InternalDoIf($hash,'Bewohner','STATE') eq "zuhause" && ::ReadingValDoIf($hash,'du_TTS','cnt') > 0 && (::InternalDoIf($hash,'BM_Wohnzimmer','STATE') eq "motion" or ::InternalDoIf($hash,'BM_Kueche_Motion','STATE') eq "motion")
   do:
     0:
       0          {TTSSayQueue()}
     1:
       0         
   helper:
     DEVFILTER  ^global$|^BM_Wohnzimmer$|^BM_Kueche_Motion$
     NOTIFYDEV  global|BM_Wohnzimmer|BM_Kueche_Motion
     event      nomotion,dark: 1
     globalinit 1
     last_timer 0
     sleeptimer -1
     timerdev   BM_Wohnzimmer
     timerevent nomotion,dark: 1
     triggerDev BM_Wohnzimmer
     DOIF_eventa:
       cmd_nr: 2
       cmd: 2
       cmd_event: BM_Wohnzimmer
       cmd_2
     DOIF_eventas:
       cmd_nr: 2
       cmd: 2
       cmd_event: BM_Wohnzimmer
       state: cmd_2
     timerevents:
       nomotion
       dark: 1
     timereventsState:
       state: nomotion
       dark: 1
     triggerEvents:
       nomotion
       dark: 1
     triggerEventsState:
       state: nomotion
       dark: 1
   internals:
     all         Bewohner:STATE BM_Wohnzimmer:STATE BM_Kueche_Motion:STATE
   readings:
   trigger:
   uiState:
   uiTable:
Attributes:
   DbLogExclude .*
   comment    DOIF steuert Ausgabe von Sprachnachrichten die vom Dummy du_TTS gesammelt werden.
Zugehörig 99_myTtsUtils.pm <sub TTSSayQueue()>
   do         always


sub TTSSayQueue() {
    my $text = '';
    my $cnt = ReadingsNum('du_TTS', 'cnt', 0);
    my $bm = ReadingsVal('di_TTSQueue', 'cmd_event', '');

    if ($cnt > 0) {

        for (my $i = 1; $i <= $cnt; $i++) {
            $text .= ReadingsVal('du_TTS', 'queue-' . $i, '') . '. ';
        }
   
    if ($bm eq "BM_Wohnzimmer"){
        fhem("set ECHO_G090LV03644201AX speak_ssml <speak>$text</speak>")}

    if ($bm eq "BM_Kueche_Motion"){
        fhem("set ECHO_G090P30874340EX4 speak_ssml <speak>$text</speak>")}

        fhem("deletereading du_TTS queue-.*");
        fhem("setreading du_TTS cnt 0");
    }
   
    return undef;
}

Otto123

Hi,

schreib doch einfach mal ins Log was da so an Werten drin steht in Deiner Sub
Log 1, "BM: $bm CNT: $cnt Text: $text";

Gruß Otto
Viele Grüße aus Leipzig  ⇉  nächster Stammtisch an der Lindennaundorfer Mühle
RaspberryPi B B+ B2 B3 B3+ ZeroW,HMLAN,HMUART,Homematic,Fritz!Box 7590,WRT3200ACS-OpenWrt,Sonos,VU+,Arduino nano,ESP8266,MQTT,Zigbee,deconz

dk3572

Hi,

danke für deine Unterstützung.

Es wird alles ausgewertet und übergeben, allerdings nur bei 2 Versuchen.
Danach wird immer nur noch BM_Wohnzimmer übergeben.

Kann es sein, dass das Reading des DOIF schneller übergeben wird als es gesetzt wird?

3 x hintereinander in Küche getestet, funktioniert.
1 x in Wohnzimmer getestet, funktioniert.
Wenn ich jetzt wieder Küche teste, wird im Wohnzimmer ausgegeben.

Otto123

#3
Sowas war auch meine Vermutung,... Ich sehe aber gerade:
Du fragst Zustände ab, ich würde gezielt auf den Event reagieren!

ich glaube so:
([BM_Wohnzimmer:"^motion"] or [BM_Kueche_Motion:"^motion"] )
oder sogar so:
["^BM_:^motion$"]
Triggert auf alle Geräte die mit BM:_ beginnen und auf genau den Event "motion"
da kein or auch keine Klammer :)

Und je länger ich darüber nachdenke, einfach ein notify mit BM und motion triggern, die beiden Readings in der Sub abfragen, $NAME beim Aufruf der Sub nutzen, da wird die Sub einfacher ;)
Viele Grüße aus Leipzig  ⇉  nächster Stammtisch an der Lindennaundorfer Mühle
RaspberryPi B B+ B2 B3 B3+ ZeroW,HMLAN,HMUART,Homematic,Fritz!Box 7590,WRT3200ACS-OpenWrt,Sonos,VU+,Arduino nano,ESP8266,MQTT,Zigbee,deconz

dk3572

Funktioniert leider nicht. Es muss aber wohl mit dem Bewegungsmelder Wohnzimmer und dem DOIF zusammen hängen.

Würdest du mir bei der sub mit deinem Vorschlag unter die Arme greifen?
Was meinst du mit $NAME nutzen?

Ich hätte mir jetzt mit z.B. my $bew = ReadinsVal von Bewohner geholt.
Der du_TTS cnt wird ja in der sub schon abgefragt und muss größer 0 sein.

Damian

#5
Zitat von: dk3572 am 23 Dezember 2020, 15:37:56
Funktioniert leider nicht. Es muss aber wohl mit dem Bewegungsmelder Wohnzimmer und dem DOIF zusammen hängen.

Sollte aber. Erstens solltest du schauen, ob bei Bewegung motion-Events kommen - was ich mal unterstelle.

Deine Abfrage:

[BM_Wohnzimmer] eq "motion"

ist schon "gefährlich". Diese triggert bei jedem Event von BM_Wohnzimmer.

Ebenfalls die Auswertung von "internen" DOIF-Readings halte ich nicht für sinnvoll.

Dieser Einzeiler sollte schon ausreichen:

DOIF { if ([?Bewohner] eq "zuhause" and [?du_TTS:cnt] > 0 and ["^BM:motion"]) {::TTSSayQueue($device)}}

In TTSSayQueue kannst du den übergebenen Parameter unmittelbar auswerten, statt die Readings von DOIF.

Und wenn es nicht funktioniert, dann postest du am besten hier die Events der BMs.

Überholen kann sich da nichts.
Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF

Otto123

#6
Der Vorschlag von Damian ist hier Mist: ["^BM:motion"] triggert auch auf nomotion :( ich denke da ist  mein letzter Vorschlag aus #3 exakter
In deiner  Sub (nach Damians Vorschlag mit $device - entspricht meinem Vorschlag mit $NAME im notify)
so den Bewegungsmelder durch Übergabe haben:
sub TTSSayQueue($) {
my ($bm) = @_;
...
}
Viele Grüße aus Leipzig  ⇉  nächster Stammtisch an der Lindennaundorfer Mühle
RaspberryPi B B+ B2 B3 B3+ ZeroW,HMLAN,HMUART,Homematic,Fritz!Box 7590,WRT3200ACS-OpenWrt,Sonos,VU+,Arduino nano,ESP8266,MQTT,Zigbee,deconz

dk3572

Vielen Dank für eure Hilfe, aber was ist nun der bessere Weg?

Bei dem DOIF von Damian bekomme ich schon mal diesen Fehler:

error   condition c01: Too many arguments for main::TTSSayQueue,"

Wenn ich das Beispiel von Otto nehme,

([?Bewohner] eq "zuhause" && [?du_TTS:cnt] > 0 && ([BM_Wohnzimmer:"^motion"] or [BM_Kueche_Motion:"^motion"])) ({TTSSayQueue($NAME)}) DOELSE

wie baue ich das in der sub ein?

Otto123

Den Einzeiler von Damian habe ich nur teilweise verstanden, da kann ich zu dem Fehler nichts sagen.

Du nimmst nicht mein Beispiel, Du haust alles durcheinander  :-X
$NAME -> notify
$device -> DOIF

Wie Du den Parameter in die SUB einbaust habe ich doch geschrieben?
Viele Grüße aus Leipzig  ⇉  nächster Stammtisch an der Lindennaundorfer Mühle
RaspberryPi B B+ B2 B3 B3+ ZeroW,HMLAN,HMUART,Homematic,Fritz!Box 7590,WRT3200ACS-OpenWrt,Sonos,VU+,Arduino nano,ESP8266,MQTT,Zigbee,deconz

dk3572

sorry, habe mich vertan, du hast in der Tat das notify vorgeschlagen.
Leider bekomme ich dieses auch nicht hin.
Wenn ich es so versuche:

(BM_Wohnzimmer:motion.*|BM_Kueche_Motion:motion.*) {TTSSayQueue($NAME)}

erhalte ich diesen Fehler:

Too many arguments for main::TTSSayQueue at (eval 160856) line 1, near "$NAME)"

Wie muss das notify aussehen?

Otto123

#10
Hast Du denn die Sub geändert?

Siehe #6

Wenn Du ein notify probieren willst musst Du in der Sub noch die Zusatz Bedingungen einfügen!
Der Trigger ist nicht falsch aber nicht gut. Die Klammern braucht es nicht
BM_Wohnzimmer:motion.*|BM_Kueche_Motion:motion.*
So ist es kürzer und ich denke der Event ist doch exakt motion?
BM_.*:motion
Viele Grüße aus Leipzig  ⇉  nächster Stammtisch an der Lindennaundorfer Mühle
RaspberryPi B B+ B2 B3 B3+ ZeroW,HMLAN,HMUART,Homematic,Fritz!Box 7590,WRT3200ACS-OpenWrt,Sonos,VU+,Arduino nano,ESP8266,MQTT,Zigbee,deconz

dk3572

Danke noch mal für deine Hilfe.

Ich möchte zuerst das notify anlegen.
Dann kümmere ich mich um die sub.
Eins nach dem Anderen  ;)

Deine Version von notify mag zwar kürzer sein, aber ich habe noch einige Bewegungsmelder mehr die mit BM_ anfangen.

Und wo und wie ich den $NAME einfüge weiß ich leider auch noch nicht.
Ich halte bei meiner Schreibweise immer die Fehlermeldung.

Vielleicht kannst du mir ja doch noch weiterhelfen?

Danke und ein schönes Weihnachtsfest.

Beta-User

Wirf' den prototype weg...
sub subname { 

[...] 
return;
}
@Otto: neben prototype könntest du eventuell mal shift+"defined-or" statt @_ vertiefen ;) 
Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: ZigBee2mqtt, MiLight@ESP-GW, BT@OpenMQTTGw | ZWave | SIGNALduino | MapleCUN | RHASSPY
svn: u.a Weekday-&RandomTimer, Twilight,  div. attrTemplate-files, MySensors

dk3572

Notify sieht nun so aus:

(BM_Wohnzimmer:motion.*|BM_Kueche_Motion:motion.*) TTSSayQueue ($NAME)

Sub sieht so aus:

sub TTSSayQueue($) {
    my $text = '';
    my $cnt = ReadingsNum('du_TTS', 'cnt', 0);
    my ($bm) = @_;

    if ($cnt > 0) {

        for (my $i = 1; $i <= $cnt; $i++) {
            $text .= ReadingsVal('du_TTS', 'queue-' . $i, '') . '. ';
        }
   
    if ($bm eq "BM_Wohnzimmer"){
        fhem("set ECHO_G090LV03644201AX speak_ssml <speak>$text</speak>")}

    if ($bm eq "BM_Kueche_Motion"){
        fhem("set ECHO_G090P30874340EX4 speak_ssml <speak>$text</speak>")}

        fhem("deletereading du_TTS queue-.*");
        fhem("setreading du_TTS cnt 0");

    }
   
    return undef;
}


Steht folgende Warnung im Log:

PERL WARNING: Prototype mismatch: sub main::TTSSayQueue () vs ($) at ./FHEM/99_myTtsUtils.pm line 56

Ich lese mir hier im Forum viel an, studiere Wiki´s und probiere aus.
Leider bin ich kein Programierer und daher auf Hilfe angewiesen.
Ich bin auch dankbar für eure Mühe, aber die Andeutungen für die Ausführung helfen mir nicht weiter.

Mit Sicherheit ist es für euch Profis ein Klacks mein Anliegen umzusetzen.
Wäre also einer so nett und beschreibt etwas genauer wie das notify und wie die sub auszusehen hat?

Vielen lieben Dank dafür.

Beta-User

Wirf' den prototype GANZ raus und starte dann FHEM neu.

sub TTSSayQueue {
Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: ZigBee2mqtt, MiLight@ESP-GW, BT@OpenMQTTGw | ZWave | SIGNALduino | MapleCUN | RHASSPY
svn: u.a Weekday-&RandomTimer, Twilight,  div. attrTemplate-files, MySensors