02-ago: [proyecto] vigilancia - secuencia TV: encender silencioso, espera 15s, sirena emergencia (WAV sintetizada), mensaje, apagado ADB
This commit is contained in:
@@ -48,10 +48,15 @@ GOOGLE_TV_ACTIVO=1
|
|||||||
GOOGLE_TV_NOMBRES=
|
GOOGLE_TV_NOMBRES=
|
||||||
GOOGLE_TV_VOLUMEN=30
|
GOOGLE_TV_VOLUMEN=30
|
||||||
GOOGLE_TV_APAGAR=1
|
GOOGLE_TV_APAGAR=1
|
||||||
|
GOOGLE_TV_PITIDO_ACTIVO=1
|
||||||
|
GOOGLE_TV_ESPERA_SG=15
|
||||||
|
GOOGLE_TV_PITIDO_SG=6
|
||||||
VOZ_EDGE=es-ES-AlvaroNeural
|
VOZ_EDGE=es-ES-AlvaroNeural
|
||||||
VOZ_PITCH=-15Hz
|
VOZ_PITCH=-15Hz
|
||||||
VOZ_RATE=-10%
|
VOZ_RATE=-10%
|
||||||
GOOGLE_TV_PUERTO=8500
|
GOOGLE_TV_PUERTO=8500
|
||||||
|
ADB_TV_IP=192.168.50.16:5555
|
||||||
|
GOOGLE_TV_APAGAR_VIA_ADB=1
|
||||||
VOZ_MENSAJE_ALERTA=Por favor, os avisamos de que no podéis cruzar este límite. Tenéis que ir a vuestro cuarto.
|
VOZ_MENSAJE_ALERTA=Por favor, os avisamos de que no podéis cruzar este límite. Tenéis que ir a vuestro cuarto.
|
||||||
VOZ_MENSAJE_CONOCIDO={nombres}, ¿qué estás haciendo? No entres ahí.
|
VOZ_MENSAJE_CONOCIDO={nombres}, ¿qué estás haciendo? No entres ahí.
|
||||||
|
|
||||||
|
|||||||
@@ -69,3 +69,6 @@ ADB_PATH = os.getenv(
|
|||||||
)
|
)
|
||||||
ADB_TV_IP = os.getenv("ADB_TV_IP", "192.168.50.16:5555")
|
ADB_TV_IP = os.getenv("ADB_TV_IP", "192.168.50.16:5555")
|
||||||
GOOGLE_TV_APAGAR_VIA_ADB = os.getenv("GOOGLE_TV_APAGAR_VIA_ADB", "1") == "1"
|
GOOGLE_TV_APAGAR_VIA_ADB = os.getenv("GOOGLE_TV_APAGAR_VIA_ADB", "1") == "1"
|
||||||
|
GOOGLE_TV_PITIDO_ACTIVO = os.getenv("GOOGLE_TV_PITIDO_ACTIVO", "1") == "1"
|
||||||
|
GOOGLE_TV_ESPERA_SG = int(os.getenv("GOOGLE_TV_ESPERA_SG", "15"))
|
||||||
|
GOOGLE_TV_PITIDO_SG = float(os.getenv("GOOGLE_TV_PITIDO_SG", "6"))
|
||||||
|
|||||||
@@ -106,13 +106,93 @@ def _esperar_fin(cast, timeout=90):
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def _generar_pitido():
|
||||||
|
"""Genera una sirena de emergencia (WAV) si no existe."""
|
||||||
|
ruta = os.path.join(MEDIA_DIR, "pitido_emergencia.wav")
|
||||||
|
if os.path.exists(ruta):
|
||||||
|
return ruta
|
||||||
|
try:
|
||||||
|
import numpy as np
|
||||||
|
import wave as _wave
|
||||||
|
|
||||||
|
os.makedirs(MEDIA_DIR, exist_ok=True)
|
||||||
|
sr = 44100
|
||||||
|
dur = config.GOOGLE_TV_PITIDO_SG
|
||||||
|
t = np.linspace(0, dur, int(sr * dur), endpoint=False)
|
||||||
|
freq = 500 + 400 * np.abs(np.sin(2 * np.pi * 0.5 * t))
|
||||||
|
fase = 2 * np.pi * np.cumsum(freq) / sr
|
||||||
|
y = 0.7 * np.sin(fase)
|
||||||
|
fade = min(0.2, dur / 4)
|
||||||
|
n_fade = int(fade * sr)
|
||||||
|
y[:n_fade] *= np.linspace(0, 1, n_fade)
|
||||||
|
y[-n_fade:] *= np.linspace(1, 0, n_fade)
|
||||||
|
data = (y * 32767).astype(np.int16)
|
||||||
|
with _wave.open(ruta, "w") as w:
|
||||||
|
w.setnchannels(1)
|
||||||
|
w.setsampwidth(2)
|
||||||
|
w.setframerate(sr)
|
||||||
|
w.writeframes(data.tobytes())
|
||||||
|
except Exception as e:
|
||||||
|
print(f"[Voz] No se pudo generar el pitido: {e}")
|
||||||
|
return ruta
|
||||||
|
|
||||||
|
|
||||||
|
def _generar_silencio():
|
||||||
|
"""Genera un WAV silencioso corto para encender la tele sin sonido."""
|
||||||
|
ruta = os.path.join(MEDIA_DIR, "silencio.wav")
|
||||||
|
if os.path.exists(ruta):
|
||||||
|
return ruta
|
||||||
|
try:
|
||||||
|
import wave as _wave
|
||||||
|
|
||||||
|
os.makedirs(MEDIA_DIR, exist_ok=True)
|
||||||
|
with _wave.open(ruta, "w") as w:
|
||||||
|
w.setnchannels(1)
|
||||||
|
w.setsampwidth(2)
|
||||||
|
w.setframerate(8000)
|
||||||
|
w.writeframes(b"\x00\x00" * (8000 * 2))
|
||||||
|
except Exception as e:
|
||||||
|
print(f"[Voz] No se pudo generar el silencio: {e}")
|
||||||
|
return ruta
|
||||||
|
|
||||||
|
|
||||||
|
def _url_pitido():
|
||||||
|
ruta = _generar_pitido()
|
||||||
|
if not os.path.exists(ruta):
|
||||||
|
return None
|
||||||
|
_arrancar_servidor()
|
||||||
|
if _server is None:
|
||||||
|
return None
|
||||||
|
return f"http://{_ip_lan()}:{config.GOOGLE_TV_PUERTO}/{os.path.basename(ruta)}"
|
||||||
|
|
||||||
|
|
||||||
|
def _url_silencio():
|
||||||
|
ruta = _generar_silencio()
|
||||||
|
if not os.path.exists(ruta):
|
||||||
|
return None
|
||||||
|
_arrancar_servidor()
|
||||||
|
if _server is None:
|
||||||
|
return None
|
||||||
|
return f"http://{_ip_lan()}:{config.GOOGLE_TV_PUERTO}/{os.path.basename(ruta)}"
|
||||||
|
|
||||||
|
|
||||||
|
def _reproducir_y_esperar(c, url, content_type, titulo, desc):
|
||||||
|
c.media_controller.play_media(url, content_type, title=titulo)
|
||||||
|
c.media_controller.block_until_active(timeout=10)
|
||||||
|
print(f"[Voz] {desc}")
|
||||||
|
return _esperar_fin(c)
|
||||||
|
|
||||||
|
|
||||||
def anuncio_en_teles(texto):
|
def anuncio_en_teles(texto):
|
||||||
"""Enciende la tele con el volumen configurado, reproduce el mensaje y la apaga."""
|
"""Enciende la tele (vol configurado), espera, sirena de emergencia,
|
||||||
|
mensaje y apaga por ADB."""
|
||||||
if not config.GOOGLE_TV_ACTIVO:
|
if not config.GOOGLE_TV_ACTIVO:
|
||||||
return
|
return
|
||||||
url = _url_audio(texto)
|
url_mensaje = _url_audio(texto)
|
||||||
if url is None:
|
if url_mensaje is None:
|
||||||
return
|
return
|
||||||
|
url_pitido = _url_pitido() if config.GOOGLE_TV_PITIDO_ACTIVO else None
|
||||||
|
url_silencio = _url_silencio() if url_pitido else None
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import pychromecast
|
import pychromecast
|
||||||
@@ -133,12 +213,25 @@ def anuncio_en_teles(texto):
|
|||||||
try:
|
try:
|
||||||
c.wait(timeout=10)
|
c.wait(timeout=10)
|
||||||
c.set_volume(config.GOOGLE_TV_VOLUMEN / 100.0)
|
c.set_volume(config.GOOGLE_TV_VOLUMEN / 100.0)
|
||||||
c.media_controller.play_media(url, "audio/mpeg", title=texto[:80])
|
|
||||||
c.media_controller.block_until_active(timeout=10)
|
if url_silencio:
|
||||||
print(f"[Voz] Anuncio en {c.cast_info.friendly_name} "
|
_reproducir_y_esperar(
|
||||||
f"(vol {config.GOOGLE_TV_VOLUMEN})")
|
c, url_silencio, "audio/wav", "inicio",
|
||||||
if _esperar_fin(c):
|
f"Tele encendida ({c.cast_info.friendly_name})")
|
||||||
print(f"[Voz] Anuncio terminado en {c.cast_info.friendly_name}")
|
|
||||||
|
if config.GOOGLE_TV_ESPERA_SG > 0:
|
||||||
|
print(f"[Voz] Esperando {config.GOOGLE_TV_ESPERA_SG}s...")
|
||||||
|
time.sleep(config.GOOGLE_TV_ESPERA_SG)
|
||||||
|
|
||||||
|
if url_pitido:
|
||||||
|
_reproducir_y_esperar(
|
||||||
|
c, url_pitido, "audio/wav", "pitido",
|
||||||
|
f"Pitido de emergencia en {c.cast_info.friendly_name}")
|
||||||
|
|
||||||
|
_reproducir_y_esperar(
|
||||||
|
c, url_mensaje, "audio/mpeg", texto[:80],
|
||||||
|
f"Anuncio en {c.cast_info.friendly_name} "
|
||||||
|
f"(vol {config.GOOGLE_TV_VOLUMEN})")
|
||||||
|
|
||||||
if config.GOOGLE_TV_APAGAR_VIA_ADB:
|
if config.GOOGLE_TV_APAGAR_VIA_ADB:
|
||||||
from tv_adb import apagar_tv
|
from tv_adb import apagar_tv
|
||||||
|
|||||||
Reference in New Issue
Block a user