OpenHarmony开源社区
直播中

xiaopeng

11年用户 230经验值
擅长:嵌入式技术,处理器/DSP
私信 关注
[经验]

【开鸿智谷NiobeU4开发板免费试用体验】LCD显示实时时间和天气

VID_20221022_170050

前言

上一篇已经获取到了天气信息,但是没有进行解析和显示。
本次就是将获取到的天气信息解析出来并显示在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和按键使用下来会导致程序卡死等一系列莫名其妙的问题,所以对于城市的设置暂时先搁置,后续等研究清楚了再改进。

回帖(1)

他在笑

2022-10-26 14:32:45
期待大佬后续分享
举报

更多回帖

发帖
×
20
完善资料,
赚取积分