Ranní briefing
Dvě fáze, 15 min apart. Limit 150/170 chars. TV mute před, unmute po. Speaker = kuchyně (kde se chystá káva). Gemini generuje, sayTTS truncuje na 200 max.
🏠 Prožívání · Audio a TTS
Tři reproduktory, čtyři režimy, jeden orchestrátor. TTS jde přes Google Cast s tvrdým limitem 200 znaků na utterance — proto se ranní briefing rozdělí do dvou fází. Sleep guard ticho v noci. Prev_playing guard, aby se po TTS nepustila radiostanice z minulé rutiny do prázdné koupelny.
Co to dělá
Tři reproduktory v bytě — kuchyně, koupelna, ložnice. Všechny Google Cast, všechny řízené přes sh_audio_brain_v2 (dispatcher) a sh_tts_orchestrator_v1 (řečí). Centrální audio_request proměnná — kdokoli může požádat o radio nebo TTS, brain rozhodne, který speaker a v jakém pořadí.
Google Cast má hard limit 200 znaků na jedno utterance. Delší text se useká uprostřed věty, user slyší „...možná už ti t". Proto je v sayTTS defenzivní truncation a ranní briefing je rozdělený do dvou fází — první ve 3:15 (čas, počasí, svátek, do 150 znaků), druhý o 15 min později (BTC, PM2.5, vlhkost, vtipný komentář, do 170 znaků).
Audio má prioritu 100 v priority engine — když TTS běží, světla
(priorita 60) ani jiné automatizace ho nepřebijí. Po dokončení TTS se priority
uvolní a může se resumovat předchozí radio (jen když prev_playing='yes'
— guard po bathroom misroute bug).
Denní provoz
Většinu dne je ticho. Akce jsou rituální — ráno briefing, večer možná comfort suggest.
15 min před budíkem. Pozdrav, čas, datum, počasí dnes, svátek dne. Limit 150 znaků. Kuchyňský speaker (kde se ráno chystá káva). Po dokončení se spustí 15min countdown na fázi 2.
BTC kurz, PM2.5 venku a uvnitř, vlhkost, vtipný komentář od Gemini. Limit 170 znaků. Stejný speaker. Cíl: dokončit ranní informace dřív než odejdu do auta v 03:45.
sh_audio_request='idle'. Žádné automatické audio přes den.
Speakers fungují jako TTS recipients pro alerty, jinak ticho. AI coordinator
monitoruje situation, zatím nic nespouští.
AI coordinator může vyhodnotit „evening + idle scene" → comfort_suggest. TTS přečte návrh: „Chceš spustit relax scénu?". Dispatch radio jen pokud user explicitně přijme přes Cube nebo Voice (ne timeout fallback).
sh_spim='yes' → priority engine zablokne TTS. Critical alerty
(zaplavení, požár) jdou přes vlastní safety bypass. Komfortní hlášky čekají
na probuzení.
Scény
Většina je triggrovaná systémem, ne user inputem.
Dvě fáze, 15 min apart. Limit 150/170 chars. TV mute před, unmute po. Speaker = kuchyně (kde se chystá káva). Gemini generuje, sayTTS truncuje na 200 max.
AI coordinator vyhodnotí level 4 situation večer → suggest. Bez user accept (cube/voice) NE auto-execute — to byl bathroom misroute bug.
Motion v koupelně + TOD ráno → spustí radio (Italia Classic Hits, Sanremo
feed). Stop při motion_off + 30s timeout. Resume guard kontroluje
prev_playing='yes'.
Sleep state → priority deny pro TTS. Critical alerts (gas, water leak) mají safety bypass. Briefing 03:15 jede normálně (sleep state už unset).
Když před TTS hrálo radio (prev_playing='yes', prev_mode='radio_*'), po dokončení TTS se obnoví. Bez prev_playing guardu by se resumovalo i když nic nehrálo.
Hardware
Tři Google Cast koncové body + Homey jako orchestrátor.
Google Cast · Wi-Fi · TTS + radio
Hlavní speaker pro ranní briefing. Kuchyně je centrem rituálu — káva, chystání, rozhodnutí dne. TTS recipient pro většinu hlášek. Radio backup pro bathroom když koupelnový padne.
Google Cast · Wi-Fi · ranní radio
Italian Classic Hits ráno při sprchování. Motion-trigger, motion_off + 30s stop. Po bathroom misroute bug 25.4. doplněn prev_playing guard, aby se radio nezapnulo z prázdna.
Google Cast · Wi-Fi · evening
Lehčí použití — večerní hudba před spaním, alerty když user v ložnici.
Sleep guard chrání před nočními TTS. Speaker variable
sh_tts_speaker='ložnice' historicky, real cast jde do kuchyně.
Google Cast · Wi-Fi · vizuál + audio
Sekundární výstup pro vizuální alerty — Nest Hub Max v ložnici. TV mute pipeline před TTS / unmute po (přes Android TV remote capabilities).
Local LLM · Whisper · HA voice
Hlasové ovládání lokálně — Whisper STT + lokální LLM nebo HA Voice. Aktuálně user_intent přes Cubo + buttons. Voice je další iterace, závisí na LLM host (RPi5 nebo NAS).
Pro tech-savvy
Orchestrator, dispatcher, priority engine, prev_playing guard.
Google Cast SDK má hard limit 200 znaků na utterance. Překročí → cast stream
padá nebo truncates uprostřed věty. NENÍ to bug, je to safety net
v sh_gemini_brain_v1::sayTTS():
if (cleaned.length > 200) {
cleaned = cleaned.substring(0, 200);
logMsg('GOOGLE CAST: message truncated to 200 chars');
}
Briefing split do dvou fází:
Orchestrace přes flow „SH – Morning – Briefing 2" s 15 min delay. Pending var: sh_morning_briefing2_pending_ts.
tts_completed event. Drží sh_priority_active='tts'
po dobu řeči.
sh_audio_request, rozhoduje speaker dle aktivní zóny
a TOD. Emituje audio_dispatch event.
prev_playing='yes'
(po bathroom misroute fix v1.8).
Centrální arbitr. Každý request má prioritu, vyhraje vyšší. Když TTS aktivní (priority 100), light request (60) odložen. Tabulka:
Stuck recovery: když active='tts' > 1 min bez forward progress,
brain guardian resetuje na none/idle.
Bug 25.4. noc: po comfort_suggest TTS, ~46 s později bathroom radio sám
spustil. Root cause: sh_tts_resume_exec_v1 fallback
if (target === 'idle' && currentMode === 'radio_bathroom')
resumoval bez ověření, že před TTS skutečně něco hrálo.
sh_audio_current_mode bylo zaseklé na radio_bathroom
z ranní rutiny. Resume podmínka byla splněná i když speaker už dávno mlčel.
Fix v1.8: přidán guard
if (sh_audio_prev_playing !== 'yes') return skip. Resume jen když
před TTS reálně hrálo radio.
Před každým TTS:
tts_completed: setCap volume_mute = false, restore volume
Bez tohoto by TTS hlas konkuroval s TV soundu — ranní zprávy + briefing nebylo slyšet.
Capability volume_mute je toggle, není potřeba čekat na driver ack.
Související