Project Summary
This tutorial will cover how to use the ESP-Touch protocol with your ESP32 based IoT projects/devices.
Using ESP-Touch, you will no longer need to hard code Wi-Fi credentials as you can easily change it whenever you want.
We will be using the Espressif app name as EspTouch: SmartConfig for ESP8266, ESP32.
By using this app, we can easily configure our ESP32 device with a new Wi-Fi credential.
We will build an ESP32 project to store Wi-Fi credentials in EEPROM memory on a successful configuration.
Additionally, we will use the onboard Boot button on ESP32 as a reset button for erasing the stored Wi-Fi credentials and configuring a new one.
Here is the Tutorial breakdown:
- Watch the Video Tutorial
- About ESP-Touch Protocol.
- Basic WiFiSmartConfig example.
- Final WiFiSmartConfig project with storage and reset.
Watch the Video Tutorial
This tutorial is available in video format (watch below) and written format (continue reading this page).
About ESP-Touch Protocol
ESP-Touch protocol uses a SmartConfig technology.
The SmartConfigTM is a technology developed by TI to connect a new Wi-Fi-based IoT device to a Wi-Fi network.
It uses a mobile app to broadcast the network credentials from a smartphone, or a tablet, to an un-provisioned Wi-Fi device.
The major advantage of using ESP-Touch is that there is no need to create an Access Point (AP) with a known SSID or Password in ESP32.
Therefore ESP-Touch protocol provides a seamless way to configure Wi-Fi devices connecting to a router. It is very user-friendly when it comes to headless systems. It only takes few clicks on your smartphone.
IoT device is not connected to the network initially, and the ESPTOUCH application cannot send any information to the device directly. With the ESP-TOUCH communication protocol, a device with Wi-Fi access capabilities, such as a smartphone, can send a series of UDP packets to the Wi-Fi Access Point (AP), encoding the SSID and password into the Length field of each of these UDP packets. The IoT device can then reach the UDP packets, obtaining and parsing out the required information. As per the ESP-Touch user guide, the data packet structure looks like this.
And the protocol itself is lightweight compared to the Wi-Fi manager as the Wi-Fi manager requires a webpage code to be stored on device memory.
Prerequisites
We will use Arduino IDE for programming our ESP32 board.
If you are not familiar with Arduino IDE, then you can check our guide on
โ Getting started with Arduino IDE
For programming ESP32 using Arduino IDE, we will need to add the ESP32 board package in Arduino IDE. Follow our guide.
โ Installing ESP32 in Arduino IDE
Skip the above steps if you have already done it before.
Additionally, we will need to download an Espressif app name as EspTouch: SmartConfig for ESP8266, ESP32 for Android, or Espressif Esptouch for apple.
And if you are planning to develop your mobile application, then don’t worry as Espressif has provided all support. Have a look at the following-
- ESP Touch for Android
- ESP Touch for IOS
- ESP Touch support in Flutter
- ESP Touch support in React Native
Basic WiFiSmartConfig example
ESP32 package comes with a basic WiFiSmartConfig example for us.
Let us understand this example first.
You can navigate to this example at
File > Examples > WiFi > WiFiSmartConfig.
Note:- The example path is only visible when selecting the proper ESP32 board in Arduino IDE.
Here is the example code-
#include "WiFi.h"
void setup() {
Serial.begin(115200);
//Init WiFi as Station, start SmartConfig
WiFi.mode(WIFI_AP_STA);
WiFi.beginSmartConfig();
//Wait for SmartConfig packet from mobile
Serial.println("Waiting for SmartConfig.");
while (!WiFi.smartConfigDone()) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("SmartConfig received.");
//Wait for WiFi to connect to AP
Serial.println("Waiting for WiFi");
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("WiFi Connected.");
Serial.print("IP Address: ");
Serial.println(WiFi.localIP());
}
void loop() {
// put your main code here, to run repeatedly:
}
Upload this example code on your ESP32 board as we can see there is no hard-coded network credential in the example.
After uploading, open the serial monitor and set the appropriate baud rate.
You will see that it is waiting to be configured by SmartConfig, and it will be showing continuous dots once it enters configuration mode.
Now open the ESP-Touch app in your mobile device and connect your mobile device to your Wi-Fi router network. In android, it will also ask you to turn on location service for detecting the connected Wi-Fi SSID.
It will fetch and display the connected Wi-Fi network SSID and BSSID.
Now you need to enter the password of the connected Wi-Fi network.
Select the Multicast radio button.
And press the confirm button, you will see a popup like this.
Wait for a while, and you will see a success message in the app along with the connected ESP32 BSSID and Inet Address information.
And, on the serial monitor, you will see a message as SmartConfig received, and now it will be connected to the given Wi-Fi network.
It’s that simple, and we do not need any stored SSID or Password for ESP Access Point.
The example is not perfect to use right now, as we need to configure it whenever we restart ESP because we are not storing Wi-Fi credentials. Also, ESP will always enter in SmartConfig mode.
We will be modifying the existing code to overcome these issues.
How code works
The first step will be to include a required library for the example.
- WiFi.h library will take care of all wifi-related tasks like connecting to your Wi-Fi and SmartConfig.
#include "WiFi.h"
setup()
Inside the setup function, we will first initialize serial communication to observe data in a serial monitor.
We are using the default baud rate of 115200. But you can change it if you want.
Serial.begin(115200);
Start SmartConfig
Before starting SmartConfig, it is mandatory to put ESP into station mode.
Therefore setting Wi-Fi mode as WIFI_AP_STA.
WiFi.mode(WIFI_AP_STA);
Now, turn ON SmartConfig by using this command.
WiFi.beginSmartConfig();
And now we will be wait in while the loop until SmartConfig data is received. It means that it will stay in an infinite loop until someone configures it again with a mobile app. Therefore, making it a drawback of this particular example.
You will see a continuous dot in the serial monitor when ESP enters in this while loop.
while (!WiFi.smartConfigDone()) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("SmartConfig received.");
Once you successfully configure Wi-Fi credentials, it will automatically try to connect to the given Wi-Fi credentials.
It will enter in another while loop until it gets connected to Wi-Fi.
Serial.println("Waiting for WiFi");
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
After connection, we will be serial printing the Wi-Fi connected message along with the IP address.
Serial.println("WiFi Connected.");
Serial.print("IP Address: ");
Serial.println(WiFi.localIP());
Wala! It is that simple now; I can configure my ESP within 5 seconds.
WiFiConFig With Storage and Reset
Now, let us add a few more functionality to this example so that it becomes more reliable.
In this project, we will store the received Wi-Fi credentials in EEPROM/Flash memory. Therefore, we do not need to configure ESP every time.
Next, we will add a little check like when ESP turns ON; it will retrieve the stored Wi-Fi credentials and connect to the Wi-Fi network.
If it connects successfully, then skip entering into SmartConfig mode.
Additionally, we will use the boot button as a reset button. It will clear the stored Wi-Fi credentials and restart ESP for a new configuration.
You need to press and hold the boot button for more than 3 seconds and release it, and you have successfully reset the configuration.
Here is the complete project code.
/*
Date: 11-08-21
Code is written by: Dharmik
Configure ESP32 Wi-Fi parameters using SmartConfig
Find more on www.TechTOnions.com
*/
#include "WiFi.h"
#include "EEPROM.h"
#define LENGTH(x) (strlen(x) + 1) // length of char string
#define EEPROM_SIZE 200 // EEPROM size
#define WiFi_rst 0 //WiFi credential reset pin (Boot button on ESP32)
String ssid; //string variable to store ssid
String pss; //string variable to store password
unsigned long rst_millis;
void setup() {
Serial.begin(115200); //Init serial
pinMode(WiFi_rst, INPUT);
if (!EEPROM.begin(EEPROM_SIZE)) { //Init EEPROM
Serial.println("failed to init EEPROM");
delay(1000);
}
else
{
ssid = readStringFromFlash(0); // Read SSID stored at address 0
Serial.print("SSID = ");
Serial.println(ssid);
pss = readStringFromFlash(40); // Read Password stored at address 40
Serial.print("psss = ");
Serial.println(pss);
}
WiFi.begin(ssid.c_str(), pss.c_str());
delay(3500); // Wait for a while till ESP connects to WiFi
if (WiFi.status() != WL_CONNECTED) // if WiFi is not connected
{
//Init WiFi as Station, start SmartConfig
WiFi.mode(WIFI_AP_STA);
WiFi.beginSmartConfig();
//Wait for SmartConfig packet from mobile
Serial.println("Waiting for SmartConfig.");
while (!WiFi.smartConfigDone()) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("SmartConfig received.");
//Wait for WiFi to connect to AP
Serial.println("Waiting for WiFi");
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("WiFi Connected.");
Serial.print("IP Address: ");
Serial.println(WiFi.localIP());
// read the connected WiFi SSID and password
ssid = WiFi.SSID();
pss = WiFi.psk();
Serial.print("SSID:");
Serial.println(ssid);
Serial.print("PSS:");
Serial.println(pss);
Serial.println("Store SSID & PSS in Flash");
writeStringToFlash(ssid.c_str(), 0); // storing ssid at address 0
writeStringToFlash(pss.c_str(), 40); // storing pss at address 40
}
else
{
Serial.println("WiFi Connected");
}
}
void loop() {
// put your main code here, to run repeatedly:
rst_millis = millis();
while (digitalRead(WiFi_rst) == LOW)
{
// Wait till boot button is pressed
}
// check the button press time if it is greater than 3sec clear wifi cred and restart ESP
if (millis() - rst_millis >= 3000)
{
Serial.println("Reseting the WiFi credentials");
writeStringToFlash("", 0); // Reset the SSID
writeStringToFlash("", 40); // Reset the Password
Serial.println("Wifi credentials erased");
Serial.println("Restarting the ESP");
delay(500);
ESP.restart(); // Restart ESP
}
}
void writeStringToFlash(const char* toStore, int startAddr) {
int i = 0;
for (; i < LENGTH(toStore); i++) {
EEPROM.write(startAddr + i, toStore[i]);
}
EEPROM.write(startAddr + i, '\0');
EEPROM.commit();
}
String readStringFromFlash(int startAddr) {
char in[128]; // char array of size 128 for reading the stored data
int i = 0;
for (; i < 128; i++) {
in[i] = EEPROM.read(startAddr + i);
}
return String(in);
}
How Code Works
First, we will include all necessary libraries for this project.
- WiFi.h library will take care of all wifi-related tasks like connecting to your Wi-Fi and SmartConfig.
- EEPROM.h library will need to store data to EEPROM/Flash memory of ESP32.
#include "WiFi.h"
#include "EEPROM.h"
Defining custom function LENGTH(x) will give us a length of a char string with one incremental. We will use this function later.
And define the EEPROM size required as EEPROM_SIZE.
#define LENGTH(x) (strlen(x) + 1) // length of char string
#define EEPROM_SIZE 200 // EEPROM size
We are using the Boot button of the ESP32 board for resetting the Wi-Fi credential settings. The boot button on the ESP32 board is connected with a GPIO0 pin and has a pullup resistor.
Therefore we will define WiFi_rst as 0. If you use any other pin for the reset button, you need to add that GPIO number to the WiFi_rst variable.
#define WiFi_rst 0 //WiFi credential reset pin (Boot button on ESP32)
We are defining String variables for retrieving SSID and Password.
Additionally, we will use the rst_millis variable for counting how long the reset button is pressed.
String ssid; //string variable to store ssid
String pss; //string variable to store password
unsigned long rst_millis;
setup()
We will initialize the serial communication with desired baud rate.
Serial.begin(115200); //Init serial
Set the WiFi_rst pin as an input pin.
pinMode(WiFi_rst, INPUT);
Now, initialize the EEPROM with pre-defined EEPROM_SIZE.
Once it is initialized, we will read the stored SSID and Passwort as a String at addresses 0 and 40, respectively.
We use a user-defined function named as readStringFromFlash() for reading a string from EEPROM/flash memory.
if (!EEPROM.begin(EEPROM_SIZE)) { //Init EEPROM
Serial.println("failed to init EEPROM");
delay(1000);
}
else
{
ssid = readStringFromFlash(0); // Read SSID stored at address 0
Serial.print("SSID = ");
Serial.println(ssid);
pss = readStringFromFlash(40); // Read Password stored at address 40
Serial.print("psss = ");
Serial.println(pss);
}
Using Wi-Fi.begin function for connecting to the Wi-Fi network. We are passing Wi-Fi credentials as a String variable; therefore, we will need to use c_str(), which will returns a const char* that points to a null-terminated string.
We will add a slight delay so that ESP can connect to the Wi-Fi network.
WiFi.begin(ssid.c_str(), pss.c_str());
delay(3500); // Wait for a while till ESP connects to WiFi
After that delay, we will check that ESP32 is connected to Wi-Fi or not.
If ESP connects to Wi-Fi, then we will skip the SmartConfig code inside the if condition.
And if it fails to connect with the Wi-Fi, we will init the Wi-Fi Station mode and SmartConfig similarly done in previous example.
if (WiFi.status() != WL_CONNECTED) // if WiFi is not connected
{
//Init WiFi as Station, start SmartConfig
WiFi.mode(WIFI_AP_STA);
WiFi.beginSmartConfig();
Wait for SmartConfig data to be arrived with while loop. Once network credentials have arrived, it will try to connect to that Wi-Fi network.
//Wait for SmartConfig packet from mobile
Serial.println("Waiting for SmartConfig.");
while (!WiFi.smartConfigDone()) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("SmartConfig received.");
//Wait for WiFi to connect to AP
Serial.println("Waiting for WiFi");
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("WiFi Connected.");
Serial.print("IP Address: ");
Serial.println(WiFi.localIP());
After Wi-Fi is connected, we will read the connected Wi-Fi SSID and password with the following function.
ssid = WiFi.SSID();
pss = WiFi.psk();
Serial.print("SSID:");
Serial.println(ssid);
Serial.print("PSS:");
Serial.println(pss);
And we will store the new credentials by using another user-defined function, writeStringToFlash(). We only need to pass string data along with an address.
Serial.println("Store SSID & PSS in Flash");
writeStringToFlash(ssid.c_str(), 0); // storing ssid at address 0
writeStringToFlash(pss.c_str(), 40); // storing pss at address 40
Loop()
Inside the loop function, we will store the current millis() value in the rst_millis variable as we will use this value as a start time when someone presses the Wi-Fi reset button.
rst_millis = millis();
When we press the Boot button, the while loop condition is satisfied. Hence, the code is stuck inside the loop until the button is released.
while (digitalRead(WiFi_rst) == LOW)
{
// Wait till boot button is pressed
}
When the button is released immediately, we will check how much time we have pressed the button if time is greater than 3000mS, the if condition is satisfied.
if (millis() - rst_millis >= 3000)
Now we will erase the stored Wi-Fi credentials at addresses 0 and 40 by passing blank values to the writeStringToFlash() function.
Serial.println("Reseting the WiFi credentials");
writeStringToFlash("", 0); // Reset the SSID
writeStringToFlash("", 40); // Reset the Password
Serial.println("Wifi credentials erased");
And finally, we will trigger a software reset to the ESP32 with the following command.
Serial.println("Restarting the ESP");
delay(500);
ESP.restart(); // Restart ESP
writeStringToFlash(const char* toStore, int startAddr)
This user-defined function stores string or character array pointer in EEPROM/Flash storage of ESP32.
We need to store it in non-volatile memory; hence data stored is not erased even after power is OFF.
If we look closely at the code of this function, it is simply a for loop. It is executed as per the LENGTH() function input, and as discussed earlier, it will provide the length of a character string.
And we will use EEPROM.write() function to store each byte of character string to a particular address passed and address keep incremented.
Once for loop is executed, we will save a '\0' as a string termination. And will commit the changes so that it stores them all in memory.
void writeStringToFlash(const char* toStore, int startAddr) {
int i = 0;
for (; i < LENGTH(toStore); i++) {
EEPROM.write(startAddr + i, toStore[i]);
}
EEPROM.write(startAddr + i, '\0');
EEPROM.commit();
}
String readStringFromFlash(int startAddr)
This user-defined function reads stored character strings from the desired address in EEPROM/Flash memory.
Here we are initializing the char array name as in[128] its size is 128, which means it can only handle the string length lower than 128. you can increase the size if you need to deal with bigger strings.
Similar to storing function, it also works with a for loop. It will read all char byte one by one from the startAddr (start address).
And lastly, we will return it in the form of a String.
String readStringFromFlash(int startAddr) {
char in[128]; // char array of size 128 for reading the stored data
int i = 0;
for (; i < 128; i++) {
in[i] = EEPROM.read(startAddr + i);
}
return String(in);
}
Wrapping Up
We have seen that SmartConfig is a very efficient and straightforward way to configure network credentials in our ESP32 based IoT projects or devices.
And for configuration, ESP32 does not need any connected Wi-Fi network as the Wi-Fi manager requires.
We have tested SmartConfig with a standard Wi-Fi router, and it worked like a charm.
We have also tried this method using a mobile hotspot network, but unfortunately, it does not work.
Therefore if any of the viewers have tried it with a mobile hotspot, leave a comment below. And if you learned something new, then consider subscribing to our weekly newsletter.
nice work, good to know about this feature.
Thank you Sanwartex.
hello it say there is no library as WIFI.h so i cant get it work. Could you please help me to solve it
Hello Alper,
WiFi.h library comes with the ESP32 board package no need to install that separately.
Make sure that you have installed the ESP32 board’s packages properly in the Arduino IDE.
If you have not installed it then follow this guide for doing so
https://www.techtonions.com/installing-esp32-in-arduino-ide/
And if it is installed try removing them and reinstall them properly.
Have a nice day.
I tried the example loaded with the ESP32 board package. When I run it and try to connect with espTouch it just grinds and grinds and then I get the message “Execute Result: Not found any devices though the screen says there is one device in the device count. Using iOS version.
Hello Charies,
Make sure in your android device WIFI and Location are turned ON.
The entered passwords of your available Wi-Fi network is correct and you have selected multicast option in your App.
Try it out and if still you get an error please add a snap shot so that we can figure out.
Have a great day.
What is the variable curIn used for? You assign it in the readFromFlash function but you don’t declare it or return it.
Hello Sam,
Thank you for pointing out, there is no use of variable curIn in the program it’s written by mistake. And we have updated the code.
Have a great day.
Nice writeup!
Is anyone aware of a functional SmartConfig plugin for Ionic? I’ve only seen a few stale / half-baked attempts out there.
Thank you for the complement AutoDog.
Amazing, really useful.
I’m checking the code of the app EspTouch as I would need the option of disconnecting from the current network. Either erasing the credentials or asking again for them. It would have to be from the app as in the end I won’t have access to the hardware.
Any suggestion? Thank you!!
Hello Pablo,
Thank you for your appreciation. Espressif people have open-source their app firmware.
We have no idea what more can we do with their app but I think that we are able to send WiFi credentials so we should also be able to send some commands with the same protocol.
Let us know if you found something interesting in the same.
Happy debugging.
Hi @Dharmik,
thanks a lot for this fantastic development of EPS-Touch. I am wondering if there is any way I can use it to configure the WiFi credential over a WPS-Enterprise. Basically I just need to add an extra “identity” string to the ESP32 SmartConfig in order to set this network. Currently I am hardcoding the SSIS, PASS and IDENTITY (without SmartConfig) in a config file, but using ESP-Touch is really ideal and is solving many issues in our project if we can use it with an Enterprise network like a University WiFi.
Best
exactly, I would like to pass also i.e. WiFi Channel, static IP address etc (with static IP, ESP32 can get connected to AP/Router within 150ms – no way to do it so fast with DHCP)
Unfortunately the author @Dharmik, is not responsive!
very bad ;-(
Hello Mohammad,
Firstly sorry for the late reply, I am not sure we can send additional data via ESP-Touch but I believe it should be possible.
I am also exploring this new protocol and only one thing is holding us back which is the app-side coding, I can get deeper into ESP32 hardware-side ESP-touch code to transfer some more data but we don’t know much about android development.
Tho espressif team has made the app code open source so any readers expert in app development can join us and we can explore ESP-Touch together.
MR. Dharmik
All your efforts are appreciated, but I am looking for an arduino code how to get custom data from esptouch v2?
@Dharmik
I did an own android app that can work as esptouch app
Woo great Wetry, would love to see your version of the app. Send some images.
Hello@ Dharmik
“ESP Touch support in React Native” but it will not working properly, it will be throw error and evaluating, deprecated my project. I have already completely read and refer your’s documentation. Please give some instruction to run and connect on ESP32 smartconfig on reactnative app.
And this is my build.gradle file
SDK, targetsdk versions
ext {
buildToolsVersion = “31.0.0”
minSdkVersion = 21
compileSdkVersion = 31
targetSdkVersion = 31
ndkVersion = “21.4.7075529”
kotlinVersion = “1.5.21”
}
Hellow @Balakarthick,
Are you currently using Expo Go or the CLI? Could you please offer more precise information regarding the error with images?