Piloter le GPIO de l’ESP8266 (2) depuis Domoticz en TCP/IP sans fil. Serveur Web et requête HTTP – Domoticz – Bienvenue sur le forum de domotique-et-objets-connectes.fr

3wsuyu4armgntc6qylwn-7212839
pxz8kre4mruum3gitmpp-3636082

Nous continuons aujourd’hui le tutoriel consacré à l’échange de données entre Domoticz et un ESP8266 par requête HTTP (TCP/IP) et plus particulièrement comment piloter le GPIO depuis Domoticz. Dans l’article précédent, nous avons mis en place l’envoi de données depuis un ESP8266 vers Domoticz. Dans cet article, nous allons mettre en place la communication dans l’autre sens.

L’API JSON de Domoticz est une porte d’entrée polyvalente qui permet de mettre à jour des appareils, récupérer des données et réaliser des opérations sur le système domotique. Par contre, cette interface n’est pas bi-directionnelle. On va devoir utiliser un système de requêtes HTTP classique.  qui seront récupérées par un petit serveur Web qui fonctionne sur l’ESP8266.

Matériel utilisé

Nous allons reprendre le même montage que le tutoriel précédent. Cette fois, ce montage va permettre d’intégrer un ESP8266. Pour la partie sonde, vous pouvez utiliser un DHT11 ou un DHT22. Rapide à mettre en oeuvre grâce à la librairie DHT.h d’Adafruit. On pourra également ajouter un BMP180 qui permettra de créer un baromètre sur Domoticz. Pour le pilotage du GPIO, vous pouvez utiliser une simple LED ou un relai.

Circuit

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
Led GPIO D7 Pole + D7
Pole – G
Shield relai Wemos D1 Mini D1

1t9biyoncpsdqeu3jtua-9827748

Changer les broches du bus I2C de l’ESP8266

Avant d’aller plus loin, vous avez du remarquer que la carte relai de Wemos utilise la broche D1. La broche D1 est partagée avec le broche SCK du bus I2C. Il va donc falloir déplacer la broche du bus I2C pour pouvoir utiliser le shield relai en même temps. Pour cela, on utilise la librairie Wire.h

Déclarez la librairie en début de programme

#include 

Dans le setup() ; mais avant le d’initialiser l’objet BMP180 avec la commande bmp.begin() ; on déclare la initialise le bus I2C en indiquant les nouvelles broches. Comme d’habitude, inutile de chercher les broches équivalentes de l’Arduino, on indique directement les broches de l’ESP8266, la conversion se ferra automatiquement. Ici, j’ai déplacé par broche D1 (SCK) sur la broche D3, ce qui donne

Wire.begin(D2,D3);

C’est tout, vous pouvez maintenant déplacer le bus I2C sur les broches que vous voulez.

Piloter le GPIO de l’ESP8266 depuis Domoticz

Nous allons maintenant piloter le GPIO de l’ESP8266 depuis Domoticz. Vous pouvez également faire des demandes complexes en intégrant des requêtes HTTP dans vos scripts Lua. Ici, nous allons simplement activer le relai du shield relai pour Wemos D1 mini. Pour moins de 8€, vous pouvez réaliser une lampe connectée ou un simulateur de présence à l’aide d’un scénario.

Code Arduino / ESP8266

Pour recevoir des commandes depuis Domoticz, on va ajouter une partie serveur au code Arduino précédent. Ajoutez la librairie ESP8266WebServer au code précédent et créer un server écoutant sur le port 80.

#include 
ESP8266WebServer server ( 80 );

Dans le startup ajouter une route sur /gpio après que la connexion au réseau Wi-Fi. Ce serveur sera simplement à l’écoute des appels sur une page /gpio. Chaque appel sur cette page déclenchera l’execution de la fonction updateGpio().

server.on("/gpio", updateGpio);
server.begin();

La fonction updateGpio() décode l’URL et met à jour l’état du GPIO correspondant. La fonction server.arg(« id ») permet de récupérer l’identifiant du GPIO etserver.arg(« etat »), l’état de ce dernier.

void updateGpio(){
  Serial.println("Update GPIO command from DOMOTICZ : ");
  for ( int i = 0 ; i < server.args(); i++ ) {
    Serial.print(server.argName(i)); Serial.println(server.arg(i));
  }
  String gpio = server.arg("id"); 
  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");
  } else if ( etat == 0 ) {
    digitalWrite(pin, LOW);
    Serial.println("GPIO updated : Off");
  } else {
    Serial.println("Bad Led Value !");
  }
}

Voici le code Arduino complet qu’il vous suffit de téléverser après avoir modifié vos paramètres :

  • ssid et mot de passe WiFi
  • Adresse IP du serveur Domoticz (host) et le port s’il est différent de 8080
#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 = 8080;
const int   watchdog = 60000; // Fréquence d'envoi des données à Domoticz - Frequency of sending data to Domoticz
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 DOMOTICZ : ");
  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");
  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");
  } else if ( etat == 0 ) {
    digitalWrite(pin, LOW);
    Serial.println("GPIO updated : Off");
  } else {
    Serial.println("Bad Led Value !");
  }
}

