Autor Thema: [39_Talk2Fhem.pm] Flexible Sprachsteuerunghilfsmodul  (Gelesen 30521 mal)

Offline klausw

  • Developer
  • Hero Member
  • ****
  • Beiträge: 1843
Antw:Flexibles Sprachanalysescript
« Antwort #30 am: 17 Dezember 2017, 16:45:19 »
Hallo Phill

muss hier mal mitlesen.  8)

Konfiguration:
Momentan muss das Script leider noch direkt in der Moduldatei konfiguriert werden. Wird auf jeden Fall ausgelagert die Frage ist nur wo die Reise eigentlich hingeht. Vorschläge dazu werden gerne angenommen.

Bisher habe ich die Posts bisher nur mal überflogen...
Eine Konfigurationszeile ist immer für ein Device, oder?
In diesem Fall könntest du über userattr gehen.
Alle Devices bekommen ein neues Attribut in dem die Konfigurationszeilen für dieses Modul abgelegt werden.

Grüße
Klaus

RasPi B v2 mit FHEM 18B20 über 1Wire, LED PWM Treiber über I2C, Luchtdruck-, Feuchtesensor und ein paar Schalter/LED\'s zum testen
Module: RPI_GPIO, RPII2C, I2C_EEPROM, I2C_MCP23008, I2C_MCP23017, I2C_MCP342x, I2C_PCA9532, I2C_PCF8574, I2C_SHT21, I2C_BME280

Offline Phill

  • Developer
  • Full Member
  • ****
  • Beiträge: 406
  • Langsam wird'n Schuh d'raus.
    • iVDR
Antw:Flexibles Sprachanalysescript
« Antwort #31 am: 17 Dezember 2017, 20:23:28 »
Eigentlich gehe ich eher davon aus das alles über ein device konfiguriert wird.
Ich überlege gerade krampfhaft was besser ist. Aber jetzt mal nur die Situation wie kommt der Satz zu dem device.
hab ich eins mach ich das über ein set fhemtalk "hier der satz"
habe ich mehrere wäre das ziemlich aufwendig, und ich müsste dem device sagen auf welches Ereignis er triggern soll, dann würde aber in allen devices das gleiche "notify" konfiguriert werden müssen und wenn der text aus unterschiedlichen Quellen kommt würde es das auch erschweren.
Oder?

Ich muss jetzt auch für mich mal Auflisten was alles Konfiguriert werden muss.
1. Die Regex Kommandozuordnung. in der Definition sage ich jetzt mal
2. Die Schlüsselwörterlisten, wie Räume, Farben, Geräte, Personen usw... wohl ein userattr
    Momentan gibt es nur eine Liste, den Array @rooms. Das Wollte ich aber noch erweitern.
    Wobei eine Liste schon mal Grundsätzlich alle Räume in FHEM enthalten könnte.
3. Die Übersetzungsliste(n). Also welcher Text ein Schlüsselwort ersetzen soll.
    Wohnzimmer wird zu "wz" oder Farbe wird zu einer Zahl.
    Das lässt sich in (1.) konfigurieren. Also in dem Annonyme Array [ ] hinter "$n".
    Welche Schlüsselwortliste gerade aktiv ist könnte im Regex vorne definiert werden fällt mir gerade ein.
Bsp:
'licht (im|in der) (@rooms) (\S*)' => 'set li_$2["soheistderlichtschalterinfhem",raumb","raumxyz"] $3{true=>"on",false=>"off"}'4. Optional die true,false listen erweiterbar machen. Ich habe gesehen das ich lauter leiser nicht drin habe. Und sowas könnte man dann zu der Liste hinzufügen.

Was meint Ihr?
Homebrew 1-Wire / HomeMatic Mix - Cubietruck mit FHEM als Server - Raspberry PI 3 als Informationsanzeige im MagicMirror Stil - Raspberry Pi 1 als Klingelanlage - VDR

Mein Modul: Talk2Fhem - Mein Tipp: https://forum.fhem.de/index.php/topic,82442.0.html

Offline klausw

  • Developer
  • Hero Member
  • ****
  • Beiträge: 1843
Antw:Flexibles Sprachanalysescript
« Antwort #32 am: 19 Dezember 2017, 23:41:03 »

Eigentlich gehe ich eher davon aus das alles über ein device konfiguriert wird.
Ich überlege gerade krampfhaft was besser ist. Aber jetzt mal nur die Situation wie kommt der Satz zu dem device.
hab ich eins mach ich das über ein set fhemtalk "hier der satz"
habe ich mehrere wäre das ziemlich aufwendig, und ich müsste dem device sagen auf welches Ereignis er triggern soll, dann würde aber in allen devices das gleiche "notify" konfiguriert werden müssen und wenn der text aus unterschiedlichen Quellen kommt würde es das auch erschweren.
Oder?
Angenommen jedes Device hat ein attribut fhemtalkconf (oder wie auch immer)

Dann kannst du mit list (list i:fhemtalkconf=.*) oder devspec2array
alle Devices die einen Datensatz gespeichert haben und dann auch an die Inhalte.

Das macht natürlich nur Sinn wenn der Datensatz nur für dieses eine Device gilt.
Bei Mehrdeutigkeiten müsstest du das anders lösen.
RasPi B v2 mit FHEM 18B20 über 1Wire, LED PWM Treiber über I2C, Luchtdruck-, Feuchtesensor und ein paar Schalter/LED\'s zum testen
Module: RPI_GPIO, RPII2C, I2C_EEPROM, I2C_MCP23008, I2C_MCP23017, I2C_MCP342x, I2C_PCA9532, I2C_PCF8574, I2C_SHT21, I2C_BME280

Online Prof. Dr. Peter Henning

  • Developer
  • Hero Member
  • ****
  • Beiträge: 6257
