Home Assistant umí hlasové ovládání přes Assist. V češtině jde o dvě věci: který model rozpozná řeč a syntézuje odpověď, a jak se přirozené věty přeloží na akce. Níže je obojí – volba modelu z vlastního testování a dvě sady vlastních vět pro spotřebu energie a televizi. Každá část nese datum, kdy vznikla.
Lokální vs. cloudové modely
Rozpoznávání řeči (STT) běželo lokálně přes Whisper na Intel NUC, výchozí model faster-whisper small-int8, čeština. Syntéza (TTS) přes Piper, lokálně hlas cs_CZ-jirka-medium.
faster-whisper small-int8 lokál (NUC) ~5 s horšíLokální model zvládal jednoduché věci, ale jeho porozumění češtině bylo znatelně horší a odezva pomalejší. Nakonec zůstalo cloudové rozpoznávání přes Nabu Casa; lokální Piper se dá použít na syntézu i tak.
Architektura vlastních vět
Ovládání se dělí na dvě vrstvy:
- Věty / Hassil intenty v
custom_sentences/cs/– jen rozpoznávání vět a slotů. Každé téma svůj soubor (energy.yaml,tv.yaml). - Obsluha intentů v
packages/voice_control.yaml–intent_scriptse skutečnými akcemi HA.
configuration.yaml načítá packages:
homeassistant: packages: !include_dir_named packages
Název intentu musí být v obou vrstvách identický. Unknown intent AssistSetTvVolume znamená, že věta byla rozpoznaná, ale nenašel se k ní handler v intent_script.
Energie: příkon a spotřeba za období (23. října 2025)
Soubor custom_sentences/cs/energy.yaml rozpoznává dotazy na aktuální příkon (volitelně filtrované) a na spotřebu za období:
intents:
EnergyGetPowerByFilter:
slots:
device_filter:
optional: true
data:
- sentences:
- 'Jaký je aktuální příkon'
- 'Jaká je teď spotřeba'
- sentences:
- 'Jaký je aktuální příkon {device_filter}'
- 'Jaká je teď spotřeba {device_filter}'
EnergyGetEnergyPeriod:
slots:
period:
required: true
data:
- sentences:
- 'Kolik elektřiny {period}'
- 'Jaká je {period} spotřeba'
lists:
device_filter:
values:
- { in: 'shelly', out: 'shelly' }
- { in: 'zásuvka|zásuvky|zásuvek', out: 'socket' }
- { in: 'bojler', out: 'ariston' }
period:
values:
- { in: 'dnes|dnešní', out: 'day' }
- { in: 'tento týden|týdenní', out: 'week' }
- { in: 'tento měsíc|měsíční', out: 'month' }Obsluha EnergyGetPowerByFilter: bez vysloveného filtru se použije přímo hlavní senzor Shelly 3EM (device_class: power, state_class: measurement, jednotka W) a odpoví například „Aktuální příkon celkem je 850 wattů.“ S filtrem se dynamicky najdou senzory power/active_power odpovídající {device_filter} a sečtou se.
EnergyGetEnergyPeriod mapuje {period} na sensor.energy_daily, sensor.energy_weekly a sensor.energy_monthly a vrací spotřebu v kWh.
Televize: hlasitost a ztlumení (30. října 2025)
Soubor custom_sentences/cs/tv.yaml řeší dva intenty – nastavení hlasitosti a přepnutí ztlumení:
intents:
AssistSetTvVolume:
data:
- sentences:
- 'nastav hlasitost (televize|televizi|tv) (v|ve) {area} na {volume}'
- 'dej (televizi|tv) (v|ve) {area} hlasitost {volume}'
AssistToggleTvMute:
data:
- sentences:
- '{toggle} [zvuk] (televize|televizi|tv) (v|ve) {area}'
lists:
volume:
range:
from: 0
to: 100
toggle:
values:
- in: '(ztiš|ztlum|ztlumit|vypni zvuk|mute|umlč)'
out: 'mute'
- in: '(zapni zvuk|zruš ztlumení|unmute|zesil|zesílit)'
out: 'unmute'Slot {area} je oblast HA, {volume} číslo 0-100. Význam byl stanoven natvrdo: ztiš = mute, zesil = unmute – tedy přepnutí ztlumení, ne postupná změna úrovně. Příklad povelu: „Nastav hlasitost televize v obýváku na 2.“
Obsluha AssistSetTvVolume: převede procenta na 0.0-1.0, přes area_id() a area_entities() najde media_player.* v oblasti, přednost dá entitě obsahující tv a podle supported_features použije media_player.volume_set, případně fallback volume_up/volume_down.
Ztlumení řeší integrace Philips TV (philips_js), která umí skutečný mute:
action: media_player.volume_mute data: is_volume_muted: true
To je lepší než volume_set nebo volume_up/down – TV si při mute zachová původní hlasitost a při unmute ji obnoví. Fallbacky přes hlasitost tohle nezaručí.
Na co si dát pozor
- Hassil
in:není YAML seznam. Zápisin: ['ztiš', 'mute']spadne naTypeError: expected string or bytes-like object, got 'list'. Každou variantu psát jako vlastní hodnotu, nebo jako alternacia|b|c. - Odsazení intentů.
data:musí být zanořené pod intentem; špatné odsazení způsobí při načítáníAttributeError: 'NoneType' object has no attribute 'get'. - HA Jinja neumí pythonové operátory. Bitové
feats & 4nefunguje; kontrolu bitu psát aritmeticky,((feats // 4) % 2) == 1. Globálníabs(x)nahradit filtremx | abs. - Rozlišit vrstvy chyby. „Při zpracování došlo k neočekávané chybě“ znamená, že intent byl rozpoznaný, ale spadla až jeho HA akce – ne chyba věty.
- Ověřit dostupnost entity. Philips
ConnectionFailure: All connection attempts failedje problém komunikace integrace s TV, ne rozpoznání intentu. Před mute/unmute proto zavolathomeassistant.update_entitya neposílat akci, když je přehrávačunavailablenebounknown.
_Energie vznikla v říjnu 2025, televize na ni navázala o týden později; poslední aktualizace textu je 30. října 2025._