Espressif 玩转 SoftAP

最近使用 ESP32-C3 跑了下 softAP demo,阅读了 demo 源码及跑过 demo 之后,脑海中不禁有以下几个疑问:

  1. ESP32-C3 作为 SoftAP 时,默认的 IP 地址为 192.168.4.1,如何修改默认的 IP 地址?
  2. ESP32-C3 作为 SoftAP 时,有 Station 连接上了之后,如何获取 SoftAP 分配给这个 Station 的 IP 地址 ?

笔者认为 Espressif 虽然提供了较为丰富的文档和示例,但是值得改进的地方还是有很多的。就以 softAP demo 为例,这个 demo 仅仅只是做了一个简单的示例,而对于我以上的 2 个问题,却没有很好的展现出来。

在网上看了一大堆所谓的技术文章,全都是千篇一律的跑了一下 softAP demo,然后对 softAP demo 源码进行一堆所谓的分析,然后就没有然后了,没有深入的对这个 demo 进行发掘。所以笔者阅读文档,结合 softAP demo 源码,写了一份自己的 demo,对以上 2 个问题以代码的形式做了示例。

ESP32-C3 作为 SoftAP 时,默认的 IP 地址为 192.168.4.1,如何修改默认的 IP 地址?

要修改 SoftAP 的默认 IP 地址,核心的逻辑就是要先停止 DHCP,然后设置 IP 地址,子网掩码,网关,然后在启用 DHCP 即可。

void set_softap_ip(esp_netif_t *softap)
{
    esp_netif_ip_info_t ip = { 0 };

    ip.ip.addr = ipaddr_addr(CONFIG_ESP_SOFTAP_IP);
    ip.netmask.addr = ipaddr_addr(CONFIG_ESP_SOFTAP_NETMASK);
    ip.gw.addr = ipaddr_addr(CONFIG_ESP_SOFTAP_GATEWAY);

    esp_netif_dhcps_stop(softap);
    esp_netif_set_ip_info(softap, &ip);
    esp_netif_dhcps_start(softap);

    return;
}
void wifi_init_softap(void)
{
    esp_log_level_set("wifi", ESP_LOG_ERROR);

    esp_netif_t *softap = esp_netif_create_default_wifi_ap();

    set_softap_ip(softap);

    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
    ESP_ERROR_CHECK(esp_wifi_init(&cfg));

    wifi_config_t wifi_config = {
        .ap = {
            .ssid = CONFIG_ESP_WIFI_SSID,
            .ssid_len = strlen(CONFIG_ESP_WIFI_SSID),
            .channel = CONFIG_ESP_WIFI_CHANNEL,
            .password = CONFIG_ESP_WIFI_PASSWORD,
            .max_connection = CONFIG_ESP_MAX_STA_CONN,
            .authmode = WIFI_AUTH_WPA_WPA2_PSK,
            .pmf_cfg = {
                    .required = false,
            },
        },
    };

    if (strlen(CONFIG_ESP_WIFI_PASSWORD) == 0) {
        wifi_config.ap.authmode = WIFI_AUTH_OPEN;
    }

    ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_AP));
    ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_AP, &wifi_config));
    ESP_ERROR_CHECK(esp_wifi_start());

    ESP_LOGI(TAG, "wifi_init_softap finished. SSID:%s password:%s channel:%d", CONFIG_ESP_WIFI_SSID, CONFIG_ESP_WIFI_PASSWORD, CONFIG_ESP_WIFI_CHANNEL);
}

ESP32-C3 作为 SoftAP 时,有 Station 连接上了之后,如何获取 SoftAP 分配给这个 Station 的 IP 地址 ?

Station 在连接 SoftAP 的过程中,其实可以分为两个阶段,在这两个阶段分别可以获取到 Station 的不同信息。

  1. Station 连接上 SoftAP,但还没有获取到 SoftAP 分配的 IP 地址,也就是在 DHCP 过程之前。此时只能获取到 Station 的 MAC 地址。
  2. Station 连接上 SoftAP,获取到 SoftAP 分配的 IP 地址,也就是在 DHCP 过程之后。此时能获取到 Station 的 IP 地址。

