看了小安派(AiPi-Eyes 天气站)的源码,感觉用W801也可以实现。
一、部分源码
main.c
#include "wm_include.h"
#include "Lcd_Driver.h"void UserMain(void)
{printf("\n user task \n");Lcd_Init();Lcd_Clear(RED);CreateWeatherTask();
}
weather.c(该文件需保存为UTF8格式)
#include "Lcd_Driver.h"
#include "wm_include.h"
#include "LCD_calculate.h"
#include "cJSON.h"
#include "ctype.h"#define SSID "SSID"
#define PASSWORD "PASSWORD"#define HTTPURL "http://v1.yiketianqi.com/api?unescape=1&version=v61&appid=此处需替换为自己的KEY"#define DEMO_TASK_SIZE 2048
static tls_os_queue_t *weather_q = NULL;
static OS_STK WeatherTaskStk[DEMO_TASK_SIZE];extern int demo_connect_net(void *, ...);
extern int http_get_demo(void *, ...);/*** @brief** @param weather_data
*/
void cjson_get_weather(char* weather_data)
{cJSON * item = NULL;//cjson对象cJSON* root = cJSON_Parse(weather_data );if (!root) {//printf("Error before: [%s]\n",cJSON_GetErrorPtr());}else{Gui_DrawFont_GBK16(5,95,WHITE,RED," ");item = cJSON_GetObjectItem(root, "city"); //城市Gui_DrawFont_utf8_3bytes_16(5,15,WHITE,RED,item->valuestring);item = cJSON_GetObjectItem(root, "cityEn"); //城市英文Gui_DrawFont_utf8_3bytes_16(40,15,WHITE,RED,item->valuestring);item = cJSON_GetObjectItem(root, "wea");Gui_DrawFont_utf8_3bytes_16(5,35,WHITE,RED,"天气:");Gui_DrawFont_utf8_3bytes_16(60,35,WHITE,RED,item->valuestring);item = cJSON_GetObjectItem(root, "tem"); //温度Gui_DrawFont_utf8_3bytes_16(5,55,WHITE,RED,"温度:");Gui_DrawFont_GBK24(60,55,WHITE,RED,item->valuestring);Gui_DrawFont_utf8_3bytes_16(100,55,WHITE,RED,"℃");item = cJSON_GetObjectItem(root, "win"); //风Gui_DrawFont_utf8_3bytes_16(5,75,WHITE,RED,item->valuestring);item = cJSON_GetObjectItem(root, "air_level"); //空气质量Gui_DrawFont_utf8_3bytes_16(69,75,WHITE,RED,item->valuestring);}cJSON_free(item);cJSON_Delete(root);}void weather_task(void *sdata)
{Gui_DrawFont_GBK16(5,95,WHITE,RED,"Start...... ");if(demo_connect_net(SSID,PASSWORD)==WM_SUCCESS){Gui_DrawFont_GBK16(5,95,WHITE,RED,"Connected ");tls_os_time_delay(3000);http_get_demo(HTTPURL);}for(;;){tls_os_time_delay(100);}
}void CreateWeatherTask(void)
{tls_os_queue_create(&weather_q, DEMO_QUEUE_SIZE);tls_os_task_create(NULL, NULL,weather_task,NULL,(void *)WeatherTaskStk, /* task's stack start address */DEMO_TASK_SIZE * sizeof(u32), /* task's stack size, unit:byte */DEMO_TASK_PRIO,0);
}
Gui_DrawFont_utf8_3bytes_16函数,用来显示3字节UTF8编码的汉字
void Gui_DrawFont_utf8_3bytes_16(unsigned int x, unsigned int y, unsigned int fc, unsigned int bc, char *s)
{unsigned char i,j;unsigned short k,x0;x0=x;while(*s) { for (k=0;k<sizeof(UTF8_hz16)/sizeof(UTF8_hz16[0]);k++) {if ((UTF8_hz16[k].Index[0]==*s)&&(UTF8_hz16[k].Index[1]==*(s+1))&&(UTF8_hz16[k].Index[2]==*(s+2))){ for(i=0;i<16;i++){for(j=0;j<8;j++) {if(UTF8_hz16[k].Msk[i*2]&(0x80>>j)) Gui_DrawPoint(x+j,y+i,fc);else {if (fc!=bc) Gui_DrawPoint(x+j,y+i,bc);}}for(j=0;j<8;j++) {if(UTF8_hz16[k].Msk[i*2+1]&(0x80>>j)) Gui_DrawPoint(x+j+8,y+i,fc);else {if (fc!=bc) Gui_DrawPoint(x+j+8,y+i,bc);}}}break;}}if(k!=sizeof(UTF8_hz16)/sizeof(UTF8_hz16[0])){s+=3;x+=16;}else //ASC字符{k=*s;if (k>32) k-=32; else k=0;for(i=0;i<16;i++)for(j=0;j<8;j++) {if(asc16[k*16+i]&(0x80>>j)) Gui_DrawPoint(x+j,y+i,fc);else {if (fc!=bc) Gui_DrawPoint(x+j,y+i,bc);}}s++;x+=8;}}
}
字模文件(UTF8格式文件)
#ifndef __FONTUTF8_H__
#define __FONTUTF8_H__struct typFNT_UrlCode
{unsigned char Index[3]; char Msk[32];
};
//阴码、逐行、顺向
const struct typFNT_UrlCode UTF8_hz16[] = {"城",0x20,0x28,0x20,0x24,0x20,0x20,0x27,0xFE,0x24,0x20,0xFC,0x20,0x24,0x24,0x27,0xA4,0x24,0xA4,0x24,0xA8,0x24,0xA8,0x3C,0x90,0xE6,0x92,0x49,0x2A,0x08,0x46,0x10,0x82,/*"城",0*/
"市",0x02,0x00,0x01,0x00,0x00,0x00,0x7F,0xFC,0x01,0x00,0x01,0x00,0x01,0x00,0x3F,0xF8,0x21,0x08,0x21,0x08,0x21,0x08,0x21,0x08,0x21,0x28,0x21,0x10,0x01,0x00,0x01,0x00,/*"市",1*/
"京",0x02,0x00,0x01,0x00,0xFF,0xFE,0x00,0x00,0x00,0x00,0x1F,0xF0,0x10,0x10,0x10,0x10,0x10,0x10,0x1F,0xF0,0x01,0x00,0x11,0x10,0x11,0x08,0x21,0x04,0x45,0x04,0x02,0x00,/*"京",1*/}
#endif
在wm_sdk_w80x_20211115\demo\wm_http_demo.c中http_snd_req函数,增加一行:cjson_get_weather(Buffer);用于处理返回的json信息。
u32 http_snd_req(HTTPParameters ClientParams, HTTP_VERB verb, char *pSndData, u8 parseXmlJson)
{int nRetCode;u32 nSize, nTotal = 0;char *Buffer = NULL;HTTP_SESSION_HANDLE pHTTP;u32 nSndDataLen ;do{Buffer = (char *)tls_mem_alloc(HTTP_CLIENT_BUFFER_SIZE);if(Buffer == NULL){return HTTP_CLIENT_ERROR_NO_MEMORY;}memset(Buffer, 0, HTTP_CLIENT_BUFFER_SIZE);printf("HTTP Client v1.0\r\n");nSndDataLen = (pSndData == NULL ? 0 : strlen(pSndData));// Open the HTTP request handlepHTTP = HTTPClientOpenRequest(0);if(!pHTTP){nRetCode = HTTP_CLIENT_ERROR_INVALID_HANDLE;break;}// Set the VerbnRetCode = HTTPClientSetVerb(pHTTP, verb);if(nRetCode != HTTP_CLIENT_SUCCESS){break;}
#if TLS_CONFIG_HTTP_CLIENT_AUTH// Set authenticationif(ClientParams.AuthType != AuthSchemaNone){if((nRetCode = HTTPClientSetAuth(pHTTP, ClientParams.AuthType, NULL)) != HTTP_CLIENT_SUCCESS){break;}// Set authenticationif((nRetCode = HTTPClientSetCredentials(pHTTP, ClientParams.UserName, ClientParams.Password)) != HTTP_CLIENT_SUCCESS){break;}}
#endif //TLS_CONFIG_HTTP_CLIENT_AUTH
#if TLS_CONFIG_HTTP_CLIENT_PROXY// Use Proxy serverif(ClientParams.UseProxy == TRUE){if((nRetCode = HTTPClientSetProxy(pHTTP, ClientParams.ProxyHost, ClientParams.ProxyPort, NULL, NULL)) != HTTP_CLIENT_SUCCESS){break;}}
#endif //TLS_CONFIG_HTTP_CLIENT_PROXYif((nRetCode = HTTPClientSendRequest(pHTTP, ClientParams.Uri, pSndData, nSndDataLen, verb == VerbPost || verb == VerbPut, 0, 0)) != HTTP_CLIENT_SUCCESS){break;}// Retrieve the the headers and analyze themif((nRetCode = HTTPClientRecvResponse(pHTTP, 30)) != HTTP_CLIENT_SUCCESS){break;}printf("Start to receive data from remote server...\r\n");// Get the data until we get an error or end of stream codewhile(nRetCode == HTTP_CLIENT_SUCCESS || nRetCode != HTTP_CLIENT_EOS){// Set the size of our buffernSize = HTTP_CLIENT_BUFFER_SIZE;// Get the datanRetCode = HTTPClientReadData(pHTTP, Buffer, nSize, 300, &nSize);if(nRetCode != HTTP_CLIENT_SUCCESS && nRetCode != HTTP_CLIENT_EOS)break;cjson_get_weather(Buffer); //增加了这一句nTotal += nSize;}}while(0); // Run only oncetls_mem_free(Buffer);if(pHTTP)HTTPClientCloseRequest(&pHTTP);if(ClientParams.Verbose == TRUE){printf("\n\nHTTP Client terminated %d (got %d b)\n\n", nRetCode, nTotal);}return nRetCode;
}
二、说明
1、W801的SDK中DEMO程序有2个函数可以直接用:
extern int demo_connect_net(void *, ...); //用于连上wifi
extern int http_get_demo(void *, ...); //用于打开网页获得数据
本质也是lwip。
2、W801的实时操作系统底层还是freertos,只是SDK对freertos进行了封装。。
3、SDK中自带了cjson,但是版本太低,最好替换为最新的。
4、一般显示汉字的部分都是GB2312编码,但是从yiketianqi.com/获取的json格式是UTF8的,所以修改了所有相关函数、字模为UTF8编码。
5、程序修改自SDK 的DEMO,还在整理中。
6、程序烧写及调试信息: