手把手教你IDF ESP32 S3 开启IPV6 作为sta 连接手机热点 获取IPV6地址

背景:众所周知IPV4的公网IP个人是无法获取到的,因此为了将设备暴露在公网,我们可以用IPV6,刚好ESP32 S3 支持IPV6 这里写下近期ESP32 连接手机热点获取IPV6 的手把手教程 

教程主要分为以下几个模块

1.所需头文件

2.所需全局变量的定义

3.NVS 初始化

4.wifi基础部分初始化

5.sta netif初始化

6.sta 事件句柄初始化

7.配置所要连接的热点

8.启动wifi 并连接wifi

9.连接所有模块

10.运行效果

废话少说,直接上代码

目录

一、头文件

二、全局变量

三、NVS初始化

四、wifi基础部分初始化

五、sta netif初始化

六、sta 事件句柄初始化

1.函数定义

2.函数的实现

七、配置所要连接的热点

八、启动wifi 并连接wifi 

九、连接所有模块

九、效果


一、头文件

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

#include "nvs_flash.h"
#include "lwip/inet.h"
#include "lwip/netdb.h"
#include "lwip/sockets.h"
#include "lwip/lwip_napt.h"
#include "lwip/err.h"
#include "lwip/sys.h"

#include "nvs_flash.h"

二、全局变量

#define STA_NETIF_DESC "sta_netif_desc"
#define TAG "dev_sta"

const char *example_ipv6_addr_types_to_str[6] = {
    "ESP_IP6_ADDR_IS_UNKNOWN",
    "ESP_IP6_ADDR_IS_GLOBAL",
    "ESP_IP6_ADDR_IS_LINK_LOCAL",
    "ESP_IP6_ADDR_IS_SITE_LOCAL",
    "ESP_IP6_ADDR_IS_UNIQUE_LOCAL",
    "ESP_IP6_ADDR_IS_IPV4_MAPPED_IPV6"};

static int s_retry_num = 0;
esp_netif_t *s_example_sta_netif = NULL;

三、NVS初始化

    esp_err_t ret = nvs_flash_init();
    if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND)
    {
        ESP_ERROR_CHECK(nvs_flash_erase());
        ret = nvs_flash_init();
    }
    ESP_ERROR_CHECK(ret);

四、wifi基础部分初始化

    ESP_ERROR_CHECK(esp_netif_init());
    ESP_ERROR_CHECK(esp_event_loop_create_default());

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

    ESP_ERROR_CHECK(esp_wifi_set_storage(WIFI_STORAGE_RAM));
    ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));

五、sta netif初始化

void sta_netif_config(void)
{
    esp_netif_inherent_config_t esp_netif_config = ESP_NETIF_INHERENT_DEFAULT_WIFI_STA();
    esp_netif_config.if_desc = STA_NETIF_DESC;
    esp_netif_config.route_prio = 128;
    s_example_sta_netif = esp_netif_create_wifi(WIFI_IF_STA, &esp_netif_config);
    esp_wifi_set_default_wifi_sta_handlers();
}

六、sta 事件句柄初始化

1.函数定义

static bool sta_is_our_netif(const char *prefix, esp_netif_t *netif);

static void sta_event_handler_unregister(void);
static esp_err_t sta_wifi_sta_do_disconnect(void);

static void sta_handler_on_wifi_connect(void *esp_netif, esp_event_base_t event_base, int32_t event_id, void *event_data);
static void sta_handler_on_wifi_disconnect(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data);
static void sta_handler_on_sta_got_ip(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data);
static void sta_handler_on_sta_got_ipv6(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data);
static esp_err_t sta_wifi_sta_do_disconnect(void);

2.函数的实现

static bool sta_is_our_netif(const char *prefix, esp_netif_t *netif)
{
    return strncmp(prefix, esp_netif_get_desc(netif), strlen(prefix) - 1) == 0;
}
static void sta_event_handler_unregister(void)
{
    ESP_ERROR_CHECK(esp_event_handler_unregister(WIFI_EVENT, WIFI_EVENT_STA_DISCONNECTED, &sta_handler_on_wifi_disconnect));
    ESP_ERROR_CHECK(esp_event_handler_unregister(WIFI_EVENT, WIFI_EVENT_STA_CONNECTED, &sta_handler_on_wifi_connect));

    ESP_ERROR_CHECK(esp_event_handler_unregister(IP_EVENT, IP_EVENT_STA_GOT_IP, &sta_handler_on_sta_got_ip));
    ESP_ERROR_CHECK(esp_event_handler_unregister(IP_EVENT, IP_EVENT_GOT_IP6, &sta_handler_on_sta_got_ipv6));
}

static esp_err_t sta_wifi_sta_do_disconnect(void)
{
    sta_event_handler_unregister();

    return esp_wifi_disconnect();
}

static void sta_handler_on_wifi_connect(void *esp_netif, esp_event_base_t event_base, int32_t event_id, void *event_data)
{
    esp_netif_create_ip6_linklocal(esp_netif);
}

