Overview
This tutorial demonstrates how Mongoose Library can be used to implement a web server on ESP32. A full source code for this tutorial is at https://github.com/cesanta/mongoose/tree/master/examples/esp32
Project structure
This example uses ESP-IDF 4.x toolchain, and therefore project structure follows a standard ESP-IDF CMake-based format:
main/
- a "main" component directory which include application codemain/CMakeLists
- a standard ESP-IDF component-level project CMake filemain/main.c
- main application file, contains Mongoose logicmain/wifi.c
- contains Wifi setup routine,wifi_init()
main/mongoose.c
- a symlink to repo'smongose.c
main/mongoose.h
- a symlink to repo'smongose.h
CMakeLists
- a standard ESP-IDF top-level project CMake filepartitions.csv
- defines a partition table for a 4MB boardsdkconfig.defaults
- default build valuesMakefile
- this Makefile is just a wrapper that invokes IDF
In the production code, mongoose.c
and mongoose.h
files should be copied
to the main/
directory instead of creating symlinks.
Build a project
Before building a project, open main/main.c
file and edit WiFi network
name and WiFi password settings:
The next step is to build a project. It is assumed you're using Linux or Mac as a workstation, and you have Docker installed.
Start a terminal in the project's directory and run make build
command:
$ git clone https://github.com/cesanta/mongoose
$ cd mongoose/examples/esp32/device-dashboard
$ make build
In order to flash a built firmware to your ESP32 board, plug it in the USB
and execute (change /dev/ttyUSB0
to an actual serial port on your system):
$ cd build
$ esptool.py --chip esp32 -p /dev/ttyUSB0 -b 460800 --before=default_reset --after=hard_reset write_flash --flash_mode dio --flash_freq 40m --flash_size 2MB 0x8000 partition_table/partition-table.bin 0x1000 bootloader/bootloader.bin 0x100000 mongoose-esp32-example.bin
$ cu -l /dev/ttyUSB0 -s 115200
When done, start a browser on http://IP_ADDRESS
where IP_ADDRESS
is the
board's IP address printed on the serial console. You should see a directory
listing with hello.txt
file.
Main function
The main()
function has three blocks:
- Mount a filesystem and write a sample file
- Initialise WiFi
- Run Mongoose
Mount filesystem
A firmware that is built does not have a filesystem image flashed, but it
has SPIFFS filesystem support. So the following piece of code initialises
a filesystem, and writes a file hello.txt
using
mg_file_printf() API call. This file will
be shown on a browser's directory listing.
Initialise wifi
There we call a wifi_init()
function which is defined in main/wifi.c
.
That is a blocking function, i.e. it does not return until the board gets
IP address:
Run Mongoose
Next goes Mongoose. Note that it should be run after network initialisation is complete - which is true in our case. A logic is standard - initialise event manager, start a listener on port 80, and fall into an infinite event loop:
The event handler function handles /api/state
RESTful handler which reports a
free RAM. Other URIs are treated as static server requests:
There is a caveat there - we redefine FS handler. This is done because
SPIFFS is a flat file system without directory support. Therefore we
create our own filesystem which is derived from a standard POSIX FS but has
a stat()
function redefined - it returns a "directory" flag for /
: