FHEMWEB/VoiceControl: Web-STT & Hardware-Wakeword
VoiceControl – Sprachsteuerung via Browser und Atom Echo S3
Diese Lösung ermöglicht eine flexible Sprachsteuerung für FHEM. Sprache wird in Text (Speech-to-Text) umgewandelt und als Reading STT im Device global bereitgestellt. Dieses Reading kann anschließend zentral (z. B. über notify oder DOIF) ausgewertet werden.
Das System unterstützt zwei unterschiedliche Wege zur Spracherfassung:
- Weg 1️⃣ (Software): Browser-basierte Komplettlösung
- Weg 2️⃣ (Hybrid): Hardware-Wakeword + Browser-Spracherkennung
Hilfe
- Forenthread zum VoiceControl Sprachsteuerung
Dort befinden sich in Post #1 auch alle benötigten Dateien.
Funktionen
Grundprinzip
- Sprache → Speech-to-Text
- Ergebnis → Reading
STTim Deviceglobal - Zentrale Logik verarbeitet Befehle
Betriebsarten
- Push-to-Talk (nur Browser)
- Always-On mit Wakeword
- Hardware-Wakeword (Hybrid)
Rückmeldungen
- Sprachausgabe (TTS)
- Visuelle Bubble im Browser
- Optional gezielte Rückmeldung per Client-ID
Weg 1️⃣: Browser-Lösung (voicecontrol.js)
Das Script nutzt die Google Web Speech API. Unterstützt werden Chromium-basierte Browser (Chrome, Edge, Fully Browser). Firefox wird aktuell nicht unterstützt.
Bedienung
Push-to-Talk
- Button gedrückt halten (~450 ms)
- Direkt sprechen (kein Wakeword nötig)
- Befehl wird sofort verarbeitet
Always-On
- Kurzer Klick aktiviert Dauerbetrieb
- Wakeword erforderlich (Standard: „James“)
- Nach Aktivierung permanentes Mithören
Wakeword
- Standard:
james - Anpassbar im Script:
const wakewords = ["james"];
Ablauf:
- „James“ sagen
- System antwortet „Ja?“
- Zeitfenster (~6 Sekunden) für Befehl
- Danach automatische Verarbeitung oder Abbruch
Installation
Datei kopieren
voicecontrol.js nach:
/opt/fhem/www/voicecontrol/
Einbindung
attr WEBphone JavaScripts voicecontrol/voicecontrol.js
Hinweis (HTTP ohne HTTPS)
Chrome benötigt Freigabe für Mikrofon:
chrome://flags/#unsafely-treat-insecure-origin-as-secure- Eigene URL hinzufügen
- Auf
Enabledsetzen
Weg 2️⃣: Hybrid-Lösung mit Browser + Atom Echo (voicecontrol_echo.js)
Diese Variante kombiniert Hardware und Software:
- Wakeword-Erkennung erfolgt auf dem ESP (Atom Echo S3)
- Die eigentliche Sprachverarbeitung (Speech-to-Text) erfolgt im Browser
Funktionsweise
- Wakeword wird auf dem ESP erkannt
- FHEM erzeugt Event (z. B.
james_detected) - Browser empfängt Event via WebSocket
- Speech-to-Text startet im Browser
- Ergebnis wird an FHEM übertragen
Aktivierung
- Kurzer Klick auf Button aktiviert/deaktiviert System
- Baut WebSocket-Verbindung zu FHEM auf
- Kein Push-to-Talk-Modus
Konfiguration im Javascript
const DEVICE = "atom_echos3r_9888e00f4280";
const TRIGGER = "james_detected";
const FHEM_IP = "192.168.1.76:8085";
DEVICE→ FHEM-Device des ESPTRIGGER→ Event bei WakewordFHEM_IP→ FHEM-Server
Konfiguration in der Yaml
Damit sich der ESP mit eurem MQTT-Server und WLAN verbindet, müssen folgende Stellen angepasst werden.
wifi:
ssid: "YOUR_SSID"
password: "YOUR_PW"
fast_connect: true
mqtt:
broker: 192.168.1.76
port: 1884
username: "YOUR_USERNAME"
password: "YOUR_PW"
topic_prefix: atom_echo
Wakeword (ESP / ESPHome)
Das Wakeword wird direkt auf dem ESP definiert:
- Umsetzung über ESPHome
- Eine große Auswahl an Wakewords sind hier zu finden:
https://github.com/TaterTotterson/microWakeWords
Hier ein Beispiel, wie das Wakeword definiert wird.
micro_wake_word:
id: mww
microphone: echo_mic
models:
- model: "https://github.com/TaterTotterson/microWakeWords/raw/main/microWakeWordsV2/james.json"
id: james_model
probability_cutoff: 0.6
Kommunikation
- WebSocket-Verbindung zu FHEM
- Lauscht auf Device-Events
- Automatischer Reconnect bei Abbruch
Ablauf nach Wakeword
- System sagt „Ja?“
- Browser startet SpeechRecognition
- Nutzer spricht Befehl
- Befehl wird verarbeitet
- Rückmeldung „Erledigt“
Installation
siehe oben wie unter Punkt 1.
Zentrale Auswertung (Logik)
Beide Wege schreiben in:
global:STT
Die Verarbeitung erfolgt zentral über ein notify.
Beispiel: notify
defmod n_VoiceControl notify global:STT:.* {\
# Parsing: Befehl und ID trennen\
my ($cleanEvent, $clientId) = $EVENT =~ /^(.*)\s\[(.*)\]$/;;\
$cleanEvent //= $EVENT;;\
$clientId //= "unknown";;\
my $event_lc = lc($cleanEvent);;\
\
# Befehlmapping\
my %simpleCmds = (\
"stt: esszimmer licht an" => "set Lampe01_Ez on",\
"stt: esszimmer licht aus" => "set Lampe01_Ez off",\
"stt: küche licht an" => "set Deckenlampe_Kue on",\
"stt: küche licht aus" => "set Deckenlampe_Kue off",\
"stt: fernseher an" => "set VuPlus on",\
"stt: fernseher aus" => "set VuPlus off",\
"stt: lade roberto" => "set MQTT2_valetudo_FlusteredUnequaledFish charge",\
"stt: ambilight" => '{ system("sshpass -p \'1431Fhem1982\' ssh -o StrictHostKeyChecking=no root\@192.168.1.46 \"/usr/share/hyperhdr/scripts/hyperhdr_toggle.sh\"") }',\
);;\
\
if (exists $simpleCmds{$event_lc}) {\
fhem($simpleCmds{$event_lc});;\
}\
\
# Valetudo\
elsif ($event_lc =~ /reinige/) {\
my %rooms = (\
"arbeitszimmer" =>"Arbeitszimmer",\
"badezimmer" =>"Badezimmer",\
"esszimmer" =>"Esszimmer",\
"flur" =>"Flur",\
"küche" =>"Küche",\
"wohnzimmer" =>"Wohnzimmer");;\
my @found = grep { index($event_lc, $_) != -1 } keys %rooms;;\
fhem("set MQTT2_valetudo_FlusteredUnequaledFish clean_segment ".join(",", map { $rooms{$_} } @found)) if @found;;\
}\
# Lampenscene\
elsif ($event_lc =~ /ambiente/) {\
if ($event_lc =~ /(\d+)/) { my $b = ($1 > 255 ? 255 : ($1 < 1 ? 1 : $1));; fhem("set LampeSzeneAlle brightness $b") }\
elsif ($event_lc =~ /an/) { fhem("set LampeSzeneAlle on") }\
elsif ($event_lc =~ /aus/) { fhem("set LampeSzeneAlle off") }\
}\
# Kommandoübersicht\
elsif ($event_lc =~ /kommandos/) {\
my $h = '<div style="text-align:left;;min-width:200px;;font-family:sans-serif;;"><b>Befehlsübersicht:</b><br><br>';;\
$h .= "• ".($_ =~ s/^stt: //r)."<br>" for sort keys %simpleCmds;;\
$h .= "• reinige [küche, bad, ...]<br>• ambiente [an|aus|0-255]</div>";;\
$h =~ s/'/\\"/g;;\
\
my $js = "if((document.querySelector('input[name=\"fw_id\"]')||{}).value==='$clientId'){FW_okDialog('$h')}";;\
FW_directNotify("#FHEMWEB:$_", $js, "")\
for devspec2array("TYPE=FHEMWEB");;\
}\
}
Unterschiede der Wege
| Feature | Browser | Hybrid (Atom Echo S3) |
|---|---|---|
| Wakeword | Browser | ESP (Hardware) |
| Push-to-Talk | Ja | Nein |
| Always-On | Ja | Ja |
| Audioaufnahme | Permanent möglich | Nur nach Trigger |
| Architektur | Software | Software + Hardware |
| Stabilität | Stabil | Sehr stabil (Wakeword extern) |
FireOS mit Fully Browser (Plus)
Damit die Spracherkennung funktioniert:
- Apps installieren:
Google Speech Recognition & Synthesis
- FireOS:
„Tastatur und Sprache“ → „Text-to-Speech“
- Fully Browser:
Enable JavaScriptInterface (PLUS) aktivieren