1 准备工程
本实验是在ESP32基础应用之http client实验基础之上修改的
- 复制 《ESP32基础应用之http client实验》中的 app-http-client 工程
- 在 http_test_task 任务函数中删掉其他测试函数,仅留下 http_rest_with_url 函数;
2 获取网络天气数据
2.1 获取心知天气的json数据
-
心知天气的url链接:该链接说明请参考心知天气官网说明书
http://api.seniverse.com/v3/weather/daily.json?key=rrpd2zmqkpwlsckt&location=shenzhen&language=en&unit=c&start=0&days=3
-
在
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); }
-
编译并烧录程序后,打印出来的心知天气json原始数据如下:
注意:如果url使用的是https,那么会出错。 -
使用JOSN在线解析工具解析该数据,如下
2.2 解析心知天气的json数据
2.2.1 JSON格式打印天气原始数据
-
添加头文件
cJSON为esp-idf的组件(component)之一,所以可以直接调用cJSON库的相关函数。#include "cJSON.h"
-
创建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库函数逐个解析参数
-
用户自己构建天气数据结构
/** * @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;
-
解析数据
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; }