From df2fbadcc3a5da341c924f2c8fac07103c1c2f6c Mon Sep 17 00:00:00 2001 From: juanjo Date: Sun, 6 Sep 2026 14:45:22 +0200 Subject: [PATCH] 06-sep: [aspiradora] pack2: vaciado, auto, stats, consumibles, potencia, agua, voz --- vigilancia/aspiradora.py | 100 ++++++++++++++++++++++++++++++++++++++- vigilancia/menu_idd.py | 43 ++++++++++++++--- vigilancia/pi_bot.py | 67 ++++++++++++++++++++++---- 3 files changed, 191 insertions(+), 19 deletions(-) diff --git a/vigilancia/aspiradora.py b/vigilancia/aspiradora.py index c9172b7..a1aad3b 100644 --- a/vigilancia/aspiradora.py +++ b/vigilancia/aspiradora.py @@ -21,6 +21,21 @@ MAP_R2205 = { "cleaning_time": {"siid": 4, "piid": 2}, "cleaning_area": {"siid": 4, "piid": 3}, "volume": {"siid": 7, "piid": 1}, + "voice_id": {"siid": 7, "piid": 2}, + "set_voice": {"siid": 7, "aiid": 4}, + "auto_collect": {"siid": 15, "piid": 1}, + "start_collect": {"siid": 15, "aiid": 1}, + "first_clean_time": {"siid": 12, "piid": 1}, + "total_clean_time": {"siid": 12, "piid": 2}, + "total_clean_times": {"siid": 12, "piid": 3}, + "total_clean_area": {"siid": 12, "piid": 4}, + "brush_left_time": {"siid": 9, "piid": 1}, + "brush_life_level": {"siid": 9, "piid": 2}, + "brush_left_time2": {"siid": 10, "piid": 1}, + "brush_life_level2": {"siid": 10, "piid": 2}, + "filter_life_level": {"siid": 11, "piid": 1}, + "filter_left_time": {"siid": 11, "piid": 2}, + "mop_mode": {"siid": 4, "piid": 5}, "start_clean": {"siid": 2, "aiid": 1}, "stop_clean": {"siid": 4, "aiid": 2}, "pause": {"siid": 2, "aiid": 2}, @@ -37,6 +52,7 @@ ESTADOS = { } CARGAS = {1: "cargando", 2: "no cargando", 5: "volviendo a cargar"} MODOS = {0: "silencioso", 1: "estándar", 2: "medio", 3: "fuerte"} +AGUAS = {1: "bajo", 2: "medio", 3: "alto"} def _env(nombre, defecto=""): @@ -87,11 +103,53 @@ def estado(): f"Area: {d.get('cleaning_area')} m2{extra}") +def _get(vac, nombre): + d = vac.status().data + return d.get(nombre) + + +def stats(): + vac = conectar() + d = vac.status().data + return (f"📊 Estadísticas Dreame\n" + f"Limpiezas totales: {d.get('total_clean_times')}\n" + f"Tiempo total: {d.get('total_clean_time')} min\n" + f"Area total: {d.get('total_clean_area')} m2") + + +def consumibles(): + vac = conectar() + d = vac.status().data + return (f"🔧 Consumibles\n" + f"Cepillo: {d.get('brush_life_level')}% " + f"({d.get('brush_left_time')}h restantes)\n" + f"Lateral: {d.get('brush_life_level2')}% " + f"({d.get('brush_left_time2')}h restantes)\n" + f"Filtro: {d.get('filter_life_level')}% " + f"({d.get('filter_left_time')}h restantes)") + + +def auto_estado(): + vac = conectar() + d = vac.status().data + return ("🗑️ Vaciado automático: " + f"{'ON' if d.get('auto_collect') else 'OFF'}") + + +def voz_estado(): + vac = conectar() + d = vac.status().data + return (f"🔊 Voz actual: {d.get('voice_id')} | " + f"Volumen: {d.get('volume')}") + + def main(argv): if len(argv) < 2: - print("Uso: aspiradora.py estado|start|stop|home|pause|locate") + print("Uso: aspiradora.py estado|start|stop|home|pause|locate|" + "vaciar|auto|stats|consumibles|potencia|agua|voz") return 1 cmd = argv[1].lower() + arg = argv[2] if len(argv) > 2 else "" try: vac = conectar() if cmd == "estado": @@ -111,8 +169,46 @@ def main(argv): elif cmd == "locate": vac.call_action("play_sound") print("Emitiendo sonido de localizacion.") + elif cmd == "vaciar": + vac.call_action("start_collect") + print("Vaciando en la base.") + elif cmd == "auto": + if arg.lower() in ("on", "1"): + vac.set_property_by(15, 1, 1) + print("Vaciado automatico activado.") + elif arg.lower() in ("off", "0"): + vac.set_property_by(15, 1, 0) + print("Vaciado automatico desactivado.") + else: + print(auto_estado().replace("", "").replace("", "")) + elif cmd == "stats": + print(stats().replace("", "").replace("", "")) + elif cmd == "consumibles": + print(consumibles().replace("", "").replace("", "")) + elif cmd == "potencia": + if arg.isdigit() and int(arg) in MODOS: + vac.set_property_by(4, 4, int(arg)) + print(f"Potencia: {MODOS[int(arg)]}.") + else: + d = vac.status().data + print(f"Potencia actual: {MODOS.get(d.get('cleaning_mode'))} " + f"(0-3).") + elif cmd == "agua": + if arg.isdigit() and int(arg) in AGUAS: + vac.set_property_by(4, 5, int(arg)) + print(f"Agua: {AGUAS[int(arg)]}.") + else: + d = vac.status().data + print(f"Agua actual: {AGUAS.get(d.get('mop_mode'))} (1-3).") + elif cmd == "voz": + if arg: + vac.set_voice(arg) + print(f"Voz cambiada a {arg} (si el pack existe).") + else: + print(voz_estado().replace("", "").replace("", "")) else: - print("Uso: aspiradora.py estado|start|stop|home|pause|locate") + print("Uso: aspiradora.py estado|start|stop|home|pause|locate|" + "vaciar|auto|stats|consumibles|potencia|agua|voz") return 1 except Exception as e: print(f"ERROR: {e}") diff --git a/vigilancia/menu_idd.py b/vigilancia/menu_idd.py index cbf85df..23ce37d 100644 --- a/vigilancia/menu_idd.py +++ b/vigilancia/menu_idd.py @@ -130,10 +130,32 @@ def teclado_aspi(): _btn("⏸️ Pausar", PREFIJO + "acc:aspiradora:pause"), _btn("🏠 A la base", PREFIJO + "acc:aspiradora:home"), ], + [ + _btn("🗑️ Vaciar", PREFIJO + "acc:aspiradora:vaciar"), + _btn("📊 Stats", PREFIJO + "acc:aspiradora:stats"), + ], + [ + _btn("⚡ Potencia…", PREFIJO + "cat:potencia"), + _btn("🔧 Consumibles", PREFIJO + "acc:aspiradora:consumibles"), + ], [_btn("⬅️ Domótica", PREFIJO + "cat:domotica")], ]) +def teclado_potencia(): + return _mk([ + [ + _btn("🔈 Silencioso", PREFIJO + "acc:potencia:0"), + _btn("🔉 Estándar", PREFIJO + "acc:potencia:1"), + ], + [ + _btn("🔊 Medio", PREFIJO + "acc:potencia:2"), + _btn("📢 Fuerte", PREFIJO + "acc:potencia:3"), + ], + [_btn("⬅️ Aspiradora", PREFIJO + "cat:aspi")], + ]) + + def teclado_termo(): return _mk([ [ @@ -351,6 +373,7 @@ def _header(categoria): "parental": "👪 Control parental", "domotica": "🏠 Domótica", "aspi": "🤖 Aspiradora", + "potencia": "⚡ Potencia aspiradora", "termo": "🔌 Termo", "sistema": "🛠️ Sistema", "router": "📡 Router ASUS", @@ -394,6 +417,7 @@ def _teclado_categoria(chat_id, categoria): "parental": teclado_parental, "domotica": teclado_domotica, "aspi": teclado_aspi, + "potencia": teclado_potencia, "termo": teclado_termo, "sistema": teclado_sistema, "router": teclado_router, @@ -575,13 +599,18 @@ def _ejecutar_accion(chat_id, message_id, partes): _fin_accion(chat_id, "termo") return if accion == "aspiradora": - if sub in ("estado", "start", "stop", "home", "pause", "locate"): - if sub == "estado": - _reabrir(chat_id, message_id, "aspi", "aspiradora estado") - else: - pi_bot.procesar(f"aspiradora {sub}", chat_id) - _cerrar_menu(chat_id, message_id) - _fin_accion(chat_id, "aspi") + if sub in ("estado", "stats", "consumibles"): + _reabrir(chat_id, message_id, "aspi", f"aspiradora {sub}") + elif sub in ("start", "stop", "home", "pause", "locate", "vaciar"): + pi_bot.procesar(f"aspiradora {sub}", chat_id) + _cerrar_menu(chat_id, message_id) + _fin_accion(chat_id, "aspi") + return + if accion == "potencia": + if sub.isdigit() and int(sub) in (0, 1, 2, 3): + pi_bot.procesar(f"aspiradora potencia {sub}", chat_id) + _cerrar_menu(chat_id, message_id) + _fin_accion(chat_id, "aspi") return if accion == "tablets": if sub in ("bloquear", "desbloquear"): diff --git a/vigilancia/pi_bot.py b/vigilancia/pi_bot.py index 598ba5b..ca82982 100644 --- a/vigilancia/pi_bot.py +++ b/vigilancia/pi_bot.py @@ -811,8 +811,8 @@ def procesar(texto, chat_id): "10. termo on|off|estado — controla el enchufe Tapo\n" " ✏️ Ej: /termo estado\n\n" "━━━ 🏠 DOMÓTICA ━━━\n" - "10b. aspiradora estado|start|stop|home|pause|locate — Dreame D10 Plus\n" - " ✏️ Ej: /aspiradora estado\n\n" + "10b. aspiradora ... — Dreame D10 Plus\n" + " ✏️ Ej: /aspiradora estado, /aspiradora vaciar, /aspiradora stats, /aspiradora potencia 3, /aspiradora agua 2, /aspiradora voz\n\n" "━━━ 📺 TV ━━━\n" "11. tv <mensaje> — mensaje rápido a la tele\n" " ✏️ Ej: /tv la cena está lista\n" @@ -1028,11 +1028,18 @@ def procesar_novedades(chat_id): def procesar_aspiradora(argumento, chat_id): - """Comandos de la Dreame D10 Plus: estado|start|stop|home|pause|locate.""" - accion = (argumento or "estado").lower().strip() - if accion not in ("estado", "start", "stop", "home", "pause", "locate"): - enviar("Uso: /aspiradora estado|start|stop|home|pause|locate.", - chat_id) + """Dreame D10 Plus: estado|start|stop|home|pause|locate|vaciar| + auto on|off|stats|consumibles|potencia 0-3|agua 1-3|voz [id].""" + partes = (argumento or "estado").lower().strip().split(None, 1) + accion = partes[0] + arg = partes[1].strip() if len(partes) > 1 else "" + validas = ("estado", "start", "stop", "home", "pause", "locate", + "vaciar", "auto", "stats", "consumibles", "potencia", + "agua", "voz") + if accion not in validas: + enviar("Uso: /aspiradora estado|start|stop|home|pause|locate|" + "vaciar|auto on|off|stats|consumibles|potencia 0-3|agua 1-3|" + "voz [id].", chat_id) return try: import aspiradora @@ -1043,6 +1050,14 @@ def procesar_aspiradora(argumento, chat_id): try: if accion == "estado": enviar(aspiradora.estado(), chat_id) + elif accion == "stats": + enviar(aspiradora.stats(), chat_id) + elif accion == "consumibles": + enviar(aspiradora.consumibles(), chat_id) + elif accion == "auto" and not arg: + enviar(aspiradora.auto_estado(), chat_id) + elif accion == "voz" and not arg: + enviar(aspiradora.voz_estado(), chat_id) else: vac = aspiradora.conectar() if accion == "start": @@ -1055,12 +1070,44 @@ def procesar_aspiradora(argumento, chat_id): vac.home() enviar("🏠 Volviendo a la base.", chat_id) elif accion == "pause": - vac.pause() + vac.call_action("pause") enviar("⏸️ Pausada.", chat_id) elif accion == "locate": - vac.play_sound() + vac.call_action("play_sound") enviar("🔊 Emitiendo sonido de localización.", chat_id) - log(f"ASPIRADORA {accion} ok") + elif accion == "vaciar": + vac.call_action("start_collect") + enviar("🗑️ Vaciando en la base.", chat_id) + elif accion == "auto": + if arg in ("on", "1"): + vac.set_property_by(15, 1, 1) + enviar("🗑️ Vaciado automático activado.", chat_id) + else: + vac.set_property_by(15, 1, 0) + enviar("🗑️ Vaciado automático desactivado.", + chat_id) + elif accion == "potencia": + if arg.isdigit() and int(arg) in aspiradora.MODOS: + vac.set_property_by(4, 4, int(arg)) + enviar(f"⚡ Potencia: " + f"{aspiradora.MODOS[int(arg)]}.", chat_id) + else: + enviar("Uso: /aspiradora potencia 0-3 " + "(0 silencioso, 1 estándar, 2 medio, 3 fuerte).", + chat_id) + elif accion == "agua": + if arg.isdigit() and int(arg) in aspiradora.AGUAS: + vac.set_property_by(4, 5, int(arg)) + enviar(f"💧 Agua: {aspiradora.AGUAS[int(arg)]}.", + chat_id) + else: + enviar("Uso: /aspiradora agua 1-3 " + "(1 bajo, 2 medio, 3 alto).", chat_id) + elif accion == "voz": + vac.set_voice(arg) + enviar(f"🔊 Voz cambiada a {arg} " + f"(si el pack existe).", chat_id) + log(f"ASPIRADORA {accion} {arg} ok") except Exception as e: log(f"aspiradora error: {e}") enviar(f"❌ Error con la aspiradora: {e}", chat_id)