[erledigt] doif zum sammeln oder als warteschlange verwenden?

Begonnen von the ratman, 07 Dezember 2021, 11:34:15

Vorheriges Thema - Nächstes Thema

the ratman

hiho,

ein paar infos:

ich hab mir ein doif zum verteilen von informationen gebaut. dieses sagt und zeigt texte auf verschiedenen endgeräten nach z.b. zeit oder hauszustand an. das funzt auch schon seit ewig und 3 tagen genau so, wie ich es will.

in diesem doif gibt's ein reading "text", dass mit den infos befüllt wird. nach jeder abarbeitung von "ernsthaften" infos wird dieses reading "text" wieder mit "nichts" gefüllt.
wird also eine ansage erfolgreich erledigt und das reading mit "nichts" befüllt, weiß ich nicht mehr, was als letzte info ausgegeben wurde.
kommen mehrere ansagen gleichzeitig, kann so schon mal eine info untergehen.

meine bitte um hilfe lautet:

idee (a) - eine liste der letzten infos erstellen

also eine kleine liste der letzten ausgegebenen infos mit gut lesbarer uhrzeit, wann sie gesendet wurden. natürlich ohne die versionen in denen "nichts" drinnen steht.
wenn dann eine bestimmte menge an texten in der liste steht, sollte diese "weiter gerückt" werden. also: der erste text verschwindet, dafür rückt der neue unten nach.
die liste ist rein zur ansicht gedacht, muss also nicht in irgendwelchen dateien gespeichert werden und muss auch nicht mein allmorgendliches fhem-update überleben.

idee (b) - erstellen einer warteschlange und abarbeiten der selben

dazu hab ich nicht mal einen ansatz *g*


geht a oder b in einem doif für dumme (also möglichst ohne perl und idiotensicher) ?
ich hab von programmieren 0 ahnung. was also über 1 zeile code mit erklärung raus geht und eventuell auch noch verknüpfen mehrerer infos beinhaltet, geht eindeutig über meinen horizont hinaus.
→do↑p!dnʇs↓shit←

xenos1984

Vielleicht lässt sich damit eine Warteschlange einrichten?

http://fhem.de/commandref_DE.html#DOIF_Device-Variablen

Idee wäre in etwa: Wenn ein neuer Text reinkommt, wird der in die Warteschlange (Device-Variable als Liste) geschrieben. Wenn gerade keine Sprachausgabe läuft, wird sie mit dem ältesten Text gestartet und der Text aus der Schlange genommen, ansonsten passiert nichts. Wenn die Sprachausgabe beendet ist, wird geschaut, ob noch Texte in der Schlange sind, und wenn ja, wird der nächste abgearbeitet.

Eine Liste sollte damit doch auch gehen...

Alternativ kann man die Informationen bestimmt auch in Readings abspeichern.

frank

modul readingsHistory erstell entsprechende listen.
FHEM: 6.0(SVN) => Pi3(buster)
IO: CUL433|CUL868|HMLAN|HMUSB2|HMUART
CUL_HM: CC-TC|CC-VD|SEC-SD|SEC-SC|SEC-RHS|Sw1PBU-FM|Sw1-FM|Dim1TPBU-FM|Dim1T-FM|ES-PMSw1-Pl
IT: ITZ500|ITT1500|ITR1500|GRR3500
WebUI [HMdeviceTools.js (hm.js)]: https://forum.fhem.de/index.php/topic,106959.0.html

the ratman

#3
thx schonmal

@xenos - muss ich in ruhe ansehen und vor allem kapieren.
das mit den readings hab ich auch schon gedacht. (mein) problem dabei ... wie schiebe ich die weiter?
ich habe dann z.b. reading "1text" bis "5text". kommt text nr. 6 muss 1 raus, 2 zu 1, ..., 6 zu 5 werden. würde wohl wieder nicht ohne programmier kenntnisse was werden. "rollen" will ichs auch nicht, also dass 6 automatisch 1 wird.

@frank - ich bin bisher um das modul herum gekommen und wollt das eigentlich so lassen. in dem fall ist das aber tatsächlich schon der notfallplan, sobald mir einige leute hier klar gemacht haben, dass ichs mit doif nicht schaffe.
→do↑p!dnʇs↓shit←

