看了小安派(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 handle
pHTTP = HTTPClientOpenRequest(0);
if(!pHTTP)
{
nRetCode = HTTP_CLIENT_ERROR_INVALID_HANDLE;
break;
}
// Set the Verb
nRetCode = HTTPClientSetVerb(pHTTP, verb);
if(nRetCode != HTTP_CLIENT_SUCCESS)
{
break;
}
#if TLS_CONFIG_HTTP_CLIENT_AUTH
// Set authentication
if(ClientParams.AuthType != AuthSchemaNone)
{
if((nRetCode = HTTPClientSetAuth(pHTTP, ClientParams.AuthType, NULL)) != HTTP_CLIENT_SUCCESS)
{
break;
}
// Set authentication
if((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 server
if(ClientParams.UseProxy == TRUE)
{
if((nRetCode = HTTPClientSetProxy(pHTTP, ClientParams.ProxyHost, ClientParams.ProxyPort, NULL, NULL)) != HTTP_CLIENT_SUCCESS)
{
break;
}
}
#endif //TLS_CONFIG_HTTP_CLIENT_PROXY
if((nRetCode = HTTPClientSendRequest(pHTTP, ClientParams.Uri, pSndData, nSndDataLen, verb == VerbPost || verb == VerbPut, 0, 0)) != HTTP_CLIENT_SUCCESS)
{
break;
}
// Retrieve the the headers and analyze them
if((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 code
while(nRetCode == HTTP_CLIENT_SUCCESS || nRetCode != HTTP_CLIENT_EOS)
{
// Set the size of our buffer
nSize = HTTP_CLIENT_BUFFER_SIZE;
// Get the data
nRetCode = 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 once
tls_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、程序烧写及调试信息: