ESP8266 NonOS-SDK Web配网

本文详细介绍了如何使用ESP8266 NonOS-SDK实现通过Web界面配置Wi-Fi的功能,包括初始化WebServer、SoftAP,数据接收和处理,以及关键步骤的代码解析。通过浏览器连接到ESP8266热点,输入WiFi账号和密码,实现实体设备的自动连接。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

参考博客:[网络篇]ESP8266-SDK教程(六)之网页配置Wi-Fi名称和密码

一、原理

        ESP8266 设置为 STATION + AP 模式。
        STATION 模式又叫做站点工作模式,类似于无线终端,处于 STATION 模式下的 ESP8266,可以连接到 AP。通过 STATION (简称为“STA”)模式,ESP8266 作为客户端连接到路由的 Wi-Fi 信号。
        AP 就是 Access Point 接入点。由 ESP8266 自己开启热点,供别的设备接入,组成一个局域网。

        流程就是这个样子,手机 / 电脑连接 ESP8266 开启的热点,在浏览器打开配网网页,通过网页发送 SSID 和 PWD 给 ESP8266,ESP8266 解析以后得到 SSID 和 PWD 去连接 Wi-Fi。

        我们需要将这个写好的网页,保存到 ESP8266 当中,当 ESP8266 收到 http 请求时,我们再将这个网页发送给浏览器,此时 ESP8266 就是一个很小的 Web Server,处理来自浏览器的 http 请求,然后按照一定格式返回具体的网页,或者其他数据,这些都是通过 TCP 传输的。

二、程序解析

程序我们可以通过 NonOS-SDK 自带的 WebServer 进行改动。

1、初始化 WebServer

//初始化webserver,webserver端口为80,可以通过初始化时传入
void ICACHE_FLASH_ATTR
www_webserver_init(uint32 port) {
	LOCAL struct espconn esp_conn;
	LOCAL esp_tcp esptcp;

	esp_conn.type = ESPCONN_TCP;
	esp_conn.state = ESPCONN_NONE;
	esp_conn.proto.tcp = &esptcp;
	esp_conn.proto.tcp->local_port = port;
	espconn_regist_connectcb(&esp_conn, www_webserver_listen);
	espconn_accept(&esp_conn);
}

2、初始化 SoftAP

/*
 * softAP模式初始化代码
 */
void ICACHE_FLASH_ATTR
www_softAP_init(void){
	struct softap_config soft_ap_Config;

	//wifi_set_opmode_current(SOFTAP_MODE);//设置为AP模式,不保存到flash
	wifi_set_opmode(STATIONAP_MODE);//设置为STATION+AP模式,并保存到flash

	os_memset(&soft_ap_Config, 0, sizeof(struct softap_config)); // AP参数结构体 = 0

	soft_ap_Config.ssid_len = os_strlen(AP_NAME);//热点名称长度,与你实际的名称长度一致就好
	os_strcpy(soft_ap_Config.ssid, AP_NAME);//实际热点名称设置,可以根据你的需要来
	os_strcpy(soft_ap_Config.password, AP_PWD);//热点密码设置
	soft_ap_Config.authmode = AUTH_OPEN;//若是你的密码为空,加密模式为AUTH_WPA2_PSK,那么ESP8266不会使用你设置的WIFI名称,而是系统生成,因此没有密码就把加密模式改成AUTH_OPEN
	soft_ap_Config.beacon_interval = 100;//信标间隔,默认为100
	soft_ap_Config.channel = 1;//信道,共支持1~13个信道
	soft_ap_Config.max_connection = 4;//最大连接数量,最大支持四个,默认四个
	soft_ap_Config.ssid_hidden = 0;//隐藏SSID,0:不隐藏  1:隐藏
	//wifi_softap_set_config_current(&soft_ap_Config);//设置 Wi-Fi SoftAP 接口配置,不保存到 Flash
	wifi_softap_set_config(&soft_ap_Config);//设置 Wi-Fi SoftAP 接口配置,保存到 Flash
}

3、绑定回调函数

//断开重连回调函数
LOCAL ICACHE_FLASH_ATTR
void www_webserver_recon(void *arg, sint8 err)
{
    struct espconn *pesp_conn = arg;

    os_printf("webserver's %d.%d.%d.%d:%d err %d reconnect\n", pesp_conn->proto.tcp->remote_ip[0],
    		pesp_conn->proto.tcp->remote_ip[1],pesp_conn->proto.tcp->remote_ip[2],
    		pesp_conn->proto.tcp->remote_ip[3],pesp_conn->proto.tcp->remote_port, err);
}

//断开连接回调函数
LOCAL ICACHE_FLASH_ATTR
void www_webserver_discon(void *arg)
{
    struct espconn *pesp_conn = arg;

    os_printf("webserver's %d.%d.%d.%d:%d disconnect\n", pesp_conn->proto.tcp->remote_ip[0],
        		pesp_conn->proto.tcp->remote_ip[1],pesp_conn->proto.tcp->remote_ip[2],
        		pesp_conn->proto.tcp->remote_ip[3],pesp_conn->proto.tcp->remote_port);
}


//绑定回调函数
LOCAL void ICACHE_FLASH_ATTR
www_webserver_listen(void *arg) {
	struct espconn *pesp_conn = arg;

	espconn_regist_recvcb(pesp_conn, www_webserver_recv);//数据接收回调函数
	espconn_regist_reconcb(pesp_conn, www_webserver_recon);//断开重连回调函数
	espconn_regist_disconcb(pesp_conn, www_webserver_discon);//断开连接回调函数
}

4、数据接收回调函数

//数据接收回调函数
LOCAL void ICACHE_FLASH_ATTR
www_webserver_recv(void *arg, char *pusrdata, unsigned short length) {
	URL_Frame *pURL_Frame = NULL;
	char *pParseBuffer = NULL;
	bool parse_flag = false;
	struct espconn *ptrespconn = arg;
	uint8 sta;

	os_printf("len:%u\n", length);
	if (www_check_data(pusrdata, length) == false) {
		os_printf("goto\n");
		goto _temp_exit;
	}

	parse_flag = www_save_data(pusrdata, length);
	if (parse_flag == false) {
		www_response_send(ptrespconn, false);
	}


	//os_printf(buffer);
	pURL_Frame = (URL_Frame *) os_zalloc(sizeof(URL_Frame));
	www_parse_url(buffer, pURL_Frame);

	//os_printf("recv:%s\n", pusrdata);
	os_printf("\r\nType[%d]\r\n", pURL_Frame->Type);
	os_printf("pSelect[%s]\r\n", pURL_Frame->pSelect);
	os_printf("pCommand[%s]\r\n", pURL_Frame->pCommand);
	os_printf("pFilename[%s]\r\n", pURL_Frame->pFilename);

	switch (pURL_Frame->Type) {
		case GET:
			os_printf("We have a GET request.\n");
			os_printf("pURL_Frame->pFilename: %s\n",pURL_Frame->pFilename);

			sta = wifi_station_get_connect_status();

			os_printf("wifi_station_get_connect_status: %d\n", sta);

			if(pURL_Frame->pFilename[0] == 0){
				www_data_send(ptrespconn, true, page_html);
			}
			if(strncmp(pURL_Frame->pFilename, "WebConfig.html", strlen("WebConfig.html")) == 0){
				www_data_send(ptrespconn, true, config_html);
			}

			break;

		case POST:
			os_printf("We have a POST request.\n");
			pParseBuffer = (char *)os_strstr(buffer, "\r\n\r\n");

			sta = wifi_station_get_connect_status();
			os_printf("wifi_station_get_connect_status: %d\n", sta);

			if(sta == STATION_GOT_IP){
				//www_data_send(ptrespconn, true, "<meta charset='UTF-8'>Connect Success!");
				www_data_send(ptrespconn, true, finish_html);
			}
			else if(sta == STATION_WRONG_PASSWORD){
				//www_data_send(ptrespconn, true, "<meta charset='UTF-8'>Wrong Password!");
				www_data_send(ptrespconn, true, finish_html);
			}
			else{
				www_data_send(ptrespconn, true, config_html);
			}

			if(strncmp(pURL_Frame->pCommand, "connect-wifi", strlen("connect-wifi")) == 0){
				webconfig_get_wifi_ssid_pwd(pusrdata);
			}


			if (pParseBuffer == NULL) {
			     break;

			}

			os_printf("%s\r\n", pParseBuffer);

			break;
	}

	if (buffer != NULL) {
		os_free(buffer);
		buffer = NULL;
	}
	os_free(pURL_Frame);
	pURL_Frame = NULL;
	_temp_exit: ;
}

5、获取网页传过来的 WiFi 账号和密码

/* 功  能:将str字符串中的oldstr字符串替换为newstr字符串
 * 参  数:str:操作目标 oldstr:被替换者 newstr:替换者
 * 返回值:返回替换之后的字符串
 * 版  本: V0.2
 */
static char * ICACHE_FLASH_ATTR
strrpc(char *str, char *oldstr, char *newstr){
    char bstr[os_strlen(str)];//转换缓冲区
    int len = os_strlen(str);
    int i, len2 = 0;
    
    os_memset(bstr, 0, sizeof(bstr));

    for(i = 0; i < len; i++){
        if(!os_strncmp(str + i, oldstr, os_strlen(oldstr))){//查找目标字符串
        	strcat(bstr, newstr);
        	len2 = os_strlen(oldstr);
            i += len2 - 1;
        }else{
        	strncat(bstr, str + i, 1);//保存一字节进缓冲区
	    }
    }

    os_strcpy(str,bstr);
    return str;
}

//获取网页传过来的 WiFi 账号和密码
static void ICACHE_FLASH_ATTR
webconfig_get_wifi_ssid_pwd(char* urlparam)
{
    char *p = NULL, *q = NULL;
    char ssid[32], pass[64];

    os_memset(ssid, 0, sizeof(ssid));
    os_memset(pass, 0, sizeof(pass));

    p = (char *)os_strstr(urlparam, "SSID=");
    q = (char *)os_strstr(urlparam, "PASSWORD=");
    if ( p == NULL || q == NULL ){
        return;
    }
    os_memcpy(ssid, p + 5, q - p - 6);
    os_memcpy(pass, q + 9, os_strlen(urlparam) - (q - urlparam) - 9);

    //空格在url参数会转码成+号,+号转码成%2B
    strrpc(ssid, "+", " ");

    os_printf("ssid[%s], pass[%s]\r\n", ssid, pass);

    wifi_set_opmode(STATIONAP_MODE);
    struct station_config stConf;
    stConf.bssid_set = 0;
    os_memset(&stConf.ssid, 0, sizeof(stConf.ssid));
    os_memset(&stConf.password, 0, sizeof(stConf.password));

    os_memcpy(&stConf.ssid, ssid, os_strlen(ssid));
    os_memcpy(&stConf.password, pass, os_strlen(pass));

    wifi_station_set_config(&stConf);

    //重启
    system_restart();
}

6、数据保存和检查函数

LOCAL char *buffer;
static uint32 sumlength = 0;

LOCAL bool ICACHE_FLASH_ATTR
www_save_data(char *precv, uint16 length)
{
    bool flag = false;
    char length_buf[10] = {0};
    char *ptemp = NULL;
    char *pdata = NULL;
    uint16 headlength = 0;
    static uint32 totallength = 0;

    ptemp = (char *)os_strstr(precv, "\r\n\r\n");

    if (ptemp != NULL) {
        length -= ptemp - precv;
        length -= 4;
        totallength += length;
        headlength = ptemp - precv + 4;
        pdata = (char *)os_strstr(precv, "Content-Length: ");

        if (pdata != NULL) {
            pdata += 16;
            buffer = (char *)os_strstr(pdata, "\r\n");

            if (buffer != NULL) {
                os_memcpy(length_buf, pdata, buffer - pdata);
                sumlength = atoi(length_buf);
            }
        } else {
        	if (totallength != 0x00){
        		totallength = 0;
        		sumlength = 0;
        		return false;
        	}
        }
        if ((sumlength + headlength) >= 1024) {
        	buffer = (char *)os_zalloc(headlength + 1);
            os_memcpy(buffer, precv, headlength + 1);
        } else {
        	buffer = (char *)os_zalloc(sumlength + headlength + 1);
        	os_memcpy(buffer, precv, os_strlen(precv));
        }
    } else {
        if (buffer != NULL) {
            totallength += length;
            os_memcpy(buffer + os_strlen(buffer), precv, length);
        } else {
            totallength = 0;
            sumlength = 0;
            return false;
        }
    }

    if (totallength == sumlength) {
        totallength = 0;
        sumlength = 0;
        return true;
    } else {
        return false;
    }
}

