diff --git a/vigilancia/pi_bot.py b/vigilancia/pi_bot.py index 4f44558..93bab01 100644 --- a/vigilancia/pi_bot.py +++ b/vigilancia/pi_bot.py @@ -94,6 +94,15 @@ def mandar_tv(mensaje, simple): return False +def mandar_youtube(url): + try: + r = requests.get(f"http://127.0.0.1:8600/tv/youtube?url={url}", timeout=10) + return r.status_code == 200 + except Exception as e: + log(f"youtube error: {e}") + return False + + def procesar(texto, chat_id): t = texto.lower().strip() log(f"RECIBIDO chat={chat_id} texto={texto!r}") @@ -119,7 +128,7 @@ def procesar(texto, chat_id): ok = mandar_tv(msj, simple=False) enviar("🚨 Alarma lanzada en la tele ✅" if ok else "❌ No se pudo lanzar la alarma", chat_id) - elif t in ("panorama", "/panorama"): + elif t.startswith("panorama") or t.startswith("/panorama"): enviar("📷 Capturando snapshots de las cámaras...", chat_id) try: import subprocess as sp @@ -128,12 +137,20 @@ def procesar(texto, chat_id): log(f"panorama: {r.stdout.strip()[-200:]}") except Exception as e: log(f"panorama error: {e}") + elif t.startswith("youtube ") or t.startswith("/youtube "): + url = texto.split(" ", 1)[1].strip() + if not url: + enviar("Uso: youtube <URL>", chat_id) + else: + ok = mandar_youtube(url) + enviar("🎬 YouTube lanzado en la TV ✅" if ok else "❌ No se pudo lanzar YouTube", chat_id) elif t in ("ayuda", "/ayuda", "help", "/help"): enviar("Comandos:\n" "estado — estado de la Pi\n" "temperatura — temperatura\n" "tv <mensaje> — mensaje rápido a la tele\n" "alarma <mensaje> — secuencia completa (sirena x3)\n" + "youtube <URL> — reproduce YouTube y apaga al terminar\n" "panorama — fotos de las cámaras", chat_id) diff --git a/vigilancia/tv_api.py b/vigilancia/tv_api.py index 8083674..1d8510d 100644 --- a/vigilancia/tv_api.py +++ b/vigilancia/tv_api.py @@ -9,12 +9,24 @@ import sys sys.path.insert(0, sys_dir) import config -from voz import anuncio_en_teles, anuncio_simple +from voz import anuncio_en_teles, anuncio_simple, youtube_en_teles class Handler(BaseHTTPRequestHandler): def do_GET(self): q = parse_qs(urlparse(self.path).query) + path = urlparse(self.path).path + + if path == "/tv/youtube": + url = (q.get("url") or [""])[0] + if not url: + self._resp(400, {"error": "falta parametro url"}) + return + threading.Thread(target=youtube_en_teles, args=(url,), daemon=True).start() + print(f"[TV-API] YouTube lanzado: {url[:80]}") + self._resp(200, {"ok": True, "url": url, "modo": "youtube"}) + return + texto = (q.get("texto") or q.get("msg") or [""])[0] if not texto: self._resp(400, {"error": "falta parametro texto"}) diff --git a/vigilancia/voz.py b/vigilancia/voz.py index b7e297f..5f77ab6 100644 --- a/vigilancia/voz.py +++ b/vigilancia/voz.py @@ -316,6 +316,53 @@ def reproducir_en_teles(texto): anuncio_en_teles(texto) +def youtube_en_teles(url): + """Reproduce un video de YouTube en la tele y la apaga al terminar.""" + import re + match = re.search(r"(?:v=|youtu\.be/)([A-Za-z0-9_-]{11})", url) + if not match: + print("[Voz] URL de YouTube no válida") + return + video_id = match.group(1) + try: + import pychromecast + from pychromecast.controllers.youtube import YouTubeController + + chromecasts, browser = pychromecast.get_chromecasts(timeout=8) + try: + if config.GOOGLE_TV_NOMBRES: + objetivos = [c for c in chromecasts + if c.cast_info.friendly_name in config.GOOGLE_TV_NOMBRES] + else: + objetivos = chromecasts + for c in objetivos: + try: + c.wait(timeout=10) + c.set_volume(config.GOOGLE_TV_VOLUMEN / 100.0) + yt = YouTubeController() + c.register_handler(yt) + print(f"[Voz] Lanzando YouTube en {c.cast_info.friendly_name}: {video_id}") + yt.play_video(video_id) + # Esperar a que termine el video + time.sleep(5) + while True: + try: + state = c.media_controller.status.player_state + if state == "IDLE": + break + except Exception: + pass + time.sleep(3) + apagar_tv_remote() + print(f"[Voz] Video terminado, TV apagada") + except Exception as e: + print(f"[Voz] Error en {c.cast_info.friendly_name}: {e}") + finally: + pychromecast.discovery.stop_discovery(browser) + except Exception as e: + print(f"[Voz] Error YouTube: {e}") + + def apagar_tv_remote(): """Apaga la TV via AndroidTVRemote (protocolo oficial Google).""" try: