Driving the GPIO of the ESP8266 (Web Server) from Domoticz to TCP/IP Wireless – Part 2

We continue today the tutorial dedicated to the exchange of data between Domoticz and an ESP8266 by HTTP request and more particularly how to control the GPIO from Domoticz. In the previous article, we set up sending data from an ESP8266 to Domoticz. In this article, we will set up communication in the other direction. The Domoticz JSON API is a versatile gateway for updating devices, retrieving data and performing operations on the home automation system. On the other hand, this interface is not bi-directional. We will have to use a system of traditional HTTP requests that will be retrieved by a small Web server that runs on the ESP8266.

Equipment used

We will resume the same montage as the previous tutorial. This time, this assembly will allow to integrate an ESP8266. For the probe part, you can use a DHT11 or a DHT22. Quick to implement thanks to Adafruit’s DHT.h library. We can also add a BMP180 which will create a barometer on Domoticz. For controlling the GPIO, you can use a single LED or a relay.

esp8266 Wemos D1 mini Any ESP8266 ESP-12 module, for example Wemos D1 Mini
chargeur raspbery pi 3 5v 3000ma 5V/3A micro-usb power supply
 BMP180 Atmospheric pressure

BMP180

Broches DHT22 Temperature and humidity sensor

DHT11 or DHT22

wemos d1 mini dht22 shield Shield DHT22 or DHT11 for Wemos D1 Mini.

The sensor is connected to pin D4 (GPIO2)

wemos d1 mini relai shield Relay shield  (250VAC/10A or 30VDC/10A) for Wemos D1 Mini.

The relay is connected to pin D1 (GPIO5)

jumper dupont Jumper Dupont
breadboard Breadboard
led 3mm Led (optional, follow the WiFi activity)
resistance 220ohms Resistor 220Ω (optional)

Circuit

Composant Pin Arduino Pin ESP8266 Pin (Wemos D1 mini)
DHT22 (shield Wemos D1 Mini) VCC 3V3 3V3
GND GND G
Data GPIO2 D4
BMP180 VCC 3V3 3V3
GND GND G
SDA GPIO4 D2
SCK GPIO5 D1
Led on GPIO (D7) Pole + GPIO13 D7
Pole – GND G

ESP8266 DHT22 BMP180 Shield Relay DOMOTICZ ESP8266HTTPCLIENT

Changing the I2C bus pins on the ESP8266

Before going any further, you have noticed that the Wemos relay card uses pin D1. Pin D1 is shared with the SCK pin of the I2C bus. It will therefore be necessary to move the pin of the I2C bus to be able to use the relay shield at the same time. To do this, we use the Wire.h library

Declare the library at the beginning of the program

#include <Wire.h>

In the setup(), the I2C bus is initialized by specifying the new pins. You must start wire.begin() before you initialize the BMP180 object with the bmp.begin() command. As usual, you do not need to look for the equivalent pins of the Arduino, you directly indicate the pins of the ESP8266, the conversion will be done automatically. Here, I moved by pin D1 (SCK) to pin D3, which gives

Wire.begin (D2, D3);

That’s all, you can now move the I2C bus over the pins you want.

Driving the ESP8266 GPIO from Domoticz

We will now drive the GPIO of the ESP8266 from Domoticz. You can also make complex queries by integrating HTTP requests into your Lua scripts. Here, we will simply activate the relay shield for Wemos D1 mini. For less than 8 €, you can make a connected lamp or a presence simulator using a scenario.

Arduino Code / ESP8266

To receive commands from Domoticz, we will add a server part to the previous Arduino code. Add the ESP8266WebServer library to the previous code and create a server listening on port 80.

#include <ESP8266WebServer.h>
ESP8266WebServer server ( 80 );

In the startup add a route to /gpio after connecting to the Wi-Fi network. This server will simply listen to calls on a page / gpio. Each call on this page will trigger the updateGpio () function.

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

The updateGpio () function decodes the URL and updates the status of the corresponding GPIO. The function server.arg (“id”) allows to retrieve the identifier of the GPIO andserver.arg (“state”), the state of the latter.

Note. One might be tempted to answer Domoticz by asking him to change the state of the switch (/json.htm?type=command&param=switchlight&idx=99&switchcmd=On ) but this causes an infinite loop! It is kind of a shame.

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 !");
  }
}