LOCAL bool ICACHE_FLASH_ATTR
www_check_data(char *precv, uint16 length)
{
        //bool flag = true;
    char length_buf[10] = {0};
    char *ptemp = NULL;
    char *pdata = NULL;
    char *tmp_precvbuffer;
    uint16 tmp_length = length;
    uint32 tmp_totallength = 0;

    ptemp = (char *)os_strstr(precv, "\r\n\r\n");

    if (ptemp != NULL) {
        tmp_length -= ptemp - precv;
        tmp_length -= 4;
        tmp_totallength += tmp_length;

        pdata = (char *)os_strstr(precv, "Content-Length: ");

        if (pdata != NULL){
            pdata += 16;
            tmp_precvbuffer = (char *)os_strstr(pdata, "\r\n");

            if (tmp_precvbuffer != NULL){
                os_memcpy(length_buf, pdata, tmp_precvbuffer - pdata);
                sumlength = atoi(length_buf);
                os_printf("A_dat:%u,tot:%u,lenght:%u\n",sumlength,tmp_totallength,tmp_length);
                if(sumlength != tmp_totallength){
                    return false;
                }
            }
        }
    }
    return true;
}

7、解析网页函数

LOCAL void ICACHE_FLASH_ATTR
www_parse_url(char *precv, URL_Frame *purl_frame)
{
    char *str = NULL;
    uint8 length = 0;
    char *pbuffer = NULL;
    char *pbufer = NULL;

    if (purl_frame == NULL || precv == NULL) {
        return;
    }

    pbuffer = (char *)os_strstr(precv, "Host:");

    if (pbuffer != NULL) {
        length = pbuffer - precv;
        pbufer = (char *)os_zalloc(length + 1);
        pbuffer = pbufer;
        os_memcpy(pbuffer, precv, length);
        os_memset(purl_frame->pSelect, 0, URLSize);
        os_memset(purl_frame->pCommand, 0, URLSize);
        os_memset(purl_frame->pFilename, 0, URLSize);

        if (os_strncmp(pbuffer, "GET ", 4) == 0) {
            purl_frame->Type = GET;
            pbuffer += 4;
        } else if (os_strncmp(pbuffer, "POST ", 5) == 0) {
            purl_frame->Type = POST;
            pbuffer += 5;
        }

        pbuffer ++;
        str = (char *)os_strstr(pbuffer, "HTTP");

        if (str != NULL) {
            length = str - pbuffer - 1;
            os_memcpy(purl_frame->pFilename, pbuffer, length);
        }

        os_free(pbufer);
    } else {
        return;
    }

    pbuffer = (char *)os_strstr(precv, "SSID");
    if (pbuffer != NULL) {
        purl_frame->Type = POST;
        os_memcpy(purl_frame->pCommand, "connect-wifi", strlen("connect-wifi"));
        os_free(pbufer);
    }
}

8、服务端写数据函数

//发送html网页数据
LOCAL void ICACHE_FLASH_ATTR
www_data_send(void *arg, bool responseOK, char *psend)
{
    uint16 length = 0;
    char *pbuf = NULL;
    char httphead[256];
    struct espconn *ptrespconn = arg;
    os_memset(httphead, 0, 256);

    if (responseOK) {
        os_sprintf(httphead,
                   "HTTP/1.0 200 OK\r\nContent-Length: %d\r\nServer: lwIP/1.4.0\r\n",
                   psend ? os_strlen(psend) : 0);

        if (psend) {
            os_sprintf(httphead + os_strlen(httphead),
                       "Content-type: text/html\r\nExpires: Fri, 10 Apr 2008 14:00:00 GMT\r\nPragma: no-cache\r\n\r\n");
            length = os_strlen(httphead) + os_strlen(psend);
            pbuf = (char *)os_zalloc(length + 1);
            os_memcpy(pbuf, httphead, os_strlen(httphead));
            os_memcpy(pbuf + os_strlen(httphead), psend, os_strlen(psend));
        } else {
            os_sprintf(httphead + os_strlen(httphead), "\n");
            length = os_strlen(httphead);
        }
    } else {
        os_sprintf(httphead, "HTTP/1.0 400 BadRequest\r\n\
Content-Length: 0\r\nServer: lwIP/1.4.0\r\n\n");
        length = os_strlen(httphead);
    }

    if (psend) {
#ifdef SERVER_SSL_ENABLE
        espconn_secure_sent(ptrespconn, pbuf, length);
#else
        espconn_sent(ptrespconn, pbuf, length);
#endif
    } else {
#ifdef SERVER_SSL_ENABLE
        espconn_secure_sent(ptrespconn, httphead, length);
#else
        espconn_sent(ptrespconn, httphead, length);
#endif
    }

    if (pbuf) {
        os_free(pbuf);
        pbuf = NULL;
    }
}

//发送json数据
LOCAL void ICACHE_FLASH_ATTR
www_data_send_json(void *arg, bool responseOK, char *psend)
{
    uint16 length = 0;
    char *pbuf = NULL;
    char httphead[256];
    struct espconn *ptrespconn = arg;
    os_memset(httphead, 0, 256);

    if (responseOK) {
        os_sprintf(httphead,
                   "HTTP/1.0 200 OK\r\nContent-Length: %d\r\nServer: lwIP/1.4.0\r\n",
                   psend ? os_strlen(psend) : 0);

        if (psend) {
            os_sprintf(httphead + os_strlen(httphead),
                       "Content-type: application/json\r\nExpires: Fri, 10 Apr 2008 14:00:00 GMT\r\nPragma: no-cache\r\n\r\n");
            length = os_strlen(httphead) + os_strlen(psend);
            pbuf = (char *)os_zalloc(length + 1);
            os_memcpy(pbuf, httphead, os_strlen(httphead));
            os_memcpy(pbuf + os_strlen(httphead), psend, os_strlen(psend));
        } else {
            os_sprintf(httphead + os_strlen(httphead), "\n");
            length = os_strlen(httphead);
        }
    } else {
        os_sprintf(httphead, "HTTP/1.0 400 BadRequest\r\n\
Content-Length: 0\r\nServer: lwIP/1.4.0\r\n\n");
        length = os_strlen(httphead);
    }

    if (psend) {
#ifdef SERVER_SSL_ENABLE
        espconn_secure_sent(ptrespconn, pbuf, length);
#else
        espconn_sent(ptrespconn, pbuf, length);
#endif
    } else {
#ifdef SERVER_SSL_ENABLE
        espconn_secure_sent(ptrespconn, httphead, length);
#else
        espconn_sent(ptrespconn, httphead, length);
#endif
    }

    if (pbuf) {
        os_free(pbuf);
        pbuf = NULL;
    }
}

//发送响应成功数据
LOCAL void ICACHE_FLASH_ATTR
www_response_send(void *arg, bool responseOK)
{
    struct espconn *ptrespconn = arg;

    www_data_send(ptrespconn, responseOK, NULL);
}

