第09章 HTTP请求注册
约 3815 字大约 13 分钟
2026-03-23
1. OTA版本检查和激活
程序初始化结束后首先要向服务器发送post请求
官方文档: https://my.feishu.cn/wiki/FjW6wZmisimNBBkov6OcmfvknVd
1.1 请求示例
请求体:
| Header | |
|---|---|
| Device-Id | 设备WiFi Mac地址 |
| Client-Id | UUID,第一次随机生成,之后需要报存 |
| Accept-Language | 语言标志,我们直接选zh-CN |
| User-Agent | 开发板名称/固件版本 |
请求头:
{
"application":
{
"compile_time": "Apr 28 2025",
"elf_sha256": "c8ded1fda8e3716d3f5da1ebcf863a5d3bedcd8f273e6be9e9990fca377eb32c",
"idf_version": "v5.3.2-dirty",
"name": "template-app",
"version": "7354bef-dirty"
},
"board":
{
"channel": 1,
"ip": "192.168.1.100",
"mac": "f0:f5:bd:50:a9:44",
"name": "bread-compact-wifi",
"rssi": -50,
"ssid": "atguigu",
"type": "bread-compact-wifi"
},
"chip_info":
{
"cores": 2,
"features": 18,
"model": 9,
"revision": 2
},
"chip_model_name": "esp32s3",
"flash_size": 8388608,
"mac_address": "f0:f5:bd:50:a9:44",
"minimum_free_heap_size": 8494904,
"ota":
{
"label": "ota_0"
},
"partition_table":
[
{
"address": 36864,
"label": "nvs",
"size": 16384,
"subtype": 2,
"type": 1
},
{
"address": 53248,
"label": "otadata",
"size": 8192,
"subtype": 0,
"type": 1
},
{
"address": 61440,
"label": "phy_init",
"size": 4096,
"subtype": 1,
"type": 1
},
{
"address": 65536,
"label": "model",
"size": 983040,
"subtype": 130,
"type": 1
},
{
"address": 1048576,
"label": "ota_0",
"size": 3670016,
"subtype": 16,
"type": 0
},
{
"address": 4718592,
"label": "ota_1",
"size": 3670016,
"subtype": 17,
"type": 0
}
],
"psram_size": 8388608,
"uuid": "3d3b749b-6a6a-4b33-ac88-3a5afe1c5a96",
"version": 2
}Body如上所示,需要根据开发板情况填写。服务器在收到我们的请求后,会回复:
{
"activation":
{
"challenge": "97582491-9a14-42a9-a18d-dca62eb67e63",
"code": "284596",
"message": "xiaozhi.me\n284596"
},
"firmware":
{
"url": "",
"version": "7354bef-dirty"
},
"mqtt":
{
"client_id": "",
"endpoint": "",
"password": "",
"publish_topic": "",
"subscribe_topic": "",
"username": ""
},
"server_time":
{
"timestamp": 1745824197471,
"timezone_offset": 480
},
"websocket":
{
"token": "test-token",
"url": "wss://api.tenclass.net/xiaozhi/v1/"
}
}其中包含几个重要部分:
(1)如果设备未激活,会发送激活信息;我们需要将激活信息显示在设备中
(2)如果设备版本过旧,会发送OTA信息(这部分我们屏蔽了,因为小智官方的固件不适配我们的门铃开发板)
(3)mqtt协议需要的服务器相关信息。
(4)服务器时间戳以及时区
(5)websocket协议相关信息
这部分代码在OTA模块中实现,是独立于具体协议的,不论使用什么协议都需要在启动时发送上面的数据包。
1.2 响应示例
正确响应:
{
"mqtt": {
"endpoint": "mqtt.example.com",
"client_id": "GID_test@@@device-id@@@uuid",
"username": "device_12345",
"password": "password",
"publish_topic": "device-server"
},
"websocket": {
"url": "wss://api.tenclass.net/xiaozhi/v1/",
"token": "test-token"
},
"server_time": {
"timestamp": 1633024800000,
"timezone": "Asia/Shanghai",
"timezone_offset": -480
},
"firmware": {
"version": "1.0.0",
"url": "https://example.com/firmware/1.0.0.bin"
}
}2. NVS 存储
2.1 NVS 介绍
ESP32的NVS(Non-Volatile Storage,非易失性存储)是一种存储子系统,用于在设备的闪存中持久化保存数据。它特别适用于需要在断电后仍能保持数据的应用场景,例如保存Wi-Fi凭据、设备配置参数、传感器校准值等。
NVS库提供了一个简单的键值对存储机制,允许用户以ASCII字符串作为键来存储和检索多种类型的数据值,包括整数型(如uint8_t, int8_t, uint16_t, 等, 每个键值对都存储在一个命名空间内,这样可以避免不同组件之间的键名冲突
2.2 代码实现
dri_nvs.h
#ifndef __DRI_NVS_H__
#define __DRI_NVS_H__
#include "nvs_flash.h"
#include "nvs.h"
#include "com_debug.h"
/**
* @brief 初始化NVS
*
*/
void dri_nvs_init(void);
/**
* @brief 写入字符串到NVS
*
* @param key 键名
* @param value 值
* @return esp_err_t 错误码
*/
esp_err_t dri_nvs_write_str(const char *key, const char *value);
/**
* @brief 从NVS读取字符串
*
* @param key 键名
* @param value 值缓冲区
* @param value_len 值缓冲区大小
* @return esp_err_t 错误码
*/
esp_err_t dri_nvs_read_str(char *key, char *value, size_t *value_len);
/**
* @brief 查找NVS中是否存在某key
*
* @param key 键名
* @return esp_err_t 错误码
*/
esp_err_t dri_nvs_find_key(char *key);
/**
* @brief 删除NVS中的某key
*
* @param key 键名
* @return esp_err_t 错误码
*/
esp_err_t dri_nvs_delete_key(char *key);
/**
* @brief 删除NVS中的所有key
*
* @return esp_err_t 错误码
*/
esp_err_t dri_nvs_delete_all(void);
#endif /* __DRI_NVS_H__ */dri_nvs.c
#include "dri_nvs.h"
// 定义NVS句柄
nvs_handle_t my_handle;
/**
* @brief 初始化NVS
*
*/
void dri_nvs_init(void)
{
// 1. Initialize NVS
esp_err_t err = nvs_flash_init();
if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND) {
nvs_flash_erase();
nvs_flash_init();
}
// 2. Open
nvs_open("storage", NVS_READWRITE, &my_handle);
}
/**
* @brief 初始化NVS
*
*/
void dri_nvs_init(void);
/**
* @brief 写入字符串到NVS
*
* @param key 键名
* @param value 值
* @return esp_err_t 错误码
*/
esp_err_t dri_nvs_write_str(const char *key, const char *value)
{
return nvs_set_str(my_handle, key, value);
}
/**
* @brief 从NVS读取字符串
*
* @param key 键名
* @param value 值缓冲区
* @param value_len 值缓冲区大小
* @return esp_err_t 错误码
*/
esp_err_t dri_nvs_read_str(char *key, char *value, size_t *value_len)
{
return nvs_get_str(my_handle, key, value, value_len);
}
/**
* @brief 查找NVS中是否存在某key
*
* @param key 键名
* @return esp_err_t 错误码
*/
esp_err_t dri_nvs_find_key(char *key)
{
nvs_type_t out_type;
return nvs_find_key(my_handle, key, &out_type);
}
/**
* @brief 删除NVS中的某key
*
* @param key 键名
* @return esp_err_t 错误码
*/
esp_err_t dri_nvs_delete_key(char *key)
{
return nvs_erase_key(my_handle, key);
}
/**
* @brief 删除NVS中的所有key
*
* @return esp_err_t 错误码
*/
esp_err_t dri_nvs_delete_all(void)
{
return nvs_erase_all(my_handle);
}3. 可变缓冲区
3.1 可变缓冲区介绍
用于存储从小智后台接收的响应内容,响应内容并非一次接收完毕,每接收一部分,就多分配一部分的存储空间。
使用 heap_caps_malloc 在 PSRAM 中分配空间
如果缓冲区大小不够,使用 heap_caps_realloc() 扩容
3.2 代码实现
dri_mutable_buffer.h
#ifndef __DRI_MUTABLE_BUFFER_H__
#define __DRI_MUTABLE_BUFFER_H__
#include <stdlib.h>
#include <string.h>
#include "esp_heap_caps.h"
// 定义可变缓冲区对象类型的别名
typedef struct mutable_buffer_struct mutable_buffer_t;
/**
* @brief 创建一个可变缓冲区对象
*
* @return mutable_buffer_t* 可变缓冲区对象的指针
*/
mutable_buffer_t *dri_mutable_buffer_create(void);
/**
* @brief 向可变缓冲区对象中添加数据
*
* @param buf 可变缓冲区对象的指针
* @param data 数据的指针
* @param size 数据的大小
*/
void dri_mutable_buffer_add_data(mutable_buffer_t *mutable_buffer, void *data, size_t size);
/**
* @brief 获取可变缓冲区对象中的数据
*
* @param mutable_buffer 可变缓冲区对象的指针
* @return void* 数据
*/
void *dri_mutable_buffer_get_data(mutable_buffer_t *mutable_buffer);
/**
* @brief 释放可变缓冲区对象占用的内存
*
* @param mutable_buffer 可变缓冲区对象的指针
*/
void dri_mutable_buffer_free(mutable_buffer_t *mutable_buffer);
#endif /* __DRI_MUTABLE_BUFFER_H__ */dri_mutable_buffer.c
#include "dri_mutable_buffer.h"
// 定义可变缓冲区对象的类型结构体
struct mutable_buffer_struct
{
void *buffer; // 指向缓冲区的指针
size_t size; // 缓冲区的大小
};
/**
* @brief 创建一个可变缓冲区对象
*
* @return mutable_buffer_t* 可变缓冲区对象的指针
*/
mutable_buffer_t *dri_mutable_buffer_create(void)
{
// 在PSRAM中分配空间给可变缓冲区对象
mutable_buffer_t *buf = (mutable_buffer_t *)heap_caps_malloc(sizeof(mutable_buffer_t), MALLOC_CAP_SPIRAM);
// 将存储空间重置
memset(buf, 0, sizeof(mutable_buffer_t));
// 返回可变缓冲区对象的指针
return buf;
}
/**
* @brief 向可变缓冲区对象中添加数据
*
* @param buf 可变缓冲区对象的指针
* @param data 数据的指针
* @param size 数据的大小
*/
void dri_mutable_buffer_add_data(mutable_buffer_t *mutable_buffer, void *data, size_t size)
{
// 如果当前可变缓冲区是空的
if (mutable_buffer->size == 0)
{
// 分配空间,多一个字节存储字符串结束标记
void *buffer = heap_caps_malloc(size + 1, MALLOC_CAP_SPIRAM);
// 让可变缓冲区对象的指针指向该空间
mutable_buffer->buffer = buffer;
}
// 如果当前缓冲区不空
else
{
// 重新分配空间,原有数据 + 新数据 + 一个字节存储字符串结束标记
void *buffer = heap_caps_realloc(mutable_buffer->buffer, mutable_buffer->size + size + 1, MALLOC_CAP_SPIRAM);
// 重新指向新空间
mutable_buffer->buffer = buffer;
}
// 将新数据复制到缓冲区末尾
memcpy(mutable_buffer->buffer + mutable_buffer->size, data, size);
// 重新指定长度
mutable_buffer->size += size;
}
/**
* @brief 获取可变缓冲区对象中的数据
*
* @param mutable_buffer 可变缓冲区对象的指针
* @return void* 数据
*/
void *dri_mutable_buffer_get_data(mutable_buffer_t *mutable_buffer)
{
return mutable_buffer->buffer;
}
/**
* @brief 释放可变缓冲区对象占用的内存
*
* @param mutable_buffer 可变缓冲区对象的指针
*/
void dri_mutable_buffer_free(mutable_buffer_t *mutable_buffer)
{
// 如果可变缓冲区有数据
if (mutable_buffer->size > 0)
{
// 释放数据占用的内存
heap_caps_free(mutable_buffer->buffer);
// 重置长度为0
mutable_buffer->size = 0;
}
// 释放可变缓冲区对象占用的内存
heap_caps_free(mutable_buffer);
}4. 获取MAC地址和 UUID
4.1 MAC地址介绍
MAC(Media Access Control Address)地址是网络设备的物理地址,是一个48位(6字节)的硬件唯一标识符,通常表示为十六进制格式,如 24:0A:C4:12:34:56。
ESP32实际上有多个MAC地址,分别用于不同的网络接口:
| 接口 | 用途 | 关系 |
|---|---|---|
| Base MAC | 基础MAC地址,存储在eFuse中 | 工厂烧录的唯一起始地址 |
| Wi-Fi Station MAC | Wi-Fi客户端模式 | = Base MAC |
| Wi-Fi SoftAP MAC | Wi-Fi热点模式 | = Base MAC + 1 |
| Bluetooth MAC | 蓝牙通信 | = Base MAC + 2 |
| Ethernet MAC | 有线网络(如果使用) | = Base MAC + 3 |
关键特性
- 唯一性:全球唯一(理论上),由IEEE分配给乐鑫,乐鑫烧录到每个芯片
- 可修改:可以通过
esp_base_mac_addr_set()覆盖,但一般不建议,且修改只是副本 - 存储位置:存储在eFuse中,断电不丢失
4.2 UUID 介绍
UUID(通用唯一标识符)是一种128位(16字节)的全局唯一标识符, 通常以36个字符的字符串形式表示。
以下为 UUID版本4 的格式:
xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx| 位置 | 字符 | 含义 |
|---|---|---|
xxxxxxxx-xxxx | x | 任意十六进制数字(0-9, a-f) |
-4xxx | 4 | 固定值,表示UUID版本号(版本4) |
-yxxx | y | 固定取值:8, 9, a, 或 b(表示变体) |
-xxxxxxxxxxxx | x | 任意十六进制数字(0-9, a-f) |
4.2 代码实现
dri_esp32s3.h
#ifndef __DRI_ESP32S3_H__
#define __DRI_ESP32S3_H__
#include <time.h>
#include "esp_heap_caps.h"
#include "esp_mac.h"
#include "dri_nvs.h"
/**
* @brief 获取ESP32S3的MAC地址
*
* @param mac_str MAC地址字符串缓冲区(需要18个字节,包含结束符)
*/
void dri_esp32s3_get_mac(uint8_t *mac_str);
/**
* @brief 获取客户端UUID
*
* @param uuid_str UUID字符串缓冲区(需要37个字节,包含结束符)
*/
void dri_esp32s3_get_uuid(uint8_t *uuid_str);
#endif /* __DRI_ESP32S3_H__ */dri_esp32s3.c
#include "dri_esp32s3.h"
// 封装一个不使用第三方库的生成uuid的函数
void dri_esp32s3_generate_uuid(char *buffer)
{
const char *template = "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx";
const char *hex_chars = "0123456789abcdef";
static int initialized = 0;
if (!initialized)
{
// 创建随机种子
srand(time(NULL));
initialized = 1;
}
for (int i = 0; i < 36; i++)
{
if (template[i] == 'x')
{
buffer[i] = hex_chars[rand() % 16];
}
else if (template[i] == 'y')
{
buffer[i] = hex_chars[8 + (rand() % 4)];
}
else
{
buffer[i] = template[i];
}
}
buffer[36] = '\0';
}
/**
* @brief 获取ESP32S3的MAC地址
*
* @param mac_str MAC地址字符串缓冲区(需要18个字节,包含结束符)
*/
void dri_esp32s3_get_mac(uint8_t *mac_str)
{
// 获取mac地址
uint8_t mac_addr[6];
esp_read_mac(mac_addr, ESP_MAC_WIFI_STA);
// 字符串处理
sprintf((char *)mac_str, "%02X:%02X:%02X:%02X:%02X:%02X",
mac_addr[0], mac_addr[1], mac_addr[2],
mac_addr[3], mac_addr[4], mac_addr[5]);
// 给mac_str添加结束符
mac_str[17] = '\0';
}
/**
* @brief 获取客户端UUID
*
* @param uuid_str UUID字符串缓冲区(需要37个字节,包含结束符)
*/
void dri_esp32s3_get_uuid(uint8_t *uuid_str)
{
// 判断NVS中是否存在UUID
if (dri_nvs_find_key("uuid") == ESP_OK)
{
dri_nvs_read_str("uuid", (char *)uuid_str, NULL);
}
else
{
// 生成UUID
dri_esp32s3_generate_uuid((char *)uuid_str);
// 写入NVS
dri_nvs_write_str("uuid", (char *)uuid_str);
}
}5. HTTP
5.1 HTTP 介绍
HTTP(HyperText Transfer Protocol)是互联网上应用最广泛的基础协议,它定义了客户端(如浏览器)与服务器之间通信的规则,专门用于传输网页、图片、数据等资源。

① 请求与响应
HTTP 采用简单的请求-响应模型,整个过程是无状态的(服务器不记录之前的对话):
客户端发起请求:你在浏览器输入网址或点击链接。
服务器处理并返回:服务器解析请求,找到对应的资源。
客户端接收响应:浏览器接收响应并显示内容。

② 请求报文(Request)
当客户端向服务器要东西时,会发送一个结构化的请求报文,主要包含三部分:
| 组成部分 | 说明 | 典型示例 |
|---|---|---|
| 请求行 | 定义操作类型(方法)和目标 | GET /index.html HTTP/1.1 |
| 请求头 | 传递附加信息(元数据) | Host: www.example.com User-Agent: Chrome/... |
| 请求体 | 携带发送的数据(仅 POST/PUT 有) | 表单数据、JSON 等 |
常用请求方法(Method):
GET:获取资源
POST:提交数据
PUT:更新资源。
DELETE:删除资源。
③ 响应报文(Response)
服务器收到请求后,会回送一个响应报文:
| 组成部分 | 说明 | 典型示例 |
|---|---|---|
| 状态行 | 包含状态码和状态信息 | HTTP/1.1 200 OK |
| 响应头 | 描述服务器和资源的属性 | Content-Type: text/html Content-Length: 1024 |
| 响应体 | 真正的数据内容 | HTML、图片二进制流、JSON等 |
④ HTTPS
HTTP 的安全版本,它通过在 HTTP 和 TCP 之间加入 SSL/TLS 加密层,解决了 HTTP 明文传输带来的数据裸奔风险。

5.2 官方示例代码位置

5.2 代码实现
小智后台请求地址:
https://api.tenclass.net/xiaozhi/ota/dri_http.h
#ifndef __DRI_HTTP_H__
#define __DRI_HTTP_H__
#include <string.h>
#include <sys/param.h>
#include <stdlib.h>
#include <ctype.h>
#include "esp_log.h"
#include "nvs_flash.h"
#include "esp_event.h"
#include "esp_netif.h"
#include "esp_tls.h"
#include "esp_crt_bundle.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h"
#include "esp_http_client.h"
#include "esp_app_desc.h"
#include "com_debug.h"
#include "dri_mutable_buffer.h"
#include "dri_esp32s3.h"
#include "cJSON.h"
/**
* @brief 发送HTTP请求获取激活码
*
*/
void dri_http_request_active_code(void);
#endif /* __DRI_HTTP_H__ */dri_http.c
#include "dri_http.h"
static const char *TAG = "HTTP_CLIENT: ";
// 静态函数:HTTP的事件处理函数
esp_err_t static _http_event_handler(esp_http_client_event_t *evt)
{
switch (evt->event_id)
{
case HTTP_EVENT_ERROR:
ESP_LOGD(TAG, "HTTP 请求失败");
break;
case HTTP_EVENT_ON_CONNECTED:
ESP_LOGD(TAG, "HTTP 连接成功");
break;
case HTTP_EVENT_HEADER_SENT:
ESP_LOGD(TAG, "HTTP 请求头已发送");
break;
case HTTP_EVENT_ON_HEADER:
ESP_LOGD(TAG, "HTTP 接收到响应头, key=%s, value=%s", evt->header_key, evt->header_value);
break;
case HTTP_EVENT_ON_DATA:
ESP_LOGD(TAG, "HTTP 接收到响应数据, len=%d", evt->data_len);
// 将已接收的数据添加user_data指向的可变缓冲区中
dri_mutable_buffer_add_data((mutable_buffer_t *)evt->user_data, evt->data, evt->data_len);
break;
case HTTP_EVENT_ON_FINISH:
ESP_LOGD(TAG, "HTTP 响应完成!");
// 从可变缓冲区中获取响应内容并打印
char *response_data = dri_mutable_buffer_get_data((mutable_buffer_t *)evt->user_data);
MY_LOGI("响应内容:%s", response_data);
break;
case HTTP_EVENT_DISCONNECTED:
ESP_LOGI(TAG, "HTTP 连接断开!");
break;
case HTTP_EVENT_REDIRECT:
ESP_LOGD(TAG, "HTTP 发现重定向!");
break;
}
return ESP_OK;
}
// 静态函数:得到请求体的JSON字符串
static char *dri_http_get_body_data(void)
{
// 创建根对象
cJSON *root = cJSON_CreateObject();
// 创建application部分
cJSON *application = cJSON_CreateObject();
cJSON_AddStringToObject(application, "version", "0.0.1");
const esp_app_desc_t *app_desc = esp_app_get_description();
cJSON_AddStringToObject(application, "elf_sha256", (char *)app_desc->app_elf_sha256);
// 创建borad部分
cJSON *board = cJSON_CreateObject();
cJSON_AddStringToObject(board, "type", "ESP32");
cJSON_AddStringToObject(board, "name", "ESP32S3");
cJSON_AddStringToObject(board, "ssid", "handongshengwei");
cJSON_AddStringToObject(board, "rssi", "-50");
// 将application和board添加到根对象
cJSON_AddItemToObject(root, "application", application);
cJSON_AddItemToObject(root, "board", board);
// 将根对象转换为字符串,将字符串创建在堆里,返回的指针
char *json_str = cJSON_PrintUnformatted(root);
// 释放根对象内存
cJSON_Delete(root);
// 返回JSON字符串指针
return json_str;
}
/**
* @brief 发送HTTP请求获取激活码
*
*/
void dri_http_request_active_code(void)
{
// 1. 创建可变缓冲区,用于存放http响应内容
mutable_buffer_t *local_response_buffer = dri_mutable_buffer_create();
// 2. http配置
esp_http_client_config_t config = {
.url = "https://api.tenclass.net/xiaozhi/ota/", // 小智服务器地址
.event_handler = _http_event_handler, // 事件处理函数,用于处理http事件
.user_data = local_response_buffer, // 存放相应内容的可变缓冲区
.disable_auto_redirect = true, // 禁用重定向
.method = HTTP_METHOD_POST, // POST方法
.crt_bundle_attach = esp_crt_bundle_attach, // HTTPS证书
};
// 3. 初始化http客户端
esp_http_client_handle_t client = esp_http_client_init(&config);
// 4. 设置http请求头
// 4.1 设置 Device-Id (使用Mac地址)
uint8_t mac_str[18];
dri_esp32s3_get_mac(mac_str);
esp_http_client_set_header(client, "Device-Id", (const char *)mac_str);
// 4.2 设置 Client-Id (使用UUID)
uint8_t uuid_str[37];
dri_esp32s3_get_uuid(uuid_str);
esp_http_client_set_header(client, "Client-Id", (const char *)uuid_str);
// 4.3 设置 User-Agent(客户端的名字和版本号)
esp_http_client_set_header(client, "User-Agent", "ESP32S3/1.0");
// 4.4 设置 Accept-Language(客户端的语言环境)
esp_http_client_set_header(client, "Accept-Language", "zh-CN");
// 5. 设置http请求体
char *post_data = dri_http_get_body_data();
esp_http_client_set_post_field(client, post_data, strlen(post_data));
// 6. 执行http请求
esp_err_t err = esp_http_client_perform(client);
if (err == ESP_OK)
{
ESP_LOGI(TAG, "HTTP POST Status = %d, content_length = %" PRId64,
esp_http_client_get_status_code(client),
esp_http_client_get_content_length(client));
}
else
{
ESP_LOGE(TAG, "HTTP POST request failed: %s", esp_err_to_name(err));
}
// 7. 释放资源
free(post_data);
dri_mutable_buffer_free(local_response_buffer);
}6. 测试
6.1 代码
main.c
#include <stdio.h>
#include "esp_task.h"
#include "com_debug.h"
#include "dri_wifi.h"
#include "int_button.h"
#include "dri_http.h"
// 重定义wifi联网成功后的弱函数
void dri_wifi_connected_cb(void)
{
MY_LOGI("WIFI联网成功!....");
}
// 重定义按键SW2长按事件触发后的弱函数
void int_button_sw2_long_press(void)
{
MY_LOGI("按键SW2长按事件触发!....");
// 重新配网
dri_wifi_reset_provisioning();
}
void app_main(void)
{
MY_LOGI("WIFI联网测试:");
// 初始化WIFI
dri_wifi_init();
// 初始化按键SW2
int_button_sw2_init();
// 发送HTTP请求获取激活码
dri_http_request_active_code();
// // 获取ESP32S3的MAC地址
// char mac_str[18];
// dri_esp32s3_get_mac((uint8_t *)mac_str);
// MY_LOGI("ESP32S3的MAC地址: %s", mac_str);
// // 获取ESP32S3的UUID
// char uuid_str[37];
// dri_esp32s3_get_uuid((uint8_t *)uuid_str);
// MY_LOGI("ESP32S3的UUID: %s", uuid_str);
while (1)
{
vTaskDelay(10);
}
}6.2 测试结果

