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

1 准备工程

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

  1. 复制 《ESP32基础应用之http client实验》中的 app-http-client 工程
  2. http_test_task 任务函数中删掉其他测试函数,仅留下 http_rest_with_url 函数;

2 获取网络天气数据

2.1 获取心知天气的json数据

  1. 心知天气的url链接:该链接说明请参考心知天气官网说明书

    http://api.seniverse.com/v3/weather/daily.json?key=rrpd2zmqkpwlsckt&location=shenzhen&language=en&unit=c&start=0&days=3
    
  2. 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 = "http://api.seniverse.com/v3/weather/daily.json?key=rrpd2zmqkpwlsckt&location=shenzhen&language=en&unit=c&start=0&days=3",
            .method = HTTP_METHOD_GET,
            .event_handler = _http_event_handler,
            .user_data = local_response_buffer,        // Pass address of local buffer to get response
            .disable_auto_redirect = true,
        };
        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));
    
    	ESP_LOGI(TAG, "recv data ---2 = %d %s\r\n", strlen(local_response_buffer), local_response_buffer); /*打印心知天气json原始数据*/
        esp_http_client_cleanup(client);
    }
    
  3. 编译并烧录程序后,打印出来的心知天气json原始数据如下:
    在这里插入图片描述
    注意:如果url使用的是https,那么会出错。

  4. 使用JOSN在线解析工具解析该数据,如下在这里插入图片描述

2.2 解析心知天气的json数据

2.2.1 JSON格式打印天气原始数据

  1. 添加头文件
    cJSON为esp-idf的组件(component)之一,所以可以直接调用cJSON库的相关函数。

    #include "cJSON.h"
    
  2. 创建json解析函数并调用

    	static user_cjson_parse(char *json_data)
    	{
    		cJSON *root = NULL;
    	    
    		root = cJSON_Parse(json_data);         /*json_data 为心知天气的原始数据*/ 
    	    ESP_LOGI(TAG, "%s\r\n", cJSON_Print(root)); /*将完整的数据以JSON格式打印出来*/
    	}
    	static void http_rest_with_url(void)
    	{
    		...
    		user_cjson_parse(local_response_buffer);
    		...
    	}
    
    

    打印出来的数据如下:
    在这里插入图片描述

    注意:

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

