Arduino-esp32 course – Espressif is on the www WebServer vs HttpClient – Chapter 4

As a preamble I wanted to make clear that is not my intention to teach C or C++ here, since they are very good online resources for that, and more to make my point in some easy ways to get the most of espressif/arduino-esp32 Framework.

In chapter 2 it was explained how to connect the ESP32 to WiFi so I thought it would be great to make an additional chapter that makes use of the connection in both directions:

  1. WebServer class – the ESP32 will listen on a port and reply or react to your query
    Additionally, we will use the ESPmDNS class to enable multicast DNS
  2. HttpClient class – it will send a GET or POST request to an endpoint

For the HttpClient I will make a special endpoint that it will be available in a subdomain of fasani.de and it will just answer with the time (HH:MM). Please note that after chapter 3 I will only focus on ESP32 since it was already explained how you can write code that works in both Espressif chips ESP8266 or ESP32 using Platformio environments and #ifdef conditionals.

1. WebServer example: ESP32 listens on port 80

The first example will be very simple and to the point. We will just take as a base what we wrote in chapter 2 to connect to WiFi and we will extend it using WebServer class. Once the ESP32 is online and we got the IP Address in the Serial output we will hit the route: http://ESP_IP_ADDRESS/switch

And in this route, using WebServer event handlers, we are going to toggle a GPIO high and low. Pretty simple, but powerful since if instead of a LED, we could use a relay that turns a 220v light or any other device On/Off via WiFi, so you can control it from any other terminal connected to the same WiFi Network. Using your imagination, you may build multiple endpoints that perform different things using predefined routes and modifying this example.

#include "Arduino.h"
#include <WiFi.h>
#include <ESPmDNS.h>  // multicast DNS
#include <WebServer.h>
#define LED_GPIO 25   // Update to a internal LED or just connect one with a resistance in that GPIO
int lostConnectionCount = 0;
char apName[] = "fasani";
bool switchState = false;
WebServer server(80); // port where we start the server

// Callback see defineServerRouting
void onServerSwitch(){
   switchState = !switchState;
   digitalWrite(LED_GPIO, switchState);
   String switchStatus = "OFF";
   if (switchState) {
     switchStatus = "ON";
   }
   server.send(200, "text/html", switchStatus);
}

