使用RTThread和TouchGFX实现DIY数字仪表(五)——同步天气信息

寵の児 提交于 2020-05-02 16:52:46

目录:

1.使用RTThread和TouchGFX实现DIY数字仪表(一)——使用STM32CUBMX5.6移植touchGFX4.13
2.使用RTThread和TouchGFX实现DIY数字仪表(二)——把TouchGFX移植到RTThread系统
3.使用RTThread和TouchGFX实现DIY数字仪表(三)——获取温湿度传感器数据
4.使用RTThread和TouchGFX实现DIY数字仪表(四)——同步网络时间
5.使用RTThread和TouchGFX实现DIY数字仪表(五)——同步天气信息
6.使用RTThread和TouchGFX实现DIY数字仪表(六)——链接阿里云物联网平台
7.使用RTThread和TouchGFX实现DIY数字仪表(七)——使用MQTT.fx模拟手机设备进行M2M设备间通信
8.使用RTThread和TouchGFX实现DIY数字仪表(八)——开发微信小程序
9.使用RTThread和TouchGFX实现DIY数字仪表(九)——TouchGFX控件使用教程







实验平台:

硬件: 野火挑战者STM32F767 V1开发版和ESP8266模块
软件: TouchGFXDesigner v4.13和 STM32CubeMX v5.6.0,MDK v5.29,RT-Thread env 工具

实验前准备工作:

1.准备一套 野火挑战者STM32F767 开发版或其他核心板
2.安装 TouchGFXDesigner v4.13
3.安装STM32CubeMX v5.6.0和X_CUBE_TOUCHGFX软件包
4.安装 MDK v5.27以上版本
5.下载 RTThread源码包https://gitee.com/rtthread/rt-thread
6.注册心知天气




下载:

代码持续更新中:github代码下载地址https://gitee.com/Aladdin-Wang/hellotouchGFX.git

联系作者:

加微信备注touchgfx,拉入touchgfx-rtthread技术交流群共同学习
在这里插入图片描述

1.注册心知天气获取私钥

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2.添加WebClient软件包

由于我们获取天气信息是通过访问心知天气的网络API,所以我们需要开启本地Web客户端。
在这里插入图片描述

3.添加CJSON软件包

查看心知天气的API返回数据可知,所使用的数据格式是JSON,所以需要开启CJSON软件包用于解析数据。
在这里插入图片描述
在这里插入图片描述

4.添加使用代码

weather_httpclient.c

#include <rtthread.h>
#include <webclient.h>
#include <url_code.h>
#include <string.h>
#include "cJSON_util.h"
#include <board.h>
#include <arpa/inet.h> 
#include <netdev.h>
#include <ntp.h>
#include <weather_httpclient.h>
#define LOG_TAG     "weather"
#define LOG_LVL     LOG_LVL_INFO
#include <ulog.h>
#define THREAD_PRIORITY         12
#define THREAD_STACK_SIZE       1024
#define THREAD_TIMESLICE        5

static rt_thread_t tid1 = RT_NULL;
static struct rt_mailbox weather_mb;
static char mb_pool[16];


char *gfxvalue;
#define GET_HEADER_BUFSZ        2048
#define GET_RESP_BUFSZ                2048
#define GET_RESP_CONTENTSZ        4096
#define URL_LEN_MAX                        2048

#define GET_LOCAL_URI                "http://api.seniverse.com/v3/weather/daily.json?key=S97hL3kj6EbnjEmyC&location=%s&language=zh-Hans&unit=c&start=0&days=5"
#define LOCAL_CITY                   "beijing"        

static weather_t gfx_weather[3];