9、网页数据

不知道为啥,meta 标签里我都设置为 utf-8 了,中文输出还是乱码,所以网页里用的全部都是英文。

//欢迎页面代码
char* page_html = "<!DOCTYPE html>\r\n"
		"<html>\r\n"
		"    <head>\r\n"
		"        <meta charset=\"utf-8\" content=\"width=device-width,initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no\" name=\"viewport\"/>\r\n"
		"        <title>\r\n"
		"            ZCM IOT WiFi Config\r\n"
		"        </title>\r\n"
		"    </head>\r\n"
		"    <body style=\"background: #00F948\">\r\n"
		"        <div align=\"center\"><br/><br/>\r\n"
		"            <font>\r\n"
		"                ZCM IOT WiFi Config\r\n"
		"            </font>\r\n"
		"            <br/>\r\n"
		"            <font>\r\n"
		"                E-mail: wxhntmy@163.com\r\n"
		"            </font>\r\n"
		"            <br/>\r\n"
		"            <br/>\r\n"
		"            <a href=\"WebConfig.html\" text-decoration=\"none\">\r\n"
		"                <button formtarget=\"_self\" style=\"display:block;margin:0 auto\">\r\n"
		"                    Start Config\r\n"
		"                </button>\r\n"
		"            </a>\r\n"
		"			<br/>\r\n"
		"        </div>\r\n"
		"    </body>\r\n"
		"</html>";
//配网页面
char* config_html = "<!DOCTYPE html>\r\n"
		"<html>\r\n"
		"    <head>\r\n"
		"        <meta charset=\"utf-8\" content=\"width=device-width,initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no\" name=\"viewport\"/>\r\n"
		"        <title>\r\n"
		"            ZCM IOT WiFi Config\r\n"
		"        </title>\r\n"
		"    </head>\r\n"
		"    <body style=\"background: #00F948\">\r\n"
		"        <div align=\"center\">\r\n"
		"			<br><br>\r\n"
		"            <font>\r\n"
		"                ZCM IOT WiFi Config\r\n"
		"            </font>\r\n"
		"            <br/>\r\n"
		"            <font>\r\n"
		"                E-mail: wxhntmy@163.com\r\n"
		"            </font>\r\n"
		"            <br/>\r\n"
		"            <br/>\r\n"
		"        </div>\r\n"
		"        <form action=\"WiFiConfig.html\" enctype=\"application/x-www-form-urlencoded\" method=\"post\">\r\n"
		"            <table align=\"center\" border=\"0\" cellspacing=\"10\">\r\n"
		"                <tr>\r\n"
		"                    <td>\r\n"
		"                        Wi-Fi Name:\r\n"
		"                        <input name=\"SSID\" placeholder=\"input Wi-Fi name\" type=\"text\"/>\r\n"
		"                    </td>\r\n"
		"                </tr>\r\n"
		"                <tr>\r\n"
		"                    <td>\r\n"
		"                        Wi-Fi&nbsp;&nbsp;&nbsp;&nbsp;Pwd:\r\n"
		"                        <input name=\"PASSWORD\" placeholder=\"input Wi-Fi Password\" type=\"password\"/>\r\n"
		"                    </td>\r\n"
		"                </tr>\r\n"
		"            </table>\r\n"
		"            <button style=\"display:block;margin:0 auto\" type=\"submit\" value=\"Submit\">\r\n"
		"                Confirm\r\n"
		"            </button>\r\n"
		"        </form>\r\n"
		"    </body>\r\n"
		"</html>";


//配网完成
char* finish_html = "<!DOCTYPE html>\r\n"
		"<html>\r\n"
		"    <head>\r\n"
		"        <meta charset=\"utf-8\" content=\"width=device-width,initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no\" name=\"viewport\"/>\r\n"
		"        <title>\r\n"
		"            ZCM IOT WiFi Config\r\n"
		"        </title>\r\n"
		"    </head>\r\n"
		"    <body style=\"background: #00F948\">\r\n"
		"        <div align=\"center\">\r\n"
		"            <br><br>\r\n"
		"            <font>\r\n"
		"                ZCM IOT WiFi Config\r\n"
		"            </font>\r\n"
		"            <br/>\r\n"
		"            <font>\r\n"
		"                E-mail: wxhntmy@163.com\r\n"
		"            </font>\r\n"
		"            <br/>\r\n"
		"            <br/>\r\n"
		"            <font>\r\n"
		"                Connecting to Wi-Fi, the connection is complete after the LED flashes three times!\r\n"
		"                <br/>\r\n"
		"                Steady on means the connection failed, please re-enter!\r\n"
		"                <br/><br>\r\n"
		"                <a href=\"WebConfig.html\" text-decoration=\"none\">\r\n"
		"                    <button formtarget=\"_self\" style=\"display:block;margin:0 auto\">\r\n"
		"                        Re-distribution Network\r\n"
		"                    </button>\r\n"
		"                </a>\r\n"
		"                <br/>\r\n"
		"                <a href=\"/\">\r\n"
		"                    Back Home\r\n"
		"                </a>\r\n"
		"            </font>\r\n"
		"        </div>\r\n"
		"    </body>\r\n"
		"</html>";

10、完整代码

/*
 * webserver.c
 *
 *  Created on: 2021年4月8日
 *      Author: wxhntmy
 */

#include "espconn.h"
#include "mem.h"
#include "ets_sys.h"
#include "osapi.h"

#include "user_interface.h"

#include "user_devicefind.h"
#include "user_webserver.h"
#include "user_esp_platform.h"
#include "user_tcpclient.h"


#include "webserver.h"	//头文件只声明了几个函数

char* AP_NAME = "zcm_iot_wifi"; //wifi名字
char* AP_PWD = "123456"; //wifi密码

//欢迎页面代码
char* page_html = "<!DOCTYPE html>\r\n"
		"<html>\r\n"
		"    <head>\r\n"
		"        <meta charset=\"utf-8\" content=\"width=device-width,initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no\" name=\"viewport\"/>\r\n"
		"        <title>\r\n"
		"            ZCM IOT WiFi Config\r\n"
		"        </title>\r\n"
		"    </head>\r\n"
		"    <body style=\"background: #00F948\">\r\n"
		"        <div align=\"center\"><br/><br/>\r\n"
		"            <font>\r\n"
		"                ZCM IOT WiFi Config\r\n"
		"            </font>\r\n"
		"            <br/>\r\n"
		"            <font>\r\n"
		"                E-mail: wxhntmy@163.com\r\n"
		"            </font>\r\n"
		"            <br/>\r\n"
		"            <br/>\r\n"
		"            <a href=\"WebConfig.html\" text-decoration=\"none\">\r\n"
		"                <button formtarget=\"_self\" style=\"display:block;margin:0 auto\">\r\n"
		"                    Start Config\r\n"
		"                </button>\r\n"
		"            </a>\r\n"
		"			<br/>\r\n"
		"        </div>\r\n"
		"    </body>\r\n"
		"</html>";
//配网页面
char* config_html = "<!DOCTYPE html>\r\n"
		"<html>\r\n"
		"    <head>\r\n"
		"        <meta charset=\"utf-8\" content=\"width=device-width,initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no\" name=\"viewport\"/>\r\n"
		"        <title>\r\n"
		"            ZCM IOT WiFi Config\r\n"
		"        </title>\r\n"
		"    </head>\r\n"
		"    <body style=\"background: #00F948\">\r\n"
		"        <div align=\"center\">\r\n"
		"			<br><br>\r\n"
		"            <font>\r\n"
		"                ZCM IOT WiFi Config\r\n"
		"            </font>\r\n"
		"            <br/>\r\n"
		"            <font>\r\n"
		"                E-mail: wxhntmy@163.com\r\n"
		"            </font>\r\n"
		"            <br/>\r\n"
		"            <br/>\r\n"
		"        </div>\r\n"
		"        <form action=\"WiFiConfig.html\" enctype=\"application/x-www-form-urlencoded\" method=\"post\">\r\n"
		"            <table align=\"center\" border=\"0\" cellspacing=\"10\">\r\n"
		"                <tr>\r\n"
		"                    <td>\r\n"
		"                        Wi-Fi Name:\r\n"
		"                        <input name=\"SSID\" placeholder=\"input Wi-Fi name\" type=\"text\"/>\r\n"
		"                    </td>\r\n"
		"                </tr>\r\n"
		"                <tr>\r\n"
		"                    <td>\r\n"
		"                        Wi-Fi&nbsp;&nbsp;&nbsp;&nbsp;Pwd:\r\n"
		"                        <input name=\"PASSWORD\" placeholder=\"input Wi-Fi Password\" type=\"password\"/>\r\n"
		"                    </td>\r\n"
		"                </tr>\r\n"
		"            </table>\r\n"
		"            <button style=\"display:block;margin:0 auto\" type=\"submit\" value=\"Submit\">\r\n"
		"                Confirm\r\n"
		"            </button>\r\n"
		"        </form>\r\n"
		"    </body>\r\n"
		"</html>";


//配网完成
char* finish_html = "<!DOCTYPE html>\r\n"
		"<html>\r\n"
		"    <head>\r\n"
		"        <meta charset=\"utf-8\" content=\"width=device-width,initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no\" name=\"viewport\"/>\r\n"
		"        <title>\r\n"
		"            ZCM IOT WiFi Config\r\n"
		"        </title>\r\n"
		"    </head>\r\n"
		"    <body style=\"background: #00F948\">\r\n"
		"        <div align=\"center\">\r\n"
		"            <br><br>\r\n"
		"            <font>\r\n"
		"                ZCM IOT WiFi Config\r\n"
		"            </font>\r\n"
		"            <br/>\r\n"
		"            <font>\r\n"
		"                E-mail: wxhntmy@163.com\r\n"
		"            </font>\r\n"
		"            <br/>\r\n"
		"            <br/>\r\n"
		"            <font>\r\n"
		"                Connecting to Wi-Fi, the connection is complete after the LED flashes three times!\r\n"
		"                <br/>\r\n"
		"                Steady on means the connection failed, please re-enter!\r\n"
		"                <br/><br>\r\n"
		"                <a href=\"WebConfig.html\" text-decoration=\"none\">\r\n"
		"                    <button formtarget=\"_self\" style=\"display:block;margin:0 auto\">\r\n"
		"                        Re-distribution Network\r\n"
		"                    </button>\r\n"
		"                </a>\r\n"
		"                <br/>\r\n"
		"                <a href=\"/\">\r\n"
		"                    Back Home\r\n"
		"                </a>\r\n"
		"            </font>\r\n"
		"        </div>\r\n"
		"    </body>\r\n"
		"</html>";

LOCAL void ICACHE_FLASH_ATTR
www_data_send(void *arg, bool responseOK, char *psend)
{
    uint16 length = 0;
    char *pbuf = NULL;
    char httphead[256];
    struct espconn *ptrespconn = arg;
    os_memset(httphead, 0, 256);

    if (responseOK) {
        os_sprintf(httphead,
                   "HTTP/1.0 200 OK\r\nContent-Length: %d\r\nServer: lwIP/1.4.0\r\n",
                   psend ? os_strlen(psend) : 0);

        if (psend) {
            os_sprintf(httphead + os_strlen(httphead),
                       "Content-type: text/html\r\nExpires: Fri, 10 Apr 2008 14:00:00 GMT\r\nPragma: no-cache\r\n\r\n");
            length = os_strlen(httphead) + os_strlen(psend);
            pbuf = (char *)os_zalloc(length + 1);
            os_memcpy(pbuf, httphead, os_strlen(httphead));
            os_memcpy(pbuf + os_strlen(httphead), psend, os_strlen(psend));
        } else {
            os_sprintf(httphead + os_strlen(httphead), "\n");
            length = os_strlen(httphead);
        }
    } else {
        os_sprintf(httphead, "HTTP/1.0 400 BadRequest\r\n\
Content-Length: 0\r\nServer: lwIP/1.4.0\r\n\n");
        length = os_strlen(httphead);
    }

    if (psend) {
#ifdef SERVER_SSL_ENABLE
        espconn_secure_sent(ptrespconn, pbuf, length);
#else
        espconn_sent(ptrespconn, pbuf, length);
#endif
    } else {
#ifdef SERVER_SSL_ENABLE
        espconn_secure_sent(ptrespconn, httphead, length);
#else
        espconn_sent(ptrespconn, httphead, length);
#endif
    }

    if (pbuf) {
        os_free(pbuf);
        pbuf = NULL;
    }
}

LOCAL void ICACHE_FLASH_ATTR
www_data_send_json(void *arg, bool responseOK, char *psend)
{
    uint16 length = 0;
    char *pbuf = NULL;
    char httphead[256];
    struct espconn *ptrespconn = arg;
    os_memset(httphead, 0, 256);

    if (responseOK) {
        os_sprintf(httphead,
                   "HTTP/1.0 200 OK\r\nContent-Length: %d\r\nServer: lwIP/1.4.0\r\n",
                   psend ? os_strlen(psend) : 0);

        if (psend) {
            os_sprintf(httphead + os_strlen(httphead),
                       "Content-type: application/json\r\nExpires: Fri, 10 Apr 2008 14:00:00 GMT\r\nPragma: no-cache\r\n\r\n");
            length = os_strlen(httphead) + os_strlen(psend);
            pbuf = (char *)os_zalloc(length + 1);
            os_memcpy(pbuf, httphead, os_strlen(httphead));
            os_memcpy(pbuf + os_strlen(httphead), psend, os_strlen(psend));
        } else {
            os_sprintf(httphead + os_strlen(httphead), "\n");
            length = os_strlen(httphead);
        }
    } else {
        os_sprintf(httphead, "HTTP/1.0 400 BadRequest\r\n\
Content-Length: 0\r\nServer: lwIP/1.4.0\r\n\n");
        length = os_strlen(httphead);
    }

    if (psend) {
#ifdef SERVER_SSL_ENABLE
        espconn_secure_sent(ptrespconn, pbuf, length);
#else
        espconn_sent(ptrespconn, pbuf, length);
#endif
    } else {
#ifdef SERVER_SSL_ENABLE
        espconn_secure_sent(ptrespconn, httphead, length);
#else
        espconn_sent(ptrespconn, httphead, length);
#endif
    }

    if (pbuf) {
        os_free(pbuf);
        pbuf = NULL;
    }
}

LOCAL void ICACHE_FLASH_ATTR
www_response_send(void *arg, bool responseOK)
{
    struct espconn *ptrespconn = arg;

    www_data_send(ptrespconn, responseOK, NULL);
}


LOCAL void ICACHE_FLASH_ATTR
www_parse_url(char *precv, URL_Frame *purl_frame)
{
    char *str = NULL;
    uint8 length = 0;
    char *pbuffer = NULL;
    char *pbufer = NULL;

    if (purl_frame == NULL || precv == NULL) {
        return;
    }

    pbuffer = (char *)os_strstr(precv, "Host:");

    if (pbuffer != NULL) {
        length = pbuffer - precv;
        pbufer = (char *)os_zalloc(length + 1);
        pbuffer = pbufer;
        os_memcpy(pbuffer, precv, length);
        os_memset(purl_frame->pSelect, 0, URLSize);
        os_memset(purl_frame->pCommand, 0, URLSize);
        os_memset(purl_frame->pFilename, 0, URLSize);

        if (os_strncmp(pbuffer, "GET ", 4) == 0) {
            purl_frame->Type = GET;
            pbuffer += 4;
        } else if (os_strncmp(pbuffer, "POST ", 5) == 0) {
            purl_frame->Type = POST;
            pbuffer += 5;
        }

        pbuffer ++;
        str = (char *)os_strstr(pbuffer, "HTTP");

        if (str != NULL) {
            length = str - pbuffer - 1;
            os_memcpy(purl_frame->pFilename, pbuffer, length);
        }

        os_free(pbufer);
    } else {
        return;
    }

    pbuffer = (char *)os_strstr(precv, "SSID");
    if (pbuffer != NULL) {
        purl_frame->Type = POST;
        os_memcpy(purl_frame->pCommand, "connect-wifi", strlen("connect-wifi"));
        os_free(pbufer);
    }
}


LOCAL char *buffer;
static uint32 sumlength = 0;
LOCAL bool ICACHE_FLASH_ATTR
www_save_data(char *precv, uint16 length)
{
    bool flag = false;
    char length_buf[10] = {0};
    char *ptemp = NULL;
    char *pdata = NULL;
    uint16 headlength = 0;
    static uint32 totallength = 0;

    ptemp = (char *)os_strstr(precv, "\r\n\r\n");

    if (ptemp != NULL) {
        length -= ptemp - precv;
        length -= 4;
        totallength += length;
        headlength = ptemp - precv + 4;
        pdata = (char *)os_strstr(precv, "Content-Length: ");

        if (pdata != NULL) {
            pdata += 16;
            buffer = (char *)os_strstr(pdata, "\r\n");

            if (buffer != NULL) {
                os_memcpy(length_buf, pdata, buffer - pdata);
                sumlength = atoi(length_buf);
            }
        } else {
        	if (totallength != 0x00){
        		totallength = 0;
        		sumlength = 0;
        		return false;
        	}
        }
        if ((sumlength + headlength) >= 1024) {
        	buffer = (char *)os_zalloc(headlength + 1);
            os_memcpy(buffer, precv, headlength + 1);
        } else {
        	buffer = (char *)os_zalloc(sumlength + headlength + 1);
        	os_memcpy(buffer, precv, os_strlen(precv));
        }
    } else {
        if (buffer != NULL) {
            totallength += length;
            os_memcpy(buffer + os_strlen(buffer), precv, length);
        } else {
            totallength = 0;
            sumlength = 0;
            return false;
        }
    }

    if (totallength == sumlength) {
        totallength = 0;
        sumlength = 0;
        return true;
    } else {
        return false;
    }
}
LOCAL bool ICACHE_FLASH_ATTR
www_check_data(char *precv, uint16 length)
{
        //bool flag = true;
    char length_buf[10] = {0};
    char *ptemp = NULL;
    char *pdata = NULL;
    char *tmp_precvbuffer;
    uint16 tmp_length = length;
    uint32 tmp_totallength = 0;

    ptemp = (char *)os_strstr(precv, "\r\n\r\n");

    if (ptemp != NULL) {
        tmp_length -= ptemp - precv;
        tmp_length -= 4;
        tmp_totallength += tmp_length;

        pdata = (char *)os_strstr(precv, "Content-Length: ");

        if (pdata != NULL){
            pdata += 16;
            tmp_precvbuffer = (char *)os_strstr(pdata, "\r\n");

            if (tmp_precvbuffer != NULL){
                os_memcpy(length_buf, pdata, tmp_precvbuffer - pdata);
                sumlength = atoi(length_buf);
                os_printf("A_dat:%u,tot:%u,lenght:%u\n",sumlength,tmp_totallength,tmp_length);
                if(sumlength != tmp_totallength){
                    return false;
                }
            }
        }
    }
    return true;
}


/* 功  能:将str字符串中的oldstr字符串替换为newstr字符串
 * 参  数:str:操作目标 oldstr:被替换者 newstr:替换者
 * 返回值:返回替换之后的字符串
 * 版  本: V0.2
 */
