- 学习目标
- 学习内容
- 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 initWifiErrorCode 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 enableerror = 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 activeif (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 wifiif (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 dhcpnetifapi_set_hostname(g_lwip_netif, hostname, strlen(hostname));netifapi_dhcp_start(g_lwip_netif);// wait dhcpwhile (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`描述的是当前子系统服务的一些配置。```bashgroup("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 taskif (osThreadNew((osThreadFunc_t)startAP, NULL, &attr) == NULL) {printf("Failed to create say hello Thread!\n");}
}
APP_FEATURE_INIT(main);
```cstatic_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 taskif (osThreadNew((osThreadFunc_t)startSta, NULL, &attr) == NULL) {printf("Failed to create say hello Thread!\n");}
}
APP_FEATURE_INIT(main);
```cstatic_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
