Files
home-voice-assistant/satellite/notifier.py
Cosmo 584e21923c feat(notifier): route TTS to tablet when TABLET_TTS_ENABLED
When TABLET_URL and VOICE_API_KEY are set, the tablet handles TTS
via its ElevenLabs proxy — local speak() is skipped. Controlled
by TABLET_TTS_ENABLED (default true when tablet is configured).

- notifier.speak_locally() — gate used by all local speech paths
- llm._maybe_speak — no-op when tablet plays the voice
- modes._handle_reset — emits response event and skips local speak
  when tablet TTS is on; keeps spoken fallback otherwise

Tablet side in smart-home-tablet repo: /api/voice/tts endpoint +
VoiceOverlay audio playback (commit ba2e… pending).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 12:52:34 +00:00

75 lines
2.5 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""
Tablet notifier — пересылает состояния ассистента в Smart Home Tablet
(https://tablet.digital-home.site/api/voice/event).
Планшет показывает оверлей (Siri-blob, распознанный текст, ответ).
Не критичный слой: любые сетевые ошибки глотаются, ассистент продолжает
работать даже если планшет оффлайн / не настроен.
Активируется только когда заполнены TABLET_URL и VOICE_API_KEY в .env.
"""
import os
import requests
from .config import log
TABLET_URL = os.getenv("TABLET_URL", "").rstrip("/")
VOICE_API_KEY = os.getenv("VOICE_API_KEY", "")
# Когда True — локальный speak() пропускается, голос идёт через планшет.
# По умолчанию включено если TABLET_URL и VOICE_API_KEY заполнены;
# явно отключить: TABLET_TTS_ENABLED=false
TABLET_TTS_ENABLED = (
bool(TABLET_URL and VOICE_API_KEY)
and os.getenv("TABLET_TTS_ENABLED", "true").lower() in ("true", "1", "yes", "on")
)
# Переиспользуем HTTP сессию (keep-alive) для минимума latency
_session = requests.Session()
_ENABLED = bool(TABLET_URL and VOICE_API_KEY)
if _ENABLED:
tts_where = "планшет" if TABLET_TTS_ENABLED else "локально"
print(f"🔔 Notifier: события → {TABLET_URL}, TTS: {tts_where}")
else:
print("🔕 Notifier: отключён (нет TABLET_URL или VOICE_API_KEY в .env)")
def speak_locally() -> bool:
"""True если локальный speak() должен работать (TTS на этой машине)."""
return not TABLET_TTS_ENABLED
def _send(event: str, **payload):
if not _ENABLED:
return
try:
_session.post(
f"{TABLET_URL}/api/voice/event",
json={"event": event, **payload},
headers={"Authorization": f"Bearer {VOICE_API_KEY}"},
timeout=1.5,
)
except requests.RequestException:
log.debug("Tablet notify failed (non-fatal)", exc_info=True)
def wake(agent_id: str):
_send("wake", agent=agent_id)
def command(text: str, agent_id: str):
_send("command", text=text, agent=agent_id)
def response(text: str, agent_id: str):
_send("response", text=text, agent=agent_id)
def idle():
_send("idle")
def error(text: str, agent_id: str = "cosmo"):
_send("error", text=text, agent=agent_id)