ESP8266 WEB 配网 (基于 RTOSSDK 3.2)

一、效果

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

二、基础例程

  1. HTTP服务基于examples\protocols\http_server\advanced_tests
  2. WIFI扫描基于https://github.com/espressif/esp-idf/tree/master/examples/wifi/scan
  3. AP配置基于ESP8266_RTOS_SDK\examples\wifi\getting_started\softAP
  4. DNS服务基于https://github.com/ospanic/Captive_Portal_ESP

三、HTTPD配置

在返回一个URL页面时,会出现response uri/header too big错误,这里需要设置一下接收页面的大小,通过make menuconfig来修改 成1500字节
Location: │
│ -> Component config
在这里插入图片描述

四、网页内嵌

通过 component.mk 可以将文件直接编译进固件里面,我这里内嵌了3个网页,都放在同级目录下
在这里插入图片描述

component.mk :

#
# "main" pseudo-component makefile.
#
# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.)

COMPONENT_EMBED_TXTFILES :=  index.html
COMPONENT_EMBED_TXTFILES +=  WebConfig.html
COMPONENT_EMBED_TXTFILES +=  WiFiConfig.html

在程序里,可以这样调用:

extern const uint8_t index_html_start[] asm("_binary_index_html_start");
extern const uint8_t index_html_end[]   asm("_binary_index_html_end");

extern const uint8_t WebConfig_html_start[] asm("_binary_WebConfig_html_start");
extern const uint8_t WebConfig_html_end[]   asm("_binary_WebConfig_html_end");

extern const uint8_t WiFiConfig_html_start[] asm("_binary_WiFiConfig_html_start");
extern const uint8_t WiFiConfig_html_end[]   asm("_binary_WiFiConfig_html_end");

五、认证页面跳转

苹果手机在连接WIFI后,会发起DNS请求,URL是/hotspot-detect.html,将其转发到根地址即可,再对这个url进行一个GET请求的回复

	///苹果跳转页面
    { .uri      = "/hotspot-detect.html",
      .method   = HTTP_GET,
      .handler  = index_get_handler,
      .user_ctx = NULL,
    },
	

六、HTTPD回调配置

我这里主要做了3个网页
1.主页,有一个按钮,点击后会跳转到另外一个URL,我这里的逻辑是收到这个GET请求后,先进行WIFI扫描,将扫描结果,做成一个表格,和配置网页数据一起返回
2.配置网页,有2个框可以输入SSID和密码,下面有一个当前环境下的WIFI表这里可以做成下拉列表,用JS获取数据,这样就不会写错SSID了,这个暂时没实现
3.WIFI设置网页,显示正在链接WIFI中

回调的设置如下:

//主页
esp_err_t index_get_handler(httpd_req_t *req)
{

    ESP_LOGI(TAG, "Free Stack for server task: '%u'", uxTaskGetStackHighWaterMark(NULL));
    httpd_resp_send(req, (char *)&index_html_start, strlen((char *)&index_html_start));
    return ESP_OK;

}

//配置页面
esp_err_t web_config_get_handler(httpd_req_t *req)
{

    ESP_LOGI(TAG, "Free Stack for server task: '%u'", uxTaskGetStackHighWaterMark(NULL));
    //httpd_resp_send(req, (char *)&WebConfig_html_start, strlen((char *)&WebConfig_html_start));
	
	//先扫描wifi
	char*  buf = malloc(3000);
	memset(buf,0,3000);
	wifi_scan(buf);
	printf("\r\nbuf=%s\r\n",buf);
	
   // httpd_handle_t hd = resp_arg->hd;
   // int fd = resp_arg->fd;
	
    //resp_arg->hd = req->handle;
   // resp_arg->fd = httpd_req_to_sockfd(req);
	
#define HTTPD_HDR_STR      "HTTP/1.1 200 OK\r\n"                   \
                           "Content-Type: text/html\r\n"           \
                           "Content-Length: %d\r\n"
	char  head_buf[256];
	memset(head_buf,0,sizeof(head_buf));
	sprintf(head_buf,HTTPD_HDR_STR,strlen(buf)+strlen((char *)&WebConfig_html_start));

	httpd_send(req, head_buf, strlen(head_buf));
	httpd_send(req, "\r\n", 2);
	httpd_send(req, (char *)&WebConfig_html_start, strlen((char *)&WebConfig_html_start));
	httpd_send(req, buf, strlen(buf));
	
   // httpd_default_send(req->handle, httpd_req_to_sockfd(req), HTTPD_HDR_STR,strlen(buf)+strlen((char *)&WebConfig_html_start), 0);
    /* Space for sending additional headers based on set_header */
  //  httpd_default_send(req->handle, httpd_req_to_sockfd(req), "\r\n", strlen("\r\n"), 0);
	//httpd_default_send(req->handle, httpd_req_to_sockfd(req), (char *)&WebConfig_html_start,strlen((char *)&WebConfig_html_start), 0);
   // httpd_default_send(req->handle, httpd_req_to_sockfd(req), buf, strlen(buf), 0);
	
	free(buf);
	
    return ESP_OK;

}

