Hi3516如何連接WiFi(三)
51CTO和華為官方合作共建的鴻蒙技術(shù)社區(qū)
小伙伴們大家好,上一篇(Hi3516如何連接Wifi(二))介紹了用程序啟動(dòng)wap_supplicant,也就是Wifi的Daemon。下一步就是如何向Daemon發(fā)信息,我們可以參考//applications/sample/camera/communication/wpa_cli,他實(shí)現(xiàn)了連接Daemon、掃描熱點(diǎn)、連接熱點(diǎn)等功能。
我們打開wpa_cli_sample.c文件,核心功能在于這幾個(gè)函數(shù):
- InitControlInterface:初始化
- TestScan:掃描周圍熱點(diǎn)
- TestNetworkConfig:連接到指定熱點(diǎn)
首先看InitControlInterface函數(shù),他先調(diào)用了wpa_ctrl_open函數(shù),獲取了用于發(fā)送命令的控制接口g_ctrlConn,是一個(gè)類型為struct wpa_ctrl的結(jié)構(gòu)體。又調(diào)用一遍wpa_ctrl_open打開了一個(gè)用于事件監(jiān)控的控制接口g_monitorConn。然后啟動(dòng)了事件監(jiān)控的線程執(zhí)行MonitorTask函數(shù),這個(gè)監(jiān)控線程不是必須,可以省略。
- int InitControlInterface()
- {
- g_ctrlConn = wpa_ctrl_open(WPA_IFACE_NAME); // create control interface for send cmd
- g_monitorConn = wpa_ctrl_open(WPA_IFACE_NAME); // create control interface for event monitor
- if (!g_ctrlConn || !g_monitorConn) {
- SAMPLE_ERROR("open wpa control interface failed.");
- return -1;
- }
- if (wpa_ctrl_attach(g_monitorConn) == 0) { // start monitor
- pthread_create(&g_wpaThreadId, NULL, MonitorTask, NULL); // create thread for read event
- return 0;
- }
- return -1;
- }
然后我們來著重分析一下TestNetworkConfig函數(shù)。實(shí)際上就是一系列SendCtrlCommand向Daemon發(fā)送指令。
- static void TestNetworkConfig(void)
- {
- char networkId[20] = {0};
- size_t networkIdLen = sizeof(networkId);
- int ret = SendCtrlCommand("DISCONNECT", networkId, &networkIdLen);
- ret += SendCtrlCommand("ADD_NETWORK", networkId, &networkIdLen);
- if (ret != 0) {
- SAMPLE_ERROR("add network failed.");
- return;
- }
- SAMPLE_INFO("add network success, network id [%.*s]", networkIdLen, networkId);
- char reply[100] = {0};
- size_t replyLen = sizeof(reply);
- char cmd[200] = {0};
- sprintf_s(cmd, sizeof(cmd), "SET_NETWORK %.*s ssid \"example\"", networkIdLen, networkId);
- ret += SendCtrlCommand(cmd, reply, &replyLen);
- replyLen = sizeof(reply);
- sprintf_s(cmd, sizeof(cmd), "SET_NETWORK %.*s psk \"012345678\"", networkIdLen, networkId);
- ret += SendCtrlCommand(cmd, reply, &replyLen);
- replyLen = sizeof(reply);
- sprintf_s(cmd, sizeof(cmd), "ENABLE_NETWORK %.*s", networkIdLen, networkId);
- ret += SendCtrlCommand(cmd, reply, &replyLen);
- replyLen = sizeof(reply);
- ret += SendCtrlCommand("RECONNECT", reply, &replyLen);
- replyLen = sizeof(reply);
- if (ret == 0) {
- SAMPLE_INFO("network config success.");
- return;
- }
- sprintf_s(cmd, sizeof(cmd), "REMOVE_NETWORK %.*s", networkIdLen, networkId);
- SendCtrlCommand(cmd, reply, &replyLen);
- SAMPLE_ERROR("network config failed remove network [%.*s].", networkIdLen, networkId);
- }
wpa_supplicant定義了許多命令,常見的有:
- PING:心跳檢測命令??蛻舳擞盟袛郬PAS是否工作正常。WPAS收到”PING”命令后需要回復(fù)“PONG”。
- MIB:客戶端用該命令獲取設(shè)備的MIB信息。
- STATUS:客戶端用該命令來獲取WPAS的工作狀態(tài)。
- ADD_NETWORK:為WPAS添加一個(gè)新的無線網(wǎng)絡(luò)。它將返回此新無線網(wǎng)絡(luò)的id(從0開始)。注意:此network id非常重要,客戶端后續(xù)將通過它來指明自己想操作的無線網(wǎng)絡(luò)。
- SET_NETWORK
:network id是無線網(wǎng)絡(luò)的id。此命令用于設(shè)置指定無線網(wǎng)絡(luò)的信息。其中variable為參數(shù)名,value為參數(shù)的值。 - ENABLE_NETWORK
:使能某個(gè)無線網(wǎng)絡(luò)。此命令最終將促使WPAS發(fā)起一系列操作以加入該無線網(wǎng)絡(luò)。 - SCAN: 掃描附近AP
- SCAN_RESULT:列出最近一次掃描的結(jié)果
- LIST_NETWORKS: 列出添加的所有AP
看完上邊就很好理解了,先是DISCONNECT斷開已有連接,ADD_NETWORK添加一個(gè)新的無線網(wǎng)絡(luò),SET_NETWORK設(shè)置ssid和psk,ENABLE_NETWORK使能這個(gè)無線網(wǎng)絡(luò),最后一個(gè)RECONNECT重新連接有點(diǎn)迷,去掉應(yīng)該也沒關(guān)系,不過本人沒有嘗試。
TestScan函數(shù)就留給讀者自行分析。
了解了這些,我們就可以在自己的代碼中去連接WIFI熱點(diǎn)了,我是放在了ACE模塊IDE自建module中,這樣就可以在JS中調(diào)用了。還可以傳遞ssid和psk參數(shù),連接指定的熱點(diǎn)。如果需要,也可以增加掃描熱點(diǎn)并獲得熱點(diǎn)列表的功能。
在移植的過程中,需要注意的是,BUILD.gn文件需要增加相關(guān)配置,頭文件目錄增加:
- "//third_party/wpa_supplicant/wpa_supplicant-2.9/src/",
依賴項(xiàng)deps增加:
- "//third_party/wpa_supplicant/wpa_supplicant-2.9:wpa_supplicant",
- ldflags選項(xiàng)增加"-lwpa_client"。
這樣應(yīng)該就可以正常編譯了。
運(yùn)行后觀察日志輸出,有點(diǎn)多:
- 01-01 00:01:32.597 11 60 D 03B00/JS-3RD-APP: [Console Debug] Connecting to ap: huaweim20
- 01-01 00:01:32.597 11 60 I 03900/ACE: ConnectToWifi invoked!
- 01-01 00:01:32.597 11 60 I 03900/ACE: ssid: huaweim20
- WpaCliSample(DumpString:584): SendCtrlCommand raw return dump start.
- OK
- WpaCliSample(DumpString:589): SendCtrlCommand raw return dump end.
- 01-01 00:01:32.597 11 60 I 03900/ACE: psk: huaweim20
- WpaCliSample(DumpString:584): SendCtrlCommand raw return dump start.
- 1
- WpaCliSample(DumpString:589): SendCtrlCommand raw return dump end.
- WpaCliSample(ConnectToWifiInner:717): add network success, network id [1
- ]
- 01-01 00:01:32.597 11 60 I 03900/ACE: InitControlInterface
- WpaCliSample(DumpString:584): SendCtrlCommand raw return dump start.
- OK
- WpaCliSample(DumpString:589): SendCtrlCommand raw return dump end.
- 01-01 00:01:32.623 11 60 I 03900/ACE: ConnectToWifiInner
- WpaCliSample(DumpString:584): SendCtrlCommand raw return dump start.
- OK
- WpaCliSample(DumpString:589): SendCtrlCommand raw return dump end.
- WpaCliSample(DumpString:584): SendCtrlCommand raw return dump start.
- OK
- WpaCliSample(DumpString:589): SendCtrlCommand raw return dump end.
- WpaCliSample(DumpString:584): SendCtrlCommand raw return dump start.
- OK
- WpaCliSample(DumpString:589): SendCtrlCommand raw return dump end.
- WpaCliSample(ConnectToWifiInner:733): network config success.
- WIFI: Scan : (null) SSID : 0
- [HDF:I/HDF_LOG_TAG]WifiWpaCmdBlockSyncSend: cmd=15, ret=0
- [ERR][HDF:E/HDF_LOG_TAG]HdfWifiSendEvent event=5
- [ERR][HDF:E/HDF_LOG_TAG]HdfWifiSendEvent event=5
- [ERR][HDF:E/HDF_LOG_TAG]HdfWifiSendEvent event=5
- [ERR][HDF:E/HDF_LOG_TAG]HdfWifiSendEvent event=5
- [ERR][HDF:E/HDF_LOG_TAG]HdfWifiSendEvent event=5
- [ERR][HDF:E/HDF_LOG_TAG]HdfWifiSendEvent event=4
- WifiWpaDriverEventProcess event=5
- WifiWpaEventScanResultProcess: ie_len=248, beacon_ie_len=248
- WifiWpaEventScanResultProcess done
- WifiWpaDriverEventProcess event=5
- WifiWpaEventScanResultProcess: ie_len=310, beacon_ie_len=310
- WifiWpaEventScanResultProcess done
- WifiWpaDriverEventProcess event=5
- WifiWpaEventScanResultProcess: ie_len=226, beacon_ie_len=226
- WifiWpaEventScanResultProcess done
- WifiWpaDriverEventProcess event=5
- WifiWpaEventScanResultProcess: ie_len=243, beacon_ie_len=243
- WifiWpaEventScanResultProcess done
- WifiWpaDriverEventProcess event=5
- WifiWpaEventScanResultProcess: ie_len=198, beacon_ie_len=198
- WifiWpaEventScanResultProcess done
- WifiWpaDriverEventProcess event=4
- WifiWpaGetScanResults2 done
- WifiWpaEventScanDoneProcess done
- wlan0: Trying to associate with bc:e2:65:3c:19:70 (SSID='huaweim20' freq=2462 MHz)
- [97854][E:1786]{oal_sdio_transfer_scatt::write failed=-84}
- [E]oal_exception_submit, g_pst_exception_info is null
- [97859][E:1786]{oal_sdio_transfer_scatt::write failed=-84}
- [E]oal_exception_submit, g_pst_exception_info is null
- [HDF:I/HDF_LOG_TAG]WifiWpaCmdBlockSyncSend: cmd=17, ret=0
- WifiWpaAssociate done ret=0
- [97876][E:1786]{oal_sdio_transfer_scatt::write failed=-84}
- [E]oal_exception_submit, g_pst_exception_info is null
- [97887][E:1786]{oal_sdio_transfer_scatt::write failed=-84}
- [E]oal_exception_submit, g_pst_exception_info is null
- [97897][E:1786]{oal_sdio_transfer_scatt::write failed=-84}
- [E]oal_exception_submit, g_pst_exception_info is null
- [97907][E:1786]{oal_sdio_transfer_scatt::write failed=-84}
- [E]oal_exception_submit, g_pst_exception_info is null
- [97917][E:1786]{oal_sdio_transfer_scatt::write failed=-84}
- [E]oal_exception_submit, g_pst_exception_info is null
- [ERR][HDF:E/HDF_LOG_TAG]HdfWifiSendEvent event=13
- [97931][E:1786]{oal_sdio_transfer_scatt::write failed=-84}
- WifiWpaDriverEventProcess event=13[E]oal_exception_submit, g_pst_exception_info is null
- [97944][E:1786]{oal_sdio_transfer_scatt::write failed=-84}
- WifiWpaDriverEventEapolRecvProcess call[E]oal_exception_submit, g_pst_exception_info is null
- [ERR]
- l2_packet_receive1
- [HDF:E/HDF_LOG_TAG]HdfWifiSendEvent event=6
- l2_packet_receive2
- [HDF:I/HDF_LOG_TAG]WifiWpaCmdBlockSyncSend: cmd=6, ret=0
- l2_packet_receive3
- rx_callback
- WifiWpaReceiveEapol done
- WifiWpaDriverEventProcess event=6
- wlan0: Associated with bc:e2:65:3c:19:70
- [HDF:I/HDF_LOG_TAG]WifiWpaCmdBlockSyncSend: cmd=5, ret=0
- WifiWpaWpaSendEapol done ret=0
- wlan0: CTRL-EVENT-SUBNET-STATUS-UPDATE status=0
- WifiWpaEventConnectResultProcess done
- [ERR][HDF:E/HDF_LOG_TAG]HdfWifiSendEvent event=13
- WifiWpaDriverEventProcess event=13
- WifiWpaDriverEventEapolRecvProcess call
- l2_packet_receive1
- l2_packet_receive2
- [HDF:I/HDF_LOG_TAG]WifiWpaCmdBlockSyncSend: cmd=6, ret=0
- l2_packet_receive3
- rx_callback
- [HDF:I/HDF_LOG_TAG]WifiWpaCmdBlockSyncSend: cmd=5, ret=0
- WifiWpaWpaSendEapol done ret=0
- [HDF:I/HDF_LOG_TAG]WifiWpaCmdBlockSyncSend: cmd=1, ret=0
- [HDF:I/HDF_LOG_TAG]WifiWpaCmdBlockSyncSend: cmd=3, ret=0
- [HDF:I/HDF_LOG_TAG]WifiWpaCmdBlockSyncSend: cmd=1, ret=0
- wlan0: WPA: Key negotiation completed with bc:e2:65:3c:19:70 [PTK=CCMP GTK=CCMP]
- wlan0: CTRL-EVENT-CONNECTED - Connection to bc:e2:65:3c:19:70 completed [id=1 id_str=]
- WifiWpaReceiveEapol done
- [ERR][HDF:E/NetDeviceLite]LiteNetDhcpIsBound fail, ret = -5!
- [ERR][HDF:E/NetDeviceLite]LiteNetDhcpIsBound fail, ret = -5!
能清楚的看到SendCtrlCommand的過程。最后看到wlan0: CTRL-EVENT-CONNECTED,就是連接成功了。同時(shí)手機(jī)熱點(diǎn)已連接設(shè)備數(shù)顯示為1。
稍后,我會做一個(gè)帶有界面的視頻Demo,展示效果。
51CTO和華為官方合作共建的鴻蒙技術(shù)社區(qū)