Antw:Flexibles Sprachanalysescript
« Antwort #33 am: 20 Dezember 2017, 03:35:43 »
Es sollte allen klar sein, dass hier gerade das Rad zum zweiten Mal erfunden wird. Die Verfahren zur Spracherkennung sind seit Jahren bestens etabliert, und inzwischen schon sehr viel weiter fortgesschritten, als die hier diskutierten Programme. Das hat vor allem damit zu tun, dass Ihr hier zwei wesentlichen Schritte überspringt, nämlich das POS-Tagging und die semantische Analyse.

Den nachstehenden Code habe ich hier in diesem Forumsteil schon vor längerer Zeit zur Verfügung gestellt - er ist eine kurzes und leicht anzupassendes Beispiel mit mehreren Listen von Zeiten, Räumen, Verben etc.

##############################################################################
#
#  Spracherkennung
#
#  Normalisierung
#  1.Wort wird für die Semantik ignoriert, wenn "james" => Ausgabe anders
#
#  Prof. Dr. Peter A. Henning 2014
#
##############################################################################


sub voiceNormalize($){
  my ($command) = @_;
  $command = lc $command;

  #-- semantics
  my @vr_states    = ("status","wert","wetter","zeit");
  my @vr_writes    = ("sagen","senden","hinzufügen","entfernen","ändern","löschen");
  my @vr_times     = ("heute","morgen","übermorgen","nacht");
  my @vr_places    = ("erdgeschoss","garderobe","gästebad","wohnzimmer","essgruppe","sitzgruppe","fernsehen","schlummern",
                      "aussen","terrasse","pavillon","rasen","garage","vorgarten","hecke",
                      "baum","eingang",
                      "keller","vorratskeller","werkstatt","kellerbad","zwischenkeller","heizungskeller",
                      "obergeschoss","schlafzimmer","badezimmer","bibliothek","flur","dominics_zimmer",
                      "dachgeschoss","arbeitszimmer","gästezimmer","party");
  my %vr_verbs     = ("schalte"=>"schalten",
                      "mach"=>"machen",
                      "machs"=>"machen",
                      "mache"=>"machen",
                      "setze"=>"setzen",
                      "stelle"=>"stellen",
                      "schließe"=>"schließen",
                      "öffne"=>"öffnen",
                      "sichern"=>"sichern",
                      "sichere"=>"sichern",
                      "hinzufügen"=>"hinzufügen",
                      "entfernen"=>"entfernen",
                      "löschen"=>"löschen",
                      "sage"=>"sagen",
                      "sagen"=>"sagen",
                      "ansagen"=>"sagen",
                      "zeige"=>"zeigen",
                      "zeigen"=>"zeigen",
                      "anzeigen"=>"zeigen",
                      "wecken"=>"wecken",
                      "senden"=>"senden",
                      "rufen"=>"rufen");
  my @vr_verbs_prt = ("zu","auf","ent","wider","ein","an","aus","ab","um");
  my @vr_prepo     = ("von","vom","des","der","in","im","auf","bei","am");
  my @vr_prono     = ("wie","wo","wann");
  my @vr_article   = ("der","die","das","den","des","dem","zur");
 
  my $re_states    = "((".join(")|(",@vr_states)."))";
  my $re_writes    = "((".join(")|(",@vr_writes)."))";
  my $re_times     = "((".join(")|(",@vr_times)."))";
  my $re_places    = "((".join(")|(",@vr_places)."))";
  my $re_verbs_inf = "((".join(")|(",(values %vr_verbs))."))";
  my $re_verbs_1ps = "((".join(")|(",(keys %vr_verbs))."))";
  my $re_verbs_prt = "((".join(")|(",@vr_verbs_prt)."))";
  my $re_prepo     = "((".join(")|(",@vr_prepo)."))";
  my $re_prono     = "((".join(")|(",@vr_prono)."))";
  my $re_article   = "((".join(")|(",@vr_article)."))";
 
  my $cat          = 0;
  my $subcat       = 0;
  my $subsubcat    = 0;
   
  my ($device,$verb,$reading,$value,$article,$reserve,$place,$state,$prepo)=("","","","","","","","","","");
 
  #-- normalize special phrases
  my $commandn = $command;
  $commandn =~ s/we((ck)|g) ?zeit/wecker/;
  $commandn =~ s/wecken um/stelle den wecker auf/;
  $commandn =~ s/beleuchtung/licht/;
  $commandn =~ s/\szimmer/_zimmer/;
  $commandn =~ s/(((zur?)|(von))\s)?(\w+)\sliste/$5_liste/;
  $commandn =~ s/\ssichern/ zusichern/;
  $commandn =~ s/unscharf\s?/aus/;
  $commandn =~ s/scharf\s?/ein/;
  $commandn =~ s/wider\s/wider/;
           
  my @word = split(' ',$commandn,15);
  my $len  = int(@word);
 
  ############################# POS tagging ###################
  #-- isolate place - take out (prepo) [arti] PLACE
  # (verb) (prepo) [arti] PLACE [arti] (device)
  # (verb) [arti] (device) (prepo) [arti] PLACE
  #  wie ist [arti] (device) (prepo) [arti] PLACE
  #  wie ist (prepo) [arti] PLACE [arti] (device)
  for( my $i=3;$i<$len;$i++){
    if( $word[$i] =~ /^$re_places/ ){
      $place = $word[$i];
      my $to = ( $word[$i-1] =~ /^$re_article/)?3:2;
      $to = ( $word[$i+1-$to] =~ /^$re_prepo/)?$to:$to-1;
      for( my $j=$i+1-$to;$j<$len;$j++){
        $word[$j]=($word[$j+$to])?$word[$j+$to]:"";
      }
      last;
    }
  }
  #-- backup for reserve
  my @xord = @word;
  shift(@xord);
 
  #-- leer
  if( int(@word) <= 1){
    return ("","","","","","","");
  #-- schalte das gerät an
  #   schalte gerät an
  #   sage den status von gerät
  #   sage status von gerät
  #   sage status gerät
  #   schalte den wecker aus ;
  #   schalte wecker aus
  }elsif( ($word[1] =~ /^$re_verbs_1ps/) && ($word[2])){
    $cat = 1;
    $verb = $vr_verbs{$word[1]};
    if( $word[2] =~ /^$re_article/){
      $subcat  = 1;
      $article = $word[2];
      $device  = $word[3];
      $reading = $word[4];
      $reserve = $word[5];
    }elsif( $word[2] =~ /^$re_prepo/){
      $subcat  = 2;
      $article = $word[2];
      $device  = $word[3];
    }else{
      $subcat  = 3;
      $device  = $word[2];
      $reading = $word[3];
      $reserve = $word[4];
    }
    #-- device=state => verb="sage" => reading
    if(  $device =~ /^$re_states/ ){
      if( $reading =~ /^$re_prepo/ ){
        $subsubcat  = 1; 
        $reading = $device;
        $device  = $reserve;
      }else{
        $subsubcat  = 2;
        $reserve = $reading;
        $reading = $device;
        $device  = $reserve;
      }
    #-- reading of device => target
    }elsif( $subcat==2 ){
      if( $word[4] =~ /^$re_article/ ){
        $subsubcat  = 3;
        $reading = $word[5];
        $reserve = $word[6];
      }else{
        $subsubcat  = 4;
        $reading = $word[4];
        $reserve = $word[5];
      }
    }
  #-- wie ist der wert von gerät
  #   wie ist wert von gerät
  #   wie ist der wert gerät
  #   wie ist wert gerät
  #   wie ist das wetter morgen
  #   wie ist wetter morgen
  #   wie ist morgen das wetter
  #   wie ist morgen wetter
  #   wie ist die weckzeit
  #   wie ist der status des weckers
  }elsif( $word[1] =~ /^$re_prono/){
     $cat = 2;
     $verb    = "sagen";
     #-- take out article
     if( $word[3] =~ /^$re_article/){
       $subcat=1;
       $article = $word[3];
       $reading = $word[4];
       #--take out preposition
       if( $word[5] =~ /^$re_prepo/ ){
         $subsubcat = 1;
         $device = $word[6];
       #-- no preposition
       }else{
         $subsubcat = 2;
         $device = $word[5];
       }
    #-- no article
    }else{
      $subcat = 2;
      $reading = $word[3];
      #--take out preposition
      if( $word[4] =~ /^$re_prepo/ ){
        $subsubcat = 1;
        $device = $word[5];
      #-- no preposition
      }else{
        $subsubcat = 2;
        $device = $word[4];
      }
    }
    #-- exchange on temporal statement
    if( $device =~ /^$re_times/ ){
      $subsubcat = 3;
      $reserve = $device;
      $device  = $reading;
      $reading = $reserve;
    }
    if( $device =~ /^$re_article/){
      $subsubcat = 4;
      $device  = $word[5];
    }
    if( $device eq ""){
      $subsubcat = 5;
      $device = $reading;
      $reading = "status";
    }
  #-- das gerät anschalten
  #   gerät anschalten
  #   das wetter von morgen
  #   wetter von morgen
  #   das wetter morgen
  #   wetter morgen
  #   guten morgen
  #   gute nacht
  #   den wecker ausschalten
  #   wecker ausschalten
  #   wecker
  #   status
  }else{
    $cat = 3;
    my $rex = $re_verbs_prt." ?".$re_verbs_inf;
    #-- guten morgen / gute nacht
    if( $word[1] =~ /^gut.*/){
      $subcat = 1;
      $device="zeit";
      $reading=$word[2];
      $reserve=$word[3]
        if( $word[3] );
      $verb="schalten";
    #-- (arti) (device) something
    }elsif( $word[1] =~ /^$re_article/){
      $subcat = 2;
      $article = $word[1];
      $device  = $word[2];
      shift(@xord);
      shift(@xord);
      #--take out preposition
      if( $word[3] =~ /^$re_prepo/ ){
        $subsubcat = 1;
        shift(@xord);
        $reserve = join(" ",@xord);
      }else{
        $subsubcat = 2;
        $reserve = join(" ",@xord);
      }
      #-- (arti) (device) [prepo] (time)
      if( $reserve =~ /^$re_times/ ){
        $subsubcat = 3;
        $reading   = $reserve;
        $verb      = "sagen";
      #-- (arti) (device) [prepo] verb
      }elsif( $reserve =~ s/^$re_verbs_inf\s?// ){
        $subsubcat = 4;
        $verb      = $1;
        $reading   = $reserve;
      #-- (arti) (device) [prepo] (reading) (verb) (value)
      }else{
        $subsubcat = 5;
        $reserve =~ /^$rex/;
        $verb    = $11;  #No verb_prt +2
        $reading = $1;
      }
    #-- status [prepo] (device)
    }elsif( $word[1] =~ /^status/){
      $subcat = 3;
      #--take out preposition
      if( $word[2] =~ /^$re_prepo/ ){
        $subsubcat = 1;
        $device    = $word[3];
      }else{
        $subsubcat = 2;
        $device  = $word[2];
      }
      $verb    = "sagen";
      $reading = "status";
    #-- (device) something
    }elsif($word[2] ne ""){
      $subcat  = 4;
      $device  = $word[1];   
      shift(@xord);
      #--take out preposition
      if( $word[2] =~ /^$re_prepo/ ){
        $subsubcat = 1;
        shift(@xord);
        $reserve   = join(" ",@xord);
      }else{
        $subsubcat = 2;
        $reserve   = join(" ",@xord);
      }
      #-- (device) [prepo] (time)
      if( $reserve =~ /^$re_times/ ){
        $subsubcat = 3;
        $reading   = $reserve;
        $verb      = "sagen";
      #-- (device) [prepo] status
      }elsif( $reserve =~ /^status/ ){
        $subsubcat = 4;
        $reading   = "status";
        $verb      = "sagen";
      #-- (device) (write)
      }elsif( $word[2] =~ /^$re_writes/ ){
        $subsubcat = 5;
        $verb      = $word[2];
        shift(@xord);
        $reading   = join(" ",@xord);
      #-- (device) [prepo] öffnen
      #}elsif( $reserve =~ /^öffne.*/ ){
      #  $subsubcat = 6;
      #  $reading = "";
      # $verb    = "öffnen";
      #-- (arti) (device) [prepo] verb
      }elsif( $reserve =~ s/^$re_verbs_inf\s// ){
        $subsubcat = 6;
        $verb      = $1;
        $reading   = $reserve;
      #-- (device) [prepo] (reading) (verb) (value)
      }else{
        $subsubcat = 7;
        $reserve   =~ /^$rex/;
        $verb      = $11;  #No verb_prt +2
        $reading   = $1;
      }
    #-- (device)
    }else{
      $subcat  = 5;
      $device  = $word[1];
      $reading = "status";
      $verb    = "sagen";
    }
  }
  #-- normalize devices
  $device = "golf"
    if( $device =~/golfplatz/);
  $device = "haus"
    if( $device =~/hauses/);
  $device = "haustür"
    if( $device =~/hauseingangstür/);
  $device = "wecker"
    if( $device =~/we((ck)|g).*/);
  $device = "alarm"
    if( $device =~/alarm.*/);
  $place = "wohnzimmer"
    if( ($device eq "licht") && ($place eq ""));
  if( $device eq "außenlicht" ){
    $place="aussen"
      if( $place eq "" );
    $device="licht";
  }
 
  #-- machen
  $verb = "schalten"
    if( $verb eq "machen");
   
  #-- sichern
  $reading = "zu"
    if(( $verb eq "sichern") && ($reading eq ""));
   
  #-- an
  $reading = "status"
    if( (($verb eq "sagen") || ($verb eq "zeigen")) && ($reading eq "an"));
  $reading = "ein"
    if( $reading eq "an");
   
  #-- value
  $value=substr($commandn,index($commandn,"auf")+4)
    if( ($reading eq "auf") || ($reserve eq "auf") );
   
  #--judgement day
  my $ok=( ($device ne "") and ($verb =~ /^$re_verbs_inf/) )?0:0;

  my $str="[voiceRecognition] Semantic analysis of sentence $command\n".
          "category=$cat.$subcat.$subsubcat: \tdevice=$device, \tverb=$verb, \treading=$reading $value \t[place=$place]\n";
  if( $word[0] eq "johann" ){
    return ($ok)?"[voiceRecognition] OK":$str;
  }else{
    Log 1,$str
      if(!$ok);
  }
  return ($device,$verb,$reading,$value,$article,$reserve,$place);
}


