HI3861学习笔记(19)——WiFi接口使用(STA和AP模式)

一、简介

  • 基站模式(即 STA 模式或 Wi-Fi 客户端模式),此时 HI3861 连接到接入点 (AP)。

  • AP 模式(即 Soft-AP 模式或接入点模式),此时基站连接到 HI3861。

二、API说明

以下 AP热点 接口位于 foundation\communication\interfaces\kits\wifi_lite\wifiservice\wifi_hotspot.h

业务BUILD.gn中包含路径

include_dirs = [
        "//utils/native/lite/include",
        "//kernel/liteos_m/components/cmsis/2.0",
        "//base/iot_hardware/interfaces/kits/wifiiot_lite",
        "//foundation/communication/interfaces/kits/wifi_lite/wifiservice",
        "//vendor/hisi/hi3861/hi3861/third_party/lwip_sack/include/",
    ]

2.1 EnableHotspot

功能 启用Wifi热点模式
函数定义 WifiErrorCode EnableHotspot(void)
参数
返回 错误码

2.2 DisableHotspot

功能 禁用Wifi热点模式
函数定义 WifiErrorCode DisableHotspot(void)
参数
返回 错误码

2.3 SetHotspotConfig

功能 设置指定的热点配置
函数定义 WifiErrorCode SetHotspotConfig(const HotspotConfig* config)
参数 config:热点配置参数
返回 错误码

2.4 GetHotspotConfig

功能 获取指定的热点配置
函数定义 WifiErrorCode GetHotspotConfig(HotspotConfig* result)
参数 result:获取指定的热点配置结果
返回 错误码

2.5 IsHotspotActive

功能 检查AP热点模式是否启用
函数定义 int IsHotspotActive(void)
参数
返回 WIFI_HOTSPOT_ACTIVE - 已启用;WIFI_HOTSPOT_NOT_ACTIVE - 未启用

2.6 GetStationList

功能 获取连接到该热点的一系列STA
函数定义 WifiErrorCode GetStationList(StationInfo* result, unsigned int* size)
参数 result:表示连接到该热点的STA列表
size:表示连接到该热点的STA数量
返回 错误码

2.7 GetSignalLevel

功能 获取接收信号强度和频率
函数定义 int GetSignalLevel(int rssi, int band)
参数 rssi:信号强度
band:频率,HOTSPOT_BAND_TYPE_5G或HOTSPOT_BAND_TYPE_2G
返回 获取到的信号水平

以下 STA联网 接口位于 foundation\communication\interfaces\kits\wifi_lite\wifiservice\wifi_device.h

业务BUILD.gn中包含路径

include_dirs = [
        "//utils/native/lite/include",
        "//kernel/liteos_m/components/cmsis/2.0",
        "//base/iot_hardware/interfaces/kits/wifiiot_lite",
        "//foundation/communication/interfaces/kits/wifi_lite/wifiservice",
        "//vendor/hisi/hi3861/hi3861/third_party/lwip_sack/include/",
    ]

2.8 RegisterWifiEvent

功能 为指定的Wi-Fi事件注册回调函数。当WifiEvent中定义的Wi-Fi事件发生时,将调用已注册的回调函数
函数定义 WifiErrorCode RegisterWifiEvent(WifiEvent* event)
参数 event:表示要注册回调的事件
返回 错误码

2.9 EnableWifi

功能 启用STA模式
函数定义 WifiErrorCode EnableWifi(void)
参数
返回 错误码

2.10 DisableWifi

功能 禁用STA模式
函数定义 WifiErrorCode DisableWifi(void)
参数
返回 错误码

2.11 IsWifiActive

功能 检查Wifi STA模式是否启用
函数定义 int IsWifiActive(void)
参数
返回 WIFI_STA_ACTIVE - 已启用;WIFI_STA_NOT_ACTIVE - 未启用

2.12 Scan

功能 开启扫描热点信息
函数定义 WifiErrorCode Scan(void)
参数
返回 错误码

2.13 GetScanInfoList

功能 获取所有扫描到的热点列表
函数定义 WifiErrorCode GetScanInfoList(WifiScanInfo* result, unsigned int* size)
参数 result:被扫描到的热点数组
size:热点数组大小
返回 错误码

2.14 AddDeviceConfig

功能 配置连接到热点信息
函数定义 WifiErrorCode AddDeviceConfig(const WifiDeviceConfig* config, int* result)
参数 config:表示要连接的热点信息
result:表示生成的networkId。每个networkId匹配一个热点配置
返回 错误码

2.15 ConnectTo

功能 接到指定的热点
函数定义 WifiErrorCode ConnectTo(int networkId)
参数 networkId:表示与目标热点匹配的网络id
返回 错误码

2.16 Disconnect

功能 断开Wifi连接
函数定义 WifiErrorCode Disconnect(void)
参数
返回 错误码

