OpenHarmony 設(shè)備開發(fā)一WIFI連接
??想了解更多關(guān)于開源的內(nèi)容,請(qǐng)?jiān)L問:??
WIFI
wifi在我們的日常開發(fā)中必不可少,想要開發(fā)鴻蒙小車聯(lián)網(wǎng)操作,想要使開發(fā)板不再局限于終端串口操作,更離不開wifi,本篇文章將詳細(xì)介紹hi3861的wifi開發(fā)步驟及介紹。
本文主要介紹如何令hi3861開機(jī)自動(dòng)連接wifi。
代碼介紹
第一步先在applications\sample\wifi-iot\下路徑創(chuàng)建WIFI_demo業(yè)務(wù)代碼文件夾,在文件夾內(nèi)創(chuàng)建業(yè)務(wù)代碼和BUILD.gn編譯腳本。
業(yè)務(wù)代碼中的頭文件引用
hi_wifi_api.h和netifapi.h保存了一些wifi的API接口,ip_addr.h則是存放了wifi需使用到的一些宏定義。
ohos_init.h和cmsis_os2.h是應(yīng)用初始化和線程創(chuàng)建必不可少的頭文件,當(dāng)我們使用到線程和SYS_RUN()都要包括這兩個(gè)頭文件。
編譯腳本代碼
編譯腳本將目標(biāo)名為Xu_WIFI.c打包成名為Xu_WIFI_demo的靜態(tài)庫,隨后在app路徑下的BUILD.gn調(diào)用該庫,調(diào)用格式為"業(yè)務(wù)代碼文件夾名:靜態(tài)庫名"。
include_dirs為頭文件的存放地址,我們?cè)谑褂胾buntu開發(fā)時(shí),遇到不知道存放路徑的頭文件或者宏定義時(shí),可以使用指令grep 頭文件名 -* nR find . -name 頭文件名進(jìn)行搜索。
業(yè)務(wù)代碼文件夾內(nèi)的BUILD.gn代碼:
static_library("Xu_WIFI_demo") {
sources = [
"Xu_WIFI.c"
]
include_dirs = [
"http://utils/native/lite/include",
"http://kernel/liteos_m/components/cmsis/2.0",
"http://base/iot_hardware/peripheral/interfaces/kits",
"http://ohos_bundles/@ohos/device_soc_hisilicon/hi3861v100/sdk_liteos/include",
"http://ohos_bundles/@ohos/device_soc_hisilicon/hi3861v100/sdk_liteos/third_party/lwip_sack/include",
]
}
app路徑下的BUILD.gn代碼:
業(yè)務(wù)代碼
在業(yè)務(wù)代碼中主要由主函數(shù)、連接函數(shù)、線程函數(shù)三大函數(shù)構(gòu)成,在主函數(shù)中編寫WIFI初始化、WIFI掃描等操作,連接函數(shù)中可以確認(rèn)需要連接的WIFI的賬號(hào)密鑰以及加密方式。
主函數(shù)代碼:
WIFI開啟的流程:
- WIFI初始化。
- 使能注冊(cè)回調(diào)函數(shù)。
- 獲取網(wǎng)絡(luò)接口進(jìn)行IP的操作。
- 掃描WIFI。
- 獲取WIFI掃描結(jié)果。
- 連接WiFi。
static struct netif *g_lwip_netif = NULL;
int hi_wifi_start_sta(void)
{
int ret;
char ifname[WIFI_IFNAME_MAX_SIZE + 1] = {0};
int len = sizeof(ifname);
const unsigned char wifi_vap_res_num = APP_INIT_VAP_NUM;
const unsigned char wifi_user_res_num = APP_INIT_USR_NUM;
unsigned int num = WIFI_SCAN_AP_LIMIT;
// ret = hi_wifi_init(wifi_vap_res_num, wifi_user_res_num); // WiFi初始化
// if (ret != HISI_OK)
// {
// return -1;
// }
ret = hi_wifi_sta_start(ifname, &len); // sta初始化
if (ret != HISI_OK)
{
return -1;
}
/* 注冊(cè)回調(diào)函數(shù)接口*/
ret = hi_wifi_register_event_callback(wifi_wpa_event_cb);
if (ret != HISI_OK)
{
printf("register wifi event callback failed\n");
}
/* 獲取網(wǎng)絡(luò)接口進(jìn)行IP的操作 */
g_lwip_netif = netifapi_netif_find(ifname);
if (g_lwip_netif == NULL)
{
printf("%s: get netif failed\n", __FUNCTION__);
return -1;
}
/* 掃描WIFI */
ret = hi_wifi_sta_scan();
if (ret != HISI_OK)
{
return -1;
}
sleep(5); /* sleep 5s, waiting for scan result. */
//創(chuàng)建pst_results存放WiFi掃描結(jié)果
hi_wifi_ap_info *pst_results = malloc(sizeof(hi_wifi_ap_info) * WIFI_SCAN_AP_LIMIT);
if (pst_results == NULL)
{
return -1;
}
//獲取station掃描結(jié)果
ret = hi_wifi_sta_scan_results(pst_results, &num);
if (ret != HISI_OK)
{
free(pst_results);
return -1;
}
//打印WIFI掃描結(jié)果
for (unsigned int loop = 0; (loop < num) && (loop < WIFI_SCAN_AP_LIMIT); loop++)
{
printf("SSID: %s\n", pst_results[loop].ssid);
}
free(pst_results);
/* 進(jìn)行WIFI連接 */
ret = hi_wifi_start_connect();
if (ret != 0)
{
return -1;
}
return 0;
}
注冊(cè)回調(diào)函數(shù):
/* 清理IP,網(wǎng)關(guān)和子網(wǎng)掩碼 */
void hi_sta_reset_addr(struct netif *pst_lwip_netif)
{
ip4_addr_t st_gw;
ip4_addr_t st_ipaddr;
ip4_addr_t st_netmask;
if (pst_lwip_netif == NULL)
{
printf("hisi_reset_addr::Null param of netdev\r\n");
return;
}
IP4_ADDR(&st_gw, 0, 0, 0, 0);
IP4_ADDR(&st_ipaddr, 0, 0, 0, 0);
IP4_ADDR(&st_netmask, 0, 0, 0, 0);
netifapi_netif_set_addr(pst_lwip_netif, &st_ipaddr, &st_netmask, &st_gw);
}
//注冊(cè)回調(diào)函數(shù)
void wifi_wpa_event_cb(const hi_wifi_event *hisi_event)
{
if (hisi_event == NULL)
return;
switch (hisi_event->event)
{
case HI_WIFI_EVT_SCAN_DONE: //STA掃描完成
printf("WiFi: Scan results available\n");
break;
case HI_WIFI_EVT_CONNECTED:
printf("WiFi: Connected\n"); //wifi已連接
netifapi_dhcp_start(g_lwip_netif); //接口功能啟動(dòng)網(wǎng)絡(luò)接口的DHCP協(xié)商
break;
case HI_WIFI_EVT_DISCONNECTED:
printf("WiFi: Disconnected\n");
netifapi_dhcp_stop(g_lwip_netif); //關(guān)閉wifi
hi_sta_reset_addr(g_lwip_netif); //清理IP,網(wǎng)關(guān)和子網(wǎng)掩碼
break;
case HI_WIFI_EVT_WPS_TIMEOUT:
printf("WiFi: wps is timeout\n"); //WPS事件超時(shí)
break;
default:
break;
}
}
連接函數(shù):
連接的步驟:
- 創(chuàng)建hi_wifi_assoc_request結(jié)構(gòu)體變量。
- hi_wifi_assoc_request結(jié)構(gòu)體成員初始化:ssid,加密方式,密鑰。
- 使用hi_wifi_sta_connect連接WiFi,其中的實(shí)參為hi_wifi_assoc_request變量的地址。
int hi_wifi_start_connect(void)
{
int ret;
errno_t rc;
hi_wifi_assoc_request assoc_req = {0};
/* copy SSID to assoc_req */
//第三參數(shù)為ssid,第四參數(shù)為ssid數(shù)據(jù)長度
rc = memcpy_s(assoc_req.ssid, HI_WIFI_MAX_SSID_LEN + 1, "M20P", 4);
if (rc != EOK)
{
return -1;
}
//開放WIFI
// assoc_req.auth = HI_WIFI_SECURITY_OPEN;
// WIFI加密方式
assoc_req.auth = HI_WIFI_SECURITY_WPA2PSK;
/* WIFI密鑰 */
memcpy(assoc_req.key, "12345678", 8);
// WIFI連接
ret = hi_wifi_sta_connect(&assoc_req);
if (ret != HISI_OK)
{
return -1;
}
return 0;
}
線程任務(wù)創(chuàng)建:
我們需要?jiǎng)?chuàng)建線程時(shí),首先需要?jiǎng)?chuàng)建osThreadAttr_t結(jié)構(gòu)體變量,下一步便是初始化該結(jié)構(gòu)體變量,在此步初始化中的關(guān)鍵是線程名稱、任務(wù)棧大小和線程優(yōu)先級(jí),再下一步便使用osThreadNew()將該結(jié)構(gòu)體變量注冊(cè),最后SYS_RUN()運(yùn)行該線程。
//線程代碼段
void *hi_wifi_text(const char *arg)
{
printf("******************************\n");
hi_wifi_start_sta();
printf("******************************\n");
}
//創(chuàng)建線程
void wifi_demo(void)
{
osThreadAttr_t attr;
attr.name = "WIFITask"; //線程名稱
attr.attr_bits = 0U;
attr.cb_mem = NULL;
attr.cb_size = 0U;
attr.stack_mem = NULL;
attr.stack_size = 4096; //任務(wù)棧大小
attr.priority = 25; //線程優(yōu)先級(jí)
//第一參數(shù)為線程代碼段函數(shù)的名稱
if (osThreadNew((osThreadFunc_t)hi_wifi_text, NULL, &attr) == NULL)
{
printf("[LedExample] Falied to create LedTask!\n");
}
}
//運(yùn)行wifi_demo線程
SYS_RUN(wifi_demo);