static void weather_data_parse(char* data)
{
   cJSON *root = RT_NULL, *arrayItem = RT_NULL,*object = RT_NULL, *object2 = RT_NULL,*list = RT_NULL, *item = RT_NULL, *weatheritem = RT_NULL;
        int index, list_size = 0;
   root = cJSON_Parse((const char *)data);
   if (!root)
   {
       rt_kprintf("No memory for cJSON root!\n");
       return;
   }
   arrayItem = cJSON_GetObjectItem(root, "results"); 
    if (arrayItem == RT_NULL)
    {
        rt_kprintf("cJSON get results failed.");
        goto __EXIT;
    }   

	 object = cJSON_GetArrayItem(arrayItem, 0); 
	 if (object == RT_NULL)
    {
        rt_kprintf("cJSON get object failed.");
        goto __EXIT;
    } 
	item = cJSON_GetObjectItem(object, "location");  /* 匹配子对象1 */
    if (item == RT_NULL)
    {
        rt_kprintf("cJSON get location failed.");
        goto __EXIT;
    } 
	if((list = cJSON_GetObjectItem(item,"name")) != NULL)   
	{
		rt_kprintf("city: %s\r\n",list->valuestring);
	}
	object2 = cJSON_GetObjectItem(object, "daily");  /* 匹配子对象2 */
	 if (object2 == RT_NULL)
    {
        rt_kprintf("cJSON get object2 failed.");
        goto __EXIT;
    } 	
	int size = cJSON_GetArraySize(object2);     //获取数组中对象个数
	rt_kprintf("\n");
	for(int i = 0 ;i<size;i++ )
	{
		item = cJSON_GetArrayItem(object2, i); 
		
		if (item == RT_NULL)
		{
			rt_kprintf("cJSON get daily failed.");
			goto __EXIT;
		} 
		if((list = cJSON_GetObjectItem(item,"date")) != NULL)   
		{
			rt_kprintf("date: %s\r\n",list->valuestring);
			strncpy(gfx_weather[i].date, list->valuestring,strlen(list->valuestring));	
		}
		if((list = cJSON_GetObjectItem(item,"text_day")) != NULL)   
		{
			rt_kprintf("text_day: %s\r\n",list->valuestring);
			strncpy(gfx_weather[i].text_day, list->valuestring,strlen(list->valuestring));	
		}
		if((list = cJSON_GetObjectItem(item,"code_day")) != NULL)   
		{
			rt_kprintf("code_day: %s\r\n",list->valuestring);
			strncpy(gfx_weather[i].code_day, list->valuestring,strlen(list->valuestring));				
		}
		if((list = cJSON_GetObjectItem(item,"text_night")) != NULL)   
		{
			rt_kprintf("text_night: %s\r\n",list->valuestring);
			strncpy(gfx_weather[i].text_night, list->valuestring,strlen(list->valuestring));				
		}	
		if((list = cJSON_GetObjectItem(item,"high")) != NULL)   
		{
			rt_kprintf("high: %s\r\n",list->valuestring);
			strncpy(gfx_weather[i].high, list->valuestring,strlen(list->valuestring));				
		}
		if((list = cJSON_GetObjectItem(item,"low")) != NULL)   
		{
			rt_kprintf("low: %s\r\n",list->valuestring);
			strncpy(gfx_weather[i].low, list->valuestring,strlen(list->valuestring));				
		}	
		if((list = cJSON_GetObjectItem(item,"wind_direction")) != NULL)   
		{
			rt_kprintf("wind_direction: %s\r\n",list->valuestring);
			strncpy(gfx_weather[i].wind_direction, list->valuestring,strlen(list->valuestring));				
		}
		if((list = cJSON_GetObjectItem(item,"wind_speed")) != NULL)   
		{
			rt_kprintf("wind_speed: %s\r\n",list->valuestring);
			strncpy(gfx_weather[i].wind_speed, list->valuestring,strlen(list->valuestring));			
		}
		if((list = cJSON_GetObjectItem(item,"rainfall")) != NULL)   
		{
			rt_kprintf("rainfall: %s\r\n",list->valuestring);
			strncpy(gfx_weather[i].rainfall, list->valuestring,strlen(list->valuestring));			
		}
		if((list = cJSON_GetObjectItem(item,"humidity")) != NULL)   
		{
			rt_kprintf("humidity: %s\r\n",list->valuestring);
			strncpy(gfx_weather[i].humidity, list->valuestring,strlen(list->valuestring));			
		}	
		rt_kprintf("\n");
	}

__EXIT:
   if (root != RT_NULL)
       cJSON_Delete(root);        
}

