06-sep: [domotica] Pantalla como dispositivo aparte (comando + submenu)
This commit is contained in:
@@ -116,6 +116,9 @@ def teclado_domotica():
|
|||||||
_btn("🤖 Aspiradora", PREFIJO + "cat:aspi"),
|
_btn("🤖 Aspiradora", PREFIJO + "cat:aspi"),
|
||||||
_btn("🔌 Termo", PREFIJO + "cat:termo"),
|
_btn("🔌 Termo", PREFIJO + "cat:termo"),
|
||||||
],
|
],
|
||||||
|
[
|
||||||
|
_btn("🖥️ Pantalla", PREFIJO + "cat:pantalla"),
|
||||||
|
],
|
||||||
FILA_VOLVER,
|
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():
|
def teclado_tv():
|
||||||
return _mk([
|
return _mk([
|
||||||
[
|
[
|
||||||
@@ -409,6 +423,7 @@ def _header(categoria):
|
|||||||
"aspi": "🤖 <b>Aspiradora</b>",
|
"aspi": "🤖 <b>Aspiradora</b>",
|
||||||
"potencia": "⚡ <b>Potencia aspiradora</b>",
|
"potencia": "⚡ <b>Potencia aspiradora</b>",
|
||||||
"termo": "🔌 <b>Termo</b>",
|
"termo": "🔌 <b>Termo</b>",
|
||||||
|
"pantalla": "🖥️ <b>Pantalla</b>",
|
||||||
"sistema": "🛠️ <b>Sistema</b>",
|
"sistema": "🛠️ <b>Sistema</b>",
|
||||||
"router": "📡 <b>Router ASUS</b>",
|
"router": "📡 <b>Router ASUS</b>",
|
||||||
}
|
}
|
||||||
@@ -453,6 +468,7 @@ def _teclado_categoria(chat_id, categoria):
|
|||||||
"aspi": teclado_aspi,
|
"aspi": teclado_aspi,
|
||||||
"potencia": teclado_potencia,
|
"potencia": teclado_potencia,
|
||||||
"termo": teclado_termo,
|
"termo": teclado_termo,
|
||||||
|
"pantalla": teclado_pantalla,
|
||||||
"sistema": teclado_sistema,
|
"sistema": teclado_sistema,
|
||||||
"router": teclado_router,
|
"router": teclado_router,
|
||||||
}
|
}
|
||||||
@@ -624,13 +640,13 @@ def _ejecutar_accion(chat_id, message_id, partes):
|
|||||||
if accion in directos:
|
if accion in directos:
|
||||||
_disp(chat_id, message_id, directos[accion], CAT_ACC.get(accion))
|
_disp(chat_id, message_id, directos[accion], CAT_ACC.get(accion))
|
||||||
return
|
return
|
||||||
if accion == "termo":
|
if accion in ("termo", "pantalla"):
|
||||||
if sub == "estado":
|
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"):
|
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)
|
_cerrar_menu(chat_id, message_id)
|
||||||
_fin_accion(chat_id, "termo")
|
_fin_accion(chat_id, accion)
|
||||||
return
|
return
|
||||||
if accion == "aspiradora":
|
if accion == "aspiradora":
|
||||||
if sub in ("estado", "stats", "consumibles"):
|
if sub in ("estado", "stats", "consumibles"):
|
||||||
|
|||||||
@@ -516,20 +516,20 @@ def procesar(texto, chat_id):
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
log(f"descargar error: {e}")
|
log(f"descargar error: {e}")
|
||||||
enviar(f"❌ Error en Download Station: {e}", chat_id)
|
enviar(f"❌ Error en Download Station: {e}", chat_id)
|
||||||
elif comando == "termo":
|
elif comando in ("termo", "pantalla"):
|
||||||
accion = argumento.lower().strip()
|
accion = argumento.lower().strip()
|
||||||
acciones = {"on": "on", "encender": "on", "off": "off",
|
acciones = {"on": "on", "encender": "on", "off": "off",
|
||||||
"apagar": "off", "estado": "status", "status": "status"}
|
"apagar": "off", "estado": "status", "status": "status"}
|
||||||
if accion not in acciones:
|
if accion not in acciones:
|
||||||
enviar("Uso: <code>/termo on</code>, <code>/termo off</code> o <code>/termo estado</code>", chat_id)
|
enviar(f"Uso: <code>/{comando} on</code>, <code>/{comando} off</code> o <code>/{comando} estado</code>", chat_id)
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
from tapo_control import controlar_termo
|
from tapo_control import controlar
|
||||||
resultado = controlar_termo(acciones[accion])
|
resultado = controlar(comando, acciones[accion])
|
||||||
enviar(f"🔌 <b>{resultado}</b>", chat_id)
|
enviar(f"🔌 <b>{resultado}</b>", chat_id)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
log(f"termo error: {e}")
|
log(f"{comando} error: {e}")
|
||||||
enviar(f"❌ Error controlando el termo: {e}", chat_id)
|
enviar(f"❌ Error controlando {comando}: {e}", chat_id)
|
||||||
elif comando == "router":
|
elif comando == "router":
|
||||||
partes_router = argumento.lower().split()
|
partes_router = argumento.lower().split()
|
||||||
accion_router = partes_router[0] if partes_router else "ayuda"
|
accion_router = partes_router[0] if partes_router else "ayuda"
|
||||||
@@ -809,7 +809,9 @@ def procesar(texto, chat_id):
|
|||||||
"<b>9.</b> <code>descargar <enlace></code> — añade a Download Station\n"
|
"<b>9.</b> <code>descargar <enlace></code> — añade a Download Station\n"
|
||||||
" ✏️ Ej: <code>/descargar magnet:?xt=urn:btih:...</code>\n"
|
" ✏️ Ej: <code>/descargar magnet:?xt=urn:btih:...</code>\n"
|
||||||
"<b>10.</b> <code>termo on|off|estado</code> — controla el enchufe Tapo\n"
|
"<b>10.</b> <code>termo on|off|estado</code> — controla el enchufe Tapo\n"
|
||||||
" ✏️ Ej: <code>/termo estado</code>\n\n"
|
" ✏️ Ej: <code>/termo estado</code>\n"
|
||||||
|
"<b>10c.</b> <code>pantalla on|off|estado</code> — enchufe de la pantalla\n"
|
||||||
|
" ✏️ Ej: <code>/pantalla estado</code>\n\n"
|
||||||
"━━━ 🏠 DOMÓTICA ━━━\n"
|
"━━━ 🏠 DOMÓTICA ━━━\n"
|
||||||
"<b>10b.</b> <code>aspiradora ...</code> — Dreame D10 Plus\n"
|
"<b>10b.</b> <code>aspiradora ...</code> — Dreame D10 Plus\n"
|
||||||
" ✏️ Ej: <code>/aspiradora estado</code>, <code>/aspiradora vaciar</code>, <code>/aspiradora stats</code>, <code>/aspiradora potencia 3</code>, <code>/aspiradora agua 2</code>, <code>/aspiradora voz</code>\n\n"
|
" ✏️ Ej: <code>/aspiradora estado</code>, <code>/aspiradora vaciar</code>, <code>/aspiradora stats</code>, <code>/aspiradora potencia 3</code>, <code>/aspiradora agua 2</code>, <code>/aspiradora voz</code>\n\n"
|
||||||
|
|||||||
@@ -28,21 +28,28 @@ def _env(name):
|
|||||||
return os.getenv(name, FILE_ENV.get(name, "")).strip()
|
return os.getenv(name, FILE_ENV.get(name, "")).strip()
|
||||||
|
|
||||||
|
|
||||||
async def _device():
|
DISPOSITIVOS = {
|
||||||
host = _env("TAPO_TERMO_IP")
|
"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")
|
username = _env("TAPO_USERNAME")
|
||||||
password = _env("TAPO_PASSWORD")
|
password = _env("TAPO_PASSWORD")
|
||||||
if not host or not username or not password:
|
if not host or not username or not password:
|
||||||
raise RuntimeError(
|
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(
|
return await Discover.discover_single(
|
||||||
host, username=username, password=password, timeout=8
|
host, username=username, password=password, timeout=8
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
async def _run(action):
|
async def _run(nombre, action):
|
||||||
device = await _device()
|
device = await _device(nombre)
|
||||||
await device.update()
|
await device.update()
|
||||||
if action == "on":
|
if action == "on":
|
||||||
await device.turn_on()
|
await device.turn_on()
|
||||||
@@ -52,18 +59,23 @@ async def _run(action):
|
|||||||
raise ValueError("Accion no soportada")
|
raise ValueError("Accion no soportada")
|
||||||
await device.update()
|
await device.update()
|
||||||
state = "encendido" if device.is_on else "apagado"
|
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."""
|
"""Ejecuta una accion Tapo y devuelve un mensaje seguro para Telegram."""
|
||||||
try:
|
try:
|
||||||
return asyncio.run(_run(action))
|
return asyncio.run(_run(nombre, action))
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
message = str(exc)
|
message = str(exc)
|
||||||
if "TAPO_" in message:
|
if "TAPO_" in message:
|
||||||
return f"Error de configuracion Tapo: {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():
|
async def _discover():
|
||||||
|
|||||||
Reference in New Issue
Block a user