Faire communiquer Jeedom et un Arduino en DIY

Mise à jour du 15/09/2020 > à l’origine écrit à l’été 2016, cette article donnait des pistes sur la programmation pour faire communiquer jeedom et un arduino. Mais rapidement, je suis revenu à la solution « JEEDOUINO » disponible sur le market Jeedom. Certaines évolutions et améliorations de Jeedouino m’ont permis d’exploiter pleinement mes arduinos. Depuis début 2017, je n’utilise donc plus mes scripts perso, ce sujet n’est donc plus actualisé.


Article original, du 18/07/2016 > Pour ceux qui ont lu mes précédents articles, vous savez que j’utilise Jeedouino pour faire communiquer mon Jeedom (RPI2) à mes Arduino (Mega, Uno, Nano).

En effet, il existe deux solutions (plugins) sur le jeedom-market :

  • Jeedouino : que j’utilise en production
  • Arduidom : que je n’ai jamais réussi à faire fonctionner, pourtant j’ai essayé…

Oui mais Jeedouino a des limites :

  • Pas de sketch perso de prévu (contrairement à Arduidom)
  • Gestion de certains capteurs (DHT, DS18B20) mais pas d autres (Afficheur TM1637, Afficheur LCD1602, Emetteur/récepteur RF433, etc)
  • et surtout… ça plante régulièrement

Je ne sais pas si c’est que moi, mais mes Arduinos avec Jeedouino s’arrêtent régulièrement de pinguer puis ça repart au bout de quelques secondes, ce qui par conséquent, ne fait pas remonter les états par moment, ou n’exécutent pas les actions.

Bref, je me suis décidé hier à coder une solution « home made ». Ce ne sera pas pour concurrencer les deux plugins du market (qui se veulent configurable par n’importe qui sans trop de connaissance à contrario de mon code qui sera dédié à ma configuration/mes besoins) mais plus pour le challenge, plaisir perso… et puis que cela arrête de planter (bah oui, je supervise les équipements réseaux, et quand il y en a un qui ne pingue pas pendant X min, je reçois une alerte, mais ça c’est une autre histoire).

Cela peut intéresser des personnes souhaitant faire la même chose, donc je publie ici mes premiers tests.

Ce mini-projet se décompose en deux parties :

  1. Arduino –> Jeedom : Création d’un premier sketch pour lire mes capteurs (donc remontée d’information de l’Arduino vers Jeedom). Oui je commence par le plus simple…
  2. Jeedom –> Arduino : Evolution du sketch pour le passage d’ordre à des actionneurs (relais, emetteur RF, calcul distance, etc)

1/ La lecture de capteur relié à un Arduino et transmission à Jeedom

Pour moi, il y a trois façons de faire :

  • créer un langage de communication spécifique qui sera compris de part et d autres. Trop complexe pour un débutant comme moi, il faudrait surtout que je développe également du côté Jeedom : j’oublie
  • utiliser le plugin « Virtuel » pour la remontée des informations : un serveur Web sur l’Arduino fait des requêtes GET sur le serveur Jeedom, qui les interprète via le plugin ‘Virtuel’.
  • utiliser un fichier XML pour la remontée des informations : un serveur Web sur l’Arduino reçoit une requête HTTP de Jeedom, et renvoi un fichier XML en retour, avec l’état de tous les capteurs.

Par facilité, j’ai choisi d’expérimenter les deux dernières solutions.

A/ Plugin Virtuel et serveur Web Arduino

Dans un premier temps, il faut installer le plugin « Virtuel ». Une fois installé, on créé un équipement ainsi qu’une « info virtuelle ». Une fois enregistré, on obtient son « ID » (le dièse, colonne de gauche).

Arduino : info virtuelle dans jeedom

Il nous faudra également la clé API jeedom que vous trouverez dans le panneau d’administration.

Maintenant, réalisation d’un sketch que l’on téléversera dans notre Arduino. Exemple avec une sonde DHT11 (température+humidité), un afficheur 4 digit TM1637, un Arduino Uno et son Shield Ethernet v2.

Le principe est assez simple :

  1. dans le setup, on initialise tout ce qui va bien (sonde+afficheur+client web)
  2. dans le loop :
    toutes les 30 sec on fait :

    • un relevé de la sonde DHT11
    • si les valeurs ont changé depuis le dernier passage : on envoi les données à Jeedom
    • puis on affiche la température sur l’afficheur

Ce qui donne ce résultat (cliquez ici pour voir le code du sketch).

Attention, je ne suis pas un professionnel de la programmation, il y a peut être des erreurs, et surement des optimisations de code à faire. Mais le principal pour moi, c’est que cela marche, et sans erreur constatée.

B/ Fichier XML et serveur Web Arduino

Dans cette variante, nous aurons besoin d’installer le plugin « Script ». Une fois installé, on créera un équipement, ainsi que des commandes. Chaque commande permettra de parser le fichier XML récupéré. Dans « Requête », c’est les données que vous souhaitez parser. Il faudra donc autant de commandes, avec des requêtes différentes, qu’il y a de données différentes à récupérer dans le fichier XML :

Arduino - parser fichier xml

Maintenant, réalisation d’un sketch que l’on téléversera dans notre Arduino. Toujours le même exemple avec une sonde DHT11 (température+humidité), un afficheur 4 digit TM1637, un Arduino Uno et son Shield Ethernet v2. Principe :

  1. dans le setup, on initialise tout ce qui va bien (sonde+afficheur+client web)
  2. dans le loop :
    • on écoute le port 80, si un client s’est connecté (jeedom dans notre cas), on lui envoi le fichier XML avec les données de la sonde DHT11
    • toutes les 30 sec on fait :
      • un relevé de la sonde DHT11
      • puis on affiche la température sur l’afficheur

Ce qui donne ce résultat (cliquez ici pour voir le code du sketch).

Les deux solutions ont été confrontés pendant plusieurs jours : les deux fonctionnent bien.

2/ Déclencher une action sur l’Arduino depuis Jeedom

Rappelez vous, à l’étape 1 (lecture capteur) j’avais opté pour une solution qui ne nécessitait pas de créer un langage de communication. C’est arrivé à cette étape 2 que je me dis que cela aurait été quand même bien… mais en même temps, tellement plus compliqué. Donc non, j’ai fait le bon choix ! : )

J’ai développé un petit code qui tourne très bien depuis 1 mois sur 2 de mes Arduinos (réception capteur + envoi de déclenchement de relais + envoi trame RF433MHz) ! Mais par manque de temps, je n’ai pas encore complété la fin de cet article, ni même publié le code intégral (il faut que j’enlève tout le superflus, que je commente un peu mon code, etc)… mais en attendant voici le principe :

  • toutes les 5 secondes, je regarde si j’ai reçu une requête HTTP sur le serveur web de l’Arduino
  • si j’ai reçu une requête (normalement généré par le plugin ‘Script’ de Jeedom), je regarde le 6ième caractère reçu (celui après « GET / »)
  • ce caractère définit l’action que l’Arduino devra exécuter (ouvrir/fermer un relais, envoyer une trame RF, etc)
  • cette requête HTTP est envoyé par Jeedom via ‘Script’, il faut donc définir un équipement avec différentes commandes… et bien penser à modifier le 6ième caractère en fonction de l’action que l’on veut envoyer à l’Arduino

Dans le plugin ‘Script’ de Jeedom, on aura :

Plugin script de Jeedom

Voici la fonction de lecture qui est appelée toutes les 5 sec :

