Modul für Spracherkennung? (menschlichen Text in einen Befehl umsetzen)

Begonnen von Rince, 11 Dezember 2013, 18:37:13

Vorheriges Thema - Nächstes Thema

Kuzl

So ich hab jetzt mal bissl rumprobiert und heng an nem punkt :/
Also das ist jetz ein Code für die myUtils und eine Funktion, der einfach der String übergeben wird.
Der Text soll dann nach Schlagwörtern durchsucht werden und dann anhand der gefundenen Wörter ein Befehl gebastelt werden.
Das durchsuchen des Strings funktioniert schon mal.
###################################################################
###### Text auswerten

sub Text2Cmd {
my $text = $_[0];
my @suchworte = ("Licht","ein","aus");
my @gefunden;
my $i = 0;

foreach my $search (@suchworte){
if ($text =~ m/$search/i){$gefunden[i] = 1;}
else {$gefunden[i] = 0;}
$i++;
}

}


Bitte nicht streng sein mit den Klammern irgendwie ist da Perl ganz anders als C das verwirrt mich voll jetzt hab ich glaub ich bei if und else unnötige Klammern gesetzt :D
So also der Text wird für jedes Suchwort durchsucht und wenn gefunden, wird ein Flag im Array "gefunden" gesetzt. .... und jetzt? :D
ich bin mir nicht sicher, ob das der richtige Weg ist. Habt ihr Vorschläge?

Rince

Du suchst ob Licht, ein und aus in einem Text vorkommt?

Daraus wird sich kein Befehl basteln lassen, oder?
Du musst ja unterscheiden, ob es ein ODER aus ist.

Diese Funktion fürchte ich brauchen wir für jeden Zustand in einer eigenen Variablen (und jedes Gerät etc).
?
Wer zu meinen Posts eine Frage schreibt und auf eine Antwort wartet, ist hiermit herzlich eingeladen mich per PN darauf aufmerksam zu machen. (Bitte mit Link zum betreffenden Thread)

Kuzl

Jap in dem Array "Suchworte" sind einfach erst mal alle Worte drinnen, nach denen gesucht werden soll also z.b. Licht, ein, aus , an , dunkler, heller, bitte, steckdose, usw.
Für jedes dieser Wörter wird jetzt der Text durchsucht und die zugehörige Variable in dem Array "gefunden" wird auf 1 gesetzt. Da in einem Text hoffentlich nie "ein" und "aus" vorkommt, werden auch nie beide Variablen auf 1 stehen :D
So kann man dan prinzipiell herausfinden welche Wörter im Text vorkommen wenn z.b. in dem Code von oben "ein" im Text vorkommt und sonst nichts, so ist dann:
                               $gefunden[0] = 0 ;
                               $gefunden[1] = 1;
                               $gefunden[2] = 0;

Jetzt kann mann dann irgendwie abfragen, wo eine 1 eingetragen ist und so auf das Wort zurückführen, da ja $suchworte[1] = "ein";
Ich hoffe jetzt es es etwas klarer, wie ich das meine :)

Ab da weiß ich jetzt nicht mehr weiter... ich glaub für jedes der Suchworte benötigt man jetzt eine "IF" abfrage, die beinhaltet, was dann passieren soll, z.B. dass aus einem "ein" ein "set on" werden soll - ich weiß nicht wie man das schöner lösen kann.

Kuzl

Hallo ich hab bisschen weitergemacht und alles etwasgeändert:

###################################################################
###### Text auswerten

sub Text2Cmd {
my $text = $_[0];
my %hbefehl = (
              'an', 'on',
              'anschalten', 'on',
              'ein', 'on',
              'einschalten', 'on',
              'aus', 'off',
              'ausschalten', 'off',
              'heller', 'up',
              'dunkler', 'down' );
my @abefehl = %hbefehl;
my $anzahlbefehle = keys %hbefehl;
my %hgeraet = (
              'Licht', 'Licht',
              'TV', 'TV',
              'Beleuchtung', 'LEDstripe',
              'Computer' , 'PC' );
my @ageraet = %hgeraet;
my $anzahlgeraete = keys %hgeraet;
my $i = 0;
my $cmd = "set";


for($i=0,$i<$anzahlgeraete,$i=$i+2){
    if ($text =~ m/$ageraet[$i]/i){$cmd= $cmd . $ageraet[$i+1];
       Log 3 , "Gerät gefunden";
    }
}

for($i=0,$i<$anzahlbefehle,$i=$i+2){
    if ($text =~ m/$abefehl[$i]/i){$cmd= $cmd . $abefehl[$i+1];
       Log 3 , "Befehl gefunden";
    }
}
return $cmd;
}


Zur Erklärung: Man kann die Wörter und die zugehörigen Befehle oben in die 2 Hashes definieren. Anschließend wird der Text erst nach dem Gerät durchsucht, und dann an $cmd angehängt. Das gleiche passiert mit den Befehlen und dann sollte man einen fertigen fhem Befehl haben.
Allerdings wenn ich der Funktion einen Text übergebe, der z.b. licht und an enthält, wird mir im Log nichts geschrieben und an $cmd wird auch nichts hinzugefügt. Kann sich das mal jemand durchsehen und schaun, ob er einen Fehler findet, den ich nicht bedacht habe?

Hab noch nie was mit Perl gemacht und die Sprache auch erst mit FHEM vor ca. 3 Wochen kennengelernt bitte nicht zu streng sein :D

EDIT: Ok einen Fehler hab ich gefunden. Es muss in den For-Schleifen heißen $anzahlgeraete*2 und das gleiche bei befehle.
     
Allerdings immer noch das gleiche Problem.

Kuzl

So gibt schon mal was neues von mir :) also jetzt kann man der Funktion einen Text übergeben und sie gibt dann einen FHEM-Befehl zurück :)
Hab heute mal Zeit gefunden den Fehler zu suchen und.... es waren nur anstatt der "," in den for schleifen ein ";" zu setzen  ::)
Oben können die Suchwörter und die Zugehörigen "Übersetzungen" eingegeben werden
So der nächste Schritt ist, das ganze etwas schöner und Übersichtlicher zu machen und anstadt des "return" den befehl an fhem zu setzen was mit einer Codezeile schon umsetzbar sein sollte :D wer will kanns mal ausprobieren;)

###################################################################
###### Text auswerten

sub Text2Cmd {
my $text = $_[0];
my %hbefehl = (
              'an', 'on',
              'anschalten', 'on',
              'ein', 'on',
              'einschalten', 'on',
              'aus', 'off',
              'ausschalten', 'off',
              'heller', 'up',
              'dunkler', 'down' );
my @abefehl = %hbefehl;
my $anzahlbefehle = keys %hbefehl;
my %hgeraet = (
              'Licht', 'Licht',
              'TV', 'TV',
              'Beleuchtung', 'LEDstripe',
              'Computer' , 'PC' );
my @ageraet = %hgeraet;
my $anzahlgeraete = keys %hgeraet;
my $i = 0;
my $cmd = "set";

{use Data::Dumper;; Log 3, "Geräte: ".Dumper($anzahlgeraete)};
{use Data::Dumper;; Log 3, "Befehle: ".Dumper($anzahlbefehle)};
{use Data::Dumper;; Log 3, "Text: ".Dumper($text)};


for($i=0;$i<($anzahlgeraete*2);$i=$i+2){
    if ($text =~ m/$ageraet[$i]/i){
       $cmd= $cmd . " " . $ageraet[$i+1];
       Log 3 , "Gerät gefunden";
    }
}

for($i=0;$i<($anzahlbefehle*2);$i=$i+2){
    if ($text =~ m/$abefehl[$i]/i){
       $cmd= $cmd . " " . $abefehl[$i+1];
       Log 3 , "Befehl gefunden";
    }
}
# das zum Testen in den Code einfügen => fhem($cmd);
return $cmd;
}


Viele Grüße
Kuzl

siggi85

Unabhängig davon, dass mal selber eine Routine in perl schreiben kann, finde ich die Steuerung von FHEM über Sprache am besten mit einem Android Gerät durch die Kombination von Tasker mit Auto-Voice Plugin und AndFHEM.
Über Tasker mit Autovoiceplugin Profile definieren und dann einen oder mehrere Befehl(e) über Tasker-AndFHEM-Plugin auslösen. Wenn man auf einen Rückgabewert reagieren möchte, dann kann man auch eine GET Abfrage Richtung FHEM machen und die Taskervariable %HTTPR auswerten (zB Temperaturansage).

einige Vorteile von Autovoice:
- versucht aus dem gesagten mehrere mögliche "Resultate" zu interpretieren
- man kann mehrere Befehle gleichzeitig ansagen
- es kann über Google Now benutzt werden (gleichzeitig diverse Fragen, persönliche Daten abfragen wie Kalender und Heimsteuerung)
- es kann über Bluetoothheadset genutzt werden

Ich nutze FHEM erst seit ein paar Tagen, aber ein paar Kommandos habe ich mir schon zusammen gebaut.

Kuzl

