问题
如何在设备上进行 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 模块接口设计
涉及的 OH 系统接口
Wifi 热点连接流程
Wifi 联网关键函数实现
Wifi 模块实现
wifi_connect.h
#ifndef WIFI_CONNECT_H
#define WIFI_CONNTCE_H
int Wifi_Init(void);
int Wifi_Connect(const char* ssid, const char* password);
int Wifi_Start(void);
void Wifi_Stop(void);
int Wifi_IsOk(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_TIMMEOUT 20
#define WLAN_PORT "wlan0"
static WifiEvent g_WifiEventHandler = {0};
static int g_WaitResult = 0;
static struct netif* g_LwipNeif = NULL;
void ClearWaitResult(void)
{
g_WaitResult = 0;
}
void SetWaitResult(int result)
{
g_WaitResult = result;
}
int GetWaitResult(void)
{
return g_WaitResult;
}
void ToWait(int timeout)
{
while((GetWaitResult() == 0) && timeout--)
{
sleep(1);
}
}
void OnWifiConnectionChanged(int state, WifiLinkedInfo* info)
{
(void)info;
g_WaitResult = state;
}
void OnWifiScanStateChanged(int state, int size)
{
(void)state;
(void)size;
}
void OnHotspotStateChanged(int state)
{
(void)state;
}
void OnHotspotStaJoin(StationInfo* info)
{
(void)info;
}
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* ssid, const char* password)
{
int ret = WIFI_SUCCESS;
if(!Wifi_IsOk())
{
ret = (ssid && password) ? EnableWifi() : ERROR_WIFI_UNKNOWN;
if(ret == WIFI_SUCCESS)
{
WifiDeviceConfig config = {0};
int result = 0;
config.securityType = WIFI_SEC_TYPE_PSK;
strcpy(config.ssid, ssid);
strcpy(config.preSharedKey, password);
ret += AddDeviceConfig(&config, &result);
ret += ConnectTo(result);
if(ret == WIFI_SUCCESS)
{
ClearWaitResult();
ToWait(WIFI_TIMMEOUT);
ret = (GetWaitResult() != 0) ? WIFI_SUCCESS : ERROR_WIFI_UNKNOWN;
}
else
{
ret = ERROR_WIFI_UNKNOWN;
}
}
}
return ret;
}
int Wifi_Start(void)
{
int ret = WIFI_SUCCESS;
if(!Wifi_IsOk())
{
g_LwipNeif = netifapi_netif_find(WLAN_PORT);
if(g_LwipNeif != NULL)
{
if(dhcp_start(g_LwipNeif) == ERR_OK)
{
int i = WIFI_TIMMEOUT;
while(((ret = dhcp_is_bound(g_LwipNeif)) != ERR_OK) && i--)
{
usleep(200 * 1000);
}
}
if(ret != WIFI_SUCCESS)
{
Wifi_Stop();
}
}
else
{
ret = ERROR_WIFI_UNKNOWN;
}
}
return ret;
}
void Wifi_Stop(void)
{
dhcp_stop(g_LwipNeif);
g_LwipNeif = NULL;
}
int Wifi_IsOk(void)
{
return !!g_LwipNeif;
}
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_LwipNeif, &addr, &mask, &gw);
if((addr.addr != 0) && (addr.addr != -1))
{
ret = ip4addr_ntoa(&addr);
}
else
{
Wifi_Stop();
}
}
return ret;
}
main_entry.c
#include <stdio.h>
#include "ohos_init.h"
#include "cmsis_os2.h"
#include "wifi_connect.h"
static void* Task_Iniit(const char* arg)
{
Wifi_Init();
Wifi_Connect("wifi_test", "12345678");
Wifi_Start();
if(Wifi_IsOk)
{
printf("addr = %s\n", Wifi_IpAddr());
}
return arg;
}
static void Main_Entry(void)
{
osThreadAttr_t attr = {0};
attr.name = "Task_Iniit";
attr.stack_size = 4 * 1024;
attr.priority = 20;
if(osThreadNew((osThreadFunc_t)Task_Iniit, NULL, &attr) == NULL)
{
printf("failed to create task!\n");
}
}
SYS_RUN(Main_Entry);
测试结果如下图所示
Hi3861成功连上 Wifi, IP 为192.168.137.48
课后思考
有了 Wifi 模块后,接下来应该干啥?