2.17 GetLinkedInfo

功能 断开Wifi连接
函数定义 WifiErrorCode GetLinkedInfo(WifiLinkedInfo* result)
参数 result:表示目前连接中的热点信息
返回 错误码

2.18 GetDeviceMacAddress

功能 获取设备的MAC地址
函数定义 WifiErrorCode GetDeviceMacAddress(unsigned char* result)
参数 result:设备的MAC地址,6字节长度数组
返回 错误码

以下 LwIP 接口位于 vendor\hisi\hi3861\hi3861\third_party\lwip_sack\include\lwip/netifapi.hvendor\hisi\hi3861\hi3861\third_party\lwip_sack\include\lwip/dhcp.h

业务BUILD.gn中包含路径

include_dirs = [
        "//utils/native/lite/include",
        "//kernel/liteos_m/components/cmsis/2.0",
        "//base/iot_hardware/interfaces/kits/wifiiot_lite",
        "//foundation/communication/interfaces/kits/wifi_lite/wifiservice",
        "//vendor/hisi/hi3861/hi3861/third_party/lwip_sack/include/",
    ]

2.19 netifapi_netif_find

功能 获取网络接口用于IP操作
函数定义 struct netif *netifapi_netif_find(const char *name)
参数 name:网络接口名称
返回 错误码

2.20 netifapi_netif_set_addr

功能 设置SoftAp的DHCP服务器的IP地址、子网掩码和网关参数
函数定义 err_t netifapi_netif_set_addr(struct netif *netif, const ip4_addr_t *ipaddr, const ip4_addr_t *netmask, const ip4_addr_t *gw)
参数 netif:被改变的网络接口
ipaddr:新的IP地址
netmask:新的子网掩码
gw:新的网关地址
返回 错误码

2.21 netifapi_dhcps_start

功能 启动SoftAp的DHCP服务器
函数定义 err_t netifapi_dhcps_start(struct netif *netif, char *start_ip, u16_t ip_num)
参数 netif:LwIP网络接口
start_ip:DHCP起始地址
ip_num:IP池数量
返回 错误码

2.22 netifapi_netif_common

功能 用于以线程安全的方式调用所有与netif相关的API
函数定义 err_t netifapi_netif_common(struct netif *netif, netifapi_void_fn voidfunc, netifapi_errt_fn errtfunc)
参数 netif:LwIP网络接口
voidfunc:如果errtfunc为NULL,将调用返回类型为void的回调
errtfunc:返回类型为err_t的回调
返回 错误码

2.23 dhcp_start

功能 启动DHCP, 获取IP
函数定义 err_t dhcp_start(struct netif *netif)
参数 netif:LwIP网络接口
返回 错误码

三、AP模式

3.1 初始化Wi-Fi事件处理

3.1.1 注册wifi事件的回调函数

通过 RegisterWifiEvent 接口向系统注册热点状态改变事件、STA站点加入事件、STA站点退出事件

//注册wifi事件的回调函数
g_wifiEventHandler.OnHotspotStaJoin = OnHotspotStaJoinHandler;
g_wifiEventHandler.OnHotspotStaLeave = OnHotspotStaLeaveHandler;
g_wifiEventHandler.OnHotspotStateChanged = OnHotspotStateChangedHandler;
error = RegisterWifiEvent(&g_wifiEventHandler);
if (error != WIFI_SUCCESS)
{
    
    
    printf("RegisterWifiEvent failed, error = %d.\r\n",error);
    return -1;
}
printf("RegisterWifiEvent succeed!\r\n");

3.1.2 终端设备加入

定义成功加入AP热点的终端设备数量 g_apEnableSuccess

static int g_apEnableSuccess = 0;

实现 OnHotspotStaJoinHandler() 终端设备加入处理函数。

用于绑定STA站点加入事件,当有新的STA站点加入时,该回调函数会创建 HotspotStaJoinTask,在该任务中会调用 GetStationList 函数获取当前接入到该AP的所有STA站点信息,并打印出每个STA站点的MAC地址;

static void OnHotspotStaJoinHandler(StationInfo *info)
{
    
    
    if (info == NULL) 
    {
    
    
        printf("HotspotStaJoin:info is null.\r\n");
    } 
    else 
    {
    
    
        printf("New Sta Join\n");
        osThreadAttr_t attr;
        attr.name = "HotspotStaJoinTask";
        attr.attr_bits = 0U;
        attr.cb_mem = NULL;
        attr.cb_size = 0U;
        attr.stack_mem = NULL;
        attr.stack_size = 2048;
        attr.priority = 24;
        if (osThreadNew((osThreadFunc_t)HotspotStaJoinTask, NULL, &attr) == NULL) 
        {
    
    
            printf("HotspotStaJoin:create task fail!\r\n");
        }
    }
    return;
}

实现 HotspotStaJoinTask() 终端设备加入处理任务