Testen kann man das mit

##############################################################################
#
#  Spracherkennung
#
#  Testroutine
#
#  Prof. Dr. Peter A. Henning 2014
#
##############################################################################

sub TVR(){
  my $str = "";
  $str .= "\nA.1:".voiceNormalize("johann guten morgen");
  $str .= "\nA.2:".voiceNormalize("johann gute nacht");
  $str .= "\nA.3:".voiceNormalize("johann guten morgen jeannie");
  $str .= "\nA.4:".voiceNormalize("johann gute nacht jeannie");
  $str .= "\n";
  $str .= "\nB.1:".voiceNormalize("johann schalte das gerät an");
  $str .= "\nB.2:".voiceNormalize("johann schalte gerät an");
  $str .= "\nB.3:".voiceNormalize("johann mach das gerät an");
  $str .= "\nB.4:".voiceNormalize("johann das gerät ausschalten");
  $str .= "\nB.5:".voiceNormalize("johann gerät ausschalten");
  $str .= "\nB.6:".voiceNormalize("johann das gerät ausmachen");
  $str .= "\nB.7:".voiceNormalize("johann gerät anmachen");
  $str .= "\nB.8:".voiceNormalize("johann schalte beleuchtung an");
  $str .= "\nB.9:".voiceNormalize("johann licht anschalten");
  $str .= "\n";
  $str .= "\nC.1:".voiceNormalize("johann wie ist der wert von gerät");
  $str .= "\nC.2:".voiceNormalize("johann wie ist wert von gerät");
  $str .= "\nC.3:".voiceNormalize("johann wie ist der wert gerät");
  $str .= "\nC.4:".voiceNormalize("johann wie ist wert gerät");
  $str .= "\nC.4:".voiceNormalize("johann sage den status von gerät");
  $str .= "\nC.5:".voiceNormalize("johann sage status von gerät");
  $str .= "\nC.6:".voiceNormalize("johann sage status gerät");
  $str .= "\n";
  $str .= "\nD.1:".voiceNormalize("johann wie ist das wetter von morgen");
  $str .= "\nD.2:".voiceNormalize("johann wie ist wetter von morgen");
  $str .= "\nD.3:".voiceNormalize("johann wie ist das wetter morgen");
  $str .= "\nD.4:".voiceNormalize("johann wie ist wetter morgen");
  $str .= "\nD.5:".voiceNormalize("johann wie ist morgen das wetter");
  $str .= "\nD.6:".voiceNormalize("johann wie ist morgen wetter");
  $str .= "\nD.7:".voiceNormalize("johann wetter von morgen");
  $str .= "\nD.8:".voiceNormalize("johann wetter morgen");
  $str .= "\n";
  $str .= "\nF.1:".voiceNormalize("johann schalte den wecker aus");
  $str .= "\nF.2:".voiceNormalize("johann schalte wecker aus");
  $str .= "\nF.3:".voiceNormalize("johann den wecker ausschalten");
  $str .= "\nF.4:".voiceNormalize("johann wecker ausschalten");
  $str .= "\nF.5:".voiceNormalize("johann wie ist die weckzeit");
  $str .= "\nF.6:".voiceNormalize("johann wie ist der status des weckers");
  $str .= "\nF.7:".voiceNormalize("johann weckzeit ansagen");
  $str .= "\nF.8:".voiceNormalize("johann weckzeit");
  $str .= "\nF.9:".voiceNormalize("johann wecken um 4 uhr 3");
  $str .= "\nF.10:".voiceNormalize("johann stelle den wecker auf 17:00");
  $str .= "\nF.11:".voiceNormalize("johann wecken um 13:12 Uhr");
  $str .= "\n";
  $str .= "\nG.1:".voiceNormalize("johann das haus ansagen");
  $str .= "\nG.2:".voiceNormalize("johann haus ansagen");
  $str .= "\nG.3:".voiceNormalize("johann haus status");
  $str .= "\nG.4:".voiceNormalize("johann wie ist der status des hauses");
  $str .= "\nG.5:".voiceNormalize("johann wie ist der status vom haus");
  $str .= "\nG.6:".voiceNormalize("johann das haus sichern");
  $str .= "\nG.7:".voiceNormalize("johann sichere das haus");
  $str .= "\nG.8:".voiceNormalize("johann haus sichern");
  $str .= "\nG.9:".voiceNormalize("johann das haus entsichern");
  $str .= "\nG.10:".voiceNormalize("johann haus entsichern");
  $str .= "\nG.11:".voiceNormalize("johann haustür öffnen");
  $str .= "\nG.12:".voiceNormalize("johann die haustür öffnen");
  $str .= "\nG.13:".voiceNormalize("johann öffne die haustür");
  $str .= "\nG.14:".voiceNormalize("johann schließe die haustür zu");
  $str .= "\nG.15:".voiceNormalize("johann schließe die haustür auf");
  $str .= "\n";
  $str .= "\nH.1:".voiceNormalize("johann alarmanlage einschalten");
  $str .= "\nH.1:".voiceNormalize("johann alarmanlage ein schalten");
  $str .= "\nH.1:".voiceNormalize("johann die alarmanlage scharfschalten");
  $str .= "\nH.2:".voiceNormalize("johann alarmanlage unscharf schalten");
  $str .= "\nH.2:".voiceNormalize("johann die alarmanlage ausschalten");
  $str .= "\nH.3:".voiceNormalize("johann schalte die alarmanlage scharf");
  $str .= "\nH.4:".voiceNormalize("johann schalte den alarm an");
  $str .= "\nH.5:".voiceNormalize("johann alarm wider rufen");
  $str .= "\nH.6:".voiceNormalize("johann alarm widerrufen");
  $str .= "\n";
  $str .= "\nI.1:".voiceNormalize("johann schalte beleuchtung in sitzgruppe an");
  $str .= "\nI.2:".voiceNormalize("johann schalte beleuchtung in der sitzgruppe an");
  $str .= "\nI.3:".voiceNormalize("johann mach die außenbeleuchtung auf terrasse an");
  $str .= "\nI.4:".voiceNormalize("johann mache die außenbeleuchtung aus");
  $str .= "\nI.5:".voiceNormalize("johann wie ist die temperatur im badezimmer");
  $str .= "\nI.6:".voiceNormalize("johann wie ist die feuchte in dominics zimmer");
  $str .= "\nI.7:".voiceNormalize("johann wie ist die feuchte in dem schlafzimmer");
  $str .= "\nI.8:".voiceNormalize("johann wie ist der status der tür im schlafzimmer");
  $str .= "\nI.9:".voiceNormalize("johann status tür schlafzimmer");
  $str .= "\nI.10:".voiceNormalize("johann status der tür schlafzimmer");
  $str .= "\nI.11:".voiceNormalize("johann status tür im schlafzimmer");
  $str .= "\nI.12:".voiceNormalize("johann status der tür im schlafzimmer");
  $str .= "\n";
  $str .= "\nJ.1:".voiceNormalize("johann stelle bei gerät den wert auf 8");
  $str .= "\nJ.2:".voiceNormalize("johann stelle am gerät wert auf 9");
  $str .= "\nJ.3:".voiceNormalize("johann stelle bei harmony den kanal auf 10");
  $str .= "\nJ.4:".voiceNormalize("johann stelle am fernseher die lautstärke auf 11");
  $str .= "\n";
  $str .= "\nK.1:".voiceNormalize("johann zur einkaufsliste hinzufügen bratheringe");
  $str .= "\nK.2:".voiceNormalize("johann zu peters liste hinzufügen ticket münchen besorgen");
  $str .= "\nK.3:".voiceNormalize("johann von dominics liste entfernen schmieröl");
  $str .= "\nK.4:".voiceNormalize("johann baumarktliste löschen");
  $str .= "\nK.5:".voiceNormalize("johann einkaufsliste senden");
 
 return $str;
 
}

