学习目标

  • 能够调用AP模式的API实现网络连接
  • 能够调用STA模式的API实现网络连接
  • 能够自定义子系统

    学习内容

    子系统服务构建

    开发中,我们需要构建一些功能执行的底座,提供给其他的调用者使用。
    例如,wifi功能在我们的开发板中是一个功能服务,只要想上网的都需要使用他。
    我们可以把wifi功能加入到自己开发板中来。

    开发流程

  1. 在开发板目录下新建一个文件夹services。我的开发板目录为device/board/itcast/genkipi
  2. services目录下新建BUILD.gn文件,并且配置这个BUILD.gn文件。
  3. services目录下新建wifi目录,并且在wifi目录新建BUILD.gn文件。
  4. 修改vendor/itcast/genkipi目录下的BUILD.gn

    代码部分

    1. static_library("genkipi_wifi") {
    2. sources = [
    3. "src/wifi_ap.c",
    4. "src/wifi_sta.c"
    5. ]
    6. include_dirs = [
    7. "include",
    8. "//foundation/communication/wifi_lite/interfaces/wifiservice",
    9. ]
    10. }
    ```c

    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

  1. ```c
  2. #ifndef __WIFI_STA_H__
  3. #define __WIFI_STA_H__
  4. /**
  5. * link wifi
  6. * @param ssid
  7. * @param password
  8. * @param hostname
  9. * @return 0 success
  10. */
  11. int wifi_sta_connect(const char* ssid, const char* password, const char* hostname);
  12. /**
  13. * disconnect wifi
  14. * @return 0 success
  15. */
  16. int wifi_sta_disconnect(void);
  17. #endif //__WIFI_STA_H__
  1. #include "wifi_ap.h"
  2. #include "wifi_hotspot.h"
  3. #include "cmsis_os2.h"
  4. #include "lwip/netifapi.h"
  5. #include <string.h>
  6. static struct netif *g_iface = NULL;
  7. static volatile int g_hotspotStarted = 0;
  8. static volatile int g_joinedStations = 0;
  9. static char *wifi_ssid = NULL;
  10. static void OnHotspotStateChanged(int state) {
  11. printf("[Debug]OnHotspotStateChanged: %d.\r\n", state);
  12. if (state == WIFI_HOTSPOT_ACTIVE) {
  13. g_hotspotStarted = 1;
  14. } else {
  15. g_hotspotStarted = 0;
  16. }
  17. }
  18. static void OnHotspotStaJoin(StationInfo *info) {
  19. g_joinedStations++;
  20. printf("[Debug]+OnHotspotStaJoin: active stations = %d.\r\n", g_joinedStations);
  21. }
  22. static void OnHotspotStaLeave(StationInfo *info) {
  23. g_joinedStations--;
  24. printf("[Debug]-OnHotspotStaLeave: active stations = %d.\r\n", g_joinedStations);
  25. }
  26. WifiEvent g_defaultWifiEventListener = {
  27. .OnHotspotStaJoin = OnHotspotStaJoin,
  28. .OnHotspotStaLeave = OnHotspotStaLeave,
  29. .OnHotspotStateChanged = OnHotspotStateChanged,
  30. };
  31. int wifi_ap_start(const char *ssid, const char *password) {
  32. WifiErrorCode err_code = WIFI_SUCCESS;
  33. err_code = RegisterWifiEvent(&g_defaultWifiEventListener);
  34. printf("[Debug]RegisterWifiEvent:%d\r\n", err_code);
  35. int len = strlen(ssid);
  36. wifi_ssid = (char *) calloc(len + 1, sizeof(char));
  37. memcpy(wifi_ssid, ssid, len);
  38. wifi_ssid[len] = '\0';
  39. HotspotConfig config = {0};
  40. strcpy(config.ssid, ssid);
  41. strcpy(config.preSharedKey, password);
  42. config.securityType = WIFI_SEC_TYPE_PSK;
  43. config.band = HOTSPOT_BAND_TYPE_2G;
  44. config.channelNum = 7;
  45. err_code = SetHotspotConfig(&config);
  46. printf("[Debug]SetHotspotConfig:%d\r\n", err_code);
  47. g_hotspotStarted = 0;
  48. err_code = EnableHotspot();
  49. printf("[Debug]EnableHotspot: %d\r\n", err_code);
  50. while (!g_hotspotStarted) {
  51. osDelay(10);
  52. }
  53. printf("[Debug]g_hotspotStarted = %d.\r\n", g_hotspotStarted);
  54. g_iface = netifapi_netif_find("ap0");
  55. if (g_iface) {
  56. ip4_addr_t ipaddr, gateway, netmask;
  57. IP4_ADDR(&ipaddr, 192, 168, 10, 1);
  58. IP4_ADDR(&gateway, 192, 168, 10, 1);
  59. IP4_ADDR(&netmask, 255, 255, 255, 0);
  60. err_t ret = netifapi_netif_set_addr(g_iface, &ipaddr, &netmask, &gateway);
  61. printf("[Debug]netifapi_netif_set_addr: %d\r\n", ret);
  62. netifapi_dhcps_start(g_iface, 0, 0);
  63. }
  64. return err_code;
  65. }
  66. int wifi_ap_stop(void) {
  67. if (g_iface) {
  68. err_t ret = netifapi_dhcps_stop(g_iface);
  69. printf("[Debug]netifapi_dhcps_stop: %d\r\n", ret);
  70. }
  71. WifiErrorCode err_code = UnRegisterWifiEvent(&g_defaultWifiEventListener);
  72. printf("[Debug]UnRegisterWifiEvent: %d\r\n", err_code);
  73. err_code = DisableHotspot();
  74. printf("DisableHotspot: %d\r\n", err_code);
  75. return err_code;
  76. }
  1. #include "wifi_sta.h"
  2. #include "ohos_init.h"
  3. #include "ohos_types.h"
  4. #include <stdio.h>
  5. #include <unistd.h>
  6. #include <string.h>
  7. #include "cmsis_os2.h"
  8. #include "wifi_device.h"
  9. #include "wifi_event.h"
  10. #include "wifi_error_code.h"
  11. #include "lwip/netif.h"
  12. #include "lwip/netifapi.h"
  13. #include "lwip/ip4_addr.h"
  14. #include "lwip/api_shell.h"
  15. #define DEF_TIMEOUT 15
  16. #define ONE_SECOND 1
  17. #define SELECT_WLAN_PORT "wlan0"
  18. static WifiEvent wifi_event_handler = {0};
  19. static int g_staScanSuccess = 0;
  20. static int g_ConnectSuccess = 0;
  21. static int ssid_count = 0;
  22. static struct netif *g_lwip_netif = NULL;
  23. static char *wifi_ssid = NULL;
  24. static unsigned char is_connected = 0;
  25. static void OnWifiConnectionChanged(int state, WifiLinkedInfo *info) {
  26. (void) info;
  27. if (state > 0) {
  28. g_ConnectSuccess = 1;
  29. printf("[wifi_sta]cb for wifi connect, success\r\n");
  30. } else {
  31. printf("[wifi_sta]cb for wifi connect, failed, please check password\r\n");
  32. }
  33. return;
  34. }
  35. static void OnWifiScanStateChanged(int state, int size) {
  36. (void) state;
  37. if (size > 0) {
  38. ssid_count = size;
  39. g_staScanSuccess = 1;
  40. }
  41. return;
  42. }
  43. static void OnHotspotStateChanged(int state) {
  44. printf("[wifi_sta]cb for HotspotStateChanged:state is %d.\n", state);
  45. return;
  46. }
  47. static void OnHotspotStaJoin(StationInfo *info) {
  48. (void) info;
  49. printf("[wifi_sta]STA join AP\r\n");
  50. return;
  51. }
  52. static void OnHotspotStaLeave(StationInfo *info) {
  53. (void) info;
  54. printf("[wifi_sta]cb for HotspotStaLeave:mac is %s.\r\n", info->macAddress);
  55. return;
  56. }
  57. static WifiErrorCode wifi_init(void) {
  58. WifiErrorCode error;
  59. wifi_event_handler.OnWifiConnectionChanged = OnWifiConnectionChanged;
  60. wifi_event_handler.OnWifiScanStateChanged = OnWifiScanStateChanged;
  61. wifi_event_handler.OnHotspotStateChanged = OnHotspotStateChanged;
  62. wifi_event_handler.OnHotspotStaJoin = OnHotspotStaJoin;
  63. wifi_event_handler.OnHotspotStaLeave = OnHotspotStaLeave;
  64. error = RegisterWifiEvent(&wifi_event_handler);
  65. return error;
  66. }
  67. static void wait_scan_result(void) {
  68. int scanTimeout = DEF_TIMEOUT;
  69. while (scanTimeout > 0) {
  70. sleep(ONE_SECOND);
  71. scanTimeout--;
  72. if (g_staScanSuccess == 1) {
  73. printf("[wifi_sta]wait scan result: wait success[%d]s\n", (DEF_TIMEOUT - scanTimeout));
  74. break;
  75. }
  76. }
  77. if (scanTimeout <= 0) {
  78. printf("[wifi_sta]wait scan result:timeout!\n");
  79. }
  80. }
  81. static int wait_connect_result(void) {
  82. int ConnectTimeout = DEF_TIMEOUT;
  83. while (ConnectTimeout > 0) {
  84. sleep(1);
  85. ConnectTimeout--;
  86. if (g_ConnectSuccess == 1) {
  87. printf("[wifi_sta]wait connect result:wait success[%d]s\n", (DEF_TIMEOUT - ConnectTimeout));
  88. break;
  89. }
  90. }
  91. if (ConnectTimeout <= 0) {
  92. printf("[wifi_sta]wait connect result:timeout!\n");
  93. return 0;
  94. }
  95. return 1;
  96. }
  97. int wifi_sta_connect(const char *ssid, const char *password, const char *hostname) {
  98. // wifi init
  99. WifiErrorCode error = wifi_init();
  100. if (WIFI_SUCCESS != error) {
  101. printf("[wifi_sta]register wifi event failed, error=%d\r\n", error);
  102. return error;
  103. }
  104. printf("[wifi_sta]register wifi event success\r\n");
  105. // wifi enable
  106. error = EnableWifi();
  107. if (WIFI_SUCCESS != error) {
  108. printf("[wifi_sta]enable wifi failed, error=%d\r\n", error);
  109. return error;
  110. }
  111. printf("[wifi_sta]enable wifi success\r\n");
  112. // check wifi active
  113. if (IsWifiActive() == 0) {
  114. printf("[wifi_sta] wifi station is not active\r\n");
  115. return error;
  116. }
  117. int len = strlen(ssid);
  118. wifi_ssid = (char *) calloc(len + 1, sizeof(char));
  119. memcpy(wifi_ssid, ssid, len);
  120. wifi_ssid[len] = '\0';
  121. WifiDeviceConfig ap_config = {0};
  122. strcpy(ap_config.ssid, ssid);
  123. strcpy(ap_config.preSharedKey, password);
  124. ap_config.securityType = WIFI_SEC_TYPE_PSK;
  125. int result;
  126. if (AddDeviceConfig(&ap_config, &result) == WIFI_SUCCESS) {
  127. // connect to wifi
  128. if (ConnectTo(result) == WIFI_SUCCESS && wait_connect_result() == 1) {
  129. printf("[wifi_sta]wifi connect success!\r\n");
  130. g_lwip_netif = netifapi_netif_find(SELECT_WLAN_PORT);
  131. }
  132. }
  133. if (!g_lwip_netif) {
  134. printf("[wifi_sta]netif error \r\n");
  135. return -1;
  136. }
  137. // start dhcp
  138. netifapi_set_hostname(g_lwip_netif, hostname, strlen(hostname));
  139. netifapi_dhcp_start(g_lwip_netif);
  140. // wait dhcp
  141. while (1) {
  142. if (dhcp_is_bound(g_lwip_netif) == ERR_OK) {
  143. printf("[wifi_sta]dhcp bound success\r\n");
  144. netifapi_netif_common(g_lwip_netif, dhcp_clients_info_show, NULL);
  145. break;
  146. }
  147. osDelay(100);
  148. }
  149. is_connected = 1;
  150. return WIFI_SUCCESS;
  151. }
  152. int wifi_sta_disconnect(void) {
  153. if (!g_lwip_netif) {
  154. printf("[wifi_sta]netif error \r\n");
  155. return -1;
  156. }
  157. WifiErrorCode error = Disconnect();
  158. if (WIFI_SUCCESS != error) {
  159. printf("[wifi_sta]disconnect wifi failed, error=%d\r\n", error);
  160. return error;
  161. }
  162. error = DisableWifi();
  163. if (WIFI_SUCCESS != error) {
  164. printf("[wifi_sta]disable wifi failed, error=%d\r\n", error);
  165. return error;
  166. }
  167. error = UnRegisterWifiEvent(&wifi_event_handler);
  168. if (WIFI_SUCCESS != error) {
  169. printf("[wifi_sta]unregister wifi event failed, error=%d\r\n", error);
  170. return error;
  171. }
  172. printf("[wifi_sta]disconnect wifi success\r\n");
  173. is_connected = 0;
  174. return WIFI_SUCCESS;
  175. }
  176. static int get_wifi_local_ip() {
  177. if (!g_lwip_netif) {
  178. printf("[wifi_sta]netif error \r\n");
  179. return -1;
  180. }
  181. ip4_addr_t ip_addr;
  182. ip4_addr_t netmask_addr;
  183. ip4_addr_t gw_addr;
  184. if (netifapi_netif_get_addr(g_lwip_netif, &ip_addr, &netmask_addr, &gw_addr) == ERR_OK) {
  185. u32_t ip = ip_addr.addr;
  186. u32_t netmask = netmask_addr.addr;
  187. u32_t gw = gw_addr.addr;
  188. printf("ip %d.%d.%d.%d\n\r", (ip & 0xff), ((ip >> 8) & 0xff), ((ip >> 16) & 0xff), (ip >> 24));
  189. printf("netmask %d.%d.%d.%d\n\r", (netmask & 0xff), ((netmask >> 8) & 0xff), ((netmask >> 16) & 0xff),
  190. (netmask >> 24));
  191. printf("gw %d.%d.%d.%d\n\r", (gw & 0xff), ((gw >> 8) & 0xff), ((gw >> 16) & 0xff), (gw >> 24));
  192. } else {
  193. printf("netif get addr failed\r\n");
  194. }
  195. return 1;
  196. }
  1. group("genkipi_services") {
  2. deps = [
  3. "wifi:genkipi_wifi"
  4. ]
  5. }
  1. # Copyright (C) 2020 Itcast Co., Ltd. All rights reserved.
  2. group("genkipi") {
  3. deps = [
  4. "//device/board/itcast/genkipi:run_genkipi_scons",
  5. "//device/board/itcast/genkipi/app",
  6. "//device/board/itcast/genkipi/iot_hardware_hals",
  7. "//device/board/itcast/genkipi/services:genkipi_services"
  8. ]
  9. }

