This basic example of an asynchronous web server for use in the esp8266 loading it from the Sketch
of arduino thanks to a firmware flashing we can reprogram it as if it were an atmega328p
, and forgetting about the tedious AT commands as we do here flashing-esp8266-fu-k-at-commands we will use the DHT22 sensor which is much more accurate than its archenemy the DHT11, we will need a serial converter like the one contained in the arduino through TX/RX
pins otherwise we would have to buy a very cheap usb-serial ttl
converter.
These are brief characteristics of both sensors:
DHT-22 pinout
MB102 adjustable power supply
We will use this 3.3v | 5v
supply with an external 2000mAh transformer plus 12vc output. You can see on the power supply MB102
, the jumper that allows us to get 3.3v, can be checked with a multimeter with alligator bits, and or needles.
A transformer of less than 6.5vdc will not be suitable for the MB102
Without Fritzing
But this serves as a final view.
-
A 10Kohm resistor (many use 4.7k) as pull-up between DATA and VCC (3.3v).
-
I get the GND from the power supply.
Writing the asynchronous web server code (AsynchronousWebServer)
We will use the following libraries:
#include <ESP8266WiFi.h> (1)
#include <ESPAsyncTCP.h> (2)
#include <ESPAsyncWebServer.h>
#include <ArduinoJson.h> (3)
#include <DHTStable.h> (4)
1 | For wifi connection (ESP8266WiFi) |
2 | For the asynchronous server as well as the ESPAsyncWebServer |
3 | Creation of the (ArduinoJson) json for the Rest api |
4 | Where <DHTStable.h> is a more up to date lib, and of the humidity and temperature sensor <DHTStable.h> |
#define DHT22_PIN 4 (1)
DHTStable DHT;
1 | We define the variables to use the DHT22 sensor pin. |
AsyncWebServer server(8081); (1)
1 | We set the server port to 8081, I have the other typical ones in use XD. |
//Endpoints
const char* TEMPERATURES = "/async-esp8266/api/v1/dht22/temperatures"; (1)
const char* HUMIDITIES = "/async-esp8266/api/v1/dht22/humidities"; (2)
const char* LED_STATUS = "/async-esp8266/api/v1/led"; (3)
1 | Temperature endpoints. |
2 | Humidity endpoints. |
3 | Endpoints for changing the led state. |
Configuration of wifi network, we place name and password.
const char* ssid = "Tu red";
const char* password = "misuperhax0rpassword";
//esperando por conexión
while (WiFi.status() != WL_CONNECTED) { (1)
delay(1000);
Serial.println("Connecting to WiFi..");
}
1 | While trying to connect to the wifi network, and notifying the console. |
void loop(void) {
DHT.read22(DHT22_PIN); (1)
t = DHT.getTemperature();
h = DHT.getHumidity();
Serial.print("Humidity: ");
Serial.print(h);
Serial.println(HUMIDITY);
Serial.print("Temperature: ");
Serial.print(t);
Serial.println(TMP);
delay(2000); (2)
}
1 | Here is the loop() function needed to read the sensor. |
2 | Set a delay of 2 seconds. |
The initRoute function simply greets with a text greeting when visiting the main url /
.
//Hello world!
void initRoute() {
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request) {
request -> send(OK_HTTP, TEXT_PLAIN, "Welcome webserver Esp8266");
});
}
Temperature endpoint
/async-esp8266/api/v1/dht22/temperatures
//Temperaturesº
void temperatures() {
server.on(TEMPERATURES, HTTP_GET, [](AsyncWebServerRequest * request) {
String json;
StaticJsonDocument<300> doc;
doc["sensor"] = "DHT-22";
doc["type"] = "AM2302";
doc["temperature"] = t;
serializeJson(doc, json);
request -> send(OK_HTTP, APPLICATION_JSON, json);
});
}
Humidity endpoint
/async-esp8266/api/v1/dht22/humidities
//Humidities%
void humidities() {
server.on(HUMIDITIES, HTTP_GET, [](AsyncWebServerRequest * request) {
String json;
StaticJsonDocument<300> doc;
doc["sensor"] = "DHT-22";
doc["type"] = "AM2302";
doc["humidity"] = h;
serializeJson(doc, json);
request -> send(OK_HTTP, APPLICATION_JSON, json);
});
}
The handeLED function will be used to see the state of the led, turn it on and off, typically updating it on pin 2
to HIGH or LOW, depending on the query parameters.
// On/off Led
void handleLED() { (1)
//Show led status
server.on(LED_STATUS, HTTP_GET, [](AsyncWebServerRequest * request) {
ledstatus = digitalRead(LED_PIN);
if (ledstatus == HIGH) {
//status is ON
request -> send(OK_HTTP, TEXT_PLAIN, "Status ON");
} else {
//status is Off
request -> send(OK_HTTP, TEXT_PLAIN, "Status OFF");
}
});
//async-esp8266/api/v1/led?id=2&newstatus=on //ON
//async-esp8266/api/v1/led?id=2&newstatus=off //OFF
server.on(LED_STATUS, HTTP_PUT, [](AsyncWebServerRequest * request) {
String id = request-> arg("id"); (2)
String newstatus = request-> arg("newstatus"); (3)
if (id.toInt() == LED_PIN && newstatus.equalsIgnoreCase("on")) {
Serial.println("PIN HIGH");
digitalWrite(LED_PIN, HIGH);
request -> send(OK_HTTP, TEXT_PLAIN, oK);
} else if (id.toInt() == LED_PIN && newstatus.equalsIgnoreCase("off")) {
Serial.println("PIN LOW");
digitalWrite(LED_PIN, LOW);
request -> send(OK_HTTP, TEXT_PLAIN, oK);
} else {
request -> send(400, TEXT_PLAIN, "Bad Request");
}
});
}
1 | Function to manage the led control, it should be factored a little more, divide better in other functions. |
2 | We obtain the id of the led. |
3 | By means of the status, we turn it off or turn it on. |
Complete code
Honestly looking at this now, after all this time, instead of using PUT, I would use the http PATCH method plus a body. |
Endpoints
Operation | URI | ||||
---|---|---|---|---|---|
|
/async-esp8285/api/v1/dht22 |
||||
|
/async-esp8285/api/v1/dht22/temperatures |
||||
|
/async-esp8285/api/v1/dht22/humidities |
||||
|
/async-esp8285/api/v1/led
|
/**
*
* Make simple Asynchronous webserver using DHT22 for log temperature and humidity.
*
*/
#include <ESP8266WiFi.h>
#include <ESPAsyncTCP.h>
#include <ESPAsyncWebServer.h>
#include <ArduinoJson.h>
#include <DHTStable.h>
#define DHT22_PIN 4
DHTStable DHT;
AsyncWebServer server(8081);// Create a asynchronous webserver object that listens for HTTP request on port 8081
int led_status = 0;
float t = 0;
float h = 0;
const int LED_PIN = 2;
const int OK_HTTP = 200;
//Endpoints
const char* DHT22 = "/async-esp8285/api/v1/dht22";
const char* TEMPERATURES = "/async-esp8285/api/v1/dht22/temperatures";
const char* HUMIDITIES = "/async-esp8285/api/v1/dht22/humidities";
const char* LED = "/async-esp8285/api/v1/led";
const char* DHT_22 = "DHT-22";
const char* AM2302 = "AM2302";
const char* CENTIGRADE = "ºC";
const char* PERCENTAGE = "%";
const char* TEXT_PLAIN = "text/plain";
const char* APPLICATION_JSON = "application/json";
const char* ON = "ON";
const char* OFF = "OFF";
const char* ID = "id";
const char* NEW_STATUS = "status";
const char* SENSOR = "sensor";
const char* TYPE = "type";
const char* TEMPERATURE = "temperature";
const char* HUMIDITY = "humidity";
//Wifi network credentials
const char* ssid = "Filomena 2.4";
const char* password = "zAHF4n+MMHniN*G"; //aqui les dejo mi contraseña para que se conecten, wifi free :)
void setup(void) {
Serial.begin(115200);
pinMode(LED_PIN, OUTPUT);
delay(10);
Serial.println('\n');
WiFi.begin(ssid, password);
//wait for connection
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.println("Connecting to WiFi..");
}
Serial.println('\n');
Serial.print("Connected to ");
Serial.println(WiFi.SSID());
Serial.print("IP address:\t");
Serial.println(WiFi.localIP());
initRoute();
temperatures();
humidities();
dht22();
handleLED();
handleNotFound();
server.begin();// Actually start the server
Serial.println("HTTP server started");
}
void loop(void) {
DHT.read22(DHT22_PIN);
t = DHT.getTemperature();
h = DHT.getHumidity();
Serial.print("Humidity: ");
Serial.print(h);
Serial.println(PERCENTAGE);
Serial.print("Temperature: ");
Serial.print(t);
Serial.println(CENTIGRADE);
delay(2000);
}
//Welcome webserver Esp8266!!!
void initRoute() {
server.on("/", HTTP_GET, [](AsyncWebServerRequest * request) {
request -> send(OK_HTTP, TEXT_PLAIN, "Welcome webserver Esp8266");
});
}
//Temperaturesª
void temperatures() {
server.on(TEMPERATURES, HTTP_GET, [](AsyncWebServerRequest * request) {
String json;
StaticJsonDocument<300> doc;
doc[SENSOR] = DHT_22;
doc[TYPE] = AM2302;
doc[TEMPERATURE] = t;
serializeJson(doc, json);
request -> send(OK_HTTP, APPLICATION_JSON, json);
});
}
//Humidities%
void humidities() {
server.on(HUMIDITIES, HTTP_GET, [](AsyncWebServerRequest * request) {
String json;
StaticJsonDocument<300> doc;
doc[SENSOR] = DHT_22;
doc[TYPE] = AM2302;
doc[HUMIDITY] = h;
serializeJson(doc, json);
request -> send(OK_HTTP, APPLICATION_JSON, json);
});
}
//DHT22 humidities% and temperaturesª
void dht22() {
server.on(DHT22, HTTP_GET, [](AsyncWebServerRequest * request) {
String json;
StaticJsonDocument<300> doc;
doc[SENSOR] = DHT_22;
doc[TYPE] = AM2302;
doc[TEMPERATURE] = t;
doc[HUMIDITY] = h;
serializeJson(doc, json);
request -> send(OK_HTTP, APPLICATION_JSON, json);
});
}
// On/off Led
void handleLED() {
//Show led status
server.on(LED, HTTP_GET, [](AsyncWebServerRequest * request) {
led_status = digitalRead(LED_PIN);
if (led_status == HIGH) {
String json;
StaticJsonDocument<300> doc;
doc[ID] = LED_PIN;
doc[NEW_STATUS] = ON;
serializeJson(doc, json);
request -> send(OK_HTTP, APPLICATION_JSON, json);
} else {
String json;
StaticJsonDocument<300> doc;
doc[ID] = LED_PIN;
doc[NEW_STATUS] = OFF;
serializeJson(doc, json);
request -> send(OK_HTTP, APPLICATION_JSON, json);
}
});
//async-esp8266/api/v1/led?id=2&status=on //ON
//async-esp8266/api/v1/led?id=2&status=off //OFF
server.on(LED, HTTP_PUT, [](AsyncWebServerRequest * request) {
String id = request-> arg(ID);
String new_status = request-> arg(NEW_STATUS);
if (id.toInt() == LED_PIN && new_status.equalsIgnoreCase(ON)) {
Serial.println("PIN HIGH");
digitalWrite(LED_PIN, HIGH);
String json;
StaticJsonDocument<300> doc;
doc[ID] = LED_PIN;
doc[NEW_STATUS] = ON;
serializeJson(doc, json);
request -> send(OK_HTTP, APPLICATION_JSON, json);
} else if (id.toInt() == LED_PIN && new_status.equalsIgnoreCase(OFF)) {
Serial.println("PIN LOW");
digitalWrite(LED_PIN, LOW);
String json;
StaticJsonDocument<300> doc;
doc[ID] = LED_PIN;
doc[NEW_STATUS] = OFF;
serializeJson(doc, json);
request -> send(OK_HTTP, APPLICATION_JSON, json);
} else {
request -> send(400, TEXT_PLAIN, "Bad Request");
}
});
}
//404
void handleNotFound() {
//Error 404 not found
server.onNotFound([](AsyncWebServerRequest * request) {
request->send(404, TEXT_PLAIN, "Sorry, 404 not found.");
});
}
// -- EOF --
With respect to safety
It would be a very good idea to add authentication and ssl certificates or forced redirection via https with a reverse-proxy nginx, so we don’t have to put so much code in the bug.