Die tatsächliche Auswertung erfolgt dann nur noch auf Basis der normalisierten Sätze, hier für die ersten paar devices:

##############################################################################
#
#  Spracherkennung
#
#  Verarbeitung
#  Parameter: $name = Gerätename für die Ausgabe
#             $command = Sprachstring, beginnt mit Jeannie, James oder Johann
#             Wenn nicht, wird "Jeannie " für die semantische Analyse
#             davor gesetzt. Wenn "James ", wird nur simuliert.
#             Wenn "Johann", wird nur die Analyse durchgeführt.
#
#  Prof. Dr. Peter A. Henning 2014
#
##############################################################################

sub voiceRecognition($$){

  my ($name,$command) = @_;
 
  my $commandn;
  my $res = "";
  my $simu = 0;
 
  #-- voiceRecognitionLastResult => entfernen
  $command =~ s/^voiceRecognitionLastResult: //;
 
  #-- Blödes Google
  $command =~ s/(([Jj]enny)|([Jj]immy)|([Gg]inny)|(Teenies)|(Tini))/Jeannie/;
   
  #-- Jeannie/James/Johann als letztes Wort => setze nach vorne
  $command =~ s/(.*) (([Jj]ea?n.*)|([Jj]ames)|([Jj]ohann))$/$2 $1/;
 
  #-- Jeannie/James/Johann nicht als erstes Wort
  if( ($command !~ /^[Jj]ea?n.*/) && ($command !~ /^[Jj]am.*/) && ($command !~ /^[Jj]oh.*/) ){
    $commandn = "Jeannie ".$command;
  }else{
    $commandn = $command;
  }
  #-- Jeannie präsent => Person= Meister
  my $person=( $command =~ /^[Jj]ea?n.*/ )?"Meister":"";
 
  #-- nur Simulieren
  $simu = 1
    if( $command =~ /^[Jj]am.*/ );
       
  my ($device,$verb,$reading,$value,$article,$reserve,$place) = voiceNormalize($commandn);
 
  Log 1,"=================> ".join(" ",($device,$verb,$reading,$value,$article,$reserve,$place));
 
  $res .= $device
    if( $simu );
 
  if ( ($device eq "zeit")&&($verb eq "schalten") ){ 
    if( $reading eq "morgen" ){
      return $res."\n============> 90 => set YYY time wakeup"
        if( $simu );
      fhem90Cmd("set YYY time wakeup");
    #++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    }elsif( $reading eq "nacht"){
      return $res."\n============> 90 => set YYY time sleep"
       if( $simu );
      fhem90Cmd("set YYY time sleep");
    }
  #++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  }elsif( $device eq "wecker" ){
    my ($nt,$nc);
    #-- ausschalten----------------------------------------
    if( ($verb eq "schalten") && ($reading eq "aus") ){
      return $res."\n============> 90 => {changeWakeTime('$name','ausschalten','off')}"
        if( $simu );
      fhem90Cmd("{changeWakeTime(\'$name\','ausschalten','off')}");
    #-- ansagen -------------------------------------------
    }elsif( (($verb eq "sagen") || ($verb eq "zeigen"))&&($reading eq "status") ){
      return $res."\n============> 90 => {sayWakeTime('$name',undef)}"
        if( $simu );
      fhem90Cmd("{sayWakeTime(\'$name\',undef)}");
    }elsif( $verb eq "stellen"){
      #-- nicht volle Stunde---------------------------------
      if( $value =~ /(\d+)([uhr\s]+)(\d+)/ ){
        $nc="$1 Uhr $3";
        $nt=sprintf("%02d:%02d:00",$1,$3); 
      #-- nicht volle Stunde----------------------------------
      }elsif( $value =~ /(\d+):(\d+)([a-z\s]*)/ ){
        $nc="$1 Uhr $2";
        $nt=sprintf("%02d:%02d:00",$1,$2);
      #-- volle Stunde----------------------------------------
      }elsif( $value=~ /(\d+)([a-z\s]+)/ ){
        $nc="$1 Uhr";
        $nt=sprintf("%02d:00:00",$1);
      #-- nichts----------------------------------------------
      }
      return $res."\n============> 90 => {changeWakeTime('$name','$nc','$nt')}"
        if( $simu );
      fhem90Cmd("{changeWakeTime(\'$name\',\'$nc\',\'$nt\')}");
    }else{
      speakHelp($name,("Weckzeit, Wecker oder Wecken um, gefolgt von","ausschalten, ansagen oder einer Uhrzeit"));
    }
  #++ Golf ++++++++++++++++++++++++++++++++++++++++++++++   
  }elsif( $device eq "golf" ){

...


LG

pah



Zustimmung Zustimmung x 1 Liste anzeigen

Offline Phill

  • Developer
  • Full Member
  • ****
  • Beiträge: 406
  • Langsam wird'n Schuh d'raus.
    • iVDR
Antw:Flexibles Sprachanalysescript
« Antwort #34 am: 20 Dezember 2017, 11:33:03 »
Es sollte allen klar sein, dass hier gerade das Rad zum zweiten Mal erfunden wird.Ich glaube da haben sich schon wesentlich mehr als wir beide gedanken dazu gemacht.  ;)
Aber nein ich kannte dein Script noch nicht, danke dafür.
Den Satz zu analysieren ist natürlich die Paradedisziplin, aber ist es bei den paar Sätzen die man mit FHEM redet wirklich notwendig? Ich bin mir nicht sicher. Vielleicht kann ich aber trotzdem einige Ansätze davon mit in meinen Code aufnehmen.

Ich habe jetzt den Code soweit, dass ein richtiges Device angelegt und alles über FHEM Konfiguriert werden kann. Mal sehen ob's gefällt.
Ich aktualisiere mal den ersten Beitrag.
Homebrew 1-Wire / HomeMatic Mix - Cubietruck mit FHEM als Server - Raspberry PI 3 als Informationsanzeige im MagicMirror Stil - Raspberry Pi 1 als Klingelanlage - VDR

Mein Modul: Talk2Fhem - Mein Tipp: https://forum.fhem.de/index.php/topic,82442.0.html

Offline Phill

  • Developer
  • Full Member
  • ****
  • Beiträge: 406
  • Langsam wird'n Schuh d'raus.
    • iVDR
Antw:Flexibles Sprachanalysescript
« Antwort #35 am: 20 Dezember 2017, 12:48:04 »
So der erste Beitrag ist aktualisiert.

Die Syntax hat sich aufgrund der FHEM-Konfigurierbarkeit etwas geändert.
Regexp und Kommando sollten nicht mehr in ' '
Trennzeichen ist nicht mehr => sondern einfach nur ein " = " mit mindestens einem Leerzeichen oder Tabulator

Abgesehen von dieser Frage hier mal meine bisherige Config für Leute die es interessiert:
Bei deiner Konfig, die du uns netterweise zur Verfügung gestellt hast, können jetzt einige Zeilen entfallen, ich habe das mal Beispielhaft hier erstellt:
DEF:(@rooms) auf (@sender)   = set Fernseher_$1[@tvdev] command $2[@channel] ; set Fernseher_$1[@tvdev] command Select
(@rooms) licht (@colors) = set Licht_$1[@lightdev] hue $2[@huecolor]'
Attribute:attr talk T2F_keywordlist
sender = ard|erste,zdf|zweite,rtl,sat 1,prosieben,kabel 1,rtl 2,vox,sixx
rooms = haus|..?berall,wohnung,wohnzimmer,bad(ezimmer)?,schlafzimmer,garten,terrasse
colors = blau,gelb,rot,magenta,gr..?n

attr talk T2F_modwordlist
channel = Number1,Number2,Number3,Number4,Number5,Number6,Number7,Number8
tvdev = ,,Wohnzimmer,,Schlafzimmer,,
lightdev = ,,Wohnzimmer,,Schlafzimmer,Garten,Terrasse
huecolor = 240,40,360,320

Bin mal gespannt ob es auf Anhieb klappt.  ::)
Viel Spaß.
« Letzte Änderung: 20 Dezember 2017, 13:53:45 von Phill »
Homebrew 1-Wire / HomeMatic Mix - Cubietruck mit FHEM als Server - Raspberry PI 3 als Informationsanzeige im MagicMirror Stil - Raspberry Pi 1 als Klingelanlage - VDR

