一、主要完成的工作
1、建立TASK
INT32 main(VOID)
{
/* system Init */
SystemInit();
OSTaskCreate(TestAppMain, NULL, &sAppStartTaskStack[NST_APP_START_TASK_STK_SIZE -1], NST_APP_TASK_START_PRIO);
OSStart();
return 1;
}
2、application test task
VOID TestAppMain(VOID * pParam)
{
demo_gpio_init(); //初始化LCD GPIO
InitLCD(); //初始化屏幕
clrScr(VGA_BLACK); //清屏
GUI_Write16CnCharMatrix(0,160,"初始化...... ",VGA_BLUE,VGA_BLACK);
pLinkUpSem = OSSemCreate(0);
InfSysEvtCBSet(AppEvtCallBack);
InfLoadDefaultParam();
sys_thread_new("weatherThread", weatherThread, NULL, NST_TEST_APP_TASK_STK_SIZE, TCPIP_THREAD_PRIO + 4);
while (1)
{ /* Task body, always written as an infinite loop. */
OSTimeDly(20);
DBGPRINT_LWIP(DEBUG_INFO, "TestApp RxDataCnt=%d, SendDataCnt=%d.\n", RxDataCnt, SendDataCnt);
}
}
3、void weatherThread(void *arg)
void weatherThread(void *arg)
{
char* buff,*http_data;
DBGPRINT(DEBUG_TRACE, " ********************** weatherThread ********************* \n\r");
connectWifi(); //连接WIFI
buff=TestWeatherApi(); //从网页API获得天气数据
printf("%s\r\n", buff);
http_data=https_get_data(buff); //获得JSON部分
mem_free(buff);
printf("[http_data]:%s\r\n", http_data);
extract_all_from_json(http_data); //解析JSON数据
mem_free(http_data);
//LCD显示
GUI_Write16CnCharMatrix(5,20,"日期:",VGA_WHITE,VGA_BLACK);
GUI_Write16CnCharMatrix(53,20,city_weather.date,VGA_BLUE,VGA_BLACK);
GUI_Write16CnCharMatrix(5,60,"城市:",VGA_WHITE,VGA_BLACK);
GUI_Write16CnCharMatrix(53,60,city_weather.city,VGA_BLUE,VGA_BLACK);
GUI_Write16CnCharMatrix(5,100,"温度:",VGA_WHITE,VGA_BLACK);
GUI_Write16CnCharMatrix(53,100,city_weather.tem,VGA_BLUE,VGA_BLACK);
while(1)
{
OSTimeDly(500);
}
}
4、void connectWifi(void)
void connectWifi(void)
{
UINT8 Err;
InfWiFiStop();
OSTimeDly(10);
InfNetModeSet(PARAM_NET_MODE_STA_BSS);
InfAuthModeSet(PARAM_AUTH_MODE_WPA2PSK);
//此处根据实际修改SSID/PASSWORD
InfSsidSet("SSID",4); /* set ssid */
InfKeySet(0, "PASSWORD",8); /* set pw */
InfEncModeSet(PARAM_ENC_MODE_AUTO);
InfConTryTimesSet(0); /* set trytime */
InfWiFiStart();
//Waiting for connect success
OSSemPend(pLinkUpSem, 0, &Err);
}
5、char* TestWeatherApi(void)
#define HTTP_HOST "v1.yiketianqi.com"
#define HTTP_URL "api?unescape=1&version=v61&appid=此处替换自己的ID&appsecret=此处替换自己的key"
#define HOST_PORT "80"
static const char* REQUEST = "GET " "/%s" " HTTP/1.1\r\n"
"Host: " "%s" ":" HOST_PORT "\r\n"
"User-Agent: AiPi-DSL_Dashboard\r\n"
"\r\n";
char* TestWeatherApi(void)
{
char* https_request_handle = mem_malloc(512);
char *recv_data;
int sock;
UINT32 TargetIp;
struct sockaddr_in server_addr;
ip_addr_t hostip;
netconn_gethostbyname(HTTP_HOST, &hostip);
DBGPRINT_LWIP(DEBUG_TRACE, "HTTP_HOST:%s,IP:%d\n",HTTP_HOST,hostip.addr);
TargetIp =hostip.addr;
DBGPRINT_LWIP(DEBUG_TRACE, "TargetIp:%d\n",TargetIp);
/* 分配用于存放接收数据的缓冲 */
recv_data = mem_malloc(1024*4);
if (recv_data == NULL)
{
DBGPRINT_LWIP(DEBUG_ERROR, "TCP Client memory ERR\n");
return 0;
}
/* 一、创建一个socket,类型是SOCKET_STREAM,TCP类型 */
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
/* 创建socket失败 */
DBGPRINT_LWIP(DEBUG_ERROR, "TCP Client Socket error\n");
/* 释放接收缓冲 */
mem_free(recv_data);
return 0;
}
/* 初始化预连接的服务端地址 */
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(atoi(HOST_PORT));
server_addr.sin_addr.s_addr= TargetIp;
memset(&(server_addr.sin_zero), 0, sizeof(server_addr.sin_zero));
/* 二、连接到服务端 */
if (connect(sock, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1)
{
/* 连接失败 */
DBGPRINT_LWIP(DEBUG_TRACE, "TCP Client connect error !");
lwip_close(sock);
///*释放接收缓冲 */
mem_free(recv_data);
return 0;
//OSTimeDly(2000);
}
else
{
DBGPRINT_LWIP(DEBUG_TRACE, "TCP Client connect OK!\n");
}
memset(https_request_handle, 0, 256);
sprintf(https_request_handle, REQUEST, HTTP_URL, HTTP_HOST);
/* 三、http请求 */
if(write(sock, https_request_handle, strlen(https_request_handle))<0)
{
DBGPRINT_LWIP(DEBUG_TRACE, "http write error !");
close(sock);
}
/* 四、读http返回结果 */
read(sock, recv_data, 1024*4);
shutdown(sock, SHUT_RDWR);
close(sock);
mem_free(https_request_handle);
return recv_data;
}
6、static char* https_get_data(const char* https_request_data)
static char* https_get_data(const char* https_request_data)
{
char* request_data = https_request_data;
static char* https_data;
char* request_value;
size_t i;
https_data = mem_malloc(1024*3);
memset(https_data, 0, 1024*3);
request_data += 2;
request_value = strtok(request_data, "\n");
for (i = 0; i < 15; i++)
{
if (i==14) strcpy(https_data, request_value);
memset(request_value, 0, strlen(request_value));
request_value = strtok(NULL, "\n");
}
return https_data;
}
7、json解析
void extract_item_from_json(const char *json_str,char *itemname,char *target)
{
char *start = strstr(json_str, itemname); // 查找"cityEn":"
char *end;
size_t len=20;
char item[20]; // +1 for null terminator
if (start != NULL) {
start += strlen(itemname); // 跳过itemname
end = strchr(start, '"'); // 查找下一个双引号
if (end != NULL) {
// 提取
len = end - start;
strncpy(item, start, len);
item[len] = '\0'; // 添加字符串结束符
printf("Item: %s\n", item);
strncpy(target, item, len);
target[len] = '\0'; // 添加字符串结束符
}
} else {
printf("Item[%s] not found in the JSON string.\n",itemname);
}
}
void extract_all_from_json(const char *json_str)
{
extract_item_from_json(json_str,"\"cityEn\":\"",city_weather.city);
extract_item_from_json(json_str,"\"tem\":\"",city_weather.tem);
extract_item_from_json(json_str,"\"date\":\"",city_weather.date);
}
二、说明
1、NL6621 SDK二次开发,还是用KEIL4吧,KEIL5编译太慢了。
2、没用CJSON,不是不想用,尝试了好长时间还是用不了CJSON,最后JSON自己解析了。
3、编译的bin文件,不要超过192k,否则没法烧录,编译也会失败。
4、scatter_loader.scat没有为适应NuDevTool ver1.11.0.exe修改,需要用bootTool.exe或bootTool_Ack_0822.exe烧录。
; 0x10100-0x40000 for download SRAM FW(including 32KB for customer), interrupt vector locate in 0x10100
LOAD_REGION 0x00010100 0x0002FF00 { ; load region size_region
ROM 0x00010100 0x0002FF00 { ; load address = execution address
*.o (RESET, +First) ; interrupt vector table, do not change it
*(InRoot$$Sections)
.ANY (+RO)
}
5、需要用NuDevTool ver1.11.0.exe烧录工具将字库gb2312_80.bin烧录到0xB0000,不烧录字库运行不了。
#define FLASH_ADDR_BASE 0xB0000
6、源码链接:
链接:https://pan.baidu.com/s/1KQwfkdXDj2R9A_3XGqbgWA?pwd=cmpn
提取码:cmpn