static char * ICACHE_FLASH_ATTR
strrpc(char *str,char *oldstr,char *newstr){
    char bstr[os_strlen(str)];//转换缓冲区
    int len = os_strlen(str);
    int i, len2 = 0;


    os_memset(bstr, 0, sizeof(bstr));

    for(i = 0; i < len; i++){
        if(!os_strncmp(str + i, oldstr, os_strlen(oldstr))){//查找目标字符串
        	strcat(bstr, newstr);
        	len2 = os_strlen(oldstr);
            i += len2 - 1;
        }else{
        	strncat(bstr, str + i, 1);//保存一字节进缓冲区
	    }
    }

    os_strcpy(str,bstr);
    return str;
}

static void ICACHE_FLASH_ATTR
webconfig_get_wifi_ssid_pwd(char* urlparam)
{
    char *p = NULL, *q = NULL;
    char ssid[32], pass[64];

    os_memset(ssid, 0, sizeof(ssid));
    os_memset(pass, 0, sizeof(pass));

    p = (char *)os_strstr(urlparam, "SSID=");
    q = (char *)os_strstr(urlparam, "PASSWORD=");
    if ( p == NULL || q == NULL ){
        return;
    }
    os_memcpy(ssid, p + 5, q - p - 6);
    os_memcpy(pass, q + 9, os_strlen(urlparam) - (q - urlparam) - 9);

    //空格在url参数会转码成+号,+号转码成%2B
    strrpc(ssid, "+", " ");

    os_printf("ssid[%s], pass[%s]\r\n", ssid, pass);

    wifi_set_opmode(STATIONAP_MODE);
    struct station_config stConf;
    stConf.bssid_set = 0;
    os_memset(&stConf.ssid, 0, sizeof(stConf.ssid));
    os_memset(&stConf.password, 0, sizeof(stConf.password));

    os_memcpy(&stConf.ssid, ssid, os_strlen(ssid));
    os_memcpy(&stConf.password, pass, os_strlen(pass));

    wifi_station_set_config(&stConf);

    //重启
    system_restart();
}

LOCAL void ICACHE_FLASH_ATTR
www_webserver_recv(void *arg, char *pusrdata, unsigned short length) {
	URL_Frame *pURL_Frame = NULL;
	char *pParseBuffer = NULL;
	bool parse_flag = false;
	struct espconn *ptrespconn = arg;
	uint8 sta;

	os_printf("len:%u\n", length);
	if (www_check_data(pusrdata, length) == false) {
		os_printf("goto\n");
		goto _temp_exit;
	}

	parse_flag = www_save_data(pusrdata, length);
	if (parse_flag == false) {
		www_response_send(ptrespconn, false);
	}


	//os_printf(buffer);
	pURL_Frame = (URL_Frame *) os_zalloc(sizeof(URL_Frame));
	www_parse_url(buffer, pURL_Frame);

	//os_printf("recv:%s\n", pusrdata);
	os_printf("\r\nType[%d]\r\n", pURL_Frame->Type);
	os_printf("pSelect[%s]\r\n", pURL_Frame->pSelect);
	os_printf("pCommand[%s]\r\n", pURL_Frame->pCommand);
	os_printf("pFilename[%s]\r\n", pURL_Frame->pFilename);

	switch (pURL_Frame->Type) {
		case GET:
			os_printf("We have a GET request.\n");
			os_printf("pURL_Frame->pFilename: %s\n",pURL_Frame->pFilename);

			sta = wifi_station_get_connect_status();
			if(sta == STATION_GOT_IP){

				//www_data_send(ptrespconn, true, "<meta charset='UTF-8'>WiFi is connected!");
				www_data_send(ptrespconn, true, finish_html);
			}
			else{
				if(pURL_Frame->pFilename[0] == 0){
					www_data_send(ptrespconn, true, page_html);
				}
				if(strncmp(pURL_Frame->pFilename, "WebConfig.html", strlen("WebConfig.html")) == 0){
					www_data_send(ptrespconn, true, config_html);
				}
			}

			break;

		case POST:
			os_printf("We have a POST request.\n");
			pParseBuffer = (char *)os_strstr(buffer, "\r\n\r\n");

			sta = wifi_station_get_connect_status();
			if(sta == STATION_GOT_IP){
				//www_data_send(ptrespconn, true, "<meta charset='UTF-8'>Connect Success!");
				www_data_send(ptrespconn, true, finish_html);
			}
			else if(sta == STATION_WRONG_PASSWORD){
				//www_data_send(ptrespconn, true, "<meta charset='UTF-8'>Wrong Password!");
				www_data_send(ptrespconn, true, finish_html);
			}
			else{
				www_data_send(ptrespconn, true, config_html);
			}

			if(strncmp(pURL_Frame->pCommand, "connect-wifi", strlen("connect-wifi")) == 0){
				webconfig_get_wifi_ssid_pwd(pusrdata);
			}


			if (pParseBuffer == NULL) {
			     break;

			}

			os_printf("%s\r\n", pParseBuffer);

			break;
	}

	if (buffer != NULL) {
		os_free(buffer);
		buffer = NULL;
	}
	os_free(pURL_Frame);
	pURL_Frame = NULL;
	_temp_exit: ;
}

LOCAL ICACHE_FLASH_ATTR
void www_webserver_recon(void *arg, sint8 err)
{
    struct espconn *pesp_conn = arg;

    os_printf("webserver's %d.%d.%d.%d:%d err %d reconnect\n", pesp_conn->proto.tcp->remote_ip[0],
    		pesp_conn->proto.tcp->remote_ip[1],pesp_conn->proto.tcp->remote_ip[2],
    		pesp_conn->proto.tcp->remote_ip[3],pesp_conn->proto.tcp->remote_port, err);
}

LOCAL ICACHE_FLASH_ATTR
void www_webserver_discon(void *arg)
{
    struct espconn *pesp_conn = arg;

    os_printf("webserver's %d.%d.%d.%d:%d disconnect\n", pesp_conn->proto.tcp->remote_ip[0],
        		pesp_conn->proto.tcp->remote_ip[1],pesp_conn->proto.tcp->remote_ip[2],
        		pesp_conn->proto.tcp->remote_ip[3],pesp_conn->proto.tcp->remote_port);
}


//绑定回调函数
LOCAL void ICACHE_FLASH_ATTR
www_webserver_listen(void *arg) {
	struct espconn *pesp_conn = arg;

	espconn_regist_recvcb(pesp_conn, www_webserver_recv);
	espconn_regist_reconcb(pesp_conn, www_webserver_recon);
	espconn_regist_disconcb(pesp_conn, www_webserver_discon);
}


/*
 * softAP模式初始化代码
 */
