esp32语音播放天气预报

本文即将为你示例如何使用esp32的wifi,http组件以及百度在线语音合成等功能,实现获取天气数据并通过语音播放。

效果演示

esp32语音播放天气预报

一,请求天气数据

1.1 思路

利用esp32的http组件,向Web API请求天气数据,我使用的是万维易源提供的API接口,这个接口的调用比较简单,而且提供了1000次的额度,还是比较良心的。

请求的方式也很简单,使用GET方式向天气接口发起请求,服务端会返回json格式的当地城市的天气数据。后续我们只要解析出json中的数据,提取我们想要的天气数据。

1.2 注册账号

官网注册账号,进入控制台,找到接口使用者-》我的应用,系统默认创建了一个应用,just_test_app,将这个应用的showapi_appid,和sercret保存下来,我们需要这两个数据作为请求参数。
然后进入天气api接口文档,购买0.00元档的套餐,到这一步,你已经可用使用它的接口了。
在接口文档中,可以选择根据不同的参数来获取天气数据,这里我选择ip查询。当ip的参数为空时,会默认返回客户端的ip地址的城市的信息。
在这里插入图片描述

1.3 获取数据

通过ip获取天气的url是https://route.showapi.com/9-4,我们只需要在url后加入showapi_appidshowapi_sign两个参数(showapi_sign就是上文的sercret),然后发起GET请求,就能接收到返回的json字符串。
例如我的url是:

https://route.showapi.com/9-4?showapi_appid=421387&showapi_sign=f5f3b508fd6c43e09457be788b251a32

http请求代码,具体逻辑见代码注释

全局变量

static char http_data[MX_HTTP_BUFF]; //! 需要定义为全局静态变量,否则会导致任务的堆栈溢出
#define WEATHER_URL "https://route.showapi.com/9-4?showapi_appid=421387&showapi_sign=f5f3b508fd6c43e09457be788b251a32"
esp_err_t err;
esp_http_client_config_t config = {
    
    
            .url = WEATHER_URL,     //http请求地址
            .event_handler = _http_event_handle,    //http请求回调函数
            .method = HTTP_METHOD_GET,      //GET方式
            
};

esp_http_client_handle_t client = esp_http_client_init(&config);
AUDIO_MEM_CHECK(TAG, client, return NULL);

//发起请求
if(esp_http_client_open(client,0)!=ESP_OK)
{
    
    
	return -1;
}

//获取返回头
esp_http_client_fetch_headers(client);
ESP_LOGI(TAG, "Status = %d, content_length = %d",esp_http_client_get_status_code(client),esp_http_client_get_content_length(client));

while(1)
{
    
    
	//读取返回的数据到http_data
	int read_len = esp_http_client_read(client, http_data + index, max_len - index);
	//读取完毕
    if(read_len <= 0)
    {
    
    
    	break;
    }
    index += read_len;
    total += read_len;
    http_data[index] = 0;
    }
    if(total<0)
    {
    
    
		ESP_LOGI(TAG,"read error");
		return -1;
	}
	esp_http_client_close(client);
	esp_http_client_cleanup(client);
}

二,解析JSON字符串

2.1 天气数据

通过将返回的json数据格式化,可得到下面的json数据:

{
    
    
	"showapi_res_error": "",
	"showapi_res_id": "5fa415b48d57ba1617db793e",
	"showapi_res_code": 0,
	"showapi_res_body": {
    
    
		"time": "20201105180000",
		"ret_code": 0,
		"now": {
    
    
			"weather_code": "00",
			"aqiDetail": {
    
    
				"num": "95",
				"co": "0.5",
				"so2": "6",
				"area": "深圳",
				"o3": "84",
				"no2": "32",
				"aqi": "51",
				"quality": "良好",
				"pm10": "52",
				"pm2_5": "25",
				"o3_8h": "98",
				"primary_pollutant": "颗粒物(PM10)"
			},
			"wind_direction": "东风",
			"temperature_time": "23:00",
			"wind_power": "1级",
			"aqi": "51",
			"sd": "78%",
			"weather_pic": "http://app1.showapi.com/weather/icon/night/00.png",
			"weather": "晴",
			"temperature": "22"
		},
		"cityInfo": {
    
    
			"c6": "guangdong",
			"c5": "深圳",
			"c4": "shenzhen",
			"c3": "宝安",
			"c9": "中国",
			"c8": "china",
			"c7": "广东",
			"c17": "+8",
			"c16": "AZ9755",
			"c1": "101280605",
			"c2": "baoan",
			"c0": "440306",
			"longitude": 113.878,
			"c11": "0755",
			"c10": "3",
			"latitude": 22.556,
			"c12": "518001",
			"c15": "1"
		},
		"showapi_fee_code": 0,
		"f1": {
    
    
			"night_weather_code": "00",
			"day_weather": "晴",
			"night_weather": "晴",
			"jiangshui": "0%",
			"air_press": "1005 hPa",
			"night_wind_power": "0-3级 <5.4m/s",
			"day_wind_power": "0-3级 <5.4m/s",
			"day_weather_code": "00",
			"sun_begin_end": "06:25|16:20",
			"ziwaixian": "很强",
			"day_weather_pic": "http://app1.showapi.com/weather/icon/day/00.png",
			"weekday": 4,
			"night_air_temperature": "20",
			"day_air_temperature": "27",
			"day_wind_direction": "北风",
			"day": "20201105",
			"night_weather_pic": "http://app1.showapi.com/weather/icon/night/00.png",
			"night_wind_direction": "无持续风向"
		},
		"f3": {
    
    
			"night_weather_code": "07",
			"day_weather": "小雨",
			"night_weather": "小雨",
			"jiangshui": "70%",
			"air_press": "1005 hPa",
			"night_wind_power": "0-3级 <5.4m/s",
			"day_wind_power": "0-3级 <5.4m/s",
			"day_weather_code": "07",
			"sun_begin_end": "06:28|16:17",
			"ziwaixian": "最弱",
			"day_weather_pic": "http://app1.showapi.com/weather/icon/day/07.png",
			"weekday": 6,
			"night_air_temperature": "21",
			"day_air_temperature": "28",
			"day_wind_direction": "东北风",
			"day": "20201107",
			"night_weather_pic": "http://app1.showapi.com/weather/icon/night/07.png",
			"night_wind_direction": "东北风"
		},
		"f2": {
    
    
			"night_weather_code": "07",
			"day_weather": "晴",
			"night_weather": "小雨",
			"jiangshui": "0%",
			"air_press": "1005 hPa",
			"night_wind_power": "0-3级 <5.4m/s",
			"day_wind_power": "0-3级 <5.4m/s",
			"day_weather_code": "00",
			"sun_begin_end": "06:27|16:18",
			"ziwaixian": "很强",
			"day_weather_pic": "http://app1.showapi.com/weather/icon/day/00.png",
			"weekday": 5,
			"night_air_temperature": "21",
			"day_wind_direction": "无持续风向",
			"day_air_temperature": "28",
			"night_wind_direction": "东北风",
			"night_weather_pic": "http://app1.showapi.com/weather/icon/night/07.png",
			"day": "20201106"
		}
	}
}

2.2 使用cJSON解析出字符串

cJSON是一个用C语言写的专门用于处理json数据的库。官方地址:http://www.json.org/。idf中已经集成了cjson组件。

以下代码示例展示了如何使用cjson解析出json字符串里的数据,并将字符串拼接成一句流畅的句子。简单的展示,只读取json中的天气和温度数据。

#include "cJSON.h"
char data[1024]={
    
    0};
void demo()
{
    
    
	//解析整个json
	cJSON *root = cJSON_Parse(http_data);
	if(!root)
    {
    
    
          ESP_LOGI(TAG, "error,json parse error");
          return -1;
    }	
    //获取showapi_res_body 
    cJSON *showapi_res_body = cJSON_GetObjectItem(root,"showapi_res_body");
    
    /*---------今天天气数据----------------------------*/
	cJSON *f1 = cJSON_GetObjectItem(showapi_res_body, "f1");
	
	//白天的天气
	cJSON *item = cJSON_GetObjectItem(f1, "day_weather");
	char *day_weather = cJSON_GetStringValue(item);

	//白天的气温
	item = cJSON_GetObjectItem(f1, "day_air_temperature");
	char *day_air_temperature = cJSON_GetStringValue(item);
	
	//拼接成一句话,如:今天,天气晴,气温26度
	snprintf(data, 50, "今天,天气%s,气温%s度", day_weather,day_air_temperature);
	
	cJSON_Delete(root);
}

几个重要的函数:

将json字符串转化成json类型的对象,这个函数必须在其他函数之前执行。

cJSON_Parse(const char *value)

根据键值获取cjson对象的一个成员,这个成员可以也是一个json对象

cJSON_GetObjectItem(const cJSON * const object, const char * const string)

获取json对象数组中的指定成员。

cJSON_GetArrayItem(const cJSON *array, int index);

获取json对象里的字符串

cJSON_GetStringValue(cJSON *item);

三,语音合成

使用百度语音合成,将拼接的字符串转换成语音,通过喇叭播放出来。
如何将文字转换成语音,请参考另一篇博客:ESP32使用百度语音合成 实现文字转语音播放

四,小结

天气API只是一个例子,网上有许多开放的API可玩,各位有什么好玩的API也可以在评论留言
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_44821644/article/details/109502203