第一阶段属于 WiFi 驱动层,原生的 softAP demo 其实写的已经很好了,主要就是通过注册 WIFI_EVENT,在 event 回调中来获取到 Station 的 MAC 地址。

第二阶段属于 TCP/IP 协议栈层,也就是 LWIP。但原生的 softAP demo 没有对这一部分进行说明。以下代码是笔者根据官方文档自己写的。读者可以参考这部分代码来获取连接上的 Station 的 IP 地址。

  1. 首先注册 IP_EVENT

    ESP_ERROR_CHECK(esp_event_handler_instance_register(IP_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL, NULL));
    
  2. 在 event 回调中对 IP_EVENT_AP_STAIPASSIGNED 这个 event_id 进行处理。

    static void event_handler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data)
    {
        if (event_base == IP_EVENT) {
            ip_event_handler(arg, event_id, event_data);
        } else {
            wifi_event_handler(arg, event_id, event_data);
        }
    }
    
    static void ip_event_handler(void* arg, int32_t event_id, void* event_data)
    {
        if (event_id == IP_EVENT_AP_STAIPASSIGNED) {
            ip_event_ap_staipassigned_t *event = (ip_event_ap_staipassigned_t *) event_data;
            ESP_LOGI(TAG, "the IP address assigned by the SoftAP is" IPSTR, IP2STR(&event->ip));
        }
    }
    

    之所以说 Espressif 值的改进的地方还有很多,一是因为 softAP demo 展示的不够详细,另一个就是因为文档更新的不及时。在阅读 Espressif Event Handling 时,文档中写明了 event_idIP_EVENT_AP_STAIPASSIGNEDevent_data 是一个 n/a 结构:
    在这里插入图片描述
    但是在阅读 esp-idf 源码的时候突然看到了 ip_event_ap_staipassigned_t 的定义:

    在这里插入图片描述
    所以在 IP_EVENT_AP_STAIPASSIGNED 的处理中抱着试一试的想法将 event_data 强制转换成了 ip_event_ap_staipassigned_t 指针,没想到还真的可以获取到连接上的 Station 的 IP 地址。

最后附上笔者自己的 SoftAP 代码,编译后可以直接在 ESP32-C3 上运行,esp-idf 使用 master 分支,测试 commit 为 fde4afc67a

完整工程代码已经上传到我的 GitHub 仓库 esp-examples ,有需要的读者可以直接下载。

#include <string.h>
#include <netdb.h>
#include "esp_system.h"
#include "esp_wifi.h"
#include "esp_event.h"
#include "esp_log.h"
#include "esp_mac.h"
#include "nvs_flash.h"
#include "esp_netif.h"

static const char *TAG = "example";

static void wifi_event_handler(void* arg, int32_t event_id, void* event_data)
{
    if (event_id == WIFI_EVENT_AP_STACONNECTED) {
        wifi_event_ap_staconnected_t *event = (wifi_event_ap_staconnected_t *) event_data;
        ESP_LOGI(TAG, "station "MACSTR" join, AID=%d", MAC2STR(event->mac), event->aid);
    } else if (event_id == WIFI_EVENT_AP_STADISCONNECTED) {
        wifi_event_ap_stadisconnected_t *event = (wifi_event_ap_stadisconnected_t *) event_data;
        ESP_LOGI(TAG, "station "MACSTR" leave, AID=%d", MAC2STR(event->mac), event->aid);
    }
}

static void ip_event_handler(void* arg, int32_t event_id, void* event_data)
{
    if (event_id == IP_EVENT_AP_STAIPASSIGNED) {
        ip_event_ap_staipassigned_t *event = (ip_event_ap_staipassigned_t *) event_data;
        ESP_LOGI(TAG, "the IP address assigned by the SoftAP is" IPSTR, IP2STR(&event->ip));
    }
}

static void event_handler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data)
{
    if (event_base == IP_EVENT) {
        ip_event_handler(arg, event_id, event_data);
    } else {
        wifi_event_handler(arg, event_id, event_data);
    }
}

