ESP32 WiFi events: Station Got IP address

The objective of this tutorial is to check how to handle the “Station Got IP” WiFi event on the ESP32. We will be using the Arduino core. The tests shown here were performed using an ESP32 board from DFRobot.

Introduction

The objective of this tutorial is to check how to handle the “Station Got IP” WiFi event on the ESP32. We will be using the Arduino core.

On this previous tutorial we learned how to get started using WiFi events and we saw an example on how to handle the “Station connected to AP” event.

Nonetheless, there are multiple events associated with the WiFi (please check this page for a detailed list) and we need to have a good understanding of those to avoid problems when developing our application.

For example, as described on the mentioned previous tutorial, when the “Station connected to AP” is received, the ESP32 doesn’t have an IP address yet, which means that we cannot use, for example, sockets.

So, if our application relies on some protocol that uses sockets under the hood (ex: HTTP), it means that we cannot start that part of the application immediately after the “Station connected to AP” event.

Thus, there’s another event to signal that the ESP32 successfully got an IP address (SYSTEM_EVENT_STA_GOT_IP), which is the one we are going to handle on this tutorial.

Additionally to registering an handling function for the event, we are also going to see 3 different ways of getting the IP address that was assigned to the ESP32.

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

The code

We will start the code by including the WiFi.h library, so we can have access to the WiFi related functionalities. This include will expose an extern variable called WiFi, which we will use to connect the ESP32 to a network and to register the event handling function.

#include <WiFi.h>

We will also need to declare the network credentials, so we can connect the ESP32 to it. In particular, we will need the network name (SSID) and the network password.

const char* ssid = "yourNetworkName";
const char* password =  "yourNetworkPassword";

Moving on to the Arduino setup, we will start by opening a serial connection, so we can output the results of our program.

Serial.begin(115200);

Then we will register the event handling function. We do this by calling the onEvent method on the WiFi extern variable.

As first input of the method we will pass the event handling function (we will define it later) and as second input we will pass the identifier of the event we want to catch. The identifiers of all the available events can be seen here. we will be catching the SYSTEM_EVENT_STA_GOT_IP event.

WiFi.onEvent(WiFiStationGotIP, SYSTEM_EVENT_STA_GOT_IP);

To finalize the setup function, we will start the connection of the ESP32 to the WiFi network. We do this simply by calling the begin method on the WiFi extern variable, passing as first input the SSID of the network and as second input the password.

WiFi.begin(ssid, password);

The complete setup function code can be seen below.

void setup()
{
    Serial.begin(115200);
  
    WiFi.onEvent(WiFiStationGotIP, SYSTEM_EVENT_STA_GOT_IP);
      
    WiFi.begin(ssid, password);
  
}

We can leave the main loop empty since the rest of the code will execute on the event handling function.

void loop(){}

Now we will take care of analyzing the code of the event handling function. Recall from the previous tutorial that this function needs to follow a predefined signature.

void WiFiStationGotIP(WiFiEvent_t event, WiFiEventInfo_t info)
{
  // event handling code
}

Inside our handling function we will analyze 3 ways of obtaining the IP address that was assigned to the ESP32 on the network.

The first and simplest one consists on calling the localIP method on the WiFi extern variable. We can directly output the result of this method call to the serial port.

Serial.println(WiFi.localIP());

The second approach consists on analyzing the content from the WiFiEventInfo_t union. One of the members of the union is called got_ip and it contains the information about the SYSTEM_EVENT_STA_GOT_IP event.

The got_ip union member corresponds to a struct of type system_event_sta_got_ip_t. You can check it here.

This struct contains a member called ip_info, which is a struct of type tcpip_adapter_ip_info_t. The definition of this struct can be seen here.

Finally, the tcpip_adapter_ip_info_t struct contains a member called ip which is of type ip4_addr_t and contains the IP address information.

To recap, starting from our event info, we need to access data members in the following sequence:

info.got_ip.ip_info.ip

Finally, to get each byte of the IP address of the ip4_addr_t type, there are 4 macros defined here. They are named ip4_addrX, where X is the number of the IP address byte we want to obtain. Take in consideration that IPv4 addresses are composed by 4 bytes.

Note that each macro receives as input the address of the ip4_addr_t struct member.

So, we are going to print each byte separated by a “.”, to follow the usual format for IP addresses.

Serial.print(ip4_addr1(&(info.got_ip.ip_info.ip)));
Serial.print(".");  
Serial.print(ip4_addr2(&(info.got_ip.ip_info.ip)));
Serial.print(".");  
Serial.print(ip4_addr3(&(info.got_ip.ip_info.ip)));
Serial.print(".");  
Serial.print(ip4_addr4(&(info.got_ip.ip_info.ip)));

It’s important to mention that this approach is the most complex and I’ve included it here just for curiosity, for those who have interest in looking into the lower layers of the code.

To finalize, we will see a third possible way to obtain the IP address. Basically, we will instantiate an object of class IPAddress, passing as input the field addr of the ip4_addr_t struct we have used in the previous approach.

We can directly print the resulting IPAddress object to the serial port, which will show the IP address in its standard format.

Serial.println(IPAddress(info.got_ip.ip_info.ip.addr));

The final source code can be seen below.

#include <WiFi.h>
  
const char* ssid = "yourNetworkName";
const char* password =  "yourNetworkPassword";
  
void WiFiStationGotIP(WiFiEvent_t event, WiFiEventInfo_t info)
{

    Serial.println(WiFi.localIP());

    Serial.print(ip4_addr1(&(info.got_ip.ip_info.ip)));
    Serial.print(".");  
    Serial.print(ip4_addr2(&(info.got_ip.ip_info.ip)));
    Serial.print(".");  
    Serial.print(ip4_addr3(&(info.got_ip.ip_info.ip)));
    Serial.print(".");  
    Serial.print(ip4_addr4(&(info.got_ip.ip_info.ip)));

    Serial.println();
    Serial.println(IPAddress(info.got_ip.ip_info.ip.addr));
} 
  
void setup()
{
    Serial.begin(115200);
  
    WiFi.onEvent(WiFiStationGotIP, SYSTEM_EVENT_STA_GOT_IP);
      
    WiFi.begin(ssid, password);
  
}
  
void loop(){}

Testing the code

To test the code, simply compile it and upload it to your ESP32, using the Arduino IDE. Make sure that you have changed the placeholders in the code by the actual credentials of your WiFi network.

Once the procedure is finished, open the Arduino IDE serial monitor. Wait for the connection to the WiFi network to be established. Once it does, you should obtain a result similar to figure 1.

As can be seen, both methodologies we have followed allowed us to obtain the IP address assigned to the device. Note that the local IP assigned to your device will most likely differ from mine.

Output of the program, showing the same result for the three methods of obtaining the IP address.
Figure 1 – Output of the program, showing the same result for the three methods of obtaining the IP address.

Leave a Reply