Wi-Fi STA模式编程
个人简介:`深圳技术大学大二学生,学习研究鸿蒙南向开发知识,发帖子记录一下学习过程中的笔记。
博客主页:https://ost.51cto.com/person/posts/16275438
通过本文可以学到:
- Wi-Fi STA 模式编程相关的 API;
- 通过案例程序学习相关 API 的具体使用方法。
一、相关 API 介绍
1. HAL API
硬件抽象层(Hardware Abstraction Layer, HAL)是一种软件层,它位于操作系统内核或运行时环境与硬件设备驱动之间,目的是隐藏具体的硬件细节,为上层软件提供一致的接口,使得上层软件不必关心底层硬件的实现细节,从而提高代码的可移植性和复用性。
Wi-Fi 接口的声明在 foundation\communication\wifi_lite\interfaces\wifiservice\*.h
文件中,如下图所示。
Wi-Fi接口的定义在 device\hisilicon\hispark_pegasus\hi3861_adapter\hals\communication\wifi_lite\wifiservice\source\*.c
文件中。可以在源码中查看接口的详细信息。
STA模式编程接口的声明在 foundation\communication\wifi-lite\interfaces\wifiservice wifi_device.h
文件中。可见下表。
API名称 |
说明 |
WifiErrorCode EnableWifi(void) |
开启STA |
WifiErrorCode DisableWifi(void) |
关闭STA |
int IsWifiActive(void) |
查询STA是否已开启 |
WifiErrorCode Scan(void) |
触发扫描 |
WifiErrorCode GetScanInfoList(WifiScanInfo* result, unsigned int* size) |
获取扫描结果 |
WifiErrorCode AddDeviceConfig(const WifiDeviceConfig* config, int* result) |
添加热点配置,若成功,则会通过result参数传出 netId |
WifiErrorCode GetDeviceConfigs(WifiDeviceConfig* result, unsigned int* size) |
获取本机的所有热点配置 |
WifiErrorCode RemoveDevice(int networkId) |
删除热点配置 |
WifiErrorCode ConnectTo(int networkId) |
连接到热点 |
WifiErrorCode Disconnect(void) |
断开热点连接 |
WifiErrorCode GetLinkedInfo(WifiLinkedInfo* result) |
获取当前连接的热点信息 |
WifiErrorCode RegisterWifiEvent(WifiEvent* event) |
注册事件监听 |
WifiErrorCode UnRegisterWifiEvent(const WifiEvent* event) |
解除事件监听 |
WifiErrorCode GetDeviceMacAddress(unsigned char* result) |
获取MAC地址 |
WifiErrorCode AdvanceScan(WifiScanParams* params) |
高级扫描 |
2. 海思SDK API
海思SDK中集成了第三方组件LwIP来完成查找网络接口、启动/停止DHCP客户端等操作。
接口的声明在 device\hisilicon\hispark_pegasus\sdk_liteos\third_party\lwip_sack\include\lwip\*.h
文件中,如下图所示。
接口的实现在 device\hisilicon\hispark_pegasus\sdk_liteos\build\libs\liblwip.a
文件中。这是一个预先编译好的静态库文件,我们无法查看具体源码。我们需要使用的API见下表。
API名称 |
描述 |
struct netif* netifapi_netif_find(const char* name) |
按名称查找网络接口,STA模式的网络接口名为“wlan0” |
err_t netifapi_dhcp_start(struct netif* netif) |
在指定的网络接口上启动 DHCP 客户端 |
err_t netifapi_dhcp_stop(struct netif* netif) |
在指定的网络接口上停止 DHCP 客户端 |
二、扫描 Wi-Fi 热点
扫描 Wi-Fi 热点的标准流程如下:
- 使用
RegisterWifiEvent
接口注册 Wi-Fi 事件监听器。
- 使用
EnableWifi
接口开启 Wi-Fi 设备的 STA 模式。
- 使用
Scan
接口开始扫描 Wi-Fi 热点。
- 在扫描状态变化事件 (
OnWifiScanStateChanged
) 的回调函数中监测扫描是否完成。
- 等待扫描完成。
- 使用
GetScanInfoList
接口获取扫描结果。
- 显示扫描结果。
- 使用
DisableWifi
接口关闭 Wi-Fi 设备的 STA 模式。
三、案例:扫描 Wi-Fi 热点
1. 新建目录
新建 applications\sample\wifi-iot\app\wifi_demo
目录。
2. 编写源码与编译脚本
新建 applications\sample\wifi-iot\app\wifi_demo\wifi_scan_demo.c
文件:
#include "cmsis_os2.h"
#include "ohos_init.h"
#include "wifi_device.h"
#include <stdio.h>
#include <string.h>
#include <unistd.h>
static int g_scanDone = 0;
static char* SecurityTypeName(WifiSecurityType type)
{
switch (type)
{
case WIFI_SEC_TYPE_OPEN:
return "OPEN";
case WIFI_SEC_TYPE_WEP:
return "WEP";
case WIFI_SEC_TYPE_PSK:
return "PSK";
case WIFI_SEC_TYPE_SAE:
return "SAE";
default:
break;
}
return "UNKNOWN";
}
void OnWifiConnectionChanged(int state, WifiLinkedInfo* info)
{
(void)state;
(void)info;
printf("%s %d\r\n", __FUNCTION__, __LINE__);
}
void PrintScanResult(void)
{
WifiScanInfo scanResult[WIFI_SCAN_HOTSPOT_LIMIT] = { 0 };
uint32_t resultSize = WIFI_SCAN_HOTSPOT_LIMIT;
memset(&scanResult, 0, sizeof(scanResult));
WifiErrorCode errCode = GetScanInfoList(scanResult, &resultSize);
if (errCode != WIFI_SUCCESS)
{
printf("GetScanInfoList failed: %d\r\n", errCode);
return;
}
for (uint32_t i = 0; i < resultSize; i++)
{
static char macAddress[32] = { 0 };
WifiScanInfo info = scanResult[i];
unsigned char* mac = info.bssid;
snprintf(macAddress, sizeof(macAddress), "%02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
printf("AP[%d]:%s,%4s,%d,%d,%d,%s\r\n",
i,
macAddress,
SecurityTypeName(info.securityType),
info.rssi,
info.band,
info.frequency,
info.ssid);
}
}
void OnWifiScanStateChanged(int state, int size)
{
printf("%s %d, state=%X, size=%d\r\n", __FUNCTION__, __LINE__, state, size);
if (state == WIFI_STATE_AVALIABLE && size > 0)
{
g_scanDone = 1;
}
}
static void WifiScanTask(void* arg)
{
(void)arg;
WifiErrorCode errCode;
WifiEvent eventListener = {
.OnWifiConnectionChanged = OnWifiConnectionChanged,
.OnWifiScanStateChanged = OnWifiScanStateChanged
};
osDelay(10);
errCode = RegisterWifiEvent(&eventListener);
printf("RegisterWifiEvent:%d\r\n", errCode);
while (1)
{
errCode = EnableWifi();
printf("EnableWifi:%d\r\n", errCode);
osDelay(100);
g_scanDone = 0;
errCode = Scan();
printf("Scan: %d\r\n", errCode);
while (!g_scanDone)
{
osDelay(5);
}
PrintScanResult();
errCode = DisableWifi();
printf("DisableWifi: %d\r\n", errCode);
osDelay(500);
}
}
static void WifiScanDemo(void)
{
osThreadAttr_t attr;
attr.name = "WifiScanTask";
attr.attr_bits = 0U;
attr.cb_mem = NULL;
attr.cb_size = 0U;
attr.stack_mem = NULL;
attr.stack_size = 10240;
attr.priority = osPriorityNormal;
if (osThreadNew(WifiScanTask, NULL, &attr) == NULL)
{
printf("[WifiScanDemo] Failed to create WifiScanTask!\n");
}
}
APP_FEATURE_INIT(WifiScanDemo);
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
- 20.
- 21.
- 22.
- 23.
- 24.
- 25.
- 26.
- 27.
- 28.
- 29.
- 30.
- 31.
- 32.
- 33.
- 34.
- 35.
- 36.
- 37.
- 38.
- 39.
- 40.
- 41.
- 42.
- 43.
- 44.
- 45.
- 46.
- 47.
- 48.
- 49.
- 50.
- 51.
- 52.
- 53.
- 54.
- 55.
- 56.
- 57.
- 58.
- 59.
- 60.
- 61.
- 62.
- 63.
- 64.
- 65.
- 66.
- 67.
- 68.
- 69.
- 70.
- 71.
- 72.
- 73.
- 74.
- 75.
- 76.
- 77.
- 78.
- 79.
- 80.
- 81.
- 82.
- 83.
- 84.
- 85.
- 86.
- 87.
- 88.
- 89.
- 90.
- 91.
- 92.
- 93.
- 94.
- 95.
- 96.
- 97.
- 98.
- 99.
- 100.
- 101.
- 102.
- 103.
- 104.
- 105.
- 106.
- 107.
- 108.
- 109.
- 110.
- 111.
- 112.
- 113.
- 114.
- 115.
- 116.
- 117.
- 118.
- 119.
- 120.
- 121.
- 122.
- 123.
- 124.
- 125.
- 126.
- 127.
- 128.
- 129.
- 130.
- 131.
- 132.
- 133.
- 134.
- 135.
- 136.
- 137.
- 138.
- 139.
- 140.
- 141.
- 142.
- 143.
- 144.
- 145.
- 146.
- 147.
- 148.
- 149.
- 150.
- 151.
- 152.
- 153.
- 154.
- 155.
- 156.
- 157.
- 158.
- 159.
- 160.
- 161.
- 162.
- 163.
- 164.
- 165.
- 166.
- 167.
- 168.
- 169.
- 170.
- 171.
- 172.
- 173.
- 174.
- 175.
- 176.
- 177.
- 178.
- 179.
- 180.
- 181.
- 182.
- 183.
- 184.
- 185.
新建 applications\sample\wifi-iot\app\wifi_demo\BUILD.gn
文件:
修改 applications\sample\wifi-iot\app\BUILD.gn
文件:
3. 编译、烧录、运行
运行结果如下图:

四、连接 Wi-Fi 热点
连接 Wi-Fi 热点的标准流程
- 使用
RegisterWifiEvent
接口注册 Wi-Fi 事件监听器。
- 使用
EnableWifi
接口开启 Wi-Fi 设备的 STA 模式。
- 使用
AddDeviceConfig
接口向系统添加热点配置,主要是 SSID、PSK 和加密方式等配置项。
- 使用
ConnectTo
接口连接到热点上。
- 在连接状态变化 (
OnWifiConnectionChanged
) 事件的回调函数中监测连接是否成功。
- 等待连接成功。
- 使用海思 SDK 接口的 DHCP 客户端 API,从热点中获取 IP 地址。
断开 Wi-Fi 热点的标准流程
- 使用
netifapi_dhcp_stop
接口停止 DHCP 客户端。
- 使用
Disconnect
接口断开热点。
- 使用
RemoveDevice
接口删除热点配置。
- 使用
DisableWifi
接口关闭 Wi-Fi 设备的 STA 模式。
五、案例:连接 Wi-Fi 热点
1. 新建目录
沿用上一个案例的 applications\sample\wifi-iot\app\wifi_demo
目录。
2. 编写源码与编译脚本
新建 applications\sample\wifi-iot\app\wifi_demo\wifi_connect_demo.c
文件,源码如下:
#include "cmsis_os2.h"
#include "lwip/api_shell.h"
#include "lwip/netifapi.h"
#include "ohos_init.h"
#include "wifi_device.h"
#include <stdio.h>
#include <string.h>
#include <unistd.h>
static int g_connected = 0;
static void PrintLinkedInfo(WifiLinkedInfo* info)
{
if (!info)
return;
static char macAddress[32] = { 0 };
unsigned char* mac = info->bssid;
snprintf(macAddress, sizeof(macAddress), "%02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
printf("bssid:%s, rssi:%d, connState:%d, reason:%d, ssid:%s\r\n",
macAddress,
info->rssi,
info->connState,
info->disconnectedReason,
info->ssid);
}
static void OnWifiConnectionChanged(int state, WifiLinkedInfo* info)
{
if (!info)
return;
printf("%s %d, state=%d, info=\r\n", __FUNCTION__, __LINE__, state);
PrintLinkedInfo(info);
if (state == WIFI_STATE_AVALIABLE)
{
g_connected = 1;
}
else
{
g_connected = 0;
}
}
static void OnWifiScanStateChanged(int state, int size)
{
printf("%s %d, state=%X, size=%d\r\n", __FUNCTION__, __LINE__, state, size);
}
static void WifiConnectTask(void* arg)
{
(void)arg;
WifiErrorCode errCode;
WifiEvent eventListener = {
.OnWifiConnectionChanged = OnWifiConnectionChanged,
.OnWifiScanStateChanged = OnWifiScanStateChanged
};
WifiDeviceConfig apConfig = {};
int netId = -1;
osDelay(10);
errCode = RegisterWifiEvent(&eventListener);
printf("RegisterWifiEvent:%d\r\n", errCode);
strcpy(apConfig.ssid, "WARDEN");
strcpy(apConfig.preSharedKey, "88888888");
apConfig.securityType = WIFI_SEC_TYPE_PSK;
while (1)
{
errCode = EnableWifi();
printf("EnableWifi:%d\r\n", errCode);
osDelay(10);
errCode = AddDeviceConfig(&apConfig, &netId);
printf("AddDeviceConfig:%d\r\n", errCode);
g_connected = 0;
errCode = ConnectTo(netId);
printf("ConnectTo(%d):%d\r\n", netId, errCode);
while (!g_connected)
{
osDelay(10);
}
printf("g_connected:%d\r\n", g_connected);
osDelay(50);
struct netif* iface = netifapi_netif_find("wlan0");
if (iface)
{
err_t ret = netifapi_dhcp_start(iface);
printf("netifapi_dhcp_start:%d\r\n", ret);
osDelay(200);
}
int timeout = 60;
printf("after %d seconds, I'll disconnect WiFi!\n", timeout);
while (timeout--)
{
osDelay(100);
printf("after %d seconds, I'll disconnect WiFi!\n", timeout);
}
err_t ret = netifapi_dhcp_stop(iface);
printf("netifapi_dhcp_stop:%d\r\n", ret);
printf("disconnect!\r\n");
Disconnect();
RemoveDevice(netId);
errCode = DisableWifi();
printf("DisableWifi:%d\r\n", errCode);
osDelay(200);
}
}
static void WifiConnectDemo(void)
{
osThreadAttr_t attr;
attr.name = "WifiConnectTask";
attr.attr_bits = 0U;
attr.cb_mem = NULL;
attr.cb_size = 0U;
attr.stack_mem = NULL;
attr.stack_size = 10240;
attr.priority = osPriorityNormal;
if (osThreadNew(WifiConnectTask, NULL, &attr) == NULL)
{
printf("[WifiConnectDemo] Failed to create WifiConnectTask!\n");
}
}
APP_FEATURE_INIT(WifiConnectDemo);
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
- 20.
- 21.
- 22.
- 23.
- 24.
- 25.
- 26.
- 27.
- 28.
- 29.
- 30.
- 31.
- 32.
- 33.
- 34.
- 35.
- 36.
- 37.
- 38.
- 39.
- 40.
- 41.
- 42.
- 43.
- 44.
- 45.
- 46.
- 47.
- 48.
- 49.
- 50.
- 51.
- 52.
- 53.
- 54.
- 55.
- 56.
- 57.
- 58.
- 59.
- 60.
- 61.
- 62.
- 63.
- 64.
- 65.
- 66.
- 67.
- 68.
- 69.
- 70.
- 71.
- 72.
- 73.
- 74.
- 75.
- 76.
- 77.
- 78.
- 79.
- 80.
- 81.
- 82.
- 83.
- 84.
- 85.
- 86.
- 87.
- 88.
- 89.
- 90.
- 91.
- 92.
- 93.
- 94.
- 95.
- 96.
- 97.
- 98.
- 99.
- 100.
- 101.
- 102.
- 103.
- 104.
- 105.
- 106.
- 107.
- 108.
- 109.
- 110.
- 111.
- 112.
- 113.
- 114.
- 115.
- 116.
- 117.
- 118.
- 119.
- 120.
- 121.
- 122.
- 123.
- 124.
- 125.
- 126.
- 127.
- 128.
- 129.
- 130.
- 131.
- 132.
- 133.
- 134.
- 135.
- 136.
- 137.
- 138.
- 139.
- 140.
- 141.
- 142.
- 143.
- 144.
- 145.
- 146.
- 147.
- 148.
- 149.
- 150.
- 151.
- 152.
- 153.
- 154.
- 155.
- 156.
- 157.
- 158.
- 159.
- 160.
- 161.
- 162.
- 163.
- 164.
- 165.
- 166.
- 167.
- 168.
- 169.
- 170.
- 171.
- 172.
- 173.
- 174.
- 175.
- 176.
- 177.
- 178.
- 179.
- 180.
- 181.
- 182.
- 183.
- 184.
- 185.
- 186.
- 187.
- 188.
- 189.
- 190.
- 191.
- 192.
- 193.
- 194.
- 195.
- 196.
- 197.
- 198.
- 199.
- 200.
- 201.
修改 applications\sample\wifi-iot\app\wifi_demo\BUILD.gn
文件,源码如下:
3. 编译、烧录、运行
使用手机开启 Wi-Fi 热点。
程序运行结果:

