[gelöst] Arduino Movi-Shield offline Spracherkennung in FHEM einbinden

Begonnen von joginet, 03 Februar 2018, 19:50:50

Vorheriges Thema - Nächstes Thema

joginet

Hallo Forum,
heute habe ich mein Arduino-Movi-Shield bekommen, damit möchte ich eine "offline" Sprachsteuerung für FHEM bauen.

Das Shield funktioniert prima, jetzt brauche ich noch die Verbindung zu FHEM. Ich habe es versucht mit ECMD.
Der Arduino hängt per USB am FHEM-Server (NUC mit Linux Mint).
Per
define movi ECMD serial /dev/ttyACM0@9600
kann ich den Arduino erreichen.
Ich verstehe aber die Sache mit der classdef nicht, die Beispiele und die commadref habe ich gelesen aber nicht verstanden.
Über den seriellen Monitor der Arduino IDE kann ich den "MOVIEvent" auslesen, mit dieser (Satz-)Nummer könnte ich eine FHEM-Aktion auslösen.
(siehe screenshot).
Hat jemand einen Tipp für mich, wie die classdef. aussehen muß?

Gruß, Jochen


Meine Konfig: FHEM auf NUC i5 mit Mint, HM-LAN, div. HM Schalter und Heizungsthermostate, FB 6840LTE mit Dect200, HUE bridge, HUE bulbs + Lightstrips, VU+Duo2 und Philips-TV Steuerung, Pushmail, Floorplan, Sprachsteuerung + Feedback per Arduino mit MOVI-Shield, LMS Multiroom mit 7x Pi

joginet

#1
Hallo nochmal,
Ich habe in FHEM schon viel erreicht, in der Regel durch "Copy&Paste" und Ausprobieren und dadurch dann auch "verstehen".
Aber diesmal bekomme ich es einfach nicht hin.
Ich habe mir jetzt alle verfügbaren Posts und Wikis durchgelesen. Die classdefs, die ich gefunden haben - z.B. um irgendwelche Ports auszulesen oder Temperatursensor-Werte zu erfassen - verstehe ich nicht, denn Sie enthalten "Device-spezifische Readings" wie "0R15" für Relais oder irgendwelche Temperaturwerte, Umwandlungen in Hex-Werte, usw.

Ich habe versucht, diese classdefs entsprechend "umzubauen" aber im Endeffekt weiss ich gar nicht, was ich da tue.
Ich dachte auch, mein Englisch wäre ganz ok, aber die ECMD, ECMDDevice und classdef-Beschreibungen in der Englischen Commandref habe ich auch nicht verstanden, ebensowenig die Perl-Syntax, die Separatoren, usw.
Um ehrlich zu sein, ich verstehe nur "Bahnhof".

Ich möchte den Wert "MOVIEvent [201}" hinter dem "#" aus meiner seriellen Kommunikation filtern (das ist sozusagen die "Satznummer") und zum schalten eines Device benutzen.

Das steht in meinem FHEM-Logfile wenn ich "GO DARK" für "Lampe aus" sage:

2018.02.04 08:06:58 3: MOVI: read MOVIEvent[141]: END ACTIVELISTEN\r\r\nMOVIEvent[201]: GO DARK\r\r\nMOVIEvent[202]: #1\r\r\nMOVIEvent[150]: SPEAKING\r\r\n (\115\117\126\111\105\166\145\156\164\133\061\064\061\135\072\040\105\116\104\040\101\103\124\111\126\105\114\111\123\124\105\116\015\015\012\115\117\126\111\105\166\145\156\164\133\062\060\061\135\072\040\107\117\040\104\101\122\113\015\015\012\115\117\126\111\105\166\145\156\164\133\062\060\062\135\072\040\043\061\015\015\012\115\117\126\111\105\166\145\156\164\133\061\065\060\135\072\040\123\120\105\101\113\111\116\107\015\015\012)

Wie gesagt, die Nummer hinter "MOVIEvent[202]: #"  brauche ich, in diesem Fall also die "1". Kann mir bitte jemand bei der classdef auf die Sprünge helfen?

Gruß, Jochen

PS: In vielen (ähnlichen) Posts steht dazu "lies Dich erstmal in die PERL-Materie ein". Das ist sicher sinnvoll und auch zielführend. Im Moment ist mein Bastel-Schwerpunkt aber die Spracherkennung und es fehlt mir "nur" an der Auflösung des seriellen Signals für ein ECMDDevice.
Meine Konfig: FHEM auf NUC i5 mit Mint, HM-LAN, div. HM Schalter und Heizungsthermostate, FB 6840LTE mit Dect200, HUE bridge, HUE bulbs + Lightstrips, VU+Duo2 und Philips-TV Steuerung, Pushmail, Floorplan, Sprachsteuerung + Feedback per Arduino mit MOVI-Shield, LMS Multiroom mit 7x Pi

CBSnake

Moin Jochen,
man könnte das Reading (ist es denn eins?) Mit userreading zerlegen und die Nummer extrahieren.
Könnte man nicht auch auf Go Dark triggern?
Grüße
Achim
FHEM auf Debian 10, HM-Wlan, JeeLink-Wlan, Wlanduino, ConBee, TP-Link Steckdose, GHoma Steckdosen, Shelly Steckdosen

joginet

#3
Moin Achim,
ja - das ist die Frage - wo bekomme ich ein Reading aus dem "unspezifiziertem" Traffic her.
Userreading habe ich auch schon versucht, in meinen classdef-versuchen habe ich auch schon versucht auf "DARK" zu triggern.
Wobei später (bei mehr Befehlen) die Satznummer natürlich einfacher ist.
Das ist auch egal, wenn ich es erstmal verstanden haben, kann ich es sicher umbauen.
Wenn ich es richtig verstanden habe, extrahiert die classdef erst das verwendbare Reading aus dem ganzen seriellen Traffic?

Gruß, Jochen
Meine Konfig: FHEM auf NUC i5 mit Mint, HM-LAN, div. HM Schalter und Heizungsthermostate, FB 6840LTE mit Dect200, HUE bridge, HUE bulbs + Lightstrips, VU+Duo2 und Philips-TV Steuerung, Pushmail, Floorplan, Sprachsteuerung + Feedback per Arduino mit MOVI-Shield, LMS Multiroom mit 7x Pi

CBSnake

Hmmm,
zu classdef muss ich mich auch erstmal einlesen ;-)
Auf die schnelle würde ich das mit doif und userreading oder notify und evtpart versuchen

Grüße
Achim, den Sprachsteuerung abseits von Amazon und Google auch brennend interessieren ;-)
FHEM auf Debian 10, HM-Wlan, JeeLink-Wlan, Wlanduino, ConBee, TP-Link Steckdose, GHoma Steckdosen, Shelly Steckdosen

joginet

Das einzige Event ist "UNKNOWNCODE", damit kann ich auch z.B. per DOIF reagieren  8)
Ich fürchte, ich komme nicht um die classdef herum - nur wie?
Meine Konfig: FHEM auf NUC i5 mit Mint, HM-LAN, div. HM Schalter und Heizungsthermostate, FB 6840LTE mit Dect200, HUE bridge, HUE bulbs + Lightstrips, VU+Duo2 und Philips-TV Steuerung, Pushmail, Floorplan, Sprachsteuerung + Feedback per Arduino mit MOVI-Shield, LMS Multiroom mit 7x Pi

Mike73

Hallo joginet,

geht denn dem erwarteten Datenstrom ein Kommando an den MOVI voraus ?  ( OK, MOVI kenne ich nicht, aber mit ECMD hab ich schon einiges gemacht )  .

Hast du denn schon eine Classdef?  Wie sieht dein Define vom MOVI aus ? 


Gruß

Mike 

joginet

#7
Moin,
Zitat( OK, MOVI kenne ich nicht, aber mit ECMD hab ich schon einiges gemacht )  .

Das hier ist der Movi: http://www.audeme.com/
Darauf gebracht hat mich dieser Thread: https://forum.fhem.de/index.php/topic,66748.msg746043.html#msg746043

Zitatgeht denn dem erwarteten Datenstrom ein Kommando an den MOVI voraus ?

Ja, ein Voice-Befehl.

ZitatWie sieht dein Define vom MOVI aus ? 

siehe erster Post: define movi ECMD serial /dev/ttyACM0@9600

Verbose=5. Ein classdef habe ich natürlich versucht anzubinden, momentan habe ich meine Versuche gerade wieder gelöscht.
Ich habe versucht, mir aus diversen Beispiel-classdefs etwas passendes zurechtzukopieren, leider ohne Erfolg.
Habe versucht, mit reading <reading> match "<regex>" eine Variable zu übergeben, allerdings scheitert es schon an der Übergabe an das ECMDDevice. Das habe ich angelegt, aber nicht verstanden.

Im Logfile wird alles angezeigt, was nötig wäre, nur im Event-Monitor kommt immer nur "UNKNOWNCOMMAND"

Ich bräuchte mal eine Erklärung "für Doofe", wie ich einen Wert mit der classdef extrahiere und an ein ECMDDecvice übergebe.

Gruß, Jochen
Meine Konfig: FHEM auf NUC i5 mit Mint, HM-LAN, div. HM Schalter und Heizungsthermostate, FB 6840LTE mit Dect200, HUE bridge, HUE bulbs + Lightstrips, VU+Duo2 und Philips-TV Steuerung, Pushmail, Floorplan, Sprachsteuerung + Feedback per Arduino mit MOVI-Shield, LMS Multiroom mit 7x Pi

joginet

Ok, evt. ein neuer Ansatz. Eventuell ist auch dieser falsch und nicht zielführend.
Ich habe mal Spasseshalber ein Jeelink-Device angelegt:

define myARDUINO JeeLink /dev/ttyACM0@9600
attr myARDUINO event-on-change-reading .*


Damit gibt es Events, zwar mit "UNKNOWNCODE" drin, aber ansonsten sauber und sortiert. Darauf müsste doch ein DOIF reagieren können?

2018-02-04 16:47:05 JeeLink myARDUINO UNKNOWNCODE MOVIEvent[200]: CALLSIGN DETECTED
2018-02-04 16:47:05 JeeLink myARDUINO UNKNOWNCODE MOVIEvent[140]: ACTIVELISTEN
2018-02-04 16:47:08 JeeLink myARDUINO UNKNOWNCODE MOVIEvent[141]: END ACTIVELISTEN
2018-02-04 16:47:08 JeeLink myARDUINO UNKNOWNCODE MOVIEvent[201]: GO DARK
2018-02-04 16:47:09 JeeLink myARDUINO UNKNOWNCODE MOVIEvent[202]: #1
2018-02-04 16:47:09 JeeLink myARDUINO UNKNOWNCODE MOVIEvent[150]: SPEAKING


Habe es bisher nicht hinbekommen...
Meine Konfig: FHEM auf NUC i5 mit Mint, HM-LAN, div. HM Schalter und Heizungsthermostate, FB 6840LTE mit Dect200, HUE bridge, HUE bulbs + Lightstrips, VU+Duo2 und Philips-TV Steuerung, Pushmail, Floorplan, Sprachsteuerung + Feedback per Arduino mit MOVI-Shield, LMS Multiroom mit 7x Pi

Mike73

Hallo Jochen,

zu ECMD ist da https://wiki.fhem.de/wiki/ECMD was gesagt. 

Grundsätzlich funktioniert ECMD so, dass du einen Befehl an das Gerät sendest und eine Antwort erwartest die du dann auswertest. WENN das MOVI nach diesem Prinzip arbeitet, kannst du das ECMD-Modul dazu "missbrauchen" .
Die Befehle werden mit den set/get-Aktionen des ECMD-Devices abgesetzt. Eben dazu brauchst du die classdef. Die legt fest, wie zB der set-Befehl als Kommando  an das MOVI geschickt wird.

However ..

Du brauchst eine classdef, die verbindest du mit dem ECMD-Gerät MOVI
attr MOVI classdefs <CLASS>=<pfad-und-dateiname-der-classdef>


Dann ein ECMDDevice zB

define meinVoice ECMDDevice
attr meinVoice IODev MOVI
attr meinVoice class <CLASS>


Dann kannst du mit

set meinVoice <befehl>


den Befehl an das MOVI schicken.

Sowei so gut.

Als Beispiel classdef kannst du die aus dem Wiki umbauen https://wiki.fhem.de/wiki/AVR-NET-IO#Digitale_Eing.C3.A4nge_in_FHEM_einbinden

Die Extraktion der Nummer aus der Ergebniszeile wird mitels eines regex ( regulären Ausdrucks) bewerkstelligt. Grundsätzliches Verständnis ist erforderlich : https://de.wikipedia.org/wiki/Regul%C3%A4rer_Ausdruck


Wenn du nun in der Classdef zB folgendes ersetzt:


get read postproc {\
m/read MOVIEvent\[(\d{1,3})\].*/ ;\
my $retval = $1;\
}


Dann sollte nach Abarbeitung des Befehls die (ein- bis) dreistellige Nummer in den eckigen Klammern im Reading "read" des Devices meinVoice zu finden sein.



joginet

#10
Ok, schonmal danke. Meine classdef. liegt in /opt/fhem/FHEM und heisst "ECMD_Arduino.classdef".
Also:
attr MOVI classdefs ABC=/opt/fhem/FHEM/ECMD_Arduino.classdef
richtig?

Für das ECMDDevice :

attr meinVoice class ABC

oder?

Meine classdef sieht so aus:

get read postproc {\
m/read MOVIEvent\[(\d{1,3})\].*/ ;\
my $retval = $1;\
}


ZitatDann sollte nach Abarbeitung des Befehls die (ein- bis) dreistellige Nummer in den eckigen Klammern im Reading "read" des Devices meinVoice zu finden sein.

Da steht nur "read". Was mache ich falsch?

Meine Konfig: FHEM auf NUC i5 mit Mint, HM-LAN, div. HM Schalter und Heizungsthermostate, FB 6840LTE mit Dect200, HUE bridge, HUE bulbs + Lightstrips, VU+Duo2 und Philips-TV Steuerung, Pushmail, Floorplan, Sprachsteuerung + Feedback per Arduino mit MOVI-Shield, LMS Multiroom mit 7x Pi

joginet

Ahh, ok - das habe ich überlesen:
ZitatGrundsätzlich funktioniert ECMD so, dass du einen Befehl an das Gerät sendest und eine Antwort erwartest die du dann auswertest. WENN das MOVI nach diesem Prinzip arbeitet, kannst du das ECMD-Modul dazu "missbrauchen" .

Ich glaube, es gibt da nichts zu senden. Ist mein ECMD-Ansatz evt. grundfalsch? Der Traffic ist ja zu sehen, aber nicht als Event - nur im log.

Gruß, Jochen

PS:
Hast Du meinen Post mit dem Jeelink-Device gesehen? Da gibt es sauber sortierte Events, kann ich evt. auf diese triggern - mit einen Userreading, z.B.?
Meine Konfig: FHEM auf NUC i5 mit Mint, HM-LAN, div. HM Schalter und Heizungsthermostate, FB 6840LTE mit Dect200, HUE bridge, HUE bulbs + Lightstrips, VU+Duo2 und Philips-TV Steuerung, Pushmail, Floorplan, Sprachsteuerung + Feedback per Arduino mit MOVI-Shield, LMS Multiroom mit 7x Pi

joginet

Uff - das war ein langer Tag ! Aber: der Durchbruch - man glaubt es kaum, ich habe es geschafft  ;D ;D ;D

Aber nicht mit dem ECMD Device sondern durch Anlegen einen "Pseudo JeeLink Devices".

define myARDUINO JeeLink /dev/ttyACM0@9600
attr myARDUINO event-on-change-reading .*


Das Teil hat dann ein Internal "RAWMSG" und auf dieses kann ich mit einem DOIF triggern:

define meinDoif DOIF ([myARDUINO:&RAWMSG] =~ "#0") (set Arbeitszimmer1 on) DOELSEIF ([myARDUINO:&RAWMSG] =~ "#1") (set Arbeitszimmer1 off)

Eigentlich ganz easy.
Im Movi-Sketch kann man ganz einfach Befehle eintragen, die Sätze haben dann "Satznummern". Diese liesst das DOIF aus den Internals aus. Möglich wäre auch das triggern auf den Text.

Ich sage: "Arduino" (Triggerword)
Arduino: (piep)
Ich: "Let there be light"
Arduino: "And there was light"
Im JeeLink Internal "MSGRAW" wird der MOVIEvent[201]:#0 ausgegeben, das DOIF triggert auf die "#0" und die Lampe "Arbeitszimmer1" geht an.
Bei "Go Dark" (=MOVIEvent [201]:#1) geht die Lampe aus.

Das ganze gibt es auch mit Deutscher Erkennung & Stimme, das muß ich noch einstellen. Fertig ist die Offline-Alexa !

Ich mach mir jetzt erstmal ein Pils auf und rede noch ein bisschen mit meiner Arbeitszimmerlampe  ;D

Vielen Dank nochmal für Eure Eingaben.

Gruß, Jochen
Meine Konfig: FHEM auf NUC i5 mit Mint, HM-LAN, div. HM Schalter und Heizungsthermostate, FB 6840LTE mit Dect200, HUE bridge, HUE bulbs + Lightstrips, VU+Duo2 und Philips-TV Steuerung, Pushmail, Floorplan, Sprachsteuerung + Feedback per Arduino mit MOVI-Shield, LMS Multiroom mit 7x Pi

CBSnake

FHEM auf Debian 10, HM-Wlan, JeeLink-Wlan, Wlanduino, ConBee, TP-Link Steckdose, GHoma Steckdosen, Shelly Steckdosen

joginet

Eine Sache noch:
solange das FHEM-device auf "opened" steht, kann man auf den Arduino keine Sketche hochladen (z.B. um neue Sätze einzufügen).
Da ist die USB-Schnittstelle dann vom FHEM blockiert.
Ich ändere dann kurzfristig die Schnittstelle des JeeLink-Devices in der DEF (z.b. in /dev/ttyACM3@9600) und nach upload wieder zurück.

Ansonsten ist das "Einlernen"  neuer Sätze denkbar einfach. Über die Arduino-IDE im MOVI-Sketch einfach eintragen + hochladen:

Für die Erkennung:

recognizer.addSentence("Aussenlicht an");   // Add German sentence 8

und für das Sprach-Feedback:

if (res==8) {                    // Sentence 8
    digitalWrite(led, HIGH);        // Turn on LED
    recognizer.say("Die Aussenbeleuchtung ist jetzt eingeschaltet!"); // Respond a sentence in German
  }


Deutsch kann er jetzt auch schon, der Kleine:

http://www.instructables.com/id/Connection-less-German-Speech-Recognition-and-Synt/

Die Deutsche Stimme ist nicht so perfekt wie bei Alexa&Co. und kann zum Beispiel keine
Umlaute. "Das Ku-echenlicht ist jetzt eingeschaltet!"  ;D

Ich habe aber beim Morgenkaffee bereits 3 Zimmer beleuchtungstechnisch plus die Aussenbeleuchtung plus den Multiroom-Lautsprecher in der Küche ("Arduino - Musik an !") eingebunden. Das geht wirklich fix.
Ich werde mir jetzt noch ein externes Mikrofon anschaffen, dann muß ich von der Küche aus nicht so schreien.
Außerdem: vielleicht eine nette Box für alles, noch liegt die nackte Platine a.d. Schreibtisch. Eine LED wird an den Arduino-PINs ja schon angesteuert, evt. kann man da was mit "Leuchtkranz" bei Spracherkennung und Voice-Feedback basteln.

Gruß, Jochen
Meine Konfig: FHEM auf NUC i5 mit Mint, HM-LAN, div. HM Schalter und Heizungsthermostate, FB 6840LTE mit Dect200, HUE bridge, HUE bulbs + Lightstrips, VU+Duo2 und Philips-TV Steuerung, Pushmail, Floorplan, Sprachsteuerung + Feedback per Arduino mit MOVI-Shield, LMS Multiroom mit 7x Pi

joginet

Nachtrag und ein erster Erfahrungsbericht:

1) das Movi-Shield vergibt die Satznummern nach der Reihenfolge im Sketch. Der erste Satz heisst  "#0", der Zweite "#1", usw.
Weil mein DOIF auf das Vorkommen der Satznummer im RAW reading triggert, ist natürlich bei Kommando "#10" Schluß.
(weil   =~ "#1" ja  "#1" findet, aber natürlich auch "#10","#11", usw.).

Ich habe das jetzt so gelöst, dass ich die ersten 4 Sätze mit "Quatsch-Kommandos" belegt habe. Also sowas wie "Arduino" - "Guten Morgen".
Antwort "Dir auch einen Guten Morgen, blabla".
Auf diese Kommandos muß FHEM nichts schalten, kein DOIF reagiert darauf und die RAW-Messages "#0","#1","#2",#3" kommen für FHEM nicht vor.
Ich kann also problemlos auf "10" "#11","#12"..."#20","#21",.. usw, triggern.

2) Erste Erfahrungen:
Die (Deutsche) Spracherkennung ist nicht immer einwandfrei. Es kommt immer Mal wieder vor, das Movi die Musik einschaltet, statt die Rollos zu öffnen.  :)
Das liegt aber nicht am FHEM, man kann in der seriellen Konsole der Arduino-IDE sehen, wie Movi die Sätze erkennt.
Über ein Low-Level Interface kann man an der MIkroempfindlichkeit schrauben und die gesprochenen Kommandos werden zur Kontrolle wiederholt. Für mich klingt das eigentlich ganz sauber, der MOVI scheint die Sätze auch richtig zu erfassen. Nur bei der richtigen Auswertung hapert es gelegentlich.
Trefferquote: wohlwollende 85% würde ich sagen, die meissten Fehler werden mit "I didn't understand that" quittiert..
Aber MOVI ist ja auch nur ein kleines Platinchen auf einem Arduino Uno - wie soll es da mit einem Großrechenzentrum wie bei Amazon, Google & Co. mithalten  :)

Gruß, Jochen

Noch ein Nachtrag: im Zuge meiner unzähligen Versuche mit verschiedenen Sprachbefehlen habe ich festgestellt, dass sich die Treffergenauigkeit deutlich erhöht, wenn man leiser spricht - also unterhalb der normalen Gesprächslautstärke. Es hat offensichtlich doch etwas mit dem Microfon-Threshold zu tun. Ich warte mal ab, bis mein externes Mikrofon kommt...
Meine Konfig: FHEM auf NUC i5 mit Mint, HM-LAN, div. HM Schalter und Heizungsthermostate, FB 6840LTE mit Dect200, HUE bridge, HUE bulbs + Lightstrips, VU+Duo2 und Philips-TV Steuerung, Pushmail, Floorplan, Sprachsteuerung + Feedback per Arduino mit MOVI-Shield, LMS Multiroom mit 7x Pi

JensS

Das sieht sehr interessant aus! Endlich mal ein funktionierender Ansatz bei einer Offline-Spracherkennung. Wo hast du den MOVI gekauft?

Gruß Jens
Debian auf APU2C4, HM-CFG-USB2, SIGNALduino, HM-ES-PMSw1-Pl, TFA 30.3121, TFA 30.3125, ITS-150, PIR-5000, configurable Firmata USB & LAN, 1-wire: DS-18B20, DS-18S20, DS-2408, DS-2413, diverse I2C-Komponenten, zigbee2mqtt, ESPEasy etc.

joginet

Moin,

ZitatWo hast du den MOVI gekauft?

