BearPi-HM_Nano开发板WiFi编程开发——Wifi AP 热点 原创

小熊派开源社区
发布于 2021-7-13 13:44
浏览
1收藏

BearPi-HM_Nano开发板WiFi编程开发——Wifi AP 热点

本示例将演示如何在BearPi-HM_Nano开发板上编写一个创建Wifi热点程序

BearPi-HM_Nano开发板WiFi编程开发——Wifi AP 热点-鸿蒙开发者社区

Wifi API分析

本案例主要使用了以下几个API完成Wifi热点创建

依赖文件:

foundation\communication\interfaces\kits\wifi_lite\wifiservice\wifi_device.h
foundation\communication\interfaces\kits\wifi_lite\wifiservice\wifi_hotspot.h

RegisterWifiEvent()

WifiErrorCode RegisterWifiEvent (WifiEvent * event)

描述:
为指定的Wi-Fi事件注册回调函数。当WifiEvent中定义的Wi-Fi事件发生时,将调用已注册的回调函数
参数:

名字 描述
event 表示要注册回调的事件.

EnableHotspot()

WifiErrorCode EnableHotspot (void )

描述:

启用Wifi热点模式

SetHotspotConfig()

WifiErrorCode SetHotspotConfig(const HotspotConfig* config)

描述:

设置指定的热点配置

IsHotspotActive()

int IsHotspotActive(void);

描述:
检查AP热点模式是否启用

GetStationList()

WifiErrorCode GetStationList(StationInfo* result, unsigned int* size)

描述:

获取连接到该热点的一系列STA

参数:

名字 描述
result 表示连接到该热点的STA列表.
size 表示连接到该热点的STA数量

软件设计

主要代码分析

