Voice Assistant & Smart Display
Overview
Self-hosted Echo Show replacement using a Samsung Galaxy Tab A8 as an always-on smart display with fully local voice assistant, Spotify control, and calling.
Architecture:
Tab A8 (Fully Kiosk Browser + HA Companion App)
|
| wake word detected on-device (microWakeWord)
| audio sent to ops-01 after wake word
v
ops-01 (10.10.30.40)
├── Home Assistant (host network, port 8123)
├── Wyoming Whisper (STT, port 10300)
├── Wyoming Piper (TTS, port 10200)
└── Wyoming openWakeWord (port 10400, for future ESP32 satellites)
The HA Companion App (2026.3+) handles wake word detection on-device using microWakeWord. No audio leaves the tablet until after the wake word is detected. The openWakeWord container is for future ESP32 voice satellites only.
Phase 1: Voice Pipeline Containers
Directory Setup
sudo mkdir -p /opt/docker/wyoming/{whisper-data,piper-data,openwakeword-data,openwakeword-custom}
sudo chown -R goose:goose /opt/docker/wyoming
Compose File
/opt/docker/wyoming/compose.yaml
services:
whisper:
container_name: whisper
image: rhasspy/wyoming-whisper
restart: unless-stopped
ports:
- "10300:10300"
volumes:
- ./whisper-data:/data
command:
- "--model"
- "small-int8"
- "--language"
- "en"
dns:
- 10.10.30.1
piper:
container_name: piper
image: rhasspy/wyoming-piper
restart: unless-stopped
ports:
- "10200:10200"
volumes:
- ./piper-data:/data
command:
- "--voice"
- "en_US-lessac-medium"
dns:
- 10.10.30.1
openwakeword:
container_name: openwakeword
image: rhasspy/wyoming-openwakeword
restart: unless-stopped
ports:
- "10400:10400"
volumes:
- ./openwakeword-data:/data
- ./openwakeword-custom:/custom
command:
- "--preload-model"
- "ok_nabu"
- "--custom-model-dir"
- "/custom"
dns:
- 10.10.30.1
Deploy
cd /opt/docker/wyoming
docker compose up -d
docker compose logs -f
Models download on first boot (1-3 minutes). Wait for Ready in each container's logs.
Model Notes
- Whisper
small-int8: ~1 second processing on i5-8500T, ~500MB RAM. Drop totiny-int8if too slow, bump tomedium-int8if accuracy is poor. - Piper
en_US-lessac-medium: Best general English voice. Preview others at rhasspy.github.io/piper-samples. - openWakeWord: Built-in words include
ok_nabu,hey_jarvis,hey_mycroft. Only used by ESP32 satellites, not the tablet.
To change a model, edit the command in compose.yaml and run docker compose up -d. The new model downloads automatically.
Phase 2: Connect to Home Assistant
Add Wyoming Integrations
Add three separate Wyoming integrations, one for each container. Use ops-01's VLAN IP (not localhost).
- Settings > Devices & Services > + Add Integration > Wyoming Protocol
- Host:
10.10.30.40, Port:10300(detected as Whisper STT) - Repeat: Host:
10.10.30.40, Port:10200(detected as Piper TTS) - Repeat: Host:
10.10.30.40, Port:10400(detected as openWakeWord)
Use the actual IP, not localhost
HA runs with network_mode: host but using 127.0.0.1 can fail depending on Docker's loopback handling. Always use the VLAN IP.
Create Assist Pipeline
- Settings > Voice Assistants > + Add Assistant
- Name:
Vanth - Speech-to-text: faster-whisper
- Text-to-speech: piper
- Wake word: hey_jarvis (or ok_nabu)
- Conversation agent: Home Assistant (default)
Expose Entities
Assist can only control entities explicitly exposed to it.
- Settings > Voice Assistants > Expose tab
- Toggle on entities you want voice-controllable
- Set clear aliases for anything with cryptic names
- Assign entities to Areas (Settings > Areas & Zones) for room-based commands like "turn off the lights in the kitchen"
Phase 3: Tablet Setup
Factory Reset & Debloat
Factory reset the Tab A8 first. After initial Google sign-in, debloat via ADB before installing anything else.
From any machine with ADB (e.g., kupier):
sudo apt install android-tools-adb
Enable Developer Options on tablet (Settings > About tablet > tap Build number 7 times), then enable USB debugging. Connect via USB.
adb devices # approve prompt on tablet
Remove Samsung bloatware:
adb shell pm uninstall -k --user 0 com.samsung.android.app.spage
adb shell pm uninstall -k --user 0 com.samsung.android.bixby.agent
adb shell pm uninstall -k --user 0 com.samsung.android.bixby.service
adb shell pm uninstall -k --user 0 com.samsung.android.visionintelligence
adb shell pm uninstall -k --user 0 com.samsung.android.game.gamehome
adb shell pm uninstall -k --user 0 com.samsung.android.game.gametools
adb shell pm uninstall -k --user 0 com.samsung.android.app.tips
adb shell pm uninstall -k --user 0 com.samsung.android.mobileservice
adb shell pm uninstall -k --user 0 com.samsung.android.app.watchmanagerstub
adb shell pm uninstall -k --user 0 com.samsung.android.ardrawing
adb shell pm uninstall -k --user 0 com.samsung.android.aremoji
adb shell pm uninstall -k --user 0 com.samsung.android.arzone
adb shell pm uninstall -k --user 0 com.samsung.android.app.dressroom
adb shell pm uninstall -k --user 0 com.samsung.android.spay
adb shell pm uninstall -k --user 0 com.samsung.android.spayfw
adb shell pm uninstall -k --user 0 com.samsung.android.app.sbrowseredge
adb shell pm uninstall -k --user 0 com.samsung.android.samsungpass
adb shell pm uninstall -k --user 0 com.samsung.android.samsungpassautofill
adb shell pm uninstall -k --user 0 com.sec.android.app.samsungapps
adb shell pm uninstall -k --user 0 com.samsung.android.themestore
adb shell pm uninstall -k --user 0 com.samsung.android.app.reminder
adb shell pm uninstall -k --user 0 com.samsung.android.calendar
adb shell pm uninstall -k --user 0 com.samsung.android.email.provider
adb shell pm uninstall -k --user 0 com.samsung.android.app.notes
adb shell pm uninstall -k --user 0 com.microsoft.office.officehubrow
adb shell pm uninstall -k --user 0 com.microsoft.skydrive
adb shell pm uninstall -k --user 0 com.microsoft.appmanager
adb shell pm uninstall -k --user 0 com.linkedin.android
adb shell pm uninstall -k --user 0 com.facebook.katana
adb shell pm uninstall -k --user 0 com.facebook.appmanager
adb shell pm uninstall -k --user 0 com.facebook.system
adb shell pm uninstall -k --user 0 com.netflix.mediaclient
adb shell pm uninstall -k --user 0 com.samsung.android.forest
adb shell pm uninstall -k --user 0 com.samsung.android.app.social
To find anything else: adb shell pm list packages -f | grep samsung
To restore if needed: adb shell cmd package install-existing <package.name>
Do NOT remove
com.samsung.android.incallui, com.samsung.android.telecom, com.samsung.android.providers.contacts, com.google.android.gms, com.google.android.gsf, com.android.systemui
Install HA Companion App
- Install from Play Store
- Open, enter HA URL:
http://ops-01.internal:8123(or direct IP) - Grant all permissions (microphone, camera, location, notifications)
- Configure wake word: Settings > Companion app > Assist for Android
- Tap Set as default, set Home Assistant as default digital assistant
- Enable Wake word detection, select "Hey Jarvis"
- Select the Assist pipeline you created ("Vanth")
Samsung battery optimization will kill wake word detection
- Settings > Apps > Home Assistant > Battery > Unrestricted
- Settings > Device care > Battery > Background usage limits > add HA to Never sleeping
- Consider disabling Adaptive battery entirely since this tablet is always plugged in
Install Fully Kiosk Browser
- Install from Play Store (~$9 for Plus license to remove watermark)
- Open, enter start URL:
http://ops-01.internal:8123/tablet/0 - Swipe from left edge to open settings menu
- Configure:
- Web Content Settings > Autoplay Videos: ON
- Web Content Settings > Enable Microphone Access: OFF (critical -- prevents mic conflict with Companion App)
- Device Management > Keep Screen On: ON
- Motion Detection > Enable: ON (use camera, not microphone)
- Motion Detection > Turn Screen On on Motion: ON
- Remote Administration > Enable: ON, set a password
- Kiosk Mode > Enable Kiosk Mode: ON
- Kiosk Mode > Kiosk Exit Gesture: set a gesture you'll remember
- Kiosk Mode > App Whitelist: add one per line:
io.homeassistant.companion.android com.google.android.apps.googlevoice com.facebook.orca - Kiosk Mode > Applications to Run on Start in Background:
io.homeassistant.companion.android
Microphone conflict
Fully Kiosk and the Companion App cannot use the mic simultaneously. Keep Enable Microphone Access OFF in Fully Kiosk and use camera-based motion detection, not microphone-based. This lets the Companion App hold the mic for wake word detection.
Add Fully Kiosk Integration to HA
- Settings > Devices & Services > + Add Integration > Fully Kiosk Browser
- Enter the tablet's IP and Remote Admin password
- Uncheck "Verify SSL"
Phase 4: Dashboard
Create a dedicated tablet dashboard: Settings > Dashboards > + Add Dashboard, name "Tablet", URL tablet.
Greeting Card
type: markdown
content: >
{% set hour = now().hour %}
{% if hour < 12 %}
<h1 style="font-size: 2.5em; font-weight: 300; margin: 0;">Good morning</h1>
{% elif hour < 17 %}
<h1 style="font-size: 2.5em; font-weight: 300; margin: 0;">Good afternoon</h1>
{% else %}
<h1 style="font-size: 2.5em; font-weight: 300; margin: 0;">Good evening</h1>
{% endif %}
<h3 style="font-size: 1.2em; font-weight: 300; opacity: 0.6; margin: 0;">{{ now().strftime('%A, %B %-d') }}</h3>
Note
HA's markdown renderer strips inline styles from <p> tags but allows them on headings. Use <h1>, <h3>, etc.
Weather
Add a Weather Forecast card. If no weather integration exists: Settings > Integrations > + Add > Met.no (no API key needed).
Timer
Create a timer helper: Settings > Devices & Services > Helpers > + Create Helper > Timer. Name it, set a default duration.
Add to dashboard:
type: tile
entity: timer.timer
Tap the card to start. Voice command "Hey Jarvis, set a timer for 5 minutes" works natively via Assist (separate from this entity).
Media / Spotify
See Phase 5. Once configured, add:
type: media-control
entity: media_player.spotify_YOUR_USERNAME
Call Buttons
See Phase 6. Add Button cards for each contact.
Phase 5: Spotify
Official Integration
- Go to developer.spotify.com/dashboard, log in with Spotify Premium
- Create App:
- Redirect URI:
http://ops-01.internal:8123/auth/external/callback - Select "Web API"
- Redirect URI:
- Copy Client ID and Client Secret
- In HA: Settings > Integrations > + Add > Spotify
- Enter credentials, authenticate
Redirect URI must exactly match your HA URL
IP vs hostname mismatch causes auth failures.
Spotcast (for voice-triggered playback)
The official integration cannot start playback on idle devices. Spotcast works around this.
- Install HACS if not already installed (hacs.xyz)
- HACS > Integrations > search "Spotcast" > install
- Get Spotify cookies:
- Open incognito window, go to open.spotify.com, log in
- DevTools (F12) > Application > Cookies > open.spotify.com
- Copy
sp_dcandsp_keyvalues - Close window WITHOUT logging out
- Add to
configuration.yaml:
spotcast:
sp_dc: "your_sp_dc_value"
sp_key: "your_sp_key_value"
- Restart HA
Note
Spotify cookies expire periodically. Re-extract when playback stops working.
Tablet as Spotify Connect Device
Install the Spotify app on the Tab A8 and log in. The tablet appears as a Spotify Connect target for playback through its speakers.
Phase 6: Calling
Apps on Tablet
- Google Voice: PSTN calls (real phone numbers). Set up at voice.google.com. In app settings, set calls to "Prefer Wi-Fi and mobile data".
- Facebook Messenger: Video calls to contacts on Messenger.
Both apps are whitelisted in Fully Kiosk (done in Phase 3). Incoming calls overlay the kiosk, and Fully Kiosk returns to the dashboard after the call ends.
HA Scripts
Create scripts in Settings > Automations & Scenes > Scripts > + Add Script.
Call Mom (Google Voice):
alias: "Call Mom"
sequence:
- action: fully_kiosk.load_url
target:
device_id: YOUR_TABLET_DEVICE_ID
data:
url: "tel:+15551234567"
Call Dad (Google Voice):
alias: "Call Dad"
sequence:
- action: fully_kiosk.load_url
target:
device_id: YOUR_TABLET_DEVICE_ID
data:
url: "tel:+15559876543"
Call Grandpa (Messenger):
alias: "Call Grandpa"
sequence:
- action: fully_kiosk.start_application
target:
device_id: YOUR_TABLET_DEVICE_ID
data:
application: "com.facebook.orca"
Find YOUR_TABLET_DEVICE_ID by creating the script via the visual editor and selecting the tablet as the target device.
Dashboard Buttons
type: button
name: "Call Mom"
icon: mdi:phone
icon_height: 80px
tap_action:
action: perform-action
perform_action: script.call_mom
show_state: false
type: button
name: "Call Grandpa"
icon: mdi:video
icon_height: 80px
tap_action:
action: perform-action
perform_action: script.call_grandpa
show_state: false
Use mdi:phone for voice calls, mdi:video for Messenger video calls.
Voice-Triggered Calling
Create config/custom_sentences/en/call_contacts.yaml:
language: "en"
intents:
CallGrandpa:
data:
- sentences:
- "call grandpa"
- "video call grandpa"
CallMom:
data:
- sentences:
- "call mom"
- "call mommy"
CallDad:
data:
- sentences:
- "call dad"
- "call daddy"
Add to configuration.yaml:
intent_script:
CallGrandpa:
speech:
text: "Calling grandpa now"
action:
- action: fully_kiosk.start_application
target:
device_id: YOUR_TABLET_DEVICE_ID
data:
application: "com.facebook.orca"
CallMom:
speech:
text: "Calling mom"
action:
- action: fully_kiosk.load_url
target:
device_id: YOUR_TABLET_DEVICE_ID
data:
url: "tel:+15551234567"
CallDad:
speech:
text: "Calling dad"
action:
- action: fully_kiosk.load_url
target:
device_id: YOUR_TABLET_DEVICE_ID
data:
url: "tel:+15559876543"
Restart HA. "Hey Jarvis, call mom" now works.
Do not rely on this tablet for 911
Google Voice E911 is unreliable. Keep a cell phone in the house -- even a deactivated phone with no service can dial 911.
HACS Recommendations
- card-mod: Custom CSS styling on any card (remove backgrounds, etc.)
- Mushroom Cards: Clean, modern, touch-friendly cards
- Mini Media Player: Better Spotify/media card than default
- Browser Mod: HA control of the tablet's browser (pop-up camera feeds, navigate views)
- Spotcast: Voice-triggered Spotify playback (covered in Phase 5)
Future: ESP32 Voice Satellites
Adding an M5Stack ATOM Echo (~$13) or ESP32-S3-BOX as a dedicated voice satellite:
- Satellite streams audio to HA
- openWakeWord on ops-01 handles wake word detection
- Whisper transcribes, Piper responds
- Audio plays through the satellite speaker
The Wyoming infrastructure deployed here supports this with no changes.
Smart Switches
For integrating existing lights with HA/voice, replace dumb switches with Zigbee smart switches.
Recommended: Inovelli Blue Series (VZM31-SN)
- Zigbee 3.0, full Zigbee2MQTT support
- Works with and without neutral wire (important for older homes)
- Dimmer + on/off in one device
- Multi-tap scene control for HA automations
- LED notification bar
- 3-way compatible
- ~$40/switch
Budget alternative: Sonoff ZBMINIL2 (~$10) -- no-neutral relay that fits behind existing switches. Keeps your current switch appearance.
Check for neutral wire before buying
Turn off breaker, pull a switch out, look for a bundle of white wires nutted together in the back of the box not connected to the switch. If present, you have neutral. Houses built before ~1985 often lack neutral in switch boxes.