ich hoffe, dass das keine unerlaubte Reklame ist. Ich habe den MOVI beim vermutlich einzigen Europ. Distributor für das Teil gekauft.
Der Laden heisst "Microchip Direct", die Sendung kommt dann relativ fix per TNT aus England.
Einfach bei audeme.com auf  "I want one" und dann auf "For our International Customers, buy from our distributor, Microchip Direct. "

Übrigens - hier ein Video über eine sehr coole Anbindung an OpenHAB via MQTT:

https://www.youtube.com/watch?v=7oy3UBMvoZs&t=20s

Die Erkennung funktioniert eindeutig zuverlässiger als bei mir. Der Unterschied: der Author verwendet einen Ardunio Mega 2560 mit dem Shield,
ich einen Uno. Ich habe den Eindruck,  dass die Erkennung mit Zunahme der Befehle/Sätze  und zus. mit dem Deutschen-Sprach-Model schwieriger geworden ist.
Evt. ist der UNO einfach überfordert. Ich hab' mir mal einen Mega 2560-Klon für 11€ zu Testzwecken bestellt.

Ich berichte weiter.

Gruß, Jochen
 
Auch hierzu noch ein Nachtrag:

1) Ich habe heute den MEGA 2560 bekommen. Der MOVI verschluckt jetzt keine Antworten mehr, insges. scheint das ganze ein klein wenig "performanter" - zumindest subjektiv.

2) Die Deutsche Erkennung ist nach wie vor mäßig. Ich habe mich sehr schwer mit einer "phonetischen Umschreibung" von "Küche" getan. Da vertut sich die Deutsche Erkennung am meisten - "Küh che" o.ä.  funktioniert ähnlich schlecht und "Licht im Zimmer wo wir kochen einschalten" war mir zu lang  ;D

Ich habe über instructables.com mit dem Autor des o.a. Videos Kontakt aufgenommen. Auch er musste die Erkennung "phonetisch" und seinem Dialekt entsprechend anpassen. Beispielsweise benutzt er als callsign "mowvi" statt "movi". Er benutzt ein ganz billiges "noName-Mikrofon". (Achtung: das Mikro muß einen Stereo-Klinkenstecker haben, Mono-Mikros brauchen einen Adapter)

3) ich habe daraufhin das Deutsche Sprach-model weggelassen und betreibe die Erkennung jetzt auf Englisch. Und siehe da: nahezu perfekt! Es passieren nur noch ganz wenige Fehler, trotzdem ich bereits viele Sätze in der Erkennung drin habe. Es liegt also eindeutig an der  Deutschen Erkennung...
Das System kann jetzt auch wesentlich kürzere Kommandos wie "kitchen on" oder "kitchen off" präzise auseinanderhalten.



 
Meine Konfig: FHEM auf NUC i5 mit Mint, HM-LAN, div. HM Schalter und Heizungsthermostate, FB 6840LTE mit Dect200, HUE bridge, HUE bulbs + Lightstrips, VU+Duo2 und Philips-TV Steuerung, Pushmail, Floorplan, Sprachsteuerung + Feedback per Arduino mit MOVI-Shield, LMS Multiroom mit 7x Pi

joginet

Ok, hier kommen weitere "Forschungs-Ergebnisse":

Die Erkennung funktioniert jetzt prima (auf Englisch), allerdings steht das Ding jetzt direkt vor meinem FHEM-NUC.
Es wäre doch doof in jeden Raum ein USB- oder Mikrofon-Kabel zu verlegen.

Da ich hier noch einige ungenutze Pis herumliegen hatte, habe ich mir auf einem PI2 ein frisches FHEM installiert. An diesem habe ich dann den Arduino
mit dem Movi-Shield angeschlossen und das Ganze als JeeLink-Device angelegt:

define myArduino1 JeeLink /dev/ttyACM0@9600
attr myArduino1 event-on-change-reading .*


Dann habe ich (wie hier beschrieben: https://forum.fhem.de/index.php/topic,25399.msg183910.html#msg183910 )
im Linux -Terminal meines (Haupt)FHEM-Servers folgendes ausgeführt:

mkfifo /tmp/jdummy

Im "Haupt-FHEM" habe ich dann einen JeeLink dummy angelegt:

define myArduino1 JeeLink /tmp/jdummy@directio
attr myArduino1 event-on-change-reading .*


dazu ein FHEM2FHEM device:

define remotepi1 FHEM2FHEM IP_meines_Client_PI:7072 LOG:.*

Das erzeugt folgende Readings im JeeLink dummy "myArduino1":

UNKNOWNCODE MOVIEvent[140] ACTIVELISTEN 2018-02-10 19:40:46
UNKNOWNCODE MOVIEvent[141] END ACTIVELISTEN 2018-02-10 19:40:50
UNKNOWNCODE MOVIEvent[150] SPEAKING 2018-02-10 19:40:52
UNKNOWNCODE MOVIEvent[151] END SPEAKING 2018-02-10 19:40:59
UNKNOWNCODE MOVIEvent[200] CALLSIGN DETECTED 2018-02-10 19:40:46
UNKNOWNCODE MOVIEvent[201] HOMEOFFICE ON 2018-02-10 19:40:51
UNKNOWNCODE MOVIEvent[202] #7 2018-02-10 19:40:52


mit
attr myArduino1 stateFormat { ReadingsVal("myArduino1","UNKNOWNCODE MOVIEvent[202]",0);; }

setze ich den Status des JeeLink dummies auf die Satznummer, im Beispiel die "#7"

Ein DOIF kann jetzt auf diese Satznummer reagieren:

define ARD1 DOIF ([myArduino1:"#7"]) (set Arbeitszimmer1 on,set Arbeitszimmer2 on) DOELSEIF ([myArduino1:"#8"]) (set Arbeitszimmer1 off,set Arbeitszimmer2 off)
attr ARD1 do always


Jetzt könnte ich also den Pi und den Arduino mit Movi zusammen in eine kleine, nette Mini-Lautsprecher-Box bauen und in jedes Zimmer stellen, wo es gebraucht wird. Verbunden wird das ganze dann per WLAN mit der Haupt-FHEM-Instanz. Der Arduino könnte gleich die passende LED dazu ansteuern.

Gruß, Jochen

Nachtrag: Das Teil hört jetzt auf den Namen "Moneypenny". Die Dame wohnt momentan noch in einem Eierkarton bei uns in der Küche, soll dann aber irgendwann umziehen in ein schickes Gehäuse:

https://www.bramborka.com/fp/moneypenny.mp4

Ein Foto der "pre-alpha" habe ich angehängt  ;D
Meine Konfig: FHEM auf NUC i5 mit Mint, HM-LAN, div. HM Schalter und Heizungsthermostate, FB 6840LTE mit Dect200, HUE bridge, HUE bulbs + Lightstrips, VU+Duo2 und Philips-TV Steuerung, Pushmail, Floorplan, Sprachsteuerung + Feedback per Arduino mit MOVI-Shield, LMS Multiroom mit 7x Pi

JensS

Hallo Jochen,

konntest du deinem MOVI inzwischen deutsch beibringen?

Gruß Jens
Debian auf APU2C4, HM-CFG-USB2, SIGNALduino, HM-ES-PMSw1-Pl, TFA 30.3121, TFA 30.3125, ITS-150, PIR-5000, configurable Firmata USB & LAN, 1-wire: DS-18B20, DS-18S20, DS-2408, DS-2413, diverse I2C-Komponenten, zigbee2mqtt, ESPEasy etc.

joginet

Moin Jens!
Nein, das habe ich bisher nicht weiter verfolgt. Der Movi kann schon Deutsch, aber man muss für die perfekte Erkennung phonetisch schon etwas umbauen. Englisch klappt nahezu "out of the box ". Ich habe mittlerweile viele tolle Sachen eingebaut, z.B. eine Realtime-clock und einen "nested dialogue" für mein Multiroom Audio. Mehr dazu später, bin z.Zt. für ein paar Tage im Ausland.
Gruss, Jochen
Meine Konfig: FHEM auf NUC i5 mit Mint, HM-LAN, div. HM Schalter und Heizungsthermostate, FB 6840LTE mit Dect200, HUE bridge, HUE bulbs + Lightstrips, VU+Duo2 und Philips-TV Steuerung, Pushmail, Floorplan, Sprachsteuerung + Feedback per Arduino mit MOVI-Shield, LMS Multiroom mit 7x Pi

joginet

Und ein neuer Nachtrag, ich habe viel gebastelt  ;D


1) weitere Pis mit Movi-Shield ins FHEM einbinden / Sprachsteuerung "überall"

