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 with
   the 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
#endif

static 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      BIT1

static 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"
{
#endif

void 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 address
    saddr.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 receiving
    return 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]);
            else
                printf("_");

        }
        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"
{
#endif

void dns_server_start();

#ifdef __cplusplus
}
#endif
#endif  

三、测试

首次编译下载后:

连接ESP32发出的热点

 连接后会弹出浏览器,没有弹出可以手动输入192.168.4.1也可以进入WEB配网界面

 输入要连接的WIFI后,ESP32会重启自动连接

四、说明

由于代码基本是拼凑起来的,稳定性不能保证,正式使用还需要多次测试

其实还可以添加搜索附近WIFI的功能(官方例程自带)这样就可以避免输入WIFI名字

 

  • 11
    点赞
  • 39
    收藏
    觉得还不错? 一键收藏
  • 12
    评论
评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值