static void sta_handler_on_wifi_disconnect(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data)
{
    s_retry_num++;
    if (s_retry_num > 5) // 重连5次失败,关闭stawifi
    {
        ESP_LOGI(TAG, "WiFi Connect failed %d times, stop reconnect.", s_retry_num);
        sta_wifi_sta_do_disconnect();
        return;
    }

    wifi_event_sta_disconnected_t *disconn = event_data;
    if (disconn->reason == WIFI_REASON_ROAMING)
    {
        ESP_LOGD(TAG, "station roaming, do nothing");
        return;
    }

    ESP_LOGI(TAG, "Wi-Fi disconnected %d, trying to reconnect...", disconn->reason);
    esp_err_t err = esp_wifi_connect();
    if (err == ESP_ERR_WIFI_NOT_STARTED)
    {
        return;
    }
    ESP_ERROR_CHECK(err);
}
static void sta_handler_on_sta_got_ip(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data)
{
    s_retry_num = 0;
    ip_event_got_ip_t *event = (ip_event_got_ip_t *)event_data;
    if (!sta_is_our_netif(STA_NETIF_DESC, event->esp_netif))
    {
        return;
    }

    ESP_LOGI(TAG, "Got IPv4 event: Interface \"%s\" address: " IPSTR, esp_netif_get_desc(event->esp_netif), IP2STR(&event->ip_info.ip));
}

static void sta_handler_on_sta_got_ipv6(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data)
{
    ip_event_got_ip6_t *event = (ip_event_got_ip6_t *)event_data;
    if (!sta_is_our_netif(STA_NETIF_DESC, event->esp_netif))
    {
        return;
    }

    esp_ip6_addr_type_t ipv6_type = esp_netif_ip6_get_addr_type(&event->ip6_info.ip);
    ESP_LOGI(TAG, "Got IPv6 event: Interface \"%s\" address: " IPV6STR ", type: %s", esp_netif_get_desc(event->esp_netif),
             IPV62STR(event->ip6_info.ip), example_ipv6_addr_types_to_str[ipv6_type]);

}

七、配置所要连接的热点

void sta_ssid_password_config(char *sta_ssid, char *sta_password)
{
    wifi_config_t wifi_config = {
        .sta = {
            .ssid = "",
            .password = "",
            .scan_method = WIFI_ALL_CHANNEL_SCAN,
            .threshold.authmode = WIFI_AUTH_WPA2_PSK,
        },
    };

    if (sta_ssid != NULL)
    {
        memset((char *)wifi_config.sta.ssid, 0, sizeof((char *)wifi_config.sta.ssid));
        memcpy((char *)wifi_config.sta.ssid, sta_ssid, strlen(sta_ssid));
    }

    if (sta_password != NULL)
    {
        memset((char *)wifi_config.sta.password, 0, sizeof((char *)wifi_config.sta.password));
        memcpy((char *)wifi_config.sta.password, sta_password, strlen(sta_password));
    }

    ESP_LOGI("", "Connecting to %s...", wifi_config.sta.ssid);
    ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config));
}

八、启动wifi 并连接wifi 

    ESP_ERROR_CHECK(esp_wifi_start());
    esp_wifi_connect();

九、连接所有模块

void sta_connet_init(char *sta_ssid, char *sta_password)
{
    
    /***********sta netif初始化   对应标题5*********/
    sta_netif_config();
    /****************************************************************/
    /***********sta 事件句柄初始化   对应标题6*********/
    sta_event_handler_register();
    /****************************************************************/
    /***********配置所要连接的wifi热点   对应标题7*********/
    sta_ssid_password_config(sta_ssid, sta_password);
    /****************************************************************/
}


void wifi_connect(void)
{
    ESP_LOGI("", "Start example_connect.");
    sta_connet_init("wifi_ssid", "wifi_password");
    /***********启动wifi并连接热点   对应标题8*********/
    ESP_ERROR_CHECK(esp_wifi_start());
    esp_wifi_connect();
    /****************************************************************/
}


void wifi_init()
{

    /***********NVS初始化   对应标题3*********/
    esp_err_t ret = nvs_flash_init();
    if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND)
    {
        ESP_ERROR_CHECK(nvs_flash_erase());
        ret = nvs_flash_init();
    }
    ESP_ERROR_CHECK(ret);
    /****************************************************************/
    /**********wifi 基础部分初始化 对应标题4***********/
    ESP_ERROR_CHECK(esp_netif_init());
    ESP_ERROR_CHECK(esp_event_loop_create_default());

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

    ESP_ERROR_CHECK(esp_wifi_set_storage(WIFI_STORAGE_RAM));
    ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_APSTA));
    /****************************************************************/
    wifi_connect();
}

九、效果

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

小鱼儿-余

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

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

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

打赏作者

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

抵扣说明:

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

余额充值