本帖最后由 51xlf 于 2022-7-20 12:42 编辑
#申请原创# @21小跑堂
准备使用ESP8266和CH32V307实现网络授时和天气的获取。
这里使用的是ESP8266-12f的芯片,需要烧录AT固件,这个固件可以在https://docs.ai-thinker.com/%E5%9B%BA%E4%BB%B6%E6%B1%87%E6%80%BB这个链接下载。
用的烧写工具是 flash_download_tools_v3.6.6,烧写的AT固件为安信可发布的v1.7.1.0 AT Firmware。
使用ESP8266 通过AT指令实现与网络进行数据交互,使用的是HTTP GET协议。
在测试数据之前,首先要注册获取天气的一些地址,我在这里使用的是心知天气,提供了很棒的API。
我使用是免费的版本,不限量,确实可以,服务器的数据速度也可以。
注册成功以后,可以查看这个API的指令。因为我使用的是免费的账号,免费用户只返回天气现象文字、代码和气温 3 项数据。
这里的your_api_key就是注册账号上的秘钥,自己根据实际情况填写即可。
首先需要通过串口调试助手测试AT指令。
发送下面的复位ESP8266,下面的所有的指令都是省略了回车的发送,测试的时候,需要自己补全。
配置ESP8266位AP+STA的模式
连接路由器实现与网络的数据通信
AT+CWJAP="xxxx_5G","1234xxxxxx"
建立esp8266与服务器的TCP连接
AT+CIPSTART="TCP","api.seniverse.com",80
配置ESP8266为透传模式以及发送数据指令
使用GET的方式获取天气数据,我这里是获取的济南的天气当,你也可以根据i生成数组获取当前的数据。
GET /v3/weather/now.json?key=<span style="color: rgb(0, 0, 0); font-size: medium; background-color: rgb(255, 255, 255);">your_api_key</span>&location=jinan&language=en&unit=c HTTP/1.1
Content-Type:application/json;charset=utf-8
Host:api.seniverse.com
Connection: Keep Alive
返回是数据如下所示。这个是json的格式。
Date可以提前时间数据,json里面可以获取温度和天气数据。
HTTP/1.1 200 OK
Date: Wed, 20 Jul 2022 04:17:13 GMT
Content-Type: application/json; charset=utf-8
Content-Length: 269
Connection: keep-alive
access-control-allow-origin: *
etag: W/"1 "
x-powered-by: Express
x-ratelimit-limit: 20;w=60
x-ratelimit-remaining: 19
x-ratelimit-reset: 60.000
x-request-id: xxx
x-tenant-id: 75
{"results":[{"location":{"id":"WWE0TGW4PX6N","name":"Jinan","country":"CN","path":"Jinan,Jinan,Shandong,China","timezone":"Asia/Shanghai","timezone_offset":"+08:00"},"now":{"text":"Light rain","code":"13","temperature":"23"},"last_update":"2022-07-20T12:02:10+08:00"}]}
"code":"13"为天气代码,在https://docs.seniverse.com/api/start/code.html可以看到每一个代码代表的天气含义,也可以获取图片。
串口中的数据。
开始代码的编写。
串口的代码编写的方法与esp8266的功能,可以查看https://bbs.21ic.com/icview-3239654-1-1.html这里。
这里主要是看如何实现esp8266 get 天气数据。
下面的代码就是实现ESP8266的初始化,连接wifi,建立与服务器的连接。
void cfg_Esp8266(void)
{
if(ESP8266_Init())
{
printf("ESP8266 init succ \r\n");
}
else printf("ESP8266 init fail!\r\n");
//连接热点
if(ESP8266_ConnectAP(WIFI_NAME,WIFI_PASSWD))
{
printf("Connected to WIFI!\r\n");
}
else printf("to WIFI fail\r\n");
Delay_Us(1000);
if(ESP8266_ConnectServer("TCP","api.seniverse.com",80)!=0)
{
printf("to Server succ!\r\n");
}
else printf("to Server Fail!\r\n");
}
api.seniverse.com 为实际应用的服务器地址,如果地址后面没有端口号,就是默认的80端口。
使用ESP8266的AT指令实现GET 方法。
ESP8266_ATSendString((char*)"GET /v3/weather/now.json?key=XXXXX&location=jinan&language=en&unit=c HTTP/1.1\r\nContent-Type:application/json;charset=utf-8\r\nHost:api.seniverse.com\r\nConnection: Keep Alive\r\n\r\n");
ESP8266_ATSendString的实现方法
//向ESP8266发送字符串
void ESP8266_ATSendString(char* str)
{
memset(usart2_rxbuf,0, 1024);
//每次发送前将接收串口接收总数置0,为了接收
USART2_RX_STA = 0;
while(*str) {
USART_SendData(USART2, *str);
while(USART_GetFlagStatus(USART2, USART_FLAG_TC) == RESET);
str++;
}
}
然后就会获取了网络返回的数据了
下面要解析获取的数据。
在获取的数据中有这样的数据,包含了时间信息。这里使用的是sscanf来分解时间数据。
Date: Wed, 20 Jul 2022 04:25:20 GMT
这个是解析的方法,将数据对应放到相应的变了里面。
char *pos=strstr(usart2_rxbuf,"Date");
if(*pos)
{
memset(data_c,0,sizeof(data_c));
while(*pos!='\r' && ch_len<128)
{
data_c[ch_len]= *pos;
ch_len++;
pos++;
}
//printf("Date:%s \r\n", data_c);
sscanf(data_c,"Date: %[^,], %d %s %d %d:%d:%d GMT",
s1,&day1,s3,&year1,&hour1,&min,&sec);//分解时间 给年月日时分秒赋值
}
这里获取的是utc时间,需要+8小时,才能获取北京时间。
然后对RTC模块进行赋值了。
RTC_Set(year,month,day,hour,min,sec);
在系统内部实现,每秒读取一次数据,把数据显示在LCD上。
if(get_tDiff(last_time1)>1000){//每秒执行一次
last_time1=timer_cnt;
sprintf(s_temp,"%02d:%02d ",calendar.hour, calendar.min);
LCD_ShowStringCn(0,0,s_temp,GREEN,BLACK,32,0);
sprintf(s_temp,"%02d ", calendar.sec);
LCD_ShowStringCn(84,8,s_temp,WHITE,BLACK,24,0);
sprintf(s_temp,"%d-%02d-%02d ", calendar.w_year, calendar.w_month, calendar.w_date);
LCD_ShowStringCn(0,32,s_temp,GREEN,BLACK,24,0);
}
然后解析温度和天气数据。
{"results":[{"location":{"id":"WWE0TGW4PX6N","name":"Jinan","country":"CN","path":"Jinan,Jinan,Shandong,China","timezone":"Asia/Shanghai","timezone_offset":"+08:00"},"now":{"text":"Moderate rain","code":"14","temperature":"23"},"last_update":"2022-07-20T12:12:15+08:00"}]}
这个json格式,没有详细的进行分解,只是获取code里面的数据,使用strstr就可以实现。
定位到前面的标志以后,查找后面固定的位数数据即可。
pos=strstr(usart2_rxbuf,"code");//查找code的数据
if(*pos)
{
if(*(pos+8)>='0' && *(pos+8)<='9')
weather_code= (*(pos+7)-'0')*10+*(pos+8)-'0';
else weather_code= (*(pos+7)-'0');}
if(weather_code>40)weather_code=39;
pos=strstr(usart2_rxbuf,"temperature");//查找temperature
if(*pos)
{if(*(pos+15)>='0' && *(pos+15)<='9')
temper= (*(pos+14)-'0')*10+*(pos+15)-'0';
else temper= (*(pos+14)-'0');
}
获取了天气代码以后,将代码转换为天气描述,我做了一个简单的数组,根据code获取即可。
char weather_CNdis[40][16]={"晴","晴","晴","晴","多云","晴间多云","晴间多云","大部多云",
"大部多云","阴","阵雨","雷阵雨","雷阵雨","小雨","中雨","大雨","暴雨","大暴雨","特大暴雨",
"冻雨","雨夹雪","阵雪","小雪","中雪","大雪","暴雪","浮尘","扬沙","沙尘暴","强沙尘暴","雾",
"霾","风","大风","飓风","热带风暴","龙卷风","冷","热","未知"};
并把天气和温湿度显示在屏幕上。
sprintf(s_temp,"天气:%s ",weather_CNdis[weather_code]);
LCD_ShowStringCn(0,64,s_temp,BLUE,BLACK,32,0);
sprintf(s_temp,"温度:%d ℃ ",temper);
到这里就实现了整个的设计过程。看看效果。
没有获取时间的图片
更新了时间的图片
获取时间和天气的图片
code.rar
(7.29 KB)
|
此文章已获得独家原创/原创奖标签,著作权归21ic所有,未经允许禁止转载。
打赏榜单
21小跑堂 打赏了 40.00 元 2022-07-21 理由:恭喜通过原创文章审核!请多多加油哦!
共1人点赞
|
巧用API,获取实时网络时间和天气,实现简单的桌面天气时钟。