Mein Modul: Talk2Fhem - Mein Tipp: https://forum.fhem.de/index.php/topic,82442.0.html

Offline Esjay

  • Sr. Member
  • ****
  • Beiträge: 898
Antw:Flexibles Sprachanalysescript
« Antwort #36 am: 20 Dezember 2017, 12:55:52 »
So der erste Beitrag ist aktualisiert.

Die Syntax hat sich aufgrund der FHEM-Konfigurierbarkeit etwas geändert.
Regexp und Kommando sollten nicht mehr in ' '
Trennzeichen ist nicht mehr => sondern einfach nur ein " = " mit mindestens einem Leerzeichen oder Tabulator
Bei deiner Konfig, die du uns netterweise zur Verfügung gestellt hast, können jetzt einige Zeilen entfallen, ich habe das mal Beispielhaft hier erstellt:
DEF:(@rooms) auf (@sender)   = set Fernseher_$1[@tvdev] command Number1 ; set Fernseher_$1[@tvdev] command Select
(@rooms) licht (@colors) = set Licht_$1[@lightdev] hue $2[@huecolor]'
Attribute:attr talk T2F_keywordlist
sender = ard|erste,zdf|zweite,rtl,sat 1,prosieben,kabel 1,rtl 2,vox,sixx
rooms = haus|..?berall,wohnung,wohnzimmer,bad(ezimmer)?,schlafzimmer,garten,terrasse
colors = blau,gelb,rot,magenta,gr..?n

attr talk T2F_modwordlist
tvdev = ,,Wohnzimmer,,Schlafzimmer,,
lightdev = ,,Wohnzimmer,,Schlafzimmer,Garten,Terrasse
huecolor = 240,40,360,320

Bin mal gespannt ob es auf Anhieb klappt.  ::)
Viel Spaß.

Dann kann es ja bald richtig losgehen mit testen. Mein Mini wird heute kommen, vll kann ich bis heute Abend noch ein kleines Feedback geben. Was noch wünschenswert wäre, ist stumpf ein Dummy im Start-Pst, als Raw-Code. Dann hat man gleich etwas leichtes zum herumspielen, falls man den Wald vor lauter regex nicht sieht  ;).

Grüße

Offline kud

  • Full Member
  • ***
  • Beiträge: 493
Antw:Flexibles Sprachanalysescript [39_Talk2Fhem.pm]
« Antwort #37 am: 20 Dezember 2017, 13:43:38 »
Jetzt mal ne blöde Frage zwischendurch.
Habe jetzt ne ganze Weile nur mit Alexa (Smarthome) verbracht und bin nicht ganz auf dem Laufenden.
Was sind die Voraussetzungen für dieses Modul ? Ein Google Home? Eine Handy ? Ein funktionierter TelegramBot?

 

