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;
}
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
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.
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 ;)
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.
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.
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) = @_;
...
}
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?
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?
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?
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
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.
Wirf' den prototype weg...
sub subname {
[...]
return;
}
@Otto: neben prototype könntest du eventuell mal shift+"defined-or" statt @_ vertiefen ;)
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.
Wirf' den prototype GANZ raus und starte dann FHEM neu.
sub TTSSayQueue {
Ach Mann, ich bin doch auch nicht der Profi mit Übergaben in einer Perlsub. Ich habe das mal vor langer Zeit so gemacht wie beschrieben, ja ich habe in der Perl Ecke mitgelesen - aber wie es jetzt richtig ist oder einfach nur geht ... ;)
Ich lese mich jetzt mal hier durch https://perldoc.perl.org/perlsub bis ich da fertig bin mache ich keine neuen Vorschläge zur Übernahme von übergebenen Werten {Sub($NAME)} 8)
@dk3572
Zumindest geht das Eine nicht ohne das Andere - Du kannst nicht einen Aufruf machen {Sub($NAME)} ohne in der Sub dann auch diesen Übergabewert irgendwie "aufzunehmen".
Daher der Fehler wie in #9 ;)
Das letzte notify ist Quark - so war mein Vorschlag - den hast Du in meiner nicht ausformulierten Aussage offenbar falsch verstanden:
BM_.*:motion {TTSSayQueue ($NAME)}
@Beta-User Wozu muss man wenn man die 99_myUtils editiert FHEM neu starten?
ok, schwere Geburt, aber jetzt funktioniert es wie es soll.
(BM_Wohnzimmer:motion.*|BM_Kueche_Motion:motion.*) {TTSSayQueue ($NAME)}
Danke an alle und schöne Feiertage.
VG Dieter
Hallo Dieter,
Ich bleibe mal noch hartnäckig wegen der Klammer um das Suchmuster 8) und verlinke mal auf eine Diskussion. (https://forum.fhem.de/index.php?topic=115414.0)
Warum lässt Du die nicht weg?
(BM_Wohnzimmer:motion.*|BM_Kueche_Motion:motion.*)
funktioniert das so nicht?
BM_Wohnzimmer:motion.*|BM_Kueche_Motion:motion.*
Ist der Event nicht wirklich exakt motion? Wozu dann das "alles und Rest" hintendran .* ?
Funktioniert das nicht?
BM_Wohnzimmer:motion|BM_Kueche_Motion:motion
Noch zu meinem Link von oben, siehst Du den Unterschied wenn Du mal die beiden Ausdrücke getrennt in die Kommandozeile wirfst ?:
{notifyRegexpCheck('(BM_Wohnzimmer:motion.*|BM_Kueche_Motion:motion.*)')}
{notifyRegexpCheck('BM_Wohnzimmer:motion.*|BM_Kueche_Motion:motion.*')}
Auf alle Fälle Schöne Weihnachten!🎄
Otto
alles klar, habe es so abgeändert, funktioniert auch.
BM_Wohnzimmer:motion|BM_Kueche_Motion:motion {TTSSayQueue ($NAME)}
Danke nochmal.
Zitat von: Otto123 link=topic=117006.msg1113869#msg1113869
@Beta-User Wozu muss man wenn man die 99_myUtils editiert FHEM neu starten?
Das betrifft NUR den Fall, dass man was an Funktionen ändert, die mit prototype arbeiten und auch nur dann, wenn sich der prototype ändert; (jedenfalls hatte ich das mal irgendwo so aufgeschnappt).
Sonst funktioniert das Editieren von myUtils via FHEMWEB stressfrei, keine Sorge ;) .
HIER war es aber vermutlich der Grund, warum es erst nicht funktioniert hat beim Wechseln von () nach ($), was mich in dem Bauchgefühl bestätigt, dass PBP Recht damit hat, dass man im Zweifel lieber auf prototype verzichten sollte.
Und wenn meine Zwischenbemerkung zum Thema shift war nicht böse gemeint, man kann auch die @_-Variante nutzen (war nur, weil ich grade sowieso dabei war wg. dieser prototype-Geschichte). In "meinen" Modulen flog das aber fast überall raus zugunsten der shift-Schreibweise; die erlaubt es m.E. eleganter, gleich Ersatzwerte oder qualifizierte Rückgaben/Fehlermeldungen reinzubauen. Dann bekommt man statt "prototype missmatch" eben "we need a target device as argument" oder "you have to specify a target value" zurück oder kann was ins Log schreiben etc....
Bin sicher, du hast das mit dem Perl-"defined-or" ("//") binnen 15 Minuten intus :) .