Hallo zusammen,
für ein Modul zur Sprachsteuerung (https://forum.fhem.de/index.php/topic,89548.0.html) soll der User per Attribut Callback Funktionen konfigurieren können,
um FHEM abseits der normalen Abfragen/Steuerbefehle auf komplexere Fragen antworten zu lassen.
Da ich weder ein alter Hase bin was die FHEM Entwicklung angeht, noch der große Perl Profi,
frage ich mich was der sauberste Weg ist die Userfunktionen aufzurufen und einen FHEM Crash zu verhindern falls sie nicht exisitert.
Mal ein Beispiel wie das aussehen soll:
Der User fügt dem Attribut userIntents z.B. diese Zeile hinzu:
CalcIntent=myCalcSub(Number1,Operator,Number2)
Sagt der Anwender nun Rechne 4 plus 5, würde das Modul einen neuen Aufruf vom Typ "CalcIntent" bekommen.
Dazu die Werte für die Slots Number1, Operator und Number2.
Er müsste dann in seiner 99_myUtils eine sub erstellen die etwa so aussehen könnte:
sub myCalcSub($$$) {
my ($val1, $operator, $val2) = @_;
my result = "Sorry, außer zwei Zahlen zu addiere kann ich bisher leider noch nichts.";
if (looks_like_number($val1) && $operator eq "plus" && looks_like_number($val2) {
$result = "Das Ergebnis ist " . ($val1 + $val2);
}
return $result;
}
Funktionieren würde das sicher mit dem "fhem" Perbefehl und in diesem dann wieder auf Perl zurückwechseln:
fhem("{myCalcSub($number1,$operator,$number2}");
Aber das ist kommt mir das innerhalb eines Moduls irgendwie nicht so ganz State of Art vor. ;)
Oder ist es durchaus legitim aus einem Modul heraus per fhem("..."); auf die FHEM Ebene zu wechseln?
Pack den Aufruf der Funktion in ein eval.
Zitat von: Thyraz am 24 Juli 2018, 11:28:23
Funktionieren würde das sicher mit dem "fhem" Perbefehl und in diesem dann wieder auf Perl zurückwechseln:
Das ist absoluter Quatsch. fhem() ist kein perl
befehl, sondern eine von FHEM bereitgestellte perl-Funktion, der man
FHEM-Befehle übergeben kann.
Bevor Du solche Zusammenhänge nicht verstanden hast, solltest Du nicht darüber nachdenken, eine Modul für FHEM zu schreiben.
Und wenn ich hier lese, was Du da mit Attributen und usereigenen Funktionen vorhast, wird mir einfach nur schlecht.
Irgendwie war ich mir schon zu 100% sicher, dass dieser Beitrag von dir kommen wird Udo. :)
Allerdings hatte ich neben dem Zerriss auf etwas mehr zufällig beigestreute Informationen gehofft.
Ich kann dich beruhigen, der Unterschied zwischen einer Perl-Funktion und einem FHEM Befehl ist mir durchaus bewusst.
Den Vorschlag erst dann Perl zu programmieren, wenn ich ein Perl-Profi bin kann ich leider nicht annehmen,
da dies dann nie eintreten würde und ich schon viel zu alt bin um ewig zu warten.
Es zwingt einen aber niemand das Modul zu nutzen. ;)
Über Vorschläge wie man solch ein flexibles System einfacherer abbildet, bei dem der User die Kommunikation mit einem Sprachassistenten praktisch frei programmieren kann, bin ich immer dankbar.
Die Vorgehensweise über Attribut und usereigene Funktionen ist übrigens inspiriert vom AlexaFhem Modul von Andre, welches das auch so löst.
Ich hatte gehofft hier ein wenig Standardisierung und eine einfachere Einarbeitung für Nutzer die bereits die anderen Module kennen zu erreichen.
Beste Grüße,
Tobias
@Leon danke, damit scheint es zu funktionieren.
Gibt es an dieser Version Einwände?
my $val1 = 4;
my $val2 = 5;
my $operator = "plus";
my $result;
my $nameOfSub = "myCalcSub";
eval {
no strict 'refs';
$result = $nameOfSub->($val1,$operator,$val2);
};
if ($@) {
# Something went wrong...
}
Danke schonmal. :)
Hallo Tobias,
zum Aufruf von Kommandos aus einem Modul heraus kannst du AnalyzeCommand oder AnalyzeCommandChain aus der API verwenden. siehe https://wiki.fhem.de/wiki/DevelopmentModuleAPI
Im DbRep verwende ich das Konstrukt für die Abarbeitung einer User eigenen Routine des Attributes userExitFn. Siehst du auch im Modul in der Sub DbRep_userexit.
Vielleicht auch eine Anregung für eigene Experimente.
VG
Heiko
Zitat von: DS_Starter am 24 Juli 2018, 13:40:48
Hallo Tobias,
zum Aufruf von Kommandos aus einem Modul heraus kannst du AnalyzeCommand oder AnalyzeCommandChain aus der API verwenden. siehe https://wiki.fhem.de/wiki/DevelopmentModuleAPI
Im DbRep verwende ich das Konstrukt für die Abarbeitung einer User eigenen Routine des Attributes userExitFn. Siehst du auch im Modul in der Sub DbRep_userexit.
Vielleicht auch eine Anregung für eigene Experimente.
VG
Heiko
Finde ich persönlich sogar noch viel sauberer.
Stimmt, das wäre auch noch eine schöne Lösung. :)
Danke euch.
Die "offizielle" Alternative zu eval ist AnalyzePerlCommand.
Vorteile:
- prueft die Authorisierung, wenn man $cl spezifiziert hat (man kann mit allowed die Ausfuehrung von perl untersagen)
- setzt $we (siehe holiday2we) und $hms,$sec,$min,...
- falls der ausgefuehrte Code eine Perl-WARNING produziert, dann wird zusaetzlich auch der ausgefuehrte Befehl geloggt.
fhem("") ist mehr oder weniger nur der Aufruf von AnalyzeCommandChain().
Danke für den Hinweis Rudi. AnalyzePerlCommand fehlt noch in der DevelopmentModuleAPI Beschreibung wenn ich mich nicht verguckt habe.
Wenn ich daran denke würde ich es im Wiki ergänzen und vllt. schaut dann noch einer drüber um sicher zu gehen dass ich keinen Mist geschrieben habe.
Zitat von: DS_Starter am 24 Juli 2018, 14:58:13
Wenn ich daran denke würde ich es im Wiki ergänzen und vllt. schaut dann noch einer drüber um sicher zu gehen dass ich keinen Mist geschrieben habe.
Gib mal bitte Bescheid wenn Du soweit bist. Dann schaue ich es mir gerne an.
Hallo Leon,
habe in https://wiki.fhem.de/wiki/DevelopmentModuleAPI#AnalyzePerlCommand etwas zum Thema geschrieben.
Kannst mal bitte drüberschauen und ggf. abändern/ergänzen.
Grüße
Heiko
Hallo Heiko,
Habe es mir durchgelesen und klingt für mich verständlich. Vielen Dank für Deine tolle Arbeit.
Grüße
Leon.