diff --git a/vigilancia/menu_idd.py b/vigilancia/menu_idd.py
index d1147a4..4b94136 100644
--- a/vigilancia/menu_idd.py
+++ b/vigilancia/menu_idd.py
@@ -116,6 +116,9 @@ def teclado_domotica():
_btn("π€ Aspiradora", PREFIJO + "cat:aspi"),
_btn("π Termo", PREFIJO + "cat:termo"),
],
+ [
+ _btn("π₯οΈ Pantalla", PREFIJO + "cat:pantalla"),
+ ],
FILA_VOLVER,
])
@@ -167,6 +170,17 @@ def teclado_termo():
])
+def teclado_pantalla():
+ return _mk([
+ [
+ _btn("π₯οΈ ON", PREFIJO + "acc:pantalla:on"),
+ _btn("π₯οΈ OFF", PREFIJO + "acc:pantalla:off"),
+ _btn("π Estado", PREFIJO + "acc:pantalla:estado"),
+ ],
+ [_btn("β¬
οΈ DomΓ³tica", PREFIJO + "cat:domotica")],
+ ])
+
+
def teclado_tv():
return _mk([
[
@@ -409,6 +423,7 @@ def _header(categoria):
"aspi": "π€ Aspiradora",
"potencia": "β‘ Potencia aspiradora",
"termo": "π Termo",
+ "pantalla": "π₯οΈ Pantalla",
"sistema": "π οΈ Sistema",
"router": "π‘ Router ASUS",
}
@@ -453,6 +468,7 @@ def _teclado_categoria(chat_id, categoria):
"aspi": teclado_aspi,
"potencia": teclado_potencia,
"termo": teclado_termo,
+ "pantalla": teclado_pantalla,
"sistema": teclado_sistema,
"router": teclado_router,
}
@@ -624,13 +640,13 @@ def _ejecutar_accion(chat_id, message_id, partes):
if accion in directos:
_disp(chat_id, message_id, directos[accion], CAT_ACC.get(accion))
return
- if accion == "termo":
+ if accion in ("termo", "pantalla"):
if sub == "estado":
- _reabrir(chat_id, message_id, "termo", "termo estado")
+ _reabrir(chat_id, message_id, accion, f"{accion} estado")
elif sub in ("on", "off"):
- pi_bot.procesar(f"termo {sub}", chat_id)
+ pi_bot.procesar(f"{accion} {sub}", chat_id)
_cerrar_menu(chat_id, message_id)
- _fin_accion(chat_id, "termo")
+ _fin_accion(chat_id, accion)
return
if accion == "aspiradora":
if sub in ("estado", "stats", "consumibles"):
diff --git a/vigilancia/pi_bot.py b/vigilancia/pi_bot.py
index ca82982..1af8e1b 100644
--- a/vigilancia/pi_bot.py
+++ b/vigilancia/pi_bot.py
@@ -516,20 +516,20 @@ def procesar(texto, chat_id):
except Exception as e:
log(f"descargar error: {e}")
enviar(f"β Error en Download Station: {e}", chat_id)
- elif comando == "termo":
+ elif comando in ("termo", "pantalla"):
accion = argumento.lower().strip()
acciones = {"on": "on", "encender": "on", "off": "off",
"apagar": "off", "estado": "status", "status": "status"}
if accion not in acciones:
- enviar("Uso: /termo on, /termo off o /termo estado", chat_id)
+ enviar(f"Uso: /{comando} on, /{comando} off o /{comando} estado", chat_id)
else:
try:
- from tapo_control import controlar_termo
- resultado = controlar_termo(acciones[accion])
+ from tapo_control import controlar
+ resultado = controlar(comando, acciones[accion])
enviar(f"π {resultado}", chat_id)
except Exception as e:
- log(f"termo error: {e}")
- enviar(f"β Error controlando el termo: {e}", chat_id)
+ log(f"{comando} error: {e}")
+ enviar(f"β Error controlando {comando}: {e}", chat_id)
elif comando == "router":
partes_router = argumento.lower().split()
accion_router = partes_router[0] if partes_router else "ayuda"
@@ -809,7 +809,9 @@ def procesar(texto, chat_id):
"9. descargar <enlace> β aΓ±ade a Download Station\n"
" βοΈ Ej: /descargar magnet:?xt=urn:btih:...\n"
"10. termo on|off|estado β controla el enchufe Tapo\n"
- " βοΈ Ej: /termo estado\n\n"
+ " βοΈ Ej: /termo estado\n"
+ "10c. pantalla on|off|estado β enchufe de la pantalla\n"
+ " βοΈ Ej: /pantalla estado\n\n"
"βββ π DOMΓTICA βββ\n"
"10b. aspiradora ... β Dreame D10 Plus\n"
" βοΈ Ej: /aspiradora estado, /aspiradora vaciar, /aspiradora stats, /aspiradora potencia 3, /aspiradora agua 2, /aspiradora voz\n\n"
diff --git a/vigilancia/tapo_control.py b/vigilancia/tapo_control.py
index 53b7d18..6cc2d3b 100644
--- a/vigilancia/tapo_control.py
+++ b/vigilancia/tapo_control.py
@@ -28,21 +28,28 @@ def _env(name):
return os.getenv(name, FILE_ENV.get(name, "")).strip()
-async def _device():
- host = _env("TAPO_TERMO_IP")
+DISPOSITIVOS = {
+ "termo": "TAPO_TERMO_IP",
+ "pantalla": "TAPO_PANTALLA_IP",
+}
+
+
+async def _device(nombre="termo"):
+ var_ip = DISPOSITIVOS.get(nombre, "TAPO_TERMO_IP")
+ host = _env(var_ip)
username = _env("TAPO_USERNAME")
password = _env("TAPO_PASSWORD")
if not host or not username or not password:
raise RuntimeError(
- "Falta configurar TAPO_TERMO_IP, TAPO_USERNAME y TAPO_PASSWORD en .env"
+ f"Falta configurar {var_ip}, TAPO_USERNAME y TAPO_PASSWORD en .env"
)
return await Discover.discover_single(
host, username=username, password=password, timeout=8
)
-async def _run(action):
- device = await _device()
+async def _run(nombre, action):
+ device = await _device(nombre)
await device.update()
if action == "on":
await device.turn_on()
@@ -52,18 +59,23 @@ async def _run(action):
raise ValueError("Accion no soportada")
await device.update()
state = "encendido" if device.is_on else "apagado"
- return f"termo: {state}"
+ return f"{nombre}: {state}"
-def controlar_termo(action):
+def controlar(nombre, action):
"""Ejecuta una accion Tapo y devuelve un mensaje seguro para Telegram."""
try:
- return asyncio.run(_run(action))
+ return asyncio.run(_run(nombre, action))
except Exception as exc:
message = str(exc)
if "TAPO_" in message:
return f"Error de configuracion Tapo: {message}"
- return f"No se pudo controlar el termo: {message[:180]}"
+ return f"No se pudo controlar {nombre}: {message[:180]}"
+
+
+def controlar_termo(action):
+ """Compatibilidad: el termo es el dispositivo por defecto."""
+ return controlar("termo", action)
async def _discover():