int get_weather(int argc, char **argv)
{
    struct webclient_session* session = RT_NULL;
    unsigned char *buffer = RT_NULL;
    char *URI = RT_NULL;
    int index, ret = 0;
    int bytes_read, resp_status;
    int content_length = -1;
	char *city_name = rt_calloc(1,255);
	if(argc == 1)
	{
		strcpy(city_name, LOCAL_CITY);
	}
	else if (argc == 2)
    {
        strcpy(city_name, argv[1]);
        urlencode(city_name);//对中文编码
    }
    else if(argc > 2)
    {
        rt_kprintf("wt [CityName]  - webclient GET request test.\n");
        return -1;
    }
        URI = rt_calloc(1, URL_LEN_MAX);        
        rt_snprintf(URI, URL_LEN_MAX, GET_LOCAL_URI, city_name);
    buffer = (unsigned char *) web_malloc(GET_RESP_CONTENTSZ);
    if (buffer == RT_NULL)
    {
        rt_kprintf("no memory for receive buffer.\n");
        ret = -RT_ENOMEM;
        goto __exit;
    }

    /* create webclient session and set header response size */
    session = webclient_session_create(GET_HEADER_BUFSZ);
    if (session == RT_NULL)
    {
        ret = -RT_ENOMEM;
        goto __exit;
    }

    /* send GET request by default header */
        rt_kprintf("send GET request to %s\n", URI);
    if ((resp_status = webclient_get(session, URI)) != 200)
    {
        rt_kprintf("webclient GET request failed, response(%d) error.\n", resp_status);
        ret = -RT_ERROR;
        goto __exit;
    }
    content_length = webclient_content_length_get(session);
    if (content_length < 0)
    {
        rt_kprintf("webclient GET request type is chunked.\n");
        do
        {
            bytes_read = webclient_read(session, buffer, GET_RESP_BUFSZ);
            if (bytes_read <= 0)
            {
                break;
            }

            for (index = 0; index < bytes_read; index++)
            {
                rt_kprintf("%c", buffer[index]);
            }
        } while (1);
        rt_kprintf("\n");
    }
    else
    {
                int content_pos = 0;
        do
        {
            bytes_read = webclient_read(session, buffer+content_pos, GET_RESP_BUFSZ);
            if (bytes_read <= 0)
            {
                                break;
            }
            content_pos += bytes_read;
        } while (content_pos < content_length);
        weather_data_parse((char*)buffer);
    }

__exit:
    if (session)
    {
        webclient_close(session);
    }

    if (buffer)
    {
        web_free(buffer);
    }

    if (URI)
    {
        web_free(URI);
    }

    return ret;
}
weather_t  *gfxget_weather_date(void)
{
	if (rt_mb_recv(&weather_mb, (rt_ubase_t *)&gfx_weather, RT_WAITING_NO) == RT_EOK)
	{
		return gfx_weather;
	}
	else
	{
		return RT_NULL;
	}
    
}
/* 入口函数 */
static void weather_collect_thread_entry(void *parameter)
{
	//获取网卡对象
	struct netdev* net = netdev_get_by_name("esp0");
	//阻塞判断当前网络是否正常连接
	while(netdev_is_internet_up(net) != 1)
	{
	   rt_thread_mdelay(200);
	}
	if(0== get_weather(1,0))
	{
		rt_mb_send(&weather_mb, (rt_uint32_t)gfx_weather);
	}
	while(1)
	{
		rt_thread_mdelay(5000);
		rt_mb_send(&weather_mb, (rt_uint32_t)gfx_weather);		
	}
}
/* 创建线程 */
int weather_collect(void)
{
	rt_err_t result = RT_EOK;
	/* 初始化mailbox */
    result = rt_mb_init(&weather_mb,
                        "weather_mbt",                /* 名称是 sht30_mbt */
                        &mb_pool[0],                /* 邮箱用到的内存池是 mb_pool */
                        sizeof(mb_pool) / 4,        /* 邮箱中的邮件数目,因为一封邮件占 4 字节 */
                        RT_IPC_FLAG_FIFO);          /* 采用 FIFO 方式进行线程等待 */
    if (result != RT_EOK)
    {
        LOG_D("init mailbox failed.\n");
        return -1;
    }

    /* 创建线程*/
    tid1 = rt_thread_create("weather",
            weather_collect_thread_entry, RT_NULL,
                            THREAD_STACK_SIZE,
                            THREAD_PRIORITY, THREAD_TIMESLICE);

    /* 如果获得线程控制块,启动这个线程 */
    if (tid1 != RT_NULL)
        rt_thread_startup(tid1);

    return 0;
}
INIT_APP_EXPORT(weather_collect);
#ifdef FINSH_USING_MSH
#include <finsh.h>
MSH_CMD_EXPORT_ALIAS(get_weather, wt, wt [CityName]  webclient GET request test);
#endif /* FINSH_USING_MSH */

