Wi-Fi in Zephyr is an integrated network interface within the operating system’s stack.
Unlike Arduino, where Wi-Fi is usually an external library, in Zephyr it is integrated with the common network stack. This means that once you have an IP address, your code to open a TCP socket looks very similar whether you use Wi-Fi, Ethernet, or Thread.
If you use an ESP32, an nRF7002, or a board with a supported Wi-Fi module, Zephyr offers IPv4, IPv6, sockets, TLS, DHCP, and diagnostic tools.
Configuration (prj.conf)
The network stack is huge. For an ESP32 or similar, we need to enable quite a few things. Here is a basic configuration to connect and obtain an address via DHCP:
# Enable Networking
CONFIG_NETWORKING=y
CONFIG_NET_L2_WIFI_MGMT=y
CONFIG_NET_IPV4=y
CONFIG_NET_TCP=y
CONFIG_NET_UDP=y
CONFIG_NET_DHCPV4=y
# Enable Wi-Fi in station mode
CONFIG_WIFI=y
CONFIG_WIFI_USAGE_MODE_STA=y
# Network Management (Network Management API)
CONFIG_NET_MGMT=y
CONFIG_NET_MGMT_EVENT=y
CONFIG_NET_MGMT_EVENT_STACK_SIZE=2048
# Logs to see what's happening
CONFIG_NET_LOG=y
CONFIG_WIFI_LOG_LEVEL_INF=yThe specific driver depends on your board. CONFIG_WIFI_ESP32=y is an example for ESP32; on other boards it may be enabled by the board’s own definition or have a different configuration symbol.
Wi-Fi Management API (wifi_mgmt)
Zephyr uses an event-based API. We don’t call connect() and wait blocking. We tell the system “Connect” and subscribe to an event that notifies us when we have an IP address.
Let’s see an example of how to connect to a WPA2 network.
#include <zephyr/kernel.h>
#include <zephyr/net/net_if.h>
#include <zephyr/net/wifi_mgmt.h>
#include <zephyr/net/net_event.h>
#include <errno.h>
#include <string.h>
/* Callback for network events (IP obtained, disconnection...) */
static void net_mgmt_event_handler(struct net_mgmt_event_callback *cb,
uint64_t mgmt_event, struct net_if *iface)
{
if (mgmt_event == NET_EVENT_WIFI_CONNECT_RESULT) {
const struct wifi_status *status = cb->info;
if (status->status) {
printk("Wi-Fi connection failed (%d)\n", status->status);
} else {
printk("Associated with access point; waiting for DHCP...\n");
}
} else if (mgmt_event == NET_EVENT_IPV4_ADDR_ADD) {
printk("Connection successful! We have an IP address.\n");
/* Here we could release a semaphore to notify the main */
}
}
/* Structure to register the callback */
static struct net_mgmt_event_callback mgmt_cb;
int main(void)
{
struct net_if *iface = net_if_get_default();
struct wifi_connect_req_params params = {0};
printk("Starting Wi-Fi...\n");
/* 1. Subscribe to network events (when we get IP) */
net_mgmt_init_event_callback(&mgmt_cb, net_mgmt_event_handler,
NET_EVENT_WIFI_CONNECT_RESULT |
NET_EVENT_IPV4_ADDR_ADD);
net_mgmt_add_event_callback(&mgmt_cb);
/* 2. Configure credentials */
params.ssid = (const uint8_t *)"MyHome_2.4G";
params.ssid_length = strlen("MyHome_2.4G");
params.psk = (const uint8_t *)"SuperSecurePassword";
params.psk_length = strlen("SuperSecurePassword");
params.security = WIFI_SECURITY_TYPE_PSK;
params.channel = WIFI_CHANNEL_ANY;
/* 3. Request connection */
if (net_mgmt(NET_REQUEST_WIFI_CONNECT, iface, ¶ms, sizeof(params))) {
printk("Error requesting Wi-Fi connection\n");
return -EIO;
}
printk("Connecting... Waiting for IP...\n");
/* The main can sleep; the event will trigger in 'net_mgmt_event_handler' */
while(1) k_sleep(K_FOREVER);
}Network Shell: If you enable CONFIG_NET_SHELL=y, you’ll have very useful commands on the console like net iface (to see IP), net ping google.com, or wifi scan.
With an interface that already has an IP address, we can use sockets, HTTP, MQTT, or other protocols from the common stack.