void onServerNotFound(){
  Serial.println("404");
  server.send(200, "text/html", "404 this route is not defined on "We could not read the time.\nPlease check in the browser that the given url: %d is correct anddefineServerRouting()");
}

// ROUTING Definitions. Add your server routes here
void defineServerRouting() {
  server.on("/switch", HTTP_GET, onServerSwitch);
  server.onNotFound(onServerNotFound);
}

/** Callback for receiving IP address from AP */
void gotIP(system_event_id_t event) {
  Serial.println("Online. Local IP address:");
  Serial.println(WiFi.localIP().toString());

  MDNS.begin(apName);
  MDNS.addService("http", "tcp", 80);
  Serial.println(String(apName)+".local mDns started");
  defineServerRouting();
  server.begin();

  Serial.println("Server started");
}

/** Callback for connection loss */
void lostCon(system_event_id_t event) {
  ++lostConnectionCount;
  Serial.printf("WiFi lost connection try %d to connect again\n", lostConnectionCount);
  WiFi.begin(WIFI_SSID, WIFI_PASS);
  if (lostConnectionCount==4) {
    Serial.println("Cannot connect to the internet. Check your WiFI credentials");
  }
}

void setup() {
  Serial.begin(115200);
  Serial.println("setup() started let's connect to WiFI");
  pinMode(LED_GPIO,OUTPUT);
  Serial.printf("WiFi name: %s\nWiFi pass: %s\n", WIFI_SSID, WIFI_PASS);
// Start our connection attempt
  WiFi.begin(WIFI_SSID, WIFI_PASS);
// Event driven WiFi callbacks
// Setup callback function for successful connection
  WiFi.onEvent(gotIP, SYSTEM_EVENT_STA_GOT_IP);

// Setup callback function for lost connection
  WiFi.onEvent(lostCon, SYSTEM_EVENT_STA_DISCONNECTED);
}

void loop() {
  // Run our server engine
  server.handleClient();
}

Note: Only Linux and Mac support mDNS out of the box. If you use windows you will need to install additional software for that. Now since we use a multicast DNS server if we are using a client that supports it once we upload that code to an ESP32 we could access it from this 2 URLs:

  1. http://ESP_IP_ADDRESS/switch
  2. http://fasani.local/switch

Please note that even that WordPress makes the links above are not clickable and I also used fasani as ApName as shameless self-promotion. Please feel free to change it to your own updating the apName char variable.

This little program will just connect to WiFi, start a mDNS server and a WebServer in port 80, define the route /switch and simply turn a GPIO High and give 3.3v (ON) or Low 0v (OFF) to a GPIO. I just added a function where the routes are defined, since I’m a web developer, and I would like to emulate how other Web frameworks do to keep the routing in a single place. It’s useful, both for the program and for the documentation, to have a single function to place all the actions that your Firmware will support. This example is very simple but it has potential since you can expand it with as many actions you want, and not only turn High or Low a Gpio but also change variables using your server routes, or any other thing you desire.

2. HttpClient: The ESP32 will make a GET request

For this I prepared a very simple endpoint:

http://fs.fasani.de/time.php -> Will return the time in Europe/Berlin as default
http://fs.fasani.de/time.php?tz=America/Los_Angeles will return the time of that timezone

Of course you can use any timezone you want. The source of time.php is just 4 lines and you can put it in any server that supports PHP no matter what version:

<?php
$tz = isset($_GET['tz'])?$_GET['tz']:'Europe/Berlin';
date_default_timezone_set($tz);
echo date("H:i");

So this example will be even easier than number 1. It will simply connect to WiFi and query this URL to print in the Serial output the current time. The applications can be endless, for example, you can return only the hour as an integer, and your program can decide to turn on something depending on the hour.

#include "Arduino.h"
#include <WiFi.h>
#include <HTTPClient.h>
int lostConnectionCount = 0;
HTTPClient http;
String url = "http://fs.fasani.de/time.php?tz=Europe/Berlin";

void gotIP(system_event_id_t event) {
  Serial.println("Online. Local IP address:");
  Serial.println(WiFi.localIP().toString());
  http.begin(url);
  int httpCode = http.GET();  //Make the request
  Serial.printf("http status:%d\n", httpCode);

  if (httpCode == 200) { 
     String response = http.getString();
     Serial.printf("The time now is: %s\n", response);
  } else {
    Serial.printf("We could not read the time.\nPlease check in the browser that the given url: %s is correct and replies with an HTTP 200 OK status", url);
  }
}

void lostCon(system_event_id_t event) {
  ++lostConnectionCount;
  Serial.printf("WiFi lost connection try %d to connect again\n", lostConnectionCount);
  WiFi.begin(WIFI_SSID, WIFI_PASS);
  if (lostConnectionCount==4) {
    Serial.println("Cannot connect to the internet. Check your WiFI credentials");
  }
}

void setup() {
  Serial.begin(115200);
  Serial.println("setup() started let's connect to WiFI");
  WiFi.begin(WIFI_SSID, WIFI_PASS);
  WiFi.onEvent(gotIP, SYSTEM_EVENT_STA_GOT_IP);
  WiFi.onEvent(lostCon, SYSTEM_EVENT_STA_DISCONNECTED);
}

void loop() {
}

I hope this two easy examples will serve you to build more powerful things on top. I will be monitoring the commentaries if you want to achieve things that are not explained here.
In the next chapters we will explore more possibilities, based on my last 2 years journey, but also on your feedback.

Cordova cross platform mobile applications

After the small Chrome App experience that resulted in a very compact app that reads Video and sends an UDP binary stream to ESP32 Led controllers I decided to start learning how to program a real mobile app.
Real because I find that the way to do it must end in the App Store and the user should be able to install it with a few clicks.
This start guide is only valid for Linux but it could be a similar approach in Mac.

1.- Install Java 8 SDK
https://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html
2.-Cordova
https://cordova.apache.org/#getstarted

It’s very straight-forward to start if you have previous html/javascript experience building a web page.

In this github repository:
https://github.com/martinberlin/udpx-app

I’m building my very first Android app. Follow the commits and watch the Repository to see my new steps and also my failures in this new world.

This is a preview of how the app looks like in it’s first version:

udpx Android application is available in the Play store.
udpx app

Soon more posts will follow explaining how to interface with Android OS (Camera as an example). There will be soon more issues to expand and implement in this repository. And my new philosophy to build Firmware for Espressif chips will be simply:

“One firmware, one mobile application”

Meaning that every firmware will have his app, where you can configure and test it, just with one click install in google Play store and setting up some very easy configuration. Starting from WiFi credentials using BLE (Bluetooth low energy) and setting up the App IP address as a last step.

My goal at last, is that internet of the things is easy to use, and not something where you need a 20 minutes complicated setup to start using something. So the mission is that for first weeks 2020 all master branches from our main ESP32 Firmwares like udpx and Remora should be bluetooth configurable.

Starting to do smart-home appliances with ESP-Mesh

ESPMesh reduces the loading of smart light devices on the router by forming a mesh with the smart light device.”

I’ve started months ago getting some smart lights for home and I’ve chosen Osram since it was about half the price than Phillips VUE. But the thing with this systems, though they work nice and with very little configuration, is that you need always a “Gateway”. A central point that receives signals and then send via Radio frequency to the lights what they have to do.

The Espressif ESP-Mesh took a different approach: Every device is a network member making a Mesh of interconnected devices. There is no gateway because there is no need for one.

There is also a very important point that is very interesting if you are a maker like me. It’s open source. That means you don’t need to buy a 60€ light to test it, you can just go to the ESP-Mesh github repository and download ESP-Mesh-Light example to compile it in one of your existing ESP32 Boards. Then you can get easily something like this working :

So what I’m working on the free time to take a rest from another pending projects is to take this PWM output and amplify it using a 74HC125 Quad Bus Buffer to power more than one led.

For those interested in reproducing this example:

https://github.com/espressif/esp-mdf/tree/master/examples/development_kit/light

Command lines to execute the compilation are only 2:

make menuconfig
make erase_flash flash

Compile this into your ESP32 and then download Espressif official Android App or if you are using I-phone / I-Pad just search for “ESP-Mesh”
The Mesh devices are configured using Bluetooth so keep in mind to have this enabled on your device. Instead of taking the “WiFi Manager” Approach, using an App, you have the benefit that you can just send the WiFi Credentials plus configuration directly to the ESP32.

Simple IoT image logging using BigIot.net

Since beginning of 2019 I’m participating in a project called “Low cost / low power sleep / WiFi Camera” so I purchased a couple of low cost boards, between them the LilyGO ESP 32 Camera.

ESP32 Lilygo 800×600 pix SVGA Camera. If you need a case, made one here

BigIot.net is an interesting IOT API site

Not only an API but a very interesting infrastructure that is also possible to link BIGIOT with WeChat allowing to “chat” with your device and use it for Smart home or just to check what was the last image uploaded.
In my fork of this ESP32 Camera, since the original looks a bit unmaintained without even an issue board, I added some better display information:

https://github.com/martinberlin/ESP32-Camera BIGIOT_UpdateImage.ino

This example shows how to set up an automatic camera that takes pictures every 20 seconds and sends them like an API Post push to BigIot.
So far so good, it works at first glance. The issue is that BigIOT is all in Chinese and there is no english. So if you consider that a problem then you can stop here. I didn’t because I think the Chinese know hell about this and they are leading the IoT world for a good reason.

So I translated it as I could just to register and get this pieces of information:

#define BIGIOT_API_KEY "KEYHASH" ( 智能设备 Devices -> APIKEY)
#define BIGIOT_DEVICE_ID "INTEGER"
#define BIGIOT_INTERFACE_ID "INTEGER"

BigIOT Registration -> 注册



A

After registering you just have to open the activation Email and you are good to go. Just log in the Admin Panel and try to feel at home. Most important parts are:

智能设备列表 List of your Devices -> Add a “Camera device”

数据接口列表 List of your Inputs -> This is the Interface, so just make an “Upload interface”

And that are the two IDs you need, device ID and interface ID. After that and compiling this, the small camera is going to start pushing pictures to BigIOT and you can just click on the stats on the interface area and start checking the pictures when you are away.

Very good to control for example a 3D printer that you leave at home finishing something. This is the result:

Interface statistics
BigIOT Interface statistics
ADDITIONAL INFO 

https://gitee.com/hejinlv/ESP32/blob/master/ESP32_bigiot_LED/
Here there is a great example on how to Listen to Commands to interact with WeChat