Im vorherigen Beitrag habe ich euch gezeigt wie ihr aus eurem Raspberry Pi mit Mikrophon und Lautsprecher eure eigene Alexa Sprachassistent baut. Wer eigenen Alexa „Custom Skill“ entwickeln möchte um das Potenzial von Alexa voll auszuschöpfen kann das anstelle mit AWS Lambda auch lokal auf seinem Raspberry Pi mit Alexa App Server testen. Diese Methode hat den vorteil das recht frei und beliebig getestet werden kann ohne ständig den Code in den ggf. kostenpflichtigen AWS Lambda Dienst hochzuladen. Die Methode eignet sich nicht für die Produktion sondern zeigt lediglich wie ihr recht einfach auf eurem Raspberry Pi Alexa Skills entwickeln und testen könnt und welche Möglichkeiten bestehen. Der Artikel richtet sich ehr an die Entwickler und extrem lernwilligen Anfänger.
Für die produktive Nutzung muss der Code in AWS Lambda eingespielt und das zu steuernde Endgerät bei Amazon registriert sein. Im Development Modus ist kein registriertes Endgerät notwendig, falls AWS Lambda verwendet wird kann mit einem Alexa Gerät / App auf der selben E-Mail Adresse getestet werde, für den lokalen App Server ist nur ein Test mit Texteingabe möglich.
Meine Meinung:
Die Entwicklung und der Test von Alexa Custom Skills macht mir persönlich riesigen Spaß und bietet mit etwas Fleiß fast unendliche Möglichkeiten. Was mich persönlich massiv stört ist das Amazon uns quasi zwingt das hauseigene AWS Lambda zu verwenden , HTTPS Endpunkte so eingeschränkt oder scheinbar absichtlich beschränkt das eine effektive Nutzung im Internet der Dinge nicht sinnvoll möglich ist.
Inhaltsverzeichnis
Hardware
Ich verwende den selben Raspberry Pi, auf welchem auch mein selbst gebauter Echo läuft ebenfalls als Server für die FHEM Abindung. Die Hardware-Liste findet ihr in vorherigen Beitrag. Beachtet die Infos zum Setup, es wird Raspbian Jessie benötigt.
- Raspberry Pi 3
- Netzteil (2,5A@5,1V),
- Eine Class 10 MicroSD Karte
- Ein Netzwerkkabel
- Ein SD-Kartenleser
- Ein USB Sound Karte mit Line-In (günstig, schlechte Qualität)
- Alternativ ein passender RasPi HAT mit Line In oder onboard MIC (teuer, besser Qualität)
- Ein Mikrophon
- Lautsprecher mit 3,5mm Klinke oder im Bildschirm integrierten Lautsprechern (HDMI)
Zusätzlich empfohlen
- Ein Gehäuse für den Pi mit Lüfter Vorbereitung
- Ein Lüfter für das Gehäuse
- Kabellose Media Center Tastatur
- HDMI Kabel
Amazons Echo verwendet ein spezielles “Far Field Microphone”, für meine Tests verwende ich ein ganz einfaches 3,5mm Klinke Mic, das eignet sich sicherlich nicht für Aufnahmen über mehrere Meter genügt aber für dieses Beispiel.
Alexa Custom Skill für FHEM – Die Praxis
Zusammenfassung der notwendigen Schritte:
- Raspberry Pi für die Amazon Cloud bzw. den Custom Skill via Internet erreichbar machen
- Setup unserer NodeJS und Alexa App Server Umgebung
- Installieren / Entwickeln unserer FHEM Alexa App auf dem Raspberry Pi
- Unseren „Custom Skill“ in unserem Developer Account anlegen
- Skill Testen
Raspberry Pi via Internet erreichbar machen
Wie bereits beschrieben wird unsere Spracheingabe über die AVS Cloud und den Custom Skill zurück an ein Gerät gesendet welches den Befehl letzten Endes ausführt. Natürlich ist das unser Raspberry Pi im Heimnetz. Um sicherzustellen das AVS den Pi über das Internet erreicht sind einige Schritte notwendig.
1 2 |
Wichtig! Amazon unterstützt weder IPv6 noch HTTP, es muss eine HTTPS Adresse sein die auf dem Standard HTTPS Port 443 erreichbar ist. Für DS-Lite Anschlüsse muss daher auf kostenpflichtige Dienste zurückgegriffen werden. WTF Amazon?! |
Wer einen DS-Lite Anschluss besitzt (zum Beispiel Unitymedia) muss sich eines kostenpflichtigen Services bedienen.
Für IPv4 Internet:
- DynDNS Dienst für euren Raspberry Pi einrichten
- Port Weiterleitung für TCP/443 an den Raspberry Pi an eurem Router einrichten
Für DS-Lite Internet:
- Raspberry Pi via DS-Lite über das Internet erreichbar machen
- Wichtig, abweichend von der Anleitung Konfigurieren wir einen DDNS Eintrag mit Portmapper und ein HTTP(S) Proxy Dienst bei fest-ip.net (kostenpflichtig)
NodeJS Server installieren
Das Herzstück unseres „Alexa Skill Servers“ auf unserem Raspberry Pi ist ein NodeJS mit Alexa App Server welcher Anfragen vom Amazon Voice Service annimmt, FHEM steuert und das Ergebnis zurückliefert.
Als erstes installieren wir NodeJS aus dem Raspbian Jessie Repository
1 2 |
sudo apt-get update sudo apt-get install nodejs |
Dann führen wir das NodeJS Update Script aus um die aktuelle Version in den Cache zu laden
1 |
curl -sL https://deb.nodesource.com/setup_8.x | sudo -E bash - |
Wir aktualisieren nodeJS via APT auf die aktuelle Version
1 |
sudo apt install nodejs |
Alexa App Server einrichten
Der Alexa App Server ist super Projekt um die Alexa Skills lokal auf seinem eigenen NodeJS Server laufen lassen zu können ohne sich um all zu viele inhaltliche Themen Gedanken machen zu müssen. Wir installieren uns diesen via GIT.
1 2 |
cd $HOME git clone https://github.com/matt-kruse/alexa-app-server.git |
Da wir für den App Server noch die notwendigen Abhängigkeiten benötigen installieren wir diese ebenfalls.
1 2 |
cd $HOME/alexa-app-server npm install |
Da Amazon nur verschlüsselt mit unserer FHEM App kommuniziert müssen wir HTTPS aktivieren, wir bearbeiten die Einstellungen des App Servers
1 |
nano $HOME/alexa-app-server/examples/server.js |
Wir fügen unter „port: 8080,“ folgendes ein
1 2 3 4 5 6 7 |
httpsPort: 443, httpsEnabled: true, privateKey: 'server.key', certificate: 'server.crt', verify: false, debug: false, |
Speichert mit STRG+X, Y und Enter.
Für eine SSL gesicherte Verbindung benötigt unser Server noch ein selbst signiertes Zertifikat welches wir uns erstellen. Wir erstellen unseren privaten Schlüssel
1 2 |
cd $HOME openssl genrsa -out server.key 2048 |
Dann erstellen wir eine Request Datei für unser Zertifikat
1 |
sudo nano $HOME/configuration.cnf |
Kopiert folgenden Text hinein. Editiert folgendes für eure spezifischen Einstellungen / Bedürfnisse:
- C: Euer Ländercode (DE)
- ST: Abkürzung für euer Bundesland, ZWEI Buchstaben (BW)
- L: Eure Stadt
- O: Eure Organisation, kann auch eine „Example Corp“ sein
- CN: Euer Skill Name aus der AVS Developer Konsole
- DNS.1:
- Bei IPv4 euer DynDNS Name (z.B. raspberrypi.dyndns.org)
- Bei DS-Lite den HTTP(S) Proxy Namen des Portmappers (z.B. raspberrytips-proxy.feste-ip.net – zu finden bei feste-ip.net unter HTTP(S) Proxy)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
[req] distinguished_name = req_distinguished_name x509_extensions = v3_req prompt = no [req_distinguished_name] C = DE ST = BW L = Bietigheim-Bissingen O = raspberry.tips CN = raspberry.tips-fhem [v3_req] keyUsage = keyEncipherment, dataEncipherment extendedKeyUsage = serverAuth subjectAltName = @subject_alternate_names [subject_alternate_names] DNS.1 = raspberrytips-proxy.feste-ip.net |
Erstellt das Zertifikat
1 |
openssl req -new -x509 -days 1825 -key server.key -config configuration.cnf -out server.crt |
Wir kopieren das erstellte Zertifikat (.crt) und den Schlüssel (.key) in den Ordner sslcert, dort sucht der App-Server nach den Dateien
1 2 |
cp $HOME/server.crt $HOME/alexa-app-server/examples/sslcert/server.crt cp $HOME/server.key $HOME/alexa-app-server/examples/sslcert/server.key |
Dann starten wir unseren NodeJS Server um zu prüfen ob alles funktioniert
1 2 |
cd $HOME/alexa-app-server/examples/ sudo node server |
Beendet den App Server mit STRG+C.
FHEM App Einrichten
Einen Großteil der Arbeit bezüglich des selbst entwickelten Skills für FHEM habe ich schon für euch erledigt, aktuell kann der Skill ein beliebiges Gerät an und Ausschalten. Folgendes ist wichtig um den Code unverändert benutzen zu können.
- Ich habe aus Gründen der Einfachheit in FHEM die Abfrage für Benutzer / Passwort deaktiviert. Kommentiert durch voranstellen einer Raute (#) für FHEM Web basicAuth in der Konfiguration aus (z.B. #attr allowed_WEB basicAuth bWU6bXlTZWNyZXQ=)
- FHEM nimmt Befehle nur mit einem korrekten Sitzungs-Token entgegen. Erstellt einen fixen CSRF-Token
Namens Schema derGeräte
- Meine Geräte sind immer so benannt <Typ><Separator><Standort>, also zum Beispiel „Licht_Esstisch“ oder „Rolladen_Wohnzimmer“. Die App Funktioniert nur wenn eure FHEM Geräte das selbe Namensschema benutzen, der Separator kann ein anderer sein. Andernfalls müsst ihr den Code anpassen.
Als erstes holt euch meinen Code aus dem GitHub repository.
1 2 |
cd $HOME git clone https://github.com/raspberry-tips/fhem-skill |
Dann holen wir uns die Abhängigkeiten des Projekts
1 2 3 |
cd $HOME/fhem-skill npm install --save alexa-app chai chai-as-promised mocha lodash request-promise |
Ihr müsst nun noch euren FHEM CSRF Token und die IP-Adresse eures FHEM-Servers ändern
1 |
nano nano fhem_data_helper.js |
Ändert in folgenden Zeilen den Token und die IP-Adresse:
1 2 |
var FHEMIpPort = '192.168.178.32:8083'; var FHEMCSRFToken = '1768510152'; |
Speichert mit STRG+X, Y und Enter. Wir kopieren unseren Skill Ordner in den App-Server
1 |
cp -R $HOME/fhem-skill $HOME/alexa-app-server/examples/apps |
Testet ob euer App Server sauber startet und lasst das Terminal die SSH Sitzung geöffnet. Die Sample Apps könnt ihr aus dem Apps Ordner entfernen.
1 2 |
cd $HOME/alexa-app-server/examples sudo node server |
Custom Skill für Alexa anlegen
Da wir nun unseren lokalen NodeJS Server zum Ausführen der Aktion mit FHEM installiert und eingerichtet haben müssen wir unseren Custom Skill noch online in unserem Entwickler Account anlegen. Sonst kann Alexa die Sprachbefehle nicht zuordnen und an unseren lokalen Server senden.
- Auf der Entwicklerkonsole anmelden (Erstellt euch einen Account oder benutzt euer normales Amazon Konto)
- Auf Alexa > Alexa Skills Kit > Get Startet
- Add a new Skill Button rechts oben
Legt euch einen Custom Skill an wie im Screenshot zu sehen.
Nun wird es etwas tricky, wir erstellen das Interaction Model wählt den Punkt im Menu links.
Das Intent Schema beschreibt unsere Absichten (also was wir mit der Sprache anfangen wollen) im JSON Format, hierbei können unsere Absichten auch Variablen beinhalten (Slots). Zusätzlich benötigen wir einige Beispielsätze das Alexa die Befehle zuordnen kann (Sample Utterances).
Da ich erst mal nur meine an FHEM angebundene Geräte via Sprache an und ausschalten möchte brauche ich ein Intent Schema welches das Gerät erkennt und die zu erledigende Aktion. Dafür benötige ich im Schema drei Slots (Variablen). Slot 1 für den Typ (Licht, Rolladen, etc), Slot 2 für den Raum (Wohnzimmer, Flur, etc) und Slot 3 für die Aktion (An, Aus, etc). Die Typen der Slots/Variablen sind „Custom Typen“. Lest dazu am Besten die Best Practice und verwendet wo möglich vorhandene vorgefertigte Slot Types
Kopiert mein fertiges Intent Schema in das Feld.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
{ "intents": [ { "slots": [ { "name": "DeviceType", "type": "LIST_OF_DEVICE_TYPES" }, { "name": "DeviceLocation", "type": "LIST_OF_DEVICE_LOCATIONS" }, { "name": "DeviceActions", "type": "LIST_OF_DEVICE_ACTIONS" } ], "intent": "FHEMSmartHomeAction" } ] } |
Dann legt ihr euren ersten Custom Slot an, falls ihr andere Geräte habt könnt ihr diese natürlich hinzufügen.
Die beiden weiteren über „Add Slot Types“ (Name und typ müssen mit, mögliche Variablen habe ich erst mal nur für meinen Test-Zweck befüllt, ihr könnt diese für euch ergänzen
Dann hinterlegen wir unter „Sample Utterances“ noch folgende Sätze sodass Alexa später die gesprochenen Befehle und Slots zuordnen kann.
1 2 3 4 5 |
FHEMSmartHomeAction schalte {DeviceType} im {DeviceLocation} {DeviceActions} FHEMSmartHomeAction schalte {DeviceType} {DeviceLocation} {DeviceActions} FHEMSmartHomeAction schalte {DeviceLocation} {DeviceType} {DeviceActions} FHEMSmartHomeAction {DeviceLocation} {DeviceType} {DeviceActions} FHEMSmartHomeAction {DeviceType} {DeviceLocation} {DeviceActions} |
Wechselt nach dem Speichern links auf Configuration wählt https und tragt eure DynDNS Adresse (IPv4) ein z,b. raspberrypi.dyndns.net. Für DS-Lite die HTTP(S) Proxy Adresse von fest-ip.net z.B. https://raspberrytips-proxy.feste-ip.net
Hängt dann an die URL /Alexa/fhem-skill an, in meinen Fall lautet die ganze URL zum Alexa App Server und meiner Fhem App https://raspberrytips-proxy.feste-ip.net/alexa/fhem-skill
Speichert und klickt auf SSL Certificate. Öffnet wieder eine SSH Sitzung oder Terminal und gebt euch den öffentlichen Schlüssel eures erstellen Zertifikats aus.
1 |
cat $HOME/server.crt |
Kopiert die Ausgabe, Inklusive der Bindestriche und Text in der Kopf / Fußzeile in die AVS Konsole
Wechselt zu Test. Startet nun einen Test, dabei geben wir ein Kommando als Text ein, AVS Sendet das dann an unseren Node.JS Server, so können wir die Kommunikation testen. Eure node server muss natürlich laufen, falls nicht startet diesen wie oben beschrieben mit „sudo node server“.
- Gesendeter Befehl „Licht Esstisch an“
Erhaltet ihr rechts ein Ergebnis zurück, passt alles. Erhaltet ihr einen Fehler stimmt vermutlich etwas mit der Kommunikation zu eurem Raspberry Pi nicht.
Falls ihr euren Skill produktiv oder im Entwicklungsmodus mit einem eurer Alexa Geräte (z.B. Echo) verwenden möchtet müsst ihr den Code bei AWS Lambda veröffentlichen und den Custom Skill entsprechend anpassen.
Happy Coding!