Nachdem wir kürzlich einen Raspberry Pi 3 dazu gebracht haben als „Amazon Echo“ zu fungieren und dabei gleich gelernt haben, dass es grundsätzlich günstiger wäre, sich einen Amazon Echo Dot (2. Generation) zu kaufen, will ich heute einen kurzen und recht „oberflächlichen“ Blick darauf werfen, wie man eine Alexa Skill erstellt.

Die Skill, die ich erstelle, wird „Flugzeuge über Otzberg“ heißen und einen selbstgeschriebenen Endpoint (php) ansprechen, der eine JSON Response ausgibt. Die JSON-Antwort, sieht dabei so aus:

{"alexa":"Flug U22654 von Copenhagen nach Milan"}

Die Antwort ist also schon vorformatiert, was zum einen unnötig ist und es zum anderen unnötig schwer macht, die Alexa Skill mehrsprachig aufzusetzen, es verkürzt jedoch den Quelltext und das ist für diesen Beitrag eine gute Idee ;)

Dass die Städtenamen auf Englisch sind, liegt daran, dass mein Programm, dass die Flugzeuge mitschreibt nur den IATA-Code bekommt und ich diese dann über eine Datenbank in Städenamen wandele. Die Städenamen der Datenbank sind jedoch allesamt auf Englisch, was zu recht „lustigen“ Ansagen führen wird (München = Munich, Köln = Cologne etc. – nur weiß das die Sprachausgabe nicht).

Bevor wir hier loslegen, muss ich erwähnen, dass Amazon es einem unglaublich leicht macht, schnell Ergebnisse zu erzielen. Die Product Manager und Entscheidungsträger in Seattle haben sich genau überlegt, wie man Entwickler davon überzeugt, einfach mal eine oder zwei Stunden damit zu verbringen an einem solchen Projekt zu basteln.

Alexa Skills Kit

Alexa ist ein Sprachservice, der auf Geräten wie Amazon Echo oder Echo Dot verfügbar ist. Alexa bietet Nutzern über Skills, und mit Hilfe von gesprochenen Anweisungen, beispielsweise die Möglichkeit Musik abzuspielen, Antworten auf allgemeine Fragen zu erhalten, einen Wecker oder Timer zu stellen und mehr.

Das Alexa Skills Kit (ASK) ist eine Sammlung von Self-Service APIs, Tools, Dokumentationen und Codebeispielen, mit denen Sie schnell und einfach Skills entwickeln und Anwendern zur Verfügung stellen können. Mittlerweile sind weltweit mehr als 10.000 Skills im Amazon Skill Store verfügbar.

Für diesen Beitrag gehe ich davon aus, dass Du Dich bereits erfolgreich bei Amazon als Entwickler registriert hast, dazu musst Du Dich eigentlich nur mit Deinem normalen Amazon-Konto einloggen. Auf der Developers-Seite von Amazon findest Du eine sehr nützliche Kurzanleitung, die Dir alles genau erklärt und mit nützlichen Code-Schnipseln den Start erleichtert.

Logge Dich im Amazon Apps & Services Developer Portal ein und wähle Alexa > Alexa Skills Kit > Get Started. Du sieht nun eine Liste aller bereits erstellten Skills, oder hast die Möglichkeit Deine erste Skill anzulegen. Wie Du in diesem Screenshot siehst, habe ich bereits eine Skill, die ich hier durchgehen werde.

Im ersten Schritt wirst Du vorgeben, was für eine Art Skill Du erstellen willst. Dabei kannst Du aus „Custom Skill“, „Smart Home Skills“ oder „Flash Briefing Skills“ auswählen.

Smart Home Skills sind für IoT-Anwendungen, so Dinge wie schalte eine Lampe an oder aus und ist entsprechend nichts für unser Beispiel. Flash Briefing Skills sind die Audio-Zusammenfassungen, wie Tageschau in 100Sekunden, die man sich von Alexa abspielen lassen kann, um einen „guten Start“ in den Tag zu haben. Auch das ist hier nicht richtig. Also war es eine Custom Skill, die ich brauchte.

