问题:如何在设备上进行 WIFI 编程?

Lwip (Light weight IP) 简介

  • Lwip 是轻量化的TCP/IP,是一个小型开源的 TCP/IP 协议栈
  • LwIP 的设计目标是用较少的资源实现完成的 TCP/IP 协议栈
  • Lwip 能在操作系统中运行,也能在无操作系统的情况下独立运行
  • Lwip 提供了 Socket API 和 Netconn API

Lwip 的主要特性

  • 支持 ARP, ICMP, IGMP
  • 支持 UDP, TCP, IP (可执行网络通讯框架)
  • 支持 DNS, PPP, SNMP
  • 直至 DHCP, 可动态分配 IP (WIFI 支持)
  • 。。。

BearPi-Nano 联网能力

  • BearPi-Nano 基于 Hi3861 芯片构建,而 Hi3861 自身具备 Wifi 能力

    • AP 模式:工作于 WIFI 热点模式,可被其它设备以 WIFI 方式连接
    • STA 模式:工作于 WIFI 连接模式,可连接到指定 WIFI 热点

WIFI 模块接口设计

init Wifi_Init(void);
init Wifi_Connect(const char *id, const char *pwd);
int Wifi_Start(void);
int Wifi_IsOk(void);
void Wifi_Stop(void);
char *Wifi_IpAddr(void);

涉及的 OH 系统接口

WifiErrorCode RegisterWifiEvent(WifiEvent *event);
WifiErrorCode EnableWifi(void);
WifiErrorCode AddDeviceConfig(const WifiDeviceConfig *config, int result);
WifiErrorCode ConnetTo(int networkid);  // 通过网络标识连接到目标热点
struct netif *netifapi_netif_find(const char *name);  // 获取 netif 结构体用于后续 dhcp 操作
err_t dhcp_start(struct netif *netif);  // 启动 hdcp, 获取 ip

WIFI 热点连接流程

image.png

WIFI 联网关键参数实现

int Wifi_Init(void)
{
    g_WifiEventHandler.OnWifiScanStateChanged = OnWifiScanStateChanged;
    g_WifiEventHandler.OnWifiConnectionChanged = OnWifiConnectionChanged;
    g_WifiEventHandler.OnHotspotStaJoin = OnHotspotStaJoin;
    g_WifiEventHandler.OnHotspotStaLeave = OnHotspotStaLeave;
    g_WifiEventHandler.OnHotspotStateChanged = OnHotspotStateChanged;

    return RegisterWifiEvent(&g_WifiEventHandler);
}
int Wifi_Connect(const char* id, const char* pwd)
{
    int ret = WIFI_SUCCESS;

    if( !Wifi_IsOk() )
    {
        ret = id && pwd ? EnableWifi() : ERROR_WIFI_UNKNOWN;
        // ret = (ret == WIFI_SUCCESS) ? && IsWifiActive() ? WIFI_SUCCESS : ERROR_WIFI_NOT_AVAILABLE;

        if( ret == WIFI_SUCCESS )
        {
            WifiDeviceConfig config = {0};
            int result = 0;

            config.securityType = WIFI_SEC_TYPE_PSK;

            strcpy(config.ssid, id);
            strcpy(config.preSharedKey, pwd);

            ret += AddDeviceConfig(&config, &result);
            ret += ConnectTo(result);

            if( ret == WIFI_SUCCESS )
            {
                ClearWaitResult();

                ToWait(WIFI_TIMEOUT);

                ret = (GetWaitResult() > 0) ? WIFI_SUCCESS : ERROR_WIFI_UNKNOWN;
            }
        }
    }

    return ret;
}
int Wifi_Start(void)
{
    int ret = WIFI_SUCCESS;

    if( !Wifi_IsOk() )
    {
        g_LwipNetif = netifapi_netif_find(WLAN_PORT);

        if( g_LwipNetif )
        {
            int i = WIFI_TIMEOUT;

            if( dhcp_start(g_LwipNetif) == ERR_OK )
            {
                while( ((ret = dhcp_is_bound(g_LwipNetif)) != ERR_OK) && i-- )
                {
                    usleep(200 * 1000);
                }
            }

            if( ret != WIFI_SUCCESS )
            {
                Wifi_Stop();
            }
        }
        else
        {
            ret = ERROR_WIFI_UNKNOWN;
        }
    }

    return ret;
}

编程实验

main_entry.c

#include <stdio.h>
#include <unistd.h>
#include "ohos_init.h"
#include "cmsis_os2.h"
#include "wifi_connect.h"

static void* Init_Task(const char* arg)
{
    Wifi_Init();
    Wifi_Connect("Py4OH-Test", "12345678");
    Wifi_Start();

    if( Wifi_IsOk() )
    {
        printf("IP: %s\n", Wifi_IpAddr());
    }

    return arg;
}

static void Main_Entry(void)
{
    osThreadAttr_t attr = {0};
    
    attr.name = "Init Task";
    attr.stack_size = 1024 * 4;
    attr.priority = 20;

    if( osThreadNew((osThreadFunc_t)Init_Task, NULL, &attr) == NULL )
    {
        printf("[dt4sw] Failed to create task!\n");
    }
}