Die Anbindung weiterer Pis mit Arduino+Movishield für die Spracherkennung in weiteren (Ziel: in allen!) Räumen ist sehr einfach:
Ich habe mich für die weiteren Pis für das Modell "Pi 3" entschieden, denn das hat WLAN an Bord. Die Erklärung, wie man Raspbian und FHEM
auf einem PI installiert und wie man die IP-Adresse festlegt schenke ich mir mal.
Um schnell meinen Arduino-Sketch auf alle Pis zu bekommen, habe ich die aktuelle Arduino IDE auf den Pi geladen. Die IDE in den Repositories des Pi ist leider stark veraltet. Ihr müsst Euch also die aktuelle IDE für ARM herunterladen:

https://www.arduino.cc/en/Main/Software

Um die IDE zu installieren, muß man im Downloadverzeichnis das Script ausführen:
sudo ./install.sh

Um die "headless" Pis mit den daran angeschlossenen Arduinos zu bedienen, habe den RDP-Server XRDP installiert.
Achtung: vorher muß der RealVNC-Server runter - die beiden beissen sich:

sudo apt-get purge realvnc-vnc-server
sudo apt-get update
sudo apt-get install xrdp


Zuletzt muß im aktuellen Raspbian noch ssh aktiviert werden. Dass kann man über die GUI erledigen:
Einstellungen --> Raspberry-Pi-Konfiguration --> Schnittstellen

Mit "passwd" dann im Terminal noch ein eigenes Passwort setzen. Es wird nach dem bisherigen Passwort gefragt, das ist per default "raspberry".

Jetzt kann man mit einem RDP-Client (unter Linux  benutze ich Remmina) auf das Desktop des PIs und auf die Arduino-IDE zugreifen.
Achtung: es wird - anders als bei klassischer Fernwartung - für die RDP-Sitzung ein eigenes Desktop aufgemacht.

Im FHEM auf dem Pi dann noch:

define myArduino1 JeeLink /dev/ttyACM0@9600
attr myArduino1 event-on-change-reading .*


und auf dem "Haupt-FHEM" ein weiteres FHEM2FHEM device für jeden zusätzlichen MOVI-Pi:

define remotepi2 FHEM2FHEM IP_meines_2tenPI:7072 LOG:.*
define remotepi3 FHEM2FHEM IP_meines_3ten_PI:7072 LOG:.*
...
...


Da alle Pis die gleichen readings erzeugen, triggern alle für den MOVI angelegten DOIFS auf alle Pis.
Den Arduino-Sketch und die Libraries schiebe ich per Filezilla auf die Pis und binde sie dann per Arduino IDE ein.
Ich habe mir eine SD-Karte mit einer fertigen Installation geklont. So brauche ich diese nur in weitere Pis zu stecken und die IP zu ändern,
der Rest passiert dann wie beschrieben per RDP.

Uhrzeit und Datum ansagen lassen:

Für ganz kleines Geld gibt es eine "Real-Time-Clock" für den Arduino.
Hier gibt es einen Beitrag, der die Installation beschreibt:

https://www.instructables.com/id/Voice-Controlled-Clock-With-Arduino-no-WiFi-No-PC/

Ich habe die dazugehörige library hier heruntergeladen: https://github.com/adafruit/RTClib
und per

#include "RTClib.h"

in den Arduino Sketch eingebunden. Die Zeilen des Uhrzeit-Sketches
habe ich in meinem Sketch integriert. Ich kann den Movi jetzt also nach Uhrzeit und Datum fragen, einen Timer für die Frühstückseier
setzen, usw.

Demo (es spricht meine "zweite" Moneypenny in der Küche mit einem Pi3 im Gehäuse eines alten Kabelmodems):

Demo-Video Datum und Uhrzeit:
  https://www.bramborka.com/fp/time_and_date.mp4
Demo-Video Timer: https://www.bramborka.com/fp/timer.mp4

Steuerung meiner Multiroom-Lautsprecher (FHEM/Squeezebox):

Mit der Movi-Library werden verschiedene Beispiel-Sketche angeboten, u.a. der "NestedDialog".
(In der Arduino IDE zu finden unter "Beispiele-->MOVI(tm)Voice Dialog Shield--> intermediate--> NestedDialog").

Hiermit kann ich z.B. folgenden Dialog erreichen:

Ich: "Moneypenny, spiele Musik!"
Moneypenny: "welchen Spieler möchtest Du?"
Ich:"Badezimmer!"
Moneypenny: "Welche Playliste oder welchen Sender soll ich spielen?"
Ich: "Latina!"
Moneypenny: "Ich spiele jetzt Radio Latina auf dem ausgewählten Player!"

Demo-Video NestedDialog: https://www.bramborka.com/fp/music.mp4

Ich habe also das Beispiel "NestedDialog" zusätzlich in meinen Sketch eingebaut.
Wie weiter oben beschrieben, triggern meine DOIFs im Haupt-FHEM ja auf die eindeutigen Satznummern,
die kommen beim "NestedDialog" nicht vor.
Also habe ich hier eine Umleitung gebaut: die Player-DOIFs reagieren auf eine Variable "#8" für Musik,
zweite Stelle für den Player, dritte Stelle für die Playlist.

Also: Event "#821" = Musik, Player 2, Playlist 1.

Mit Serial.println übergebe ich das "Reading" an das Haupt-FHEM.

Anders ausgedrückt:

Moneypenny: "welchen Spieler möchtest Du?"
Ich:"Badezimmer!" --> Variable Player wird gesetzt
Moneypenny: "Welche Playliste oder welchen Sender soll ich spielen?"
Ich: "Latina!" --> Variable Playlist wird gesetzt
Moneypenny: "Ich spiele jetzt Radio Latina auf dem ausgewählten Player!"

Im Arduino-Sketch sieht das im Wesentlichen so aus:

// choose Player
 
  if (context==BOOT) { // MOVI just started
        if (res==20) {
            recognizer.ask(F("What Player do you choose?"));
            context=PLAYER;
            sbp=0;
                   }
  }
   if (context==PLAYER) {
           if (res==45) { // player living room
           recognizer.say(F("player living room choosen"));
           recognizer.ask(F("What Playlist or Station do you choose?"));
           context=PLAYLIST;
           sbp=1;
                  }
        if (res==46) { // player kitchen
           recognizer.say(F("player kitchen choosen"));
           recognizer.ask(F("What Playlist or Station do you choose?"));
           context=PLAYLIST;
            sbp=2;
        }
         if (res==47) { // player bathroom
           recognizer.say(F("player bathroom choosen"));
           recognizer.ask(F("What Playlist or Station do you choose?"));
           okresponse=true;
           context=PLAYLIST;
           sbp=3;
        }
        if (res==48) { // player outside
           recognizer.say(F("player outside choosen"));
           recognizer.ask(F("What Playlist or Station do you choose?"));
           context=PLAYLIST;
           sbp=4;
        }
   }
   if (context==PLAYLIST) {
           if (res==50) { // NDR2
           recognizer.say(F("I am now playing ND R2 on the selected player"));
           context=BOOT;
           playlst=1;
           String Au1=String (sbp,DEC);
           String Au2=String (playlst,DEC);
           String Au4=Au3+Au1+Au2;
           Serial.println(Au4);
           
        }
        if (res==51) { // LATINA
           recognizer.say(F("I am now playing LATINA on the selected player"));
           context=BOOT;
           playlst=2;
           String Au1=String (sbp,DEC);
           String Au2=String (playlst,DEC);
           String Au4=Au3+Au1+Au2;
           Serial.println(Au4);
           
           
        }
         if (res==52) { // Barbaras Liste
           recognizer.say(F("I am now playing Barbaras Playlist on the selected player"));
           context=BOOT;
           playlst=3;
           String Au1=String (sbp,DEC);
           String Au2=String (playlst,DEC);
           String Au4=Au3+Au1+Au2;
           Serial.println(Au4);
                     
        }
         if (res==53) { // Jochens Liste
           recognizer.say(F("I am now playing Jochens playlist on the selected player"));
           context=BOOT;
           playlst=4;
           String Au1=String (sbp,DEC);
           String Au2=String (playlst,DEC);
           String Au4=Au3+Au1+Au2;
           Serial.println(Au4);
           
           
        }
       


Und so sieht das passende DOIF im Haupt-FHEM aus:

define play22 DOIF[ ([myArduino1:state] =~ "#822") (set JNSKuechePower on,set Kueche on,set Kueche playlist play latina)
attr play22 do always


Natürlich sind weitere Befehle wie Sync. und Lautstärke möglich, soweit bin ich aber noch nicht.

Ansage des Wetters:

Der Movi kann in zwei Richtungen kommunizieren. Ich kann über:

{system("echo SAY test > /dev/ttyACM0")}

vom FHEM des jewiligen MOVI-Pis einen Text (hier "test") vorlesen lassen.
Da auch eine "offline-Alexa" über das Wetter informieren können
muß, habe ich folgendes gemacht:

Achtung: das passiert alles im FHEM des/der Movi-Pi(s), nicht im Haupt-FHEM

Ich habe ein "Weather" - device angelegt: https://wiki.fhem.de/wiki/Weather

define MeinWetter Weather 676378 3600 de

Da Moneypenny noch Englisch spricht, habe ich das "de" weggelassen. Euren Städtecode bekommt ihr wie im Wiki beschrieben.

dann:

define forecast dummy

Diesen dummy kann ich schonmal mit den Readings aus dem Weather-Device plus etwas Zwischentext  befüllen:

{ fhem("set forecast " ."The weather in ".(ReadingsVal("MeinWetter","city",0)." today is ". ReadingsVal("MeinWetter","condition",0)).". The temperature currently is ". ReadingsVal("MeinWetter","temp_c",0)." degrees celsius. The forecast for tomorrow will be ".ReadingsVal("MeinWetter","fc2_condition",0)." and a maximum temperature of ".ReadingsVal("MeinWetter","fc2_high_c",0)." degrees celsius. ") }

Merkwürdigerweise konnte ich nicht direkt in einem DOIF auf ein "MOVI-Event" reagieren, die "system"-Ausgabe gibt den Wert "-1" zurück und damit macht das DOIF (oder ich?) einen Fehler. Egal, über den Umweg dummy+notify geht es:

define wetterdummy dummy
attr wetterdummy setList on off
define wspeech_on notify wetterdummy:on {my $wetter = ReadingsVal("forecast","state",0);;system("echo SAY $wetter > /dev/ttyACM0")}


Im Arduino Sketch passiert bei Anfrage nach dem Wetter folgendes:

if (res==54) {                    // Sentence 53
    digitalWrite(led, HIGH);        // Turn on LED
    Serial.println("wetter"); // Ausgabe wetterdummy on
    Serial.println("..."); // Ausgabe wetterdummy off
    digitalWrite(led, LOW); //Turn off LED
  }


Im FHEM reagiert ein DOIF darauf:

define forecast_act DOIF ([myArduino1:&RAWMSG] =~ "wetter") (set wetterdummy on) DOELSEIF ([myArduino1:&RAWMSG] =~ "...") (set wetterdummy off)
attr forecast_act do always


Und damit das Wetter immer schön aktuell bleibt, wird der dummy "forecast" bei Aktualiserung des Devices "MeinWetter" neu befüllt:

define wetteraktuell notify MeinWetter.* { fhem("set forecast " ."The weather in ".(ReadingsVal("MeinWetter","city",0)." today is ". ReadingsVal("MeinWetter","condition",0)).". The temperature currently is ". ReadingsVal("MeinWetter","temp_c",0)." degrees celsius. The forecast for tomorrow will be ".ReadingsVal("MeinWetter","fc2_condition",0)." and a maximum temperature of ".ReadingsVal("MeinWetter","fc2_high_c",0)." degrees celsius. ") }


Demo-Video Ansage des Wetters: https://www.bramborka.com/fp/weather.mp4

Puh, langer Text. ich hoffe, alles ist einigermassen verständlich und ich habe nicht zu viele Fehler in diesen Text kopiert.
Eventuell ist diese Beschreibung ja für den einen oder anderen "MOVI"-Bastler hilfreich. Meine Offline-Alexa wird jedenfalls langsam gesprächiger  ;D

Viele Grüße, Jochen
Meine Konfig: FHEM auf NUC i5 mit Mint, HM-LAN, div. HM Schalter und Heizungsthermostate, FB 6840LTE mit Dect200, HUE bridge, HUE bulbs + Lightstrips, VU+Duo2 und Philips-TV Steuerung, Pushmail, Floorplan, Sprachsteuerung + Feedback per Arduino mit MOVI-Shield, LMS Multiroom mit 7x Pi

JensS

Hallo Jochen,

vielen Dank für die ausführliche Beschreibung. Ich werde mir wohl auch einen MOVI +Arduino Mega + RP3 gönnen.  :)

Gruß Jens
Debian auf APU2C4, HM-CFG-USB2, SIGNALduino, HM-ES-PMSw1-Pl, TFA 30.3121, TFA 30.3125, ITS-150, PIR-5000, configurable Firmata USB & LAN, 1-wire: DS-18B20, DS-18S20, DS-2408, DS-2413, diverse I2C-Komponenten, zigbee2mqtt, ESPEasy etc.

joginet

Hallo Jens,
ich glaube, Du wirst es nicht bereuen. Das Ganze hat nicht wirklich den Funktions- und Leistungsumfang von Alexa und Co., macht aber als "homebrew"-System m.E. viel mehr Spaß als die "Fertiglösung".
Ein wesentlicher Vorteil ist natürlich, dass alles "Cloudfree" und "Offline" funktioniert.

Hier noch zwei Tipps zur Bedienung:

1) Wenn das FHEM auf dem Client-Pi an der USB-Schnittstelle ,,lauscht" ist diese blockiert.
Es gibt in der Arduino-IDE dann eine Fehlermeldung beim Upload eines neuen oder geänderten Sketches.
Abhilfe: im FHEM des Client-Pis muß das JeeLink-Device kurzfristig auf eine andere Schnittstelle.
Im FHEM-web auf das Device klicken und bei ,,DEF" z.B. /dev/ACM0@9600 in /dev/ACM1@9600 ändern.
Der state wechselt dann auf ,,disconnected" und dann funktioniert der Sketch-Upload. Wenn alles auf den Arduino hochgeladen ist,
Schnittstelle wieder ändern.

2) Wenn irgendetwas im Sketch geändert wurde und/oder die Schnittstelle wie in Punkt 1 beschrieben kurzzeitig geändert wurde,
dann braucht das FHEM2FHEM -Device im Haupt-FHEM ein ,,set mein_Client_Pi reopen".
Wenn man mehrere Clients geändert hat, ist es natürlich mühsam, das "reopen" bei jedem einzelnen auszuführen.
Also habe ich mir einen ,,pi-reopen" dummy gebaut.
Ein DOIF triggert auf diesen dummy führt den Befehl dann für alle FHEM2FHEM-Pis gleichzeitig aus:

define pi_reopen dummy
attr pi_reopen setList on off
define pi_reopen_act DOIF ([pi_reopen:"on"]) (set remotepi1 reopen,set remotepi2 reopen,...,set pi_reopen off)
attr pi_reopen_act do always


