(ESP32学习记录)在ESP32C3上实现HTTP Web服务器

借鉴ESP32官方例程实现了简单的HTTP Web服务器,代码如下:

/*HTTP服务器端*/
#include <stdio.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_wifi.h"
#include "esp_netif.h"
#include "nvs_flash.h"
#include "wifi_provisioning/manager.h"
#include "wifi_provisioning/scheme_softap.h"
#include "socket.h"
#include "esp_http_server.h"
/*宏定义*/
#define ERASE_NVS 0
// 清除储存的wifi密码->0: 沿用上次的WIFI信息进行连接; 1: 清除WIFI信息,使用SOFTAP一键配网进行新链接
/*函数声明*/
void WIFI_CALLBACK_FUN(void *event_handler_arg, esp_event_base_t event_base, int32_t event_id, void *event_data); // 事件队列回调函数
void wifi_connect(void);                                                                                          // WIFI连接处理函数
esp_err_t HTTPD_URI_HANDLER_GET_FUN(httpd_req_t *r); //HTTP web server 事件URI处理函数, 处理来自于客户端的GET请求
esp_err_t HTTPD_URI_HANDLER_POST_FUN(httpd_req_t *r); //HTTP web server 事件URI处理函数, 处理来自于客户端的POST请求
/*全局变量*/

/***************************************************************************************************************/
/*MAIN函数*/
void app_main(void)
{
    wifi_connect(); // 连接wifi
    /*1. 配置Web服务器*/
    httpd_handle_t handle;
    httpd_config_t config = HTTPD_DEFAULT_CONFIG();
    config.server_port = 80;
    config.lru_purge_enable = true; //清除“最近最少使用”连接
    httpd_start(&handle, &config);
    /*2. 注册URI处理事件*///注册函数必须放在httpd_start函数成功执行之后
    httpd_uri_t uri_handler_get_from_client_dt =
    {
        .uri = "/ok",
        .method = HTTP_GET, //客户端发送来的GET请求
        .handler = HTTPD_URI_HANDLER_GET_FUN
    };
    httpd_register_uri_handler(handle, &uri_handler_get_from_client_dt);    //客户端GET请求事件注册

    httpd_uri_t uri_handler_post_from_client_dt =
    {
        .uri = "/ok",
        .method = HTTP_POST,
        .handler = HTTPD_URI_HANDLER_POST_FUN
    };
    httpd_register_uri_handler(handle, &uri_handler_post_from_client_dt);  //客户端POST请求事件注册
    /*while循环,空任务*/
    while(1)
    {
        vTaskDelay(10);
    }
    /*end. 关闭http服务*/
    httpd_stop(handle);
}
/*HTTPD注册URI的处理函数*/
esp_err_t HTTPD_URI_HANDLER_GET_FUN(httpd_req_t *r)
{
    char *snd_dat = "Hello http client!\0";
    esp_err_t ret = httpd_resp_send(r, snd_dat, strlen(snd_dat));
    if(ret == ESP_OK)
    {
        printf("已经向客户端发送数据: %s\n", snd_dat);
        printf("URL=%s\n", r->uri);
        printf("LEN=%d\n", r->content_len);
    }
    return ret;
}
esp_err_t HTTPD_URI_HANDLER_POST_FUN(httpd_req_t *r)
{
    char recv_buf[100] = {0};
    int err_cnt = 0;
    int recv_dt_len = 0;
    printf("收到POST请求,开始处理!\n");
    printf("数据长度为: %d\n", r->content_len);
    printf("recv_buf size is %d\n", sizeof(recv_buf));
    if((r->content_len) > sizeof(recv_buf))    //如果接收的数据长度大于缓冲去大小
    {
        recv_dt_len = sizeof(recv_buf);
        while(recv_dt_len > 0)
        {
            int ret = httpd_req_recv(r, recv_buf, sizeof(recv_buf));
            if(ret > 0)
            {
                printf("收到的数据为:%s\n", recv_buf);
                recv_dt_len = recv_dt_len - ret;
                err_cnt = 0;
            }
            else if(ret == HTTPD_SOCK_ERR_TIMEOUT)   //连接超时,需要重试
            {
                err_cnt ++;
                vTaskDelay(100);
                if(err_cnt == 20)   //重试次数20
                {
                    printf("TIMEOUT连接超时!\n");
                    httpd_resp_send_404(r); //向客户端发送404错误
                    break;
                }
            }
            else if(ret < 0)
            {
                printf("错误!\n");
                httpd_resp_send_408(r); //向客户端发送错误
                break;
            }
            else    //ret=0->连接断开或接收缓冲区(HTTP缓冲区)为空
            {
                break;
            }
        }
    }
    else        //接收数据长度小于缓冲区大小
    {
        recv_dt_len = r->content_len;
        int ret = httpd_req_recv(r, recv_buf, recv_dt_len);
        if(ret > 0)
            printf("收到的数据为:%s\n", recv_buf);
        else if(ret < 0)
        {
            if(ret == HTTPD_SOCK_ERR_TIMEOUT)
            {
                while(1)
                {
                    err_cnt ++;
                    vTaskDelay(100);
                    ret = httpd_req_recv(r, recv_buf, recv_dt_len);
                    if(ret > 0)
                    {
                        printf("收到的数据为:%s\n", recv_buf);
                        break;
                    }
                    else        //其他小于0的情况
                        break;
                    if(err_cnt == 20)
                    {
                        printf("TIMEOUT连接超时!\n");
                        httpd_resp_send_404(r); //向客户端发送404错误
                        break;
                    }
                }
            }
        }
    }
    printf("POST请求处理完毕,退出函数!\n");
    return ESP_OK;
    //HTTPD_SOCK_ERR_INVALID
}
/**********************************************************************************************/
/*回调函数*/
void WIFI_CALLBACK_FUN(void *event_handler_arg, esp_event_base_t eb, int32_t ei, void *event_data)
{
    if (eb == WIFI_EVENT)
    {
        if (ei == WIFI_EVENT_STA_START)
        {
            esp_wifi_connect(); // 开始连接WIFI
            printf("正在连接WIFI!\n");
        }
        if (ei == WIFI_EVENT_STA_DISCONNECTED)
        {
            printf("自动连接失败,正在启动SOFTAP配网服务!\n");
            const char *pop = "abcd1234";
            const char *wifi_name = "SOFTAP_PROV_MGR_PROB";
            const char *wifi_key = "12345678";
            wifi_prov_mgr_start_provisioning(WIFI_PROV_SECURITY_1, pop, wifi_name, wifi_key);
            wifi_prov_mgr_wait();
            wifi_prov_mgr_deinit();
            printf("Provisioning服务结束,连接WIFI成功!\n");
        }
    }
    if (eb == IP_EVENT && ei == IP_EVENT_STA_GOT_IP)
    {
        printf("WIFI连接成功!\n");
        ip_event_got_ip_t *sta_ip = (ip_event_got_ip_t *)event_data;
        printf("本机IP地址为: " IPSTR "\n", IP2STR(&sta_ip->ip_info.ip));
    }
}

/*连接WIFI*/
void wifi_connect(void)
{
    nvs_flash_init();
#if ERASE_NVS != 0
    nvs_flash_erase();
    nvs_flash_init();
#endif
    esp_event_loop_create_default(); // 创建默认事件队列
    esp_event_handler_instance_register(IP_EVENT, IP_EVENT_STA_GOT_IP, WIFI_CALLBACK_FUN, NULL, NULL);
    esp_netif_init();                    // 初始化网卡
    esp_netif_create_default_wifi_ap();  // 创建默认网卡ap
    esp_netif_create_default_wifi_sta(); // 创建默认网卡sta
    wifi_init_config_t esp_wifi_init_config = WIFI_INIT_CONFIG_DEFAULT();
    esp_wifi_init(&esp_wifi_init_config); // 初始化WIFI功能
    /*softAP配网*/
    wifi_prov_mgr_config_t wifi_prov_mgr_config_t =
        {
            .scheme = wifi_prov_scheme_softap,
            .app_event_handler = WIFI_PROV_EVENT_HANDLER_NONE};
    wifi_prov_mgr_init(wifi_prov_mgr_config_t);
    bool wifi_prov_mgr_diag = false;
    wifi_prov_mgr_is_provisioned(&wifi_prov_mgr_diag);
    if (wifi_prov_mgr_diag == false)
    {
        const char *pop = "abcd1234";
        const char *wifi_name = "SOFTAP_PROV_MGR_PROB";
        const char *wifi_key = "12345678";
        wifi_prov_mgr_start_provisioning(WIFI_PROV_SECURITY_1, pop, wifi_name, wifi_key);
        wifi_prov_mgr_wait();
        wifi_prov_mgr_deinit();
        printf("Provisioning服务结束,连接WIFI成功!\n");
    }
    else
    {
        esp_event_handler_instance_register(WIFI_EVENT, WIFI_EVENT_STA_START, WIFI_CALLBACK_FUN, NULL, NULL);        // 注册WIFI开启事件
        esp_event_handler_instance_register(WIFI_EVENT, WIFI_EVENT_STA_CONNECTED, WIFI_CALLBACK_FUN, NULL, NULL);    // 注册WIFI连接事件
        esp_event_handler_instance_register(WIFI_EVENT, WIFI_EVENT_STA_DISCONNECTED, WIFI_CALLBACK_FUN, NULL, NULL); // 注册WIFI连接失败事件
        esp_wifi_start();
    }
    esp_wifi_set_ps(WIFI_PS_NONE); // 关闭WIFI的省电模式
}

使用浏览器向ESP32 http web server发送POST请求

var xhr = new XMLHttpRequest();
xhr.open("POST", "http://192.168.137.123/ok", true);
xhr.send("hello web server!");

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值