ESP8266_15天气预报之TCP的GET操作

ESP8266_01搭建开发环境

ESP8266_02程序的编译与下载

ESP8266_03SDK与Makefile的基本用法

ESP8266_04管脚控制与软件定时器

ESP8266_05 ESP8266有几个串口?

ESP8266_06硬件定时器与IO中断

ESP8266_07基于PWM的呼吸灯

ESP8266_08基于flash的数据掉电保护

ESP8266_09基于IIC控制的OLED屏幕

ESP8266_10 ESP8266的STATION模式

ESP8266_11 ESP8266的UDP广播

ESP8266_12 ESP8266客户端模式下的TCP通信

ESP8266_13服务器端模式下的TCP通信

ESP8266_14 SOFTAP模式下的服务器端和客户端

ESP8266_15天气预报之TCP的GET操作

ESP8266_16天气预报之JSON数据的生成与解析

ESP8266_17简单网络时间协议-SNTP

ESP8266_18 MQTT协议接入ONENET平台

ESP8266_19MQTT协议接入ONENET平台_订阅主题

ESP8266_20 基于ONENET平台的数据上传之TCP的POST操作

ESP8266_21基于ESP8266的一键配网

ESP8266_22基于自身ADC的电压采样

ESP8266_23基于硬件定时器的红外遥控器解码

前面几节,TCP的基本操作聊了一些。接下来这几节,聊一聊HTTP协议下的GET操作。首先明确几个基本概念:

HTTP(HyperText Transfer Protocol,超文本传输协议)是一套计算机通过网络进行通信的规则,使HTTP客户端能够从HTTP服务器端请求到信息和服务,目前的版本号是1.1。

HTTP通讯机制是在一次完整的HTTP通讯过程中,客户端和服务器之间建立连接分为以下几个步骤。

1、建立连接: 其中包括:域名解析,TCP三次握手。

2、发送数据

3、返回数据

4、关闭连接

咱们这一节主要研究的是其中的前二个步骤:建立连接和发送数据。即域名如何解析,数据该以什么样的格式发送。

如何演示?天气预报?

是的,天气预报。这个东西虽然有点俗,但用来讲解,效果还是挺好的。

首先,去心知天气(自行百度,非广告)注册一个账户,然后购买一个免费版的产品。这时,你就能通过API查看全国任意城市的天气了。

使用方式,将 API 密钥中的“私钥”作为 API 请求中的 key 参数值: 

https://api.seniverse.com/v3/weather/now.json?key=your_private_key&location=beijing&language=zh-Hans&unit=c

把连接中的加黑字体换成你的私钥,然后粘贴到浏览器,效果如下:

 

 

看不清图片的,看下面文字:

{"results":[{"location":{"id":"WX4FBXXFKE4F","name":"北京","country":"CN","path":"北京,北京,中国","timezone":"Asia/Shanghai","timezone_offset":"+08:00"},"now":{"text":"多云","code":"4","temperature":"27"},"last_update":"2019-09-17T14:25:00+08:00"}]}

想看其它城市的天气,更换连接中的文字:beijing为你想要的城市即可。

 

先说域名解析,为什么要解析?

研究这个之前,先思考一个问题,我们上网的时候,究竟是怎么上的。以百度为例,我们输入的网址是:www.baidu.com或者http://www.baidu.com,再或者https://www.baidu.com。

严格来说,URL应该符合以下形式:

<协议>://<主机>:<端口>/<路径>?<参数>&<参数>

协议常用的有http、https或者ftp;“://”不能省略;主机就是“www”开头的网址,端口没有写的话,默认80;斜杠后面跟的是路径等等。对照这个格式,百度的网址可以写成这样:

http://www.baidu.com:80/index.html

所以,做域名解析的时候,要考虑这几方面的因素:协议、主机、端口、路径,也就是说你要把这几样因素都找到。域名解析的函数网上有很多公开的代码,我这里贴一个,仅供参考:

void ICACHE_FLASH_ATTR http_parse_request_url(char *URL,char *host,char *filename,unsigned short *port)
{
	char *PA;
	char *PB;
	memset(host,0,sizeof(host));
	memset(filename,0,sizeof(filename));
	*port=0;
	if(!(*URL)) return;
	PA=URL;
	if(!strncmp(PA,"http://",strlen("http://")))
		PA=URL+strlen("http://");
	if(!strncmp(PA,"https://",strlen("https://")))
		PA=URL+strlen("https://");
	PB=strchr(PA,'/');
	if(PB){
		memcpy(host,PA,strlen(PA)-strlen(PB));
		if(PB+1){
			memcpy(filename,PB+1,strlen(PB-1));
			filename[strlen(PB)-1]=0;
		}
		host[strlen(PA)-strlen(PB)]=0;
	}else{
		memcpy(host,PA,strlen(PA));
		host[strlen(PA)]=0;
	}
	PA=strchr(host,':');
	if(PA)
		*port=atoi(PA+1);
	else
		*port=80;
}

所以,解析完成之后,得到主机和路径,按照相应格式,组成数据包,发送给服务器,服务器就能返回相应的数据。

 

那么,ESP8266怎么发送?直接通过espconn_sent函数把数据发出去?那是肯定不行滴。需要一个特定的格式。HTTP请求数据格式如下:

当浏览器发送请求时,它要向服务器发送一个数据块,也就是请求信息,其中信息由三部分组成。

1. 请求方法 URI协议/版本

2. 请求头(Request Header)

3. 请求正文

示范代码如下:

GET/sample.jspHTTP/1.1

Accept:image/gif.image/jpeg,*/*

Accept-Language:zh-cn

Connection:Keep-Alive

Host:localhost

User-Agent:Mozila/4.0(compatible;MSIE5.01;Window NT5.0)

Accept-Encoding:gzip,deflate

再比如,当我使用浏览器访问网址的时候,通过抓包工具,可以看到如下信息:

 

这些内容,有些是可以不要的。所以最终整理一下,以访问心知天气的API为例,实际的内容格式如下:

GET v3/weather/now.json?key=your_private_key&location=beijing&language=zh-Hans&unit=c HTTP/1.1

Accept: */*

Host: api.seniverse.com

Connection: Keep-Alive

GET后面跟的是前面那个API网址中,api.seniverse.com后面的那一串字符,然后是“HTTP/1.1”。由于格式原因,没有显示在同一行,实际应用的时候放在同一行即可。

实际应用中,每次输入不同的API链接,我们不可能手动把前面的host和后面的字符串拆分开,所以需要上面的解析函数,用来判断哪部分是host,哪部分是字符串。

程序修改完成,保存、清理、编译、下载一条龙,然后重新上电。这里借助串口助手来查看效果。效果如下所示:

 

从receive data开始,都是收到的信息。我这里查看了廊坊的天气,显示晴天,28度,还可以~

但是目前这个数据只能通过串口打印出来,而且还有一定的格式,需要对格式进行解析,这部分下一节再说。

链接:

https://pan.baidu.com/s/1SkngvsrzbOJ2R-YWwbZrFQ

提取码:rco4

发布了27 篇原创文章 · 获赞 7 · 访问量 5194

猜你喜欢

转载自blog.csdn.net/lazyduck/article/details/100933552