openHAB :: Sprachausgabe auf einem Raspberry
Mit Hilfe von TTS-Diensten ist es uns möglich, gesprochenen Text über an den Raspberry angeschlossene Lautsprecher ausgeben zu lassen. Wir nutzen dazu einen TextToSpeech-Modul, das uns eine API für die Kommandozeile bietet. Die Nachteile hieran sind natürlich, dass die Himbeere eine permanente Verbindung zum Internet benötigt und die zu sprechenden Sätze zum Anbieter gesendet werden. Die Umsetzung und Integration in openHAB zeigt dieser Artikel.
Verfügbare Artikel zu openHAB
!slideshow_deploy!
System aktualisieren
Zunächst aktualisieren wir unseren Raspberry mit dem bekannten
1 |
apt-get update && apt-get upgrade |
Audio testen
Wir installieren die notwendigen Pakete, um Audio abspielen zu können mit:
1 |
apt-get install mplayer mplayer-gui alsa-base alsa-utils |
Anschließend lassen wir den Raspberry das Soundmodul beim Booten starten:
1 |
echo 'snd-bcm2835' >> /etc/modules |
Nun starten wir unser System neu:
1 |
reboot |
Zum Testen besorgen wir uns zunächst irgendeine .wav-Datei und speichern diese auf unserem Raspberry:
1 2 3 4 |
mkdir -p /scripts/audio cd /scripts/audio wget -O testeins.wav http://www.ringelkater.de/Sounds/3aeusserungen_westfalen/GEJIDEL.WAV aplay testeins.wav |
Konnten wir den Herrn mit dem westfälischen Akzent vernehmen, haben wir den ersten Schritt geschafft.
Lautstärke erhöhen
Anschließend erhöhen wir die Systemlautstärke des Raspberrys auf 100%. Dafür eignet sich am besten das Programm alsamixer. Dieses starten wir in der Befehlszeile mit
1 |
alsamixer |
Mit den Hoch- und Runter-Pfeiltasten erhöhen bzw. verringern wir die Lautstärke und „ESC“ beendet das Programm. Die getroffene Einstellung wird mittels
1 |
alsactl store |
(ausgeführt als Nutzer root) gespeichert.
Anmelden bei einem TTS-Dienst
Bisher habe ich für die Sprachausgabe die TTS-Engine von Google genutzt. Diese wurde nun mit einem Captcha versehen, so dass diese für unsere Zwecke nicht mehr sinnvoll einzusetzen ist. Daher weichen wir auf einen anderen Anbieter aus. Nach einer kurzen Registrierung bei voicerss.org erhalten wir einen API-Schlüssel, den wir uns für unsere Zwecke speichern. Wie der Dienst von VoiceRSS einzusetzen ist, zeigt die kurze, aber verständliche Dokumentation unter http://www.voicerss.org/api/documentation.aspx. Es ergibt sich dementsprechend eine URL, die wie folgt aufgebaut ist:
1 |
http://api.voicerss.org/?key=DEIN_API_KEY&f=22khz_16bit_mono&hl=de-de&src=Hallo |
Hier muss natürlich der nach der Registrierung erhaltene Key eingetragen werden.
TTS-Script erstellen
Nun erstellen wir ein Script, dass unsere Texte mit Hilfe vom TTS-Dienst von VoiceRSS vorliest.
1 |
nano /scripts/tts.sh |
Wir kopieren das folgende Script in die neu erstellte Datei:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
#!/bin/bash /usr/bin/amixer cset numid=1 $2% if [ -n "$3" ] ; then /usr/bin/aplay /scripts/audio/$3.wav &> /dev/null fi INPUT=$1 STRINGNUM=0 ary=($INPUT) for key in "${!ary[@]}" ; do SHORTTMP[$STRINGNUM]="${SHORTTMP[$STRINGNUM]} ${ary[$key]}" LENGTH=$(echo ${#SHORTTMP[$STRINGNUM]}) if [[ "$LENGTH" -lt "100" ]]; then SHORT[$STRINGNUM]=${SHORTTMP[$STRINGNUM]} else STRINGNUM=$(($STRINGNUM+1)) SHORTTMP[$STRINGNUM]="${ary[$key]}" SHORT[$STRINGNUM]="${ary[$key]}" fi done for key in "${!SHORT[@]}" ; do say() { local IFS=+;/usr/bin/mplayer -ao alsa -really-quiet -noconsolecontrols "http://api.voicerss.org/?key=DEIN_API_KEY&f=22khz_16bit_mono&hl=de-de&src=${SHORT[$key]}"; } say $* done |
Wir erlauben die Ausführung des Scripts mit
1 |
chmod +x /scripts/tts.sh |
und testen dieses sogleich:
1 |
/scripts/tts.sh "dies ist ein test" 100 |
Das Script erlaubt die dynamische Angabe der auszugebenden Lautstärke. Diese geben wir in diesem Aufruf mit 100% an. Zusätzlich kann vor dem vorgelesenen Text eine WAV-Datei abgespielt werden, die im Ordner „/scripts/audio“ erwartet wird. Z.B.:
1 |
/scripts/tts.sh "dies ist ein test" 100 kuckuck |
…spielt zuvor die Datei „/scripts/audio/kuckuck.wav“ ab und liest anschließend den Text „dies ist ein test“ mit der Lautstärke 100% vor.
Integration in openHAB
Auf unserem Server, auf dem openHAB läuft, erstellen wir ein weiteres Script, um Texte remote auf dem Raspberry vorlesen zu lassen:
1 |
nano /scripts/vorlesen.sh |
Das Script wird mit folgenden Inhalt befüllt:
1 2 |
#!/bin/bash /usr/bin/ssh -i /scripts/.ssh/id_rsa root@192.168.1.$1 "/scripts/tts.sh \"$2\" $3 $4" &> /dev/null |
Wir erlauben die Ausführung des Scripts durch
1 |
chmod +x /scripts/vorlesen.sh |
und übertragen den Besitz an „openhab“ durch
1 |
chown openhab: /scripts/vorlesen.sh |
Nun definieren wir ein neues Item, um in der openHAB-Sitemap die Lautstärke einstellen zu können, mit der die Texte vorgelesen werden:
1 |
Number BOXEN_EZ_VOL "Lautstärke [%.1f %%]" |
Das neue Item binden wir in der Sitemap ein:
1 |
Slider item=BOXEN_EZ_VOL |
Die Lautsprecher selbst sind an einem 433-MHz Sender angeschlossen, so dass diese nicht permanent eingeschaltet sein müssen:
1 |
Switch BOXEN_EZ <speaker> (grp_BOXEN) { exec=">[ON:/scripts/fsd.sh 10011 4 1] >[OFF:/scripts/fsd.sh 10011 4 0]" } |
Die Steuerung von 433MHz-Geräten wird in diesem Beitrag und die Integration dieser in openHAB in diesem Beitrag beschrieben.
Eine praktische Anwendung findet beispielsweise als Regel in openHAB statt. Morgens lasse ich mich bei der zum Trödeln einladenden Tasse Kaffee gerne daran erinnern, dass ich mich auf den Weg zur Arbeit machen sollte. Dazu erstellen wir einen neuen Regelblock, der so strukturiert sein könnte:
1 2 3 4 5 6 |
rule "Morgens zur Maloche" when Time cron "0 40 06 * * ?" then executeCommandLine("/scripts/vorlesen.sh@@236@@Es wird langsam Zeit, zur Arbeit aufzubrechen.@@" + BOXEN_EZ_VOL.state + "@@clock", 2000) end |
Morgens um 06:40 Uhr wird auf dem Raspberry mit der IP „192.168.1.236“ der Ton „/scripts/audio/clock.wav“ abgespielt und anschließend der definierte Text vorgelesen. Die Lautstärke entspricht der in der Sitemap eingestellten (item: BOXEN_EZ_VOL). Die Angabe eines vorab abgespielten Tons ist dabei optional. Die doppelten @-Zeichen stehen in diesem Aufruf für ein Leerzeichen zwischen den Attributen.
Als weiteres Beispiel konstruieren wir uns eine digitale Kuckucksuhr. Zunächst erstellen wir auf dem openHAB-Server ein weiteres Script:
1 2 3 4 |
#!/bin/bash #Script: /scripts/stunde.sh /usr/bin/ssh -i /scripts/.ssh/id_rsa root@192.168.1.$1 '/usr/bin/aplay /scripts/audio/kuckuck.wav &> /dev/null && /scripts/tts.sh "Es ist $(date +%H) Uhr" 100 &> /dev/null' |
…und erstellen eine neue openHAB-Regel:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
rule "Kuckuck" when Time cron "0 00 * * * ?" then if(BOXEN_EZ.state == OFF) { sendCommand(BOXEN_EZ, ON) Thread::sleep(2000) executeCommandLine("/scripts/stunde.sh@@236", 2000) Thread::sleep(10000) sendCommand(BOXEN_EZ, OFF) } if(BOXEN_EZ.state == ON) { executeCommandLine("/scripts/stunde.sh@@236", 2000) } end |
Diese Regel führt stündlich das lokale Script „/scripts/stunde.sh“ aus, welches wiederum die Audiodatei „/scripts/audio/kuckuck.wav“ auf dem Raspberry mit der IP „192.168.1.236“ abspielt und anschließend die Stunde vorliest. Zusätzlich prüft diese Regel vorab, ob die Boxen im Esszimmer eingeschaltet sind oder nicht. Wenn nicht, werden diese für die Zeit der Aktion ein- und anschließend wieder ausgeschaltet.
Nun ist die eigene Phantasie gefragt. Es könnten beispielsweise Warnungen ausgegeben werden, wenn irgendein Wasserstand zu niedrig ist oder eine Temperatur einen Wert über-/unterschreitet. Selbst eine kleine „Alarmanlage“ (in Anführungszeichen!) könnte so umgesetzt werden.
Peter
03.02.2016 @ 11:58
@Peter, wie haben sie den Aufruf in der Rules geändert? Ich habe auch nur normale Lautsprecher am Pi.
Gruß Peter
Peter
27.01.2016 @ 18:58
Hi, hat sich erledigt… Es war wegen den Lautsprechern gewesen… Weil die Beschreibung ist mit den 433 MHZ Lautsprecher gewesen und die rule hat nicht gewusst was sie machen soll wegen dem + BOXEN_EZ_VOL.state + „@@clock“, 2000… Ich habe normale Lautsprechen an den Pi angeschlossen…
Jetzt funktioniert es aber zu 100%. Danke für die gute Anleitung..
Daniel Wenzel
27.01.2016 @ 01:08
Hallo,
kannst du mir bitte die entsprechende rule hier mitteilen? Dann schauen wir mal.
Peter
20.01.2016 @ 07:27
Hi,
evtl. einen Tipp für mich? habe alles step-by-step gemacht aber bei mir kommt die Fehlermeldung in Openhab bei rule „zur Arbeit gehen“
2016-01-20 07:21:06.496 [WARN ] [g.openhab.io.net.exec.ExecUtil] – Process exited with an error: 143 (Exit value: 143)
Danke vorab…
Pedro
12.01.2016 @ 12:53
Hi Daniel, ich wollte nur kurz bescheid geben das ich es mit der Sprachausgabe hinbekommen habe. Das Problem lag bei den rechten von Openhab. Jetzt funktioniert es.
Gruß und danke für die Unterstützung.
Daniel Wenzel
12.01.2016 @ 05:00
Das sollte auch möglich sein.
Probier doch mal folgendes:
executeCommandLine(„/scripts/vorlesen.sh@@236@@as Telefon klingelt. “ + Incoming_Call_No.state + “ ruft an.@@“ + BOXEN_EZ_VOL.state, 2000)
Habs grad selber nicht getestet, könnte aber klappen.
Robert Kleinert
11.01.2016 @ 22:06
Hi,
danke für die tolle Anleitung.
Ist es auch möglich eine Variable aus OpenHAB zu übergeben? Ich würde gerne die Nummer bzw. den Namen des Anrufers vorlesen lassen (mit dem neuen FritzBox Binding).
Ist das möglich?
Lg,
Robert
Daniel Wenzel
04.01.2016 @ 05:55
Hallo Pedro,
1) Den Wert des Items „BOXEN_EZ_VOL“ legst du selber in der Sitemap fest, deshalb hast du das Item auch in die sitemap eingebunden.
2) Auf den ersten Blick sehen die Scripte aus wie in der Anleitung
3) Natürlich ist deine Himbeere „Passwort-geschützt“, wäre schlimm, wenn nicht ;) Damit sich openHAB ohne Passwort via SSH auf deiner Himbeere anmelden kann, musst du zuvor unbedingt folgende Anleitung durchführen:
https://klenzel.de/1871
Grüße
Daniel
Pedro
03.01.2016 @ 17:03
hallo nochmal
also ich habe versucht alles an zu passen, leider ohne erfolg
hier mal alles im überblick
items:
Switch test
Number BOXEN_EZ_VOL „Lautstärke [%.1f %%]“
frage dazu, wo hollt sich das item den die info wie laut die lautsprecher im putty wirklich eingestellt sind, oder wie laut er es abspielen soll?
sitemaps
Switch item=test
Slider item=BOXEN_EZ_VOL
rule
rule „Morgens zur Maloche“
when
Item test changed from OFF to ON
then
executeCommandLine(„/scripts/vorlesen.sh@@90@@Es wird langsam Zeit, zur Arbeit aufzubrechen.@@“ + BOXEN_EZ_VOL.state, 2000)
end
hier nochmal genau der inhalt der vorlesen.sh datei
#!/bin/bash
/usr/bin/ssh root@192.168.178.$1 „/scripts/tts.sh „$2″ $3 $4“ &> /dev/null
was ich noch sagen möchte, ist das ich nur einen Raspberry habe und der durch ein passwort geschützt ist. vielleicht hilf das ja :-(. Gruß
Daniel Wenzel
30.12.2015 @ 06:56
Hallo,
1) Die @-Zeichen stehen jeweils für ein Leerzeichen in der Befehlszeile und müssen daher mit übernommen werden.
2) In deinem Beispielscript oben nutzt du die „.1“ in dritten Oktett. Weiter unten schreibst du, dass dein Netzwerk die „.178“ im dritten Oktett konfiguriert hat. Das kann nicht funktionieren
3) Du scheinst im Script auf dem openHAB-Rechner die Anführungszeichen nicht richtig übernommen zu haben. Schau dafür nochmal in den entsprechenden Punkt der Anleitung.
4) Wenn alle Scripte richtig angepasst haben, sind im Shell-Script auf dem openHAB-Rechner die ersten drei Oktette „192.168.178“ fest vorgegeben, dass heißt du mit in der „executeCommandLine“ nur noch das vierte Oktett, in deinem Fall die „90“ angeben
Wenn du weitere Fragen hast, melde dich gerne wieder.
Pedro
29.12.2015 @ 08:53
hallo schon wieder :-),
ich probiere immer wieder was neues eurer seite aus, mit der sprachausgabe bin ich jetzt bis zum erreichen von (integrieren in Openhab ) erfolgreich gewesen. leider tut sich jetzt nichts mehr :-(.
muss das vorlese script genau so aussehen oder muss ich da meine ip eingeben?
(#!/bin/bash
/usr/bin/ssh root@192.168.1.$1 „/scripts/tts.sh „$2″ $3 $4“ &> /dev/null)
als nächstes
(executeCommandLine(„/scripts/vorlesen.sh@@236@@Es wird langsam Zeit, zur Arbeit aufzubrechen.@@“ + BOXEN_EZ_VOL.state + „@@clock“, 2000)
end)
muss ich diese @ zeichen rein machen und wieder die frage zwecks meiner IP?
executeCommandLine(„/scripts/vorlesen.sh 192.168.178.90 Es wird langsam Zeit, zur Arbeit aufzubrechen. “ )
end
so richtig?
sorry für die dummen fragen.
Danke im voraus
Daniel Wenzel
19.11.2015 @ 11:04
Danke für das Lob. Nein, Sonos kommt mir nicht ins Haus. Aber es ist ein Artikel in Vorbereitung, wie wir Squeezeboxen (oder Raspberrys als Squeezebox mit squeezelight) in openHAB einbinden können.
Miki
19.11.2015 @ 11:00
Wow! Das sieht super aus! Das weckt wieder ganz neue Ideen in mir! :)
Du hast nicht zufällig ein Sonos System? Weißt du wie ich die Sprachausgaben über das Sonos schicken könnte?
Gruß
Miki