SYS_RUN(Main_Entry);

wifi_connect.h


#ifndef WIFI_CONNECT_H
#define WIFI_CONNECT_H

int Wifi_Init(void);
int Wifi_Connect(const char* id, const char* pwd);
int Wifi_Start(void);
int Wifi_IsOk(void);
void Wifi_Stop(void);
char* Wifi_IpAddr(void);

#endif

wifi_connect.c

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

#include "wifi_connect.h"
#include "wifi_device.h"
#include "lwip/netif.h"
#include "lwip/netifapi.h"
#include "lwip/ip4_addr.h"
#include "lwip/api_shell.h"
#include "lwip/dhcp.h"

#define WIFI_TIMEOUT 20
#define WLAN_PORT    "wlan0"

static int g_WaitResult = 0;
static WifiEvent g_WifiEventHandler = {0};
static struct netif* g_LwipNetif = NULL;

static void ClearWaitResult(void)
{
    g_WaitResult = 0;
}

static void SetWaitResult(int result)
{
    g_WaitResult = result;
}

static int GetWaitResult(void)
{
    return g_WaitResult;
}

static void ToWait(unsigned int sec)
{
    while( sec-- && !GetWaitResult() )
    {
        sleep(1);
    }
}

static void OnWifiScanStateChanged(int state, int size)
{
    (void)state;
    (void)size;
}

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

    SetWaitResult(state);
}

static void OnHotspotStaJoin(StationInfo *info)
{
    (void)info;
}

static void OnHotspotStateChanged(int state)
{
    (void)state;
}

static void OnHotspotStaLeave(StationInfo *info)
{
    (void)info;
}

int Wifi_Init(void)
{
    g_WifiEventHandler.OnWifiScanStateChanged = OnWifiScanStateChanged;
    g_WifiEventHandler.OnWifiConnectionChanged = OnWifiConnectionChanged;
    g_WifiEventHandler.OnHotspotStaJoin = OnHotspotStaJoin;
    g_WifiEventHandler.OnHotspotStaLeave = OnHotspotStaLeave;
    g_WifiEventHandler.OnHotspotStateChanged = OnHotspotStateChanged;

    return RegisterWifiEvent(&g_WifiEventHandler);
}

int Wifi_Connect(const char* id, const char* pwd)
{
    int ret = WIFI_SUCCESS;

    if( !Wifi_IsOk() )
    {
        ret = id && pwd ? EnableWifi() : ERROR_WIFI_UNKNOWN;
        // ret = (ret == WIFI_SUCCESS) ? && IsWifiActive() ? WIFI_SUCCESS : ERROR_WIFI_NOT_AVAILABLE;

        if( ret == WIFI_SUCCESS )
        {
            WifiDeviceConfig config = {0};
            int result = 0;

            config.securityType = WIFI_SEC_TYPE_PSK;

            strcpy(config.ssid, id);
            strcpy(config.preSharedKey, pwd);

            ret += AddDeviceConfig(&config, &result);
            ret += ConnectTo(result);

            if( ret == WIFI_SUCCESS )
            {
                ClearWaitResult();

                ToWait(WIFI_TIMEOUT);

                ret = (GetWaitResult() > 0) ? WIFI_SUCCESS : ERROR_WIFI_UNKNOWN;
            }
        }
    }

    return ret;
}

int Wifi_Start(void)
{
    int ret = WIFI_SUCCESS;

    if( !Wifi_IsOk() )
    {
        g_LwipNetif = netifapi_netif_find(WLAN_PORT);

        if( g_LwipNetif )
        {
            int i = WIFI_TIMEOUT;

            if( dhcp_start(g_LwipNetif) == ERR_OK )
            {
                while( ((ret = dhcp_is_bound(g_LwipNetif)) != ERR_OK) && i-- )
                {
                    usleep(200 * 1000);
                }
            }

            if( ret != WIFI_SUCCESS )
            {
                Wifi_Stop();
            }
        }
        else
        {
            ret = ERROR_WIFI_UNKNOWN;
        }
    }

    return ret;
}

int Wifi_IsOk(void)
{
    return !!g_LwipNetif;
}

void Wifi_Stop(void)
{
    dhcp_stop(g_LwipNetif);

    g_LwipNetif = NULL;
}

char* Wifi_IpAddr(void)
{
    char* ret = NULL;
    
    if( Wifi_IsOk() )
    {
        ip4_addr_t addr = {0};
        ip4_addr_t mask = {0};
        ip4_addr_t gw = {0};

        netif_get_addr(g_LwipNetif, &addr, &mask, &gw);

        if( (addr.addr != 0) && (addr.addr != -1) )
        {
            ret = ip4addr_ntoa(&addr);
        }
        else
        {
            Wifi_Stop();
        }
    }

    return ret;
}

TianSong
737 声望139 粉丝

阿里山神木的种子在3000年前已经埋下,今天不过是看到当年注定的结果,为了未来的自己,今天就埋下一颗好种子吧