Offline Phill

  • Developer
  • Full Member
  • ****
  • Beiträge: 406
  • Langsam wird'n Schuh d'raus.
    • iVDR
Antw:Flexibles Sprachanalysescript [39_Talk2Fhem.pm]
« Antwort #38 am: 20 Dezember 2017, 14:01:38 »
Jetzt mal ne blöde Frage zwischendurch.
Habe jetzt ne ganze Weile nur mit Alexa (Smarthome) verbracht und bin nicht ganz auf dem Laufenden.
Was sind die Voraussetzungen für dieses Modul ? Ein Google Home? Eine Handy ? Ein funktionierter TelegramBot?
Hi, also eigentlich nur irgendetwas womit du Text in Richtung FHEM bekommst.
Das kann ein Messenger sein, irgendeine Speak-To-Text Engine wie ein GoogleHome oder einfach eine Konsole.
Schau mal hier, da ist auf eine ähnliche Frage eingegangen.
https://forum.fhem.de/index.php/topic,80960.msg731273.html#msg731273
« Letzte Änderung: 20 Dezember 2017, 14:08:53 von Phill »
Homebrew 1-Wire / HomeMatic Mix - Cubietruck mit FHEM als Server - Raspberry PI 3 als Informationsanzeige im MagicMirror Stil - Raspberry Pi 1 als Klingelanlage - VDR

Mein Modul: Talk2Fhem - Mein Tipp: https://forum.fhem.de/index.php/topic,82442.0.html