Weiterhin gibst Du die Sprache vor, da ich in Deutschland bin, habe ich entsprechend Deutsch gewählt.

Die Application ID wird von Amazon vergeben, den Namen und den „Invocation Name“ vergibst Du selbst. Dabei solltest Du darauf achten, dass der „Invocation Name“ nicht mehr als drei Worte lang ist, möglichst einzigartig und leicht auszusprechen ist.

Meine private iOS App, die mir die selben Flugdaten abrufen kann, habe ich OtzPlane genannt, das wäre aber für einen sprachbasierten Dienst eine denkbar schlechte Wahl ;)

Letzendlich musst Du noch sagen, ob Du den Audio Player nutzen wirst und da wir das nicht tun, sind wir damit schon fast durch.

Im nächsten Schritt wird es spannender, denn hier geben wir das „Intent Schema“ vor. Dabei handelt es sich um eine JSON-formatierte Liste, die vorgibt, welche „intents“ es geben kann. Am Ende der Seite (außerhalb des Screenshots) gibt man dann in reinem Text vor, welche Sprachanweisung, welchen Intent starten soll.

Mein Intent Schema ist super einfach gestrickt. Ich habe keine Platzhalter für Feedback der Nutzer, noch will ich dass meine Skill sich mit dem Nutzer unterhält. Ich brauche daher auch keine Custom Slot Types, bei denen man bestimmte Werte vorgeben könnte, aus denen der Nutzer wählen kann.

Also hier mein Intent Schema:

{
  "intents": [
    {
      "intent": "getPlanes"
    },
    {
      "intent": "AMAZON.HelpIntent"
    },
    {
      "intent": "AMAZON.StopIntent"
    },
    {
      "intent": "AMAZON.CancelIntent"
    }
  ]
}

Und hier meine „Sample Utterances“:

getPlanes Welches Flugzeug fliegt gerade über Otzberg
getPlanes Wohin fliegt das Flugzeug
getPlanes Wohin fliegt dieses Flugzeug

Gerade bei den „Sample Utterances“ muss man sich eigentlich richtig Gedanken machen, was die Leute so sagen können sollen / wollen / würden. Ich habe mir nicht wirklich Mühe gegeben.

Im dritten Schritt – Configuration – müssen wir nun einen Web Service angeben, mit dem sich unsere Skill verbinden soll. Amazon empfielt, dass man AWS Lambda nutzen soll. Zu AWS Lambda schreibt Amazon dabei:

AWS Lambda is a server-less compute service that runs your code in response to events and automatically manages the underlying compute resources for you.

Was das im Ende für Dich bedeutet ist folgendes: Amazon „schenkt“ Dir bis zu 1 Millionen kostenloser Aufrufe pro Monat, oder 3,2 Millionen Sekunden Datenverarbeitungszeit.

Für eine Skill, die Du nur so zum Testen einrichtest, mehr als Du jemals verwenden wirst. Selbst wenn Du Deine Skill veröffentlichst denke ich, dass 1 Millionen Anforderungen im Monat mehr als nur ein Erfolg darstellen würde. Hier kannst Du also recht beruhigt zugreifen, dafür brauchst Du allerdings ein AWS Konto und dafür muss man seine Kreditkarte hinterlegen.

Als nächstes müssen wir also zu AWS Lamda, das es für Alexa Skills nur in der Region „USA Ostküse“ und „Europa – Irland“ gibt.

Wenn Du schon eine Lambda Funktion hast, wird diese hier gezeigt, ansonsten kannst Du mit „Create a Lambda function“ beginnen. Dort gibt es verschiedene Beispiel-Funktionen zur Auswahl und die für uns interessante Funktion ist „alexa-skill-kit-sdk-factskill“. Wir werden zwar einen guten Teil des Quelltextes überschreiben, aber der basic setup ist optimal.

Das interessante an Lambda ist, dass man seien Quelltext in node.js einfach eintippen kann und es läuft. Ich habe Euch hier einmal den von mir verwendeten Code eingefügt, wobei Ihr die App_ID  aus den Alexa Skills Kit Schritten vorher übernehmen müsst.

