背景:众所周知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.运行效果
废话少说,直接上代码
目录
一、头文件
#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();
}