前言:
ESPIDF框架下ESP32 没有内置证书存储,因此开发者必须手动提供所需的证书,以便设备能够验证服务器的身份。
官方给的例子很丰富,比如https部分,但是代码量比较大,难以消化,对刚入手espidf比较不友好。
连接wifi就不多说了,这里直接一步到位,总结出最精炼步骤:
一、https结构体配置
虽然这里是esp_http_client_config_t, 但其实也包含了https
在需要证书的情况下,就这四个就够了。图中最后一步是初始化客户端。
其余参数具体什么含义这里不多讲了,这些都能简单搜到
里面的事件处理函数:
根据需要写你想写的就行,官方的例子写了很多事件。
token的获取这里不多叙述了,具体就是先通过访问url,获取到信息,解析出token。也要用到证书。有了证书是再多访问一次的事。
二、证书 获取
这里单独拿出来讲,个人认为是它是最不友好的一点。
什么是证书这里不多介绍了,都能搜到。
首先你的证书最好是完整的,什么是完整的?
服务器证书 + 中间件书 + 根证书
如何获取?
首先是服务器证书和中间证书:
比如我要拿esp32访问菜鸟教程,使用espidf框架编程,肯定要手动获取证书。我们先获取服务器证书和中间证书:
菜鸟网址:https://www.runoob.com/
我们打开powershell执行如下指令就行:
openssl s_client -connect www.runoob.com:443 -showcerts
为什么是443, https默认就是443端口
没有openssl, 自行搜索就行,教程很多。
接下来会看到:
这种长文本。第一个出现的长文本就是服务器证书,第二个是中间证书,一般不会出现第三个。
那我们的根证书呢?
根证书获取:
以chrome浏览器为例:
按如下点击:
记住框起来的名字。
现在win + R键, 输入certmgr.msc
然后按如下点击找到他:
鼠标右键他,并如下点击
然后点击下一步,
然后选择base64编码
这些你随便整,只要你找得到:
然后导出:
随后你发现它是这种长相:
太丑陋了,内容也不是我们想要的,我们暴改一下:
重命名后缀.txt
这样顺眼多了:
这样根证书就获取成功了。
证书拼接:
建一个文本文件,按服务器证书,中间证书,根证书顺序,拼接起来,像这样:
然后后缀改成.pem
三、证书嵌入
刚刚的文件粘贴进你的espidf main文件夹:
main目录下的cmakelists增加:
二进制文件嵌入声明:
按如下编写,表示在本文件夹下,要嵌入名字叫my_cert.pem的二进制文件到my_cert_pem变量。
在引用的时候,是填入my_cert_pem_start。
四、最后四部曲
构建消息 -> 消息转换为标准 JSON 字符串 -> 设置请求体 -> 发送
cJSON *messages = cJSON_CreateObject();
cJSON_AddStringToObject(messages, "消息的键", "要发送的消息");
char *payload = cJSON_PrintUnformatted(messages);
esp_http_client_set_post_field(client, payload, strlen(payload));
esp_http_client_perform(client);
函数用法示意就对应上述描述。
五、完整步骤
#include <string.h>
#include "esp_http_client.h"
#include "cJSON.h"
extern const char my_cert_pem_start[] asm("_binary_my_cert_pem_start");
extern const char my_cert_pem_end[] asm("_binary_my_cert_pem_end");
static esp_err_t connect_https_example_event_handler(esp_http_client_event_t *evt) {
if (evt->event_id == HTTP_EVENT_ON_DATA) {
// 就一个HTTP_EVENT_ON_DATA情况足以
// 然后开始你的操作
}
return ESP_OK;
}
esp_http_client_config_t config = {
.url = "你的url + token",
.method = HTTP_METHOD_POST, // 选择模式,根据你需要选择
.event_handler = connect_https_example_event_handler,
.cert_pem = my_cert_pem_start,
};
esp_http_client_handle_t client = esp_http_client_init(&config);
cJSON *messages = cJSON_CreateObject();
cJSON_AddStringToObject(messages, "消息的键", "要发送的消息");
char *payload = cJSON_PrintUnformatted(messages);
esp_http_client_set_post_field(client, payload, strlen(payload));
esp_http_client_perform(client);