České hlasové ovládání v Home Assistantu: modely a vlastní věty

návod · chytrá domácnost

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.

01

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.

model kde
faster-whisper small-int8 lokál (NUC) ~5 s horší
Nabu Casa (subscription) cloud ~2 s lepší

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.

02

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_script se 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.

03

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.

04

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čí.

05

Na co si dát pozor

  • Hassil in: není YAML seznam. Zápis in: ['ztiš', 'mute'] spadne na TypeError: expected string or bytes-like object, got 'list'. Každou variantu psát jako vlastní hodnotu, nebo jako alternaci a|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 & 4 nefunguje; kontrolu bitu psát aritmeticky, ((feats // 4) % 2) == 1. Globální abs(x) nahradit filtrem x | 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 failed je problém komunikace integrace s TV, ne rozpoznání intentu. Před mute/unmute proto zavolat homeassistant.update_entity a neposílat akci, když je přehrávač unavailable nebo unknown.

_Energie vznikla v říjnu 2025, televize na ni navázala o týden později; poslední aktualizace textu je 30. října 2025._

← zpět na Objevuj