05-sep: [vigilancia] comandos /aiMesh /qos /limite /seguridad para el ASUS desde Telegram
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
"""Lectura segura de datos ASUSWRT mediante la API web del router."""
|
||||
|
||||
import asyncio
|
||||
import html
|
||||
import json
|
||||
import os
|
||||
import unicodedata
|
||||
@@ -8,6 +9,7 @@ import unicodedata
|
||||
import aiohttp
|
||||
from asusrouter import AsusData, AsusRouter
|
||||
from asusrouter.modules.parental_control import PCRuleType, ParentalControlRule
|
||||
from asusrouter.modules.system import AsusSystem
|
||||
|
||||
|
||||
def _load_env():
|
||||
@@ -110,3 +112,115 @@ def cambiar_bloqueo(nombre, blocked):
|
||||
raise ValueError(f"Dispositivo no reconocido: {nombre}")
|
||||
asyncio.run(_set_block(device["mac"], device["name"], blocked))
|
||||
return f"{'Bloqueado' if blocked else 'Activado'}: {device['name']}"
|
||||
|
||||
|
||||
async def _aimesh_data():
|
||||
username = _env("ASUS_USERNAME")
|
||||
password = _env("ASUS_PASSWORD")
|
||||
if not username or not password:
|
||||
raise RuntimeError(
|
||||
"Falta ASUS_USERNAME o ASUS_PASSWORD en el .env de la Raspberry"
|
||||
)
|
||||
session = aiohttp.ClientSession()
|
||||
router = AsusRouter(
|
||||
hostname=_env("ASUS_ROUTER_IP", "192.168.50.1"),
|
||||
username=username,
|
||||
password=password,
|
||||
session=session,
|
||||
)
|
||||
try:
|
||||
await router.async_connect()
|
||||
return await router.async_get_data(AsusData.AIMESH, force=True)
|
||||
finally:
|
||||
await router.async_disconnect()
|
||||
await session.close()
|
||||
|
||||
|
||||
async def _aimesh_action(cmd, mac=None):
|
||||
username = _env("ASUS_USERNAME")
|
||||
password = _env("ASUS_PASSWORD")
|
||||
if not username or not password:
|
||||
raise RuntimeError(
|
||||
"Falta ASUS_USERNAME o ASUS_PASSWORD en el .env de la Raspberry"
|
||||
)
|
||||
session = aiohttp.ClientSession()
|
||||
router = AsusRouter(
|
||||
hostname=_env("ASUS_ROUTER_IP", "192.168.50.1"),
|
||||
username=username,
|
||||
password=password,
|
||||
session=session,
|
||||
)
|
||||
try:
|
||||
await router.async_connect()
|
||||
if cmd == "reconstruir":
|
||||
return await router.async_set_state(AsusSystem.AIMESH_REBUILD)
|
||||
if cmd == "reiniciar_todo":
|
||||
return await router.async_set_state(AsusSystem.AIMESH_REBOOT)
|
||||
return await router.async_set_state(
|
||||
AsusSystem.NODE_REBOOT, device_list=mac
|
||||
)
|
||||
finally:
|
||||
await router.async_disconnect()
|
||||
await session.close()
|
||||
|
||||
|
||||
def _nodo_texto(node):
|
||||
tipo = "ROUTER" if getattr(node, "type", "") == "router" else "NODO"
|
||||
alias = node.alias or node.model or "Sin nombre"
|
||||
lineas = [f"{tipo} · {alias} ({node.model})"]
|
||||
estado = "conectado" if node.status else "apagado"
|
||||
lineas.append(f" estado: {estado}")
|
||||
if node.ip:
|
||||
lineas.append(f" ip: {node.ip}")
|
||||
if node.fw:
|
||||
lineas.append(f" firmware: {node.fw}")
|
||||
if node.mac:
|
||||
lineas.append(f" mac: {node.mac}")
|
||||
parent = node.parent or {}
|
||||
if parent:
|
||||
rssi = parent.get("rssi", "?")
|
||||
conexion = parent.get("connection", "?")
|
||||
lineas.append(f" enlace: {conexion} · rssi={rssi}")
|
||||
for banda, ssid in (node.ap or {}).items():
|
||||
lineas.append(f" wifi {banda}: {ssid}")
|
||||
return "\n".join(lineas)
|
||||
|
||||
|
||||
def aimesh_estado():
|
||||
data = asyncio.run(_aimesh_data()) or {}
|
||||
if not data:
|
||||
return "<pre>Sin datos AiMesh</pre>"
|
||||
nodos = list(data.values())
|
||||
nodos.sort(key=lambda n: getattr(n, "level", 0))
|
||||
texto = "\n\n".join(_nodo_texto(n) for n in nodos)
|
||||
return f"<pre>{html.escape(texto)}</pre>"
|
||||
|
||||
|
||||
def _resolver_nodo(nombre):
|
||||
data = asyncio.run(_aimesh_data()) or {}
|
||||
clave = normalizar_nombre(nombre)
|
||||
for mac, node in data.items():
|
||||
if mac and mac.lower() == nombre.lower().strip():
|
||||
return node
|
||||
alias = normalizar_nombre(node.alias or "")
|
||||
if clave and (alias == clave or clave in alias or alias in clave):
|
||||
return node
|
||||
return None
|
||||
|
||||
|
||||
def aimesh_reiniciar_nodo(nombre):
|
||||
node = _resolver_nodo(nombre)
|
||||
if not node:
|
||||
raise ValueError(f"Nodo AiMesh no encontrado: {nombre}")
|
||||
asyncio.run(_aimesh_action("nodo", mac=node.mac))
|
||||
return f"🔄 Nodo reiniciado: {node.alias or node.model} ({node.mac})"
|
||||
|
||||
|
||||
def aimesh_reconstruir():
|
||||
asyncio.run(_aimesh_action("reconstruir"))
|
||||
return "🛠️ AiMesh reconstruida. Los nodos se reconectarán en unos minutos."
|
||||
|
||||
|
||||
def aimesh_reiniciar_todo():
|
||||
asyncio.run(_aimesh_action("reiniciar_todo"))
|
||||
return "⚠️ Router y todos los nodos se están reiniciando..."
|
||||
|
||||
Reference in New Issue
Block a user