3) Der MOVI verfügt über ein "LowLevel Interface". Damit kann man z.B.die Systemmeldungen ("there is a lot of noise in the room") abstellen oder den Mikrofon-Threshold für die optimale Erkennung einstellen. Der Hersteller hat dafür einen eigenen Sketch bereitgestellt. Wenn man diesen Sketch hochlädt, kann man das LowLevel-Interface über den Seriellen Monitor der Arduino IDE bedienen. Es geht aber auch viel einfacher: man kann einfach über das Terminal des Pis darauf zugreifen:

echo "SYSTEMMESSAGES OFF" > /dev/ttyACM0

oder über die FHEM-Kommandozeile:

{system("echo SYSTEMMESSAGES OFF > /dev/ttyACM0")}


Die Systemrückmeldungen werden im Event Monitor von FHEM angezeigt. "HELP" gibt eine Liste der möglichen Befehle aus. Für diese Variante muß der PI nichtmal "disconnected" werden (wie in Punkt 1 beschrieben)

Gruß, Jochen

PS: angehängt habe ich noch ein Foto meiner "aktuellen Gehäuseversion".
Die "Technik" kann hinter einem Schrank oder auf einem Regal verschwinden, nur der Lautsprecher und das 360°-Mikro (das ist der kleine "Hut" auf dem Lautsprecher) sind sichtbar. Ein winziges "Frontend" sozusagen.
Meine Konfig: FHEM auf NUC i5 mit Mint, HM-LAN, div. HM Schalter und Heizungsthermostate, FB 6840LTE mit Dect200, HUE bridge, HUE bulbs + Lightstrips, VU+Duo2 und Philips-TV Steuerung, Pushmail, Floorplan, Sprachsteuerung + Feedback per Arduino mit MOVI-Shield, LMS Multiroom mit 7x Pi

joginet

Alexa goes private mit MOVI

Hallo Forum,
ich lebe jetzt eine ganze Zeit mit Moneypenny zusammen (Beschreibung siehe weiter oben) und die Sprachsteuerung klappt auch sehr gut. Der Nachteil einer "offline"-Sprachsteuerung ist natürlich, dass sie "offline" ist. Fragen nach Zugverbindung, Stau, "wie hiess der letzte Kaiser von China" funktionieren so natürlich nicht.

Cloudlösungen von Amazon oder Google können da deutlich mehr, sind aber natürlich "Wanzen" - wie schlimm oder nicht, das mag jeder für sich selbst beurteilen.

Im Internet bin ich jetzt auf diese nette Bastellösung gestoßen: https://www.instructables.com/id/Project-Alias

Im wesentlichen ist das ein Deckel, der auf ein Google oder Amazon-Gerät gesetzt wird. Der Deckel enthält einen Pi, ein Mikrofon-Shield und zwei kleine Lautsprecher. Per selbst definiertem "Triggerword" flüstern diese Lautsprecher "ALEXA" (oder "OK Google") in das Gerät und aktivieren so Alexa (oder Google). Wenn das Triggerword nicht fällt, kommt aus den Lautsprechern ein "Stimmengemurmel" und Alexa oder Google versteht nur noch Bahnhof.
Das ganze ist so leise, dass man es von Aussen nicht hört und die "Wanze" ist somit abgeschaltet.

Ich bin eigentlich komplett  gegen Cloudlösungen aber ich habe mir gedacht, damit könnte ich leben und habe das Projekt nachgebaut.
Ich bin dabei aber nicht so richtig glücklich geworden. Das Triggerword wird per Keras "Deep-Learning" eingelernt.  Das ist sehr komplex und man muß v.a. auch negativ-Beispiele (z.B. Hintergrundgeräusche) einlernen. Das Ding triggert bei allen möglichen Geräuschen (gelegentlich auch bei "Alexa") und dann sagt es "Alexa" gerne 2 oder 3 mal und würgt damit die Alexa-Aktion damit ab. Kurz: ich habe keine stabile Triggerworderkennung hinbekommen.

Also habe ich die Alias-Software mal rausgeschmissen und mich auf die gute alte Moneypenny besonnen. Da muß das Triggerword ja nur in den Sketch und es muß nichts eingelernt werden.

Bei meinen Moneypennies ist der Arduino ja schon über seriell (=USB) am FHEM-Pi. Also habe ich mir auf dem Pi einen MPD installiert wie hier beschrieben:

https://forum-raspberrypi.de/forum/thread/326-music-player-daemon-mpd-und-mpc-auf-dem-raspberry-pi/

Ein kurzer Abriss:

JSON installieren:

sudo apt-get install libjson-perl

und das Perl-Modul XML:Simple:

sudo apt-get install libxml-simple-perl

MPD installieren:

sudo apt-get update
sudo apt-get install mpd mpc alsa-utils
sudo modprobe snd_bcm2835
sudo amixer cset numid=3 1


dann die Zeile

snd-bcm2835

per sudo nano /etc/modules in die /etc/modules eintragen

Berechtigungen setzen:

sudo chmod g+w /var/lib/mpd/music/ /var/lib/mpd/playlists/
sudo chgrp audio /var/lib/mpd/music/ /var/lib/mpd/playlists/


und die 2 Dateien "alexa.wav"(oder "google.wav") und "noise.wav" in das Verzeichnís /var/lib/mpd/music kopieren.

Die Sound-Dateien gibt es auf der Github-Seite des Alias Autors:
https://github.com/bjoernkarmann/project_alias/tree/master/data

dann den MPD neu starten:

sudo /etc/init.d/mpd restart
sudo mpc update


Im FHEM auf dem Pi:

define myMPD MPD (weil der MPD auf dem gleichen Server läuft)

Dann wieder das Pseudo-Jeelink device definieren (siehe Beschreibung Moneypenny):

define myArduino2 JeeLink /dev/ttyACM0@9600
attr myArduino2 event-on-change-reading .*


Der Arduino-Sketch sieht so aus:



#include "MOVIShield.h"     // Include MOVI library, needs to be *before* the next #include

#if defined(ARDUINO_ARCH_AVR) || defined(ARDUINO_ARCH_PIC32)
#include <SoftwareSerial.h> // This is nice and flexible but only supported on AVR and PIC32 architecture, other boards need to use Serial1
#endif

MOVI recognizer(true);            // Get a MOVI object, true enables serial monitor interface, rx and tx can be passed as parameters for alternate communication pins on AVR architecture boards

const int led =45 ;

void setup() 
{
   pinMode(led, OUTPUT);
  recognizer.init();      // Initialize MOVI (waits for it to boot)
  recognizer.setSynthesizer(SYNTH_PICO,"-l=de-DE");
  //*
 
  // Soft call sign.
  recognizer.addSentence("moneypenny"); // Sentence 1 will serve as a call sign
  recognizer.addSentence("the"); // #2
  recognizer.addSentence("be");  // #3
  recognizer.addSentence("to");  // #4
  recognizer.addSentence("of");  // #5
  recognizer.addSentence("a");   // #6
  recognizer.addSentence("in");  // #7
  recognizer.addSentence("that"); // #8
  recognizer.addSentence("have"); // #9
  recognizer.addSentence("I");    // #10
  recognizer.addSentence("it");   // #11
  recognizer.addSentence("for");  // #12
  recognizer.addSentence("not");  // #13
  recognizer.addSentence("on");   // #14
  recognizer.addSentence("with"); // #15
  recognizer.addSentence("he");   // #16
  recognizer.addSentence("as");   // #17
  recognizer.addSentence("you");  // #18
  recognizer.addSentence("do");   // #19
  recognizer.addSentence("at");   // #20
  recognizer.addSentence("wo");   // #21
  recognizer.addSentence("ihnen");   // #22
  recognizer.addSentence("der"); // #23
  recognizer.addSentence("ist");  // #24
  recognizer.addSentence("zu");  // #25
  recognizer.addSentence("von");  // #26
  recognizer.addSentence("ein");   // #27
  recognizer.addSentence("innen");  // #28
  recognizer.addSentence("das"); // #29
  recognizer.addSentence("habe"); // #30
  recognizer.addSentence("ich");    // #31
  recognizer.addSentence("du");   // #32
  recognizer.addSentence("fuer");  // #33
  recognizer.addSentence("nicht");  // #34
  recognizer.addSentence("an");   // #35
  recognizer.addSentence("mit"); // #36
  recognizer.addSentence("er");   // #37
  recognizer.addSentence("als");   // #38
  recognizer.addSentence("wir");  // #39
  recognizer.addSentence("machen");   // #40
  recognizer.addSentence("bei");   // #41

 
  recognizer.train();                          // Train (may take 20seconds)
  //*

  // Reconfigure MOVI
  recognizer.beeps(false);                      // turns the beeping off
  recognizer.welcomeMessage(false);             // turns off MOVI welcome message
  recognizer.responses(false);                  // turns of MOVI's responses
  recognizer.ask();                             // Skip waiting for MOVI's callsign
 
  recognizer.say("Ich bin bereit.");     // Say a welcome message
 
  recognizer.setThreshold(5); // uncomment and set to a higher value (valid range 2-95) if you have a problems due to a noisy environment.
}