//配置WIFI等待页面
esp_err_t wifi_config_post_handler(httpd_req_t *req)
{

    ESP_LOGI(TAG, "Free Stack for server task: '%u'", uxTaskGetStackHighWaterMark(NULL));
   // httpd_resp_send(req, (char *)&WebConfig_html_start, strlen((char *)&WebConfig_html_start));
	
    ESP_LOGI(TAG, "/echo handler read content length %d", req->content_len);

    char*  buf = malloc(req->content_len + 1);
    size_t off = 0;
    int    ret;

    if (!buf) {
        httpd_resp_send_500(req);
        return ESP_FAIL;
    }

    while (off < req->content_len) {
        /* Read data received in the request */
        ret = httpd_req_recv(req, buf + off, req->content_len - off);
        if (ret <= 0) {
            if (ret == HTTPD_SOCK_ERR_TIMEOUT) {
                httpd_resp_send_408(req);
            }
            free (buf);
            return ESP_FAIL;
        }
        off += ret;
        ESP_LOGI(TAG, "/echo handler recv length %d", ret);
    }
    buf[off] = '\0';

    if (req->content_len < 128) {
        ESP_LOGI(TAG, "/echo handler read %s", buf);
    }
	
	///>下面会将收到的post数据重新回复回去,这里我直接拿来联网,并且将成功配网返回去
	#if 0
    /* Search for Custom header field */
    char*  req_hdr = 0;
    size_t hdr_len = httpd_req_get_hdr_value_len(req, "Custom");
    if (hdr_len) {
        /* Read Custom header value */
        req_hdr = malloc(hdr_len + 1);
        if (req_hdr) {
            httpd_req_get_hdr_value_str(req, "Custom", req_hdr, hdr_len + 1);

            /* Set as additional header for response packet */
            httpd_resp_set_hdr(req, "Custom", req_hdr);
        }
    }
    httpd_resp_send(req, buf, req->content_len);
	free (req_hdr);
	#else 
	httpd_resp_send(req, (char *)&WiFiConfig_html_start, strlen((char *)&WiFiConfig_html_start));
	#endif
	
    
    free (buf);
    return ESP_OK;
	
}


    { .uri      = "/",
      .method   = HTTP_GET,
      .handler  = index_get_handler,
      .user_ctx = NULL,
    },
    { .uri      = "/WebConfig.html",
      .method   = HTTP_GET,
      .handler  = web_config_get_handler,
      .user_ctx = NULL,
    },
	
    { .uri      = "/WiFiConfig.html",
      .method   = HTTP_POST,
      .handler  = wifi_config_post_handler,
      .user_ctx = NULL,
    },

七、WIFI扫描

WIFI扫描,做了一个HTML的表格数据返回,最多15个,表格的结构如下:

<table border="1">
  <tr>
    <th>Month</th>
    <th>Savings</th>
  </tr>
  <tr>
    <td>January</td>
    <td>$100</td>
  </tr>
</table>

程序如下:

#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/event_groups.h"
#include "esp_wifi.h"
#include "esp_log.h"
#include "esp_event.h"
#include "nvs_flash.h"

#define DEFAULT_SCAN_LIST_SIZE 15

static const char *TAG = "scan";