Damian

Zitat von: the ratman am 07 Dezember 2021, 13:47:17
thx schonmal

@xenos - muss ich in ruhe ansehen und vor allem kapieren.
das mit den readings hab ich auch schon gedacht. (mein) problem dabei ... wie schiebe ich die weiter?
ich habe dann z.b. reading "1text" bis "5text". kommt text nr. 6 muss 1 raus, 2 zu 1, ..., 6 zu 5 werden. würde wohl wieder nicht ohne programmier kenntnisse was werden. "rollen" will ichs auch nicht, also dass 6 automatisch 1 wird.

@frank - ich bin bisher um das modul herum gekommen und wollt das eigentlich so lassen. in dem fall ist das aber tatsächlich schon der notfallplan, sobald mir einige leute hier klar gemacht haben, dass ichs mit doif nicht schaffe.

Tja da wird man schon ein paar Perlkenntnisse brauchen.

Bsp:

defmod di_shift DOIF {\
push (@{$_msg},[test:bla]);;\
shift (@{$_msg}) if (@{$_msg}== 6);;\
set_State("@{$_msg}");;\
}

Testen kannst du es mit

setreading test bla irgendwas

test ist ein dummy

die Queuetiefe ist hier 6. Im Array befinden sich die letzten sechs Inhalte des Readings bla von test. Das Array wird hier im Status angezeigt.

Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF

jkriegl

Noch ein Beispiel als stack in einem userReading
stack_JET:JET-e10:.* {
my @words=split/ /, ReadingsVal($name,"stack_JET","");
my $price=ReadingsVal($name,"JET-e10",0);
my $time=substr(ReadingsTimestamp($name,"JET-e10","0"),11,5);
push(@words, $time); push(@words, $price);
if(my $i=@words>8) {my $first=shift @words; $first=shift @words;}
return("@words");}

Sieht dann so aus (für 4 Einträge):
stack_JET 15:32 1.559 16:52 1.549 17:12 1.529 17:32 1.549
Rpi 3, Fhem, Cul 868, HM-CC-RT-DN, HM-Sec-Sco, HM-ES-PMSw1-Pl, ebus (Vaillant), ECMD, Telegram, HTTPMOD, Xiaomi, Shelly

xenos1984

Ich habe mal etwas an der Warteschlange und Sprachausgabe programmiert, und es scheint zu funktionieren:


defmod di_speak DOIF subs {\
sub speak_exec\
{\
my $arg = shift;;\
my ($lang, $text) = split("\\|", $arg);;\
system("ssh pi\@deimos 'espeak -v$lang \"$text\"' > /dev/null 2>&1");;\
return 0;;\
}\
\
sub speak_done\
{\
my $ret = shift;;\
if($ret)\
{\
Log3("$SELF", 2, "Speak aborted.");;\
}\
\
fhem("set di_speak done")\
}\
\
sub speak_next\
{\
my $arg = shift @{$_queue};;\
my ($vol, $lang, $text) = split("\\|", $arg);;\
set_Reading('cur_volume', $vol, 1);;\
set_Reading('cur_language', $lang, 1);;\
set_Reading('cur_text', $text, 1);;\
fhem_set("deimos_amixer_pcm $vol");;\
$_pid = ::BlockingCall('DOIF::speak_exec', "$lang|$text", 'DOIF::speak_done', 120, 'DOIF::speak_done', 1);;\
}\
}\
\
init {\
my @arr = ();;\
$_queue = \@arr;;\
set_Reading('cur_volume', '-', 1);;\
set_Reading('cur_language', '-', 1);;\
set_Reading('cur_text', '-', 1);;\
set_State('empty');;\
}\
\
done {\
delete $_pid;;\
\
if(@{$_queue})\
{\
speak_next();;\
}\
else\
{\
fhem_set("deimos_amixer_pcm $_vol_pcm");;\
fhem_set("deimos_vlc volume $_vol_vlc");;\
set_Reading('cur_volume', '-', 1);;\
set_Reading('cur_language', '-', 1);;\
set_Reading('cur_text', '-', 1);;\
set_State('empty');;\
}\
}\
\
text {\
my $arg = [?$SELF:volume] . '|' . [?$SELF:language] . '|' . [$SELF:text];;\
push @{$_queue}, $arg;;\
if(get_State() eq 'empty')\
{\
$_vol_pcm = ReadingsNum('deimos_amixer_pcm', 'state', 0);;\
$_vol_vlc = ReadingsNum('deimos_vlc', 'volume', 0);;\
fhem_set("deimos_vlc volume 0");;\
set_State('speaking');;\
speak_next();;\
}\
}
attr di_speak devStateIcon empty:speach_control@red\
speaking:speach_control@lime
attr di_speak icon helper_doif
attr di_speak readingList volume language text
attr di_speak room Logic->DOIF
attr di_speak setList volume:slider,0,1,100\
language:de,en,et\
text:textField