void loop() // run over and over
{
  signed int event=recognizer.poll();       // Get result from MOVI, 0 denotes nothing happened, negative values denote events (see docs)
   
 
  if (event==1) {    // This is our self-programmed call sign
       Serial.println("alexa");
       digitalWrite(led, HIGH);
       delay(1000); 
       digitalWrite(led, LOW);
       Serial.println("clear");
       delay(1000);
       recognizer.say("Ja bitte?"); 
       digitalWrite(led, HIGH);
       delay(3000); 
       digitalWrite(led, LOW);
       recognizer.ask();
             }
   
 
  if ((event>1 || event==SILENCE || event==UNKNOWN_SENTENCE)) { // If it's not the call sign and we are not listening
   
    //recognizer.say("false");
    Serial.println("noise");
    Serial.println("clear");
    recognizer.ask();    // silently ignore what was said, and tell MOVI to listen again
  }
    Serial.println("noise");
}



(Warum so viele "Sätze"? Auch MOVI braucht "negativ-Beispiele" um das Trigger-Word genau herauszuhören...)

ACHTUNG: zum Upload des Sketches muß das Jeelink-Device disconnected sein, sonst ist die Schnittstelle blockiert. Dazu im Device unter DEF kurzfristig die Schnittstelle ändern (z.B. in /dev/ttyACM1@9600)

Wenn der Arduino jetzt das Triggerword "Moneypenny" erkennt, wird über  "Serial.println" "alexa" oder "noise" vom Arduino ausgegeben.

Das FHEM auf dem Pi triggert auf diesen seriellen Input. Wenn "noise.wav" abgespielt werden soll wird der MPD auf "repeat" gesetzt, "alexa" soll er ja nur einmal sagen. (beim MPD gibt es kein repeat on/off - nur toggle - also muß das Status-Reading "repeat" ausgelesen werden):

,,alexa" wird vom Arduino empfangen und ,,repeat" vom MPD ist aus

define alexa0 DOIF ([myArduino2:&RAWMSG] =~ "alexa" and [myMPD:repeat] eq "0")(set myMPD stop,set myMPD playfile alexa.wav)

,,alexa" wird vom Arduino empfangen und ,,repeat" vom MPD ist an

define alexa1 DOIF ([myArduino2:&RAWMSG] =~ "alexa" and [myMPD:repeat] eq "1")(set myMPD repeat,set myMDP playfile alexa.wav)

,,noise" wird vom Arduino empfangen und ,,repeat" vom MPD ist aus:

define noise0 DOIF ([myArduino2:&RAWMSG] =~ "noise" and [myMPD:repeat] eq "0")(set myMPD repeat,set myMDP playfile noise.wav)

,,noise" wird vom Arduino empfangen und ,,repeat" vom MPD ist an:

define noise1 DOIF ([myArduino2:&RAWMSG] =~ "noise" and [myMPD:repeat] eq "1")(set myMPD playfile noise.wav)

Das Logfile habe ich abgeschaltet

attr Logfile disable 1

Es geht jetzt also folgendes:


Alexa hört erstmal gar nicht, da kann ich "ALEXA" schreien, wie ich will.
Sage ich "Moneypenny" sagt Moneypenny "Ja, bitte?" Und flüstert Alexa "Alexa" ins Ohr.
Dann kann ich ganz normal weiterreden "Schalte das Licht im Wohnzimmer an", "wer war der letzte Kaiser von China", usw.
Damit ist die Wanze auf "privat" geschaltet.

Zur Mechanik:
die 3D-Druckdateien für den Deckel und den Lautsprecher-Halter gibt es auf der instructables Seite zum Download. Da ich keinen 3D-Drucker besitze, habe ich diese bei einem 3D-Druckdienst im Internet bestellt. Ich habe das billigste Material (PA12) genommen - ist sehr stabil. Beim Lautsprecher-Halter sagt mein Druckdienstleister "zu dünn, auf eigene Gefahr" - der Halter ist aber absolut in Ordnung.
Ich habe den Deckel auf dem Echo-Dot (Version 2).
Im Gegensatz zum "Project Alias" passt mein PI+Arduino+Movi-Shield natürlich nicht in den Deckel.
Lediglich die Lautsprecher an dem dafür vorgesehenen 3D-gedrucktem Plastikgestänge befinden sich im Deckel und ein Zuleitungskabel führt hinein.
Die Lautsprecher decken 2 der Mikrofone ab, das reicht, um Alexa zu verwirren. Ich habe die Lautsprecherhalterung aber direkt auf die Mikros geklebt, damit Alexa auch wirklich nichts hört.
Den Moneypenny-Lautsprecher (kommt aus dem Soundausgang des Movi-Shields) habe ich beibehalten - wegen des "Ja, Bitte ?".
Das ist nicht nur lustig sondern v.a. eine Timing-Frage, denn es vergeht ca. eine Sekunde bis zum "Alexa"-flüstern, wenn man zu früh spricht, reagiert der Dot nicht.
Das wav-file kommt aus der Klinkenbuchse des Pi, ich habe es mit einen winzigen Audioverstärker etwas anheben müssen, der Kopfhörerpegel reicht nicht ganz aus. 

Gruß, Jochen
Meine Konfig: FHEM auf NUC i5 mit Mint, HM-LAN, div. HM Schalter und Heizungsthermostate, FB 6840LTE mit Dect200, HUE bridge, HUE bulbs + Lightstrips, VU+Duo2 und Philips-TV Steuerung, Pushmail, Floorplan, Sprachsteuerung + Feedback per Arduino mit MOVI-Shield, LMS Multiroom mit 7x Pi

joginet

Hab' jetzt mal mein Arduino-Shield rausgeschmissen und den Alexa-Hut mit Snips-Hotworderkennung und einem Respeaker MicArray v2.0
aufgesetzt. Funktioniert grandios !
Und wie immer (auch damit ich mich selbst in 2 Monaten noch erinnern kann), habe ich das ganz mal "zu Papier gebracht".
Ich will hier jetzt nicht alles reinkopieren - wer Interesse hat oder nachbauen will:

https://www.jochens-techblog.org/index.php/projekte/smarthome-mit-fhem

Rubrik: Die private Alexa - ein Hut für den Echo Dot"

Jetzt steuert Alexa - nein - Moneypenny 2.0 -  mein FHEM, hört mich aber nur, wenn ich sie Moneypenny nenne  ;D

Gruß, Jochen
Meine Konfig: FHEM auf NUC i5 mit Mint, HM-LAN, div. HM Schalter und Heizungsthermostate, FB 6840LTE mit Dect200, HUE bridge, HUE bulbs + Lightstrips, VU+Duo2 und Philips-TV Steuerung, Pushmail, Floorplan, Sprachsteuerung + Feedback per Arduino mit MOVI-Shield, LMS Multiroom mit 7x Pi