ESP32基础应用之httpt获取网络天气并使用cJSON解析数据

Posted while(1)

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ESP32基础应用之httpt获取网络天气并使用cJSON解析数据相关的知识,希望对你有一定的参考价值。

1 建立工程

本实验是在ESP32基础应用之http实验基础之上修改的

1.1 http-get工程

  1. 使用http-get协议t获取网络天气;
  2. 复制 app-http-client 实验并修改工程名为 app-GetNetWeather
  3. http_test_task 任务函数中去掉其他测试项目,只留下 http_rest_with_url 函数;

1.2 获取心知天气的json数据

  1. 心知天气的url链接:该链接说明请参考心知天气官网说明书
https://api.seniverse.com/v3/weather/daily.json?key=rrpd2zmqkpwlsckt&location=shenzhen&language=en&unit=c&start=0&days=3
  1. 在 http_rest_with_url 函数填写心知天气的url链接,并打印json原始数据,如下:
static void http_rest_with_url(void)
{
    char local_response_buffer[MAX_HTTP_OUTPUT_BUFFER] = {0};  
    esp_http_client_config_t config = {
        .url = "https://api.seniverse.com/v3/weather/daily.json?key=rrpd2zmqkpwlsckt&location=shenzhen&language=en&unit=c&start=0&days=3",
        .event_handler = _http_event_handler,
        .user_data = local_response_buffer,        // Pass address of local buffer to get response
    };
    esp_http_client_handle_t client = esp_http_client_init(&config);

    // GET
    esp_err_t err = esp_http_client_perform(client);
    if (err == ESP_OK) {
        ESP_LOGI(TAG, "HTTP GET Status = %d, content_length = %d",
                esp_http_client_get_status_code(client),
                esp_http_client_get_content_length(client));
    } else {
        ESP_LOGE(TAG, "HTTP GET request failed: %s", esp_err_to_name(err));
    }
    //ESP_LOG_BUFFER_HEX(TAG, local_response_buffer, strlen(local_response_buffer));

	printf("local_response_buffer:%s ", local_response_buffer); /*打印心知天气json原始数据*/

	user_parse_json(local_response_buffer); /*解析心知天气json原始数据*/

    esp_http_client_cleanup(client);
}
  1. 编译并烧录程序后,打印出来的心知天气json原始数据如下:
{"results":[{"location":{"id":"WS10730EM8EV","name":"Shenzhen","country":"CN","path":"Shenzhen,Shenzhen,Guangdong,China","timezone":"Asia/Shanghai","timezone_offset":"+08:00"},"daily":[{"date":"2021-05-05","text_day":"Cloudy","code_day":"4","text_night":"Cloudy","code_night":"4","high":"30","low":"23","rainfall":"0.3","precip":"","wind_direction":"CLM","wind_direction_degree":"","wind_speed":"3.0","wind_scale":"1","humidity":"73"},{"date":"2021-05-06","text_day":"Cloudy","code_day":"4","text_night":"Cloudy","code_night":"4","high":"30","low":"22","rainfall":"0.0","precip":"","wind_direction":"CLM","wind_direction_degree":"","wind_speed":"3.0","wind_scale":"1","humidity":"72"},{"date":"2021-05-07","text_day":"Cloudy","code_day":"4","text_night":"Cloudy","code_night":"4","high":"32","low":"23","rainfall":"0.0","precip":"","wind_direction":"CLM","wind_direction_degree":"","wind_speed":"3.0","wind_scale":"1","humidity":"73"}],"last_update":"2021-05-05T08:00:00+08:00"}]}
  1. 使用JOSN在线解析工具解析该数据,如下在这里插入图片描述

1.3 解析心知天气的json数据

1.3.1 使用cJSON库函数将数据以JSON格式打印出来

调用cJSON库函数

	cJSON *root = NULL;
	root = cJSON_Parse(json_data);         /*json_data 为心知天气的原始数据*/ 
	printf("%s\\n\\n", cJSON_Print(root));   /*将完整的数据以JSON格式打印出来*/

cJSON为整个工程的组件(component)之一,所以可以直接调用cJSON库的相关函数,当然还要先添加其头文件。#include "cJSON.h"
在这里插入图片描述
打印出来的数据如下:

{
        "results":      [{
                        "location":     {
                                "id":   "WS10730EM8EV",
                                "name": "Shenzhen",
                                "country":      "CN",
                                "path": "Shenzhen,Shenzhen,Guangdong,China",
                                "timezone":     "Asia/Shanghai",
                                "timezone_offset":      "+08:00"
                        },
                        "daily":        [{
                                        "date": "2021-05-05",
                                        "text_day":     "Cloudy",
                                        "code_day":     "4",
                                        "text_night":   "Cloudy",
                                        "code_night":   "4",
                                        "high": "30",
                                        "low":  "23",
                                        "rainfall":     "0.3",
                                        "precip":       "",
                                        "wind_direction":       "CLM",
                                        "wind_direction_degree":        "",
                                        "wind_speed":   "3.0",
                                        "wind_scale":   "1",
                                        "humidity":     "73"
                                }, {
                                        "date": "2021-05-06",
                                        "text_day":     "Cloudy",
                                        "code_day":     "4",
                                        "text_night":   "Cloudy",
                                        "code_night":   "4",
                                        "high": "30",
                                        "low":  "22",
                                        "rainfall":     "0.0",
                                        "precip":       "",
                                        "wind_direction":       "CLM",
                                        "wind_direction_degree":        "",
                                        "wind_speed":   "3.0",
                                        "wind_scale":   "1",
                                        "humidity":     "72"
                                }, {
                                        "date": "2021-05-07",
                                        "text_day":     "Cloudy",
                                        "code_day":     "4",
                                        "text_night":   "Cloudy",
                                        "code_night":   "4",
                                        "high": "32",
                                        "low":  "23",
                                        "rainfall":     "0.0",
                                        "precip":       "",
                                        "wind_direction":       "CLM",
                                        "wind_direction_degree":        "",
                                        "wind_speed":   "3.0",
                                        "wind_scale":   "1",
                                        "humidity":     "73"
                                }],
                        "last_update":  "2021-05-05T08:00:00+08:00"
                }]
}

注意:

  1. results 的键值对为数组,且该数组里只有1个元素: "results": [{}]
  2. daily 的键值对也为数组,且该数组里有3个元素:"daily": [{},{},{}],

1.3.2 使用cJSON库函数逐个解析参数

  1. 为了使数据分类,这里使用了结构体
/**
 * @brief 心知天气(seniverse) 天气各项数据结构体
 */
typedef struct{
	char *date;
	char *text_day;
	char *code_day;
	char *text_night;
	char *code_night;
	char *high;
	char *low;
	char *rainfall;
	char *precip;
	char *wind_direction;
	char *wind_direction_degree;
	char *wind_speed;
	char *wind_scale;
	char *humidity;

} user_seniverse_day_config_t;


/**
 * @brief 心知天气(seniverse) 数据结构体
 */
typedef struct {
	char *id;
	char *name;
	char *country;
	char *path;
	char *timezone;
	char *timezone_offset;
    user_seniverse_day_config_t day_config[3];/*这里的3是指心知天气URL中的 days=3*/
	char *last_update;

} user_seniverse_config_t;

具体解析如下:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "cJSON.h"
#include "user_cjson.h"


