Home Assistant on iris: update, Zigbee, voice stack, LLM conversation agent
Last updated 05/11/2026 · migrated-from-outline, llm, metis, homeassistant
id: home-assistant-metis title: Home Assistant (on iris since 2026-10-21; voice stack and LLM on metis): update, Wyoming… importance: medium tags: migrated-from-outline, llm, metis, homeassistant updated: 2026-10-31 content: HA moved to iris 2026-10-21 (voice/llama entries still broken); update procedure, Whisper/Piper stack, conversation agent, LLM tests. outline: /doc/home-assistant-on-iris-since-2026-10-21-voice-stack-and-llm-on-metis-update-wyoming-CoIcbqrl7b
.
CURRENT STATE: HA runs on iris since 2026-10-21
- HA moved from metis to iris (compose
/data/docker/HomeAssistant/compose.ymlon iris, config./config, image 2026.10.2,docker exec homeassistant ...on iris). LANhttp://192.168.68.63:8123, tailnethttp://100.64.0.3:8123. Skill:home-assistant. - The ConBee II is plugged into iris; compose maps its
/dev/serial/by-id/usb-dresden_elektronik_ingenieurtechnik_GmbH_ConBee_II_DE2153523-if00to/dev/ttyACM0so the ZHA config is unchanged. After the move ZHA recovered (unavailable 197 to 40 = battery devices). - Public access:
home.handtrixxx.comforwarderforward-homeassistant(in/data/docker/homelab.vpn/compose.ymlon handtrixxx.com) points atTCP:100.64.0.3:8123.internal_urlin.storage/core.configishttp://192.168.68.63:8123. - Rollback copy on metis: gone. As of 2026-10-25 there is no
homeassistantcontainer and no/data/docker/HomeAssistant/directory on metis (removed 2026-10-23); only the orphanghcr.io/home-assistant/home-assistant:stableimage (1.6 GB) is still cached, referenced by nothing. Never start HA on metis - the live instance is iris. - Voice moved to iris 2026-10-23: whisper/piper/openwakeword now run on iris in
/data/docker/voice/(127.0.0.1, HA host network), so the three Wyoming entries work again. The metis copies of those three images weredocker rmi’d on 2026-10-25, so voice tasks must run on iris; there is no local fallback left on metis. Still broken (backlog): the llama conversation entry points at127.0.0.1; repoint tohttp://192.168.68.50:8000/v1. - Hallway lights (2026-10-21): two new innr RCL 231 T (
light.flur_eingang,light.flur_kleiderschrank, ZHA) replaced the two IKEA E14 bulbs, which now sit in the area Arbeitszimmer and were renamed the same day tolight.arbeitszimmer_telefon/light.arbeitszimmer_schrank(device namesArbeitszimmer Telefon/Arbeitszimmer Schrank; their HomeKit accessory entriesArbeitszimmer Leuchte Telefon|Schrankfollow).Flur Bewegungnow switches onlylight.flur_kleiderschrankat 15 % / 2000 K. GroupsLichter Flur/Lichter Arbeitszimmer, ZHA group 0x000C, the remote and motion automations (Lichter an/aus/Heller/Dunkler,Flur Bewegung) and the mobile dashboard were updated; backups on iris:config-lights-pre-20261021.tar.gz,config-rename-pre-20261021.tar.gz,automations.yaml.bak-lights-20261021,automations.yaml.bak-motion-20261021. Procedure in skillhome-assistant(Zigbee section). - Bluetooth/iBeacon is intentionally dropped (adapter was on metis; the 95 iBeacon entities were passing cars).
- Everything below is history up to 2026-10-15 and describes metis; paths and
127.0.0.1URLs there are outdated for HA itself and for the voice stack (voice is on iris now); only the llama server at192.168.68.50:8000is still on metis.
Status as of 2026-10-09 (history). Compose projects lived on Metis under /data/docker/.
HA container
/data/docker/HomeAssistant/compose.yml: imageghcr.io/home-assistant/home-assistant:stable, host networking, privileged, config./config.- Updated 2026.9.2 to 2026.10.0 on 2026-10-09. Procedure used:
docker tag <old image id> ha-rollback:2026.9.2thendocker compose pull,docker compose stop, tar the config,docker compose up -d. (HA rewrites state on shutdown, so always stop it before copying/editing config.) - Rollback: point the compose image to
ha-rollback:2026.9.2and restoreconfig-backup-20261009-pre2026.10.tar.gz(in/data/docker/HomeAssistant/, ~150 MB, owned by root). - 2026.10 breaking changes reviewed: none affect our integrations (legacy auth-provider mode removed,
mqtt.publish/mqtt.dumpneed admin, several dead integrations removed). Custom components: frigate 5.15.6, hacs 2.0.5, mbapi2020 v0.40.0, nodered, philips_airpurifier_coap, speedport, tplink_deco, llama_conversation (home-llm) v0.4.12. - 2026.10 has a new Settings > System > AI page with a one-click MCP server card (HA as MCP server; URLs listed there). Plan: use it for Hermes (see backlog).
- HA language
de, country DE, timezone Europe/Berlin.
Voice stack: /data/docker/voice/ (compose project on Metis)
| Container | Image | Port | Notes |
|---|---|---|---|
whisper |
rhasspy/wyoming-whisper |
127.0.0.1:10300 |
model large-v3-turbo, de, **WYO_WHISPER_COMPUTE_TYPE=int8**, 8 threads, beam 1 |
piper |
rhasspy/wyoming-piper |
127.0.0.1:10200 |
voice de_DE-thorsten-medium |
openwakeword |
rhasspy/wyoming-openwakeword |
127.0.0.1:10400 |
wake word |
(ha-llm-proxy was removed 2026-10-15, see “Current LLM setup” below.)
- Ports are bound to localhost only; HA is on host networking so it connects to
127.0.0.1. Nothing is exposed on the LAN. - Gotcha: default compute type on CPU is float32 (3.5 GiB RAM);
int8brings it to ~0.9 GiB and is fast enough. CPU has 32 cores, no GPU needed. - Measured (Piper TTS to Whisper STT, synthetic German commands): transcript correct, STT 1.3 s for 2 s of audio, TTS ~0.07 s warm.
- A Wyoming service from another container can’t reach
127.0.0.1:portof the host; test inside the compose network by service name (piper:10200).
Current LLM setup (since 2026-10-15)
- HA talks directly to the production llama on metis — since 2026-10-18 that is Qwen3.8-Flash-Next (
llama-flashnext,http://192.168.68.50:8000/v1; formerly Ornith-1.5-35B-A3B). Generic OpenAI backend, port 8000, pathv1; llama-server ignores the model name. Thinking stays on (server default). No proxy. Because HA runs on iris, the entry cannot use127.0.0.1— it must point at metis’s LAN IP (backlog item, still open 2026-11-01). - Why the proxy was dropped: measured on prod with 3 HA-style prompts and 2 tools, thinking on = 0.9 to 3.7 s vs no-think 0.5 to 0.9 s, identical tool calls. Ornith is fast enough that the extra 0.4 to 3 s does not matter. Verified live: connections go only to
:8000, light on/off via Assist works. - Gotcha (HA UI): host/port are stored in the config entry’s
options(Reconfigure on the parent entry), the model name in the conversation sub-entry. The entry title (...:8002/v1) is only a label created at setup and does not update. - Open latency item: every turn sends a ~7.8k-token prompt (entity list + in-context examples) that is processed from scratch (~5.9 s cold, ~6.4 s total), because
refresh_prompt_per_turnrebuilds it and the prefix cache misses. Ideas: expose fewer entities, fewer in-context examples, check whether the time sits at the top of the prompt. - Rebuild recipe if a no-think proxy is ever needed again: ~60-line Python stdlib
ThreadingHTTPServer(python:3.12-alpine, host network,127.0.0.1:8002) forwarding to127.0.0.1:8000; for POST*/chat/completionsit doeschat_template_kwargs.setdefault("enable_thinking", False)andtemperature.setdefault(0.4), streams the upstream body back unchanged (HTTP/1.0 close-delimited), passesAuthorization. home-llm cannot sendchat_template_kwargsitself, which is why the proxy was needed. Backup of the old compose:/data/docker/voice/compose.yml.bak-20261015-noproxy.
Choosing the conversation model (tested 2026-10-09, German, tool calling; HISTORICAL, superseded by “Current LLM setup”)
| Model | Latency | Result |
|---|---|---|
Qwen3.5-2B (llama-small, :8001) |
0.3 to 0.9 s | Unsafe: “light off” became HassLightSet brightness=100, invented entity names |
| Qwen3.8-27B no-think (via ha-llm-proxy :8002) | 2 to 3 s non-stream; ~1.2 s to first token streaming | Correct tools/areas (HassTurnOff area=Wohnzimmer domain=[light]) |
Decision then (obsolete, 2026-10-09): 27B no-think via the proxy for the HA conversation agent. Superseded: prod is llama-flashnext, proxy removed. HA’s built-in intent matching still handles simple commands instantly (prefer local handling first); the LLM is the fallback.
- Why there was a proxy (
ha-llm-proxyon 8002, now removed):home-llm(acon96) cannot sendchat_template_kwargs, and the old Qwen3.8-27B thought by default (effort xhigh). Obsolete - prod is llama-flashnext and the proxy is gone.
home-llm (acon96/home-llm v0.4.12)
- Installed by copying
custom_components/llama_conversationfrom the git tag into/data/docker/HomeAssistant/config/custom_components/(HACS is installed too, but update it via HACS later if wanted). HA restarted, loads fine. Needs HA >= 2026.5. - Backends: Generic OpenAI API (Chat Completions), llama.cpp server, Ollama, etc. Correct values today: Generic OpenAI, host
192.168.68.50(metis LAN - HA runs on iris, so127.0.0.1never works), port8000, API pathv1, modelqwen3.8-flashnext(the oldornith-1.5-35b-a3band the removedha-llm-proxyon8002are obsolete). “Use server defaults for sampling” can stay on.
Remaining manual UI steps (need a logged-in HA session)
- Settings > Devices & services > Add integration > Wyoming Protocol: host
127.0.0.1port10300(Whisper), again with port10200(Piper). - Add integration > Local LLMs, pick Generic OpenAI API with the values above, then add a conversation agent (API: Assist).
- Settings > Voice assistants: create/edit a pipeline: language German, conversation agent = the new one, STT = faster-whisper, TTS = piper (
de_DE-thorsten-medium). Enable “Prefer handling commands locally”. - Expose only the entities you want Assist to control (Settings > Voice assistants > Expose).
Update 2026-10-09 (late): Hermes–HA, 2B model, female voice, wake word
Hermes ↔ Home Assistant is already working
data/.envhasHASS_URL+HASS_TOKEN;platforms.homeassistant.enabled: true.- Verified from the Hermes container: REST returns 635 entities; a read-only
hermes chat -Q --oneshot -t homeassistantquery answered “26 lights, 4 on”. - Log warnings are harmless: “Reconnection failed 502” = HA restarts; “No watch_domains/entities configured” = event-watch filter unset.
- Optional: use the tailnet URL
http://100.64.0.1:8123instead of the public Traefik URL.
Qwen3.5-2B (llama-small, :8001)
- Only used for Hermes title generation (~7 requests/24 h). Unusable for HA control (wrong tool arguments). Marginal value; can be replaced by the 27B no-think at the cost of queueing behind
-np 1.
Female German voice
- Piper’s female German voices are all low quality:
ramona-low,kerstin-low,eva_k-x_low. - Alternative: Wyoming-Piper OmniVoice backend (image
rhasspy/wyoming-piper:omnivoice, ~1.5 GiB RAM, CPU). Voices live inomnivoice_voices/de_DE/<name>/instruct.txt(voice design) orref.wav+ref.txt(cloning). instruct.txtaccepts only: gender, age (child/teenager/young adult/middle-aged/elderly), pitch (very low..very high), whisper, accents. Words like “warm”/“calm” produce an error. Restart the container after editing voices.- Timing: first audio ~1.6 s, 8 s sentence in ~6 s (Piper: ~0.07 s). Run with
--omnivoice-steps 16. - Trial container
piper-omni-trial(127.0.0.1:10201, data in/data/docker/voice/omnivoice-data).
Wake word / satellite
- Hands-free needs a mic/speaker satellite plus wake word. Without it Assist works only typed or push-to-talk (Companion app / browser).
- openWakeWord (Wyoming, port 10400) supports English wake words only (okay nabu, hey jarvis, alexa, hey mycroft). Porcupine has German wake words. On-device microWakeWord (ESP32-S3-BOX-3, Voice PE, Android Companion App) uses the same English set.
- Decide the satellite hardware first; the wake word container is cheap but useless without one.
Decisions and changes 2026-10-09 (final state of this session)
- TTS stays Piper
**de_DE-thorsten-medium**(male is fine). OmniVoice trial container,omnivoice-data(3.7 GB) and samples removed. OmniVoice remains an option if a female voice is wanted later: imagerhasspy/wyoming-piper:omnivoice,--backend omnivoice --omnivoice-ref-dir ... --omnivoice-steps 16. - openWakeWord added to
/data/docker/voice/compose.yml:rhasspy/wyoming-openwakeword, 127.0.0.1:10400, 512 MB limit (uses ~35 MiB), English wake words only. Not yet added in HA (no satellite yet). - Qwen3.5-2B /
**llama-small**removed (freed ~1.8 GiB VRAM + 1.3 GB disk). Hermesauxiliary.title_generationnow points at the 27B (base_url http://100.64.0.1:8000/v1, model aliasqwen3.8-27b-nothink,extra_body.chat_template_kwargs.enable_thinking=false); tested: title in ~6 s. Backupconfig.yaml.bak3-20261009. Note: callinggenerate_title()outside the gateway without an explicit base_url fails (“main provider unavailable”), so keep the explicit base_url. - Hermes -> HA now uses
**HASS_URL=http://100.64.0.1:8123**(tailnet, no Traefik). Latency is the same as the public URL (~0.1 s); the benefit is independence from Traefik/TLS/public DNS. Backup.env.bak-20261009. Verified withhermes chat -Q --oneshot -t homeassistant -q "..."(use-q, the query is not positional).
Source: Wiki.js