[pastacode lang= »c » manual= »%2F%2F%20Fonction%20pour%20lire%20les%20requ%C3%AAtes%20HTTP%20qui%20arrivent%20sur%20le%20serveur%20WEB%20de%20l’Arduino%0Avoid%20LireTrame()%0A%7B%0A%20%20%2F%2F%20On%20cr%C3%A9%C3%A9%20l’objet%20pour%20voir%20si%20l’on%20re%C3%A7oit%20quelque%20chose%0A%20%20EthernetClient%20clientIncoming%20%3D%20server.available()%3B%0A%20%20%2F%2F%20Si%20on%20a%20re%C3%A7u%20une%20requ%C3%AAte%20HTTP%0A%20%20if%20(clientIncoming)%20%0A%20%20%7B%0A%20%20%20%20%2F%2F%20Pour%20compter%20les%2015%20premiers%20caract%C3%A8res%20de%20la%20r%C3%A9ponse%20du%20serveur%0A%20%20%20%20int%20CompteurCodeHTTP%20%3D%200%3B%0A%20%20%20%20char%20MessageRecu%5B20%5D%20%3D%20%22%22%3B%0A%20%20%20%20%20%20%20%0A%20%20%20%20boolean%20currentLineIsBlank%20%3D%20true%3B%0A%0A%20%20%20%20%2F%2F%20Tant%20que%20le%20client%20est%20connect%C3%A9%0A%20%20%20%20while%20(clientIncoming.connected())%20%0A%20%20%20%20%7B%0A%20%20%20%20%20%20%2F%2F%20S’il%20y%20a%20quelque%20chose%20%C3%A0%20lire%20en%20arriv%C3%A9e%0A%20%20%20%20%20%20if%20(clientIncoming.available())%20%0A%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20char%20c%20%3D%20clientIncoming.read()%3B%0A%20%20%20%20%20%20%20%20if%20(c%20%3D%3D%20’%5Cn’)%20%7B%0A%20%20%20%20%20%20%20%20%20%20currentLineIsBlank%20%3D%20true%3B%0A%20%20%20%20%20%20%20%20%7D%20else%20if%20(c%20!%3D%20’%5Cr’)%20%7B%0A%20%20%20%20%20%20%20%20%20%20currentLineIsBlank%20%3D%20false%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20if%20(CompteurCodeHTTP%20%3C%3D%2015)%0A%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20Serial.print(c)%3B%0A%20%20%20%20%20%20%20%20%20%20CompteurCodeHTTP%2B%2B%3B%0A%20%20%20%20%20%20%20%20%20%20MessageRecu%5BCompteurCodeHTTP%5D%20%3D%20%20c%20%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%2F%2F%20Pour%20la%20gestion%20des%20actionneurs%2C%20on%20lit%20la%20valeur%20juste%20apr%C3%A8s%20%22GET%20%2F%22%20(6i%C3%A8me%20caract%C3%A8re%20re%C3%A7u%20dans%20la%20requ%C3%AAte%20HTTP)%0A%20%20%20%20%20%20%20%20if%20(CompteurCodeHTTP%3D%3D6)%0A%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%2F%2F%20Convertit%20le%20char%20en%20int%2C%20pour%20pouvoir%20utiliser%20le%20switch%20–%3E%20le%20’0’%20correspondant%20%C3%A0%2048%20en%20ASCII%0A%20%20%20%20%20%20%20%20%20%20int%20a%20%3D%20c%20%20-%20’0’%20%3B%0A%20%20%20%20%20%20%20%20%20%20switch(a)%0A%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20case%204%20%3A%20%2F%2F%20Si%20le%206i%C3%A8me%20caract%C3%A8re%20re%C3%A7u%20est%20le%20%224%22%2C%20on%20allume%20le%20ventilateur%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20Serial.println(F(%22Ventilateur%20%3A%20ON%22))%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20digitalWrite(8%2C%20HIGH)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20break%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20case%205%20%3A%20%2F%2F%20Si%20le%206i%C3%A8me%20caract%C3%A8re%20re%C3%A7u%20est%20le%20%225%22%2C%20on%20%C3%A9teint%20le%20ventilateur%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20Serial.println(F(%22Ventilateur%20%3A%20OFF%22))%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20digitalWrite(8%2C%20LOW)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20break%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20default%20%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20Serial.println(F(%22DEFAUT%20dans%20le%20switch%2C%20aucun%20cas%20ne%20correspond!%22))%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20break%3B%0A%20%20%20%20%20%20%20%20%20%20%7D%20%2F%2F%20fin%20de%20switch%0A%20%20%20%20%20%20%20%20%7D%20%2F%2F%20Fin%20du%20SI%20pour%20interpr%C3%A9tation%20du%206i%C3%A8me%20caract%C3%A8re%0A%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%2F%2F%20Si%20on%20re%C3%A7oit%20un%20retour%20%C3%A0%20la%20ligne%20et%20que%20la%20ligne%20est%20blanche%2C%20c’est%20que%20la%20requ%C3%AAte%20est%20finie%0A%20%20%20%20%20%20%20%20%2F%2F%20on%20renvoi%20donc%20une%20r%C3%A9ponse%20HTTP%20200%0A%20%20%20%20%20%20%20%20%20if%20(c%20%3D%3D%20’%5Cn’%20%26%26%20currentLineIsBlank)%20%0A%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20clientIncoming.println(%22HTTP%2F1.1%20200%20OK%22)%3B%0A%20%20%20%20%20%20%20%20%20%20clientIncoming.println(%22Content-Type%3A%20text%2Fxml%22)%3B%0A%20%20%20%20%20%20%20%20%20%20clientIncoming.println(%22Connection%3A%20close%22)%3B%0A%20%20%20%20%20%20%20%20%20%20clientIncoming.println()%3B%0A%20%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20break%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%7D%20%2F%2F%20FIN%20de%20’%20S’il%20y%20a%20quelque%20chose%20%C3%A0%20lire%20en%20arriv%C3%A9e’%0A%20%20%20%20%7D%20%2F%2F%20FIN%20de%20’Tant%20que%20le%20client%20est%20connect%C3%A9’%0A%20%20%20%20%0A%20%20%20%20Serial.println()%3B%0A%20%20%20%20%2F%2F%20On%20donne%20le%20temps%20au%20serveur%20distant%20de%20recevoir%20la%20r%C3%A9ponse%20HTTP%0A%20%20%20%20delay(20)%3B%0A%20%20%20%20%2F%2F%20close%20the%20connection%3A%0A%20%20%20%20clientIncoming.stop()%3B%0A%20%20%7D%0A%7D » message= »Fonction pour lire la requête HTTP » highlight= » » provider= »manual »/]

Dans cet exemple simplifié, on est limité à 10 actions possibles (6ième caractère = 0 à 9). Mais il est facile de rajouter l’interprétation du 7ième, 8ième, … caractères pour avoir plus que 10 actions possibles.

Finalement, on peut donc créer facilement un langage de communication HomeMade entre l’Arduino et Jeedom, pour lire des capteurs ou agit sur des actionneurs.


Cet article fait partie d’une série d’articles sur la box domotique Jeedom, les micro-contrôleurs Arduino et compatible, le tout en DIY (Do It Yourself). Consultez la liste complète des articles de cette thématique en cliquant ici.


Si vous souhaitez partager cet article...Share on facebook
Facebook
Share on google
Google
Share on twitter
Twitter