Hallo siggi,
Jap, so eine Routine siehst du ja oben :D
ich selbst benutze für die Sprachsteuerung auch Tasker - allerdings ohne das Auto-Voice plugin, geht genau so.
Außerdem gibt es eine eigene FHEM-Browser-App, die die Sprachsteuerung unterstützt.
Allerdings gibt es bei diesen 2. Varianten zwei Probleme:
1. Jeder Befehl muss einzeln extra definiert werden.
2. man muss trotsdem immer den exakten Wortlaut in dem Geredeten einbauen (ausnahme Regex, siehe weiter oben)

Deswegen hab ich diese Routine oben geschrieben, die übrigens sogar ganz gut funkioniert :)
Ich selbst nutze aber so lange, bis man mit Tasker Variablen an FHEM übergeben kann weiter die Tasker-Variante, da ich die Befehle sowiso habe weil ich auch über meine Smartwatch steuere :)
Demnächst wird aber auch der Raspberry auf Voice-Steuerung mit einem Raummicro aufgebaut und dann im Zusammenhang mit der Routine  verwendet :D

Viele Grüße
Kuzl

siggi85

Zitat von: Kuzl am 27 Januar 2014, 17:11:51
Demnächst wird aber auch der Raspberry auf Voice-Steuerung mit einem Raummicro aufgebaut und dann im Zusammenhang mit der Routine  verwendet :D

Das habe ich vor einem Jahr auch angefangen. Vorlage war Jarvis aus Iron Man. ;) Funktionierte auch mit vielen selbst gebauten Modulen. (Netzwerkscans, Radio/Videos anmachen, XBMC steuern, WOL Geräte ansteuern und Status abfragen, etc.) Das eigene programmieren von allen benötigten Schnittstellen ist jedoch alleine sehr mühsam und muss ständig gepflegt werden, daher habe ich momentan große Freude an FHEM. :)
Ich will demnächst anschauen wie man Audio von Raspbian (mein FHEM Server) auf AirPlay Lautsprecher bekommt. In den Haupträumen einen Airplaylautsprecher und man kann von überall über wichtige Events im Haus informiert werden (jemand an der Tür -> IP Cam anschauen, Freundin kommt gleich nach Hause, etc). Nebenbei auch Radio hören möglich. :P

Ich hoffe später auf eine Tasker- und FHEM version für Google Glass und werde so wohl endlich meine portable sprachgesteuerte Heimsteuerung haben. Momentan mit Bluetoothheadset funktioniert auch, aber ein Bildschirm im Sichtfeld gibt einige neue Möglichkeiten als nur auf Sprachausgabe zu setzen. :)

Sorry für die Plauderei, hier gehts ja um ein Wunschmodul. Man schreibt sich in anderen Threads. ;)

Kuzl

Bei mir soll der Raspberry dann einfach den Text an FHEM senden und dann wird er dort weiterverarbeitet dann spare ich mir die ganze Pflegerei :) ausgegeben wird der Text dann mit dem Text2Speech Modul. Das ist nebenbei für dich auch interessant, da man dort wählen kann, dass der auszugebende Text als MP3 gespeichert wird. Ebenfalls ist gerade ein DLNA-Modul (ähnlich Airplay) am entstehen, was deine Idee in der Kombination auch umsetzbar macht :D Warscheinlich wirds allerdings auch sehr viel einfacher gehen :D

Rince

Da ich zur Zeit mit 64kBit surfe, ist die Spracherkennung bei mir zur Zeit eher problematisch ;)

Sobald ich wieder vernünftig online bin, sehe ich es mir gerne an  :)
Wer zu meinen Posts eine Frage schreibt und auf eine Antwort wartet, ist hiermit herzlich eingeladen mich per PN darauf aufmerksam zu machen. (Bitte mit Link zum betreffenden Thread)

Kuzl


der-Lolo


Kuzl

Ich bräuchte weitere ideen :D
Der ursprüngliche zweck eine menschliche sprache beliebig und unabhängig von der grammatik auszuwerten erfüllt diese funktion und sie ist an beliebiger stelle aus fhem aufrufbar.
Wenn du einer Idee hast immer her damit :)

der-Lolo

Achso, ok - ich dachte es wäre noch Baustelle...
Sieht ja gar nicht Soooo aufwendig aus - auf den ersten Blick vermisse ich wärmer und kälter, lauter und leiser. Oder auch Mengen wie viel oder ein bisschen.
Mach bitte viel leiser wäre -10db etwas leiser vielleicht dann -2db oder so.
Nächster Titel wäre auch noch Schick.
Wenn ich deinen Code aber anschaue sollte es doch auch einfach möglich sein es selbst zu erweitern...

Kuzl

Jap genau kann man sich anpassen wie man will einfach oben das schlüsselwort und dahinter das, was beim set-befehl hinter dem device stehen würde :)
so kann man sich eigendlich alles eintragen was man will