ESP32基础应用之httpt获取网络天气并使用cJSON解析数据
Posted while(1)
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ESP32基础应用之httpt获取网络天气并使用cJSON解析数据相关的知识,希望对你有一定的参考价值。
文章目录
1 建立工程
本实验是在ESP32基础应用之http实验基础之上修改的
1.1 http-get工程
- 使用http-get协议t获取网络天气;
- 复制 app-http-client 实验并修改工程名为 app-GetNetWeather;
- 在 http_test_task 任务函数中去掉其他测试项目,只留下 http_rest_with_url 函数;
1.2 获取心知天气的json数据
- 心知天气的url链接:该链接说明请参考心知天气官网说明书
https://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 = "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);
}
- 编译并烧录程序后,打印出来的心知天气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"}]}
- 使用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"
}]
}
注意:
- results 的键值对为数组,且该数组里只有1个元素:
"results": [{}]
- daily 的键值对也为数组,且该数组里有3个元素:
"daily": [{},{},{}],
1.3.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;
具体解析如下:
#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-IDF 05-2 WIFI-esp32获取温度和天气信息
基于Arduino和ESP8266的JSON数据获取与解压之和风天气
基于STM32的ESP8266天气时钟--------MCU获取天气数据