配置说明

  1. vendor/itcast/genkipi/BUILD.gn描述了开发板提供的服务。deps表示编译依赖。 ```bash

    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” ] }

  1. - `//device/board/itcast/genkipi/services:genkipi_services`指向了我们刚刚新建的文件夹`services`文件夹下的`BUILD.gn`文件。
  2. 2. `services/BUILD.gn`描述的是当前子系统服务的一些配置。
  3. ```bash
  4. group("genkipi_services") {
  5. deps = [
  6. "wifi:genkipi_wifi"
  7. ]
  8. }
  • genkipi_services表示当前子服务名称。group表示是一个服务集合。
  • deps表示依赖。
  • wifi:genkipi_wifi表示当前services目录下的wifi目录中BUILD.gn配置

    1. services/wifi/BUILD.gn为wifi部分的配置。
      1. static_library("genkipi_wifi") {
      2. sources = [
      3. "src/wifi_ap.c",
      4. "src/wifi_sta.c"
      5. ]
      6. include_dirs = [
      7. "include",
      8. "//foundation/communication/wifi_lite/interfaces/wifiservice",
      9. ]
      10. }
  • sources表示源码部分

  • include_dirs表示需要引入的头

    AP逻辑说明

    AP就是扮演路由器角色,我们开启路由器,需要给路由器配置名称和密码,供其他设备扫描连接用。
    AP提供了wifi_ap_start函数,就是为这个服务的。
    1. int wifi_ap_start(const char *ssid, const char *password);
  • ssid: 路由器的名称
  • password:路由器密码

STA逻辑说明

STA就是扮演类似于手机这种角色,可以连接路由器。
STA提供了wifi_sta_connect函数,来实现连接路由器的功能。

  1. int wifi_sta_connect(const char *ssid, const char *password, const char *hostname)
  • ssid: 要连接的路由器名称
  • password:要连接的路由器密码
  • hostname: 当前设备在路由器中显示的名称

    AP模式调试

    开发流程

    来到应用开发根目录。
    我们编写代码的根目录device/board/itcast/genkipi/app
  1. 根目录下新建ap文件夹,此为项目目录
  2. 项目目录下新建main.c文件
  3. 项目目录下新建BUILD.gn文件
  4. 修改根目录下的BUILD.gn文件

    代码部分

    ```c

    include

    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;

  1. attr.name = "ap";
  2. attr.attr_bits = 0U;
  3. attr.cb_mem = NULL;
  4. attr.cb_size = 0U;
  5. attr.stack_mem = NULL;
  6. attr.stack_size = 1024 * 2;
  7. attr.priority = 25;
  8. // Create the Thread1 task
  9. if (osThreadNew((osThreadFunc_t)startAP, NULL, &attr) == NULL) {
  10. printf("Failed to create say hello Thread!\n");
  11. }

}

