1. 開發(fā)環(huán)境搭建
本次評(píng)測(cè)開發(fā)環(huán)境搭建在windows11的WSL2的Ubuntu20.04中,
(1) 在WSL的Ubuntu20.04下安裝必要的工具的.
- 安裝git:
sudo apt-get install git
- 安裝gcc編譯器套件:
sudo apt-get install build-essential
- 安裝bear,該工具用來(lái)生成編譯數(shù)據(jù)庫(kù)文件:compile_commands.json,可以實(shí)現(xiàn)編輯代碼時(shí)智能提示和代碼跳轉(zhuǎn).
sudo apt-get install bear
- 安裝ncurses庫(kù),使用make menuconfig配置工程時(shí)依賴該庫(kù).
sudo apt-get install libncurses5-dev
(2)安裝windows下必要的工具
我們編譯的固件要通過串口燒錄到XR806,由于WSL2下不能直接使用windows的串口,所以需要在windows下使用工具 usbipd共享串口給WSL2使用,
(3)搭建XR806編譯開發(fā)環(huán)境
需要注意的是文章中提供的編譯工具鏈gcc-arm-none-eabi-8-2019-q3-update下載鏈接無(wú)效,
2. 創(chuàng)建工程
我們?cè)诮K端中進(jìn)入工程跟目錄,按如下步驟來(lái)配置工程和編譯代碼生成鏡像:
# 復(fù)制默認(rèn)配置文件到頂層目錄(不切換工程可不要此步驟)
$ make PRJ=demo/wifi_sta defconfig
# 檢查SDK 基礎(chǔ)配置,如工程名、芯片型號(hào)、高頻晶振、板級(jí)配置是否正確
$ make menuconfig
# 清理,切換工程時(shí)需要
$ make build_clean
# 編譯代碼并生成鏡像文件,生成的鏡像文件為“out/xr_system.img”
$ bear make build -j 12
依次執(zhí)行上述命令后,在工程根目錄執(zhí)行如下命令,使用vscode打開工程code .
在vscode中打開工程目錄后,敲擊F1鍵,彈出如下選擇項(xiàng),我們選擇C/C++:編輯配置(UI)
在編譯器路徑輸入框中輸入XR806交叉編譯器完整路徑,如下圖所示:
在高級(jí)設(shè)置下的編譯命令輸入框中輸入編譯數(shù)據(jù)庫(kù)文件compile_commands.json的路徑,如下圖所示:
3. 編輯工程代碼
想要從心知天氣網(wǎng)獲取天氣預(yù)報(bào),首先需要注冊(cè)該網(wǎng)站賬號(hào). 注冊(cè)賬號(hào)并登陸,打開獲取天氣預(yù)報(bào)相關(guān)的API文檔頁(yè)
其中參數(shù)"your_api_key"是你獲取天氣預(yù)報(bào)信息的API密鑰,該API密鑰可以從心知天氣網(wǎng)主頁(yè)進(jìn)入控制臺(tái)頁(yè)面,然后點(diǎn)擊左側(cè)的"免費(fèi)版",即可看到自己的私鑰,該私鑰即為API 密鑰,如下圖所示:
接下來(lái)我們編寫代碼實(shí)現(xiàn)通過http請(qǐng)求從心知天氣網(wǎng)獲取未來(lái)3天的天氣信息.
首先在main.c中添加必要的頭文件:
#include < stdio.h > #include < string.h > #include "kernel/os/os.h" #include "net/wlan/wlan.h" #include "net/wlan/wlan_defs.h" #include "common/framework/net_ctrl.h" #include "common/framework/platform_init.h" #include < errno.h > #include "lwip/err.h" #include "lwip/sockets.h" #include "lwip/sys.h" #include "lwip/inet.h" #include "lwip/netdb.h" #include "sys/select.h" #include "cjson/cJSON.h"
然后定義關(guān)于天氣信息的結(jié)構(gòu)體類型:
/* 天氣數(shù)據(jù)結(jié)構(gòu)體 */ typedef struct tagWeather { /* 實(shí)況天氣數(shù)據(jù) */ char id[32]; //id char name[32]; //地名 char country[32]; //國(guó)家 char path[32]; //完整地名路徑 char timezone[32]; //時(shí)區(qū) char timezone_offset[32]; //時(shí)差 char text[32]; //天氣預(yù)報(bào)文字 char code[32]; //天氣預(yù)報(bào)代碼 char temperature[32]; //氣溫 char last_update[32]; //最后一次更新的時(shí)間 /* 今天、明天、后天天氣數(shù)據(jù) */ char date[3][32]; //日期 char text_day[3][64]; //白天天氣現(xiàn)象文字 char code_day[3][32]; //白天天氣現(xiàn)象代碼 char code_night[3][64]; //晚間天氣現(xiàn)象代碼 char high[3][32]; //最高溫 char low[3][32]; //最低溫 char wind_direction[3][64]; //風(fēng)向 char wind_speed[3][32]; //風(fēng)速,單位km/h(當(dāng)unit=c時(shí)) char wind_scale[3][32]; //風(fēng)力等級(jí) } Weather_T;
再定義通過http的GET請(qǐng)求方式獲取天氣預(yù)報(bào)的請(qǐng)求頭部:
#define WEB_SERVER "api.seniverse.com" // 天氣預(yù)報(bào)網(wǎng)服務(wù)器地址 #define WEB_PORT "80" // 天氣預(yù)報(bào)網(wǎng)服務(wù)器端口號(hào) #define CONFIG_API_KEY "xxxxxxxxxxxxxx" // 你的API密鑰,從心知天氣網(wǎng)控制臺(tái)頁(yè)面獲取 /* 獲取天氣預(yù)報(bào)信息的http請(qǐng)求頭部 */ #define GET_REQUEST_PACKAGE "GET https://api.seniverse.com/v3/weather/daily.json?key=" CONFIG_API_KEY "&location=%s&language=zh-Hans&unit=crnrn" #define HTTPC_DEMO_THREAD_STACK_SIZE (8 * 1024) /* 任務(wù)棧大小 */
定義WiFi的ssid和password:
char *sta_ssid = "xxxxxx"; // 你要連接的WiFi名 char *sta_psk = "xxxxxxxx"; // 你要連接的WiFi密碼 char httpc_response_buf[2048]; //用于保存獲取到的天氣信息的原始數(shù)據(jù) int write_idx = 0; // 寫數(shù)據(jù)到httpc_response_buf的數(shù)組下標(biāo) static OS_Thread_t httpc_demo_thread; // 獲取天氣的線程ID
編寫WiFi聯(lián)網(wǎng)初始化函數(shù):
void sta_start(void) { /* switch to sta mode */ net_switch_mode(WLAN_MODE_STA); #if STA_MODE_USE_WPA2_ONLY /* set ssid and password to wlan, only use WPA2 mode to connect AP. */ wlan_sta_config((uint8_t *)sta_ssid, strlen(sta_ssid), (uint8_t *)sta_psk, 0); #else /* set ssid and password to wlan, use WPA2|WPA3 compatible mode to connect AP. */ wlan_sta_set((uint8_t *)sta_ssid, strlen(sta_ssid), (uint8_t *)sta_psk); #endif /* start scan and connect to ap automatically */ wlan_sta_enable(); }
在mian函數(shù)中添加如下代碼
int main(void) { observer_base *net_ob; platform_init(); /* create an observer to monitor the net work state */ net_ob = sys_callback_observer_create(CTRL_MSG_TYPE_NETWORK, NET_CTRL_MSG_ALL, net_cb, NULL); if (net_ob == NULL) { return -1; } if (sys_ctrl_attach(net_ob) != 0) { return -1; } sta_start(); return 0; }
其中,函數(shù)sys_callback_observer_create創(chuàng)建一個(gè)事件監(jiān)聽器,當(dāng)函數(shù)第1個(gè)參數(shù)CTRL_MSG_TYPE_NETWORK和第2個(gè)參數(shù)NET_CTRL_MSG_ALL所指定的事件發(fā)生時(shí)自動(dòng)調(diào)用回調(diào)函數(shù)net_cb,此處表示所有的網(wǎng)絡(luò)事件發(fā)生時(shí)均會(huì)調(diào)用回調(diào)函數(shù)net_cb,net_cb定義如下:
static void net_cb(uint32_t event, uint32_t data, void *arg) { uint16_t type = EVENT_SUBTYPE(event); switch (type) { case NET_CTRL_MSG_NETWORK_UP: // WiFi sta連接AP成功并自動(dòng)分配了ip地址 { /* 打印本機(jī)的IP地址,網(wǎng)關(guān),子網(wǎng)掩碼 */ struct netif *nif = wlan_netif_get(WLAN_MODE_STA); while (!NET_IS_IP4_VALID(nif)) { OS_MSleep(100); } printf("local ip: %sn", ipaddr_ntoa(&nif- >ip_addr)); printf("gw: %sn", ipaddr_ntoa(&nif- >gw)); printf("netmask: %sn", ipaddr_ntoa(&nif- >netmask)); } /*創(chuàng)建線程,通過http請(qǐng)求獲取天氣預(yù)報(bào)信息*/ if (!OS_ThreadIsValid(&httpc_demo_thread)) { OS_ThreadCreate(&httpc_demo_thread, "httpc_demo_thread", httpc_demo_fun, (void *)NULL, OS_THREAD_PRIO_APP, HTTPC_DEMO_THREAD_STACK_SIZE); } break; case NET_CTRL_MSG_NETWORK_DOWN: //WiFi連接斷開事件 break; default: break; } }
httpc_demo_fun函數(shù)的定義如下:
static void httpc_demo_fun(void *arg) { http_get_weather("beijing"); // 獲取天氣預(yù)報(bào)信息結(jié)束后,刪除本線程 OS_ThreadDelete(&httpc_demo_thread); }
其中http_get_weather函數(shù)的參數(shù)即為想要獲取天氣預(yù)報(bào)的城市的漢語(yǔ)拼音名,定義如下:
static void http_get_weather(char *city) { int32_t ret; char request_head[sizeof(REQUEST) + 64]; const struct addrinfo hints = { .ai_family = AF_INET, .ai_socktype = SOCK_STREAM, }; struct addrinfo *res; struct in_addr *addr; int s, r; Weather_T weather_data = {0}; bzero(httpc_response_buf, sizeof(httpc_response_buf)); /* 通過服務(wù)器域名和端口獲取服務(wù)器的IP地址相關(guān)信息 */ ret = getaddrinfo(WEB_SERVER, WEB_PORT, &hints, &res); if (ret != 0 || res == NULL) { printf("DNS lookup failed ret=%d res=%pn", ret, res); return; } // Note: inet_ntoa is non-reentrant, look at ipaddr_ntoa_r for "real" code */ addr = &((struct sockaddr_in *)res- >ai_addr)- >sin_addr; printf("DNS lookup succeeded. IP=%sn", inet_ntoa(*addr)); /* 創(chuàng)建soocket */ s = socket(res- >ai_family, res- >ai_socktype, 0); if(s < 0) { printf("... Failed to allocate socket.n"); freeaddrinfo(res); return; } printf("... allocated socketn"); /* 使用第1步獲取的服務(wù)器IP地址連接服務(wù)器 */ if(connect(s, res- >ai_addr, res- >ai_addrlen) != 0) { printf("... socket connect failed errno=%dn", errno); close(s); freeaddrinfo(res); return; } printf("... connectedn"); freeaddrinfo(res); /* 使用城市名生成完整的http的GET請(qǐng)求頭部并發(fā)送到服務(wù)器*/ snprintf(request_head, sizeof(request_head), GET_REQUEST_PACKAGE, city); if (write(s, request_head, strlen(request_head)) < 0) { printf("... socket send failedn"); close(s); return; } printf("... socket send successn"); /* 讀取服務(wù)器返回的應(yīng)答數(shù)據(jù) */ /* Read HTTP response */ do { r = read(s, &httpc_response_buf[write_idx], sizeof(httpc_response_buf) - write_idx -1); if (r > 0) { write_idx += r; } } while(r > 0 && write_idx < (sizeof(httpc_response_buf) - 1)); printf("... done reading from socket. Last read return=%d write_idx=%u errno=%d.n", r, write_idx, errno); /* 打印服務(wù)器返回的數(shù)據(jù) */ for (int i = 0; i < write_idx; ++i) { putchar(httpc_response_buf[i]); } puts(""); /* 解析天氣預(yù)報(bào)數(shù)據(jù) */ ret = cJSON_DailyWeatherParse(httpc_response_buf, &weather_data); if (ret == 0) { /* 格式化打印天氣預(yù)報(bào)信息 */ DisplayWeather(&weather_data); } close(s); }
由于服務(wù)器返回的天氣預(yù)報(bào)數(shù)據(jù)為json字符串, 我們編寫函數(shù)cJSON_DailyWeatherParse解析天氣預(yù)報(bào)json數(shù)據(jù)并保存到結(jié)構(gòu)體變量weather_data中,cJSON_DailyWeatherParse函數(shù)和DisplayWeather函數(shù)的定義如下:
static int cJSON_DailyWeatherParse(char *JSON, Weather_T *result) { cJSON *json,*arrayItem,*object,*subobject,*item,*sub_child_object,*child_Item; json = cJSON_Parse(JSON); //解析JSON數(shù)據(jù)包 if(json == NULL) //檢測(cè)JSON數(shù)據(jù)包是否存在語(yǔ)法上的錯(cuò)誤,返回NULL表示數(shù)據(jù)包無(wú)效 { printf("Error before: [%s]n",cJSON_GetErrorPtr()); //打印數(shù)據(jù)包語(yǔ)法錯(cuò)誤的位置 return 1; } else { if ((arrayItem = cJSON_GetObjectItem(json,"results")) != NULL) //匹配字符串"results",獲取數(shù)組內(nèi)容 { // int size = cJSON_GetArraySize(arrayItem); //獲取數(shù)組中對(duì)象個(gè)數(shù) #if DEBUG printf("Get Array Size: size=%dn",size); #endif if((object = cJSON_GetArrayItem(arrayItem,0)) != NULL)//獲取父對(duì)象內(nèi)容 { /* 匹配子對(duì)象1------結(jié)構(gòu)體location */ if((subobject = cJSON_GetObjectItem(object,"location")) != NULL) { if((item = cJSON_GetObjectItem(subobject,"name")) != NULL) //匹配子對(duì)象1成員"name" { memcpy(result- >name, item- >valuestring,strlen(item- >valuestring)); // 保存數(shù)據(jù)供外部調(diào)用 } } /* 匹配子對(duì)象2------數(shù)組daily */ if((subobject = cJSON_GetObjectItem(object,"daily")) != NULL) { int sub_array_size = cJSON_GetArraySize(subobject); #if DEBUG printf("Get Sub Array Size: sub_array_size=%dn",sub_array_size); #endif for(int i = 0; i < sub_array_size; i++) { if((sub_child_object = cJSON_GetArrayItem(subobject,i))!=NULL) { // 匹配日期 if((child_Item = cJSON_GetObjectItem(sub_child_object,"date")) != NULL) { memcpy(result- >date[i], child_Item- >valuestring,strlen(child_Item- >valuestring)); // 保存數(shù)據(jù) } // 匹配白天天氣現(xiàn)象文字 if((child_Item = cJSON_GetObjectItem(sub_child_object,"text_day")) != NULL) { memcpy(result- >text_day[i], child_Item- >valuestring,strlen(child_Item- >valuestring)); // 保存數(shù)據(jù) } // 匹配白天天氣現(xiàn)象代碼 if((child_Item = cJSON_GetObjectItem(sub_child_object,"code_day")) != NULL) { memcpy(result- >code_day[i], child_Item- >valuestring,strlen(child_Item- >valuestring)); // 保存數(shù)據(jù) } // 匹配夜間天氣現(xiàn)象代碼 if((child_Item = cJSON_GetObjectItem(sub_child_object,"code_night")) != NULL) { memcpy(result- >code_night[i], child_Item- >valuestring,strlen(child_Item- >valuestring)); // 保存數(shù)據(jù) } // 匹配最高溫度 if((child_Item = cJSON_GetObjectItem(sub_child_object,"high")) != NULL) { memcpy(result- >high[i], child_Item- >valuestring,strlen(child_Item- >valuestring)); //保存數(shù)據(jù) } // 匹配最低溫度 if((child_Item = cJSON_GetObjectItem(sub_child_object,"low")) != NULL) { memcpy(result- >low[i], child_Item- >valuestring,strlen(child_Item- >valuestring)); // 保存數(shù)據(jù) } // 匹配風(fēng)向 if((child_Item = cJSON_GetObjectItem(sub_child_object,"wind_direction")) != NULL) { memcpy(result- >wind_direction[i],child_Item- >valuestring,strlen(child_Item- >valuestring)); //保存數(shù)據(jù) } // 匹配風(fēng)速,單位km/h(當(dāng)unit=c時(shí)) if((child_Item = cJSON_GetObjectItem(sub_child_object,"wind_speed")) != NULL) { memcpy(result- >wind_speed[i], child_Item- >valuestring,strlen(child_Item- >valuestring)); // 保存數(shù)據(jù) } // 匹配風(fēng)力等級(jí) if((child_Item = cJSON_GetObjectItem(sub_child_object,"wind_scale")) != NULL) { memcpy(result- >wind_scale[i], child_Item- >valuestring,strlen(child_Item- >valuestring)); // 保存數(shù)據(jù) } } } } /* 匹配子對(duì)象3------最后一次更新的時(shí)間 */ if((subobject = cJSON_GetObjectItem(object,"last_update")) != NULL) { //printf("%s:%sn",subobject- >string,subobject- >valuestring); } } } } cJSON_Delete(json); //釋放cJSON_Parse()分配出來(lái)的內(nèi)存空間 return 0; } /******************************************************************************************************* ** 函數(shù): DisplayWeather,顯示天氣數(shù)據(jù) **------------------------------------------------------------------------------------------------------ ** 參數(shù): weather_data:天氣數(shù)據(jù) ** 返回: void ********************************************************************************************************/ static void DisplayWeather(Weather_T *weather_data) { printf("===========%s近三天的天氣情況如下===========n",weather_data- >name); printf("【%s】n",weather_data- >date[0]); printf("天氣:%sn",weather_data- >text_day[0]); printf("最高溫:%s℃n",weather_data- >high[0]); printf("最低溫:%s℃n",weather_data- >low[0]); printf("風(fēng)向:%sn",weather_data- >wind_direction[0]); printf("風(fēng)速:%skm/hn",weather_data- >wind_speed[0]); printf("風(fēng)力等級(jí):%sn",weather_data- >wind_scale[0]); printf("n"); printf("【%s】n",weather_data- >date[1]); printf("天氣:%sn",weather_data- >text_day[1]); printf("最高溫:%s℃n",weather_data- >high[1]); printf("最低溫:%s℃n",weather_data- >low[1]); printf("風(fēng)向:%sn",weather_data- >wind_direction[1]); printf("風(fēng)速:%skm/hn",weather_data- >wind_speed[1]); printf("風(fēng)力等級(jí):%sn",weather_data- >wind_scale[1]); printf("n"); printf("【%s】n",weather_data- >date[2]); printf("天氣:%sn",weather_data- >text_day[2]); printf("最高溫:%s℃n",weather_data- >high[2]); printf("最低溫:%s℃n",weather_data- >low[2]); printf("風(fēng)向:%sn",weather_data- >wind_direction[2]); printf("風(fēng)速:%skm/hn",weather_data- >wind_speed[2]); printf("風(fēng)力等級(jí):%sn",weather_data- >wind_scale[2]); }
編譯工程
bear make build -j 8
燒錄鏡像到xr806
首先使用USB線將開發(fā)板連上電腦,可能需要重新安裝CP2102驅(qū)動(dòng),在Windows中打開powershell,輸入如下命令:PS C:Users30751Desktop > usbipd wsl list BUSID VID:PID DEVICE STATE 2-1 10c4:ea60 Silicon Labs CP210x USB to UART Bridge (COM3) Not attached 2-3 248a:8367 USB 輸入設(shè)備 Not attached 2-6 0c45:6a1b Integrated Webcam Not attached 2-10 8087:0026 英特爾(R) 無(wú)線 Bluetooth(R) Not attached
我們可以看到開發(fā)板連接的USB端口的的BUSID為2-1,接著使用如下命令將該USB串口共享給WSL:
PS C:Users30751Desktop > usbipd wsl attach --busid 2-1 usbipd: info: Using default WSL distribution 'Ubuntu-20.04'; specify the '--distribution' option to select a different one.
接下來(lái)我們?cè)赨buntu終端中進(jìn)入工程源碼目錄下的tools目錄下,開啟固件燒錄USB串口的讀寫權(quán)限:
sudo chmod 666 /dev/ttyUSB0
使用如下命令燒錄鏡像到xr806./phoenixMC
燒錄成功信息如下:我們?cè)俅卧赪indows中打開powershell,輸入如下命令將開發(fā)板連接到windows:
usbipd wsl detach --busid 2-1
我們?cè)趙indows中打開終端軟件Tera Term,連上開發(fā)板串口,復(fù)位開發(fā)板將會(huì)看到如下信息:use default flash chip mJedec 0x0 [FD I]: mode: 0x10, freq: 96000000Hz, drv: 0 [FD I]: jedec: 0x0, suspend_support: 1 mode select:e wlan information =================================================== firmware: version : R0-XR_C07.08.52.67_ULP_R_02.132 Jan 10 2023 19:14:11-Y02.132 buffer : 8 driver: version : XR_V02.06.10 mac address: in use : 8c:6d:08:3d:14:01 in use : 8c:6d:08:3d:14:02 ==================================================================== wlan mode:a platform information =============================================== XR806 SDK v1.2.2 Oct 21 2023 23:46:57 62800400 heap space [0x217098, 0x24bc00), size 215912 cpu clock 160000000 Hz HF clock 40000000 Hz sdk option: XIP : enable INT LF OSC : enable INT LDO : select INT LDO / EXT PWR: enable SIP flash : enable mac address: efuse : 80:74:84:05:b9:ca in use : 8c:6d:08:3d:14:01 ==================================================================== [net INF] no need to switch wlan mode 0 [net INF] msg < wlan scan success > en1: Trying to associate with 8c:ab:8e:fd:c3:58 (SSID='302' freq=2412 MHz) en1: Associated with 8c:ab:8e:fd:c3:58 en1: WPA: Key negotiation completed with 8c:ab:8e:fd:c3:58 [PTK=CCMP GTK=TKIP] en1: CTRL-EVENT-CONNECTED - Connection to 8c:ab:8e:fd:c3:58 completed [id=0 id_str=] [net INF] msg < wlan connected > [net INF] netif is link up [net INF] start DHCP... WAR drop=1135, fctl=0x00d0. [net INF] netif (IPv4) is up [net INF] address: 192.168.2.107 [net INF] gateway: 192.168.2.1 [net INF] netmask: 255.255.255.0 [net INF] msg < network up > local ip: 192.168.2.107 gw: 192.168.2.1 netmask: 255.255.255.0 DNS lookup succeeded. IP=116.62.81.138 ... allocated socket ... connected ... socket send success ... done reading from socket. Last read return=0 write_idx=995 errno=107. {"results":[{"location":{"id":"WX4FBXXFKE4F","name":"北京","country":"CN","path":"北京,北京,中國(guó)","timezone":"Asia/Shanghai","timezone_offset":"+08:00"},"daily":[{"date":"2023-10-22","text_day":"晴","code_day":"0","text_night":"晴","code_night":"1","high":"21","low":"6","rainfall":"0.00","precip":"0.00","wind_direction":"無(wú)持續(xù)風(fēng)向","wind_direction_degree":"","wind_speed":"8.4","wind_scale":"2","humidity":"61"},{"date":"2023-10-23","text_day":"晴","code_day":"0","text_night":"晴","code_night":"1","high":"21","low":"7","rainfall":"0.00","precip":"0.00","wind_direction":"無(wú)持續(xù)風(fēng)向","wind_direction_degree":"","wind_speed":"3.0","wind_scale":"1","humidity":"75"},{"date":"2023-10-24","text_day":"晴","code_day":"0","text_night":"晴","code_night":"1","high":"23","low":"9","rainfall":"0.00","precip":"0.00","wind_direction":"無(wú)持續(xù)風(fēng)向","wind_direction_degree":"","wind_speed":"3.0","wind_scale":"1","humidity":"75"}],"last_update":"2023-10-20T08:00:00+08:00"}]} ===========北京近三天的天氣情況如下=========== 【2023-10-22】 天氣:晴 最高溫:21℃ 最低溫:6℃ 風(fēng)向:無(wú)持續(xù)風(fēng)向 風(fēng)速:8.4km/h 風(fēng)力等級(jí):2 【2023-10-23】 天氣:晴 最高溫:21℃ 最低溫:7℃ 風(fēng)向:無(wú)持續(xù)風(fēng)向 風(fēng)速:3.0km/h 風(fēng)力等級(jí):1 【2023-10-24】 天氣:晴 最高溫:23℃ 最低溫:9℃ 風(fēng)向:無(wú)持續(xù)風(fēng)向 風(fēng)速:3.0km/h 風(fēng)力等級(jí):1
可以看到我們已經(jīng)成功獲取了北京的未來(lái)三天的天氣情況.
4. 總結(jié)
通過本次開發(fā)板評(píng)測(cè),掌握了XR806的WiFi相關(guān)API的使用,系統(tǒng)事件監(jiān)聽API的使用掌,握了sokect網(wǎng)絡(luò)編程相關(guān)知識(shí),掌握了cJSON的使用.
-
回調(diào)函數(shù)
+關(guān)注
關(guān)注
0文章
87瀏覽量
11528 -
CP2102
+關(guān)注
關(guān)注
2文章
20瀏覽量
12410 -
Ubuntu系統(tǒng)
+關(guān)注
關(guān)注
0文章
85瀏覽量
3898 -
gcc編譯器
+關(guān)注
關(guān)注
0文章
78瀏覽量
3346 -
vscode
+關(guān)注
關(guān)注
1文章
154瀏覽量
7649
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論