Der ganze Quelltext ist nicht auf meinen Mist gewachsen, sondern wurde aus dem Amazon GitHub Repositories zusammengestellt. Manchmal muss es auch mit Copy & Paste gehen ;)

'use strict';

const Alexa = require('alexa-sdk');

const APP_ID = 'MUSS_AUS_DEM_VORHERIGEN_SCHRITTEN_ÜBERNOMMEN_WERDEN';


const handlers = {
    'LaunchRequest': function () {
        this.emit('getPlanes');
    },
    'getPlanes': function () {
        httpsGet(myResult => {
          console.log("received : " + myResult);
          this.emit(':tell', 'Das Flugzeug über Otzberg ist: ' + myResult );
          }
        );
    },
    'AMAZON.HelpIntent': function () {
        const speechOutput = 'Ich werde Dir das Flugzeug nennen, das zu letzt über Otzberg geflogen ist';
        const reprompt = 'Dies ist nur ein Demo. Ich werde Dir das Flugzeug über Otzberg nennen. ';
        this.emit(':ask', speechOutput, reprompt);
    },
    'AMAZON.CancelIntent': function () {
        this.emit(':tell', 'Ich werde Dir das Flugzeug nennen, das zu letzt über Otzberg geflogen ist.');
    },
    'AMAZON.StopIntent': function () {
        this.emit(':tell', 'Auf Wiedersehen!');
    },
    'SessionEndedRequest': function () {
        this.emit(':tell', 'Auf Wiedersehen!');
    },
};

exports.handler = (event, context) => {
    const alexa = Alexa.handler(event, context);
    alexa.APP_ID = APP_ID;
    alexa.registerHandlers(handlers);
    alexa.execute();
};


var https = require('https');

function httpsGet(callback) {

    // Update these options with the details of the web service you would like to call
    var options = {
        host: 'www.YOURDOMAIN.de',
        port: 443,
        path: '/PATH/SCRIPT_NAME.php',
        method: 'GET',
    };

    var req = https.request(options, res => {
        res.setEncoding('utf8');
        var returnData = "";

        res.on('data', chunk => {
            returnData = returnData + chunk;
        });

        res.on('end', () => {

            var alexaResponse = JSON.parse(returnData).alexa;

            callback(alexaResponse);  

        });

    });
    req.end();

}

Spannend ist, dass man die Funktion gleich testen kann und somit weiß, ob es geht!

Bevor Du hier mit Lamda fertig bist, musst Du noch einen Trigger einrichten. Dazu auf die passende Registerkarte klicken und als Trigger Alexa Skills Kit auswählen. Auch hier hilft Dir Lambda, da die ganze Arbeit den Request kryptographisch zu überprüfen im Hintergrund einfach für Dich erledigt wird.

So jetzt, solltest Du eine ID für Deiene Funktion haben und diese gibst Du in der deverloper.amazon.com Ansicht ein.

Was übrig bleibt ist nur noch ein Test, in der Konsole, und wenn dieser erfolgreich ist, kannst Du Deine Skill in der Alexa-App unter iOS aktivieren und dann mit Deinem Amazon Echo (oder Raspberry Pi 3) testen.

In der Testumgebung, kannst Du dann einfach eine Deiner „Utterances“ eingeben, dir wird die JSON-Anfrage gezeigt und die entsprechende Antwort, die erhalten wurde. Zum Spaß gibt es einen „Listen“ Knopf, mit dem Du Dir das vorlesen lassen kannst.

Ganz grob ist es das dann auch schon. Gar nicht mal so kompliziert, oder?

So hört sich das übrigens dann an:


Claus Wolf

Seit 1994 im Netz unterwegs und seit 2004 eingefleischter Mac-Nutzer.

5 Kommentare

Stefan · 27. Dezember 2017 um 00:02

Hallo Claus,

erst einmal vielen Dank und Kompliment zu Deinem Blog.

