使用RTThread和TouchGFX實現DIY數字儀表(五)——同步天氣信息

目錄:

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. 實驗

在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章