0

$USD

$USD
TUTORIALS ESP32

ESP32 Arduino Soft AP: Obtaining IP address of connected stations

DFRobot Dec 16 2019 3985

In this tutorial we will check how to obtain the IP address of all the stations connected to a network hosted by the ESP32, working as Soft AP. The tests shown here were performed using an ESP32 board from DFRobot.

 

 

Introduction

In this tutorial we will check how to obtain the IP address of all the stations connected to a network hosted by the ESP32, working as Soft AP. We will also print the MAC address, so we can know which station has which IP.

We will be using the Arduino core to program the ESP32.

The code shown below was adapted from this awesome IDF tutorial by Lucadentella. I really encourage you to check his website and all the useful content provided there.

The tests shown here were performed using an ESP32 board from DFRobot.

 

The code

We will start by including the WiFi.h library, so we can easily setup the ESP32 to work as a Soft AP. We could alternatively use lower level functions also to do this, but we will follow the simpler approach.

We will also need o to include the esp_wifi.h, which will expose lower level functions and data structures to obtain the IP addresses of all the stations connected to the ESP32.

#include <WiFi.h> #include "esp_wifi.h"
 

Moving on to the Arduino setup function, we will start by opening a serial connection.

After that, we will setup the ESP32 to work in Soft AP mode. This is done with a call to the softAP method on the WiFi extern variable.

As input of this method, we will pass a string with the name (SSID) that we want to assign to our network. I will be calling it “MyESP32AP“, but you can call it how you prefer.

The full setup function can be seen below.

void setup() {  Serial.begin(115200);  WiFi.softAP("MyESP32AP"); }
 

We will write the rest of our code in the Arduino main loop, so periodically we will print the IP addresses of all the stations connected to the network.

We will start by declaring a struct of type wifi_sta_list_t. This will contain the list of stations associated with the ESP32 soft AP. Nonetheless, it doesn’t contain any IP related information about the stations.

wifi_sta_list_t wifi_sta_list;
 

We will also declare a struct of type tcpip_adapter_sta_list_t. This data structure also contains information about the stations connected to the network. In this case, it contains the IP information.

tcpip_adapter_sta_list_t adapter_sta_list;
 

After declaring these structs and before starting to use them, we will initialize them by doing a memset of all their bytes to 0.

memset(&wifi_sta_list, 0, sizeof(wifi_sta_list)); memset(&adapter_sta_list, 0, sizeof(adapter_sta_list));
 

After this we will get the list of stations associated with the soft AP with a call to the esp_wifi_ap_get_sta_list function. As input of this function we will pass the address of our wifi_sta_list_t struct.

esp_wifi_ap_get_sta_list(&wifi_sta_list);

Then, to get the IP information of all the stations connect to the AP interface of the ESP32, we will call the tcpip_adapter_get_sta_list function.

This function receives as first input the address of a wifi_sta_list struct, filled with the stations information by a previous call to the esp_wifi_ap_get_sta_list function [2], like we did.

As second input we need to pass the address of our tcpip_adapter_sta_list_t, which will then receive the IP address related information [2]. Note that this struct will also contain the MAC address information of the stations, so we can know which IP was assigned to each MAC.

tcpip_adapter_get_sta_list(&wifi_sta_list, &adapter_sta_list);
 

The rest of our code will be based in the information contained on the tcpip_adapter_sta_list_t struct. As can be seen here, this struct contains a member called num which corresponds to the number of stations currently connected to the ESP32 network.

It also contains an array of structs of type tcpip_adapter_sta_info_t, which contain the actual IP and MAC address information. This array is called sta and it has a length equal to the number of stations connected.

Taking the previous information in consideration, we can do a for loop to iterate over the sta array and print the information about each station. Note that the code inside the loop won’t execute if there are no stations connected to the network.

