ESP32实现天气播报
文章目录
前言
前面几篇已经把WiFi天气语音播报涉及到的知识内容提了一下,这一篇进行项目的整合进而完成WiFi天气语音播报。
1、实现功能
自己编写相关代码,驱动WIFI模组,连接气象服务器,获取当地天气,同时还可以通过温湿度传感器采集到当前室内的温湿度值,并在LCD屏上进行显示,还可以进行语音播报
无需使用温湿度传感器即可读取实时温湿度。
[En]
There is no need to use temperature and humidity sensors to read real-time temperature and humidity.
; 2、获取并解析天气数据
首先我们要配置WIFI模块连上热点,检测是否接入 WIFI GOT IP,连接服务器,开启透传,获取天气结果。当WIFI模块获取服务器一次实时天气成功后,会返回对应的json格式数据,然后再对json格式数据解析获取需要的内容。需要说的是JSON是一种特殊的数据结构,ESP32中有一个内置的库cjson,用来处理json格式的数据并且获取内容。
void Get_Weather(void)
{
static uint8_t count = 0;
char http_cmd[256] = {0};
uint8_t recv = 0;
cJSON *root = NULL,*json_results = NULL,*json_arry = NULL,*json_location = NULL,*json_now = NULL,*json_daily = NULL,*json_daily_arr = NULL;
switch(count)
{
case 0:
weatherTime[1] = 1000;
WIFI_SendStr("+++");
count++;
break;
case 1:
WIFI_SendStr("AT+RST\r\n");
count++;
break;
case 2:
recv = ESP8266_SendCmd_RecAck(NULL, "WIFI GOT IP", 30000, 1);
count++;
break;
case 3:
recv = ESP8266_SendCmd_RecAck("AT+CIPSTART=\"TCP\",\"116.62.81.138\",80\r\n", "OK", 20000, 1);
if(recv == 0) count++;
break;
case 4:
recv = ESP8266_SendCmd_RecAck("AT+CIPMODE=1\r\n", "OK", 1000, 1);
if(recv == 0) count++;
break;
case 5:
recv = ESP8266_SendCmd_RecAck("AT+CIPSEND\r\n", ">", 2000, 1);
if(recv == 0) count++;
break;
case 6:
sprintf(http_cmd, "GET https://api.seniverse.com/v3/weather/now.json?key=%s&location=%s&language=en&unit=c\r\n",
Key_ID,
location[location_pos]);
printf("%s\r\n", http_cmd);
WIFI_SendStr(http_cmd);
count++;
break;
case 7:
count = 0;
weatherTime[1] = 10000;
printf("开始解析JSON数据\r\n");
root = cJSON_Parse((char *)wifi_message.rx_buff);
if(!root)
{
printf("root Error before: %s\n", cJSON_GetErrorPtr());
break;
}
else
{
json_results = cJSON_GetObjectItem(root,"results");
if(!json_results)
{
printf("results Error before: %s\n", cJSON_GetErrorPtr());
}
else
{
json_arry = json_results->child;
json_location = cJSON_GetObjectItem(json_arry,"location");
if(!json_location)
{
printf("location Error before: %s\n", cJSON_GetErrorPtr());
}
json_now = cJSON_GetObjectItem(json_arry,"now");
if(!json_now)
{
printf("json_now Error before: %s\n", cJSON_GetErrorPtr());
}
else
{
printf("地址\t天气\t温度\tcode\r\n");
printf("%s\t", cJSON_GetObjectItem(json_location,"name")->valuestring);
printf("%s\t", cJSON_GetObjectItem(json_now,"text")->valuestring);
printf("%s\t", cJSON_GetObjectItem(json_now,"temperature")->valuestring);
printf("%s\r\n", cJSON_GetObjectItem(json_now,"code")->valuestring);
weather[0].now_tem = atoi(cJSON_GetObjectItem(json_now,"temperature")->valuestring);
weather[0].now_code = atoi(cJSON_GetObjectItem(json_now,"code")->valuestring);
sprintf(weather[0].now_text,"%s",cJSON_GetObjectItem(json_now,"text")->valuestring);
if(weather[0].now_code > 38) weather[0].now_code = 39;
}
}
}
cJSON_Delete(root);
wifi_message.rx_count = 0;
memset(wifi_message.rx_buff,0,1024);
break;
}
}
JSON数据格式包括数组和对象两种嵌套方式,简单来说,数组就是中括号的嵌套,对象就是大括号的嵌套,解析的时候是两种不同的函数。
解析的大致步骤为:
- 从第一层对象解析出键为results的对象
- 对results对象进行继续解析,获取序号为0的数组
- 该数组包含了键为location和now的两个对象
- 继续解析来自两个对象的数据
[En]
continue to parse data from two objects*
3、获取天气
代码如下:
if(weatherTime[0]>=weatherTime[1])
{
Get_Weather();
if(Gui_flag==2)
{
memset(buff,0,20);
sprintf(buff,"%s",location_cn[location_pos]);
Draw_Text_8_16_Str(100,10,YELLOW,BLACK,buff);
Draw_Text_8_16_Str(100,30,YELLOW,BLACK,weather[0].now_text);
memset(buff,0,20);
sprintf(buff,"%d",weather[0].now_tem);
Draw_Text_8_16_Str(100,50,YELLOW,BLACK,buff);
}
weatherTime[0]=0;
}
4、LCD显示
主界面画面
代码如下(示例):
void Gui_Main(void)
{
LCD_Clear(YELLOW);
Draw_Text_8_16_Str(10,288,YELLOW,BLACK,"WiFi语音气象站");
}
播报城市天气信息界面
void Gui_Weather(void)
{
LCD_Clear(YELLOW);
Draw_Text_8_16_Str(10,10,YELLOW,BLACK,"城市:");
Draw_Text_8_16_Str(10,30,YELLOW,BLACK,"天气:");
Draw_Text_8_16_Str(10,50,YELLOW,BLACK,"温度:");
memset(buff,0,20);
sprintf(buff,"%s",location_cn[location_pos]);
Draw_Text_8_16_Str(100,10,YELLOW,BLACK,buff);
Draw_Text_8_16_Str(100,30,YELLOW,BLACK,weather[0].now_text);
memset(buff,0,20);
sprintf(buff,"%d",weather[0].now_tem);
Draw_Text_8_16_Str(100,50,YELLOW,BLACK,buff);
}
5、按键实现切换城市和界面
按键实现切换城市和界面
if(KeyTime[0]>=KeyTime[1])
{
keyval = Get_KeyVal();
switch(keyval)
{
case 1:
location_pos++;
if(location_pos>5) location_pos=0;
break;
case 2: Play_Weather();break;
case 3: Gui_flag=2;Gui_mode=1;break;
case 4: Gui_flag=1;Gui_mode=1;break;
}
KeyTime[0]=0;
}
if(GuiTime[0]>GuiTime[1])
{
GuiTime[0]=0;
if(Gui_mode)
{
switch(Gui_flag)
{
case 1:Gui_Main();Gui_mode = 0;break;
case 2:Gui_Weather();Gui_mode = 0;break;
}
}
}
6、语音播报天气
天气播报实现
void Play_Weather(void)
{
int i=0;int len=0;
int num1[3] = {0};
len = weather[0].now_tem;
num1[0] = len/100;
num1[1] = (len-num1[0]*100)/10;
num1[2] = len%10;
printf("num = %d %d %d \r\n",num1[0],num1[1],num1[2]);
if(len != 0)
{
Voice_PlayDirectoryMusic(01,(location_pos+11));
Delay_nms(500);
Voice_PlayDirectoryMusic(02,weather[0].now_code);
Delay_nms(500);
for(i=1;i<3;i++)
{
switch(num1[i])
{
case 0:break;
case 1:Voice_PlayDirectoryMusic(00,0x01);break;
case 2:Voice_PlayDirectoryMusic(00,0x02);break;
case 3:Voice_PlayDirectoryMusic(00,0x03);break;
case 4:Voice_PlayDirectoryMusic(00,0x04);break;
case 5:Voice_PlayDirectoryMusic(00,0x05);break;
case 6:Voice_PlayDirectoryMusic(00,0x06);break;
case 7:Voice_PlayDirectoryMusic(00,0x07);break;
case 8:Voice_PlayDirectoryMusic(00,0x08);break;
case 9:Voice_PlayDirectoryMusic(00,0x09);break;
default:break;
}
Delay_nms(1);
if((i==1) && (num1[1]!=0))
Voice_PlayDirectoryMusic(00,10);
}
Delay_nms(1);
Voice_PlayDirectoryMusic(01,01);
}
}
总结
以上就是WiFi天气语音播报的全部内容了,可能有些地方有错误也有些地方是借鉴别的大佬的,不管怎样亲自完成一个项目还是挺有成就感的。最后附上整个项目的源码
WiFi天气语音播报 提取码:lwm2
Original: https://blog.csdn.net/qq_44890147/article/details/121380850
Author: 清道 夫
Title: ESP32+TFTLCD实现WiFi天气语音播报(八)
原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/515025/
转载文章受原作者版权保护。转载请注明原作者出处!