static void print_auth_mode(int authmode,char * buf)
{
    switch (authmode) {
    case WIFI_AUTH_OPEN:
        ESP_LOGI(TAG, "Authmode \tWIFI_AUTH_OPEN");
		sprintf(buf+strlen(buf),"<td>%s</td>","AUTH_OPEN");
        break;
    case WIFI_AUTH_WEP:
        ESP_LOGI(TAG, "Authmode \tWIFI_AUTH_WEP");
		sprintf(buf+strlen(buf),"<td>%s</td>","AUTH_WEP");
        break;
    case WIFI_AUTH_WPA_PSK:
		sprintf(buf+strlen(buf),"<td>%s</td>","AUTH_WPA_PSK");
        break;
    case WIFI_AUTH_WPA2_PSK:
        ESP_LOGI(TAG, "Authmode \tWIFI_AUTH_WPA2_PSK");
		sprintf(buf+strlen(buf),"<td>%s</td>","WPA2_PSK");
        break;
    case WIFI_AUTH_WPA_WPA2_PSK:
        ESP_LOGI(TAG, "Authmode \tWIFI_AUTH_WPA_WPA2_PSK");
		sprintf(buf+strlen(buf),"<td>%s</td>","WPA_WPA2_PSK");
        break;
    case WIFI_AUTH_WPA2_ENTERPRISE:
        ESP_LOGI(TAG, "Authmode \tWIFI_AUTH_WPA2_ENTERPRISE");
		sprintf(buf+strlen(buf),"<td>%s</td>","WPA2_ENTERPRISE");
        break;
    default:
        ESP_LOGI(TAG, "Authmode \tWIFI_AUTH_UNKNOWN");
		sprintf(buf+strlen(buf),"<td>%s</td>","UNKNOWN");
        break;
    }
}

static void print_cipher_type(int pairwise_cipher, int group_cipher)
{
    switch (pairwise_cipher) {
    case WIFI_CIPHER_TYPE_NONE:
        ESP_LOGI(TAG, "Pairwise Cipher \tWIFI_CIPHER_TYPE_NONE");
        break;
    case WIFI_CIPHER_TYPE_WEP40:
        ESP_LOGI(TAG, "Pairwise Cipher \tWIFI_CIPHER_TYPE_WEP40");
        break;
    case WIFI_CIPHER_TYPE_WEP104:
        ESP_LOGI(TAG, "Pairwise Cipher \tWIFI_CIPHER_TYPE_WEP104");
        break;
    case WIFI_CIPHER_TYPE_TKIP:
        ESP_LOGI(TAG, "Pairwise Cipher \tWIFI_CIPHER_TYPE_TKIP");
        break;
    case WIFI_CIPHER_TYPE_CCMP:
        ESP_LOGI(TAG, "Pairwise Cipher \tWIFI_CIPHER_TYPE_CCMP");
        break;
    case WIFI_CIPHER_TYPE_TKIP_CCMP:
        ESP_LOGI(TAG, "Pairwise Cipher \tWIFI_CIPHER_TYPE_TKIP_CCMP");
        break;
    default:
        ESP_LOGI(TAG, "Pairwise Cipher \tWIFI_CIPHER_TYPE_UNKNOWN");
        break;
    }

    switch (group_cipher) {
    case WIFI_CIPHER_TYPE_NONE:
        ESP_LOGI(TAG, "Group Cipher \tWIFI_CIPHER_TYPE_NONE");
        break;
    case WIFI_CIPHER_TYPE_WEP40:
        ESP_LOGI(TAG, "Group Cipher \tWIFI_CIPHER_TYPE_WEP40");
        break;
    case WIFI_CIPHER_TYPE_WEP104:
        ESP_LOGI(TAG, "Group Cipher \tWIFI_CIPHER_TYPE_WEP104");
        break;
    case WIFI_CIPHER_TYPE_TKIP:
        ESP_LOGI(TAG, "Group Cipher \tWIFI_CIPHER_TYPE_TKIP");
        break;
    case WIFI_CIPHER_TYPE_CCMP:
        ESP_LOGI(TAG, "Group Cipher \tWIFI_CIPHER_TYPE_CCMP");
        break;
    case WIFI_CIPHER_TYPE_TKIP_CCMP:
        ESP_LOGI(TAG, "Group Cipher \tWIFI_CIPHER_TYPE_TKIP_CCMP");
        break;
    default:
        ESP_LOGI(TAG, "Group Cipher \tWIFI_CIPHER_TYPE_UNKNOWN");
        break;
    }
}

