ESP32 强制门户 WEB配网
修改自此博主代码
参考博客
参考WEB配网的网页代码
ESP32学习笔记(23)——NVS(非易失性存储)接口使用
目录
前言
一、工程创建
1.获取源代码
2.新建一个ESP32的工程
3.移植代码到工程下
4.修改工程的配置信息
二、修改工程代码
1.main.c
2.ConnectWIFI.c
3.webserver.c
4.my_dns_server.c
三、测试
四、说明
前言
使用WEB配网可以使ESP32连接到WIFI更加的便捷,灵活性更高
一、工程创建
1.获取源代码
先拿到博主大大的代码代码在 13_captive_portal
2.新建一个ESP32的工程
3.移植代码到工程下
把博主其中的两份代码复制到新建的工程下
因为配网要连接WIFI,所以给连接WIFI单独写在一文件(自己新建)中,实现WIFI的STA和AP模式(移植自IDF的其他示例工程)
文件目录如下:
4.修改工程的配置信息
修改main下的CMakeLists.txt
修改如下内容
idf_component_register(SRCS "main.c" "./WIFI/ConnectWIFI.c" "./dns_server/my_dns_server.c" "./web_server/webserver.c" "./tcp_client/tcp_client.c"INCLUDE_DIRS "." "./WIFI" "./dns_server" "./web_server" "./tcp_client"EMBED_FILES "./web_server/index.html")
因为嵌入html,所以 EMBED_FILES "./web_server/index.html" 就是对html的处理
二、修改工程代码
1.main.c
#include <stdio.h>#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"#include "nvs_flash.h"
#include "esp_vfs_fat.h"#include <netdb.h>
#include <sys/socket.h>#include "WIFI/ConnectWIFI.h"
#include "my_dns_server.h"#include "webserver.h"void app_main(void)
{ESP_ERROR_CHECK( nvs_flash_init() );//NvsWriteDataToFlash("","","");char WIFI_Name[50] = { 0 };char WIFI_PassWord[50] = { 0 }; /*读取保存的WIFI信息*/if(NvsReadDataFromFlash("WIFI Config Is OK!",WIFI_Name,WIFI_PassWord) == 0x00){printf("WIFI SSID :%s\r\n",WIFI_Name );printf("WIFI PASSWORD :%s\r\n",WIFI_PassWord);printf("开始初始化WIFI Station 模式\r\n");wifi_init_sta(WIFI_Name,WIFI_PassWord); /*按照读取的信息初始化WIFI Station模式*/}else{printf("未读取到WIFI配置信息\r\n");printf("开始初始化WIFI AP 模式\r\n");WIFI_AP_Init(); /*上电后配置WIFI为AP模式*///vTaskDelay(1000 / portTICK_PERIOD_MS);dns_server_start(); //开启DNS服务web_server_start(); //开启http服务}}
2.ConnectWIFI.c
别忘了修改一下STA模式下的WIFI的名字密码
#include <stdio.h>
#include "WIFI/ConnectWIFI.h"
/* The examples use WiFi configuration that you can set via project configuration menu.If you'd rather not, just change the below entries to strings withthe config you want - ie #define EXAMPLE_WIFI_SSID "mywifissid"
*/
#define EXAMPLE_ESP_WIFI_SSID "设置WIFI STA模式的名字"
#define EXAMPLE_ESP_WIFI_PASS "设置WIFI STA模式的密码"
#define EXAMPLE_ESP_WIFI_CHANNEL (10)
#define EXAMPLE_MAX_STA_CONN (1)// #define EXAMPLE_ESP_WIFI_SSID "espConnect"
// #define EXAMPLE_ESP_WIFI_PASS "12345678"
#define EXAMPLE_ESP_MAXIMUM_RETRY 10#define CONFIG_ESP_WIFI_AUTH_OPEN 1#if CONFIG_ESP_WIFI_AUTH_OPEN
#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_OPEN
#elif CONFIG_ESP_WIFI_AUTH_WEP
#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WEP
#elif CONFIG_ESP_WIFI_AUTH_WPA_PSK
#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA_PSK
#elif CONFIG_ESP_WIFI_AUTH_WPA2_PSK
#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA2_PSK
#elif CONFIG_ESP_WIFI_AUTH_WPA_WPA2_PSK
#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA_WPA2_PSK
#elif CONFIG_ESP_WIFI_AUTH_WPA3_PSK
#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA3_PSK
#elif CONFIG_ESP_WIFI_AUTH_WPA2_WPA3_PSK
#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA2_WPA3_PSK
#elif CONFIG_ESP_WIFI_AUTH_WAPI_PSK
#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WAPI_PSK
#endifstatic void wifi_event_handler(void* arg, esp_event_base_t event_base,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("ESP32", "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("ESP32", "station "MACSTR" leave, AID=%d",MAC2STR(event->mac), event->aid);}
}void WIFI_AP_Init(void)
{ESP_LOGI("ESP32", "WIFI Start Init");ESP_ERROR_CHECK(esp_netif_init()); /*初始化底层TCP/IP堆栈*/ESP_ERROR_CHECK(esp_event_loop_create_default()); /*创建默认事件循环*/esp_netif_create_default_wifi_ap(); /*创建默认WIFI AP,如果出现任何初始化错误,此API将中止*/wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();ESP_ERROR_CHECK(esp_wifi_init(&cfg)); /*初始化WiFi为WiFi驱动程序分配资源,如WiFi控制结构、RX/TX缓冲区、WiFi NVS结构等。此WiFi还启动WiFi任务。*/ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT,ESP_EVENT_ANY_ID,&wifi_event_handler,NULL,NULL));wifi_config_t wifi_config = {.ap = {.ssid = EXAMPLE_ESP_WIFI_SSID,.ssid_len = strlen(EXAMPLE_ESP_WIFI_SSID),.channel = EXAMPLE_ESP_WIFI_CHANNEL,.password = EXAMPLE_ESP_WIFI_PASS,.max_connection = EXAMPLE_MAX_STA_CONN,.authmode = WIFI_AUTH_WPA_WPA2_PSK},};if (strlen(EXAMPLE_ESP_WIFI_PASS) == 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("ESP32", "wifi_init_softap finished. SSID:%s password:%s channel:%d",EXAMPLE_ESP_WIFI_SSID, EXAMPLE_ESP_WIFI_PASS, EXAMPLE_ESP_WIFI_CHANNEL);
}/* FreeRTOS event group to signal when we are connected*/
static EventGroupHandle_t s_wifi_event_group;/* The event group allows multiple bits for each event, but we only care about two events:* - we are connected to the AP with an IP* - we failed to connect after the maximum amount of retries */
#define WIFI_CONNECTED_BIT BIT0
#define WIFI_FAIL_BIT BIT1static const char *TAG = "wifi station";static int s_retry_num = 0;static void event_handler(void* arg, esp_event_base_t event_base,int32_t event_id, void* event_data)
{if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) {esp_wifi_connect();} else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) {if (s_retry_num < EXAMPLE_ESP_MAXIMUM_RETRY) {esp_wifi_connect();s_retry_num++;ESP_LOGI(TAG, "retry to connect to the AP");} else {xEventGroupSetBits(s_wifi_event_group, WIFI_FAIL_BIT);}ESP_LOGI(TAG,"connect to the AP fail");} else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {ip_event_got_ip_t* event = (ip_event_got_ip_t*) event_data;ESP_LOGI(TAG, "got ip:" IPSTR, IP2STR(&event->ip_info.ip));s_retry_num = 0;xEventGroupSetBits(s_wifi_event_group, WIFI_CONNECTED_BIT);}
}void wifi_init_sta(char *WIFI_Name,char *WIFI_PassWord)
{s_wifi_event_group = xEventGroupCreate();ESP_ERROR_CHECK(esp_netif_init());ESP_ERROR_CHECK(esp_event_loop_create_default());esp_netif_create_default_wifi_sta();wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();ESP_ERROR_CHECK(esp_wifi_init(&cfg));esp_event_handler_instance_t instance_any_id;esp_event_handler_instance_t instance_got_ip;ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT,ESP_EVENT_ANY_ID,&event_handler,NULL,&instance_any_id));ESP_ERROR_CHECK(esp_event_handler_instance_register(IP_EVENT,IP_EVENT_STA_GOT_IP,&event_handler,NULL,&instance_got_ip));wifi_config_t wifi_config = {.sta = {/* Setting a password implies station will connect to all security modes including WEP/WPA.* However these modes are deprecated and not advisable to be used. Incase your Access point* doesn't support WPA2, these mode can be enabled by commenting below line */.threshold.authmode = ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD,},};strcpy((char *)&wifi_config.sta.ssid,WIFI_Name);strcpy((char *)&wifi_config.sta.password,WIFI_PassWord);ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA) );ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config) );ESP_ERROR_CHECK(esp_wifi_start() );ESP_LOGI(TAG, "wifi_init_sta finished.");/* Waiting until either the connection is established (WIFI_CONNECTED_BIT) or connection failed for the maximum* number of re-tries (WIFI_FAIL_BIT). The bits are set by event_handler() (see above) */EventBits_t bits = xEventGroupWaitBits(s_wifi_event_group,WIFI_CONNECTED_BIT | WIFI_FAIL_BIT,pdFALSE,pdFALSE,portMAX_DELAY);/* xEventGroupWaitBits() returns the bits before the call returned, hence we can test which event actually* happened. */if (bits & WIFI_CONNECTED_BIT) {ESP_LOGI(TAG, "connected to ap SSID:%s password:%s",WIFI_Name, WIFI_PassWord);//xTaskCreate(tcp_client_task, "tcp_client", 1024 * 10, NULL, 5, NULL);/*TCP_client 连接TCP*/} else if (bits & WIFI_FAIL_BIT) {ESP_LOGI(TAG, "Failed to connect to SSID:%s, password:%s",WIFI_Name, WIFI_PassWord);NvsWriteDataToFlash("","","");/*超出最大重连次数后,退出连接,清楚保存的连接信息,重启*/esp_restart();} else {ESP_LOGE(TAG, "UNEXPECTED EVENT");}
}void NvsWriteDataToFlash(char *ConfirmString,char *WIFI_Name,char *WIFI_PassWord)
{nvs_handle handle;// 写入一个整形数据,一个字符串,WIFI信息以及版本信息static const char *NVS_CUSTOMER = "customer data";static const char *DATA2 = "String";static const char *DATA3 = "blob_wifi";// static const char *DATA4 = "blob_version";// // 要写入的字符串// char str_for_store[50] = "WIFI Config Is OK!";// 要写入的WIFI信息wifi_config_t wifi_config_to_store;// wifi_config_t wifi_config_to_store = {// .sta = {// .ssid = "store_ssid:hello_kitty",// .password = "store_password:1234567890",// },// };strcpy((char *)&wifi_config_to_store.sta.ssid,WIFI_Name);strcpy((char *)&wifi_config_to_store.sta.password,WIFI_PassWord);// // 要写入的版本号// uint8_t version_for_store[4] = {0x01, 0x01, 0x01, 0x00};printf("set size:%u\r\n", sizeof(wifi_config_to_store));ESP_ERROR_CHECK( nvs_open( NVS_CUSTOMER, NVS_READWRITE, &handle) );ESP_ERROR_CHECK( nvs_set_str( handle, DATA2, ConfirmString) );ESP_ERROR_CHECK( nvs_set_blob( handle, DATA3, &wifi_config_to_store, sizeof(wifi_config_to_store)) );// ESP_ERROR_CHECK( nvs_set_blob( handle, DATA4, version_for_store, 4) );ESP_ERROR_CHECK( nvs_commit(handle) );nvs_close(handle);}unsigned char NvsReadDataFromFlash(char *ConfirmString,char *WIFI_Name,char *WIFI_PassWord)
{nvs_handle handle;static const char *NVS_CUSTOMER = "customer data";static const char *DATA2 = "String";static const char *DATA3 = "blob_wifi";// static const char *DATA4 = "blob_version";uint32_t str_length = 50;char str_data[50] = {0};wifi_config_t wifi_config_stored;// uint8_t version[4] = {0};// uint32_t version_len = 4;memset(&wifi_config_stored, 0x0, sizeof(wifi_config_stored));uint32_t wifi_len = sizeof(wifi_config_stored);ESP_ERROR_CHECK( nvs_open(NVS_CUSTOMER, NVS_READWRITE, &handle) );ESP_ERROR_CHECK ( nvs_get_str(handle, DATA2, str_data, &str_length) );ESP_ERROR_CHECK ( nvs_get_blob(handle, DATA3, &wifi_config_stored, &wifi_len) );// ESP_ERROR_CHECK ( nvs_get_blob(handle, DATA4, version, &version_len) );printf("[data1]: %s len:%u\r\n", str_data, str_length);printf("[data3]: ssid:%s passwd:%s\r\n", wifi_config_stored.sta.ssid, wifi_config_stored.sta.password);strcpy(WIFI_Name,(char *)&wifi_config_stored.sta.ssid);strcpy(WIFI_PassWord,(char *)&wifi_config_stored.sta.password);nvs_close(handle);if(strcmp(ConfirmString,str_data) == 0){return 0x00;}else{return 0xFF;}
}
ConnectWIFI.h
#ifndef _CONNECT_WIFI_H
#define _CONNECT_WIFI_H
#include <string.h>
#include <stdlib.h>#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include "esp_system.h"
#include "esp_event.h"#include "esp_wifi.h"
#include "nvs_flash.h"
#include "esp_log.h"#include "lwip/err.h"
#include "lwip/sys.h"void WIFI_AP_Init(void);void wifi_init_sta(char *WIFI_Name,char *WIFI_PassWord);void NvsWriteDataToFlash(char *ConfirmString,char *WIFI_Name,char *WIFI_PassWord);
unsigned char NvsReadDataFromFlash(char *ConfirmString,char *WIFI_Name,char *WIFI_PassWord);#endif
3.webserver.c
#include <string.h>
#include <stdlib.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"#include "esp_wifi.h"
#include "esp_event.h"
#include "esp_log.h"#include "nvs_flash.h"#include "lwip/err.h"
#include "lwip/sockets.h"
#include "lwip/sys.h"
#include "lwip/netdb.h"
#include "lwip/dns.h"#include "esp_http_server.h"#include "webserver.h"
#include "WIFI/ConnectWIFI.h"extern const uint8_t index_html_start[] asm("_binary_index_html_start");
extern const uint8_t index_html_end[] asm("_binary_index_html_end");static const char *TAG = "WEB_SERVER";#define MIN( x, y ) ( ( x ) < ( y ) ? ( x ) : ( y ) )/* Send HTTP response with a run-time generated html consisting of* a list of all files and folders under the requested path.* In case of SPIFFS this returns empty list when path is any* string other than '/', since SPIFFS doesn't support directories */
static esp_err_t http_SendText_html(httpd_req_t *req)
{/* Get handle to embedded file upload script */const size_t upload_script_size = (index_html_end - index_html_start);const char TxBuffer[] = "<h1> SSID1 other WIFI</h1>";/* Add file upload form and script which on execution sends a POST request to /upload */httpd_resp_send_chunk(req, (const char *)index_html_start, upload_script_size);httpd_resp_send_chunk(req,(const char *)TxBuffer,sizeof(TxBuffer));return ESP_OK;
}
unsigned char CharToNum(unsigned char Data)
{if(Data >= '0' && Data <= '9'){return Data - '0';}else if(Data >= 'a' && Data <= 'f'){switch (Data){case 'a':return 10;case 'b':return 11;case 'c':return 12;case 'd':return 13;case 'e':return 14;case 'f':return 15;default:break;}}else if(Data >= 'A' && Data <= 'F'){switch (Data){case 'A':return 10;case 'B':return 11;case 'C':return 12;case 'D':return 13;case 'E':return 14;case 'F':return 15;default:break;}}return 0;
}
/* 强制门户访问时连接wifi后的第一次任意GET请求 */
static esp_err_t HTTP_FirstGet_handler(httpd_req_t *req)
{http_SendText_html(req);return ESP_OK;
}
/* 门户页面发回的,带有要连接的WIFI的名字和密码 */
static esp_err_t WIFI_Config_POST_handler(httpd_req_t *req)
{char buf[100];int ret, remaining = req->content_len;while (remaining > 0) {/* Read the data for the request */if ((ret = httpd_req_recv(req, buf,MIN(remaining, sizeof(buf)))) <= 0) {if (ret == HTTPD_SOCK_ERR_TIMEOUT) {/* Retry receiving if timeout occurred */continue;}return ESP_FAIL;}/* Send back the same data */char WIFI_ConfigBackInformation[100] = "The WIFI To Connect :";strcat(WIFI_ConfigBackInformation,buf);httpd_resp_send_chunk(req, WIFI_ConfigBackInformation, sizeof(WIFI_ConfigBackInformation));remaining -= ret;char wifi_name[50];char wifi_password[50];char wifi_passwordTransformation[50] = {0};esp_err_t e = httpd_query_key_value(buf,"ssid",wifi_name,sizeof(wifi_name));if(e == ESP_OK) {printf("SSID = %s\r\n",wifi_name);}else {printf("error = %d\r\n",e);}e = httpd_query_key_value(buf,"passWord",wifi_password,sizeof(wifi_password));if(e == ESP_OK) {/*对传回来的数据进行处理*/unsigned char Len = strlen(wifi_password);char tempBuffer[2];char *temp;unsigned char Cnt = 0;temp = wifi_password;for(int i=0;i<Len;){if(*temp == '%'){tempBuffer[0] = CharToNum(temp[1]);tempBuffer[1] = CharToNum(temp[2]);*temp = tempBuffer[0] * 16 + tempBuffer[1];wifi_passwordTransformation[Cnt] = *temp;temp+=3;i+=3;Cnt++;}else{wifi_passwordTransformation[Cnt] = *temp;temp++;i++;Cnt++;}}temp -= Len;printf("Len = %d\r\n",Len);printf("wifi_password = %s\r\n",wifi_password);printf("pswd = %s\r\n",wifi_passwordTransformation);}else {printf("error = %d\r\n",e);}/* Log data received */ESP_LOGI(TAG, "=========== RECEIVED DATA ==========");ESP_LOGI(TAG, "%.*s", ret, buf);ESP_LOGI(TAG, "====================================");NvsWriteDataToFlash("WIFI Config Is OK!",wifi_name,wifi_passwordTransformation);esp_restart();// esp_wifi_stop();// esp_event_handler_unregister(WIFI_EVENT,// ESP_EVENT_ANY_ID,// &wifi_event_handler// );// esp_netif_destroy_default_wifi(ap_netif);// esp_event_loop_delete_default();// esp_wifi_deinit();// esp_netif_deinit();// httpd_stop(server);// printf("hello \r\n");// ESP_LOGI(TAG,"led on");// wifi_init_sta(wifi_name,wifi_passwordTransformation);}return ESP_OK;
}void web_server_start(void)
{// xTaskCreate(&webserver, "webserver_task", 2048, NULL, 5, NULL);httpd_handle_t server = NULL;httpd_config_t config = HTTPD_DEFAULT_CONFIG();/* Use the URI wildcard matching function in order to* allow the same handler to respond to multiple different* target URIs which match the wildcard scheme */config.uri_match_fn = httpd_uri_match_wildcard;ESP_LOGI(TAG, "Starting HTTP Server on port: '%d'", config.server_port);if (httpd_start(&server, &config) != ESP_OK) {ESP_LOGE(TAG, "Failed to start file server!");return ;}/* URI handler for getting uploaded files */httpd_uri_t file_download = {.uri = "/*", // Match all URIs of type /path/to/file.method = HTTP_GET,.handler = HTTP_FirstGet_handler,.user_ctx = NULL,};httpd_register_uri_handler(server, &file_download);/* URI handler for uploading files to server */httpd_uri_t file_upload = {.uri = "/configwifi", // Match all URIs of type /upload/path/to/file.method = HTTP_POST,.handler = WIFI_Config_POST_handler,.user_ctx = NULL,};httpd_register_uri_handler(server, &file_upload);}
webserver.h
#ifndef WEB_SERVER_h
#define WEB_SERVER_h#ifdef __cplusplus
extern "C"
{
#endifvoid web_server_start(void);#endif
index.html
<!DOCTYPE html>
<html><head><title>WIFI</title><meta name="viewport" content="width=device-width, initial-scale=1"></head><style type="text/css">.input{display: block; margin-top: 10px;}.input span{width: 100px; float: left; float: left; height: 36px; line-height: 36px;}.input input{height: 30px;width: 200px;}.btn{width: 120px; height: 35px; background-color: #000000; border:0px; color:#ffffff; margin-top:15px; margin-left:100px;}</style><body><form method="POST" action="configwifi"><label class="input"><span>WiFi SSID </span><input type="text" name="SSID"></label><label class="input"><span>WiFi PASS</span> <input type="text" name="passWord"></label><input class="btn" type="submit" name="submit" value="Submie"> <p><span> Nearby wifi:</P></form></body>
</html>
4.my_dns_server.c
#include <string.h>
#include <sys/param.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include "esp_system.h"
#include "esp_wifi.h"
#include "esp_event.h"
#include "esp_log.h"
#include "nvs_flash.h"
#include "cJSON.h"#include "lwip/err.h"
#include "lwip/sockets.h"
#include "lwip/sys.h"
#include <lwip/netdb.h>
#include "mbedtls/md5.h"
#include "webserver.h"static const char *TAG = "DNS_SERVER";static int create_udp_socket(int port)
{struct sockaddr_in saddr = { 0 };int sock = -1;int err = 0;sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);if (sock < 0) {ESP_LOGE(TAG,"Failed to create socket. Error %d", errno);return -1;}// Bind the socket to any addresssaddr.sin_family = PF_INET;saddr.sin_port = htons(port);saddr.sin_addr.s_addr = htonl(INADDR_ANY);err = bind(sock, (struct sockaddr *)&saddr, sizeof(struct sockaddr_in));if (err < 0) {ESP_LOGE(TAG,"Failed to bind socket. Error %d", errno);goto err;}// All set, socket is configured for sending and receivingreturn sock;err:close(sock);return -1;
}static void my_dns_server(void *pvParameters)
{
/* Wait for all the IPs we care about to be set*/uint8_t data[128];int len = 0;struct sockaddr_in client = { 0 };socklen_t client_len=sizeof(struct sockaddr_in); uint32_t i = 0;ESP_LOGI(TAG,"DNS server start ...");int sock = create_udp_socket(53);if (sock < 0) {ESP_LOGE(TAG,"Failed to create IPv4 multicast socket");}while(1){len=recvfrom(sock,data,100,0,(struct sockaddr *)&client,&client_len); //阻塞式if((len < 0) || ( len > 100)){ESP_LOGE(TAG,"recvfrom error\n");continue;}printf("DNS request:");for(i = 0x4; i< len;i++){if((data[i] >= 'a' && data[i] <= 'z') || (data[i] >= 'A' && data[i] <= 'Z') ||(data[i] >= '0' && data[i] <= '9'))printf("%c",data[i]);elseprintf("_");}printf("\r\n");//printf("%d\r\n",esp_get_free_heap_size()); //打印系统可用内存//过滤掉一些乱糟糟的域名if( strstr((const char *)data+0xc,"taobao")||strstr((const char *)data+0xc,"qq") || strstr((const char *)data+0xc,"sogou") ||strstr((const char *)data+0xc,"amap") ||strstr((const char *)data+0xc,"alipay")||strstr((const char *)data+0xc,"youku") ||strstr((const char *)data+0xc,"iqiyi") ||strstr((const char *)data+0xc,"baidu")){continue;}data[2] |= 0x80;data[3] |= 0x80;data[7] =1;data[len++] =0xc0;data[len++] =0x0c;data[len++] =0x00;data[len++] =0x01;data[len++] =0x00;data[len++] =0x01;data[len++] =0x00;data[len++] =0x00;data[len++] =0x00;data[len++] =0x0A;data[len++] =0x00;data[len++] =0x04;data[len++] =192;data[len++] =168;data[len++] =4;data[len++] =1;/*打印客户端地址和端口号*/// inet_ntop(AF_INET,&client.sin_addr,(char *)data,sizeof(data));// printf("client IP is %s, port is %d\n",data,ntohs(client.sin_port));sendto(sock,data,len,0,(struct sockaddr*)&client,client_len);vTaskDelay(10);}ESP_LOGE(TAG,"DNS server stop ...");shutdown(sock, 0);close(sock);vTaskDelete(NULL);
}void dns_server_start()
{xTaskCreate(&my_dns_server, "dns_task", 2048, NULL, 5, NULL);
}
my_dns_server.h
#ifndef MY_DNS_SERVER_h
#define MY_DNS_SERVER_h#ifdef __cplusplus
extern "C"
{
#endifvoid dns_server_start();#ifdef __cplusplus
}
#endif
#endif
三、测试
首次编译下载后:
连接ESP32发出的热点
连接后会弹出浏览器,没有弹出可以手动输入192.168.4.1也可以进入WEB配网界面
输入要连接的WIFI后,ESP32会重启自动连接
四、说明
由于代码基本是拼凑起来的,稳定性不能保证,正式使用还需要多次测试
其实还可以添加搜索附近WIFI的功能(官方例程自带)这样就可以避免输入WIFI名字
ESP32 强制门户 WEB配网相关推荐
- ESP8266的Web配网以及强制门户的实现(连接wifi自动打开网页)
目录 前言 Web配网详解 强制门户详解 完整代码 实验效果 前言 1.Web配网概述 在应用到esp8266的场景,往往与wifi是离不开的,但用户的wifi账号密码又无从知晓,于是乎有了配网. 目 ...
- 验证可用的ESP32/8266配网方式,开源代码,web配网,smartconfig配网
web配网 设备内做了个小web服务器通过网页交换SSID和PWD.这个方式比较友好,不依赖外部app或小程序,保密性更好,产品可用性更好(苹果等个别手机不能打开配网页面可直接浏览器登陆192.168 ...
- ESP8266开发之旅 网络篇⑭ web配网
文章目录 1. 前言 2. Web配网(AP配网) 2.1 自定义AP配网 2.2 WiFiManager 3. 总结 授人以鱼不如授人以渔,目的不是为了教会你具体项目开发,而是学会学习的能力.希望大 ...
- ESP32 C3 使用ConfigWiFi配网
ESP32C3 的配网方式有好多种,这里主要使用AP配网方式.在 ESP32C3 上建立热点AP,使用手机连接上后在浏览器打开配置网页,输入WIFI信息,完成配网.这种方式很可靠,而且允许在电脑端完成 ...
- ESP8266 web配网微信小程序配网 全平台配网库 arduino 傻瓜式通用库
wifi_link_tool esp8266通用配网库 (arduino) 库地址:点击进入GitHub 这是一个为esp8266设计的通用配网库 该库免费提供 使用请注明出处 允许毕业设计使用本库 ...
- ESP32 smart_config和airkiss配网
陈拓 2021/11/28-2021/11/30 1. 简介 官方例程: https://gitee.com/EspressifSystems/esp-idf/tree/master/examples ...
- Arduino ESP32Web配网(二)
Arduino ESP32Web配网(二) 相关篇<Arduino ESP32Web配网> 相对于之前的那篇文章,这篇的配网有不同的地方就是,html页面修饰了一下. 配网操作 1.如果是 ...
- ESP32常见配网方式分析
ESP32常见配网方式分析 SoftAP 配网 BLE 配网 Smartconfig 配网: WEB 配网: SoftAP 配网 在 SoftAP 模式下,ESP32会充当临时的 Wi-Fi 接入点. ...
- 【工程师有空了】安信可ESP8266系列及ESP32系列模组AT指令实现网页配网---又多了一个配网方式
文章目录 前言 AT指令介绍: 配网原理 一.实验准备 可能你还要用到: 二.编译固件 三.开启配网 四.常见问题 1.AT固件烧录不显示 "ready" 2.显示配网失败 3.除 ...
最新文章
- 近期必读的6篇NeurIPS 2019零样本学习论文
- 蚂蚁金服开源增强版Spring Boot 的研发框架!
- Java swing 如何将一个按钮放置到弹出框框的任意位置?(Absolute layout 布局的使用)...
- 前端大神用React刻了一个Windows XP
- linux路由修改密码,Linux中修改Mysql root用户密码的方法
- 遍历HashMap的最佳方法
- vite配置 vite.config.js
- 修改mysql编码方式
- linux网络安装mysql_linux系统安装mysql
- Python Day56-57 js
- dtu阿里云自定义透传
- LabVIEW基于Kvaser USBcan的UDS烧录Hex文件
- 计算机类专业哪些专业比较好,计算机类专业有哪些 哪个专业比较好
- c语言项目研发实训,C语言实训项目表V1.0.doc
- 站群网站八大盈利模式浅析
- 飞机飞行与碰撞问题matlab,建模案例—飞行管理问题.ppt
- QQ农场破解思路(版本20091212)
- # android移动开发——第十三章——个人理财通案例(Eclipse版)
- 一九产业AI速写:工业篇
- 操作系统学习笔记:保护
热门文章
- Netty-编码和解码
- XX健康:预约管理-预约设置日历插件文件简单下载Excel文件解析Excel表数据批量导入
- 二阶振荡环节的谐振频率_典型环节的频率特性二阶振荡环节-西安电子科技大学.PPT...
- CSMA/CD中重传与冲突检测机制
- oracle日记账查询,OraEBSR12GL日记账业务操作16:按汇总模板进行查询
- win7/win10屏幕录制教程?--QVE屏幕录制
- 微型计算机原理及应用第四版第七章课后答案,郑学坚微型计算机原理及应用第4版笔记和课后习题答案详解...
- CKEditor 4使用方法,来自http://docs.ckeditor.com/#!/guide/dev_ckeditor_js_load官网地址
- MyBatis动态批量插入、更新Mysql数据库的通用实现方案
- 检测到可疑访问 php,php.net被Chrome/Firefox浏览器标注为可疑站点