Here is the complete Arduino code that you can upload after changing your settings:

  • ssid and WiFi password
  • IP address of Domoticz server (host) and port if different from 8080
#include <ESP8266WebServer.h>
#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
#include <DHT.h>
#include <Adafruit_BMP085.h>
#include <Wire.h>

#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 ) {
          hum_stat = 0;
        } else if ( h > 45 & h <= 70 ) {
          hum_stat = 1;
        }

        if ( pa > 1030 ) {
          bar_for = 1;  
        } else if ( pa > 1010 & pa <= 1030 ) {
          bar_for = 2;
        } else if ( pa > 990 & pa <= 1010 ) {
          bar_for = 3;
        } else if ( 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();
}

Domoticz configuration: create a virtual switch

Return to the hardware to add a new virtual sensor.

Note. Give it a name without spaces or special characters or accented if you want to create a script in Lua.

domoticz esp8266 interrupteur shield relai wemos switch virtuel

Driving the GPIO with an action

To turn on, turn off a lamp without any other condition, the easiest and fastest is to configure an action depending on the state of the switch. Go to the Switches tab and open the device in edit mode.

In the Action On field, paste the following URL by replacing IP_ESP8266 with your

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

For the Off state, the state will simply be set to 0.

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

Save.

domoticz esp8266 shield relai wemos d1 mini url http action on off

Driving the GPIO using a Lua script

The other way to proceed and create a Lua script. It takes a little longer to set up, but we have all the power of the language at our disposal. If you do not know the Lua scripts, you can start with this tutorial.

Log in to your Domoticz server in SSH and go to the Lua scripts directory

cd ~/domoticz/scripts/lua

We will create u script which triggers each time the switch is changed. By convention, the file will have to be named script_device_DeviceName.lua , which gives

sudo nano script_device_GPIO_D1.lua

Paste this Lua code. Change the IP address of your ESP8266 into the baseurlESP8266 variable. The script tests the value of the RelayD1 device. If it is equal to On, one supplements the url by indicating the id=D1 with the state to 1, 0 otherwise. You can set the status to On, ON, ON … you just have to test the value of the variable in the Arduino code.

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

Secure communication

It is possible to improve the security of exchanges between Domoticz and ESP8266. You certainly noticed that sending data to Domoticz is done without any authentication. Considering that the home automation server is never exposed to the Internet and that the Wi-Fi network is secure, this is not too much of a problem. On the other hand if you want to make Domoticz accessible from the internet, you will have to improve that. Here, we will not go so far as to encrypt the exchanges, it is possible but outside the scope of tutorial.

Local networks (no username and password)

In most cases, your connected objects based on ESP8266 should be on the same network as the Domoticz server. In this case, the easiest way is to add the IP addresses of your connected objects to the list of devices allowed to use the API in authorization. To do this, go to Settings and then Settings and complete the Networks field.

Note. In this case, it is preferable to assign a fixed IP address to the ESP8266 because in the event of a router breakdown, the IP address of the router could change, and therefore no longer work.

Authentication by user and password (Arduino code)

If you have protected the access of your Domoticz by an identifier and a password, you only need to modify the host variable

domoticz-securite-identifiant-mot-de-passe

The host variable will then take the form

username:password@domoticz-ip

Note. This protection works only in the direction ESP8266 towards Domoticz. If you want to secure the control of the GPIO, it will be necessary to integrate a public key that will simply have to check in Arduino code.

Add a token in the HTTP request

These two security methods work only in the direction ESP8266 towards Domoticz. It is not (yet) possible to encrypt the web server of the ESP8266. To secure the commands, the easiest way is to add a public key or a token to be tested in the Arduino code. It’s a pretty basic security but it’s always better than nothing.

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

domoticz relay shield wemos d1 mini request tcp ip

Here you can now send data, sensor states and drive the GPIO of the ESP8266 from a Domoticz server. Next time we’ll see how to do it for Jeedom.

Subscribe to the weekly newsletter

No spam and no other use will be made of your email. You can unsubscribe anytime.

We will be happy to hear your thoughts

Leave a Reply

DIY Projects
%d bloggers like this: