esp-01 webconfig配网

前言:

玩esp-01有断时间了,自己使用homeassistant搭建后台控制中心,esp-01做终端控制灯、控制风扇、温度检测等等。但在控制之前esp-01需要配网,说到配网baidu搜索到最多应该就是smartconfig,以及微信的airkiss。但是不管是smartconfi或airkiss配置网,配置过程很不稳定,经常无法配置成功然后就只能断电重来;另一个原因是smartconfig需要app上配置很是麻烦。以上原因让我去寻找找到了另一种配网方式webconfig

webconfig基本思路

基本思路是ESP8266工作AP模式下,作为TCP Server监听TCP Client的连接。因为网页HTTP默认的端口是80,所以ESP8266作为TCP Server的端口需要设置为80。电脑连接上ESP8266的AP后,网页访问默认IP地址192.168.4.1,此时ESP8266就会收到来自网页的HTTP的Get请求,此请求数据为HTML格式。ESP8266收到请求后,读出保存在Flash中的HTML格式网页,并将带有HTML应答头的HTML网页发送给网页,网页端就可以显示出网页。

实现过程

从flash中读取上次保留的wifi信息,若有wifi信息进入station模式反之进程softap模式等待配网

void ICACHE_FLASH_ATTR
init_done_cb_init(void)
{   
    struct station_config stconfig;
    struct softap_config  apconfig;

    print_chip_info();

    os_memset(&stconfig, 0, sizeof(struct station_config));
    wifi_station_get_config_default(&stconfig);
    if(os_strlen(stconfig.ssid) != 0){
        os_printf("ssid[%s]pass[%s]", stconfig.ssid, stconfig.password);
        wifi_set_opmode(STATION_MODE);
        wifi_station_set_reconnect_policy(TRUE);
        wifi_station_set_auto_connect(TRUE);
    }
    else{
        wifi_set_opmode(SOFTAP_MODE);
        wifi_softap_get_config(&apconfig);
        os_memset(apconfig.ssid, 0, 32);
        os_memset(apconfig.password, 0, 64);
        os_sprintf(apconfig.ssid,"ESP_%X",system_get_chip_id());
        apconfig.authmode = AUTH_OPEN;
        apconfig.ssid_len = 0;
        apconfig.max_connection = 5; 
        wifi_softap_set_config(&apconfig);
        wifi_station_set_reconnect_policy(FALSE);
        wifi_station_set_auto_connect(FALSE);
        wifi_station_disconnect();
    }
#if PLUG_DEVICE
    user_plug_init();
#elif FAN_DEVICE
    user_fan_init();
#elif DS18B20_DEVICE
    ds_init();
#endif
    user_webserver_init(SERVER_PORT);
}

在TCP Server接收函数中实现解析GET请求获取配网页面,POST请求配置

#define HTML    "<html><head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"/></head>"  \
                "<body align=\"center\"><h2>WiFi Settings</h2><form method='post'>" \
                "<input type='text' name='ssid' placeholder='ssid'><br>"    \
                "<input type='text' name='pass' placeholder='pass'><br>"  \
                "<input type='submit'><br></form></body></html>"

LOCAL void ICACHE_FLASH_ATTR
webconfig_set_wifi(char* urlparam){
    char *p = NULL, *q = NULL;
    char ssid[10], pass[15];

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

    p = (char *)os_strstr(urlparam, "ssid=");
    q = (char *)os_strstr(urlparam, "pass=");
    if ( p == NULL || q == NULL ){
        return;
    }
    os_memcpy(ssid, p + 5, q - p - 6);
    os_memcpy(pass, q + 5, os_strlen(urlparam) - (q - urlparam) - 5);
    os_printf("ssid[%s]pass[%s]\r\n", ssid, pass);

    wifi_set_opmode(STATION_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();
    return ;
}

LOCAL void ICACHE_FLASH_ATTR
webserver_recv(void *arg, char *pusrdata, unsigned short length){
    struct espconn *ptrespconn = arg;
    URL_Frame *pURL_Frame = NULL;
    char *pParseBuffer = NULL;
    char szOut[512];
    int stat = -1;

    static char post_data[1024];
    static bool last_post = false;

    os_printf("length[%d]\r\n", length);
    os_printf("recv[%s]\r\n", pusrdata);

    if(check_data(pusrdata, length) == false){
        os_printf("check error\r\n");
        data_send(ptrespconn, false, NULL);
        return ;
    }
    if(save_data(pusrdata, length) == false){
        os_printf("save_data error\r\n");
        data_send(ptrespconn, false, NULL);
        return ;
    }
    pURL_Frame = (URL_Frame *)os_zalloc(sizeof(URL_Frame));
    parse_url(precvbuffer, pURL_Frame);
    os_printf("Type[%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");
            if((strlen(pURL_Frame->pSelect) == 1) && 
                (os_strncmp(pURL_Frame->pSelect, "/", 1) == 0)){
                //获取webconfig页面
                html_send(ptrespconn, true, HTML);
            }
            if(os_strcmp(pURL_Frame->pSelect, "config") == 0 &&
                os_strcmp(pURL_Frame->pCommand, "command") == 0) {
                os_memset(szOut, 0, sizeof(szOut));
#if PLUG_DEVICE
                stat = user_plug_getmethed(szOut);
#elif FAN_DEVICE
                stat = user_fan_getmethed(szOut);
#elif DS18B20_DEVICE
                stat = user_ds18b20_getmethed(szOut);
#endif
                if(stat==0){
                    os_printf("get22szOut[%s]\r\n", szOut);
                    data_send(ptrespconn, true, szOut);
                }else
                    data_send(ptrespconn, false, NULL);
            }else
                data_send(ptrespconn, false, NULL);
            break ;
        case POST:
            os_printf("We have a POST request.\n");
            pParseBuffer = (char *)os_strstr(precvbuffer, "\r\n\r\n");
            if (pParseBuffer == NULL) {
                break;
            }
            pParseBuffer += 4;
            os_printf("pParseBuffer[%s]\r\n", pParseBuffer);

            if((strlen(pURL_Frame->pSelect) == 1) && 
                (os_strncmp(pURL_Frame->pSelect, "/", 1) == 0)){
                //webconfig配网
                webconfig_set_wifi(pParseBuffer);
                data_send(ptrespconn, false, NULL);
                break ;
            }else if (os_strcmp(pURL_Frame->pSelect, "config") == 0 &&
                os_strcmp(pURL_Frame->pCommand, "command") == 0) {
                os_memset(szOut, 0, sizeof(szOut));
#if PLUG_DEVICE
                stat = user_plug_postmethed(pParseBuffer, szOut);
#elif FAN_DEVICE
                stat = user_fan_postmethed(pParseBuffer, szOut);
#elif DS18B20_DEVICE
                stat = user_ds18b20_postmethed(pParseBuffer, szOut);
#endif
                if(stat == 0){
                    os_printf("post22szOut[%s]\r\n", szOut);
                    data_send(ptrespconn, true, szOut);
                }else
                    data_send(ptrespconn, false, NULL);

            } else {
                os_printf("\r\nparse error!\r\n");
                data_send(ptrespconn, false, NULL);
            }
            break ;
    }

    if (precvbuffer != NULL){
        os_free(precvbuffer);
        precvbuffer = NULL;
    }
    os_free(pURL_Frame);
    pURL_Frame = NULL;
}

OVER 很简单。本人参考使用Web页面配置ESP8266的参数思路开发修改。

git链接https://gitee.com/review/esp-01.git

这里写图片描述

猜你喜欢

转载自blog.csdn.net/vr7jj/article/details/80316745