static void HotspotStaJoinTask(void)
{
    
    
    static char macAddress[32] = {
    
    0};
    StationInfo stainfo[WIFI_MAX_STA_NUM] = {
    
    0};
    StationInfo *sta_list_node = NULL;
    unsigned int size = WIFI_MAX_STA_NUM;

    error = GetStationList(stainfo, &size);
    if (error != WIFI_SUCCESS) 
    {
    
    
        printf("HotspotStaJoin:get list fail, error is %d.\r\n", error);
        return;
    }
    sta_list_node = stainfo;
    for (uint32_t i = 0; i < size; i++, sta_list_node++) 
    {
    
    
        unsigned char* mac = sta_list_node->macAddress;
        snprintf(macAddress, sizeof(macAddress), "%02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
        printf("HotspotSta[%d]: macAddress=%s.\r\n",i, macAddress);
    }
    g_apEnableSuccess++;
}

3.1.3 终端设备离开

实现 OnHotspotStaLeaveHandler() 终端设备离开处理函数。

用于绑定STA站点退出事件,当有STA站点退出,该回调函数会打印出退出站点的MAC地址。

static void OnHotspotStaLeaveHandler(StationInfo *info)
{
    
    
    if (info == NULL) 
    {
    
    
        printf("HotspotStaLeave:info is null.\r\n");
    } 
    else 
    {
    
    
        static char macAddress[32] = {
    
    0};
        unsigned char* mac = info->macAddress;
        snprintf(macAddress, sizeof(macAddress), "%02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
        printf("HotspotStaLeave: macAddress=%s, reason=%d.\r\n", macAddress, info->disconnectedReason);
        g_apEnableSuccess--;
    }
    return;
}

3.1.4 AP热点状态改变

实现 OnHotspotStateChangedHandler() AP热点状态改变处理函数。

用于绑定热点状态改变事件,该回调函数有一个参数 state

  • state表示是否开启AP模式,取值为0和1,0表示已启用Wifi AP模式,1表示已禁用Wifi AP模式;
  • 当已启用Wifi AP模式,该回调函数会将标志位 g_apEnableSuccess 置 1;
static void OnHotspotStateChangedHandler(int state)
{
    
    
    printf("HotspotStateChanged:state is %d.\r\n", state);
    if (state == WIFI_HOTSPOT_ACTIVE) 
    {
    
    
        printf("wifi hotspot active.\r\n");
    }
    else 
    {
    
    
        printf("wifi hotspot noactive.\r\n");
    }
}

3.2 Wi-Fi配置阶段

调用 SetHotspotConfig 接口,设置指定的热点配置。

//设置指定的热点配置
HotspotConfig config = {
    
    0};

strcpy(config.ssid, AP_SSID);
strcpy(config.preSharedKey, AP_PSK);
config.securityType = WIFI_SEC_TYPE_PSK; // 加密方式
config.band = HOTSPOT_BAND_TYPE_2G;      // 2.4G频率
config.channelNum = 7;

error = SetHotspotConfig(&config);
if (error != WIFI_SUCCESS)
{
    
    
    printf("SetHotspotConfig failed, error = %d.\r\n", error);
    return -1;
}
printf("SetHotspotConfig succeed!\r\n");

3.3 Wi-Fi启动阶段

调用 EnableHotspot 接口,使能 Wifi AP 模式。
调用 IsHotspotActive 接口,检查AP热点模式是否启用。

//启动wifi热点模式
error = EnableHotspot(); 
if (error != WIFI_SUCCESS)
{
    
    
    printf("EnableHotspot failed, error = %d.\r\n", error);
    return -1;
}
printf("EnableHotspot succeed!\r\n");

//检查热点模式是否使能
if (IsHotspotActive() == WIFI_HOTSPOT_NOT_ACTIVE)
{
    
    
    printf("Wifi station is not actived.\r\n");
    return -1;
}
printf("Wifi station is actived!\r\n");

3.4 LwIP初始阶段

//启动dhcp
g_lwip_netif = netifapi_netif_find("ap0");
if (g_lwip_netif) 
{
    
    
    ip4_addr_t bp_gw;
    ip4_addr_t bp_ipaddr;
    ip4_addr_t bp_netmask;

    IP4_ADDR(&bp_gw, 192, 168, 1, 1);           /* input your gateway for example: 192.168.1.1 */
    IP4_ADDR(&bp_ipaddr, 192, 168, 1, 1);       /* input your IP for example: 192.168.1.1 */
    IP4_ADDR(&bp_netmask, 255, 255, 255, 0);    /* input your netmask for example: 255.255.255.0 */

    err_t ret = netifapi_netif_set_addr(g_lwip_netif, &bp_ipaddr, &bp_netmask, &bp_gw);
    if(ret != ERR_OK)
    {
    
    
        printf("netifapi_netif_set_addr failed, error = %d.\r\n", ret);
        return -1;
    }
    printf("netifapi_netif_set_addr succeed!\r\n");

    ret = netifapi_dhcps_start(g_lwip_netif, 0, 0);
    if(ret != ERR_OK)
    {
    
     
        printf("netifapi_dhcp_start failed, error = %d.\r\n", ret);
        return -1;
    }
    printf("netifapi_dhcps_start succeed!\r\n");
}

3.5 完整代码

编译时在业务BUILD.gn中包含路径

include_dirs = [
        "//utils/native/lite/include",
        "//kernel/liteos_m/components/cmsis/2.0",
        "//base/iot_hardware/interfaces/kits/wifiiot_lite",
        "//foundation/communication/interfaces/kits/wifi_lite/wifiservice",
        "//vendor/hisi/hi3861/hi3861/third_party/lwip_sack/include/",
    ]
#include <stdio.h>
#include <string.h>
#include <unistd.h>

#include "cmsis_os2.h"
#include "ohos_init.h"

#include "wifi_device.h"
#include "wifi_hotspot.h"
#include "wifi_error_code.h"
#include "lwip/netifapi.h"


#define AP_SSID "BearPi"
#define AP_PSK  "12345678"

#define ONE_SECOND 1
#define DEF_TIMEOUT 15

static void OnHotspotStaJoinHandler(StationInfo *info);
static void OnHotspotStateChangedHandler(int state);
static void OnHotspotStaLeaveHandler(StationInfo *info);

static struct netif *g_lwip_netif = NULL;
static int g_apEnableSuccess = 0;
WifiEvent g_wifiEventHandler = {
    
    0};
WifiErrorCode error;

static BOOL WifiAPTask(void)
{
    
    
    //延时2S便于查看日志
    osDelay(200);

    //注册wifi事件的回调函数
    g_wifiEventHandler.OnHotspotStaJoin = OnHotspotStaJoinHandler;
    g_wifiEventHandler.OnHotspotStaLeave = OnHotspotStaLeaveHandler;
    g_wifiEventHandler.OnHotspotStateChanged = OnHotspotStateChangedHandler;
    error = RegisterWifiEvent(&g_wifiEventHandler);
    if (error != WIFI_SUCCESS)
    {
    
    
        printf("RegisterWifiEvent failed, error = %d.\r\n",error);
        return -1;
    }
    printf("RegisterWifiEvent succeed!\r\n");
    //设置指定的热点配置
    HotspotConfig config = {
    
    0};

    strcpy(config.ssid, AP_SSID);
    strcpy(config.preSharedKey, AP_PSK);
    config.securityType = WIFI_SEC_TYPE_PSK;
    config.band = HOTSPOT_BAND_TYPE_2G;
    config.channelNum = 7;

    error = SetHotspotConfig(&config);
    if (error != WIFI_SUCCESS)
    {
    
    
        printf("SetHotspotConfig failed, error = %d.\r\n", error);
        return -1;
    }
    printf("SetHotspotConfig succeed!\r\n");

    //启动wifi热点模式
    error = EnableHotspot(); 
    if (error != WIFI_SUCCESS)
    {
    
    
        printf("EnableHotspot failed, error = %d.\r\n", error);
        return -1;
    }
    printf("EnableHotspot succeed!\r\n");

    //检查热点模式是否使能
    if (IsHotspotActive() == WIFI_HOTSPOT_NOT_ACTIVE)
    {
    
    
        printf("Wifi station is not actived.\r\n");
        return -1;
    }
    printf("Wifi station is actived!\r\n");

    //启动dhcp
    g_lwip_netif = netifapi_netif_find("ap0");
    if (g_lwip_netif) 
    {
    
    
        ip4_addr_t bp_gw;
        ip4_addr_t bp_ipaddr;
        ip4_addr_t bp_netmask;

        IP4_ADDR(&bp_gw, 192, 168, 1, 1);           /* input your gateway for example: 192.168.1.1 */
        IP4_ADDR(&bp_ipaddr, 192, 168, 1, 1);       /* input your IP for example: 192.168.1.1 */
        IP4_ADDR(&bp_netmask, 255, 255, 255, 0);    /* input your netmask for example: 255.255.255.0 */

        err_t ret = netifapi_netif_set_addr(g_lwip_netif, &bp_ipaddr, &bp_netmask, &bp_gw);
        if(ret != ERR_OK)
        {
    
    
            printf("netifapi_netif_set_addr failed, error = %d.\r\n", ret);
            return -1;
        }
        printf("netifapi_netif_set_addr succeed!\r\n");

        ret = netifapi_dhcps_start(g_lwip_netif, 0, 0);
        if(ret != ERR_OK)
        {
    
     
            printf("netifapi_dhcp_start failed, error = %d.\r\n", ret);
            return -1;
        }
        printf("netifapi_dhcps_start succeed!\r\n");

    }

    while (1)
    {
    
    
        osDelay(1000);
    }
}

static void HotspotStaJoinTask(void)
{
    
    
    static char macAddress[32] = {
    
    0};
    StationInfo stainfo[WIFI_MAX_STA_NUM] = {
    
    0};
    StationInfo *sta_list_node = NULL;
    unsigned int size = WIFI_MAX_STA_NUM;

    error = GetStationList(stainfo, &size);
    if (error != WIFI_SUCCESS) {
    
    
        printf("HotspotStaJoin:get list fail, error is %d.\r\n", error);
        return;
    }
    sta_list_node = stainfo;
    for (uint32_t i = 0; i < size; i++, sta_list_node++) {
    
    
    unsigned char* mac = sta_list_node->macAddress;
    snprintf(macAddress, sizeof(macAddress), "%02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
    printf("HotspotSta[%d]: macAddress=%s.\r\n",i, macAddress);
    }
    g_apEnableSuccess++;
}
static void OnHotspotStaJoinHandler(StationInfo *info)
{
    
    
    if (info == NULL) {
    
    
    printf("HotspotStaJoin:info is null.\r\n");
    } 
    else {
    
    
        printf("New Sta Join\n");
        osThreadAttr_t attr;
        attr.name = "HotspotStaJoinTask";
        attr.attr_bits = 0U;
        attr.cb_mem = NULL;
        attr.cb_size = 0U;
        attr.stack_mem = NULL;
        attr.stack_size = 2048;
        attr.priority = 24;
        if (osThreadNew((osThreadFunc_t)HotspotStaJoinTask, NULL, &attr) == NULL) {
    
    
            printf("HotspotStaJoin:create task fail!\r\n");
        }
    }
    return;
}

static void OnHotspotStaLeaveHandler(StationInfo *info)
{
    
    
    if (info == NULL) {
    
    
        printf("HotspotStaLeave:info is null.\r\n");
    } 
    else {
    
    
        static char macAddress[32] = {
    
    0};
        unsigned char* mac = info->macAddress;
        snprintf(macAddress, sizeof(macAddress), "%02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
        printf("HotspotStaLeave: macAddress=%s, reason=%d.\r\n", macAddress, info->disconnectedReason);
        g_apEnableSuccess--;
    }
    return;
}

static void OnHotspotStateChangedHandler(int state)
{
    
    
    printf("HotspotStateChanged:state is %d.\r\n", state);
    if (state == WIFI_HOTSPOT_ACTIVE) {
    
    
        printf("wifi hotspot active.\r\n");
    } else {
    
    
        printf("wifi hotspot noactive.\r\n");
    }
}

static void Wifi_AP_Demo(void)
{
    
    
    osThreadAttr_t attr;

    attr.name = "WifiAPTask";
    attr.attr_bits = 0U;
    attr.cb_mem = NULL;
    attr.cb_size = 0U;
    attr.stack_mem = NULL;
    attr.stack_size = 10240;
    attr.priority = 25;

    if (osThreadNew((osThreadFunc_t)WifiAPTask, NULL, &attr) == NULL)
    {
    
    
        printf("Falied to create WifiAPTask!\r\n");
    }
}

APP_FEATURE_INIT(Wifi_AP_Demo);

3.6 查看打印


使用手机连接

四、STA模式

4.1 初始化Wi-Fi事件处理

4.1.1 注册wifi事件的回调函数

通过 RegisterWifiEvent 接口向系统注册扫描状态监听函数,用于接收扫描状态通知,如扫描动作是否完成等

printf("<--Wifi Init-->\r\n");
g_wifiEventHandler.OnWifiScanStateChanged = OnWifiScanStateChangedHandler;
g_wifiEventHandler.OnWifiConnectionChanged = OnWifiConnectionChangedHandler;
g_wifiEventHandler.OnHotspotStaJoin = OnHotspotStaJoinHandler;
g_wifiEventHandler.OnHotspotStaLeave = OnHotspotStaLeaveHandler;
g_wifiEventHandler.OnHotspotStateChanged = OnHotspotStateChangedHandler;
error = RegisterWifiEvent(&g_wifiEventHandler);
if (error != WIFI_SUCCESS)
{
    
    
    printf("register wifi event fail!\r\n");
}
else
{
    
    
    printf("register wifi event succeed!\r\n");
}

4.1.2 绑定连接状态监听

OnWifiConnectionChangedHandler 用于绑定连接状态监听函数,该回调函数有两个参数 state 和 info。

  • state表示扫描状态,取值为0和1,1表示热点连接成功;
  • info表示Wi-Fi连接信息,包含以下参数;
名字 描述
ssid [WIFI_MAX_SSID_LEN] 连接的热点名称.
bssid [WIFI_MAC_LEN] MAC地址.
rssi 接收信号强度(RSSI).
connState Wifi连接状态.
disconnectedReason Wi-Fi断开的原因.
static void OnWifiConnectionChangedHandler(int state, WifiLinkedInfo *info)
{
    
    
    (void)info;

    if (state > 0)
    {
    
    
        g_ConnectSuccess = 1;
        printf("callback function for wifi connect\r\n");
    }
    else
    {
    
    
        printf("connect error,please check password\r\n");
    }
    return;
}

4.2 Wi-Fi启动阶段

调用 EnableWifi 接口,使能 Wifi。
调用 AddDeviceConfig 接口,配置连接的热点信息。

//使能WIFI
if (EnableWifi() != WIFI_SUCCESS)
{
    
    
    printf("EnableWifi failed, error = %d\n", error);
    return -1;
}

//判断WIFI是否激活
if (IsWifiActive() == 0)
{
    
    
    printf("Wifi station is not actived.\n");
    return -1;
}

4.3 Wi-Fi连接阶段

调用 ConnectTo 接口,连接到指定networkId的热点。
调用 WaitConnectResult 接口等待,该函数中会有15s的时间去轮询连接成功标志位
g_ConnectSuccess,当 g_ConnectSuccess 为 1 时退出等待。

//连接指定的WiFi热点
for(uint8_t i = 0; i < ssid_count; i++)
{
    
    
    if (strcmp(SELECT_WIFI_SSID, info[i].ssid) == 0)
    {
    
    
        int result;

        printf("Select:%3d wireless, Waiting...\r\n", i+1);

        //拷贝要连接的热点信息
        strcpy(select_ap_config.ssid, info[i].ssid);
        strcpy(select_ap_config.preSharedKey, SELECT_WIFI_PASSWORD);
        select_ap_config.securityType = SELECT_WIFI_SECURITYTYPE;

        if (AddDeviceConfig(&select_ap_config, &result) == WIFI_SUCCESS)
        {
    
    
            if (ConnectTo(result) == WIFI_SUCCESS && WaitConnectResult() == 1)
            {
    
    
                printf("WiFi connect succeed!\r\n");
                g_lwip_netif = netifapi_netif_find(SELECT_WLAN_PORT);
                break;
            }
        }
    }

    if(i == ssid_count-1)
    {
    
    
        printf("ERROR: No wifi as expected\r\n");
        while(1) osDelay(100);
    }
}

4.4 Wi-Fi“Got IP”阶段

调用 netifapi_netif_find 接口,获取 netif 用于 IP 操作
调用 dhcp_start 接口,启动 DHCP, 获取 IP

//启动DHCP
if (g_lwip_netif)
{
    
    
    dhcp_start(g_lwip_netif);
    printf("begain to dhcp");
}

//等待DHCP
for(;;)
{
    
    
    if(dhcp_is_bound(g_lwip_netif) == ERR_OK)
    {
    
    
        printf("<-- DHCP state:OK -->\r\n");

        //打印获取到的IP信息
        netifapi_netif_common(g_lwip_netif, dhcp_clients_info_show, NULL);
        break;
    }

    printf("<-- DHCP state:Inprogress -->\r\n");
    osDelay(100);
}

4.5 完整代码

编译时在业务BUILD.gn中包含路径

include_dirs = [
        "//utils/native/lite/include",
        "//kernel/liteos_m/components/cmsis/2.0",
        "//base/iot_hardware/interfaces/kits/wifiiot_lite",
        "//foundation/communication/interfaces/kits/wifi_lite/wifiservice",
        "//vendor/hisi/hi3861/hi3861/third_party/lwip_sack/include/",
    ]

修改 SELECT_WIFI_SSIDSELECT_WIFI_PASSWORD 成要连接的WIFI名和密码。

#include <stdio.h>
#include <string.h>
#include <unistd.h>

#include "lwip/netif.h"
#include "lwip/netifapi.h"
#include "lwip/ip4_addr.h"
#include "lwip/api_shell.h"

#include "cmsis_os2.h"
#include "hos_types.h"
#include "wifi_device.h"
#include "wifiiot_errno.h"
#include "ohos_init.h"

#define DEF_TIMEOUT 15

static void WiFiInit(void);
static int WaitConnectResult(void);
static void OnWifiConnectionChangedHandler(int state, WifiLinkedInfo *info);
static void OnHotspotStaJoinHandler(StationInfo *info);
static void OnHotspotStateChangedHandler(int state);
static void OnHotspotStaLeaveHandler(StationInfo *info);

static int g_ConnectSuccess = 0;
WifiEvent g_wifiEventHandler = {
    
    0};
WifiErrorCode error;

#define SELECT_WLAN_PORT "wlan0"

#define SELECT_WIFI_SSID "406"
#define SELECT_WIFI_PASSWORD "82069909"
#define SELECT_WIFI_SECURITYTYPE WIFI_SEC_TYPE_PSK

static BOOL WifiSTATask(void)
{
    
    
    WifiScanInfo *info = NULL;
    unsigned int size = WIFI_SCAN_HOTSPOT_LIMIT;
    static struct netif *g_lwip_netif = NULL;
    WifiDeviceConfig select_ap_config = {
    
    0};

    osDelay(200);
    printf("<--System Init-->\r\n");

    //初始化WIFI
    WiFiInit();

    //使能WIFI
    if (EnableWifi() != WIFI_SUCCESS)
    {
    
    
        printf("EnableWifi failed, error = %d\n", error);
        return -1;
    }

    //判断WIFI是否激活
    if (IsWifiActive() == 0)
    {
    
    
        printf("Wifi station is not actived.\n");
        return -1;
    }
    
    int result;

    //拷贝要连接的热点信息
    strcpy(select_ap_config.ssid, SELECT_WIFI_SSID);
    strcpy(select_ap_config.preSharedKey, SELECT_WIFI_PASSWORD);
    select_ap_config.securityType = SELECT_WIFI_SECURITYTYPE;

    if (AddDeviceConfig(&select_ap_config, &result) == WIFI_SUCCESS)
    {
    
    
        if (ConnectTo(result) == WIFI_SUCCESS && WaitConnectResult() == 1)
        {
    
    
            printf("WiFi connect succeed!\r\n");
            g_lwip_netif = netifapi_netif_find(SELECT_WLAN_PORT);
        }
    }

    //启动DHCP
    if (g_lwip_netif)
    {
    
    
        dhcp_start(g_lwip_netif);
        printf("begain to dhcp");
    }


    //等待DHCP
    for(;;)
    {
    
    
        if(dhcp_is_bound(g_lwip_netif) == ERR_OK)
        {
    
    
            printf("<-- DHCP state:OK -->\r\n");

            //打印获取到的IP信息
            netifapi_netif_common(g_lwip_netif, dhcp_clients_info_show, NULL);
            break;
        }

        printf("<-- DHCP state:Inprogress -->\r\n");
        osDelay(100);
    }

    //执行其他操作
    for(;;)
    {
    
    
        osDelay(100);
    }

}

static void WiFiInit(void)
{
    
    
    printf("<--Wifi Init-->\r\n");
    g_wifiEventHandler.OnWifiConnectionChanged = OnWifiConnectionChangedHandler;
    g_wifiEventHandler.OnHotspotStaJoin = OnHotspotStaJoinHandler;
    g_wifiEventHandler.OnHotspotStaLeave = OnHotspotStaLeaveHandler;
    g_wifiEventHandler.OnHotspotStateChanged = OnHotspotStateChangedHandler;
    error = RegisterWifiEvent(&g_wifiEventHandler);
    if (error != WIFI_SUCCESS)
    {
    
    
        printf("register wifi event fail!\r\n");
    }
    else
    {
    
    
        printf("register wifi event succeed!\r\n");
    }
}

static void OnWifiConnectionChangedHandler(int state, WifiLinkedInfo *info)
{
    
    
    (void)info;

    if (state > 0)
    {
    
    
        g_ConnectSuccess = 1;
        printf("callback function for wifi connect\r\n");
    }
    else
    {
    
    
        printf("connect error,please check password\r\n");
    }
    return;
}

static void OnHotspotStaJoinHandler(StationInfo *info)
{
    
    
    (void)info;
    printf("STA join AP\n");
    return;
}

static void OnHotspotStaLeaveHandler(StationInfo *info)
{
    
    
    (void)info;
    printf("HotspotStaLeave:info is null.\n");
    return;
}

static void OnHotspotStateChangedHandler(int state)
{
    
    
    printf("HotspotStateChanged:state is %d.\n", state);
    return;
}

static int WaitConnectResult(void)
{
    
    
    int ConnectTimeout = DEF_TIMEOUT;
    while (ConnectTimeout > 0)
    {
    
    
        sleep(1);
        ConnectTimeout--;
        if (g_ConnectSuccess == 1)
        {
    
    
            printf("WaitConnectResult:wait success[%d]s\n", (DEF_TIMEOUT - ConnectTimeout));
            break;
        }
    }
    if (ConnectTimeout <= 0)
    {
    
    
        printf("WaitConnectResult:timeout!\n");
        return 0;
    }

    return 1;
}

static void WifiClientSTA(void)
{
    
    
    osThreadAttr_t attr;

    attr.name = "WifiSTATask";
    attr.attr_bits = 0U;
    attr.cb_mem = NULL;
    attr.cb_size = 0U;
    attr.stack_mem = NULL;
    attr.stack_size = 10240;
    attr.priority = 24;

    if (osThreadNew((osThreadFunc_t)WifiSTATask, NULL, &attr) == NULL)
    {
    
    
        printf("Falied to create WifiSTATask!\n");
    }
}

APP_FEATURE_INIT(WifiClientSTA);

4.6 查看打印:

五、扫描

#include <stdio.h>
#include <string.h>
#include <unistd.h>

#include "lwip/netif.h"
#include "lwip/netifapi.h"
#include "lwip/ip4_addr.h"
#include "lwip/api_shell.h"

#include "cmsis_os2.h"
#include "hos_types.h"
#include "wifi_device.h"
#include "wifiiot_errno.h"
#include "ohos_init.h"

#define DEF_TIMEOUT 15
#define ONE_SECOND 1

static void WiFiInit(void);
static void WaitSacnResult(void);
static void OnWifiScanStateChangedHandler(int state, int size);

static int g_staScanSuccess = 0;
static int ssid_count = 0;
WifiEvent g_wifiEventHandler = {
    
    0};
WifiErrorCode error;

static BOOL WifiSTATask(void)
{
    
    
    WifiScanInfo *info = NULL;
    unsigned int size = WIFI_SCAN_HOTSPOT_LIMIT;
    static struct netif *g_lwip_netif = NULL;
    WifiDeviceConfig select_ap_config = {
    
    0};

    osDelay(200);
    printf("<--System Init-->\r\n");

    //初始化WIFI
    WiFiInit();

    //使能WIFI
    if (EnableWifi() != WIFI_SUCCESS)
    {
    
    
        printf("EnableWifi failed, error = %d\n", error);
        return -1;
    }

    //判断WIFI是否激活
    if (IsWifiActive() == 0)
    {
    
    
        printf("Wifi station is not actived.\n");
        return -1;
    }

    //分配空间,保存WiFi信息
    info = malloc(sizeof(WifiScanInfo) * WIFI_SCAN_HOTSPOT_LIMIT);
    if (info == NULL)
    {
    
    
        return -1;
    }

    while(1)
    {
    
    
        //轮询查找WiFi列表
        do{
    
    
            //重置标志位
            ssid_count = 0;
            g_staScanSuccess = 0;

            //开始扫描
            Scan();

            //等待扫描结果
            WaitSacnResult();

            //获取扫描列表
            error = GetScanInfoList(info, &size);

        }while(g_staScanSuccess != 1);

        //打印WiFi列表
        printf("********************\r\n");
        for(uint8_t i = 0; i < ssid_count; i++)
        {
    
    
            printf("no:%03d, ssid:%-30s, rssi:%5d\r\n", i+1, info[i].ssid, info[i].rssi/100);
        }
        printf("********************\r\n");
        memset(info, 0, (sizeof(WifiScanInfo) * WIFI_SCAN_HOTSPOT_LIMIT));

        osDelay(1000);
    }
}

static void WiFiInit(void)
{
    
    
    printf("<--Wifi Init-->\r\n");
    g_wifiEventHandler.OnWifiScanStateChanged = OnWifiScanStateChangedHandler;
    error = RegisterWifiEvent(&g_wifiEventHandler);
    if (error != WIFI_SUCCESS)
    {
    
    
        printf("register wifi event fail!\r\n");
    }
    else
    {
    
    
        printf("register wifi event succeed!\r\n");
    }
}

static void OnWifiScanStateChangedHandler(int state, int size)
{
    
    
    (void)state;
    if (size > 0)
    {
    
    
        ssid_count = size;
        g_staScanSuccess = 1;
    }
    return;
}

static void WaitSacnResult(void)
{
    
    
    int scanTimeout = DEF_TIMEOUT;
    while (scanTimeout > 0)
    {
    
    
        sleep(ONE_SECOND);
        scanTimeout--;
        if (g_staScanSuccess == 1)
        {
    
    
            printf("WaitSacnResult:wait success[%d]s\n", (DEF_TIMEOUT - scanTimeout));
            break;
        }
    }
    if (scanTimeout <= 0)
    {
    
    
        printf("WaitSacnResult:timeout!\n");
    }
}

static void WifiClientSTA(void)
{
    
    
    osThreadAttr_t attr;

    attr.name = "WifiSTATask";
    attr.attr_bits = 0U;
    attr.cb_mem = NULL;
    attr.cb_size = 0U;
    attr.stack_mem = NULL;
    attr.stack_size = 10240;
    attr.priority = 24;

    if (osThreadNew((osThreadFunc_t)WifiSTATask, NULL, &attr) == NULL)
    {
    
    
        printf("Falied to create WifiSTATask!\n");
    }
}

APP_FEATURE_INIT(WifiClientSTA);

查看打印:


• 由 Leung 写于 2021 年 12 月 14 日

• 参考:【鸿蒙2.0设备开发教程】小熊派HarmonyOS 鸿蒙·季 开发教程

猜你喜欢

转载自blog.csdn.net/qq_36347513/article/details/121938584