The ability to communicate with your IoT things — to send commands and receive responses is an essential pillar of your “connected” system. You need a network link to control things and to read sensors. Two of the most common Internet to machine communication protocols used with the ESP8266 and other MCUs are http and MQTT.
There are advantages and drawbacks using either one of these methods.
So which one is better?
For an assessment, I created a simple Arduino IDE sketch with just two metrics in mind for the evaluation. First was the simplicity of the application code. How clean was the framework needed to implement the server?
The other concern was latency. That is, how long is required from the time of a client request to server reply? I was curious to measure this time. Is the delay magnitude in the order of milliseconds, or seconds?
I started out with the intent on creating two sketches; one of an http server and one for MQTT. But what became apparent was that other than the code needed to connect, read and write to the protocol, the software was almost identical. So for simplicity and efficiency, the http and MQTT servers were combined into a single sketch.
This also made the evaluation easier-there was no need to reload the firmware to switch protocols.
The typical Arduino IDE based http server requires the use of two class objects. These objects are defined in WiFi.h for Arduino based systems and the ESP8266WiFi.h library for the ESP8266.
The major shortcoming with the Arduino IDE library is the need in the user sketch to poll for new connections in the loop(). It would be far more efficient to register a callback function that is executed upon an external client connection. Like the EspressIf SDK Iot_demo example web server.
This constraint alone would be sufficient justification to use the Espressif SDK over the Arduino IDE for all but the simplest Web Server application.
Fortunately, however, there is a way to use the SDK callbacks with the Arduino IDE. Here is how it is done. That is just what we will use for comparing the http and MQTT servers. The sketch for this test is just a reuse of that sketch with the added code needed to support MQTT. The Dual MQTT & HTTP Web Server code is here.
When looking at the code structure for the MQTT broker vs the Arduino Wifi library vs the SDK API, the most efficient design was the SDK API. While all 3 methods worked well, the SDK design uses a callback to service client connections without any code needed in the loop() function.
The Arduino Wifi library requires polling for connections each iteration of loop().
And sure, the MQTT broker server, like the SDK API, also uses callbacks. But it still requires the execution of “client.loop()” in the sketch’s loop() function. This consumes bandwidth which undoubtedly will add latency to other tasks added to loop().
If loop() latency becomes an issue in your sketch, use of the SDK API web server callbacks will minimize the delays.
Response Delay Evaluation
Twelve requests were made for each of the three server setups. The average of the twelve, and the average of ten with the high and low readings removed are shown in this table:
|HTTP: WiFi Library||HTTP: SDK API||MQTT|
|Average of 12||463||91||380|
|Average of 10(w/o Hi & Lo)||447||62||366|
The time is measured in milliseconds. From this experiment, it is clear that the SDK API offers significantly less latency than either the Wifi Library or MQTT. From this, it should be clear that callbacks that do not use the sketch loop() function are more efficient.
There are advantages and shortcomings when using either MQTT or http for web server applications. MQTT offers a clean and simple code interface, but it does require the use of a broker. That adds an additional layer of complexity and potential failure to your system.
In my opinion, MQTT is best suited to be used for data distribution, not as a web server. The MQTT publish/subscribe model works great to simultaneously send information from one source to many consumers. If speed is critical, the EspressIf SDK API is the best option to use the ESP8266 as a web server.
Great comparison, thank you. But why is there such a difference between callbacks and polling? Iterating through an idle loop should be really fast. And could you also test CoAP? It should perform well, since it is based on UDP.
Thanks for your comment Jerzy. Callback always tend to be more efficient than polling. We also do not know exactly all the tasks loop() services between each iteration…under the hood.
I also apprecieate your bringing my attention to CoAP. I checked it out, for my first time, and added it to the server for a side-by-side comparison. The results are in this post.
Hi, have you looked at the ESP8266WebServer in the ESP8266 Arduino standard library set ? Supports the event driven callback approach which as you mention is much more elegant than a big polling/parsing/decision block.
Here’s a simple example using the library
Thanks for your comment and information. I am aware of the Web server library but have not used it…yet. It would be great to hear of anyone’s experience regarding stability and heap usage using ESP8266webserver.
I did a test of polling once per second in loop(), which I implemented by a Chromo.h timer (e.g. each time the seconds changed I called a processHTTP() function. I did this because my program advances an LED display and emits a short "beep" at every second change. Most of the time this works fine (average 60ms) but when I get a blank HTTP request (e.g. "" after applying string.trim() ) it takes just over a second, which causes a noticable hickup in the clock/beeper.
This is the same issue I just posted in http://internetofhomethings.com/homethings/?p=470 post. I'm only posting it twice, but the in the context of this discussion I thought it was applicable as another option to work around this issue in similar situations.
I could not compile your projects. the problem is redeclaration of several functions in webserver/memmanager.h previously declared in esp8266core.I am using esp8266 core v2.3 and I've tested then with Arduino ide 1.83 and 1.68.
thanks in advance
Using Arduino 1.8.2, I was able to compile the project by updating the prototype for external function pvPortZalloc which changed since this was initially posted.
//void * pvPortZalloc(int size);
void * pvPortZalloc(int size,char *, int);
Please also not that the library PubSubClient has been added to the repository as it was initially missing. This library must be added to your Arduino IDE library for the project to compile.
Did you get it to work?
Yes. It was way easier than I thought.
I just followed the directions here to create a simple Hello World Android App using Android Studio on a laptop running Windows 10:
This is what my Android phone looked like after installing and running the app:
From this, building an app with an MQTT interface should be straight-forward.
Finally got around to posting some info on making an MQTT Android App.