完成Wifi热点的扫描需要以下几步

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

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

      • state表示是否开启AP模式,取值为0和1,0表示已启用Wifi AP模式,1表示已禁用Wifi AP模式;
    • OnHotspotStaLeaveHandler 用于绑定STA站点退出事件,当有STA站点退出,该回调函数会打印出退出站点的MAC地址;

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

  2. 调用 SetHotspotConfig 接口,设置指定的热点配置;

  3. 调用 EnableHotspot 接口,使能 Wifi AP 模式;

  4. 调用 IsHotspotActive 接口,检查AP热点模式是否启用;

  5. 调用 netifapi_netif_set_addr 函数设置网卡信息;

  6. 调用 netifapi_dhcps_start 函数启动dhcp服务;

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");

    }

    /****************以下为UDP服务器代码***************/
	//在sock_fd 进行监听
    int sock_fd;
    //服务端地址信息
	struct sockaddr_in server_sock;

    //创建socket
	if ((sock_fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
	{
		perror("socket is error.\r\n");
		return -1;
	}

	bzero(&server_sock, sizeof(server_sock));
	server_sock.sin_family = AF_INET;
	server_sock.sin_addr.s_addr = htonl(INADDR_ANY);
	server_sock.sin_port = htons(8888);

	//调用bind函数绑定socket和地址
	if (bind(sock_fd, (struct sockaddr *)&server_sock, sizeof(struct sockaddr)) == -1)
	{
		perror("bind is error.\r\n");
		return -1;
	}

    int ret;
    char recvBuf[512] = {0};
    //客户端地址信息
    struct sockaddr_in client_addr;
    int size_client_addr= sizeof(struct sockaddr_in);
    while (1)
    {
        
        printf("Waiting to receive data...\r\n");
        memset(recvBuf, 0, sizeof(recvBuf));
        ret = recvfrom(sock_fd, recvBuf, sizeof(recvBuf), 0, (struct sockaddr*)&client_addr,(socklen_t*)&size_client_addr);
        if(ret < 0)
        {
            printf("UDP server receive failed!\r\n");
            return -1;
        }
        printf("receive %d bytes of data from ipaddr = %s, port = %d.\r\n", ret, inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
        printf("data is %s\r\n",recvBuf);
        ret = sendto(sock_fd, recvBuf, strlen(recvBuf), 0, (struct sockaddr *)&client_addr, sizeof(client_addr));
        if (ret < 0)
        {
            printf("UDP server send failed!\r\n");
            return -1;
        }
    }
    /*********************END********************/
}

编译调试

修改 BUILD.gn 文件

修改 applications\BearPi\BearPi-HM_Nano\sample 路径下 BUILD.gn 文件,指定 wifi_ap 参与编译。

"D1_iot_wifi_ap:wifi_ap",
#"D2_iot_wifi_sta_connect:wifi_sta_connect",        
#"D3_iot_udp_client:udp_client",
#"D4_iot_tcp_server:tcp_server",
#"D5_iot_mqtt:iot_mqtt",        
#"D6_iot_cloud_oc:oc_mqtt",
#"D7_iot_cloud_onenet:onenet_mqtt",

运行结果

示例代码编译烧录代码后,按下开发板的RESET按键,通过串口助手查看日志,使用手机去连接该热点,会打印出一下信息。

RegisterWifiEvent succeed!

SetHotspotConfig succeed!

HotspotStateChanged:state is 1.

EnableHotspot succeed!

Wifi station is actived!

+NOTICE:STA CONNECTED
New Sta Join
HotspotSta[0]: macAddress=EC:5C:68:5B:2D:3D.

netifapi_netif_set_addr succeed!

netifapi_dhcps_start succeed!

Waiting to receive data...

©著作权归作者所有,如需转载,请注明出处,否则将追究法律责任
已于2021-7-13 13:53:01修改
3
收藏 1
回复
举报
3条回复
按时间正序
/
按时间倒序
lxf8023
lxf8023

请问用3.0的代码开启热点的时候第71行启动DHCP为什么会失败呢?

ret = netifapi_dhcps_start(g_lwip_netif, 0, 0);

其他都是正常的 ,就这里会返回-1,日志如下:

[21:54:17.892]收←◆RegisterWifiEvent succeed!
SetHotspotConfig succeed!

[21:54:18.329]收←◆HotspotStateChanged:state is 1.
wifi hotspot active.
EnableHotspot succeed!
Wifi station is actived!
netifapi_netif_set_addr succeed!
netifapi_dhcp_start failed, error = -1.

然后我的gn文件是这样改的:

static_library("wifi_ap") {
    sources = [
        "wifi_ap.c"
    ]
    cflags = [ "-Wno-unused-variable" ]
    include_dirs = [
        "//utils/native/lite/include",
        "//kernel/liteos_m/components/cmsis/2.0",
        "//base/iot_hardware/peripheral/interfaces/kits",
        "//foundation/communication/wifi_lite/interfaces/wifiservice",
        "//vendor/hisi/hi3861/hi3861/third_party/lwip_sack/include/",
    ]

}

其他都没有改动。

回复
2022-3-12 21:58:58
HJY88168
HJY88168

链接成功之后,但无法上网,请问是什么原因?

IP地址、网关、子网掩码已经设置好,是电脑的地址,还有哪里要设置吗

回复
2022-5-18 23:27:28
wx64912a40cff05
wx64912a40cff05 回复了 lxf8023
请问用3.0的代码开启热点的时候第71行启动DHCP为什么会失败呢? ret = netifapi_dhcps_start(g_lwip_netif, 0, 0); 其他都是正常的 ,就这里会返回-1,日志如下: [21:54:17.892]收&larr;◆RegisterWifiEvent succeed!SetHotspotConfig succeed! [21:54:18.329]收&larr;◆HotspotStateChanged:state is 1.wifi hotspot active.EnableHotspot succeed!Wifi station is actived!netifapi_netif_set_addr succ...

这么做就OK了

 //要先关闭dhcp,否则直接进行第四步开启dhcp会产生内存报错
    netifapi_dhcps_stop(g_lwip_netif);
    ret = netifapi_dhcps_start(g_lwip_netif, 0, 0);


回复
2023-6-20 12:26:56
回复
    相关推荐