Spracherkennung ohne Cloud mit Snips und Raspberry Pi (Teil 4 Von der Spracherkennung zur Sprachsteuerung: JSON-Objekte von Snips zur Steuerung von Geräten verwenden)

  • Von der Spracherkennung zur Sprachsteuerung: Snips JSON-Objekte zur Steuerung von Geräten verwenden

    Wie im Teil 2 dieser Artikelserie gezeigt, generiert Snips aus den aufgezeichneten und "verstandenen" Worten einen JSON-Ausdruck. In diesem Teil werde ich beispielhaft darstellen, wie dieser JSON-Ausdruck mit einem kleinen Python-Skript ausgewertet wird und Schaltvorgänge auf mit Tasmota geflashten Geräten ausgelöst werden bzw. MQTT benutzt wird, um die Hausautomation anzusteuern.

    Dabei gehe ich von folgender Konfiguration aus:

    • Snips (bzw. die Snips-Basis) ist auf einem Raspberry Pi installiert
    • Auf demselben Board (localhost) läuft bereits ein MQTT-Broker (mosquitto, IOBroker usw.)
    • Auf den Tasmota-Geräten ist MQTT aktiviert
    • Alle Tasmota-Geräte haben einen eindeutigen MQTT-Namen (= topic), z. B. Fernseher, Werkstattleuchte usw.
    • Das fulltopic auf den Geräten ist folgendermaßen konfiguriert: %topic%/%prefix%/
      Anmerkung: Es scheint, dass bei Tasmota-Versionen > 6.2.1 die fulltopic-Struktur %topic%/%prefix%/ voreingestellt ist. In älteren Versionen ist es %prefix%/%topic%/. Ich weise an dieser Stelle deshalb daraufhin, weil das Skriptbeispiel mit der neueren Struktur arbeitet. Bei einer anderen fulltopic-Struktur müssen die Funktionen im Skript entsprechend angepasst werden.
    • Das Python-Skript läuft ebenfalls auf demselben Gerät
      Anmerkung: Das muss nicht sein, es kann auch auf einem anderen Gerät laufen, denn es wird lediglich der Zugriff auf den MQTT-Broker benötigt. Da aber das Skript im 24/7-Modus läuft, macht es Sinn, es auf demselben Gerät zu starten.

    Schritt 1 Python-Bibliothek paho-mqtt installieren

    sudo pip install paho-mqtt

    Diese Bibliothek und ihre Funktionen werden gebraucht, um mit dem MQTT-Broker zu kommunizieren. Zudem wird die Bibliothek json benötigt. Diese wird nicht installiert, weil sie bereits vorhanden ist. Sie muss durch das Skript lediglich importiert werden.

    Hier nun ein Skript, das mit den Slots aus Teil 2 arbeitet (Dateiname sprachsteuerung.py):

    Dieses Skript muss noch mit dem Befehl chmod +x sprachsteuerung.py ausführbar gemacht werden und kann nun mit der Eingabe ./sprachsteuerung.py gestartet werden. Nun sollte, wenn z. B. der Satz "Hey Snips, schalte den Fernseher ein" gesprochen wird, das MQTT-Topic "Fernseher/cmnd/Power" mit der payload "1" ausgesendet werden.

    Überprüfen kann man das z. B. praktisch, indem man einem Testgerät den MQTT-Namen (topic) "Fernseher" gibt, z. B. auf der Tasmota-Console durch topic Fernseher oder eher "virtuell" indem wir eine weiteres Terminal öffnen und dort mit mosquitto_sub -h <IP MQTT-Broker> -t Fernseher/stat/# das Status-Topic abonnieren (subskribieren) . Damit können wir kontrollieren, ob das Topic (richtig) übermittelt wird.

    Sicherlich kann man die Auswertung des JSON-Strings auch anders vornehmen. Dies ist eine quick-and-dirty-Version um die Weiterverarbeitung der von Snips generierten MQTT Botschaften zu demonstrieren.

    Zum Schluss dieses Artikels möchte ich noch vorstellen, wie man einen systemd-Starter anlegt, damit das Skript bei einem (Neu-) Start des Rechners gleich geladen wird und von Anfang an läuft um die Sprachbotschaften umzusetzen:

    Auf dem Raspberry Pi wird mit dem Befehl

    sudo nano etc/systemd/system/multi-user.target.wants/sprachsteuerung.service

    eine neue Datei anlegen. Der Inhalt dieser Datei soll so aussehen:

    Mit STRG-x und y die Datei speichern und verlassen. Danach noch folgende Eingaben:

    sudo systemctl enable sprachsteuerung.service

    sudo systemctl start sprachsteuerung.service

    Nun läuft die Sprachsteuerung und würde nach jedem Neustart automatisch gestartet. Wenn die Kommentarzeichen # in den beiden Restart-Zeilen entfernt werden startet das Skript auch im Falle von Fehlern (z. B. Unerreichbarkeit des MQTT-Brokers) immer wieder neu. Sonst würde es bei einem solchen Zustand/Fehler einfach stoppen und die Sprachbefehlsausführung nicht mehr umsetzen.

    Grundsätzlich ist es möglich, dass die Ausführung von Skripten im Prinzip in Snips-Assistenten mit angelegt werden kann. Die Bezeichnung von Snips dafür ist es, eine action zu definieren. Diese wird in der Snips-Console an der Stelle angelegt, wo auch ein Intent definiert wird. Rechts neben dem Tab Intent befindet sich der Tab Action. Dort kann man unter Nutzung diverser Hermes-*-Python-Bibliotheken mehr oder weniger komplexe Skripte programmieren, die fest mit Snips verbunden werden. Doch die Aktivierung dieser Skripte ist nicht gerade ein Selbstläufer. Deshalb möchte ich hier nicht darauf eingehen.