Skip to content

Overview

Soft-AP mode turns the Ai-WB2 into a Wi-Fi hotspot (sending out a Wi-Fi signal like a phone's personal hotspot); phones/computers can connect directly to the board, commonly used for device provisioning and LAN direct control. The board's default IP (the "house number" on the network) is 192.168.169.1, and joined devices get their IP from the onboard DHCP server (the little steward that assigns IPs automatically). This tutorial demonstrates starting the hotspot and observing device join events.

In plain words: Soft-AP is the board "opening its own hotspot" — it sends out a Wi-Fi signal (named SSID), and the phone connects to it like connecting to home Wi-Fi, communicating with the board directly without any router. The board gives the hotspot a fixed "house number" 192.168.169.1; whoever joins, the DHCP little steward inside the board automatically hands them an IP. Commonly used for provisioning devices and directly controlling devices on the LAN.

This tutorial is based on the official Ai-Thinker SDK (Ai-Thinker-Open/Ai-Thinker-WB2, version release_bl_iot_sdk_1.6.40) example applications/wifi/softAP; the code can be found directly in your local SDK.

🎯Page GoalBy starting the hotspot, setting the hotspot IP and observing device join/leave events, master the Soft-AP startup flow and network configuration.
🧰Prerequisites① Ai-WB2 development board (Type-C data cable) ② A phone or computer (for joining the hotspot to verify) ③ Environment set up per [SDK Installation](../../sdk/sdk_intro).
🔗RelatedConnecting to a router in STA mode: [Connect Wi-Fi](./wifi_connect); provisioning products can use [Blufi Provisioning](../../ble/blufi).

Enter the Example Project

Open a terminal and enter the official softAP example project directory:

cd ~/Ai-Thinker-WB2/applications/wifi/softAP

Note: cd is the “change directory” command, entering the official example project; all subsequent make commands must run in this directory.

Modify the Hotspot Parameters

Open softAP/main.c and change the hotspot name (SSID, the Wi-Fi’s name) and password at the top:

#define AP_SSID "ai-thinker"
#define AP_PWD "12345678"

For example:

#define AP_SSID "WB2-Hotspot"
#define AP_PWD "88888888"

💡 The hotspot password must be at least 8 characters (a WPA2 encryption requirement; shorter than 8 and the hotspot won’t start); search for the hotspot with your phone to join and test.

Write the Code

Open softAP/main.c. The full code for this step has been moved to the end of this page:

📜 Full Code — in the “Full Code” section below, collapsed by default — click to expand, identical to the official example (applications/wifi/softAP/softAP/main.c).

Code highlights:

Code Purpose
wifi_mgmr_ap_enable() Enable AP mode first; without it the hotspot-start functions that follow are all unusable
wifi_mgmr_conf_max_sta(4) Limit to at most 4 joined devices, preventing the hotspot from being overwhelmed
wifi_mgmr_ap_start(if, ssid, 0, pwd, 6) Actually starts the hotspot: name, channel 0 (auto), password, encryption 6 (WPA2)
wifi_ap_ip_set(...) Gives the hotspot its “house number” IP 192.168.169.1, netmask, gateway
netif_find("ap1") Finds the hotspot network interface (ap1); must find it before changing the IP
CODE_WIFI_ON_AP_STA_ADD Notification that a device joined the hotspot; do business here
CODE_WIFI_ON_AP_STA_DEL Notification that a device left the hotspot; do business here

💡 The default gateway IP 192.168.169.1 is defined by the DHCPD_SERVER_IP macro at line 42 of components/network/lwip_dhcpd/dhcp_server_raw.c; to switch subnets (e.g. 192.168.4.1) you must change both that macro and the wifi_ap_ip_set arguments.

Build the Project

Build in the project directory:

make -j8

Note: make is the “build” command, turning code into firmware (the program flashed into the board) the board can run; -j8 builds with 8 parallel cores, faster.

On success a firmware build_out/softAP.bin is generated.

Flash the Firmware

Keep the board connected via USB, confirm the serial device, and flash:

make flash p=/dev/ttyUSB0 b=921600

Note: make flash is the “flash” command, writing the compiled firmware into the board. After p= comes the serial device (often /dev/ttyUSB0 on Linux, COM3-like on Windows — use your computer’s actual one), b=921600 is the flash baud rate (serial transfer speed), keep the default.

⏳ During flashing, press and hold the EN button on the board when prompted to enter download mode; wait for the progress bar to complete — that means the flash succeeded.

Run and Verify

After flashing, the board automatically restarts and runs. Open a serial assistant (baud rate 921600, the “speech speed” of serial data — both ends must match) and observe the logs:

[OS] Starting TCP/IP Stack...
<<<<<<<<<  init wifi done  <<<<<<<<<<
<<<<<<<<< startting soft ap <<<<<<<<<<<
<<<<<<<<< startt soft ap OK<<<<<<<<<<<
[softAP]:SSID:ai-thinker,PASSWORD:12345678,IP addr:192.168.169.1

Search Wi-Fi with your phone, find the hotspot ai-thinker, enter the password and connect; the serial prints:

<<<<<<<<< station connent ap <<<<<<<<<<<

When the phone disconnects it prints station disconnet ap. Visit http://192.168.169.1 in the phone browser to access the board’s Web service (needs a TCP Server application).

The phone joining the hotspot and the serial printing station connent ap means success; if the phone can’t find the hotspot, first check whether the serial printed startt soft ap OK (if not, the hotspot didn’t start); if it can be found but not joined, check that the password is 8+ characters and that you rebuilt and re-flashed after the change — see the FAQ at the end.


API Summary for This Tutorial

wifi_mgmr_ap_enable

Enables AP mode and returns the hotspot interface handle.

Return: interface handle (wifi_interface_t) on success; NULL on failure

wifi_mgmr_conf_max_sta(num)

Limits the maximum number of devices that can join the hotspot.

Parameters:

  • num: maximum joined devices, the official example passes 4

Return: 0 on success; negative error code on failure

wifi_mgmr_ap_start(if, ssid, channel, pwd, enc)

Starts the hotspot (encryption 6 = WPA2, 0 = open).

Parameters:

  • if: AP interface handle (return of wifi_mgmr_ap_enable())
  • ssid: hotspot name (official default "ai-thinker")
  • channel: channel (1~13)
  • pwd: hotspot password (official default "12345678"), pass NULL for an open network
  • enc: encryption (6 = WPA2, 0 = open)

Return: 0 on success; negative error code on failure

wifi_mgmr_start_background(conf)

Starts the Wi-Fi manager (the scheduling core of connecting/hotspot/scanning).

Parameters:

  • conf: wifi_conf_t struct pointer, optional fields: country_code (country code, "CN" for China)

Return: 0 on success; negative error code on failure

netif_find(name)

Finds a network interface by name (the hotspot interface is "ap1").

Parameters:

  • name: network interface name string, values: "st1" (station interface) / "ap1" (hotspot interface)

Return: struct netif* on success; NULL on failure

netif_set_ipaddr / netif_set_netmask / netif_set_gw(netif, addr)

Sets the network interface IP / subnet mask / gateway.

Parameters:

  • netif: target interface (return of netif_find)
  • addr: ip4_addr_t pointer, constructed with the IP4_ADDR macro

Return: none

netif_set_down / netif_set_up(netif)

Brings the network interface down / up.

Parameters:

  • netif: target interface (return of netif_find)

Return: none

IP4_ADDR(addr, a, b, c, d)

Constructs an IP address from 4 integer segments (network byte order).

Parameters:

  • addr: output ip4_addr_t pointer
  • a, b, c, d: the four IP segment values, e.g. 192, 168, 169, 1

Return: none

ip4addr_ntoa(addr)

Converts an IP address to a dotted-decimal string.

Parameters:

  • addr: ip4_addr_t pointer

Return: dotted-decimal string (e.g. "192.168.169.1")

📌 Hotspot event codes: CODE_WIFI_ON_AP_STARTED (hotspot started) / CODE_WIFI_ON_AP_STOPPED (stopped) / CODE_WIFI_ON_AP_STA_ADD (device joined) / CODE_WIFI_ON_AP_STA_DEL (device left), defined in hal_wifi.h.


Full Code

Below is the complete softAP/main.c source, identical to the official example (applications/wifi/softAP/softAP/main.c):

📜 Click to expand the full softAP/main.c code
c
/**
 * @file main.c
 * @author your name (you@domain.com)
 * @brief
 * @version 0.1
 * @date 2022-10-09
 *
 * @copyright Copyright (c) 2022
 *
 */
#include <FreeRTOS.h>
#include <task.h>
#include <stdio.h>
#include <string.h>
#include <aos/yloop.h>
#include <aos/kernel.h>
#include <lwip/tcpip.h>
#include <wifi_mgmr_ext.h>
#include <hal_wifi.h>
#include <lwip/netif.h>
#include <lwip/inet.h>
#include <blog.h>

#define AP_SSID "ai-thinker"
#define AP_PWD "12345678"

#define TAG "softAP"

static wifi_conf_t ap_conf = {
    .country_code = "CN",
};
static wifi_interface_t ap_interface;
/**
 * @brief wifi_ap_ip_set
 *      Set the IP address of soft AP
 * @param ip_addr IPV4 addr
 * @param netmask netmask
 * @param gw DNS
 */
static void wifi_ap_ip_set(char* ip_addr, char* netmask, char* gw)
{
    struct netif* ap_netif = netif_find("ap1");
    int i = 0;
    int ap_ipaddr[4] = { 0 };
    int ap_netmask[4] = { 255,255,255,0 };
    int ap_gw_arry[4] = { 0,0,0,0 };

    ap_ipaddr[0] = atoi(strtok(ip_addr, "."));

    for (i = 1;i<4;i++) {
        ap_ipaddr[i] = atoi(strtok(NULL, "."));
    }
    if (netmask) {
        ap_netmask[0] = atoi(strtok(netmask, "."));
        for (i = 1;i<4;i++)
            ap_netmask[i] = atoi(strtok(NULL, "."));
    }
    if (gw) {
        ap_gw_arry[0] = atoi(strtok(gw, "."));
        for (i = 1;i<4;i++)
            ap_gw_arry[i] = atoi(strtok(NULL, "."));
    }

    if (ap_netif) {

        ip_addr_t ap_ip;
        ip_addr_t ap_mask;
        ip_addr_t ap_gw;
        IP4_ADDR(&ap_ip, ap_ipaddr[0], ap_ipaddr[1], ap_ipaddr[2], ap_ipaddr[3]);
        IP4_ADDR(&ap_mask, ap_netmask[0], ap_netmask[1], ap_netmask[2], ap_netmask[3]);
        IP4_ADDR(&ap_gw, ap_gw_arry[0], ap_gw_arry[1], ap_gw_arry[2], ap_gw_arry[3]);

        netif_set_down(ap_netif);
        netif_set_ipaddr(ap_netif, &ap_ip);
        netif_set_netmask(ap_netif, &ap_mask);
        netif_set_gw(ap_netif, &ap_gw);
        netif_set_up(ap_netif);
        blog_info("[softAP]:SSID:%s,PASSWORD:%s,IP addr:%s", AP_SSID, AP_PWD, ip4addr_ntoa(netif_ip4_addr(ap_netif)));
    }
    else
        blog_info("no find netif ap1 ");

}

/**
 * @brief wifi_ap_start
 *
 */
static void wifi_ap_start()
{
    ap_interface = wifi_mgmr_ap_enable();
    wifi_mgmr_conf_max_sta(4);
    wifi_mgmr_ap_start(ap_interface, AP_SSID, 0, AP_PWD, 6);
    wifi_ap_ip_set("192.168.169.1", "255.255.255.0", "192.168.169.1");  //defaut gateway ip is "192.168.169.1",if you want usb other gateway ip ,please change components/network/lwip_dhcpd/dhcp_server_raw.c:42   DHCPD_SERVER_IP 
                                                                        //for example, gateway ip:"192.168.4.1" , change DHCPD_SERVER_IP to "192.168.4.1"  :
                                                                        //wifi_ap_ip_set("192.168.4.1", "255.255.255.0", "192.168.4.1");
                                                                        //components/network/lwip_dhcpd/dhcp_server_raw.c:42   #define DHCPD_SERVER_IP "192.168.4.1"
}

static void event_cb_wifi_event(input_event_t* event, void* private_data)
{
    switch (event->code) {
        case CODE_WIFI_ON_INIT_DONE:
            blog_info("<<<<<<<<<  init wifi done  <<<<<<<<<<");
            wifi_mgmr_start_background(&ap_conf);
            break;
        case CODE_WIFI_ON_MGMR_DONE:
            blog_info("<<<<<<<<< startting soft ap <<<<<<<<<<<");
            wifi_ap_start();
            break;
        case CODE_WIFI_ON_AP_STARTED:
            blog_info("<<<<<<<<< startt soft ap OK<<<<<<<<<<<");

            break;
        case CODE_WIFI_ON_AP_STOPPED:
            break;
        case CODE_WIFI_ON_AP_STA_ADD:
            blog_info("<<<<<<<<< station connent ap <<<<<<<<<<<");

            break;
        case CODE_WIFI_ON_AP_STA_DEL:
            blog_info("<<<<<<<<< station disconnet ap <<<<<<<<<<<");

            break;
        default:
            break;

    }
}

static void proc_main_entry(void* pvParameters)
{

    aos_register_event_filter(EV_WIFI, event_cb_wifi_event, NULL);
    hal_wifi_start_firmware_task();
    aos_post_event(EV_WIFI, CODE_WIFI_ON_INIT_DONE, 0);
    vTaskDelete(NULL);
}

static void system_thread_init()
{
    /*nothing here*/
}

void main()
{
    system_thread_init();

    puts("[OS] Starting TCP/IP Stack...");
    tcpip_init(NULL, NULL);
    puts("[OS] proc_main_entry task...");
    xTaskCreate(proc_main_entry, (char*)"main_entry", 1024, NULL, 15, NULL);
}

FAQ & Troubleshooting

⚠️ Phone can't find the hotspot
Cause: the hotspot didn't start successfully, or the phone's Wi-Fi is off / prefers 5GHz
Fix: confirm the serial printed startt soft ap OK; turn on the phone's Wi-Fi and wait a few seconds then search again (the hotspot is 2.4GHz)

⚠️ Wrong password prompt when joining the hotspot
Cause: the hotspot password is under 8 characters (WPA2 requirement), or the code was changed but not re-flashed
Fix: make AP_PWD at least 8 characters; rebuild and re-flash after changes

⚠️ Device joins but can't get an IP
Cause: the DHCP server isn't running, or the subnet doesn't match DHCPD_SERVER_IP
Fix: confirm dhcp_server_raw.c wasn't modified; when switching subnets change both the macro and wifi_ap_ip_set

⚠️ Want to connect to a router and open a hotspot at the same time
Cause: the official example only enables AP mode
Fix: first wifi_mgmr_sta_enable() + connect to the router, then wifi_mgmr_ap_enable() + wifi_mgmr_ap_start(); the SDK supports STA+AP coexistence

⚠️ Serial device not found / can't open
Cause: USB-to-serial driver not installed, insufficient permission, or the cable only charges and can't transfer data
Fix: on Linux check the device with lsusb/dmesg; if permission denied run sudo chmod 666 /dev/ttyUSB0; on Windows install the driver and check the COM port in Device Manager; try a data-capable cable

⚠️ Flashing keeps waiting / fails
Cause: download mode wasn't entered, wrong baud rate, or a wrong serial number
Fix: press and hold EN during flashing to enter download mode as prompted; change p=/dev/ttyUSB0 to your actual serial port; try another USB port or cable

Self-Check

The phone finds and joins the hotspot (serial prints station connent ap) — Soft-AP is verified.

Released under the MIT License. Build Time 2026-09-11 14:52:23