ESP8266 HTTP实现天气信息实时获取以及JSON解析天气数据

您所在的位置:网站首页 中国气象无法更新 ESP8266 HTTP实现天气信息实时获取以及JSON解析天气数据

ESP8266 HTTP实现天气信息实时获取以及JSON解析天气数据

2024-07-16 23:26| 来源: 网络整理| 查看: 265

本博文实现了HTTP 每隔20秒请求一次心知天气的天气数据,并且在OLED上显示天气信息,HTTP天气信息使用cJSON进行解析。

本博文Demo所有代码下载地址:https://download.csdn.net/download/zq666888/13125206

效果图如下:

我这里使用的天气API接口是心知天气的,如果学习用的话可以申请免费版的做测试用,详情见:https://www.seniverse.com/login?callback=%2Fproducts%3Fiid%3Dnew

要想实现获取天气信息我们需要经过以下步骤:

1、设置ESP8266工作模式,连接wifi。

/****************************************************************************** * FunctionName : user_init * Description : entry of user application, init user function here * Parameters : none * Returns : none *******************************************************************************/ void ICACHE_FLASH_ATTR user_init(void) { uart_init(115200,115200); // 初始化串口波特率 os_delay_us(10000); // 等待串口稳定 os_printf("SDK version:%s\n", system_get_sdk_version()); OLED_Init();// OLED初始化 PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO4_U,FUNC_GPIO4); PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO5_U,FUNC_GPIO5); GPIO_OUTPUT_SET(GPIO_ID_PIN(4),1); //绿灯默认灭 GPIO_OUTPUT_SET(GPIO_ID_PIN(5),0); //红灯默认灭 OLED_ShowString(0,0,"ESP8266 HTTP"); // ESP8266 wifi_set_opmode(0x01);//设置wifi为Station模式 os_memcpy(MyStation.ssid,"Leagend_K2P",strlen("Leagend_K2P"));//要连接的wifi名字 os_memcpy(MyStation.password,"www.leagend.com",strlen("www.leagend.com"));//要连接的wifi密码 wifi_station_set_config(&MyStation);//初始化Station参数 wifi_station_connect();//连接wifi os_timer_disarm(&CheckWifiState);//取消定时器 os_timer_setfn(&CheckWifiState,(os_timer_func_t *)CheckWifiFunction,NULL); os_timer_arm(&CheckWifiState,500,1); }

2、解析URL,进行DNS解析。

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; } http_parse_request_url(ServiceURL,Host,Filename,&Port);//解析URL os_printf("Host:%s\r\nFilename:%s\r\nPort:%d\r\n",Host,Filename,Port); os_sprintf(buffer,GET,Filename,Host); espconn_gethostbyname(&MyEspconn,Host,&addr,DNSFoundCb);//DNS功能

3、根据DNS解析到的IP和端口,在DNS解析回调函数中进行Station相关初始化并进行TCP连接

void ICACHE_FLASH_ATTR MyStationInit(struct ip_addr *RemoteIP,struct ip_addr *LocalIP,int RemotePort) { MyEspconn.type = ESPCONN_TCP;//连接类型 MyEspconn.proto.tcp = (esp_tcp *)os_zalloc(sizeof(esp_tcp));//开辟TCP空间 os_memcpy(MyEspconn.proto.tcp->remote_ip,RemoteIP,4); os_memcpy(MyEspconn.proto.tcp->local_ip,LocalIP,4); MyEspconn.proto.tcp->remote_port = RemotePort; MyEspconn.proto.tcp->local_port = espconn_port();//获取 ESP8266可用的端口 //和连接失败的回调函数 espconn_regist_connectcb(&MyEspconn,TcpConnectCb);//注册连接成功的回调函数 espconn_regist_reconcb(&MyEspconn,TcpReconCb);//注册 TCP 连接发生异常断开时的回调函数 espconn_connect(&MyEspconn); } void DNSFoundCb(const char *name, ip_addr_t *ipaddr, void *callback_arg) { struct ip_info MyIPInfo; os_printf("DNS Found\r\n"); wifi_get_ip_info(STATION_IF,&MyIPInfo);//查询 Wi-Fi Station 接口或者 SoftAP 接口的IP地址 MyStationInit(ipaddr,&MyIPInfo.ip,Port); }

4、在TCP连接成功回调函数中发送GET请求天气数据

void TcpConnectCb(void *arg) { os_printf("Tcp Connect OK!\r\n"); espconn_regist_recvcb(&MyEspconn,TCPRecvCb); espconn_regist_sentcb(&MyEspconn,TCPSendCb); espconn_regist_disconcb(&MyEspconn,TCPDisconCb); os_printf("buffer:%s\r\n",buffer); espconn_send(&MyEspconn,buffer,strlen(buffer)); }

5、从TCP服务器返回的数据中进行JSON解析,获取城市、温度、湿度等天气信息

void TCPRecvCb(void *arg, char *pdata, unsigned short len) { os_printf("Receive Data:%s\r\n",pdata); cJSON *Result = 0; cJSON *now = 0; cJSON *Temper = 0; cJSON *Humidi = 0; cJSON *Name = 0; cJSON *Location = 0; cJSON *Array = 0; char *Body = strstr(pdata,"{\""); if(Body) { OLED_Clear(); os_printf("Find JSON Body!\r\n"); cJSON *DataRoot = cJSON_Parse((const char *)Body); if(DataRoot) { os_printf("JSON Parse OK!\r\n"); Result = cJSON_GetObjectItem(DataRoot,"results"); if(Result) { os_printf("Parse results OK!\r\n"); Array = cJSON_GetArrayItem(Result,0);//找到数组的第0个元素 if(Array) { Location = cJSON_GetObjectItem(Array,"location"); if(Location) { Name = cJSON_GetObjectItem(Location,"name"); if(Name) { char *str = Name->valuestring; os_printf("name:%s\r\n",str); OLED_ShowString(0,0,str); } } now = cJSON_GetObjectItem(Array,"now"); if(now) { Temper = cJSON_GetObjectItem(now,"temperature"); if(Temper) { char *Tem = Temper->valuestring; os_printf("temperature:%s\r\n",Tem); OLED_ShowString(0,2,"Tem:"); OLED_ShowString(33,2,Tem); } Humidi = cJSON_GetObjectItem(now,"humidity"); if(Humidi) { char *Hum = Humidi->valuestring; os_printf("humidity:%s\r\n",Hum); OLED_ShowString(0,4,"Hum:"); OLED_ShowString(33,4,Hum); } } } } else { os_printf("Parse results error!\r\n"); } cJSON_Delete(DataRoot); } else { os_printf("JSON Parse Error!\r\n"); } } else { os_printf("Not Find JSON Body!\r\n"); } os_timer_disarm(&BreakTcp); os_timer_setfn(&BreakTcp,(os_timer_func_t *)BreakTcpFun,NULL); os_timer_arm(&BreakTcp,5000,0); }

6、设置一个定时器,处理完数据断开TCP连接,20秒后重新请求数据并解析。

void TCPDisconCb(void *arg) { os_printf("Tcp Break!\r\n"); os_timer_disarm(&ConnectTcp); os_timer_setfn(&ConnectTcp,(os_timer_func_t *)ConnectTcpFun,NULL); os_timer_arm(&ConnectTcp,20000,0); }

关于cJSON的具体用法请参考:https://zhuanlan.zhihu.com/p/53730181

 

 

 

 



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3