Zur Erläuterung: Das DOIF triggert (nur) auf das Reading text. Wenn man dort einen Text reinschreibt, wird der in $_queue abgespeichert (zusammen mit der aktuell eingestellten Lautstärke und Ausgabesprache). Wenn gerade keine Sprachausgabe aktiv ist, wird selbige angestoßen. (Außerdem schalte ich den VLC auf stumm und merke mir die alte Lautstärke.) Die eigentliche Sprachausgabe wird dann als BlockingCall ausgeführt (in dem Fall mit espeak). Wenn die beendet ist, wird überprüft, ob noch andere Texte in der Warteschlange sind, und dann entweder der nächste ausgegeben, oder die Ausgabe beendet (und die alte Lautstärke wiederhergestellt). Der Status des Geräts zeigt den aktuellen Zustand an, außerdem enthält cur_text den aktuell gesprochenen Text.

Man könnte natürlich auch noch eine Liste der zuletzt ausgegebenen Texte als Reading einbauen.

@Damian: In DOIF-Perl kann man vermutlich keine Referenz auf ein leeres Array mit [] erstellen, oder? Ich vermute, das wird als Reading interpretiert.

the ratman

wow - vielen dank leute!

da würd ich mich eventuell doch drüber trauen.

@Damian
ich darf dein stück als "warteschlange" interpretieren?
dann würde mir da wohl nur mehr der "nichts" filter fehlen. richtig?
und du müsstest mir erklären, wo und wie ich "[test:bla]" her bekomme.

@jkriegl
wo müsste müsste ich das rein kloppen?
wenn man das mehrzeilig hinbekommen würde, hätte ich dafür auch einsatzzwecke. so listen könnt ich schon gut gebrauchen *g*

@xenos1984
ja, wenn ich programmieren könnte, hät ichs sicher genau so gemacht *g*
bei mir ists allerdings eine windoof-nas, die per winconnect bespielt wird. vor allem, weil das die einzig mir bekannte art ist, den tts-inhalt nicht in googles, amazons, ... ohren zu blasen.
funzt dann so: winconnect - tts - player geht an - ansage - player geht aus = kein task mehr da = ausgabe fertig.
bzw. wart ich einfach ne zeit, weil die task-prüfung manches mal nicht grade flott geht.
→do↑p!dnʇs↓shit←

Damian

Zitat von: the ratman am 08 Dezember 2021, 09:28:00
@Damian
ich darf dein stück als "warteschlange" interpretieren?
dann würde mir da wohl nur mehr der "nichts" filter fehlen. richtig?
und du müsstest mir erklären, wo und wie ich "[test:bla]" her bekomme.

ja, mein Vierzeiler ist zwar ein Beispiel auf das Device "test" und das Reading "bla", aber es funktioniert genauso gut mit einem anderen Devicenamen und einem anderen Reading. [test:bla] ist hier ja gleichzeitig der Trigger für die Ausführung des Blocks - das ist natürlich DOIF-spezifisch und würde z.B. in myUtil nicht funktionieren. Auch die umständliche Schreibweise eines Array @{$_msg} statt @msg ist der Tatsache geschuldet, dass DOIF hier intern Devicevariablen mit hash nutzt, damit das Array nach der Abarbeitung nicht verloren geht, sondern im DOIF-Device weiter lebt.