Bei der Suche, nach Informationen, wie man Skills für Alexa selbst schreiben kann, bin ich auf Deine Anleitung zum Skill „Flugzeuge über Otzberg“ gestoßen. Eigentlich konnte ich Deiner Erklärung soweit folgen. Wenn ich am Ende im Service Simulator die Funktion teste, erhalte ich jedoch als Ausgabe diese Fehlermeldung: „The remote endpoint could not be called, or the response it returned was invalid.“ Ich habe den Platzhalter aus der Zeile:
const APP_ID = ‚MUSS_AUS_DEM_VORHERIGEN_SCHRITTEN_ÜBERNOMMEN_WERDEN‘; mit der Application ID des Skills ersetzt. Bei der Zeile 49 “ host: ‚www.YOURDOMAIN.de‘,“ war ich mir nicht sicher, welche Domain ich eintragen muss. Google habe ich versucht, genauso wie flightradar. Beides hat leider nicht geklappt.

Es wäre schön, wenn Du mir einen Tipp geben könntest, woran es liegen könnte. Woher weiß der Skill, wo sich Alexa (Otzberg) befindet? Die Flugdaten müssen ja von einem Webdienst stammen. Diesen muss man dann sicher in dem Quellcode eingeben.

Wie füge ich in der Lambda Funktion die node,js ein? Unter Function Code wird mir als Standart die index.js angezeigt. Muss diese gelöscht werden und dafür die node,js (mit entsprechendem Quellcode) erstellt werden?

Vielen Dank im Voraus für Deine Hilfe!!

Viele Grüße aus dem Rheinland,

Stefan

    Claus Wolf · 27. Dezember 2017 um 08:43

    Hallo Stefan,

    Ich habe einen Webservice geschrieben, der weiß, wo Otzberg liegt und die Daten für Amazon Echo aufbereitet zur Verfügung stellt. Die Skill selbst ist also entsprechend blöd, und ruft lediglich den Webservice ab und liest die Daten aus. Das hatte ich auch in Absatz 2 & 3 des Artikels als einleitende Erklärung hinzugedacht. Sorry, dass das offensichtlich genug war.

    Unter www. Yourdomain.de musst du also die URL deines Webservice hinterlegen, dafür braucht es eine Domain, oder zu mindestens eine statische IP, dyndns dürfte auch gehen, aber ohne diese Voraussetzung wirst du leider nicht weiterkommen. Sorry…

      Stefan · 27. Dezember 2017 um 10:19

      Hey,

      Danke für Deine schnelle Antwort. Okay, dann weiß ich zumindest Bescheid. Leider habe ich keine Ahnung, wie man einen entsprechenden Webservice schreibt. Deine Idee finde ich trotzdem super. Ich fange gerade erst an, mich in das Thema einzuarbeiten. Einfach gehaltene Beispiel Skills helfen dabei ganz gut, die Sache zu verstehen.

      Schade, so wird mein Projekt, Deinen Skill nachzuvollziehen wohl leider an dieser Stelle zuende gehen.

      Wünsche einen guten Rutsch ins neue Jahr und noch einmal vielen Dank für die Erklärung!

        Claus Wolf · 27. Dezember 2017 um 15:51

        Wenn ich mal so richtig Zeit habe, könnte ich mir vorstellen, das raspberry Pi Projekt, dass den WebService befeuert mit anderen zu teilen. Der Quelltext ist aber nicht so sauber, dass ich das jetzt schon tun wollte. openSource ist harte Arbeit ;)

        Dir weiterhin viel Spaß mit Amazon Echo & Co!

Eigener AlexaSkill – tom's blog · 2. Oktober 2017 um 14:14

[…] Habe es erst mit Amazon’s “Minecraft Helper” Beispiel probiert – hat nicht geklappt. AWS meinte irgendwas sei falsch. Vernünftige Videos auf YouTube hab ich auch nicht gefunden – ich probier es jetzt mal mit dem Tutorial hier […]

Schreibe einen Kommentar zu Stefan Antworten abbrechen

Avatar-Platzhalter

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

Diese Website verwendet Akismet, um Spam zu reduzieren. Erfahre mehr darüber, wie deine Kommentardaten verarbeitet werden.