for (int i = 0; i < adapter_sta_list.num; i++) {  // printing the station information }
 

First we will obtain the tcpip_adapter_sta_info_t struct for the current iteration of the loop. Recall that this represents the information of a single station connected to the ESP32 network.

tcpip_adapter_sta_info_t station = adapter_sta_list.sta[i];

This struct contains a member called mac, which corresponds to a 6 bytes array with the MAC address of the device. We will print it to the serial console with each byte in hexadecimal format, separated by colons.

Serial.print("MAC: "); for(int i = 0; i< 6; i++){         Serial.printf("%02X", station.mac[i]);     if(i<5)Serial.print(":"); }
 

The tcpip_adapter_sta_info_t struct also contains a member called ip, which contains the station IP information. This member is a struct of type ip4_addr_t.

To get the IP address in a dots and numbers formatted string, we simply need to call theip4addr_ntoa function, passing as input the address of the ip data member.

Serial.print("\nIP: ");   Serial.println(ip4addr_ntoa(&(station.ip))); 

You can check the complete loop code below. We have added a delay between each iteration of the loop.

void loop() {  wifi_sta_list_t wifi_sta_list;  tcpip_adapter_sta_list_t adapter_sta_list;  memset(&wifi_sta_list, 0, sizeof(wifi_sta_list));  memset(&adapter_sta_list, 0, sizeof(adapter_sta_list));  esp_wifi_ap_get_sta_list(&wifi_sta_list);  tcpip_adapter_get_sta_list(&wifi_sta_list, &adapter_sta_list);  for (int i = 0; i < adapter_sta_list.num; i++) {    tcpip_adapter_sta_info_t station = adapter_sta_list.sta[i];    Serial.print("station nr ");    Serial.println(i);    Serial.print("MAC: ");    for(int i = 0; i< 6; i++){            Serial.printf("%02X", station.mac[i]);        if(i<5)Serial.print(":");    }    Serial.print("\nIP: ");      Serial.println(ip4addr_ntoa(&(station.ip)));      }  Serial.println("-----------");  delay(5000); }
 

The final complete code can be seen below.

#include <WiFi.h> #include "esp_wifi.h" void setup() {  Serial.begin(115200);  WiFi.softAP("MyESP32AP"); } void loop() {  wifi_sta_list_t wifi_sta_list;  tcpip_adapter_sta_list_t adapter_sta_list;  memset(&wifi_sta_list, 0, sizeof(wifi_sta_list));  memset(&adapter_sta_list, 0, sizeof(adapter_sta_list));  esp_wifi_ap_get_sta_list(&wifi_sta_list);  tcpip_adapter_get_sta_list(&wifi_sta_list, &adapter_sta_list);  for (int i = 0; i < adapter_sta_list.num; i++) {    tcpip_adapter_sta_info_t station = adapter_sta_list.sta[i];    Serial.print("station nr ");    Serial.println(i);    Serial.print("MAC: ");    for(int i = 0; i< 6; i++){            Serial.printf("%02X", station.mac[i]);        if(i<5)Serial.print(":");    }    Serial.print("\nIP: ");      Serial.println(ip4addr_ntoa(&(station.ip)));      }  Serial.println("-----------");  delay(5000); }
 


 

Testing the code

To test the code, simply compile it and upload it to your ESP32 using the Arduino IDE. When the procedure finishes, open the Arduino IDE serial monitor.

Wait until the ESP32 network setup ends. After that, you should be able to see it from any WiFi enabled device.

Then, use a device (or multiple) of your choice and connect it to the network. You should see an output similar to figure 1 (note that on figure 1 I had two devices connected).

As can be seen, you should obtain the IP and MAC addresses of all the devices connected to the network.


Figure 1 – IP and MAC addresses of all the devices connected to the ESP32 network.


References

[1] https://docs.espressif.com/projects/esp-idf/en/latest/api-reference/network/esp_wifi.html#_CPPv415wifi_sta_list_t

[2] https://docs.espressif.com/projects/esp-idf/en/latest/api-reference/network/tcpip_adapter.html#_CPPv426tcpip_adapter_get_sta_listPK15wifi_sta_list_tP24tcpip_adapter_sta_list_t