Comment envoyer des données à Jeedom via l'API JSON depuis un IoT ESP8266 • Domotique et objets connectés à faire soi-même

Nous continuons notre série d’articles sur l’échange de données par requêtes HTTP (TCP/IP) entre un ESP8266 et le serveur domotique Jeedom. Jeedom met à disposition une API au standard JSON RPC (presque) aussi complète que celle de Domoticz. Nous irons un peu plus vite que pour Domoticz, le principe général étant le même.

Lectures recommandées

ESP8266 (Client Web) : envoyer des données à Domoticz en TCP/IP sans fil (API/JSON)

ESP Easy : utiliser des objets connectés DIY avec Jeedom

Documentation API JSON RPC de Jeedom

Matériel utilisé

Le circuit reste le même, à savoir un ESP8266 LoLin D1 Mini (WeMos), un capteur de température et d’humidité (DHT22), un capteur de pression atmosphérique (BMP180) ainsi qu’un shield relai pour piloter l’allumage d’un appareil depuis l’interface de Jeedom.

Circuit d’une mini station météo connectée

Composant Broches Broche ESP8266 (Wemos D1 mini)
DHT22 (shield Wemos D1 Mini) VCC 3V3
GND G
Data D4
BMP180 VCC 3V3
GND G
SDA D2
SCK D3
Shield relai Wemos D1 Mini D1

woevzaezqjj092tvbwzb-3949620

Récupérer votre clé API Jeedom

Pour pouvoir transmettre des données à Jeedom, il est nécessaire de récupérer la clé API depuis l’interface d’administration. Connectez vous à votre serveur et allez dans la configuration (roues crantées). Elle se trouve dans le champ clef API. Vous aurez besoin de cette clé pour le code Arduino.

Préparer un instrument virtuel

Nous allons maintenant créer un instrument qui va recevoir les données. Allez dans les plugins et vérifiez que le plugin Instrument Virtuel est installé. Si ce n’est pas le cas, faites-le.

r0kpqxltjpmusibh3mbh-3509146

Rendez-vous dans plugins -> Programmation -> Virtuel et cliquer sur + pour créer un nouveau instrument :

  • Donnez lui un nom
  • Un objet
  • Un type (optionnel)
  • Cochez Activer et Visible

