Automatiser son aspirateur Xiaomi avec Python sur Raspberry Pi

Automatiser son aspirateur Xiaomi avec Python sur Raspberry Pi
ou « comment passer l'aspirateur quand personne n'est à la maison ? »

Un confort de vie et un appartement propre

Je possède depuis maintenant près d'un an un aspirateur robot Xiaomi Mi Vacuum, et au delà du gain de temps, ce petit robot améliore nettement la propreté dans l'appartement. En effet, la fonction de programmation permet d'automatiser le nettoyage, ce qui n'est pas possible avec un aspirateur traditionnel : le travail, les sorties, et la vie de famille ne permettent pas toujours une régularité exemplaire dans ce genre de tâches ménagères quotidiennes.

Les limites de l'application Mi Home

Mais l'application Xiaomi Mi Home se retrouve vite limitée. Il n'est possible que de programmer des heures de passage et l'aspirateur est donc susceptible de déclencher lorsqu'on est à la maison. La domotique n'a d'interêt que si elle sait se faire oublier, et le robot n'est pas vraiment discret. Malheureusement l'application est incapable de savoir si l'appartement est vide ou non.

La fonction d'automatisation de Mi Home

Pour ne pas entendre le robot et ne pas se le prendre dans les pattes, il est possible de coder un bête script à l'aide de la librairie Python-Miio et d'un Raspberry Pi (ou d'un NAS). Ce script déclencherait à une heure donnée le passage de l'aspirateur si nos smartphones ne sont pas connectés en WiFi à la box internet. J'ai utilisé quelques mois une instance de Home Assistant dans cet unique but, une solution fonctionnelle mais quelque peu démesurée.


Pour information, ma configuration actuelle est composée d'une Livebox v4, d'un Xiaomi Mi Vacuum (v1), de deux smartphones Google Pixel 2 (celui de la Miss et le mien) et d'une box ARM. Le fonctionnement sera identique avec un autre modèle de routeur internet, de smartphone, d'aspirateur robot Xiaomi et/ou avec un Raspberry Pi (tous modèles confondus, le script étant vraiment léger).

Dans mon cas, je souhaite que l'aspirateur déclenche à 11h30, mais si quelqu'un est là il tente de nouveau à 15h00, et je veux qu'il ne démarre qu'une seule fois par jour.

Obtenir le Token de l'aspirateur

Le token est un code, une clé qui permettra à votre script de donner des ordres à votre aspirateur. La page d'aide de Home Assistant propose différentes solutions pour récupérer le token en fonction de votre appareil ou de votre configuration.

Fixer l'IP du Robot et des téléphones

Il est préférable de fixer l'adresse IP de vos appareils pour éviter des mauvaises surprises.

Dans les réglages réseau de votre routeur vous pourrez donner une IP statique à vos appareils. Notez les adresses IP et gardez les pour la suite.

Installer Python-Miio et ses dépendances

Commençons par installer pip3, un outil indispensable pour télécharger des librairies Python :

sudo apt-get install python3-pip

Nous pouvons dès à présent installer Python-Miio :

sudo pip3 install python-miio

Sous les systèmes basés sur Debian, assurez-vous d'avoir libffi et openssl d'installés :

sudo apt-get install libffi-dev libssl-dev

Tester l'installation

Avant de commencer à coder un script, on peut déjà tester la bonne configuration de l'installation. On ouvre python :

python3

On peut exécuter :

from miio import Vacuum
vac = Vacuum("<ipAspirateur>", "<tokenAspirateur>")
vac.start()

Si l'aspirateur démarre, c'est bon signe, on peut passer à la suite !

Coller le script

En SSH, dans votre dossier /home/pi on créé un fichier "script.py" à l'aide de :

nano script.py

On insère :

from miio import Vacuum
import os
import requests
import time
import datetime  

telephone1 = "<ipAppareil1>" #Mon téléphone
telephone2 = "<ipAppareil2>" #Un autre téléphone

isVacuumedToday = 0 #L'aspirateur est-il passé aujourd'hui ?

vac = Vacuum("<ipAspirateur>", "<tokenAspirateur>")

def isConnected():
  telephone1IsConnected = os.system("ping -c 1 " + telephone1)
  telephone2IsConnected = os.system("ping -c 1 " + telephone2)

  if telephone1IsConnected == 0 or telephone2IsConnected == 0:
      return 0
  else:
      return 1
      
def vacuumStart():
  if isConnected() == 1 :
      print("Trying to start the vacuum.")
      print(vac.start())
  else:
      return 0    
    
while 1:
  current_time = datetime.datetime.now()  
  if current_time.hour == <heure> and current_time.minute == <minutes> and isVacuumedToday == 0: #1er essai à une heure donnée
      vacuumStart()
      isVacuumedToday = 1
  elif current_time.hour == <heure> and current_time.minute == <minutes> and isVacuumedToday == 0: #2eme essai si l'aspirateur n'a pas démarré au premier horaire
      vacuumStart()
      isVacuumedToday = 1
  elif current_time.hour == 0 and current_time.minute == 0:
      isVacuumedToday = 0 #On réinitialise à minuit
  else:
      print("Wait 30 seconds")
      print(isVacuumedToday)
  time.sleep(30)

N'oubliez pas d'adapter le code selon vos besoins et les variables entre crochet par les données correspondantes :

<ipAppareil1>
<ipAppareil2>
<ipAspirateur>
<tokenAspirateur>
<heure>
<minutes>

On quitte nano en enregistrant avec Ctrl+X. Maintenant on peut dire au système d'exécuter le code au démarrage du Raspberry à l'aide de rc.local :

sudo nano /etc/rc.local

Insérez :

python3 /home/pi/script.py &

On enregistre et on reboot, et c'est parti, plus qu'à attendre l'horaire donné.

Cette solution n'est pas la meilleure, mais c'est le plus simple que j'ai trouvé, et la consommation de ressources est vraiment négligeable (quelques 20Mo de RAM utilisée). La mise en place ne prend pas beaucoup de temps et est assez simple à comprendre. Cela marche depuis plusieurs jours chez moi sans problème

Bonus : Notifications via Bot Telegram

Si vous possédez un bot Telegram, vous pouvez simplement mettre en place des notifications en rajoutant la commande :

r = requests.get("https://api.telegram.org/<tokenTelegram>/sendMessage?chat_id=<chatID>&text=L'aspirateur+démarre")

<tokenTelegram> est le token de votre bot (contactez le bot @botFather pour créer et obtenir le token de votre bot)

<chat_id> est l'identifiant de votre compte Télégram (contactez le bot @get_id_bot pour obtenir votre chat_id)

Appliqué dans le script, cela donne :

from miio import Vacuum
import os
import requests
import time
import datetime  

telephone1 = "<ipAppareil1>"
telephone2 = "<ipAppareil2>"

isVacuumedToday = 0

vac = Vacuum("<ipAspirateur>", "<tokenAspirateur>")

r = requests.get("https://api.telegram.org/<tokenTelegram>/sendMessage?chat_id=<chatID>&text=Le+script+démarre") #optionnel

def isConnected():
  telephone1IsConnected = os.system("ping -c 1 " + telephone1)
  telephone2IsConnected = os.system("ping -c 1 " + telephone2)

  if telephone1IsConnected == 0 or telephone2IsConnected == 0:
      return 0
  else:
      return 1
      
def vacuumStart():
  if isConnected() == 1 :
      print("Trying to start the vacuum.")
      print(vac.start())
      r = requests.get("https://api.telegram.org/<tokenTelegram>/sendMessage?chat_id=<chatID>&text=L'aspirateur+démarre") #optionnel
  else:
      return 0    
    
while 1:
  current_time = datetime.datetime.now()  
  if current_time.hour == <heure> and current_time.minute == <minutes> and isVacuumedToday == 0:
      vacuumStart()
      isVacuumedToday = 1
  elif current_time.hour == <heure> and current_time.minute == <minutes> and isVacuumedToday == 0:
      vacuumStart()
      isVacuumedToday = 1
  elif current_time.hour == 0 and current_time.minute == 0:
      isVacuumedToday = 0
  else:
      print("Wait 30 seconds")
      print(isVacuumedToday)
  time.sleep(30)

Merci à Bryan pour la relecture