Was man mit der Liste dann macht, ist eine andere Sache. Ich habe einfach das Array im Status anzeigen lassen, um zu schauen, ob es funktioniert.
Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF

the ratman

ach so, also nur ne liste - verstehe.
da hängt also noch mehr dran, wollte ich damit eine zeitversetzte ausgabe machen.

nachdem ich jetzt schon das bissl code falsch verstanden hab, tendiere ich immer mehr zum modul readingshistory und knall einfach ne liste meiner holden auf den bildschirm - ganz ohne perl (hoff ich), wenn's wieder fragt, was die computer-tante grad gesagt hat *g*

ich probier das mal - und wenn alle hier zufrieden sind, vergess ich, dass ich hier je gefragt hab *g*

vorerst mal vielen, vielen dank für eure hilfe!
→do↑p!dnʇs↓shit←

Damian

Zitat von: the ratman am 08 Dezember 2021, 15:18:40
ach so, also nur ne liste - verstehe.
da hängt also noch mehr dran, wollte ich damit eine zeitversetzte ausgabe machen.

nachdem ich jetzt schon das bissl code falsch verstanden hab, tendiere ich immer mehr zum modul readingshistory und knall einfach ne liste meiner holden auf den bildschirm - ganz ohne perl (hoff ich), wenn's wieder fragt, was die computer-tante grad gesagt hat *g*

ich probier das mal - und wenn alle hier zufrieden sind, vergess ich, dass ich hier je gefragt hab *g*

vorerst mal vielen, vielen dank für eure hilfe!

xenos1984-Lösung war aber schon viel detaillierter, inclusive Sprachausgabe, aber wenn es schon Module dafür gibt, dann wird es wohl eine allgemeinverständliche Doku dazu geben :)
Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF

the ratman

ja, nur müsste ich xenos version und meine vorhandenen teile total umschreiben, weil ja bis auf die liste schon alles existiert - das wäre für mich noch schwerer, als frischer code.
wie gesagt: ich versteh nix vom programmieren, kann mir immer nur denken, was ne zeile code bedeuten könnte und liege dabei ja noch zu 90% falsch ... ich will aber zumindest das, was ich verwende halbwegs kapieren, sonst endet jedes kleine problem in einer fragestunde hier.

naja, es gibt readingshistory, die kann auch ne liste bauen für mich. aber da happerts scheinbar an den nicht vorhandenen formatierungsmöglichkeiten, stell ich die letzte halbe stunde fest.
→do↑p!dnʇs↓shit←

Ellert

Zitat von: the ratman am 08 Dezember 2021, 16:13:21
ja, nur müsste ich xenos version und meine vorhandenen teile total umschreiben, weil ja bis auf die liste schon alles existiert - das wäre für mich noch schwerer, als frischer code.
wie gesagt: ich versteh nix vom programmieren, kann mir immer nur denken, was ne zeile code bedeuten könnte und liege dabei ja noch zu 90% falsch ... ich will aber zumindest das, was ich verwende halbwegs kapieren, sonst endet jedes kleine problem in einer fragestunde hier.

naja, es gibt readingshistory, die kann auch ne liste bauen für mich. aber da happerts scheinbar an den nicht vorhandenen formatierungsmöglichkeiten, stell ich die letzte halbe stunde fest.
Irgendwo in deiner vorhandenen Lösung löst Du die Ansage aus (Befehl 1) und setzt  das Reading text auf nichts (Befehl 2).
Zwischen Befehl 1 und Befehl 2 kannst Du das Reading text durch beliebig viele Zwischenspeicherreadings (text1, text2...) schieben.
Bei zwei Zwischenspeicherplätze: setreading $SELF text2 [$SELF:text1],setreading $SELF text1 [$SELF:text],

the ratman

upps, das [erledigt] vergessen *g*

wird nun dank frank mit readingshistory und einem notify fürs speichern derselben erledigt.
--> https://forum.fhem.de/index.php/topic,124672.0.html
→do↑p!dnʇs↓shit←