Jannik S. (js329@hdm-stuttgart.de) Jan Z. (jz043@hdm-stuttgart.de)
Uns stand beiden jeweils ein eigener Raspberry Pi 4, sowie der MiFa Lautsprecher zur Wiedergabe und die Logitech c270 Webcam als Mikrofon zur Verfügung. Die Hardware haben wir bei dem gemeinsamen Vor-Ort-Termin an der HdM erhalten. Das Einrichten des Pi hat dort auch schon funktioniert, bei uns bestand lediglich die selbe Problematik wie bei nahezu allen anderen, dass die Wiedergabe- bzw. Aufnahmegeräte nicht korrekt verwendet wurden.
Für das weitere Vorgehen und das Hinzufügen eines eigenen Skills stand uns jeweils ein eigener Account auf der nextcloud-Instanz (https://next.social-robot.info/nc) zur Verfügung.
Über einen eigenen github-Account verfügten wir bereits.
Ziel ist es einen eigenen Skill zu entwickeln, der die nächsten Eintragungen in einem nextcloud-Kalender verkünden soll. Folgende optionale Bonusaufgaben wurden implementiert:
- Kalendereintrag machen
- bestimmten Tag abfragen
- Event löschen
- Event umbenennen
Folgender Link war hierfür sehr hilfreich: https://elinux.org/R-Pi_Troubleshooting#Sound
sudo apt-get --purge remove pulseaudio
sudo apt-get update
sudo apt-get upgrade
sudo apt-get install alsa-utils
sudo modprobe snd_bcm2835
amixer cset numid=X <n>
0 = auto, 1 = Kopfhörer, 2= HDM)
speaker-test -t sine -f 440 -c 2 -s 1
sudo apt-get install gstreamer1.0-pulseaudio
Durch diesen Workaround hat dann unser Setup auch jeweils funktioniert.
Für die Einrichtung und das Starten von Mycroft haben wir hauptsächlich die Mycroft eigene Anleitung verwendet. (Anleitung) Nach dieser haben wir auch unseren ersten eigenen Skill angelegt. Hierbei wird man mit dem Befehl mycroft-msk create` durch ein interatktives Skript geführt in dem man einige grundlegende Fragen zur Funktionalität beantowrten muss und es wird ein allgemeines Skill Template erstellt. Folgende Fragen bzw. Abfragen waren zu beantworten.
- Name: Der Name des Projektes sollte möglichst kurz und prägnant sein, von Mycroft selbst wird hier eine Länge bis zu maximal 22 Zeichen vorgeschlagen. Desweiteren muss der Name einzigartig sein innerhalb des Mycroft Marketplaces.
- Beispielsätze: Hier sollten Äußerungen eingetragen werden, die vom User erwartet werden und auf die der Skill dann reagieren soll.
- Antwortdialog: Der Dialog oder die Dialoge mit denen der Skill antworten wird.
- Kurze Erklärung: Ein Einzeiler zur Erklärung des Skills, der nach Mycroft unter 40 Zeichen lang sein sollte.
- Lange Erklärung: Eine ausführliche Erklärung, die beliebig lang sein darf.
- Author: Hier konnte bereits ein Authorenname eingetragen werden.
- Kategorien: Kategorien, unter die der Skill fehlt, die dann im Marketplace benutzt werden. Wichtig um den Skill richtig einzuordnen. Die erste ausgewählte Kategorie ist die Default-Kategorie.
- Tags: Beliebig wählbare Tags, die es anderen Nutzern erleichtern soll, den Skill zu finden.
Anschließend an dieses Skript wird man gefragt, ob ein Github Repo angelegt werden soll, was Relevanz bekommt, so fern man den Skill im Marketplace veröffentlichen möchte.
Nach dem Anlegen des Skills, ging es weiter mit der Überlegung welche Grundfunktionen denn insgesamt möglich sein sollten und dazu wurden nach folgendem Schema Testfiles angelegt. Ein solches Testfile besteht aus den einzelnen Tests für die Funktionalitäten des Skills. Anhand folgenden Beispiels werden die Optionen erklärt:
Feature: next-appointment
Scenario Outline: next appointment
Given an english speaking user
When the user says "<when is my next appointment>"
Then mycroft reply should contain "appointment"
Examples: When is my next appointment
| when is my next appointment |
| what is my next appointment |
| when's my next appointment |
| what's my next appointment |
| when will my next appointment take place |
Im "Scenario Outline" wird der allgemein Testfall beschrieben. Da unsere Implementierung nur die englische Sprache unterstützt,
ist immer ein englischsprachiger Benutzer gegeben. Der When-Then Test beschreibt, was passiert, wenn ein Nutzer eine gewisse
Phrase verwendet. Im obigen Beispiel gibt es zwei Mögliche Fälle: Es gibt ein geplantes Event in der Zukunft oder eben nicht.
Die Gemeinsamkeit der Sprachausgabe für beide Fälle ist hier nur das Wort "appointment", weshalb nur geprüft wird, ob die Antwort des Skills
"appointment" enthält.
Basierend auf den Scenarios der Testfiles wurden anschließend die jeweiligen .dialog und .intent Dateien angelegt, ebenfalls mit Vorüberlegungen auf welche Weise der Benutzer die Sätze jeweils anders formulieren könnte und dennoch eine Antwort erwartet. Hierbei gilt zu beachten:
- .intent-Dateien: Diese Dateien bilden das ab, was der Nutzer an Mycroft richtet.
- .dialog-Dateien: Diese Dateien bilden die Antwortmöglichkeiten von Mycroft ab.
- Insgesamt:
- Worte in
()bilden eine Auswahlmöglichkeit mehrerer Worte ab, die mit einem|getrennt werden. Zudem ist es möglich ein "leeres" Feld zur Auswahl zu lassen, falls es möglich sein soll, keine der Möglichkeiten benutzen zu müssen. - Bei Worten in
{}handelt es sich um Variablen, die später im Code verwendet werden können.
Nach dem Anlegen der Sprachein- bzw. -ausgabe-Dateien war es wichtig und notwendig eine Schnittstelle zwischen dem Nextcloud- Kalender und dem Skill herzustellen. Hier wurde die Verwendung von Caldav bereits empfohlen. Die eigentliche Implementierung der Schnittstelle und des Skills an sich wird unter den nachfolgenden Punkt beschrieben.
Für die Implemmentierung der Schnittstelle zum Nexcloud Kalender wurden folgende Libraries verwendet:
Um die Schnittstelle zum Kalender abzubilden, wurde die Klasse CalDavInterface erstellt. Um die Verbindung zum Nextcloud Kalender aufbauen
zu können, wird die CalDav-Url, ein Username und ein Passwort benötigt. Diese drei Parameter sind in der settingsmeta.yaml
aufgelistet, was bedeutet, dass der User sie auf home.mycroft.ai in den Skill Settings nach der Installation des Skills setzen kann.
Sobald die festgelegten Login Details automatisch mit dem Gerät synchronisiert wurden, kann der Skill auf die Credentials zugreifen und
beim Instanzieren der Klasse an diese übergeben.
Der Klasse wurden alle benötigten Funktionen hinzugefügt, um mit dem Nextcloud Calender zu interagieren. Die Daten, die man bei der Abfrage des Kalenders erhält, sind im Format eines .ical Strings. Um leichter in Python arbeiten zu können, wird der ical String für jedes Event mithilfe der iCalendar geparst und in ein Python Dictionary geschrieben, das dann den Titel, die Startzeit und die Endzeit enthält. Außerdem wird in dem Dictionary eine URL gespeichert, die einen späteren Zugriff auf das eigentliche Event im Kalender über die CalDav ermöglicht.
Vom MyCroft Skill genutzte Methoden sind:
- get_next_event um das nächste Event abzufragen, falls eines existiert
- get_events_for_date um alle Events an einem bestimmten Tag abzufragen
- get_events_with_title um Events zu einem gegebenen Title zu finden (wird für das Umbenennen und Löschen von spezifischen Events benötigt)
- create_new_event um ein neues Event anzulegen (hier wird die iCalendar Library verwendet, um die festgelegten Event Details in ein ical String umzuwandeln, der von der CalDav Library verarbeitet werden kann)
- delete_event um ein Event anhand seiner Event Url zu löschen
- rename_event um einem Event anhand seiner Event Url einen neuen Event Title zu geben
Beim Starten des Skills wird zunächst geprüft, ob die benötigen Credentials für die Nextcloud verfügbar sind. Wenn ja, wird eine Instanz
des CalDavInterface erstellt. Ansonsten wird der User über die Sprachausgabe über die fehlenden Credentials informiert und das
empfohlene Vorgehen erklärt.
Die Klasse für den Skill enthält insgesamt sechs Intent Handler Methoden:
- handle_get_next_appointment für die Abfrage des Kalenders nach dem nächsten geplanten Termin. Je nach gegebenen Event Details, wird für die entsprechende Ausgabe der passende Name der .dialog Datei zusammengebaut und die vorhandenen Informationen übergeben.
- handle_get_appointment_date für die Abfrage des Kalenders der Termine an einem bestimmten Tag. Sind Termine an dem Tag geplant wird zunächst nur die Anzahl der geplanten Termine ausgegeben und der User anschließend gefragt, ob die Termine aufgelistet werden sollen.
- handle_delete_event für das Löschen eines Termins aus dem Kalender. Zunächst wird basierend auf den vom User gegebenen Informationen (Titel, Datum) nach einem übereinstimmenden Event gesucht. Gibt es mehrere Übereinstimmungen, wird der User nach einer genauen Angabe des zu löschenden Events gefragt. Bevor das Event endgültig gelöscht wird, muss der User dies noch einmal bestätigen.
- handle_rename_event für das Umbennen eines Termins im Kalender. Zunächst wird basierend auf den vom User gegebenen Informationen (Titel, Datum) nach einem übereinstimmenden Event gesucht. Gibt es mehrere Übereinstimmungen, wird der User nach einer genauen Angabe des umzubenennenden Events gefragt. Anschließend muss der User noch den gewünschten, neuen Titel des Termins angeben.
- handle_create_event für das Anlegen eines neuen Termins. Je nach Umfang der Informationen in der initialen Intent Message, wird der User nach mehr oder weniger weiteren Informationen gefragt. Benötigt werden Titel, Datum, Startzeit (bzw. ganztägig) und Dauer, wovon Titel, Datum und Startzeit ggf. schon aus der initialen Intent Message herausgelesen werden können.
- handle_connect_to_calendar für den Verbindungsaufbau zum Kalender, nachdem auf home.mycroft.ai die Credentials eingetragen
und auf das Gerät synchronisiert wurden.
Zusätzlich enthält die Klasse unterschieldliche Hilfsmethoden, unter anderem um durch unterschiedliche Rückfragen die jeweils genauen Events vom User zu erfragen.
An mehreren Stellen werden Funktionen des mycroft.util Packages verwendet:
- nice_time und nice_date, um datetime Objekte in ein besseres Output Formt zu bringen
- extract_datetime um aus den Nachrichten der Spracheingabe Datumsangaben in datetime Objekte zu parsen
- extract_duration um aus den Nachrichten der Spracheingabe timedelta Objekte zu erhalten
- extract_number um aus den Nachrichten der Spracheingabe Integer zu erhalten
- default_timezone um die Zeitzone des Users zu erfahren, damit die Zeitangaben der Termine korrekt ausgegebene werden können
Für die Aufgabe war die Code-Dokumentierung in Python Docstrings gemäß der Google-Styleguidelines gefordert. Die Guidelines sind unter folgendem Link zu finden.
Insgesamt lässt sich bei den Learnings Folgendes festhalten:
- Der allgemeine Umgang mit einem Raspberry sowie weiterer an den Pi verbundene Hardware und die daraus resultierenden Probleme mit Treibern und Einstellungen unter Linux konnten hier noch einmal sehr gut vertieft werden.
- Das Kennenlernen eines OpenSource Sprachassistententools (MyCroft) war sehr spannend.
- Es war sehr interessant, die Schnittstelle Caldav und iCalendar und allem was dazugehört, zu benutzen und den Umgang damit zu üben. Bisher hatten wir beide noch keine Erfahrung damit.
- Beim Testen des eigenen Skills und dessen Funktionen kam es sehr häufig dazu, dass die Spracherkennung einzelne Worte nicht richtig nachvollziehen konnte oder sie falsch verstanden hat. Gelegentlich kam es so zu Konflikten mit anderen Skills. Aber insbesondere mit Eigennamen kam es doch auch häufiger zu Schwierigkeiten, was für einen Kalender Skill denkbar schlecht ist. Gerade beim Anlegen eines neuen Kalendereintrags werden doch häufiger Namen bzw. Eigennamen verwendet. Werden diese nicht richtig erkannt, führt das möglicherweise zur Frustration bei Usern.
- Bei den Vorüberlegungen ist bereits unser Testing beschrieben. Hier ist uns aufgefallen, dass bei den automatischen Tests
bei mehrmaligen Durchläufen unter denselben Bedingungen willkürliche Fehler auftreten, die bei manuellem Testing nicht
vorkommen oder sich nicht reproduzieren lassen. Nach kurzer Recherche sind wir auf folgenden Blog-Artikel in der
Mycroft-Community aufmerksam geworden. Hier wird die Einführung der Tests angekündigt, im letzten Absatz ist aber auch die
Rede davon, dass sie durch diese Tests auch auf Fehler in ihren offiziellen Skills aufmerksam geworden sind, die sie sich
mitunter auch nicht erklären können. Unter folgendem Link sind alle derzeit bekannten fehlerhaften Tests von Marketplace
Skills hinterlegt. Da es sich um ein recht junges Feature handelt, scheint es noch nicht komplett fehlerfrei zu laufen.
So ist uns beispielsweise aufgefallen, dass ein Test fehlschlägt, wenn eine Zahl ausgeschrieben wird, der gleiche Test aber erfolgreich durchläuft, wenn die Zahl als tatsächliches Zahlsymbol eingefügt wird, ein Umstand der sich bei einer Spracherkennungssoftware nicht ganz erklären lässt.