Présentation
Il y a quelques jours, j’ai trouvé un détecteur de mouvement avec une batterie rechargeable de chez Calex. Comme la plupart des IOT sur le marché, il fonctionne sur la plate-forme Tuya avec un microcontrôleur TYWE3S. J’ai essayé de le convertir à l’aide du logiciel Tuya-Convert mais j’ai lamentablement échoué, il semble que Tuya ait amélioré son jeu de piratage.
Problème
La détection via le cloud met plusieurs secondes à être acquittée et utilisée par mon serveur homeassistant, cela rend l’automatisation des lumières bizarre à cause du lag.
Solution
J’ai le contrôle du DNS via mon pihole, et j’ai vu que le capteur appelle son serveur “tuya” à chaque fois qu’il y a du mouvement. J’ai décidé de capitaliser sur cette information.
grep -Ea "from 192.168.10.172" /var/log/pihole.log
Jul 16 11:37:58 dnsmasq[242]: query[A] m2.tuyaeu.com from 192.168.10.172
Jul 16 11:37:58 dnsmasq[242]: query[A] a3.tuyaeu.com from 192.168.10.172
Jul 16 13:52:03 dnsmasq[242]: query[A] m2.tuyaeu.com from 192.168.10.172
Jul 16 13:52:03 dnsmasq[242]: query[A] a3.tuyaeu.com from 192.168.10.172
En fait, ce dont j’ai besoin, c’est de l’heure exacte.
grep -Ea "from 192.168.10.172" /var/log/pihole.log | tail -1 | awk '{print $3}'
13:52:03
MQTT
Avec l’aide de la documentation homeassistant et beaucoup d’essais et d’erreurs, je suis arrivé à cette commande :
mosquitto_pub -h hass.lan -p 1883 -u $user -P $pass -t /pihole/pir/${target_item[i]} -m '{"motion" : "true"}' --qos 0 --retain
Le target_item est le capteur, ils étaient bon marché donc j’en ai acheté 3. Celui-ci communique au Mosquitto Broker l’état du capteur, puis les configurations sur l’assistant domestique aident à un paramétrage plus cohérent et utilisable.
Homeassistant: config/mqtt.yaml
binary_sensor:
- name: "mqtt-pir.atelier"
state_topic: "/pihole/pir/atelier"
availability_topic: "/pihole/pir/availability"
value_template: "{{ 'ON' if value_json.motion == 'true' else 'OFF' }}"
force_update: true
off_delay: 15
qos: 0
device_class: motion
Le Script
Dans un premier temps je déclare les variables utilisées :
#!/bin/bash
# Informations d'identification MQTT
user="mqttuser"
pass="password"
# Éléments cibles et leurs adresses IP correspondantes
target_item=("atelier" "cour_avant" "cour_arriere")
ip_item=("192.168.10.172" "192.168.10.173" "192.168.10.177")
# Tableau pour stocker les horodatages de détection
det_at=()
# Tableau pour stocker les derniers horodatages de détection
last_det=()
# Tableau pour stocker les jours de journalisation
log_day=()
Ensuite, comme écrit dans la documentation, j’ai paramétré la disponibilité du capteur et mis en place un piège en cas de reboot ou d’erreur.
# Publier l'état de disponibilité sur MQTT
mosquitto_pub -h hass.lan -p 1883 -u $user -P $pass -t /pihole/pir/availability -m "online" --qos 0 --retain
# S'il y a une erreur soudaine ou un redémarrage, changez le statut en hors ligne
trap 'mosquitto_pub -h hass.lan -p 1883 -u $user -P $pass -t /pihole/pir/availability -m "offline" --qos 0 --retain' EXIT
Ensuite, je démarre la boucle principale qui transformera une deuxième boucle qui parcourt la liste des capteurs à traiter. Et filtre le journal pour les entrées.
while true; do
# Parcourir les éléments cibles
for ((i = 0; i < ${#target_item[@]}; i++ )); do
# Récupérer le dernier horodatage de détection depuis le journal pour l'élément et l'IP actuels
det_at[i]=$(grep -Ea "from ${ip_item[i]}" /var/log/pihole.log | tail -1 | awk '{print $3}')
# Convertir le dernier horodatage de détection en secondes depuis l'époque
last_item_sec[i]=$(date -d "${last_det[i]}" +%s)
# Convertir l'horodatage de détection actuel en secondes depuis l'époque
detected_item_sec[i]=$(date -d "${det_at[i]}" +%s)
# Récupérer le jour de journalisation pour l'élément et l'IP actuels
log_day[i]=$(grep -Ea "from ${ip_item[i]}" /var/log/pihole.log | tail -1 | awk '{print $2}')
# Obtenir le jour actuel
current_day=$(date -du +%_d)
Ensuite, je vérifie s’il y a une différence entre le dernier horodatage enregistré et les nouvelles entrées, et je mets à jour le registre.
# Vérifier si une nouvelle détection s'est produite pour l'élément actuel et si c'est le même jour
if (( ${detected_item_sec[i]} )) && [[ ${log_day[i]} -eq $current_day ]]; then
# Vérifier si la nouvelle détection s'est produite après la dernière détection
if (( ${last_item_sec[i]} )) && [[ ${last_item_sec[i]} < ${detected_item_sec[i]} ]]; then
# Mettre à jour le dernier horodatage de détection
last_det[i]=${det_at[i]}
Voici la commande mosquitto_pub
, j’ai également implémenté une commande ’no-motion’ apres le else
, mais cela ne semble pas avoir beaucoup d’importance, et cela fait juste du bruit, mais vous pouvez l’activer si vous le souhaitez.
Il met également à jour la variable last_det
et dort un peu.
# Utilisez mosquitto_pub pour publier la charge de détection
mosquitto_pub -h hass.lan -p 1883 -u $user -P $pass -t /pihole/pir/${target_item[i]} -m '{"motion" : "true"}' --qos 0 --retain
sleep 2
else
# Décommentez la ligne suivante si vous souhaitez exécuter la commande mosquitto_pub et publier la charge "pas de mouvement/clair"
# mosquitto_pub -h hass.lan -p 1883 -u $user -P $pass -t /pihole/pir/${target_item[i]} -m '{"motion" : "false"}' --qos 0 --retain
# Mettre à jour le dernier horodatage de détection
last_det[i]=${det_at[i]}
sleep 2
fi
else
sleep 2
fi
done
done
Est-ce que ça marche? Eh bien, si avec la solution cloud, le capteur fonctionne de manière peu fiable avec un décalage compris entre 3 et 10 secondes, j’ai ainsi un temps de réponse fiable de 3 secondes.
Vous pouvez trouver le script à télécharger sur : https://git.cabivr.net/radu/pir-mqtt