02-ago: [proyecto] vigilancia - integra middleware Alexa (alexa_notify.js/VoiceMonkey) + .env con credenciales de Telegram y VoiceMonkey + tests 18/18
This commit is contained in:
@@ -18,5 +18,11 @@ COOLDOWN=45
|
|||||||
# Webhook Alexa/Node-RED (opcional, dejar vacío si no se usa)
|
# Webhook Alexa/Node-RED (opcional, dejar vacío si no se usa)
|
||||||
WEBHOOK_ALEXA=
|
WEBHOOK_ALEXA=
|
||||||
|
|
||||||
|
# Middleware VoiceMonkey (reutiliza scripts/alexa_notify.js de biblioteca_negocio_prolongo)
|
||||||
|
VOICEMONKEY_TOKEN=
|
||||||
|
VOICEMONKEY_DEVICE=
|
||||||
|
ALEXA_NODE=node
|
||||||
|
ALEXA_NOTIFY_SCRIPT=C:\Users\juanm\Documents\GitHub\biblioteca_negocio_prolongo\scripts\alexa_notify.js
|
||||||
|
|
||||||
# Directorio de snapshots
|
# Directorio de snapshots
|
||||||
SNAPSHOT_DIR=snapshots
|
SNAPSHOT_DIR=snapshots
|
||||||
|
|||||||
@@ -27,4 +27,8 @@ HORA_INICIO = int(os.getenv("HORA_INICIO", 0))
|
|||||||
HORA_FIN = int(os.getenv("HORA_FIN", 23))
|
HORA_FIN = int(os.getenv("HORA_FIN", 23))
|
||||||
COOLDOWN = int(os.getenv("COOLDOWN", 30))
|
COOLDOWN = int(os.getenv("COOLDOWN", 30))
|
||||||
WEBHOOK_ALEXA = os.getenv("WEBHOOK_ALEXA", "").strip()
|
WEBHOOK_ALEXA = os.getenv("WEBHOOK_ALEXA", "").strip()
|
||||||
|
VOICEMONKEY_TOKEN = os.getenv("VOICEMONKEY_TOKEN", "").strip()
|
||||||
|
VOICEMONKEY_DEVICE = os.getenv("VOICEMONKEY_DEVICE", "").strip()
|
||||||
|
ALEXA_NODE = os.getenv("ALEXA_NODE", "node")
|
||||||
|
ALEXA_NOTIFY_SCRIPT = os.getenv("ALEXA_NOTIFY_SCRIPT", "").strip()
|
||||||
SNAPSHOT_DIR = os.getenv("SNAPSHOT_DIR", "snapshots")
|
SNAPSHOT_DIR = os.getenv("SNAPSHOT_DIR", "snapshots")
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
import os
|
||||||
|
import subprocess
|
||||||
|
|
||||||
import requests
|
import requests
|
||||||
|
|
||||||
import config
|
import config
|
||||||
@@ -24,6 +27,23 @@ def enviar_telegram(ruta_imagen: str, texto: str):
|
|||||||
|
|
||||||
|
|
||||||
def disparar_webhook_alexa(texto: str):
|
def disparar_webhook_alexa(texto: str):
|
||||||
|
if config.ALEXA_NOTIFY_SCRIPT:
|
||||||
|
env = os.environ.copy()
|
||||||
|
if config.VOICEMONKEY_TOKEN:
|
||||||
|
env["VOICEMONKEY_TOKEN"] = config.VOICEMONKEY_TOKEN
|
||||||
|
if config.VOICEMONKEY_DEVICE:
|
||||||
|
env["VOICEMONKEY_DEVICE"] = config.VOICEMONKEY_DEVICE
|
||||||
|
try:
|
||||||
|
r = subprocess.run(
|
||||||
|
[config.ALEXA_NODE, config.ALEXA_NOTIFY_SCRIPT, texto],
|
||||||
|
env=env, timeout=15, capture_output=True, text=True,
|
||||||
|
)
|
||||||
|
if r.returncode != 0:
|
||||||
|
print(f"[Alexa] Error middleware: {r.stderr[:200]}")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"[Alexa] Excepción lanzando middleware: {e}")
|
||||||
|
return
|
||||||
|
|
||||||
if not config.WEBHOOK_ALEXA:
|
if not config.WEBHOOK_ALEXA:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|||||||
@@ -142,12 +142,15 @@ def test_webhook_mock():
|
|||||||
real = notificador.requests
|
real = notificador.requests
|
||||||
notificador.requests = FakeRequests()
|
notificador.requests = FakeRequests()
|
||||||
orig = config.WEBHOOK_ALEXA
|
orig = config.WEBHOOK_ALEXA
|
||||||
|
orig_script = config.ALEXA_NOTIFY_SCRIPT
|
||||||
config.WEBHOOK_ALEXA = "http://localhost:1880/alexa"
|
config.WEBHOOK_ALEXA = "http://localhost:1880/alexa"
|
||||||
|
config.ALEXA_NOTIFY_SCRIPT = ""
|
||||||
try:
|
try:
|
||||||
disparar_webhook_alexa("PRUEBA")
|
disparar_webhook_alexa("PRUEBA")
|
||||||
check("Webhook disparado cuando configurado", len(llamadas) == 1)
|
check("Webhook disparado cuando configurado", len(llamadas) == 1)
|
||||||
finally:
|
finally:
|
||||||
config.WEBHOOK_ALEXA = orig
|
config.WEBHOOK_ALEXA = orig
|
||||||
|
config.ALEXA_NOTIFY_SCRIPT = orig_script
|
||||||
notificador.requests = real
|
notificador.requests = real
|
||||||
|
|
||||||
llamadas.clear()
|
llamadas.clear()
|
||||||
@@ -172,6 +175,43 @@ def test_yolo():
|
|||||||
res is False)
|
res is False)
|
||||||
|
|
||||||
|
|
||||||
|
def test_alexa_middleware():
|
||||||
|
print("\n--- RF-08: Middleware alexa_notify.js (mock subprocess) ---")
|
||||||
|
llamadas = {}
|
||||||
|
|
||||||
|
def fake_run(cmd, **kwargs):
|
||||||
|
llamadas["cmd"] = cmd
|
||||||
|
llamadas["env_token"] = kwargs.get("env", {}).get("VOICEMONKEY_TOKEN", "")
|
||||||
|
class R:
|
||||||
|
returncode = 0
|
||||||
|
stderr = ""
|
||||||
|
return R()
|
||||||
|
|
||||||
|
import notificador
|
||||||
|
real_run = notificador.subprocess.run
|
||||||
|
notificador.subprocess.run = fake_run
|
||||||
|
orig_script = config.ALEXA_NOTIFY_SCRIPT
|
||||||
|
orig_token = config.VOICEMONKEY_TOKEN
|
||||||
|
orig_dev = config.VOICEMONKEY_DEVICE
|
||||||
|
orig_node = config.ALEXA_NODE
|
||||||
|
config.ALEXA_NOTIFY_SCRIPT = "alexa_notify.js"
|
||||||
|
config.VOICEMONKEY_TOKEN = "VM_TOKEN_FAKE"
|
||||||
|
config.VOICEMONKEY_DEVICE = "echo-salon"
|
||||||
|
config.ALEXA_NODE = "node"
|
||||||
|
try:
|
||||||
|
disparar_webhook_alexa("PRUEBA movimiento")
|
||||||
|
check("Ejecuta node + script + texto",
|
||||||
|
llamadas.get("cmd") == ["node", "alexa_notify.js", "PRUEBA movimiento"])
|
||||||
|
check("Inyecta VOICEMONKEY_TOKEN al proceso",
|
||||||
|
llamadas.get("env_token") == "VM_TOKEN_FAKE")
|
||||||
|
finally:
|
||||||
|
notificador.subprocess.run = real_run
|
||||||
|
config.ALEXA_NOTIFY_SCRIPT = orig_script
|
||||||
|
config.VOICEMONKEY_TOKEN = orig_token
|
||||||
|
config.VOICEMONKEY_DEVICE = orig_dev
|
||||||
|
config.ALEXA_NODE = orig_node
|
||||||
|
|
||||||
|
|
||||||
def test_flujo_completo():
|
def test_flujo_completo():
|
||||||
print("\n--- RF-03/RF-04/RF-05: Flujo completo snapshot+cooldown (mock) ---")
|
print("\n--- RF-03/RF-04/RF-05: Flujo completo snapshot+cooldown (mock) ---")
|
||||||
os.makedirs(config.SNAPSHOT_DIR, exist_ok=True)
|
os.makedirs(config.SNAPSHOT_DIR, exist_ok=True)
|
||||||
@@ -202,6 +242,7 @@ if __name__ == "__main__":
|
|||||||
test_franja_horaria()
|
test_franja_horaria()
|
||||||
test_telegram_mock()
|
test_telegram_mock()
|
||||||
test_webhook_mock()
|
test_webhook_mock()
|
||||||
|
test_alexa_middleware()
|
||||||
test_yolo()
|
test_yolo()
|
||||||
test_flujo_completo()
|
test_flujo_completo()
|
||||||
print(f"\n=== RESULTADO: {APROBADOS} OK, {FALLIDOS} FALLO ===")
|
print(f"\n=== RESULTADO: {APROBADOS} OK, {FALLIDOS} FALLO ===")
|
||||||
|
|||||||
Reference in New Issue
Block a user