上一篇已经获取到了天气信息,但是没有进行解析和显示。
本次就是将获取到的天气信息解析出来并显示在lcd屏幕上,另外,还增加了网络对时功能。
天气数据的解析使用了第三方的cJSON包,主要解析如下数据:
①城市
②天气
③温度
④湿度
⑤风力
天气原始数据格式如下:
{
"code": 1,
"msg": "Sucess",
"counts": 2362, //访问的剩余次数。
"data": {
"cityId": "CH010100", //城市id
"cityName": "北京", //城市名称
"lastUpdate": "2016-03-09 17:10:00", //实况更新时间
"tq": "多云", //天气现象
"numtq": "01", //天气现象编码
"qw": "5.0", //当前气温
"fl": "微风", //当前风力
"numfl": "0", //当前风力编码
"fx": "无持续风向", //当前风向
"numfx": "0", //当前风向编码
"sd": "10.0" //相对湿度,直接在此数值后添加%即可
}
}
由上可以看出,每一个参数基本上都可以通过编号或者是内容直接解析出来,为了方便我这边都是通过获取对应参数的编号,然后通过编号再解析出内容。
具体cJSON使用方法不详细说明,下面针对天气信息的解析过程贴出关键代码:
从解析到显示过程:
cJSON_temp = cJSON_GetObjectItem(wdata,"numtq");
weathrer_get_info(cJSON_temp, &weather_data.weather_num[1]);
numtq_to_tq(weather_data.weather_num, temp);
//LCD_ShowString(8,46,16," ",1); //清除该行
LCD_ShowString(8,46,16,&temp[2],0); //显示天气
printf("tqnum : %s\r\n",temp);
// mb_msg_send(temp);//发送消息到队列
// rt_thread_mdelay(80);
将json对象转换为字符串或者数字:
static void weathrer_get_info(const cJSON *item, uint8_t* val)
{
switch(item ->type)
{
case cJSON_Number:
if(item ->valuedouble - item->valueint > 0.001)
{
sprintf(val,"%.1f",item->valuedouble);
}
else
{
if(item->valueint <= 99999)
{
sprintf(val,"%d",item->valueint);
}
}
break;
case cJSON_String:
sprintf(val,"%s",item->valuestring);
break;
}
}
根据天气编号解析出天气:
//天气代码转换为天气英文
static void numtq_to_tq(char *num_code, char *des)
{
uint16_t temp_tq = 0;
uint16_t len;
len = strlen(num_code);
if(len == 3)
{
temp_tq = (num_code[1] - '0')* 10 + (num_code[2] - '0');//代码转为为数字
}
else if(len == 4)
{
temp_tq = (num_code[1] - '0') * 100 + (num_code[2] - '0') * 10 + (num_code[3] - '0');//代码转为为数字
}
if(temp_tq > 100)//超出范围,数据无效
{
return;
}
// des[0] = '1';
// des[1] = temp_tq;
// des[2] = '\0';
#if 1
switch(temp_tq)
{
case 0://晴
memcpy(des,"1 Sunny",sizeof("1 Sunny"));
break;
case 1://多云
memcpy(des,"1 Cloudy",sizeof("1 Cloudy"));
break;
case 2://阴
memcpy(des,"1 Overcast",sizeof("1 Overcast"));
break;
case 3://阵雨
memcpy(des,"1 Shower",sizeof("1 Shower"));
break;
case 4://雷阵雨
memcpy(des,"1 Thundershower",sizeof("1 Thundershower"));
break;
case 5://雷阵雨伴有冰雹
memcpy(des,"1 Thundershower with hail",sizeof("1 Thundershower with hail"));
break;
case 6://雨夹雪
memcpy(des,"1 Sleet",sizeof("1 Sleet"));
break;
case 7://小雨
memcpy(des,"1 Light rain",sizeof("1 Light rain"));
break;
case 8://中雨
memcpy(des,"1 Moderate rain",sizeof("1 Moderate rain"));
break;
case 9://大雨
memcpy(des,"1 Heavy rain",sizeof("1 Heavy rain"));
break;
case 10://暴雨
memcpy(des,"1 Storm",sizeof("1 Storm"));
break;
case 11://大暴雨
memcpy(des,"1 Heavy storm",sizeof("1 Heavy storm"));
break;
case 12://特大暴雨
memcpy(des,"1 Severe storm",sizeof("1 Severe storm"));
break;
case 13://阵雪
memcpy(des,"1 Snow flurry",sizeof("1 Snow flurry"));
break;
case 14://小雪
memcpy(des,"1 Light snow",sizeof("1 Light snow"));
break;
case 15://中雪
memcpy(des,"1 Moderate snow",sizeof("1 Moderate snow"));
break;
case 16://大雪
memcpy(des,"1 Heavy snow",sizeof("1 Heavy snow"));
break;
case 17://暴雪
memcpy(des,"1 Snowstorm",sizeof("1 Snowstorm"));
break;
case 18://雾
memcpy(des,"1 Fog",sizeof("1 Fog"));
break;
case 19://冻雨
memcpy(des,"1 Ice rain",sizeof("1 Ice rain"));
break;
case 20://沙尘暴
memcpy(des,"1 Duststorm",sizeof("1 Duststorm"));
break;
case 21://小到中雨
memcpy(des,"1 Light to moderate rain",sizeof("1 Light to moderate rain"));
break;
case 22://中到大雨
memcpy(des,"1 Moderate to heavy rain",sizeof("1 Moderate to heavy rain"));
break;
case 23://大到暴雨
memcpy(des,"1 Heavy rain to storm",sizeof("1 Heavy rain to storm"));
break;
case 24://暴雨到大暴雨
memcpy(des,"1 Storm to heavy storm",sizeof("1 Storm to heavy storm"));
break;
case 25://暴雨到特大暴雨
memcpy(des,"1 Heavy to severe storm",sizeof("1 Heavy to severe storm"));
break;
case 26://小到中雪
memcpy(des,"1 Light to moderate snow",sizeof("1 Light to moderate snow"));
break;
case 27://中到大雪
memcpy(des,"1 Moderate to heavy snow",sizeof("1 Moderate to heavy snow"));
break;
case 28://大到暴雪
memcpy(des,"1 Heavy snow to snowstorm",sizeof("1 Heavy snow to snowstorm"));
break;
case 29://浮尘
memcpy(des,"1 Dust",sizeof("1 Dust"));
break;
case 30://扬沙
memcpy(des,"1 Sand",sizeof("1 Sand"));
break;
case 31://强沙尘暴
memcpy(des,"1 Sandstorm",sizeof("1 Sandstorm"));
break;
case 32://浓雾
memcpy(des,"1 Dense fog",sizeof("1 Dense fog"));
break;
case 49://强浓雾
memcpy(des,"1 Heavy dense fog",sizeof("1 Heavy dense fog"));
break;
case 53://霾
memcpy(des,"1 Haze",sizeof("1 Haze"));
break;
case 54://中度霾
memcpy(des,"1 Moderate haze",sizeof("1 Moderate haze"));
break;
case 55://重度霾
memcpy(des,"1 Severe haze",sizeof("1 Severe haze"));
break;
case 56://严重霾
memcpy(des,"1 Hazardous haze",sizeof("1 Hazardous haze"));
break;
case 57://大雾
memcpy(des,"1 heavy fog",sizeof("1 heavy fog"));
break;
case 58://特强浓雾
memcpy(des,"1 Extra-heavy dense fog",sizeof("1 Extra-heavy dense fog"));
break;
case 99://无
memcpy(des,"1 Unknown",sizeof("1 Unknown"));
break;
case 100://刮风
memcpy(des,"1 Windy",sizeof("1 Windy"));
break;
default:
break;
}
//des[1] = temp;
#end
获取时间最好的方式是使用ntp,我尝试了使用第三方的sntp库来进行对时,但是总是无法对时成功,最后只能放弃了。
最终选择了一种比较偷懒的方式,直接从天气原始数据中提取时间。
因为天气原始数据中提供的时间是天气网站数据更新的时间,一定程度上会有滞后,但是滞后通常不会太多,对于时间精度不高的情况下可以直接利用这个时间来显示。
思路是:
①先获取时间字符串
cJSON_temp = cJSON_GetObjectItem(wdata,"lastUpdate");
weathrer_get_info(cJSON_temp, &weather_data.update_time[1]);
②将字符串转换为十进制整数,包括年月日,时分秒
time_str_to_int(&mytime.year, &weather_data.update_time[1], 0, 4);
time_str_to_int(&mytime.mon, &weather_data.update_time[6], 0, 2);
time_str_to_int(&mytime.day, &weather_data.update_time[9], 0, 2);
time_str_to_int(&mytime.hour, &weather_data.update_time[12], 0, 2);
time_str_to_int(&mytime.min, &weather_data.update_time[15], 0, 2);
time_str_to_int(&mytime.sec, &weather_data.update_time[18], 0, 2);
③将整数型的时间设置到系统时间
set_time_date(mytime);
设置到系统时间的具体方法:
//设置时间
void set_time_date(t_mytime my_tm)
{
struct tm* cur_tm;
time_t now;
char time_str[50];
//char str[50];
time(&now);
cur_tm = localtime(&now);
cur_tm->tm_year = my_tm.year - 1900;
cur_tm->tm_mon = my_tm.mon - 1;
cur_tm->tm_mday = my_tm.day;
cur_tm->tm_hour = my_tm.hour;
cur_tm->tm_min = my_tm.min;
cur_tm->tm_sec = my_tm.sec;
time_t time_sec = mktime(cur_tm);
struct timeval stime;
stime.tv_sec = time_sec + 7 * 60;//补偿7分钟
settimeofday(&stime, NULL);
sprintf(time_str,"ST%d-%02d-%02d %02d:%02d:%02d\r\n",cur_tm->tm_year + 1900, cur_tm->tm_mon +1, cur_tm->tm_mday,
cur_tm->tm_hour, cur_tm->tm_min,cur_tm->tm_sec);
printf("time: %s",time_str);
}
本来是希望通过蓝牙来设置城市的,但是蓝牙的demo例程好像不支持数据的收发,暂时不知道怎么用。uart和按键使用下来会导致程序卡死等一系列莫名其妙的问题,所以对于城市的设置暂时先搁置,后续等研究清楚了再改进。
更多回帖