ESP32+idf开发之WIFI通信入门(5)HTTP通信

本文介绍了如何使用ESP32和idf框架进行WIFI通信,通过HTTP协议实现GET和POST请求。ESP32作为HTTP客户端,向服务器发送请求并接收响应,涉及URL参数、JSON数据格式和事件回调函数。同时,文章提供了服务端代码示例,展示了一个简单的计算和响应功能。

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

ESP32+idf开发之WIFI通信入门(5)HTTP通信

一、实现功能:

esp32作为HTTP客户端分别使用GET方法和POST方法向HTTP服务端发送请求得到响应,具体如下:

1、GET方法:向web服务器url发出get请求/add,发送参数x、y的值在服务端求和并响应,esp32得到返回数据;

2、POST方法:向web服务器url发出POST请求/add,发送参数x、y的值在服务端求和并响应,esp32得到返回数据;

3、使用json数据格式通信

二、HTTP概述:

​ HTTP协议是Hyper Text Transfer Protocol(超文本传输协议)基于TCP/IP通信协议来传递数据(HTML 文件, 图片文件, 查询结果等),是一个属于应用层的面向对象的协议,由于其简捷、快速的方式,适用于分布式超媒体信息系统。其主要特点:

简单快速:客户向服务器请求服务时,只需传送请求方法和路径。请求方法常用的有GET、HEAD、POST。每种方法规定了客户与服务器联系的类型不同。由于HTTP协议简单,使得HTTP服务器的程序规模小,因而通信速度很快。

灵活:HTTP允许传输任意类型的数据对象。正在传输的类型由Content-Type加以标记。

无连接:无连接的含义是限制每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开连接。采用这种方式可以节省传输时间。

无状态:HTTP协议是无状态协议。无状态是指协议对于事务处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大。另一方面,在服务器不需要先前信息时它的应答就较快。

支持B/S及C/S模式。

img

HTTP使用统一资源标识符(Uniform Resource Identifiers, URI)来传输数据和建立连接。URL(UniformResourceLocator, 统一资源定位符)是一种特殊类型的URI,

http://xxx.xxx.xxx.xxx:9999/add?x=3&y=4

以上URL包括以下几部分:协议部分(http:),域名/IP地址部分,端口部分(9999),文件名部分(从域名后的最后一个“/”开始到“?”为止,即/add?),参数部分(x=3&y=4)等。

客户端发送一个HTTP请求到服务器的请求消息(request):请求行(request line)、请求头部(header)、空行和请求数据四个部分组成。

img

服务器接收并处理客户端发过来的请求后会返回一个HTTP的响应消息(response):状态行、消息报头、空行和响应正文。

img

GET方法和POST方法区别:

GET提交:请求的数据会附在URL之后(就是把数据放置在HTTP协议头中),以?分割URL和传输数据,多个参数用&连接;

POST提交:把提交的数据放置在是HTTP包的包体中。

因此,GET提交的数据会在地址栏中显示出来,而POST提交,地址栏不会改变。

三、步骤

1、复制wifi连接的组件代码到工程的自定义组件(components)中,进入vscode创建示例空项目,打开命令终端:

mkdir components

cp -r D:\Espressif\frameworks\esp-idf-v4.4.1\examples\common_components\protocol_examples_common .\components

2、配置wifi连接设置,打开终端命令界面输入idf.py menuconfig,进入到Example Connection Configuration界面对热点信息的ssid和password等配置。

image-20230403194716985

3、在main.c中编写实现以上功能的esp32的http客户端代码:

#include <esp_log.h>
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
#include <esp_system.h>
#include <esp_event.h>

#include <nvs_flash.h>
#include <esp_netif.h>
#include <protocol_examples_common.h>

#include <esp_http_client.h>
#include <cJSON.h>

static char *TAG = "http_client";
static char response_data[1024]; // 自定义缓存空间储存一次响应数据
static int recived_len = 0;      // 自定义变量储存一次响应中接收到分片数据的累计偏移

// http客户端的事件处理回调函数
static esp_err_t http_client_event_handler(esp_http_client_event_t *evt)
{
    switch (evt->event_id)
    {
    case HTTP_EVENT_ON_CONNECTED:
        ESP_LOGI(TAG, "connected to web-server");
        recived_len = 0;
        break;
    case HTTP_EVENT_ON_DATA:
        if (evt->user_data)
        {
            memcpy(evt->user_data + recived_len, evt->data, evt->data_len); // 将分片的每一片数据都复制到user_data
            recived_len += evt->data_len;//累计偏移更新
        }
        break;
    case HTTP_EVENT_ON_FINISH:
        ESP_LOGI(TAG, "finished a request and response!");
        recived_len = 0;
        break;
    case HTTP_EVENT_DISCONNECTED:
        ESP_LOGI(TAG, "disconnected to web-server");
        recived_len = 0;
        break;
    case HTTP_EVENT_ERROR:
        ESP_LOGE(TAG, "error");
        recived_len = 0;
        break;
    default:
        break;
    }

    return ESP_OK;
}

void app_main(void)
{
    esp_err_t ret;

    nvs_flash_init();
    esp_netif_init();
    esp_event_loop_create_default();

    example_connect();

    const esp_http_client_config_t cfg = {
        .url = "http://111.230.201.180:3000",
        .event_handler = http_client_event_handler,
        .user_data = response_data,
    };
    //使用http服务器配置参数对http客户端初始化
    esp_http_client_event_handle_t httpclient = esp_http_client_init(&cfg);

    // GET方法请求
    esp_http_client_set_method(httpclient, HTTP_METHOD_GET);
    esp_http_client_set_url(httpclient, "/add?x=10&y=11");//url传递发送数据x=10,y=11
    ret = esp_http_client_perform(httpclient);//启动并阻塞等待一次响应完成
    if (ret == ESP_OK)
    {
		//一次响应完成,打印完整响应数据,即得到X+y的值
        printf("GET:%s\n", response_data);
    }
    // POST方法请求
    esp_http_client_set_method(httpclient, HTTP_METHOD_POST);
    esp_http_client_set_url(httpclient, "/add/");

    //设置请求头
    esp_http_client_set_header(httpclient, "Content-Type", "application/json");

    //构造json数据jsonArg请求体(即发送数据x=24,y=124)
    cJSON *pRoot = cJSON_CreateObject();
    cJSON_AddStringToObject(pRoot, "x", "24");
    cJSON_AddStringToObject(pRoot, "y", "124");
    // char *jsonArg = "{\"x\":23,\"y\":34}";
    char *jsonArg = cJSON_Print(pRoot);
    //printf("jsonArg:%s\n", jsonArg);
    esp_http_client_set_post_field(httpclient, jsonArg, strlen(jsonArg));

    ret = esp_http_client_perform(httpclient);
    if (ret == ESP_OK)
    {
        //一次响应完成,打印完整响应数据,即得到X+y的值
        printf("POST:%s\n", response_data);
    }

    esp_http_client_cleanup(httpclient);//清空http客户端描述符
}

4、服务端本人部署在腾讯云服务器,其中服务端代码文件index.js如下所示。(初学者可先不部署服务端,可使用本人的服务端进行测试)

const express = require('express')
const bodyParser = require('body-parser')
const request = require('request')
const fs = require('fs')
const app = express()
app.use(bodyParser.json())

app.get('/add', (req, res) => {
    console.log("\nx: "+req.query.x)
    console.log("\ny: "+req.query.y)
    //查询
    res.json({
                result: true,
                method:"GET",
                message:Number(req.query.x) + Number(req.query.y)
            })
})

app.post('/add', (req, res) => {
    console.log("\nx: "+req.body.x)
    console.log("\ny: "+req.body.y)
    //增加
    res.json({
                result: true,
                method:"POST",
                message:Number(req.body.x) + Number(req.body.y)
            })
})


app.listen(3000, () => {
    console.log('server running at http://127.0.0.1:3000')
})

四、测试

有自行搭建服务器的则对应路径下运行:sudo node index.js开启服务端。

编译、烧写、监控esp32,观察打印esp32的终端打印信息,测试是否响应数据正常。得到GET请求测试10+11=21返回json数据测试正常;POST请求24+124=148返回json数据测试正常。