void set_softap_ip(esp_netif_t *softap)
{
    esp_netif_ip_info_t ip = { 0 };

    ip.ip.addr = ipaddr_addr(CONFIG_ESP_SOFTAP_IP);
    ip.netmask.addr = ipaddr_addr(CONFIG_ESP_SOFTAP_NETMASK);
    ip.gw.addr = ipaddr_addr(CONFIG_ESP_SOFTAP_GATEWAY);

    esp_netif_dhcps_stop(softap);
    esp_netif_set_ip_info(softap, &ip);
    esp_netif_dhcps_start(softap);

    return;
}

void wifi_init_softap(void)
{
    esp_log_level_set("wifi", ESP_LOG_ERROR);

    esp_netif_t *softap = esp_netif_create_default_wifi_ap();

    set_softap_ip(softap);

    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
    ESP_ERROR_CHECK(esp_wifi_init(&cfg));

    wifi_config_t wifi_config = {
        .ap = {
            .ssid = CONFIG_ESP_WIFI_SSID,
            .ssid_len = strlen(CONFIG_ESP_WIFI_SSID),
            .channel = CONFIG_ESP_WIFI_CHANNEL,
            .password = CONFIG_ESP_WIFI_PASSWORD,
            .max_connection = CONFIG_ESP_MAX_STA_CONN,
            .authmode = WIFI_AUTH_WPA_WPA2_PSK,
            .pmf_cfg = {
                    .required = false,
            },
        },
    };

    if (strlen(CONFIG_ESP_WIFI_PASSWORD) == 0) {
        wifi_config.ap.authmode = WIFI_AUTH_OPEN;
    }

    ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_AP));
    ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_AP, &wifi_config));
    ESP_ERROR_CHECK(esp_wifi_start());

    ESP_LOGI(TAG, "wifi_init_softap finished. SSID:%s password:%s channel:%d", CONFIG_ESP_WIFI_SSID, CONFIG_ESP_WIFI_PASSWORD, CONFIG_ESP_WIFI_CHANNEL);
}

void app_main(void)
{
    ESP_ERROR_CHECK(nvs_flash_init());

    ESP_ERROR_CHECK(esp_netif_init());
    ESP_ERROR_CHECK(esp_event_loop_create_default());
    ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL, NULL));
    ESP_ERROR_CHECK(esp_event_handler_instance_register(IP_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL, NULL));

    wifi_init_softap();
    
}

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
iOS SoftAP是指苹果公司的iOS操作系统支持的软件热点功能。软件热点是一种让用户将自己的移动设备(如iPhone、iPad)转化为一个无线热点,其他设备可以通过连接到该热点来共享移动设备上的网络连接的功能。iOS SoftAP功能使用户可以方便地使用自己的移动设备分享网络连接,而无需额外的硬件设备。 使用iOS SoftAP非常简单。用户只需在iOS设备的设置中打开“个人热点”选项,然后设置一个网络名称和密码即可。其他设备(如电脑、其他手机等)可以搜索到该网络名称,并通过输入密码连接到该热点。一旦连接成功,这些设备就可以与iOS设备共享网络连接,进行上网浏览、下载文件等操作。 iOS SoftAP功能在一些特定的场景下非常有用。比如,在没有Wi-Fi网络的地方,用户可以通过这种方式将自己的移动数据连接分享给其他设备,方便他人上网。此外,即使有Wi-Fi网络,但信号较弱或者网络断网时,用户也可以使用iOS SoftAP功能,将移动运营商的数据网络分享给其他设备,以保持网络连接的稳定性。 需要注意的是,使用iOS SoftAP功能会消耗设备的电池和数据流量。因此,在使用前应确保有足够的电量和可用的数据流量。另外,在一些国家或地区,移动运营商可能对数据共享进行限制或收取额外费用,请在使用前咨询相关政策。 总之,iOS SoftAP是苹果公司iOS操作系统所支持的软件热点功能,方便用户将自己的移动设备转化为无线热点,以便其他设备共享网络连接。用户只需简单设置即可使用,而且在一些特定场景下非常有用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

嵌入式工程狮

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值