06-sep: [aspiradora] modulo Dreame D10 Plus (r2205 map mc1808) + comando /aspiradora en bot IDD
This commit is contained in:
101
vigilancia/aspiradora.py
Normal file
101
vigilancia/aspiradora.py
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
"""Aspiradora Dreame D10 Plus (dreame.vacuum.r2205) via python-miio.
|
||||||
|
|
||||||
|
El modelo r2205 habla el spec MIoT de mc1808, asi que se le pasa el
|
||||||
|
mapping de mc1808 explicitamente. Lee IP/token del .env del directorio.
|
||||||
|
Uso: python aspiradora.py estado|start|stop|home|pause|locate
|
||||||
|
"""
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
|
BASE = os.path.dirname(os.path.abspath(__file__))
|
||||||
|
if BASE not in sys.path:
|
||||||
|
sys.path.insert(0, BASE)
|
||||||
|
|
||||||
|
ESTADOS = {
|
||||||
|
1: "limpiando",
|
||||||
|
2: "inactiva",
|
||||||
|
3: "pausada",
|
||||||
|
4: "error",
|
||||||
|
5: "volviendo a la base",
|
||||||
|
6: "cargando",
|
||||||
|
7: "actualizando",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def _env(nombre, defecto=""):
|
||||||
|
valor = os.getenv(nombre, defecto).strip()
|
||||||
|
if not valor:
|
||||||
|
try:
|
||||||
|
with open(os.path.join(BASE, ".env")) as f:
|
||||||
|
for linea in f:
|
||||||
|
linea = linea.strip()
|
||||||
|
if linea and not linea.startswith("#") and "=" in linea:
|
||||||
|
k, v = linea.split("=", 1)
|
||||||
|
if k.strip() == nombre:
|
||||||
|
valor = v.strip()
|
||||||
|
break
|
||||||
|
except OSError:
|
||||||
|
pass
|
||||||
|
return valor
|
||||||
|
|
||||||
|
|
||||||
|
def conectar():
|
||||||
|
from miio.integrations.vacuum.dreame.dreamevacuum_miot import (
|
||||||
|
MIOT_MAPPING,
|
||||||
|
DreameVacuum,
|
||||||
|
)
|
||||||
|
ip = _env("DREAME_IP", "192.168.50.122")
|
||||||
|
token = _env("DREAME_TOKEN")
|
||||||
|
if not token:
|
||||||
|
raise RuntimeError("Falta DREAME_TOKEN en el .env")
|
||||||
|
return DreameVacuum(ip, token, model="dreame.vacuum.r2205",
|
||||||
|
mapping=MIOT_MAPPING["dreame.vacuum.mc1808"])
|
||||||
|
|
||||||
|
|
||||||
|
def estado():
|
||||||
|
vac = conectar()
|
||||||
|
st = vac.status()
|
||||||
|
cod = st.device_status
|
||||||
|
texto_estado = ESTADOS.get(cod, f"codigo {cod}")
|
||||||
|
return (f"🤖 Dreame D10 Plus: <b>{texto_estado}</b>\n"
|
||||||
|
f"🔋 Bateria: <b>{st.battery_level}%</b> "
|
||||||
|
f"({'cargando' if st.charging_state else 'no cargando'})\n"
|
||||||
|
f"🧹 Modo: {st.cleaning_mode} | "
|
||||||
|
f"Tiempo: {st.cleaning_time} | Area: {st.cleaning_area}")
|
||||||
|
|
||||||
|
|
||||||
|
def main(argv):
|
||||||
|
if len(argv) < 2:
|
||||||
|
print("Uso: aspiradora.py estado|start|stop|home|pause|locate")
|
||||||
|
return 1
|
||||||
|
cmd = argv[1].lower()
|
||||||
|
try:
|
||||||
|
vac = conectar()
|
||||||
|
if cmd == "estado":
|
||||||
|
print(estado().replace("<b>", "").replace("</b>", ""))
|
||||||
|
elif cmd == "start":
|
||||||
|
vac.start()
|
||||||
|
print("Limpieza iniciada.")
|
||||||
|
elif cmd == "stop":
|
||||||
|
vac.stop()
|
||||||
|
print("Limpieza detenida.")
|
||||||
|
elif cmd == "home":
|
||||||
|
vac.home()
|
||||||
|
print("Volviendo a la base.")
|
||||||
|
elif cmd == "pause":
|
||||||
|
vac.pause()
|
||||||
|
print("Pausada.")
|
||||||
|
elif cmd == "locate":
|
||||||
|
vac.play_sound()
|
||||||
|
print("Emitiendo sonido de localizacion.")
|
||||||
|
else:
|
||||||
|
print("Uso: aspiradora.py estado|start|stop|home|pause|locate")
|
||||||
|
return 1
|
||||||
|
except Exception as e:
|
||||||
|
print(f"ERROR: {e}")
|
||||||
|
return 2
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
sys.exit(main(sys.argv))
|
||||||
@@ -754,6 +754,8 @@ def procesar(texto, chat_id):
|
|||||||
elif t.startswith("bajar ") or t.startswith("/bajar "):
|
elif t.startswith("bajar ") or t.startswith("/bajar "):
|
||||||
n = _int_arg(texto)
|
n = _int_arg(texto)
|
||||||
procesar_bajar(n, chat_id)
|
procesar_bajar(n, chat_id)
|
||||||
|
elif comando == "aspiradora":
|
||||||
|
procesar_aspiradora(argumento, chat_id)
|
||||||
elif comando in ("menu", "menú", "inicio", "start") and not argumento:
|
elif comando in ("menu", "menú", "inicio", "start") and not argumento:
|
||||||
try:
|
try:
|
||||||
from menu_idd import enviar_menu
|
from menu_idd import enviar_menu
|
||||||
@@ -1003,6 +1005,45 @@ def procesar_novedades(chat_id):
|
|||||||
log(f"NOVEDADES: {len(items)} items")
|
log(f"NOVEDADES: {len(items)} items")
|
||||||
|
|
||||||
|
|
||||||
|
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: <code>/aspiradora estado|start|stop|home|pause|locate</code>.",
|
||||||
|
chat_id)
|
||||||
|
return
|
||||||
|
try:
|
||||||
|
import aspiradora
|
||||||
|
except Exception as e:
|
||||||
|
log(f"aspiradora import error: {e}")
|
||||||
|
enviar("❌ No se pudo cargar el modulo aspiradora", chat_id)
|
||||||
|
return
|
||||||
|
try:
|
||||||
|
if accion == "estado":
|
||||||
|
enviar(aspiradora.estado(), chat_id)
|
||||||
|
else:
|
||||||
|
vac = aspiradora.conectar()
|
||||||
|
if accion == "start":
|
||||||
|
vac.start()
|
||||||
|
enviar("🧹 Limpieza iniciada.", chat_id)
|
||||||
|
elif accion == "stop":
|
||||||
|
vac.stop()
|
||||||
|
enviar("⏹️ Limpieza detenida.", chat_id)
|
||||||
|
elif accion == "home":
|
||||||
|
vac.home()
|
||||||
|
enviar("🏠 Volviendo a la base.", chat_id)
|
||||||
|
elif accion == "pause":
|
||||||
|
vac.pause()
|
||||||
|
enviar("⏸️ Pausada.", chat_id)
|
||||||
|
elif accion == "locate":
|
||||||
|
vac.play_sound()
|
||||||
|
enviar("🔊 Emitiendo sonido de localización.", chat_id)
|
||||||
|
log(f"ASPIRADORA {accion} ok")
|
||||||
|
except Exception as e:
|
||||||
|
log(f"aspiradora error: {e}")
|
||||||
|
enviar(f"❌ Error con la aspiradora: {e}", chat_id)
|
||||||
|
|
||||||
|
|
||||||
def _int_arg(texto):
|
def _int_arg(texto):
|
||||||
"""Extrae el numero de un comando tipo '/bajar 3'."""
|
"""Extrae el numero de un comando tipo '/bajar 3'."""
|
||||||
partes = texto.split()
|
partes = texto.split()
|
||||||
|
|||||||
Reference in New Issue
Block a user