Monitorer la température et le PH d’un bassin avec une connexion Lora et remonter l’information dans Jeedom

Monitorer la température et le PH d’un bassin avec une connexion Lora et remonter l’information dans Jeedom

6 January 2021 0 By Jérôme Ferrari

Bonjour à tous,

Aujourd’hui, on va apprendre comment monitorer l’état d’un bassin pour monitorer la température de l’eau ainsi que son PH afin de savoir si tout va bien pour ses habitants. Ce tutoriel change un peu de l’ordinaire car le matériel utilisé est plus cher que ce que j’utilise d’habitude.

Partie 0: Le matériel choisi

  • Une Raspberry pi + son alimentation + une carte SD
Raspberry Pi® 4 B 4 Go 4 x 1.5 GHz Raspberry Pi® | Conrad.fr
  • Un shield Dragino
  • Une sonde de température Atlas scientific PT-1000
  • Un circuit de mesure de température EZO RTD
  • Une sonde de PH Atlas scientific
  • Un circuit de mesure de EZO PH
  • 2 Cartes de support EZO vers USB
  • 2 câbles mini USB -> USB
  • Optionnellement, une imprimante 3D

Partie 1: Préparation du matériel

Comme pour chaque projet que je fais avec un raspberry pi, vous devez commencer par créer une carte SD (voir les parties de 1 à 4 de mon ancine poste http://miniprojets.net/index.php/2019/05/13/jeedom-ou-comment-domotiser-sa-maison-en-quelques-clics/)

Maintenant nous pouvons préparer le matériel physique.

Dans un premier temps, nous devons faire une légère modification sur le shield Dragino car certaines versions ont un défaut et il faut souder en elles les pins 22 et 24. (Pour plus d’information, je vous invite à aller vous le wiki https://wiki.dragino.com/index.php?title=Lora_Shield)

Maintenant je vous propose d’imprimer en 3D le boitier pour la raspberry et le shield Dragino mais cela n’est pas nécessaire pour la suite du projet, c’est juste que je vais l’installer dans mon garage et j’aimerai une installation propre.

https://www.thingiverse.com/thing:3352448

Ainsi que le support pour maintenir en place les cartes de support EZO vers USB.

https://www.thingiverse.com/thing:1561906

Une fois cela fait, nous pouvons les monter de la façon suivante:

On commence par mettre la raspberry dans le support bas du boitier

Puis on monte la pièce intermédiaire et le chapeau.

Ensuite on fixe les 2 cartes supports

On assemble le tout sur le boitier et on branche les 2 câbles USB

On peux enfin mettre en place le système.

Avant de plonger la sonde de PH, il faudra faire sa calibration. Pour cela, je modifierai mon article un peu plus tard car je n’ai pas le matériel sous la main à cause de la situation actuelle….

Partie 2: Identification des sondes

Pour cette partie, je me base sur la documentation fournie par AtlasScientific (comme d’habitude je vous mets la copie ci-dessous).

Dans un premier temps, il faut rentrer en SSH sur la raspberry pi puis télécharger depuis le git le code nécessaire avec la commande suivante:

git clone https://github.com/AtlasScientific/Raspberry-Pi-sample-code.git

Il faut maintenant installer et paramétrer les modules nécessaire avec les commandes suivantes:

sudo apt-get install libftdi-dev
sudo pip3 install pylibftdi
sudo nano /etc/udev/rules.d/99-libftdi.rules

Copier en remplaçant le contenu du fichier 99-libftdi.rules par la ligne suivante:

SUBSYSTEMS==”usb”, ATTRS{idVendor}==”0403”, ATTRS{idProduct}==”6015”,GROUP=”dialout”, MODE=”0660”, SYMLINK+=”FTDISerial_Converter_$attr{serial}”

Faites un Ctrl+X, puis y pour sauvegarder.

Redemarrez le service udev avec la commande suivante:

sudo service udev restart

Vérifiez que dans le fichier /usr/local/lib/python3.7/dist-packages/pylibftdi/driver.py pour la ligne qui contient USB_PID_LIST vous avez exactement cela USB_PID_LIST = [0x6001, 0x6010, 0x6011, 0x6014, 0x6015] grâce à la commande suivante:

sudo nano /usr/local/lib/python3.7/dist-packages/pylibftdi/driver.py

puis faite un Ctrl+W et tapez USB_PID_LIST, puis entrée.

Si jamais il manque 0x6015, rajoutez le en faite un Ctrl+X, puis Y.

Maintenant tapez la commande suivante:

sudo python3 -m pylibftdi.examples.list_devices

Normalement vous devriez avec une réponse de ce genre:

FTDI:FT230X Basic UART:DO009J4O
FTDI:FT230X Basic UART:DO009MWF

Ce qui correspond à nos 2 capteurs.

Maintenant tapez les commandes suivantes:

cd ~/Raspberry-Pi-sample-code

Nous allons modifier le fichier ftdi car avec python3 la fonction decode n’est plus nécessaire. Pour cela on tape la commande:

sudo nano ftdi.py

Puis on recherche decode avec le Ctrl+w

On tombe sur la ligne suivante:

 dev_info = map(lambda x: x.decode('latin1'), device)

il suffit de supprimer le “.decode(‘latin1’)” ce qui donne

 dev_info = map(lambda x: x, device)

Faites un Ctrl+x, puis Y

Maintenant, tapez la commande suivante:

 sudo python3 ftdi.py

Vous aurez le choix suivant:


Welcome to the Atlas Scientific Raspberry Pi FTDI Serial example.

    Any commands entered are passed to the board via UART except:
    Poll,xx.x command continuously polls the board every xx.x seconds
    Pressing ctrl-c will stop the polling

    Press enter to receive all data in buffer (for continuous mode)

Discovered FTDI serial numbers:

Index:  0  Serial:  DO009J4O

Index:  1  Serial:  DO009MWF
===================================
Please select a device index:

Tapez par exemple 0 ou 1 au choix (ici je tape 1), vous vous retrouvez avec l’annonce suivante:

Please select a device index: 1

>> Opened device  DO009MWF
>> Any commands entered are passed to the board via FTDI:
Enter command:

Tapez la commande R (Read (lecture)) puis taper sur Entrée. Après quelques secondes, vous aurez le résultat suivant:

>> Opened device  DO009MWF
>> Any commands entered are passed to the board via FTDI:
Enter command: R
8.294

Comme je sais que l’eau est à environ 23°C (mesure fait via un thermomètre simple) cela me renseigne que le capteur DO009MWF (ayant pour index 1) est mon capteur de PH et donc que le capteur DO009J4O (ayant pour index 0) est mon capteur de température.

Je mets ici les 2 pdfs correspondant aux 2 capteurs afin de permettre de s’amuser avec les différentes commandes possibles (étalonnage, mesure continue,….)

Voila nous avons identifié les 2 capteurs et nous pouvons passer à la suite afin de permettre la lecture des 2 capteurs toutes les 15 minutes, la sauvegarde de la valeur puis leur envoie via Lora.

Partie 3: Lecture et enregistrement des valeurs des sondes

Maintenant, nous allons créer un script qui va permettre de lire les valeurs des capteurs puis de sauvegarder leur valeur dans 3 fichiers distincts (1 pour l’historisation, 1 pour la valeur actuelle de la température mais retravaillé pour la transmission et 1 pour la valeur actuelle du PH).

Pour cela, il faut créer un fichier avec la commande suivante:

sudo nano read_sensor_temp_ph.py

Puis collez le code suivant:

import string

import pylibftdi
from pylibftdi.device import Device
from pylibftdi.driver import FtdiError
from pylibftdi import Driver
import os
import time
from datetime import datetime

class AtlasDevice(Device):

        def __init__(self, sn):
                Device.__init__(self, mode='t', device_id=sn)


        def read_line(self, size=0):
                """
                taken from the ftdi library and modified to
                use the ezo line separator "\r"
                """
                lsl = len('\r')
                line_buffer = []
                while True:
                        next_char = self.read(1)
                        if next_char == '' or (size > 0 and len(line_buffer) > size):
                                break
                        line_buffer.append(next_char)
                        if (len(line_buffer) >= lsl and
                                        line_buffer[-lsl:] == list('\r')):
                                break
                return ''.join(line_buffer)

        def read_lines(self):
                """
                also taken from ftdi lib to work with modified readline function
                """
                lines = []
                try:
                        while True:
                                line = self.read_line()
                                if not line:
                                        break
                                        self.flush_input()
                                lines.append(line)
                        return lines

                except FtdiError:
                        print("Failed to read from the sensor.")
                        return ''

        def send_cmd(self, cmd):
                """
                Send command to the Atlas Sensor.
                Before sending, add Carriage Return at the end of the command.
                :param cmd:
                :return:
                """
                buf = cmd + "\r"        # add carriage return
                try:
                        self.write(buf)
                        return True
                except FtdiError:
                        print("Failed to send command to the sensor.")
                        return False



def get_ftdi_device_list():
        """
        return a list of lines, each a colon-separated
        vendor:product:serial summary of detected devices
        """
        dev_list = []

        for device in Driver().list_devices():
                # list_devices returns bytes rather than strings
#               dev_info = map(lambda x: x.decode('latin1'), device)
                dev_info = map(lambda x: x, device)
                # device must always be this triple
                vendor, product, serial = dev_info
                dev_list.append(serial)
        return dev_list

##########################################################################
if __name__ == '__main__':

        real_raw_input = vars(__builtins__).get('raw_input', input) # used to find the correct function for python2/3

        print("\nWelcome to the Atlas Scientific Raspberry Pi FTDI Serial.\n")
        print("Discovered FTDI serial numbers:")

        devices = get_ftdi_device_list()
        cnt_all = len(devices)

        #print "\nIndex:\tSerial: "
        for i in range(cnt_all):
                print(  "\nIndex: ", i, " Serial: ", devices[i])
        print( "===================================")

############### Capteurs ###################

        index_temp = 0
        index_ph = 1
        while True:
                dev_temp = AtlasDevice(devices[int(index_temp)])
                dev_ph = AtlasDevice(devices[int(index_ph)])
                time.sleep(1)
                dev_temp.flush()
                dev_ph.flush()
                input_val = "R"

                # pass commands straight to board
                if len(input_val) == 0:
                        lines = dev.read_lines()
                        for i in range(len(lines)):
                                print("temperature" + lines[i])
                else:
                        fichier = open("/home/pi/Raspberry-Pi-sample-code/datalog_Sensors_Temp_Ph.csv", "a")
                        fichier_lastest_temp = open("/home/pi/Raspberry-Pi-sample-code/datalog_sensors_lastest_temp.csv", "w")
                        fichier_lastest_ph = open("/home/pi/Raspberry-Pi-sample-code/datalog_sensors_lastest_ph.csv", "w")
                        dev_temp.send_cmd(input_val)
                        time.sleep(1.3)
                        lines = dev_temp.read_lines()
                        now = datetime.now()
                        timestamp = datetime.timestamp(now)

                        for i in range(len(lines)):
                                print("Temperature: " + lines[i])
                                fichier.write(str(timestamp) + ",")
                                temperature = lines[i]
                                temperature = temperature.replace(temperature[len(temperature)-1],',')
                                fichier.write(temperature)
                                temperature = temperature.replace(temperature[len(temperature)-1],'')
                                temperature = str(float(temperature)+40)
                                fichier_lastest_temp.write(temperature)
                                fichier_lastest_temp.close()
                        dev_ph.send_cmd(input_val)
                        time.sleep(1.3)
                        lines = dev_ph.read_lines()
                        for i in range(len(lines)):
                                print("PH: " + lines[i])
                                ph = lines[i]
                                ph = ph.replace(ph[len(ph)-1],'')
                                fichier.write(ph + "\n")
                                fichier_lastest_ph.write(ph)
                                fichier_lastest_ph.close()
                        fichier.close()
                        time.sleep(60)

Vérifiez que les index sont corrects pour vos capteurs (ici)

    index_temp = 0
    index_ph = 1

et modifiez en cas où

Ce code un fois lancé va lire la valeur du capteur de température ainsi que celui du capteur de PH puis les enregistrer dans les fichiers et attendre 60 secondes avant de recommencer.

Faites un Ctrl+X, puis Y.

Maintenant, on va créer un service qui se lancera ce script au démarrage de la raspberry pi.

Pour cela, il faut faire les commandes suivantes:

cd /lib/systemd/system/
sudo nano atlassensors.service

Maintenant, il faut coller le code suivant:

[Unit]
Description=Read Atlas sensors
After=multi-user.target

[Service]
Type=simple
ExecStart=/usr/bin/python3 /home/pi/Raspberry-Pi-sample-code/read_sensor_temp_ph.py
Restart=on-abort

[Install]
WantedBy=multi-user.target

Faites un Ctrl+X, puis Y.

Maintenant on met en route le service via les commandes suivantes:

sudo chmod 644 /lib/systemd/system/atlassensors.service
sudo chmod +x /home/pi/Raspberry-Pi-sample-code/read_sensor_temp_ph.py
sudo systemctl daemon-reload
sudo systemctl enable atlassensors.service
sudo systemctl start atlassensors.service

Maintenant, nous allons vérifier que l’enregistrement fonctionne bien avec la commande suivante:

sudo nano /home/pi/Raspberry-Pi-sample-code/datalog_Sensors_Temp_Ph.csv

On se retrouve avec l’affichage suivant:

1591267278.838152,21.467,8.039
1591267342.582241,21.467,8.048
1591267406.338943,21.465,8.043
1591267470.095639,21.463,8.031
1591267533.852958,21.464,8.035
1591267597.594173,21.462,8.035
1591267661.351104,21.463,8.041
1591267725.10559,21.462,8.042
1591267788.860872,21.463,8.048

Ce qui correspond pour la première colonne au timestamp, la seconde à la température et la troisième au PH.

on vérifie aussi pour les valeurs actuelles avec les commandes:

sudo nano /home/pi/Raspberry-Pi-sample-code/datalog_sensors_lastest_temp.csv

Qui nous donne 61.463 (car on a rajouté 40° afin de n’avoir que des chiffres positifs pour l’envoi)

et la commande

sudo nano /home/pi/Raspberry-Pi-sample-code/datalog_sensors_lastest_ph.csv

qui nous donne 8.048

Voila maintenant que les données sont formatées et enregistrées, nous pouvons passer à leur envoi via le réseau Lora

Partie 4: Préparation de l’environnement LORA sur thethingsnetwork

Dans un premier temps, il faut vous inscrire sur TTN

https://www.thethingsnetwork.org/

Quand vous êtes inscrit et loggé, cliquez sur Console puis Application

Cliquez maintenant sur add application

Remplissez les cases vides comme ci-dessous (c’est un exemple que j’ai fait avec ma raspberry qui se situe dans le garage ^^)

La prochaine étape consiste a ajouter un appareil (device) donc cliquez sur register device

Remplissez le Device ID avec un nom du genre sensors_from_dragino. (car c’est un shield dragino que j’utilise ^^)

Cliquez sur les deux flèches sous le champ Device EUI ce qui le généra de façon automatique

Et finalement cliquez sur Register (Surtout pas sur Cancel car si vous cliquez dessus, vous perdez votre configuration en cours et cela est peu stupide…. Non non je n’ai jamais fait cela… Bon Ok peut-être une fois quand j’étais jeune…)

Normalement vous devriez avoir une nouvelle page avec les identifiants pour connecter votre Lopy sur le réseau Lora

Maintenant que nous avons les bonnes informations, nous pouvons retourner sur la raspberry pi pour coder la partie Lora

Partie 5: Code LORA avec un dragino

Dans un premier temps, il faut télécharger le programme avec la commande suivante:

git clone https://github.com/wklenk/lmic-rpi-lora-gps-hat

Une fois cela fait, allez dans le dossier lmic-rpi-lora-gps-hat/examples/periodic/

cd lmic-rpi-lora-gps-hat/examples/periodic/

Maintenant, il faut modifier le fichier sensor.c

sudo nano lmic-rpi-lora-gps-hat/examples/periodic/sensor.c

On modifie la partie Read data de la façon suivante:

 // Read data
 u2_t readsensor (char* file_name) {
     debug_str(file_name);
 FILE* file = NULL; int tempo[2]={0}; file = fopen(file_name, "r");
 if (file != NULL)
     {
         fscanf(file, "%d.%d", &tempo[0], &tempo[1] );
         printf("Les meilleurs scores sont : %d,%d", tempo[0], tempo[1]);
         fclose(file);
     }
 int t = 21; 
return tempo[0]*1000+tempo[1];
 }

On sauvegarde avec ctrl+x

Puis, nous allons modifier le fichier main.c

sudo nano lmic-rpi-lora-gps-hat/examples/periodic/main.c

Ajoutez les lignes suivantes en dessous de #include “lmic.h” #include “debug.h”

// sensor functions
extern void initsensor(void);
extern u2_t readsensor(char*);

Dans la partie CONFIGURATION renseignez les clefs APPEUI, DEVEUI et DEV KEY avec les informations TTN respectives Application EUI, Device EUI et App Key

ATTENTION!!!! Pour les APPEUI et DEVEUI, il faut inverser l’ordre des hexas, c’est à dire que par exemple sur TTN, vous avez la clef Device EUI: 0127356F2894472B, il faudra écrire pour DEVEUI: 0x2B, 0x47, 0x94, 0x28, 0x6F, 0x35, 0x27, 0x01.

Seul App Key garde le même sens de lecture!

Voila ce que cela donne par exemple:

//////////////////////////////////////////////////
// CONFIGURATION (FOR APPLICATION CALLBACKS BELOW)
//////////////////////////////////////////////////

// application router ID (LSBF)
 static const u1_t APPEUI[8] = { 0xXX, 0xXX, 0xXX, 0xXX, 0x7E, 0xD5, 0xB3, 0x70 };

// unique device ID (LSBF)
 static const u1_t DEVEUI[8] = { 0xXX, 0x37, 0x94, 0x28, 0xXX, 0xXX, 0xXX, 0x00 };

// device-specific AES key (derived from device EUI)
 static const u1_t DEVKEY[16] = { 0xXX, 0x95, 0xEA, 0x92, 0xXX, 0xXX, 0xDD, 0x9C, 0xXX, 0x27, 0xXX, 0xXX, 0xF7, 0xXX, 0xFB, 0xF4 };

Maintenant, il faut aussi modifier la partie UTILIY JOB de la façon suivante:

//////////////////////////////////////////////////
 // UTILITY JOB
 //////////////////////////////////////////////////
 static osjob_t reportjob;
 // report sensor value every minute
 static void reportfunc (osjob_t* j) {
   char sensors[2][100] = { "/home/pi/Raspberry-Pi-sample-code/datalog_sensors_lastest_temp.csv",
                            "/home/pi/Raspberry-Pi-sample-code/datalog_sensors_lastest_ph.csv"};
   int i;
   for(i=0; i<2; i++){
    u2_t val = readsensor(sensors[i]);
    debug_val("val = ", val);
    // prepare and schedule data for transmission
    LMIC.frame[2i] = val >> 8;    LMIC.frame[2i+1] = val;
   }
   LMIC_setTxData2(1, LMIC.frame, i*2, 0); // (port 1, 2 bytes, unconfirmed)
   // reschedule job in 900 seconds
   os_setTimedCallback(j, os_getTime()+sec2osticks(900), reportfunc);
 }

On fait une sauvegarde avec ctrl+x

Maintenant, on compile le code

sudo make clean && sudo make && sudo ./build/periodic.out

on test le programme avec la commande suivante:

sudo ./examples/periodic/build/periodic.out

on devrait avoir le retour suivant:

000000000 HAL: Initializing …
 000000002 HAL: Detected SX1276 radio module.
 000000002 HAL: Set radio RST pin to 0x00
 000000002 HAL: Wait until 000000003 ms
 000000003 HAL: Set radio RST pin to 0x02
 000000003 HAL: Wait until 000000008 ms
 000000011 HAL: Receiving …
 000000029 Debug: Initializing
 000000029 Debug: JOINING
 000004213 Debug: EV_TXSTART
 000004214 HAL: Sending …
 000009279 HAL: Receiving …
 000009279 HAL: Wait until 000009278 ms
 000009349 Debug: JOINED
 000009350 Debug: /home/pi/Raspberry-Pi-sample-code/datalog_sensors_lastest_temp.csv
 Les meilleurs scores sont : 23,589000009350 Debug: Label 'val = ' value 0x5c25
 000009350 Debug: /home/pi/Raspberry-Pi-sample-code/datalog_sensors_lastest_ph.csv
 Les meilleurs scores sont : 5,190000009350 Debug: Label 'val = ' value 0x1446
 000009350 Debug: EV_TXSTART
 000009351 HAL: Sending …
 000010406 HAL: Receiving …
 000010406 HAL: Wait until 000010405 ms
 000011451 HAL: Receiving …
 000011451 HAL: Wait until 000011452 ms
 000015017 Debug: TXCOMPLETE

On vérifie sur TTN que tout est ok en allant sur l’onglet DATA

Si tout est bon, repérez bien le numéro de Port. Cela servira pour la suite.

on peux créer le service lora-node pour rendre automatique celui-ci

Pour cela on fait les commande suivantes:

cd /lib/systemd/system/
sudo nano lora-node.service

On remplile fichier de la façon suivante:

[Unit]
 Description=LoRaWAN node
 After=user.target
 [Service]
 Type=idle
 ExecStart=/home/pi/lmic-rpi-lora-gps-hat/examples/periodic/build/periodic.out
 StandardOutput=journal
 StandardError=journal
 Restart=on-failure
 [Install]
 WantedBy=multi-user.target

On sauvegarde avec ctrl+x et on execute les commandes suivantes:

sudo chmod 644 /lib/systemd/system/lora-node.service
sudo systemctl daemon-reload
sudo systemctl enable lora-node.service
sudo systemctl start lora-node.service
sudo systemctl status lora-node.service

Nous devons avoir le retour suivant:

● lora-node.service - LoRaWAN node
    Loaded: loaded (/lib/systemd/system/lora-node.service; enabled; vendor preset: enabled)
    Active: active (running) since Wed 2021-01-06 10:35:23 CET; 7min ago
  Main PID: 26155 (periodic.out)
     Tasks: 1 (limit: 2063)
    CGroup: /system.slice/lora-node.service
            └─26155 /home/pi/lmic-rpi-lora-gps-hat/examples/periodic/build/periodic.out
 janv. 06 10:35:23 raspberrypi systemd[1]: Started LoRaWAN node.

C’est ok? Parfait! maintenant on va passer à la partie décodage

Partie 6: Décodage de la Trame Lora

Il faut aller dans l’onglet Applications > capteurs_garage > Payload Formats

On renseigne le code suivant dans la partie decoder

function Decoder(bytes, port) {
 var decoded = {};
 var counter = 1;
 decoded.temperature_eau = 0;
 for(i=0; i<2; i++){
 decoded.temperature_eau += Math.pow(256,i)*parseInt(bytes[2*counter-1-i]);
 }
 decoded.temperature_eau = decoded.temperature_eau/1000-20;
 counter +=1;
 decoded.ph_eau = 0;
 for(i=0; i<2; i++){
 decoded.ph_eau += Math.pow(256,i)*parseInt(bytes[2*counter-1-i]);
 }
 decoded.ph_eau = decoded.ph_eau/1000;
 return decoded;
 }

On va tester pour voir si cela fonctionne pour cela dans Payload, mettez 5C 24 14 46 et cliquez sur Test

Si tout est ok, on sauvegarde avec le bouton situé en bas. Voilà nous avons réussi à décoder la trame et elle sera ainsi tout le temps décodée.

Partie 7: Récupérer les données sur Jeedom

Pour cette partie, on va utiliser le plugin LoRa Node for TTN (Attention le plugin est payant, j’écrirai un article sur une solution gratuite utilisant MQTT un peu plus tard)

Pour cela dans le market de Jeedom téléchargé le plugin et activé le, il n’y a pas de configuration spécifique.

Maintenant allez dans le plugin en cliquant sur Plugins > Protocole domotique > Lora Node for TTN

Cliquez sur Ajouter un équipement et donnez lui un nom

Remplissez les informations suivantes: Application ID, Device ID et Port

Pensez à mettre Visible et sauvegardez

Copiez l’adresse avec l’apikey en bas de la page et renseignez Europe pour le Sélection du serveur TTN (Région)

Maintenant allez sur TTN et cliquez sur l’onglet Applications >capteurs_garage > Integrations

Cliquez sur + add integration

Choisissez HTPP Integration

Maintenant, remplissez les données suivantes Process ID, choisissez default key et collez l’URL prise dans Jeedom (ATTENTION, Il faut avoir ouvert et redirigé les ports correctement de sa box afin d’avoir accès à Jeedom depuis l’extérieur, je ferai un article prochainement dessus)

Sauvegardez et maintenatnt retournez sur Jeedom.

Si tout est paramétré correctement, on devrait voir apparaitre à la prochaine remontée les données issues de TTN. Notre script Lora remontant les données toutes les 15 minutes, nous avons le temps de boire un café ^^

Après cette pause café, on vérifie….

Nous pouvons même historiser…

Voilà, maintenant vous êtes capable de faire le monitoring d’un bassin via une connexion Lora et remonter les données dans Jeedom.

J’espère que cela vous aidera, n’hésitez pas à poser des questions ou des updates.

Jérôme Ferrari