void setup() {
  Serial.begin(115200);
  delay(10);
  Wire.begin(D2,D3);
  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 Domoticz");
      
      float t = dht.readTemperature();
      float h = dht.readHumidity();
      float pa = bmp.readPressure() / 100.0F;
      
      if ( isnan(t) || isnan(h) ) {
        Serial.println("DHT KO");
      } else {
        int hum_stat;
        int bar_for = 0;
        if ( h > 70 ) {
          hum_stat = 3;
        } else if ( h < 30 ) {
          hum_stat = 2; 
        } else if ( h >= 30 & h  45 & h  1030 ) {
          bar_for = 1;  
        } else if ( pa > 1010 & pa  990 & pa  970 & pa < 990 ) {
          bar_for = 4;
        }
        
        String url = "/json.htm?type=command&param=udevice&idx=12&nvalue=0&svalue=";
        url += String(t); url += ";";
        url += String(h); url += ";";
        url += String(hum_stat); url += ";";
        url += String(pa);url += ";";
        url += String(bar_for);
     
        sendToDomoticz(url);
      }
    }
  }
}

void sendToDomoticz(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();
    if (httpCode) {
      if (httpCode == 200) {
        String payload = http.getString();
        Serial.println("Domoticz response "); 
        Serial.println(payload);
      }
    }
  Serial.println("closing connection");
  http.end();
}

Configuration Domoticz : créer un interrupteur virtuel

Retournez dans le matériel pour ajouter un nouveau capteur virtuel.

Piloter le GPIO à l’aide d’une action

Pour allumer, éteindre une lampe sans aucune autre condition, le plus facile et le plus rapide est de configurer une action en fonction de l’état de l’interrupteur. Allez à l’onglet Interrupteurs et ouvrez l’appareil en édition.

Dans le champ Action On, collez l’URL suivante en remplaçant IP_ESP8266 par la votre

 http://IP_ESP8266/gpio?id=D1&etat=1&token=123abCde 

Pour l’état Off, on mettra donc simplement l’état à 0.

 http://IP_ESP8266/gpio?id=D1&etat=0&token=123abCde 

Enregistrez.

Piloter le GPIO à l’aide d’un script Lua

L’autre manière de procéder et de créer un script Lua. C’est un peu plus long à mettre en place, mais on a toute la puissance du language à notre disposition. Si vous ne connaissez pas les scripts Lua, vous pouvez commencer par ce tutoriel.

Connectez-vous à votre serveur Domoticz en SSH et placez vous dans le répertoire des scripts Lua

cd ~/domoticz/scripts/lua

On va créer u script qui se déclenche à chaque changement d’état de l’interrupteur. Par convention, le fichier devra donc porter le nom script_device_nomDuDevice.lua, ce qui donne

sudo nano script_device_GPIO_D1.lua

Collez ce code Lua. Modifiez l’adresse IP de votre ESP8266 dans la variable baseurlESP8266. Le script test la valeur de l’appareil RelayD1. Si elle est égale à On, on complète l’url en indiquant l’id=D1 avec l’état à 1, 0 dans le cas contraire. Vous pouvez mettre l’état à On, ON, ALLUME…il faudra simplement tester la valeur de la variable dans le code Arduino.

baseurlESP8266 = "http://192.168.1.22/gpio?"
commandArray =  {}

print ("Update Wemos D1 Mini Relay shield (Pin D1)")
if (otherdevices['RelayD1'] == 'On') then
  commandArray['OpenURL'] = baseurlESP8266..'id=D1&etat=1&token=123abCd'
else
  commandArray['OpenURL'] = baseurlESP8266..'id=D1&etat=0&token=123abCd'
end

return commandArray

Sécuriser la communication

Il est possible d’améliorer la sécurité des échanges entre Domoticz et l’ESP8266. Vous avez certainement remarqué que l’envoi de données à Domoticz se fait sans la moindre authentification. Si on considère que le serveur domotique n’est jamais exposé à internet et que le réseau Wi-Fi est bien sécurisé, cela ne pose pas trop de problème. Par contre si vous voulez rendre accessible Domoticz depuis internet, il va falloir améliorer ça. Ici, nous n’irons pas jusqu’à chiffrer les échanges, c’est possible mais sort du cadre de ce tutoriel.

Réseaux locaux (pas d’identifiant ni mot de passe)

Dans la majorité des cas, vos objets connectés à base d’ESP8266 devrait se trouver sur le même réseau que le serveur Domoticz. Dans ce cas, le plus facile est d’ajouter les adresses IP de vos objets connectés à la liste des appareils autorisés à utiliser l’API dans autorisation. Pour cela, allez dans les réglages puis Paramètres et complétez le champ Réseaux.

Authentification par utilisateur et mot de passe (code Arduino)

Si vous avez protégé l’accès de votre Domoticz par un identifiant et un mot de passe, il vous suffit de modifier la variable host

La variable host prendra alors la forme

username:password@domoticz-ip

Ajouter un token (jeton) dans la requête HTTP

Ces deux méthodes de sécurisation ne fonctionnent que dans le sens ESP8266 vers Domoticz. Il n’est pas (encore) possible de crypter le serveur web de l’ESP8266. Pour sécuriser les commandes, le plus simple est d’ajouter un clé publique ou un jeton qu’il suffira de tester dans le code Arduino. C’est une sécurisation assez basique mais c’est toujours mieux que rien.

String token = server.arg("token");
if ( token != "123abCde" ) {
  Serial.println("Not authentified ");
  return;
}

Voilà, vous pouvez maintenant envoyer des données, l’états de capteurs et piloter le GPIO de l’ESP8266 depuis un serveur Domoticz. La prochaine fois, nous verrons comment faire pour Jeedom.