/*
<table border="1">
  <tr> 一行
    <th>Month</th> th 标题元素 会加粗
    <th>Savings</th> 
  </tr>
  <tr>
    <td>January</td> 第二行第一列
    <td>$100</td> 第二行第二列
  </tr>
</table>

[0;32mI (4292) scan: SSID 		ZZKJ[0m
[0;32mI (4297) scan: RSSI 		-77[0m
[0;32mI (4302) scan: Authmode 	WIFI_AUTH_WPA_WPA2_PSK[0m
[0;32mI (4310) scan: Pairwise Cipher 	WIFI_CIPHER_TYPE_UNKNOWN[0m
[0;32mI (4319) scan: Group Cipher 	WIFI_CIPHER_TYPE_UNKNOWN[0m
[0;32mI (4328) scan: Channel 		6

*/
/* Initialize Wi-Fi as sta and set scan method */
void wifi_scan(char *buf)//将扫描数据存进buf
{
	#if 0
    ESP_ERROR_CHECK(esp_netif_init());
    ESP_ERROR_CHECK(esp_event_loop_create_default());
    esp_netif_t *sta_netif = esp_netif_create_default_wifi_sta();
    assert(sta_netif);

    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
    ESP_ERROR_CHECK(esp_wifi_init(&cfg));

    uint16_t number = DEFAULT_SCAN_LIST_SIZE;
    wifi_ap_record_t ap_info[DEFAULT_SCAN_LIST_SIZE];
    uint16_t ap_count = 0;
    memset(ap_info, 0, sizeof(ap_info));

    ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
    ESP_ERROR_CHECK(esp_wifi_start());
	
	#else 
    uint16_t number = DEFAULT_SCAN_LIST_SIZE;
    wifi_ap_record_t ap_info[DEFAULT_SCAN_LIST_SIZE];
    uint16_t ap_count = 0;
    memset(ap_info, 0, sizeof(ap_info));
	
	#endif
	
    esp_wifi_scan_start(NULL, true);
    ESP_ERROR_CHECK(esp_wifi_scan_get_ap_records(&number, ap_info));
    ESP_ERROR_CHECK(esp_wifi_scan_get_ap_num(&ap_count));
    ESP_LOGI(TAG, "Total APs scanned = %u", ap_count);
	
	sprintf(buf+strlen(buf),"<div align=\"center\">");//写入居中
	sprintf(buf+strlen(buf),"Total APs scanned = %u<br/><br/>",ap_count);//写入总共的AP数
	sprintf(buf+strlen(buf),"<table border=\"1\">");//写入表格
	sprintf(buf+strlen(buf),"<tr><th>SSID</th><th>RSSI</th><th>Authmode</th><th>Channel</th></tr>");//写入标签头 
	
    for (int i = 0; (i < DEFAULT_SCAN_LIST_SIZE) && (i < ap_count); i++) {
        ESP_LOGI(TAG, "SSID \t\t%s", ap_info[i].ssid);
        ESP_LOGI(TAG, "RSSI \t\t%d", ap_info[i].rssi);
        
		
		sprintf(buf+strlen(buf),"<tr>");//一行开头
		sprintf(buf+strlen(buf),"<td>%s</td>",ap_info[i].ssid);//写入SSID元素
		sprintf(buf+strlen(buf),"<td>%d</td>",ap_info[i].rssi);//写入rssi元素
			
		print_auth_mode(ap_info[i].authmode,buf); //写入authomode元素
		
        if (ap_info[i].authmode != WIFI_AUTH_WEP) {
            print_cipher_type(ap_info[i].pairwise_cipher, ap_info[i].group_cipher);
        }
        ESP_LOGI(TAG, "Channel \t\t%d\n", ap_info[i].primary);
		sprintf(buf+strlen(buf),"<td>%d</td>",ap_info[i].primary);//写入channal 元素
		sprintf(buf+strlen(buf),"</tr>");//完成一行
    }
	//写入表尾
	sprintf(buf+strlen(buf),"</table>");
	
}
  • 1
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值