weather_httpclient.h

#ifndef __WEATHER_H_
#define __WEATHER_H_
#include <rtthread.h>
typedef struct weather {
	char date[8];				
	char text_day[8];		
	char code_day[8];	
	char text_night[8];	
	char high[8];	
	char low[8];		
	char wind_direction[8];		
	char wind_speed[8];		
	char rainfall[8];	
	char humidity[8];	
} weather_t;


#endif

5. 添加URL转码文件

因中文地名需要URL转码
url_code.c

#include <url_code.h>
//#include <stdio.h>
#include <string.h>
#include <rtthread.h>

#define BURSIZE 1024

static int hex2dec(char c)
{
        if ('0' <= c && c <= '9') {
                return c - '0';
        } else if ('a' <= c && c <= 'f') {
                return c - 'a' + 10;
        } else if ('A' <= c && c <= 'F') {
                return c - 'A' + 10;
        } else {
                return -1;
        }
}

static char dec2hex(short int c)
{
        if (0 <= c && c <= 9) {
                return c + '0';
        } else if (10 <= c && c <= 15) {
                return c + 'A' - 10;
        } else {
                return (char)-1;
        }
}


/*
* 编码一个url
*/
void urlencode(char *url)
{
        int i = 0;
        int len = strlen(url);
        int res_len = 0;
        char *res = rt_calloc(1, BURSIZE);
        for (i = 0; i < len; ++i) {
                char c = url[i];
                if (('0' <= c && c <= '9') ||
                                ('a' <= c && c <= 'z') ||
                                ('A' <= c && c <= 'Z') || c == '/' || c == '.') {
                        res[res_len++] = c;
                } else {
                        int j = (short int)c;
                        if (j < 0)
                                j += 256;
                        int i1, i0;
                        i1 = j / 16;
                        i0 = j - i1 * 16;
                        res[res_len++] = '%';
                        res[res_len++] = dec2hex(i1);
                        res[res_len++] = dec2hex(i0);
                }
        }
        res[res_len] = '\0';
        strcpy(url, res);
        rt_free(res);
}

/*
* 解码url
*/
void urldecode(char *url)
{
        int i = 0;
        int len = strlen(url);
        int res_len = 0;
        char *res = rt_calloc(1, BURSIZE);
        for (i = 0; i < len; ++i) {
                char c = url[i];
                if (c != '%') {
                        res[res_len++] = c;
                } else {
                        char c1 = url[++i];
                        char c0 = url[++i];
                        int num = 0;
                        num = hex2dec(c1) * 16 + hex2dec(c0);
                        res[res_len++] = num;
                }
        }
        res[res_len] = '\0';
        strcpy(url, res);
        rt_free(res);
}

url_code.h

#ifndef __URL_CODE_H__
#define __URL_CODE_H__

void urlencode(char *url);
void urldecode(char *url);

#endif

6. 实验

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!