APP_FEATURE_INIT(main);

  1. ```c
  2. static_library("ap") {
  3. sources = [ "main.c" ]
  4. include_dirs = [
  5. "//base/iothardware/peripheral/interfaces/inner_api",
  6. "../../services/wifi/include",
  7. ]
  8. deps = [
  9. "../../services:genkipi_services",
  10. ]
  11. }
  1. import("//build/lite/config/component/lite_component.gni")
  2. lite_component("app") {
  3. features = [
  4. "ap"
  5. ]
  6. }

校验

114.png

STA模式调试

开发流程

来到应用开发根目录。
我们编写代码的根目录device/board/itcast/genkipi/app

  1. 根目录下新建sta文件夹,此为项目目录
  2. 项目目录下新建main.c文件
  3. 项目目录下新建BUILD.gn文件
  4. 修改根目录下的BUILD.gn文件

    代码部分

    ```c

    include

    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;

  1. attr.name = "sta";
  2. attr.attr_bits = 0U;
  3. attr.cb_mem = NULL;
  4. attr.cb_size = 0U;
  5. attr.stack_mem = NULL;
  6. attr.stack_size = 1024 * 4;
  7. attr.priority = 25;
  8. // Create the Thread1 task
  9. if (osThreadNew((osThreadFunc_t)startSta, NULL, &attr) == NULL) {
  10. printf("Failed to create say hello Thread!\n");
  11. }

}

APP_FEATURE_INIT(main);

  1. ```c
  2. static_library("sta") {
  3. sources = [ "main.c" ]
  4. include_dirs = [
  5. "//base/iothardware/peripheral/interfaces/inner_api",
  6. "../../services/wifi/include",
  7. ]
  8. deps = [
  9. "../../services:genkipi_services",
  10. ]
  11. }
  1. import("//build/lite/config/component/lite_component.gni")
  2. lite_component("app") {
  3. features = [
  4. "sta"
  5. ]
  6. }

校验

114.jpg

练习题

  • 通过代码实现AP
  • 通过代码实现STA