Allez ensuite à l’onglet Commandes et ajoutez 3 infos virtuelles : température, humidité, baromètre. Vous pouvez en profiter pour attribuer une étiquette pour l’unité ainsi qu’une valeur mini et maxi pur l’échelle. Sauvegardez. Après la sauvegarde, un identifiant (#) est attribué pour chaque information virtuelle. Ici, température (#78), humidité (#79) et baromètre (#80). Nous en aurons besoin dans le code Arduino.

Code Arduino compatible ESP8266

C’est exactement le même que celui développé pour Domoticz, il n’y a que la construction de la requête HTTP qui change. Contrairement à Domoticz, on doit envoyer les données séparément, c’est à dire celle qui correspond à l’instrument virtuel.

La requête HTTP prend la forme suivante

http://#IP_JEEDOM#/core/api/jeeApi.php?apikey=#APIKEY#&type=virtual&id=#ID#&value=#value#

Pour faciliter le travail, vous trouverez au début du programme les variables suivantes qu’il vous reste à modifier par vos valeurs :

const char* apiKey   = "mVuQikcXm69l2mDMYZiCsLj0wamT0HsCcrBCuXRxntJDO1kn";
const char* idTemp   = "78";
const char* idHumi   = "79";
const char* idPA     = "80";

On va donc devoir envoyer une requête HTTP pour chaque mesure et l’envoyer à l’instrument virtuel correspondant. La fonction SendToJeedom() utilise la librairie ESP8266HTTPClient pour envoyer la requête de type Get (les données étant encodées dans l’URL). En retour Jeedom, renvoi le code 200 si tout s’est bien passé.

Si la clé API est mauvaise, la librairie ESP8266HTTPClient renvoi l’erreur -11 (HTTPC_ERROR_READ_TIMEOUT). Jeedom reste muet tout simplement.

boolean sendToJeedom(String url){
  Serial.print("connecting to ");
  Serial.println(host);
  Serial.print("Requesting URL: ");
  Serial.println(url);
  http.begin(host,port,url);
  int httpCode = http.GET();
  Serial.println("closing connection");
  http.end();
}

La requête reste un simple chaine de caractère que l’on assemble avec les différentes variables, par exemple pour la température

String baseurl = "/core/api/jeeApi.php?apikey="; 
baseurl += apiKey;
baseurl += "&type=virtual&id="; 

String url = baseurl + idTemp;
url += url + "&value="; url += String(t); 
sendToJeedom(url);
delay(1000);

Ce qui donne par exemple la requête suivante

/core/api/jeeApi.php?apikey=mVuQikcXm69l2mDMYZiCsLj0wamT0HsCcrBCuXRxntJDO1kn&type=virtual&id=78&value=19.8

Il suffit ensuite de reprendre la base de l’url (baseurl) qui est toujours identique et l’assembler avec l’identifiant et sa valeur. J’ai ajouté un délai de 1s entre chaque publication. Pour optimiser le code, on pourrait vérifier que l’envoi précédent a été correct avant de poursuivre.

Ouvrez l’IDE Arduino et collez le code suivant. Modifiez les variables et téléversez-le.

/*
 * HTTP communication between ESP8266 and Jeedom Smart Home Server
 * Communication HTTP (TCP/IP) entre ESP8266 et le serveur domotique Jeedom
 * Copyright (C) 2017 http://www.projetsdiy.fr - http://www.diyprojects.io
 *   
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see .
 */
#include 
#include 
#include 
#include 
#include 
#include 

#define DHTTYPE   DHT22       // DHT type (DHT11, DHT22)
#define DHTPIN    D4          // Broche du DHT / DHT Pin

const char* ssid     = "xxxxxxxx";
const char* password = "xxxxxxxx";
const char* host     = "xxx.xxx.xxx.xxx";
const int   port     = 80;
const char* apiKey   = "mVuQikcXm69l2mDMYZiCsLj0wamT0HsCcrBCuXRxntJDO1kn";
const char* idTemp   = "78";
const char* idHumi   = "79";
const char* idPA     = "80";
const int   watchdog = 60000;
unsigned long previousMillis = millis(); 
const uint8_t GPIOPIN[5] = {D1,D5,D6,D7,D8};  // Led

DHT dht(DHTPIN, DHTTYPE);
Adafruit_BMP085 bmp;
ESP8266WebServer server ( 80 );
HTTPClient http;

void updateGpio(){
  Serial.println("Update GPIO command from Jeedom : ");
  for ( int i = 0 ; i < server.args(); i++ ) {
    Serial.print(server.argName(i)); Serial.println(server.arg(i));
  }
  String gpio = server.arg("id"); 
  String token = server.arg("token");
  // Vérifie si le serveur est autorisé - Check if server is authorized
  if ( token != "123abCde" ) {
    Serial.println("Not authentified ");
    return;
  }
  int etat = server.arg("etat").toInt();
  int pin = D1;
  if ( gpio == "D1" ) {
    pin = D1;
  } else if ( gpio == "D7" ) {
    pin = D7;
  } else if ( gpio == "D8" ) {
    pin = D8;  
  } else {   
    pin = D1;
  }
  Serial.print("Update GPIO "); Serial.println(pin);
  if ( etat == 1 ) {
    digitalWrite(pin, HIGH);
    Serial.println("GPIO updated : On");
    server.send(200, "application/json","success:1");
  } else if ( etat == 0 ) {
    digitalWrite(pin, LOW);
    Serial.println("GPIO updated : Off");
    server.send(200, "application/json","success:1");
  } else {
    Serial.println("Bad state Value !");
    server.send(200, "application/json","success:0");
  }
}

void setup() {
  Serial.begin(115200);
  delay(10);
  
  Wire.begin(D2,D3);            // Modifie les broches du bus I2C - Change I2C Pins
  if ( !bmp.begin() ) {
    Serial.println("BMP180 KO!");
    while (1);
  } else {
    Serial.println("BMP180 OK");
  }
  
  Serial.setDebugOutput(true);  
  Serial.println("Connecting Wifi...");

  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  
  for ( int x = 0 ; x < 5 ; x++ ) {
    pinMode(GPIOPIN[x], OUTPUT);
  }
  
  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.print(WiFi.localIP()); 
  
  server.on("/gpio", updateGpio);
  server.begin();
}

int value = 0;

void loop() {
  server.handleClient();
  unsigned long currentMillis = millis();

  if ( currentMillis - previousMillis > watchdog ) {
    previousMillis = currentMillis;

    if(WiFi.status() != WL_CONNECTED) {
      Serial.println("WiFi not connected !");
    } else {  
      Serial.println("Send data to Jeedom");
      
      float t = dht.readTemperature();
      float h = dht.readHumidity();
      float pa = bmp.readPressure() / 100.0F;
      
      if ( isnan(t) || isnan(h) ) {
        Serial.println("DHT KO");
      } else {
        String baseurl = "/core/api/jeeApi.php?apikey="; 
        baseurl += apiKey;
        baseurl += "&type=virtual&id="; 
        String url = baseurl + idTemp;
        url += url + "&value="; url += String(t); 
        sendToJeedom(url);
        delay(1000);
        
        url = baseurl + idHumi;
        url += url + "&value="; url += String(h);
        sendToJeedom(url);
        delay(1000);

        url = baseurl + idPA;
        url += url + "&value="; url += String(pa);
        sendToJeedom(url);
        delay(1000);
      }
    }
  }
}

boolean sendToJeedom(String url){
  Serial.print("connecting to ");
  Serial.println(host);
  Serial.print("Requesting URL: ");
  Serial.println(url);
  http.begin(host,port,url);
  int httpCode = http.GET();
  Serial.println("closing connection");
  http.end();
}

De retour sur l’interface Jeedom, vous pouvez visualiser les mesures qui remontent de l’ESP8266 sur l’instrument virtuel.

Avez-vous aimé cet article ?