Offline Esjay

  • Sr. Member
  • ****
  • Beiträge: 898
Antw:Flexibles Sprachanalysescript [39_Talk2Fhem.pm]
« Antwort #39 am: 21 Dezember 2017, 21:46:36 »
Nabend Phil,
was mir bisher aufgefallen ist:
Du hast meiner Meinung nach einen kleinen Fehler im Startpost. Im Beispiel Konfiguration nutzt du beim regexp --> attr talk T2F_keywordlist
Bei kommando ebenfalls.

Wenn ich es richtig verstanden habe, ist das Notify die Verbindung zum Device welches den Text liefert?

Für die Konfiguration ist es mir heute schon zu dunkel draußen. Da muss ich mich nochmal in Ruhe dran machen.

Grüße

Offline Phill

  • Developer
  • Full Member
  • ****
  • Beiträge: 406
  • Langsam wird'n Schuh d'raus.
    • iVDR
Antw:Flexibles Sprachanalysescript [39_Talk2Fhem.pm]
« Antwort #40 am: 22 Dezember 2017, 11:12:50 »
Ist korregiert, Danke.
Homebrew 1-Wire / HomeMatic Mix - Cubietruck mit FHEM als Server - Raspberry PI 3 als Informationsanzeige im MagicMirror Stil - Raspberry Pi 1 als Klingelanlage - VDR

Mein Modul: Talk2Fhem - Mein Tipp: https://forum.fhem.de/index.php/topic,82442.0.html

Offline Esjay

  • Sr. Member
  • ****
  • Beiträge: 898
Antw:Flexibles Sprachanalysescript [39_Talk2Fhem.pm]
« Antwort #41 am: 23 Dezember 2017, 17:04:18 »
Ich muss nochmal fragen, weil ich es einfach nicht sehe. Wo ist die Verbindung zwischen erkanntem Text und deinem Modul.
Ich checke es gerade nicht.

Wäre nett wenn du mir da nochmal auf die Sprünge hilfst.

Grüße

Offline Pitcher90

  • Jr. Member
  • **
  • Beiträge: 54
Antw:Flexibles Sprachanalysescript [39_Talk2Fhem.pm]
« Antwort #42 am: 23 Dezember 2017, 19:19:56 »
Du musst über IFTTT einen Webhook anlegen, der von außen auf dein System zugreifen kann und den Text übermittelt. Weis jetzt nicht ob das deine Frage war ... etwas zweideutig.
https://haus-automatisierung.com/hardware/fhem/2017/01/04/fhem-tutorial-reihe-part-22-ifttt-integration-webservices-in-fhem-nutzen.html

« Letzte Änderung: 23 Dezember 2017, 19:23:54 von Pitcher90 »

Offline Phill

  • Developer
  • Full Member
  • ****
  • Beiträge: 406
  • Langsam wird'n Schuh d'raus.
    • iVDR
Antw:Flexibles Sprachanalysescript [39_Talk2Fhem.pm]
« Antwort #43 am: 23 Dezember 2017, 19:21:28 »
Meinst duset talk zu interpretierender text
Homebrew 1-Wire / HomeMatic Mix - Cubietruck mit FHEM als Server - Raspberry PI 3 als Informationsanzeige im MagicMirror Stil - Raspberry Pi 1 als Klingelanlage - VDR

Mein Modul: Talk2Fhem - Mein Tipp: https://forum.fhem.de/index.php/topic,82442.0.html

Offline Esjay

  • Sr. Member
  • ****
  • Beiträge: 898
Antw:Flexibles Sprachanalysescript [39_Talk2Fhem.pm]
« Antwort #44 am: 23 Dezember 2017, 20:29:24 »
Den dummy welcher durch ifttt befüllt wird habe ich schon..Das klappt ohne probleme.
Ich habe keinen set befehl den ich auswählen kann.Die Auswahl ist leer..

Das ist der dummy
Internals:
   NAME       IFTTT
   NR         274
   STATE      ???
   TYPE       dummy
   READINGS:
     2017-12-23 17:47:53   alarm           Wohnzimmer Licht und Fernseher an
Attributes:
   room       Webhook

Das das Device

Internals:
   CFGFN     
   DEF        licht (\S+ ){0,2}(@rooms) (\S*) = set $2[@lights] $3{true=>"on", false=>"off"}
(@rooms) auf (@sender)   = set Fernseher_$1[@tvdev] command $2[@channel] ; set Fernseher_$1[@tvdev] command Select
(@rooms) licht (@colors) = set Licht_$1[@lightdev] hue $2[@huecolor]'

   NAME       talk
   NR         2569
   NTFY_ORDER 50-talk
   STATE      Initialized
   TYPE       Talk2Fhem
Attributes:
   T2F_keywordlist rooms = haus|..?berall,wohnung,wohnzimmer,esszimmer,bad\S*,toilette|wc,b..?ro,schlafzimmer,ankleide|garderobe,kinderzimmer,spielzimmer,flur|gang|diele,garage,garten,terrasse,balkon,eg|erdgescho\S*,og|obergescho\S* names = Mama,Papa,Sohn|Name,Tochter|Name
sender = ard|erste,zdf|zweite,rtl,sat 1,prosieben,kabel 1,rtl 2,vox,sixx
colors = blau,gelb,rot,magenta,gr..?n
   T2F_modwordlist lights = lampen_alle,lampen_alle,lampen_wohnzimer,lampen_esszimmer,,,,lampen_schlafzimmer,[...]
channel = Number1,Number2,Number3,Number4,Number5,Number6,Number7,Number8
tvdev = ,,Wohnzimmer,,Schlafzimmer,,
lightdev = ,,Wohnzimmer,,Schlafzimmer,Garten,Terrasse
huecolor = 240,40,360,320

Grüße
« Letzte Änderung: 23 Dezember 2017, 20:33:42 von Esjay »

 

decade-submarginal