int user_parse_json(char *json_data)
{
    uint8_t i,j;
	uint8_t result_array_size = 0;
	uint8_t daily_array_size = 0;

	cJSON *item = NULL;
	cJSON *root = NULL;
	cJSON *results_root = NULL;
	cJSON *daily_root = NULL;
	user_seniverse_config_t user_sen_config;
    /* print the version */
    printf("Version: %s\\n", cJSON_Version());
	root = cJSON_Parse(json_data);   /*json_data 为心知天气的原始数据*/ 
    if (!root) 
    {
      printf("Error before: [%s]\\n",cJSON_GetErrorPtr());
	  return  -1;
	}
       
    printf("%s\\n\\n", cJSON_Print(root));   /*将完整的数据以JSON格式打印出来*/


	cJSON *Presult = cJSON_GetObjectItem(root, "results");  /*results 的键值对为数组,*/ 
//        printf("%s\\n", cJSON_Print(Presult));


	result_array_size = cJSON_GetArraySize(Presult);  /*求results键值对数组中有多少个元素*/
//	printf("Presult array size is %d\\n",result_array_size);

    for(i = 0;i < result_array_size;i++)
    {
		cJSON *item_results = cJSON_GetArrayItem(Presult, i);

        char *sresults = cJSON_PrintUnformatted(item_results);
		results_root = cJSON_Parse(sresults);
		if (!results_root) 
	    {
	      printf("Error before: [%s]\\n",cJSON_GetErrorPtr());
		  return  -1;
		}
/*-------------------------------------------------------------------*/

		cJSON *Plocation = cJSON_GetObjectItem(results_root, "location");

	    item = cJSON_GetObjectItem(Plocation, "id");
		user_sen_config.id = cJSON_Print(item);
//	        printf("id:%s\\n", cJSON_Print(item));	/*逐个打印*/


	    item = cJSON_GetObjectItem(Plocation, "name");
		user_sen_config.name = cJSON_Print(item);
//	        printf("name:%s\\n", cJSON_Print(item));	

	    item = cJSON_GetObjectItem(Plocation, "country");
        user_sen_config.country = cJSON_Print(item);
//	        printf("country:%s\\n", cJSON_Print(item));	

	    item = cJSON_GetObjectItem(Plocation, "path");
        user_sen_config.path = cJSON_Print(item);
//	        printf("path:%s\\n", cJSON_Print(item));	

	    item = cJSON_GetObjectItem(Plocation, "timezone");
		user_sen_config.timezone = cJSON_Print(item);
//	        printf("timezone:%s\\n", cJSON_Print(item));	

		item = cJSON_GetObjectItem(Plocation, "timezone_offset");
		user_sen_config.timezone_offset = cJSON_Print(item);
//	        printf("timezone_offset:%s\\n", cJSON_Print(item));	
/*-------------------------------------------------------------------*/
		cJSON *Pdaily = cJSON_GetObjectItem(results_root, "daily");


		daily_array_size = cJSON_GetArraySize(Pdaily);
//			printf("Pdaily array size is %d\\n",daily_array_size);

        for(j = 0;j < daily_array_size;j++)
        {
			cJSON *item_daily = cJSON_GetArrayItem(Pdaily, j);
			
			char *sdaily = cJSON_PrintUnformatted(item_daily);

			daily_root = cJSON_Parse(sdaily);

			if (!daily_root) 
		    {
		      printf("Error before: [%s]\\n",cJSON_GetErrorPtr());
			  return  -1;
			}


		    item = cJSON_GetObjectItem(daily_root, "date");
			user_sen_config.day_config[j].date = cJSON_Print(item);
//		        printf("date:%s\\n", cJSON_Print(item));		
			
		    item = cJSON_GetObjectItem(daily_root, "text_day");
			user_sen_config.day_config[j].text_day = cJSON_Print(item);
//		        printf("text_day:%s\\n", cJSON_Print(item));	

		    item = cJSON_GetObjectItem(daily_root, "code_day");
		    user_sen_config.day_config[j].code_day = cJSON_Print(item);
//		        printf("code_day:%s\\n", cJSON_Print(item));		

			item = cJSON_GetObjectItem(daily_root, "text_night");
			user_sen_config.day_config[j].text_night = cJSON_Print(item);
//		        printf("text_night:%s\\n", cJSON_Print(item));		

			item = cJSON_GetObjectItem(daily_root, "code_night");
			user_sen_config.day_config[j].code_night = cJSON_Print(item);
//		        printf("code_night:%s\\n", cJSON_Print(item));		

			item = cJSON_GetObjectItem(daily_root, "high");
			user_sen_config.day_config[j].high = cJSON_Print(item);
//		        printf("high:%s\\n", cJSON_Print(item));		

			item = cJSON_GetObjectItem(daily_root, "low");
			user_sen_config.day_config[j].low = cJSON_Print(item);
//		        printf("low:%s\\n", cJSON_Print(item));		

			item = cJSON_GetObjectItem(daily_root, "rainfall");
			user_sen_config.day_config[j].rainfall = cJSON_Print(item);
//		        printf("rainfall:%s\\n", cJSON_Print(item));		

			item = cJSON_GetObjectItem(daily_root, "precip");
			user_sen_config.day_config[j].precip = cJSON_Print(item);
//		        printf("precip:%s\\n", cJSON_Print(item));		

			item = cJSON_GetObjectItem(daily_root, "wind_direction");
			user_sen_config.day_config[j].wind_direction = cJSON_Print(item);
//		        printf("wind_direction:%s\\n", cJSON_Print(item));		

			item = cJSON_GetObjectItem(daily_root, "wind_direction_degree");
			user_sen_config.day_config[j].wind_direction_degree = cJSON_Print(item);
//		        printf("wind_direction_degree:%s\\n", cJSON_Print(item));		

			item = cJSON_GetObjectItem(daily_root, "wind_speed");
			user_sen_config.day_config[j].wind_speed = cJSON_Print(item);
//		        printf("wind_speed:%s\\n", cJSON_Print(item));		

			item = cJSON_GetObjectItem(daily_root, "wind_scale");
			user_sen_config.day_config[j].wind_scale = cJSON_Print(item);
//		        printf("wind_scale:%s\\n", cJSON_Print(item));		

			item = cJSON_GetObjectItem(daily_root, "humidity");
			user_sen_config.day_config[j].humidity = cJSON_Print(item);
//		        printf("humidity:%s\\n", cJSON_Print(item));		
			cJSON_Delete(daily_root);/*每次调用cJSON_Parse函数后,都要释放内存*/

        }
	/*-------------------------------------------------------------------*/
		item = cJSON_GetObjectItem(results_root, "last_update");
		user_sen_config.last_update = cJSON_Print(item);
//		    printf("last_update:%s\\n", cJSON_Print(item));	
		cJSON_Delete(results_root);  /*每次调用cJSON_Parse函数后,都要释放内存*/

    }

    printf("id:%s\\n", user_sen_config.id);	
	printf("name:%s\\n", user_sen_config.name);
	printf("country:%s\\n", user_sen_config.country以上是关于ESP32基础应用之httpt获取网络天气并使用cJSON解析数据的主要内容,如果未能解决你的问题,请参考以下文章

ESP32基础项目之资讯显示(更新中)

ESP32-IDF 05-2 WIFI-esp32获取温度和天气信息

基于Arduino和ESP8266的JSON数据获取与解压之和风天气

基于STM32的ESP8266天气时钟--------MCU获取天气数据

基于STM32的ESP8266天气时钟--------MCU获取天气数据

STM32天气数据获取