2.2.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;
    
  2. 解析数据

    static int user_cjson_parse(char *json_data)
    {
        // cJSON *root = NULL;
    
        // root = cJSON_Parse(json_data);         /*json_data 为心知天气的原始数据*/
        // ESP_LOGI(TAG, "%s\r\n", cJSON_Print(root)); /*将完整的数据以JSON格式打印出来*/
    
        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 */
        ESP_LOGI(TAG, "Version: %s\n", cJSON_Version());
        root = cJSON_Parse(json_data); /*json_data 为心知天气的原始数据*/
        if (!root)
        {
            ESP_LOGI(TAG, "Error before: [%s]\n", cJSON_GetErrorPtr());
            return -1;
        }
    
        ESP_LOGI(TAG, "%s\r\n", cJSON_Print(root)); /*将完整的数据以JSON格式打印出来*/
    
        cJSON *Presult = cJSON_GetObjectItem(root, "results"); /*results 的键值对为数组,*/
                                                               //        ESP_LOGI(TAG, "%s\n", cJSON_Print(Presult));
    
        result_array_size = cJSON_GetArraySize(Presult); /*求results键值对数组中有多少个元素*/
                                                         //	ESP_LOGI(TAG, "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)
            {
                ESP_LOGI(TAG, "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);
            //	        ESP_LOGI(TAG, "id:%s\n", cJSON_Print(item));	/*逐个打印*/
    
            item = cJSON_GetObjectItem(Plocation, "name");
            user_sen_config.name = cJSON_Print(item);
            //	        ESP_LOGI(TAG, "name:%s\n", cJSON_Print(item));
    
            item = cJSON_GetObjectItem(Plocation, "country");
            user_sen_config.country = cJSON_Print(item);
            //	        ESP_LOGI(TAG, "country:%s\n", cJSON_Print(item));
    
            item = cJSON_GetObjectItem(Plocation, "path");
            user_sen_config.path = cJSON_Print(item);
            //	        ESP_LOGI(TAG, "path:%s\n", cJSON_Print(item));
    
            item = cJSON_GetObjectItem(Plocation, "timezone");
            user_sen_config.timezone = cJSON_Print(item);
            //	        ESP_LOGI(TAG, "timezone:%s\n", cJSON_Print(item));
    
            item = cJSON_GetObjectItem(Plocation, "timezone_offset");
            user_sen_config.timezone_offset = cJSON_Print(item);
            //	        ESP_LOGI(TAG, "timezone_offset:%s\n", cJSON_Print(item));
            /*-------------------------------------------------------------------*/
            cJSON *Pdaily = cJSON_GetObjectItem(results_root, "daily");
    
            daily_array_size = cJSON_GetArraySize(Pdaily);
            //			ESP_LOGI(TAG, "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)
                {
                    ESP_LOGI(TAG, "Error before: [%s]\n", cJSON_GetErrorPtr());
                    return -1;
                }
    
                item = cJSON_GetObjectItem(daily_root, "date");
                user_sen_config.day_config[j].date = cJSON_Print(item);
                //		        ESP_LOGI(TAG, "date:%s\n", cJSON_Print(item));
    
                item = cJSON_GetObjectItem(daily_root, "text_day");
                user_sen_config.day_config[j].text_day = cJSON_Print(item);
                //		        ESP_LOGI(TAG, "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);
                //		        ESP_LOGI(TAG, "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);
                //		        ESP_LOGI(TAG, "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);
                //		        ESP_LOGI(TAG, "code_night:%s\n", cJSON_Print(item));
    
                item = cJSON_GetObjectItem(daily_root, "high");
                user_sen_config.day_config[j].high = cJSON_Print(item);
                //		        ESP_LOGI(TAG, "high:%s\n", cJSON_Print(item));
    
                item = cJSON_GetObjectItem(daily_root, "low");
                user_sen_config.day_config[j].low = cJSON_Print(item);
                //		        ESP_LOGI(TAG, "low:%s\n", cJSON_Print(item));
    
                item = cJSON_GetObjectItem(daily_root, "rainfall");
                user_sen_config.day_config[j].rainfall = cJSON_Print(item);
                //		        ESP_LOGI(TAG, "rainfall:%s\n", cJSON_Print(item));
    
                item = cJSON_GetObjectItem(daily_root, "precip");
                user_sen_config.day_config[j].precip = cJSON_Print(item);
                //		        ESP_LOGI(TAG, "precip:%s\n", cJSON_Print(item));
    
                item = cJSON_GetObjectItem(daily_root, "wind_direction");
                user_sen_config.day_config[j].wind_direction = cJSON_Print(item);
                //		        ESP_LOGI(TAG, "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);
                //		        ESP_LOGI(TAG, "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);
                //		        ESP_LOGI(TAG, "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);
                //		        ESP_LOGI(TAG, "wind_scale:%s\n", cJSON_Print(item));
    
                item = cJSON_GetObjectItem(daily_root, "humidity");
                user_sen_config.day_config[j].humidity = cJSON_Print(item);
                //		        ESP_LOGI(TAG, "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);
            //		    ESP_LOGI(TAG, "last_update:%s\n", cJSON_Print(item));
            cJSON_Delete(results_root); /*每次调用cJSON_Parse函数后,都要释放内存*/
        }
    
        ESP_LOGI(TAG, "id:%s\n", user_sen_config.id);
        ESP_LOGI(TAG, "name:%s\n", user_sen_config.name);
        ESP_LOGI(TAG, "country:%s\n", user_sen_config.country);
        ESP_LOGI(TAG, "path:%s\n", user_sen_config.path);
        ESP_LOGI(TAG, "timezone:%s\n", user_sen_config.timezone);
        ESP_LOGI(TAG, "timezone_offset:%s\n", user_sen_config.timezone_offset);
        for (i = 0; i < daily_array_size; i++)
        {
            ESP_LOGI(TAG, "date:%s\n", user_sen_config.day_config[i].date);
            ESP_LOGI(TAG, "text_day:%s\n", user_sen_config.day_config[i].text_day);
            ESP_LOGI(TAG, "code_day:%s\n", user_sen_config.day_config[i].code_day);
            ESP_LOGI(TAG, "text_night:%s\n", user_sen_config.day_config[i].text_night);
            ESP_LOGI(TAG, "code_night:%s\n", user_sen_config.day_config[i].code_night);
            ESP_LOGI(TAG, "high:%s\n", user_sen_config.day_config[i].high);
            ESP_LOGI(TAG, "low:%s\n", user_sen_config.day_config[i].low);
            ESP_LOGI(TAG, "precip:%s\n", user_sen_config.day_config[i].precip);
            ESP_LOGI(TAG, "wind_direction:%s\n", user_sen_config.day_config[i].wind_direction);
            ESP_LOGI(TAG, "wind_direction_degree:%s\n", user_sen_config.day_config[i].wind_direction_degree);
            ESP_LOGI(TAG, "wind_speed:%s\n", user_sen_config.day_config[i].wind_speed);
            ESP_LOGI(TAG, "wind_scale:%s\n", user_sen_config.day_config[i].wind_scale);
            ESP_LOGI(TAG, "humidity:%s\n", user_sen_config.day_config[i].humidity);
        }
        ESP_LOGI(TAG, "last_update:%s\n", user_sen_config.last_update);
    
        cJSON_Delete(root); /*每次调用cJSON_Parse函数后,都要释放内存*/
    
        return 0;
    }
    
    
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值