esp8266调用心知天气

最近在用esp8266获取天气预报时,遇到了许多问题,经过了一下午的搜罗,总结出以下经验供各位网友学习。

本文只需通晓8266连接wifi,创建tcp连接即可。

我使用的是心知天气的api,百度搜索即可,可以申请免费试用付费版也可以使用免费版,这里以免费版为例。

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

当你注册好心知天气的账号并开通免费版或者申请试用后或获得一个密钥,将连接中的加粗字体key替换为你的密钥即可。

PS:

链接中加粗字体beijing为地区名,想换成哪里就是哪里的拼音。

链接中加粗字体zh-Hans为语言,如果想代码简单化就改成en,英文方式显示,中文处理过于复杂,本文即为在英语环境下处理

首先我们来看下本文程序思想:

1.连接WIFI

2.DNS解析域名获得IP

3.创建TCP连接

4.GET获得源代码

5.数据处理

1.连接WIFI

本步骤过于简单,不再赘述。

2.DNS解析域名获得IP

8266官方库中给出了espconn_gethostbyname()这样的一个函数,可以解析域名获得IP,但本人觉得放在8266中运行无疑是增加了负担,这一步完全可以通过PC端完成,本文便以最简便方式说明。

步骤:win+r键→输入cmd→输入ping api.seniverse.com并回车

文中红框便为心知天气IP地址,此处注意域名前面千万不要加http://或https://

3.创建TCP连接

本步骤过于简单,不再赘述。

但要提一下的是创建TCP连接时,IP为上面取到的IP,端口则为80。

4.GET获得源代码

如想获取源代码,便需要以下知识。

客户端发送一个HTTP请求到服务器的请求消息包括以下格式:

请求行(request line)、请求头部(header)、空行和请求数据四个部分组成,下图给出了请求报文的一般格式。

而我们这次用的方法是GET,URL是:/v3/weather/now.json?key=Key&location=beijing&language=zh-Hans&unit=c,Key注意替换,协议版本是HTTP/1.1,HOST是api.seniverse.com,剩下的我们并不需要,再加上请求报文一般格式上的符号,代码如下:

//要获取网站的网址
#define HOST "api.seniverse.com"


/*二下两个请求头都是可以使用,第二个请求头使用了最少的报文头
 *请求头由几个部分组成:<请求方法> <请求URL> <请求协议版本>\r\n<报文头>\r\n\r\n
 */
#define HEAD "GET /v3/weather/now.json?key=Key&location=shijiazhuang&language=en&unit=c HTTP/1.1\r\nHost: %s\r\n\r\n"

然后在TCP连接成功回调函数中,发送此字符串,以数组形式保存。

此时服务器会返回我们json格式的数据,在TCP接收到数据回调函数内执行之后的代码:

5.数据处理

我们收到的数据会是这样的:

{"results":[{"location":{"id":"WWC2MYYCM6J5","name":"Shijiazhuang","country":"CN","path":"Shijiazhuang,Shijiazhuang,Hebei,China","timezone":"Asia/Shanghai","timezone_offset":"+08:00"},"now":{"text":"Cloudy","code":"4","temperature":"26"},"last_update":"2019-05-15T19:45:00+08:00"}]}

u8 Buffer[]={0};
void ICACHE_FLASH_ATTR user_tcp_recv_cb(void *arg,
		char *pdata,
		unsigned short len)
{
	
        os_printf("收到数据:%s\r\n",pdata);//将收到的json格式数据串口输出
	char *p=strstr(pdata,"code");//查找code首次出现的地址并赋值给指针p
	p+=7;//p+7跳转到code的数据 code为天气数据
	os_printf("收到:%s\r\n",p);//将code的数据及之后的json格式数据串口输出
	strncpy(Buffer,p,1);//将code的数据放到Buffer里
	os_printf("收到:%s\r\n",Buffer);//将Buffer数据打印
	p+=18;//跳转到temperature的数据 temperature为温度数据
	strncpy(Buffer+2,p,2);//存放到Buffer+2里
        ChooseWeather();//判断天气代码
}

这里每个数据都用两个位置存放,因为不管天气代码还是温度都有两位数的。

天气代码格式参见:https://docs.seniverse.com/api/start/code.html

当我们将两个数据都放到Buffer数组后,就可以进行条件选择了。

因为数组是无符号char型的并非整数并且是放在两个地方存储的,我们无法直接进行if判断,所以要先进行转换。

这里博主通过aoti函数进行转换发现程序会跑飞,无奈只能自己通过ASCII字符码表转换了,ASCII字符码表48——57对应0~9。

代码如下:

void ChooseWeather()
{
	int a,b;
	a=Buffer[0]-48;
	b=Buffer[1]-48;
	if(b<0)//如果b不存在 即天气代码为个位数
	{
		if(a==0||a==1)//晴天
		{
			OLED_ShowSChar(16,16,2,5,Sunny);
			os_printf("That is ok\r\n");
		}
		//多云
		else if(a==4||a==5||a==6||a==7||a==8)
		{
			OLED_ShowSChar(16,16,2,5,Cloudy);
			os_printf("That is ok\r\n");
		}
		else if(a==9)//阴天
		{
			OLED_ShowSChar(16,16,2,5,weather+32);
		}
	}
	else
	{
		//雨
		if(a==1&&(b==1||b==2||b==3||b==4||b==5||b==6||b==7||b==8||b==9))
		{
			OLED_ShowSChar(16,16,2,5,Rain);
		}
		//雨夹雪
		else if(a==2&&b==0)
		{
			OLED_ShowSChar(16,16,2,5,RainSnow);
		}
		//雪
		else if(a==2&&(b==1||b==2||b==3||b==4||b==5))
		{
			OLED_ShowSChar(16,16,2,5,Snow);
		}
		//雾霾
		else if(a==3&&b==0)
		{
			OLED_ShowSChar(16,16,2,5,Smog);
		}
	}

}

至于温度以及时间这里不再一一赘述,逻辑都是一样的,自己参考便可独立完成,勿做伸手党!

发布了3 篇原创文章 · 获赞 9 · 访问量 1516

猜你喜欢

转载自blog.csdn.net/weixin_44220583/article/details/90243917