image-20230403201839132

<think>好的,用户的问题是关于ESP32通过串口进行HTTP OTA更新的示例和文档。首先,我需要确认用户的需求。他们可能已经知道OTA更新的基本概念,但需要具体的实现方法,特别是通过串口结合HTTP的OTA更新。 首先,我应该回顾ESP32的OTA机制。ESP32通常支持两种OTA方式:通过WiFi的无线更新和通过串口的有线更新。但用户提到的是串口HTTP OTA,这可能是指使用串口传输固件文件,同时利用HTTP协议进行控制。不过,标准的ESP32 OTA流程中,串口通常用于使用例如esptool.py的工具进行更新,而HTTP OTA通常是无线方式。这里可能存在一些混淆,或者用户希望将两者结合,比如通过串口接收HTTP请求来触发OTA流程。 接下来,我需要查阅相关文档和示例。Arduino-esp32的文档中提到了使用BasicOTA和AsyncElegantOTA库进行OTA更新,但这些主要是基于WiFi的。不过,用户提供的引用提到了AsyncElegantOTA,这可能是一个支持异步处理的库,但同样需要网络连接。 用户的需求可能是想通过串口来传输固件,而不是通过WiFi,但使用HTTP协议进行控制。这可能涉及到自定义协议,或者在串口上模拟HTTP通信。不过,标准的HTTP OTA需要网络连接,因此需要明确用户的具体场景。 可能的解决方案是:使用串口接收固件文件,然后通过Bootloader进行更新。但这需要自己处理固件的传输和校验,而不是使用HTTP协议。或者,用户可能希望通过串口发送HTTP请求来触发从某个服务器下载固件,这时候需要ESP32通过串口连接到另一个设备(如蜂窝模块)来访问网络,但这可能超出单纯串口更新的范围。 我需要确认是否有现有的库或示例支持这种串口HTTP OTA。根据现有的知识,ESP-IDF中的OTA机制主要通过WiFi或以太网,串口通常用于使用esptool的烧录。不过,用户可能希望在不使用WiFi的情况下,通过串口进行类似于OTA的更新,这时候可能需要自定义实现。 因此,回答应该包括以下几点: 1. 澄清标准OTA方法(串口烧录 vs HTTP OTA)。 2. 提供使用Arduino库的HTTP OTA示例(需要WiFi)。 3. 如果用户确实需要通过串口进行OTA,可能需要自定义流程,例如通过串口传输固件并重启进入Bootloader。 4. 提供相关文档链接,如ESP-IDF OTA文档和Arduino-esp32的OTA示例。 同时,确保回答符合格式要求,使用正确的中文,LaTeX格式,以及引用标识。检查是否有生成的相关问题,如如何通过WiFi进行HTTP OTA,如何通过串口烧录固件,自定义串口OTA的方法等。</think>[系统级回答] 关于ESP32通过串口进行HTTP OTA更新的实现,目前ESP-IDF框架和Arduino核心库主要支持以下两种方式: 1. **标准串口烧录**:使用$esptool.py$工具通过UART协议直接写入固件[^1],但此过程需手动触发且不涉及HTTP协议 2. **无线HTTP OTA**:基于WiFi网络实现的OTA更新,典型实现代码如下: ```cpp #include <HTTPClient.h> #include <Update.h> void performOTA(){ HTTPClient http; http.begin("http://your-server/firmware.bin"); int code = http.GET(); if(code == HTTP_CODE_OK) { Update.begin(http.getSize()); Update.writeStream(http.getStream()); if(Update.end()) { ESP.restart(); } } } ``` 目前官方文档中暂未发现直接通过物理串口实现HTTP OTA的案例。但可以通过以下技术路线实现类似功能: 1. 创建虚拟串口协议栈,使用$UART$接收HTTP请求报文 2. 通过自定义协议封装固件数据包 3. 调用$esp_ota_ops.h$接口进行分区写入 参考文档: - ESP-IDF OTA机制说明:https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/system/ota.html - Arduino-esp32 OTA示例:https://github.com/espressif/arduino-esp32/tree/master/libraries/ArduinoOTA/examples
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值