让你的ESP32显示一张公网图片吧
让你的ESP32显示一张公网图片吧
众所周知,ESP32它是能联网的,而配上屏幕,它就可以显示一张图片,那么它可以显示一张互联网上的图片吗?当然可以!
虽然之前已经做过了视频的传输,而视频不过是很多图片的集合,但是那篇文章中的传输都是建立在局域网之中,通信建立在Socket上。
而这次要突破局域网,使用HTTP协议来传输数据,所以会比之前复杂一些。
序
使用的网络请求库为AsyncTCP-esphome,所以将以下内容添加到你的platformio.ini中1
2
3lib_deps =
ottowinter/AsyncTCP-esphome@^1.1.1
ottowinter/ESPAsyncWebServer-esphome@^1.2.7
这里先介绍一下HTTP协议吧,引用百度百科的原文超文本传输协议(Hypertext Transfer Protocol,HTTP)是一个简单的请求-响应协议,它通常运行在TCP之上。它指定了客户端可能发送给服务器什么样的消息以及得到什么样的响应。
在这个通信过程中,客户端和服务端以报文的形式通信,客户端发送的报文叫做请求报文,服务端发送的报文叫做应答报文。
其中请求报文的格式结构如下请求行 - 通用信息头 - 请求头 - 实体头 - 报文主体
应答报文结构如下状态行 - 通用信息头 - 响应头 - 实体头 - 报文主体
知道报文格式后,解析报文,就能获取我们想要的内容。
下面通过一次演习来研究下报文有什么内容,然后再做后续开发。
演习
为了此次演习,我在阿里云OSS中上传了一张很小的JPG图片,借助阿里云OSS,这张图片就有了一个固定的公网地址,
https://chaosgoo-pic.oss-cn-shanghai.aliyuncs.com/response.jpg
下面打开Postman,把图片地址填进去,请求头参数保持默认,然后发送请求,直接查看Postman的控制台,点击Show raw log查看原始请求日志。
请求报文如下1
2
3
4
5
6
7GET /response.jpg HTTP/1.1
User-Agent: PostmanRuntime/7.26.10
Accept: */*
Postman-Token: 8f142c2a-1547-40df-a07e-637450e576c4
Host: chaosgoo-pic.oss-cn-shanghai.aliyuncs.com
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
请求报文的结构如图所示
请求报文中需要关注的内容有
内容 | 备注 |
---|---|
GET /response.jpg HTTP/1.1 | 请求行,由方法字段、URL字段和HTTP协议版本字段组成 |
… | … |
Host: chaosgoo-pic.oss-cn-shanghai.aliyuncs.com | 请求的主机名和端口号 |
… | … |
可以发现,表中内容就是由图片的链接构造出来的。
再看一眼应答报文,应答报文的结构如图所示
应答报文如下1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18HTTP/1.1 200 OK
Server: AliyunOSS
Date: Thu, 04 Mar 2021 08:52:28 GMT
Content-Type: image/jpeg
Content-Length: 2544
Connection: keep-alive
x-oss-request-id: 60409FCC0EF7D03534F4A1F5
Accept-Ranges: bytes
ETag: "C6C67E44834D62DC1FC9729C94E74CCB"
Last-Modified: Wed, 03 Mar 2021 18:04:44 GMT
x-oss-object-type: Normal
x-oss-hash-crc64ecma: 18170594484795111235
x-oss-storage-class: Standard
Content-Disposition: attachment
x-oss-force-download: true
Content-MD5: xsZ+RINNYtwfyXKclOdMyw==
x-oss-server-time: 27
#The console does not support viewing response bodies with media files.
有很多现在不需要关注的内容,只需要关心下表中的内容
内容 | 备注 |
---|---|
HTTP/1.1 200 OK | 状态行,由协议版本、状态码与原因短语组成 |
… | … |
Content-Type: image/jpeg | 实体的媒体类型 |
Content-Length: 2544 | 实体的长度,此处即为JPG图片的大小 |
… | … |
有了状态行,我们就可以知道此次请求是否成功;有了Content-Length,我们就知道目标图片的尺寸。
后续操作就是先解析报文,然后根据请求行判断请求是否成功,如果成功,就继续解析应答首部,获取图片的尺寸,如果不成功,那就慢慢Debug吧。
一切就绪后,那可以开始读取剩下的内容吧。
由于传输过程中可能无法一次性将实体传输过来,所以实体会被分割成很多小块发送,使用extractBodyChunkFromResponseRaw提取实体并返回提取到的长度。
前面client->onData([&] (void arg, AsyncClient c, void *data, size_t len)会被调用很多次。
在onData中的data就是每一数据帧去掉帧头和帧尾的部分,即为实体被分成的小块。
由于是通过TCP传输的,所以这个大小存在上限,采用Arduino方式开发ESP32的话,MSS的值会被设置成1436。很荣幸的能够观察到这个现象,感觉摸到MTU了
代码时间
请求部分代码
关于网络请求操作的代码,参阅ESP32异步网络请求,本文只关注应答报文处理函数
1 |
|
1 | [env:pico32] |