一、简介
参看上一章:鸿蒙Hi3861学习十四-Huawei LiteOS-M(STA模式)_t_guest的博客-CSDN博客
二、API介绍
RegisterWifiEvent
函数功能:
为指定的WIFI事件注册回调函数。当WIFIEVENT中定义的WIFI事件发生时,将调用已注册的回调函数。
函数原型:
WifiErrorCode RegisterWifiEvent(WifiEvent* event)
参数:
event:相关事件,结构体为WifiEvent。
typedef struct {
/** Connection state change */
void (*OnWifiConnectionChanged)(int state, WifiLinkedInfo* info);
/** Scan state change */
void (*OnWifiScanStateChanged)(int state, int size);
/** Hotspot state change */
void (*OnHotspotStateChanged)(int state);
/** Station connected */
void (*OnHotspotStaJoin)(StationInfo* info);
/** Station disconnected */
void (*OnHotspotStaLeave)(StationInfo* info);
} WifiEvent;
OnWifiConnectionChanged:网络连接状态改变回调。与STA有关。具体含义见上一章。
OnWifiScanStateChanged:扫描结果回调。与STA有关。具体含义见上一章。
OnHotspotStateChanged:热点状态改变回调,即热点创建时的回调。与AP有关。state热点状态。WIFI_HOTSPOT_ACTIVE(1)热点已创建成功。WIFI_HOTSPOT_NOT_ACTIVE(0)热点已关闭。
OnHotspotStaJoin:有STA连接回调,与AP有关。info为连接上的STA相关信息。
typedef struct {
/** MAC address. For its length, see {@link WIFI_MAC_LEN}. */
unsigned char macAddress[WIFI_MAC_LEN];
unsigned short disconnectedReason;
} StationInfo;
macAddress:MAC地址
disconnectedReason:断连原因
OnHotspotStaLeave:STA断开连接的回调,与AP有关。indo为连接上的STA相关信息。
返回值:
WIFI_SUCCESS:成功
其他值:失败
实例:
WifiEvent g_wifiEventHandler = {0};
//注册wifi事件的回调函数
g_wifiEventHandler.OnHotspotStaJoin = OnHotspotStaJoinHandler; //STA连接的回调
g_wifiEventHandler.OnHotspotStaLeave = OnHotspotStaLeaveHandler; //STA断开连接的回调
g_wifiEventHandler.OnHotspotStateChanged = OnHotspotStateChangedHandler; //热点状态改变的回调
error = RegisterWifiEvent(&g_wifiEventHandler); //注册任务
SetHotspotConfig
函数功能:
设置指定的热点配置
函数原型:
WifiErrorCode SetHotspotConfig(const HotspotConfig* config)
参数:
config:热点配置参数。结构体类型为:HotspotConfig
typedef struct {
/** Service set ID (SSID). For its length, see {@link WIFI_MAX_SSID_LEN}. */
char ssid[WIFI_MAX_SSID_LEN];
/** Security type */
int securityType;
/** Frequency band */
int band;
/** Channel number */
int channelNum;
/** Key. For its length, see {@link WIFI_MAX_SSID_LEN}. */
char preSharedKey[WIFI_MAX_KEY_LEN];
} HotspotConfig;
ssid:热点名
securityType:加密类型,具体如下:
typedef enum {
/** Invalid security type */
WIFI_SEC_TYPE_INVALID = -1,
/** Open */
WIFI_SEC_TYPE_OPEN,
/** Wired Equivalent Privacy (WEP) */
WIFI_SEC_TYPE_WEP,
/** Pre-shared key (PSK) */
WIFI_SEC_TYPE_PSK,
/** Simultaneous Authentication of Equals (SAE) */
WIFI_SEC_TYPE_SAE,
} WifiSecurityType;
band:带宽。2.4G还是5G
channelNum:通道号
preSharedKey:加密密钥。可不填。
返回值:
WIFI_SUCCESS:成功
其他值:失败
实例:
WifiErrorCode error;
HotspotConfig config = {0};
strcpy(config.ssid, "Harmony_test_ap"); //设置SSID
strcpy(config.preSharedKey, "0987654321"); //设置密码
config.securityType = WIFI_SEC_TYPE_PSK; //加密类型
config.band = HOTSPOT_BAND_TYPE_2G; //频率类型
config.channelNum = 7; //信道
error = SetHotspotConfig(&config); //配置热点
EnableHotspot
函数功能:
启用WIFI热点模式
函数原型:
WifiErrorCode EnableHotspot(void)
参数:
无
返回值:
WIFI_SUCCESS:成功
其他值:失败
实例:
WifiErrorCode error;
error = EnableHotspot(); //使能热点
IsHotspotActive
函数功能:
检查AP热点模式是否启用
函数原型:
int IsHotspotActive(void)
参数:
无
返回值:
#define WIFI_HOTSPOT_NOT_ACTIVE 0
#define WIFI_HOTSPOT_ACTIVE 1
其他值:失败
实例:
if (IsHotspotActive() == WIFI_HOTSPOT_NOT_ACTIVE)
{}
netifapi_netif_find
函数功能:
获取网络接口用于IP操作。
函数原型:
struct netif *netifapi_netif_find(const char *name);
参数:
name:网络接口名称。STA为“wlan0”,AP为“ap0”。为什么是这俩,还没搞清楚。搞清楚后会回来补充。
返回值:
NULL:失败
其他值:网络接口值。netif:LwIP网络接口
实例:
struct netif *g_lwip_netif = NULL;
g_lwip_netif = netifapi_netif_find("ap0"); //获取网络借口,用于IP操作
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:网络接口。netifapi_netif_find获得。
ipaddr:自身IP地址
netmask:子网掩码
gw:网关IP
返回值:
ERR_OK:成功
其他值:失败
实例:
struct netif *g_lwip_netif = NULL;
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); //设置IP
netifapi_dhcps_start
函数功能:
启动SoftAp的DHCP服务器。
函数原型:
err_t netifapi_dhcps_start(struct netif *netif, char *start_ip, u16_t ip_num)
参数:
netif:网络接口。netifapi_netif_find获得。
start_ip:DHCP起始地址,默认0,自动分配
ip_num:IP池数量,默认0,自动分配
返回值:
ERR_OK:成功
其他值:失败
实例:
struct netif *g_lwip_netif = NULL;
err_t ret = netifapi_dhcps_start(g_lwip_netif, 0, 0); //启动DHCP
GetStationList
函数功能:
获取连接到该热点的一系列STA信息。注:该函数不能在OnHotspotStaJoin回调中使用。
函数原型:
WifiErrorCode GetStationList(StationInfo* result, unsigned int* size)
参数:
result:输出值,STA信息列表。
size:输出值,列表中STA的数量
返回值:
WIFI_SUCCESS:成功
其他值:失败
实例:
StationInfo stainfo[WIFI_MAX_STA_NUM] = {0};
unsigned int size = 0;
error = GetStationList(stainfo, &size);
三、实例
这里创建一个名为“Harmony_test_ap”的热点,供STA连接。
在BUILD.gn中添加如下代码:
include_dirs = [
"//utild/native/lite/include",
"//base/iot_hardware/interfaces/kits/wifiiot_lite",
"//utils/native/lite/include",
"//kernel/liteos_m/components/cmsis/2.0",
"//foundation/communication/interfaces/kits/wifi_lite/wifiservice",
"//vendor/hisi/hi3861/hi3861/third_party/lwip_sack/include/",
"src",
]
#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 LOG_I(fmt, args...) printf("<%8ld> - [AP]:"fmt"\r\n",osKernelGetTickCount(),##args);
#define LOG_E(fmt, args...) printf("<%8ld>-[AP_ERR]>>>>>>>>>>>>:"fmt"\r\n",osKernelGetTickCount(), ##args);
#define AP_SSID "Harmony_test_ap"
#define AP_PSK "123123123"
#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;
WifiEvent g_wifiEventHandler = {0};
WifiErrorCode error;
/*STA加入的任务*/
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)
{
LOG_E("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]);
LOG_I("HotspotSta[%d]: macAddress=%s.\r\n", i, macAddress);
}
}
/*STA连接的回调*/
static void OnHotspotStaJoinHandler(StationInfo *info)
{
if (info == NULL)
{
LOG_E("HotspotStaJoin:info is null.\r\n");
}
else
{
LOG_I("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)
{
LOG_E("HotspotStaJoin:create task fail!\r\n");
}
}
return;
}
/*STA断开连接的回调*/
static void OnHotspotStaLeaveHandler(StationInfo *info)
{
if (info == NULL) {
LOG_E("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]);
LOG_I("HotspotStaLeave: macAddress=%s, reason=%d.\r\n", macAddress, info->disconnectedReason);
}
return;
}
/*热点状态改变的回调*/
static void OnHotspotStateChangedHandler(int state)
{
LOG_I("HotspotStateChanged:state is %d.\r\n", state);
if (state == WIFI_HOTSPOT_ACTIVE) {
LOG_I("wifi hotspot active.\r\n");
} else {
LOG_I("wifi hotspot noactive.\r\n");
}
}
/*WIFI AP 任务*/
static BOOL WifiAPTask(void)
{
//延时2S便于查看日志
osDelay(200);
//注册wifi事件的回调函数
g_wifiEventHandler.OnHotspotStaJoin = OnHotspotStaJoinHandler; //STA连接的回调
g_wifiEventHandler.OnHotspotStaLeave = OnHotspotStaLeaveHandler; //STA断开连接的回调
g_wifiEventHandler.OnHotspotStateChanged = OnHotspotStateChangedHandler; //热点状态改变的回调
error = RegisterWifiEvent(&g_wifiEventHandler); //注册任务
if (error != WIFI_SUCCESS)
{
LOG_E("RegisterWifiEvent failed, error = %d.\r\n",error);
return -1;
}
LOG_I("RegisterWifiEvent succeed!\r\n");
//设置指定的热点配置
HotspotConfig config = {0};
strcpy(config.ssid, AP_SSID); //设置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)
{
LOG_E("SetHotspotConfig failed, error = %d.\r\n", error);
return -1;
}
LOG_I("SetHotspotConfig succeed!\r\n");
//启动wifi热点模式
error = EnableHotspot(); //使能热点
if (error != WIFI_SUCCESS)
{
LOG_E("EnableHotspot failed, error = %d.\r\n", error);
return -1;
}
LOG_I("EnableHotspot succeed!\r\n");
//检查热点模式是否使能
if (IsHotspotActive() == WIFI_HOTSPOT_NOT_ACTIVE)
{
LOG_E("Wifi station is not actived.\r\n");
return -1;
}
LOG_I("Wifi station is actived!\r\n");
//启动dhcp
g_lwip_netif = netifapi_netif_find("ap0"); //获取网络借口,用于IP操作
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); //设置IP
if(ret != ERR_OK)
{
LOG_E("netifapi_netif_set_addr failed, error = %d.\r\n", ret);
return -1;
}
LOG_I("netifapi_netif_set_addr succeed!\r\n");
ret = netifapi_dhcps_start(g_lwip_netif, 0, 0); //启动DHCP
if(ret != ERR_OK)
{
LOG_E("netifapi_dhcp_start failed, error = %d.\r\n", ret);
return -1;
}
LOG_I("netifapi_dhcps_start succeed!\r\n");
}
while(1)
{
osDelay(100);
}
return 0;
}
/*AP任务创建*/
void drv_ap_task_init(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)
{
LOG_E("Falied to create WifiAPTask!\r\n");
}
}
看结果:
这里是用手机连接的,看一下手机界面的相关属性。
可以看到,IP地址、MAC地址、加密类型、频率都与在程序里设置的相同。