void ICACHE_FLASH_ATTR
www_softAP_init(void){
	struct softap_config soft_ap_Config;

	//wifi_set_opmode_current(SOFTAP_MODE);//设置为AP模式,不保存到flash
	wifi_set_opmode(STATIONAP_MODE);//设置为STATION+AP模式,并保存到flash

	os_memset(&soft_ap_Config, 0, sizeof(struct softap_config)); // AP参数结构体 = 0

	soft_ap_Config.ssid_len = os_strlen(AP_NAME);//热点名称长度,与你实际的名称长度一致就好
	os_strcpy(soft_ap_Config.ssid, AP_NAME);//实际热点名称设置,可以根据你的需要来
	os_strcpy(soft_ap_Config.password, AP_PWD);//热点密码设置
	soft_ap_Config.authmode = AUTH_OPEN;//若是你的密码为空,加密模式为AUTH_WPA2_PSK,那么ESP8266不会使用你设置的WIFI名称,而是系统生成,因此没有密码就把加密模式改成AUTH_OPEN
	soft_ap_Config.beacon_interval = 100;//信标间隔,默认为100
	soft_ap_Config.channel = 1;//信道,共支持1~13个信道
	soft_ap_Config.max_connection = 4;//最大连接数量,最大支持四个,默认四个
	soft_ap_Config.ssid_hidden = 0;//隐藏SSID,0:不隐藏  1:隐藏
	//wifi_softap_set_config_current(&soft_ap_Config);//设置 Wi-Fi SoftAP 接口配置,不保存到 Flash
	wifi_softap_set_config(&soft_ap_Config);//设置 Wi-Fi SoftAP 接口配置,保存到 Flash
}

//初始化webserver
void ICACHE_FLASH_ATTR
www_webserver_init(uint32 port) {
	LOCAL struct espconn esp_conn;
	LOCAL esp_tcp esptcp;

	esp_conn.type = ESPCONN_TCP;
	esp_conn.state = ESPCONN_NONE;
	esp_conn.proto.tcp = &esptcp;
	esp_conn.proto.tcp->local_port = port;
	espconn_regist_connectcb(&esp_conn, www_webserver_listen);
	espconn_accept(&esp_conn);
}

11、实现方式

在主函数中调用以下两个函数即可

//初始化AP模式
www_softAP_init();
//开启webserver
www_webserver_init(SERVER_PORT);

三、效果展示

1、连接 WiFi

在这里插入图片描述

2、配网首页

打开浏览器,地址栏输入 192.168.4.1

在这里插入图片描述

3、配网页面

在这里插入图片描述

4、配网完成页面

在这里插入图片描述

<think>好的,我现在需要帮用户解决如何ESP8266连接Wi-Fi的问题。首先,用户提到了ESP8266WiFiManager库,所以应该先确定使用这个库的步骤。根据引用中的信息,WiFiManager可以简化连接过程,自动保存凭证,支持AP模式置。 接下来,我需要考虑用户可能的操作步骤。首先安装库,用户可能不知道如何安装,所以需要指导他们通过Arduino IDE的库管理器安装。然后,基本的连接代码,这里需要提供一个简单的示例,并解释每个部分的作用,比如初始化串口、创建WiFiManager对象,设置AP名称,自动连接或启动置门户。 然后,需要处理自动连接失败的情况,进入置模式。这时候,用户需要连接到ESP8266的AP,访问指定IP来置Wi-Fi。这部分要详细说明步骤,比如用手机或电脑连接热点,打开浏览器,输入IP,选择络,输入密码,保存后自动重启。 另外,用户可能需要高级置,比如设置自定义AP名称和密码,设置静态IP。这时候需要给出相应的代码示例,并解释参数的作用。同时,要提醒用户保存凭证到闪存中,避免重复置。 可能的问题包括代码是否正确、AP模式无法连接、置后无法连接络等。需要列出常见问题及解决方法,比如检查密码正确性、信号强度、重启模块等。还要注意代码中的关键点,比如自动连接和启动置门户的条件判断。 最后,生成相关问题,帮助用户进一步了解优化方法、处理连接失败、静态IP置和WiFiManager的其他功能。确保所有步骤清晰,代码正确,符合用户的使用场景,特别是针对ESP8266置。同时,引用中的信息要正确标注,确保用户参考的可靠性。</think>### ESP8266置Wi-Fi络连接教程 #### 一、基础置步骤 1. **安装WiFiManager库** - 通过Arduino IDE菜单栏选择`工具`→`管理库` - 搜索`WiFiManager`选择tzapu版本安装[^1] 2. **基础连接代码** ```cpp #include <ESP8266WiFi.h> #include <WiFiManager.h> void setup() { Serial.begin(115200); WiFiManager wifiManager; // 设置AP模式名称(默认ESP+芯片ID) wifiManager.autoConnect("MyESP8266"); Serial.println("连接成功!"); Serial.print("IP地址: "); Serial.println(WiFi.localIP()); } void loop() {} ``` #### 二、置流程 1. **首次运行行为** - 模块自动扫描保存的Wi-Fi凭证 - 若未找到有效凭证,进入AP置模式 - 手机/电脑连接`MyESP8266`热点(无密码) - 浏览器访问`192.168.4.1`打开置页面 2. **置界面** ```mermaid graph TD A[选择Wi-Fi络] --> B[输入密码] B --> C{置成功?} C -->|是| D[自动重启] C -->|否| E[返回置页] ``` #### 三、高级置方法 1. **自定义AP参数** ```cpp wifiManager.setAPCallback([](WiFiManager* mgr){ Serial.println("进入置模式"); }); wifiManager.setConfigPortalTimeout(180); // 设置3分钟超时 ``` 2. **静态IP置** ```cpp IPAddress staticIP(192,168,1,100); IPAddress gateway(192,168,1,1); IPAddress subnet(255,255,255,0); wifiManager.setSTAStaticIPConfig(staticIP, gateway, subnet); ``` #### 四、常见问题排查 | 现象 | 解决方法 | |------|----------| | 无法打开置页 | 检查设备是否连接ESP热点 | | 置后无法联 | 确认路由器支持2.4GHz频段 | | 重复进入置模式 | 调用`wifiManager.setBreakAfterConfig(true)` | #### 五、代码关键点说明 - `autoConnect()`方法实现自动重连与置模式切换 - 凭证自动保存于ESP8266的闪存中(约512字节) - 支持同时置多个络参数:$$W_{total} = \sum_{i=1}^{n}(SSID_i + PASS_i)$$
评论 17
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

菠萝蚊鸭

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

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

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

打赏作者

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

抵扣说明:

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

余额充值