- 学习目标
- 学习内容
- ifndef WIFI_AP_H
- define WIFI_AP_H
- include
- endif //WIFI_AP_H
- Copyright (C) 2020 Itcast Co., Ltd. All rights reserved.
- AP模式调试
- include
- include
- include
- include “cmsis_os2.h”
- include “ohos_init.h”
- include “wifi_ap.h”
- STA模式调试
- include
- include
- include
- include “cmsis_os2.h”
- include “ohos_init.h”
- include “wifi_sta.h”
- 练习题
学习目标
- 能够调用AP模式的API实现网络连接
- 能够调用STA模式的API实现网络连接
- 能够自定义子系统
学习内容
子系统服务构建
开发中,我们需要构建一些功能执行的底座,提供给其他的调用者使用。
例如,wifi功能在我们的开发板中是一个功能服务,只要想上网的都需要使用他。
我们可以把wifi功能加入到自己开发板中来。开发流程
- 在开发板目录下新建一个文件夹
services
。我的开发板目录为device/board/itcast/genkipi
。 - 在
services
目录下新建BUILD.gn
文件,并且配置这个BUILD.gn
文件。 - 在
services
目录下新建wifi
目录,并且在wifi
目录新建BUILD.gn
文件。 - 修改
vendor/itcast/genkipi
目录下的BUILD.gn
。代码部分
```cstatic_library("genkipi_wifi") {
sources = [
"src/wifi_ap.c",
"src/wifi_sta.c"
]
include_dirs = [
"include",
"//foundation/communication/wifi_lite/interfaces/wifiservice",
]
}
ifndef WIFI_AP_H
define WIFI_AP_H
include
/**
- start wifi ap
- @param ssid
- @param password
- @return 0 success / int wifi_ap_start(const char ssid, const char* password);
/**
- stop wifi ap
- @return 0 success */ int wifi_ap_stop(void);
endif //WIFI_AP_H
```c
#ifndef __WIFI_STA_H__
#define __WIFI_STA_H__
/**
* link wifi
* @param ssid
* @param password
* @param hostname
* @return 0 success
*/
int wifi_sta_connect(const char* ssid, const char* password, const char* hostname);
/**
* disconnect wifi
* @return 0 success
*/
int wifi_sta_disconnect(void);
#endif //__WIFI_STA_H__
#include "wifi_ap.h"
#include "wifi_hotspot.h"
#include "cmsis_os2.h"
#include "lwip/netifapi.h"
#include <string.h>
static struct netif *g_iface = NULL;
static volatile int g_hotspotStarted = 0;
static volatile int g_joinedStations = 0;
static char *wifi_ssid = NULL;
static void OnHotspotStateChanged(int state) {
printf("[Debug]OnHotspotStateChanged: %d.\r\n", state);
if (state == WIFI_HOTSPOT_ACTIVE) {
g_hotspotStarted = 1;
} else {
g_hotspotStarted = 0;
}
}
static void OnHotspotStaJoin(StationInfo *info) {
g_joinedStations++;
printf("[Debug]+OnHotspotStaJoin: active stations = %d.\r\n", g_joinedStations);
}
static void OnHotspotStaLeave(StationInfo *info) {
g_joinedStations--;
printf("[Debug]-OnHotspotStaLeave: active stations = %d.\r\n", g_joinedStations);
}
WifiEvent g_defaultWifiEventListener = {
.OnHotspotStaJoin = OnHotspotStaJoin,
.OnHotspotStaLeave = OnHotspotStaLeave,
.OnHotspotStateChanged = OnHotspotStateChanged,
};
int wifi_ap_start(const char *ssid, const char *password) {
WifiErrorCode err_code = WIFI_SUCCESS;
err_code = RegisterWifiEvent(&g_defaultWifiEventListener);
printf("[Debug]RegisterWifiEvent:%d\r\n", err_code);
int len = strlen(ssid);
wifi_ssid = (char *) calloc(len + 1, sizeof(char));
memcpy(wifi_ssid, ssid, len);
wifi_ssid[len] = '\0';
HotspotConfig config = {0};
strcpy(config.ssid, ssid);
strcpy(config.preSharedKey, password);
config.securityType = WIFI_SEC_TYPE_PSK;
config.band = HOTSPOT_BAND_TYPE_2G;
config.channelNum = 7;
err_code = SetHotspotConfig(&config);
printf("[Debug]SetHotspotConfig:%d\r\n", err_code);
g_hotspotStarted = 0;
err_code = EnableHotspot();
printf("[Debug]EnableHotspot: %d\r\n", err_code);
while (!g_hotspotStarted) {
osDelay(10);
}
printf("[Debug]g_hotspotStarted = %d.\r\n", g_hotspotStarted);
g_iface = netifapi_netif_find("ap0");
if (g_iface) {
ip4_addr_t ipaddr, gateway, netmask;
IP4_ADDR(&ipaddr, 192, 168, 10, 1);
IP4_ADDR(&gateway, 192, 168, 10, 1);
IP4_ADDR(&netmask, 255, 255, 255, 0);
err_t ret = netifapi_netif_set_addr(g_iface, &ipaddr, &netmask, &gateway);
printf("[Debug]netifapi_netif_set_addr: %d\r\n", ret);
netifapi_dhcps_start(g_iface, 0, 0);
}
return err_code;
}
int wifi_ap_stop(void) {
if (g_iface) {
err_t ret = netifapi_dhcps_stop(g_iface);
printf("[Debug]netifapi_dhcps_stop: %d\r\n", ret);
}
WifiErrorCode err_code = UnRegisterWifiEvent(&g_defaultWifiEventListener);
printf("[Debug]UnRegisterWifiEvent: %d\r\n", err_code);
err_code = DisableHotspot();
printf("DisableHotspot: %d\r\n", err_code);
return err_code;
}
#include "wifi_sta.h"
#include "ohos_init.h"
#include "ohos_types.h"
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include "cmsis_os2.h"
#include "wifi_device.h"
#include "wifi_event.h"
#include "wifi_error_code.h"
#include "lwip/netif.h"
#include "lwip/netifapi.h"
#include "lwip/ip4_addr.h"
#include "lwip/api_shell.h"
#define DEF_TIMEOUT 15
#define ONE_SECOND 1
#define SELECT_WLAN_PORT "wlan0"
static WifiEvent wifi_event_handler = {0};
static int g_staScanSuccess = 0;
static int g_ConnectSuccess = 0;
static int ssid_count = 0;
static struct netif *g_lwip_netif = NULL;
static char *wifi_ssid = NULL;
static unsigned char is_connected = 0;
static void OnWifiConnectionChanged(int state, WifiLinkedInfo *info) {
(void) info;
if (state > 0) {
g_ConnectSuccess = 1;
printf("[wifi_sta]cb for wifi connect, success\r\n");
} else {
printf("[wifi_sta]cb for wifi connect, failed, please check password\r\n");
}
return;
}
static void OnWifiScanStateChanged(int state, int size) {
(void) state;
if (size > 0) {
ssid_count = size;
g_staScanSuccess = 1;
}
return;
}
static void OnHotspotStateChanged(int state) {
printf("[wifi_sta]cb for HotspotStateChanged:state is %d.\n", state);
return;
}
static void OnHotspotStaJoin(StationInfo *info) {
(void) info;
printf("[wifi_sta]STA join AP\r\n");
return;
}
static void OnHotspotStaLeave(StationInfo *info) {
(void) info;
printf("[wifi_sta]cb for HotspotStaLeave:mac is %s.\r\n", info->macAddress);
return;
}
static WifiErrorCode wifi_init(void) {
WifiErrorCode error;
wifi_event_handler.OnWifiConnectionChanged = OnWifiConnectionChanged;
wifi_event_handler.OnWifiScanStateChanged = OnWifiScanStateChanged;
wifi_event_handler.OnHotspotStateChanged = OnHotspotStateChanged;
wifi_event_handler.OnHotspotStaJoin = OnHotspotStaJoin;
wifi_event_handler.OnHotspotStaLeave = OnHotspotStaLeave;
error = RegisterWifiEvent(&wifi_event_handler);
return error;
}
static void wait_scan_result(void) {
int scanTimeout = DEF_TIMEOUT;
while (scanTimeout > 0) {
sleep(ONE_SECOND);
scanTimeout--;
if (g_staScanSuccess == 1) {
printf("[wifi_sta]wait scan result: wait success[%d]s\n", (DEF_TIMEOUT - scanTimeout));
break;
}
}
if (scanTimeout <= 0) {
printf("[wifi_sta]wait scan result:timeout!\n");
}
}
static int wait_connect_result(void) {
int ConnectTimeout = DEF_TIMEOUT;
while (ConnectTimeout > 0) {
sleep(1);
ConnectTimeout--;
if (g_ConnectSuccess == 1) {
printf("[wifi_sta]wait connect result:wait success[%d]s\n", (DEF_TIMEOUT - ConnectTimeout));
break;
}
}
if (ConnectTimeout <= 0) {
printf("[wifi_sta]wait connect result:timeout!\n");
return 0;
}
return 1;
}
int wifi_sta_connect(const char *ssid, const char *password, const char *hostname) {
// wifi init
WifiErrorCode error = wifi_init();
if (WIFI_SUCCESS != error) {
printf("[wifi_sta]register wifi event failed, error=%d\r\n", error);
return error;
}
printf("[wifi_sta]register wifi event success\r\n");
// wifi enable
error = EnableWifi();
if (WIFI_SUCCESS != error) {
printf("[wifi_sta]enable wifi failed, error=%d\r\n", error);
return error;
}
printf("[wifi_sta]enable wifi success\r\n");
// check wifi active
if (IsWifiActive() == 0) {
printf("[wifi_sta] wifi station is not active\r\n");
return error;
}
int len = strlen(ssid);
wifi_ssid = (char *) calloc(len + 1, sizeof(char));
memcpy(wifi_ssid, ssid, len);
wifi_ssid[len] = '\0';
WifiDeviceConfig ap_config = {0};
strcpy(ap_config.ssid, ssid);
strcpy(ap_config.preSharedKey, password);
ap_config.securityType = WIFI_SEC_TYPE_PSK;
int result;
if (AddDeviceConfig(&ap_config, &result) == WIFI_SUCCESS) {
// connect to wifi
if (ConnectTo(result) == WIFI_SUCCESS && wait_connect_result() == 1) {
printf("[wifi_sta]wifi connect success!\r\n");
g_lwip_netif = netifapi_netif_find(SELECT_WLAN_PORT);
}
}
if (!g_lwip_netif) {
printf("[wifi_sta]netif error \r\n");
return -1;
}
// start dhcp
netifapi_set_hostname(g_lwip_netif, hostname, strlen(hostname));
netifapi_dhcp_start(g_lwip_netif);
// wait dhcp
while (1) {
if (dhcp_is_bound(g_lwip_netif) == ERR_OK) {
printf("[wifi_sta]dhcp bound success\r\n");
netifapi_netif_common(g_lwip_netif, dhcp_clients_info_show, NULL);
break;
}
osDelay(100);
}
is_connected = 1;
return WIFI_SUCCESS;
}
int wifi_sta_disconnect(void) {
if (!g_lwip_netif) {
printf("[wifi_sta]netif error \r\n");
return -1;
}
WifiErrorCode error = Disconnect();
if (WIFI_SUCCESS != error) {
printf("[wifi_sta]disconnect wifi failed, error=%d\r\n", error);
return error;
}
error = DisableWifi();
if (WIFI_SUCCESS != error) {
printf("[wifi_sta]disable wifi failed, error=%d\r\n", error);
return error;
}
error = UnRegisterWifiEvent(&wifi_event_handler);
if (WIFI_SUCCESS != error) {
printf("[wifi_sta]unregister wifi event failed, error=%d\r\n", error);
return error;
}
printf("[wifi_sta]disconnect wifi success\r\n");
is_connected = 0;
return WIFI_SUCCESS;
}
static int get_wifi_local_ip() {
if (!g_lwip_netif) {
printf("[wifi_sta]netif error \r\n");
return -1;
}
ip4_addr_t ip_addr;
ip4_addr_t netmask_addr;
ip4_addr_t gw_addr;
if (netifapi_netif_get_addr(g_lwip_netif, &ip_addr, &netmask_addr, &gw_addr) == ERR_OK) {
u32_t ip = ip_addr.addr;
u32_t netmask = netmask_addr.addr;
u32_t gw = gw_addr.addr;
printf("ip %d.%d.%d.%d\n\r", (ip & 0xff), ((ip >> 8) & 0xff), ((ip >> 16) & 0xff), (ip >> 24));
printf("netmask %d.%d.%d.%d\n\r", (netmask & 0xff), ((netmask >> 8) & 0xff), ((netmask >> 16) & 0xff),
(netmask >> 24));
printf("gw %d.%d.%d.%d\n\r", (gw & 0xff), ((gw >> 8) & 0xff), ((gw >> 16) & 0xff), (gw >> 24));
} else {
printf("netif get addr failed\r\n");
}
return 1;
}
group("genkipi_services") {
deps = [
"wifi:genkipi_wifi"
]
}
# Copyright (C) 2020 Itcast Co., Ltd. All rights reserved.
group("genkipi") {
deps = [
"//device/board/itcast/genkipi:run_genkipi_scons",
"//device/board/itcast/genkipi/app",
"//device/board/itcast/genkipi/iot_hardware_hals",
"//device/board/itcast/genkipi/services:genkipi_services"
]
}
配置说明
vendor/itcast/genkipi/BUILD.gn
描述了开发板提供的服务。deps表示编译依赖。 ```bashCopyright (C) 2020 Itcast Co., Ltd. All rights reserved.
group(“genkipi”) { deps = [ “//device/board/itcast/genkipi:run_genkipi_scons”, “//device/board/itcast/genkipi/app”, “//device/board/itcast/genkipi/iot_hardware_hals”, “//device/board/itcast/genkipi/services:genkipi_services” ] }
- `//device/board/itcast/genkipi/services:genkipi_services`指向了我们刚刚新建的文件夹`services`文件夹下的`BUILD.gn`文件。
2. `services/BUILD.gn`描述的是当前子系统服务的一些配置。
```bash
group("genkipi_services") {
deps = [
"wifi:genkipi_wifi"
]
}
genkipi_services
表示当前子服务名称。group
表示是一个服务集合。- deps表示依赖。
wifi:genkipi_wifi
表示当前services
目录下的wifi
目录中BUILD.gn
配置services/wifi/BUILD.gn
为wifi部分的配置。static_library("genkipi_wifi") {
sources = [
"src/wifi_ap.c",
"src/wifi_sta.c"
]
include_dirs = [
"include",
"//foundation/communication/wifi_lite/interfaces/wifiservice",
]
}
sources
表示源码部分include_dirs
表示需要引入的头AP逻辑说明
AP就是扮演路由器角色,我们开启路由器,需要给路由器配置名称和密码,供其他设备扫描连接用。
AP提供了wifi_ap_start
函数,就是为这个服务的。int wifi_ap_start(const char *ssid, const char *password);
- ssid: 路由器的名称
- password:路由器密码
STA逻辑说明
STA就是扮演类似于手机这种角色,可以连接路由器。
STA提供了wifi_sta_connect
函数,来实现连接路由器的功能。
int wifi_sta_connect(const char *ssid, const char *password, const char *hostname)
- ssid: 要连接的路由器名称
- password:要连接的路由器密码
- hostname: 当前设备在路由器中显示的名称
AP模式调试
开发流程
来到应用开发的根目录。
我们编写代码的根目录为device/board/itcast/genkipi/app
。
- 根目录下新建
ap
文件夹,此为项目目录。 - 此项目目录下新建
main.c
文件 - 此项目目录下新建
BUILD.gn
文件 - 修改根目录下的
BUILD.gn
文件代码部分
```cinclude
include
include
include “cmsis_os2.h”
include “ohos_init.h”
include “wifi_ap.h”
static void startAP(void) { wifi_ap_start(“helloworld”, “12345678”); }
static void main(void) { osThreadAttr_t attr;
attr.name = "ap";
attr.attr_bits = 0U;
attr.cb_mem = NULL;
attr.cb_size = 0U;
attr.stack_mem = NULL;
attr.stack_size = 1024 * 2;
attr.priority = 25;
// Create the Thread1 task
if (osThreadNew((osThreadFunc_t)startAP, NULL, &attr) == NULL) {
printf("Failed to create say hello Thread!\n");
}
}
APP_FEATURE_INIT(main);
```c
static_library("ap") {
sources = [ "main.c" ]
include_dirs = [
"//base/iothardware/peripheral/interfaces/inner_api",
"../../services/wifi/include",
]
deps = [
"../../services:genkipi_services",
]
}
import("//build/lite/config/component/lite_component.gni")
lite_component("app") {
features = [
"ap"
]
}
校验
STA模式调试
开发流程
来到应用开发的根目录。
我们编写代码的根目录为device/board/itcast/genkipi/app
。
- 根目录下新建
sta
文件夹,此为项目目录。 - 此项目目录下新建
main.c
文件 - 此项目目录下新建
BUILD.gn
文件 - 修改根目录下的
BUILD.gn
文件代码部分
```cinclude
include
include
include “cmsis_os2.h”
include “ohos_init.h”
include “wifi_sta.h”
static void startSta(void) { wifi_sta_connect(“xq”, “qwer1234”, “itcast”); }
static void main(void) { osThreadAttr_t attr;
attr.name = "sta";
attr.attr_bits = 0U;
attr.cb_mem = NULL;
attr.cb_size = 0U;
attr.stack_mem = NULL;
attr.stack_size = 1024 * 4;
attr.priority = 25;
// Create the Thread1 task
if (osThreadNew((osThreadFunc_t)startSta, NULL, &attr) == NULL) {
printf("Failed to create say hello Thread!\n");
}
}
APP_FEATURE_INIT(main);
```c
static_library("sta") {
sources = [ "main.c" ]
include_dirs = [
"//base/iothardware/peripheral/interfaces/inner_api",
"../../services/wifi/include",
]
deps = [
"../../services:genkipi_services",
]
}
import("//build/lite/config/component/lite_component.gni")
lite_component("app") {
features = [
"sta"
]
}
校验
练习题
- 通过代码实现AP
- 通过代码实现STA