239 lines
7.9 KiB
Markdown
239 lines
7.9 KiB
Markdown
|
|
# HA Voice Control — MCP Server + Webinterface
|
||
|
|
|
||
|
|
Spraakgestuurde Home Assistant bediening via Whisper voice-to-text.
|
||
|
|
Druk op een knop, spreek je commando, en stuur je smarthome aan.
|
||
|
|
|
||
|
|
## Architectuur
|
||
|
|
|
||
|
|
```
|
||
|
|
┌──────────────┐ ┌──────────────────┐ ┌─────────────────┐
|
||
|
|
│ Browser │────▶│ nginx (SSL) │────▶│ FastAPI │
|
||
|
|
│ (microfoon) │ │ ha.el-kadi.nl │ │ :8765 │
|
||
|
|
└──────────────┘ └──────────────────┘ │ │
|
||
|
|
│ ┌─────────────┐ │
|
||
|
|
┌──────────────┐ │ │ Whisper │ │
|
||
|
|
│ Claude / │──▶ MCP stdio ───────────────▶│ │ (spraak→tekst)│ │
|
||
|
|
│ DeepSeek │ │ └─────────────┘ │
|
||
|
|
└──────────────┘ │ ┌─────────────┐ │
|
||
|
|
│ │ HA REST API │ │
|
||
|
|
│ │ 192.168... │ │
|
||
|
|
│ └─────────────┘ │
|
||
|
|
└──────────────────┘
|
||
|
|
```
|
||
|
|
|
||
|
|
Twee interfaces:
|
||
|
|
1. **Web UI** op `www.ha.el-kadi.nl` — push-to-talk knop in de browser
|
||
|
|
2. **MCP Server** — via Claude Desktop / DeepSeek TUI (stdio)
|
||
|
|
|
||
|
|
Beide gebruiken dezelfde Whisper-transcriptie en Home Assistant client.
|
||
|
|
|
||
|
|
## Vereisten
|
||
|
|
|
||
|
|
- Python 3.10+
|
||
|
|
- Home Assistant met een [long-lived access token](https://www.home-assistant.io/docs/authentication/#your-account-profile)
|
||
|
|
- nginx (voor SSL en domein)
|
||
|
|
- Een domein (hier: `ha.el-kadi.nl`) met DNS die naar jouw server wijst
|
||
|
|
- Optioneel: CUDA-compatibele GPU voor snellere lokale Whisper
|
||
|
|
|
||
|
|
## Installatie
|
||
|
|
|
||
|
|
### 1. Clone en installeer dependencies
|
||
|
|
|
||
|
|
```bash
|
||
|
|
cd /opt # of een andere gewenste locatie
|
||
|
|
git clone <jouw-repo> ha-voice-control
|
||
|
|
cd ha-voice-control
|
||
|
|
python -m venv venv
|
||
|
|
source venv/bin/activate # Windows: venv\Scripts\activate
|
||
|
|
pip install -r requirements.txt
|
||
|
|
```
|
||
|
|
|
||
|
|
### 2. Configuratie
|
||
|
|
|
||
|
|
Kopieer het voorbeeld en vul je gegevens in:
|
||
|
|
|
||
|
|
```bash
|
||
|
|
cp .env.example .env
|
||
|
|
```
|
||
|
|
|
||
|
|
Bewerk `.env`:
|
||
|
|
|
||
|
|
```env
|
||
|
|
# Home Assistant
|
||
|
|
HA_URL=http://192.168.1.235:8123
|
||
|
|
HA_TOKEN=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
|
||
|
|
|
||
|
|
# Whisper: "local" (faster-whisper, offline) of "openai" (API)
|
||
|
|
WHISPER_MODE=local
|
||
|
|
WHISPER_MODEL=base
|
||
|
|
|
||
|
|
# Web server
|
||
|
|
WEB_HOST=127.0.0.1
|
||
|
|
WEB_PORT=8765
|
||
|
|
```
|
||
|
|
|
||
|
|
De Home Assistant token maak je aan via:
|
||
|
|
**Home Assistant → Profiel (linksonder) → Beveiliging → Lange-levensduur toegangstokens**
|
||
|
|
|
||
|
|
### 3. Eerste keer Whisper model downloaden
|
||
|
|
|
||
|
|
Bij de eerste start met `WHISPER_MODE=local` downloadt faster-whisper automatisch het model.
|
||
|
|
Beschikbare modellen (oplopend in grootte/nauwkeurigheid):
|
||
|
|
- `tiny` / `tiny.en` — ~75 MB, snelste
|
||
|
|
- `base` / `base.en` — ~145 MB, aanbevolen voor NL
|
||
|
|
- `small` / `small.en` — ~488 MB
|
||
|
|
- `medium` / `medium.en` — ~1.5 GB
|
||
|
|
- `large-v3` — ~3 GB, meest accuraat
|
||
|
|
|
||
|
|
`.en` varianten zijn alleen voor Engels. Voor Nederlands gebruik je de meertalige versies.
|
||
|
|
|
||
|
|
### 4. Start de web server
|
||
|
|
|
||
|
|
```bash
|
||
|
|
source venv/bin/activate
|
||
|
|
python -m src.web_server
|
||
|
|
# Of direct met uvicorn:
|
||
|
|
uvicorn src.web_server:app --host 127.0.0.1 --port 8765
|
||
|
|
```
|
||
|
|
|
||
|
|
Test of het werkt: `curl http://127.0.0.1:8765/api/health`
|
||
|
|
|
||
|
|
### 5. nginx + SSL configureren
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# Kopieer de nginx config
|
||
|
|
sudo cp nginx/ha.el-kadi.nl.conf /etc/nginx/sites-available/
|
||
|
|
sudo ln -s /etc/nginx/sites-available/ha.el-kadi.nl.conf /etc/nginx/sites-enabled/
|
||
|
|
|
||
|
|
# SSL certificaten met Let's Encrypt (certbot)
|
||
|
|
sudo certbot --nginx -d ha.el-kadi.nl -d www.ha.el-kadi.nl
|
||
|
|
|
||
|
|
# Pas de ssl_certificate paden aan in de config indien nodig
|
||
|
|
# Herlaad nginx
|
||
|
|
sudo nginx -t && sudo systemctl reload nginx
|
||
|
|
```
|
||
|
|
|
||
|
|
### 6. Systemd service (zodat de server automatisch start)
|
||
|
|
|
||
|
|
Maak `/etc/systemd/system/ha-voice-control.service`:
|
||
|
|
|
||
|
|
```ini
|
||
|
|
[Unit]
|
||
|
|
Description=HA Voice Control Web Server
|
||
|
|
After=network.target
|
||
|
|
|
||
|
|
[Service]
|
||
|
|
Type=simple
|
||
|
|
User=www-data
|
||
|
|
WorkingDirectory=/opt/ha-voice-control
|
||
|
|
EnvironmentFile=/opt/ha-voice-control/.env
|
||
|
|
ExecStart=/opt/ha-voice-control/venv/bin/python -m src.web_server
|
||
|
|
Restart=always
|
||
|
|
RestartSec=5
|
||
|
|
|
||
|
|
[Install]
|
||
|
|
WantedBy=multi-user.target
|
||
|
|
```
|
||
|
|
|
||
|
|
```bash
|
||
|
|
sudo systemctl daemon-reload
|
||
|
|
sudo systemctl enable --now ha-voice-control
|
||
|
|
```
|
||
|
|
|
||
|
|
## MCP Server gebruiken
|
||
|
|
|
||
|
|
### Claude Desktop
|
||
|
|
|
||
|
|
Voeg toe aan je `claude_desktop_config.json`:
|
||
|
|
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"mcpServers": {
|
||
|
|
"ha-voice": {
|
||
|
|
"command": "python",
|
||
|
|
"args": ["-m", "src.mcp_server"],
|
||
|
|
"cwd": "/opt/ha-voice-control",
|
||
|
|
"env": {
|
||
|
|
"HA_TOKEN": "jouw-token-hier",
|
||
|
|
"WHISPER_MODE": "local"
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
### DeepSeek TUI
|
||
|
|
|
||
|
|
In je `config.toml`:
|
||
|
|
|
||
|
|
```toml
|
||
|
|
[[mcp_servers]]
|
||
|
|
name = "ha-voice"
|
||
|
|
command = "python"
|
||
|
|
args = ["-m", "src.mcp_server"]
|
||
|
|
cwd = "/opt/ha-voice-control"
|
||
|
|
env = { HA_TOKEN = "jouw-token-hier", WHISPER_MODE = "local" }
|
||
|
|
```
|
||
|
|
|
||
|
|
### Beschikbare MCP tools
|
||
|
|
|
||
|
|
| Tool | Beschrijving |
|
||
|
|
|------|-------------|
|
||
|
|
| `speak_command` | Base64 audio → transcribeer → voer uit via HA |
|
||
|
|
| `transcribe_audio` | Alleen transcriberen, geen actie |
|
||
|
|
| `send_text_command` | Stuur tekst naar HA conversation agent |
|
||
|
|
| `list_lights` | Toon alle lampen en hun status |
|
||
|
|
| `control_light` | Zet een lamp aan/uit/toggle met helderheid |
|
||
|
|
| `list_all_entities` | Toon alle HA entities |
|
||
|
|
| `get_entity_state` | State van één entity opvragen |
|
||
|
|
| `call_ha_service` | Roep een willekeurige HA service aan |
|
||
|
|
|
||
|
|
## API endpoints (web server)
|
||
|
|
|
||
|
|
| Methode | Pad | Beschrijving |
|
||
|
|
|---------|-----|-------------|
|
||
|
|
| `GET` | `/api/health` | Health check |
|
||
|
|
| `POST` | `/api/transcribe` | Upload audio (multipart), krijg transcriptie + HA resultaat |
|
||
|
|
| `POST` | `/api/command` | `{"text": "doe de lampen uit"}` → HA |
|
||
|
|
| `GET` | `/api/lights` | Alle lampen met status |
|
||
|
|
| `POST` | `/api/light/control` | `{"entity_id": "...", "action": "turn_on"}` |
|
||
|
|
| `GET` | `/api/entities?domain=light` | Entities (optioneel gefilterd) |
|
||
|
|
| `GET` | `/api/entity/{entity_id}` | Volledige state van één entity |
|
||
|
|
| `POST` | `/api/service` | `{"domain": "light", "service": "turn_on", "entity_id": "..."}` |
|
||
|
|
|
||
|
|
## Gebruik
|
||
|
|
|
||
|
|
1. Open `https://www.ha.el-kadi.nl` in je browser (Chrome/Edge/Safari op desktop of mobiel)
|
||
|
|
2. Geef de browser toestemming voor de microfoon
|
||
|
|
3. Houd de microfoonknop ingedrukt en spreek je commando:
|
||
|
|
- "Doe de lampen in de woonkamer aan"
|
||
|
|
- "Zet alle lichten uit"
|
||
|
|
- "Dim de slaapkamer naar 50 procent"
|
||
|
|
4. Laat de knop los — je commando wordt getranscribeerd en uitgevoerd
|
||
|
|
5. Je ziet het resultaat verschijnen
|
||
|
|
|
||
|
|
De lampen onderaan de pagina kun je ook direct met de toggle-schakelaars bedienen.
|
||
|
|
|
||
|
|
## Troubleshooting
|
||
|
|
|
||
|
|
**"Microfoon niet beschikbaar"**
|
||
|
|
- De site moet via HTTPS geladen worden (browsers vereisen dit voor `getUserMedia`)
|
||
|
|
- Controleer of nginx SSL correct is ingesteld
|
||
|
|
- Lokaal testen op `localhost` werkt ook zonder HTTPS
|
||
|
|
|
||
|
|
**Transcriptie werkt niet / foutmelding**
|
||
|
|
- Check of `faster-whisper` correct is geïnstalleerd: `pip list | grep faster`
|
||
|
|
- Controleer de logs: `journalctl -u ha-voice-control -f`
|
||
|
|
- Bij Open AI-modus: check of `OPENAI_API_KEY` is ingesteld
|
||
|
|
- Het model wordt de eerste keer gedownload; dit kan even duren
|
||
|
|
|
||
|
|
**"Fout bij uitvoeren" / Home Assistant niet bereikbaar**
|
||
|
|
- Controleer of `HA_URL` klopt en bereikbaar is vanaf de server
|
||
|
|
- Verifieer de token: `curl -H "Authorization: Bearer $HA_TOKEN" $HA_URL/api/`
|
||
|
|
- Check of de conversation agent in HA is ingeschakeld (Standaard is `conversation` integratie actief)
|
||
|
|
|
||
|
|
**Audio wordt niet goed herkend**
|
||
|
|
- Gebruik een groter Whisper-model (`small` of `medium`) voor betere NL herkenning
|
||
|
|
- Spreek duidelijk en dicht bij de microfoon
|
||
|
|
- Verminder achtergrondgeluid
|