ToB企服应用市场:ToB评测及商务社交产业平台

标题: 《HarmonyOS开发 – OpenHarmony开发笔记(基于小型系统)》第5章 WiFi联网(S [打印本页]

作者: 用户云卷云舒    时间: 2022-6-25 09:16
标题: 《HarmonyOS开发 – OpenHarmony开发笔记(基于小型系统)》第5章 WiFi联网(S
开发环境:
开发系统:Ubuntu 20.04
开发板:Pegasus物联网开发板
MCU:Hi3861
OpenHarmony版本:3.0.1-LTS
HI3861默认已经初始化了WiFi,因此这里讲解如何使用WiFi联网。
5.1使用AT联网

串口终端上执行相应的AT命令,即可使Hi3861 WLAN模组联网,依次执行如下AT命令,启动STA模式,连接指定路由器,并开启DHCP功能配置IP地址。
  1. AT+STARTSTA                             # 启动STA模式
  2. AT+SCAN                                 # 扫描周边AP
  3. AT+SCANRESULT                           # 显示扫描结果
  4. AT+CONN="SSID",,2,"PASSWORD"            # 连接指定AP,其中SSID/PASSWORD为待连接的热点名称和密码
  5. AT+STASTAT                              # 查看连接结果
  6. AT+DHCP=wlan0,1                         # 通过DHCP向AP请求wlan0的IP地址
复制代码
查看Hi3861 WLAN模组与网关联通是否正常,如下所示。
  1. AT+IFCFG                                # 查看模组接口IP
  2. AT+PING=X.X.X.X                         # 检查模组与网关的联通性,其中X.X.X.X需替换为实际的网关地址
复制代码
下面具体演示:



有上图可知Hi3861 WLAN模组联网成功。
当然也可在同一个局域网中ping HI3861。

说明网络是连通的。
关于Wifi联网的AT命令有很多,所有的AT指令都是通过函数hi_at_sys_cmd_register() 函数注册的,其中调用了hi_at_register_cmd()函数注册AT。
重点介绍三个函数。
1.启动WiFi STA模式, AT+STARTSTA
  1. hi_u32 cmd_sta_start_adv(hi_s32 argc, const hi_char *argv[])
  2. {
  3.     hi_s32  ret;
  4.     hi_wifi_bw bw = HI_WIFI_BW_LEGACY_20M;
  5.     if (argc != 3) { /* "+STARTSTA" command fix 3 parameters */
  6.         return HI_ERR_FAILURE;
  7.     }
  8.     ret = (hi_s32)sta_start_adv_param(argc, argv, &bw);
  9.     if (ret != HI_ERR_SUCCESS) {
  10.         return HI_ERR_FAILURE;
  11.     }
  12. #ifndef CONFIG_FACTORY_TEST_MODE
  13.     hi_char ifname[WIFI_IFNAME_MAX_SIZE + 1] = {0};
  14.     hi_s32  len = sizeof(ifname);
  15.     ret = hi_wifi_sta_start(ifname, &len);
  16.     if (ret != HISI_OK) {
  17.         return HI_ERR_FAILURE;
  18.     }
  19. #endif
  20.     ret = hi_wifi_set_bandwidth(DEFAULT_IFNAME_STA, strlen(DEFAULT_IFNAME_STA) + 1, bw);
  21.     if (ret != HI_ERR_SUCCESS) {
  22. #ifndef CONFIG_FACTORY_TEST_MODE
  23.         hi_wifi_sta_stop();
  24. #endif
  25.         return HI_ERR_FAILURE;
  26.     }
  27.     hi_at_printf("OK\r\n");
  28.     return HI_ERR_SUCCESS;
  29. }
复制代码
该函数的核心就是hi_wifi_sta_start()函数。
2.连接WiFi ,AT+CONN
  1. /*****************************************************************************
  2. * Func description: station connect network
  3. * example: AT+CONN="hisilicon",,3,"123456789"
  4. *****************************************************************************/
  5. hi_u32 cmd_sta_connect(hi_s32 argc, const hi_char *argv[])
  6. {
  7.     hi_wifi_assoc_request assoc_req = {0};
  8.     if ((argc < 3) || (argc > 4)) {     /* argc 3/4 */
  9.         return HI_ERR_FAILURE;
  10.     }
  11.     /* get ssid */
  12.     if ((argv[0] != HI_NULL) && (cmd_sta_connect_get_ssid(argv, &assoc_req, HI_NULL, 0) != HI_ERR_SUCCESS)) {
  13.         return HI_ERR_FAILURE;
  14.     }
  15.     /* get bssid */
  16.     if (argv[1] == HI_NULL) {
  17.         memset_s(assoc_req.bssid, sizeof(assoc_req.bssid), 0, sizeof(assoc_req.bssid));
  18.     } else if (strlen(argv[1]) == HI_WIFI_TXT_ADDR_LEN) {
  19.         if (cmd_strtoaddr(argv[1], assoc_req.bssid, HI_WIFI_MAC_LEN) != HISI_OK) {
  20.             return HI_ERR_FAILURE;
  21.         }
  22.     } else {
  23.         return HI_ERR_FAILURE;
  24.     }
  25.     /* get auth_type */
  26.     if ((integer_check(argv[2]) != HI_ERR_SUCCESS) || (atoi(argv[2]) < HI_WIFI_SECURITY_OPEN) ||    /* argc 2 */
  27.         (atoi(argv[2]) == HI_WIFI_SECURITY_WPA) || (atoi(argv[2]) == HI_WIFI_SECURITY_WPA2) || /* argc 2 */
  28.         (atoi(argv[2]) == HI_WIFI_SECURITY_WPAPSK) || (atoi(argv[2]) >= HI_WIFI_SECURITY_UNKNOWN) || /* argc 2 */
  29.         ((atoi(argv[2]) == HI_WIFI_SECURITY_OPEN) && (argc != 3)) || /* argc 2/3/4 */
  30.         ((atoi(argv[2]) != HI_WIFI_SECURITY_OPEN) && (argc != 4))) { /* argc 2/3/4 */
  31.         return HI_ERR_FAILURE;
  32.     }
  33.     assoc_req.auth = (hi_wifi_auth_mode)atoi(argv[2]); /* 2 */
  34.     assoc_req.pairwise = HI_WIFI_PARIWISE_UNKNOWN;
  35.     /* get key */
  36.     if (argc == 4) {    /* argc 4 */
  37.         const hi_char *buf = argv[3];   /* argc 3 */
  38.         if (buf == HI_NULL) {
  39.             return HI_ERR_FAILURE;
  40.         }
  41.         size_t len = strlen(argv[3]); /* 3:key */
  42.         if ((atoi(argv[2]) == HI_WIFI_SECURITY_WEP) && (len != 9) && (len != 17) && /* argc 2, len 9/17 */
  43.             (len != 12) && (len != 28))  { /* 12 28: password len */
  44.             return HI_ERR_FAILURE;
  45.         } else if ((atoi(argv[2]) != HI_WIFI_SECURITY_WEP) && ((len > HI_WIFI_AP_KEY_LEN_MAX + 2) ||    /* argc 2 */
  46.             (len < HI_WIFI_AP_KEY_LEN_MIN + 2))) {  /* len plus 2 */
  47.             return HI_ERR_FAILURE;
  48.         }
  49.         if ((*buf != '"') || (*(buf + strlen(argv[3]) - 1) != '"') || /* argc 3 */
  50.             (memcpy_s(assoc_req.key, HI_WIFI_MAX_KEY_LEN + 1, buf + 1, strlen(argv[3]) - 2) != EOK)) { /* 3 2 */
  51.             return HI_ERR_FAILURE;
  52.         }
  53.     }
  54.     if (hi_wifi_sta_connect(&assoc_req) != HISI_OK) {
  55.         return HI_ERR_FAILURE;
  56.     }
  57.     hi_at_printf("OK\r\n");
  58.     return HI_ERR_SUCCESS;
  59. }
复制代码
该函数主要用于解析AT+CONN指令,核心是hi_wifi_sta_connect()函数。
3.获取IP地址, AT+DHCP
  1. hi_u32 at_setup_dhcp(hi_s32 argc, const hi_char **argv)
  2. {
  3.     hi_s32 ret = 0;
  4.     if (at_param_null_check(argc, argv) == HI_ERR_FAILURE) {
  5.         return HI_ERR_FAILURE;
  6.     }
  7.     if (argc != 2) { /* at+dhcp cmd length equl 2 */
  8.         return HI_ERR_FAILURE;
  9.     }
  10. #ifndef CONFIG_FACTORY_TEST_MODE
  11.     struct netif *netif_p = netifapi_netif_find(argv[0]);
  12.     if (netif_p == NULL) {
  13.         return HI_ERR_FAILURE;
  14.     }
  15.     if (strcmp(argv[1], "1") == 0) {
  16.         ret = netifapi_dhcp_start(netif_p);
  17.     } else if (strcmp(argv[1], "0") == 0) {
  18.         ret = netifapi_dhcp_stop(netif_p);
  19.     } else if (strcmp(argv[1], "2") == 0) {
  20.         ret = netifapi_netif_common(netif_p, dhcp_clients_info_show, NULL);
  21.     } else {
  22.         return HI_ERR_FAILURE;
  23.     }
  24. #endif
  25.     if (ret == LOS_OK) {
  26.         hi_at_printf("OK\r\n");
  27.     }
  28.     return ret;
  29. }
复制代码
其中netifapi_netif_find()函数通过DHCP向AP请求wlan0的IP地址,然后就调用netifapi_dhcp_start()函数获取IP。
以上函数在device/hisilicon/hispark_pegasus/sdk_liteos/components/at/src目录下。
使用AT比较麻烦,接下来笔者将通过程序来联网。
5.2 Hi3861自动联网

编程自动联网,其本质和使用AT指令一样,最终都是调用了相同的API,只是通过加载应用的方式去实现了,联网流程和使用AP一样的,编写应用的方式参看上一章内容,本文将在wifi-iot目录下新建应用,这样可以简化步骤。
5.2.1新建目录

在./applications/sample/wifi-iot/app路径下新建一个目录,用于存放WiFi应用的源码文件。
在app下新增业务wifi_connect,其中wifi_app.c为应用代码,BUILD.gn为编译脚本,目录结构如下:

5.2.2编写应用代码

新建./applications/sample/wifi-iot/app/wifi_app下的wifi_app.c文件,在wifi_app.c中新建入口函数wifi_task,并实现业务逻辑。并在代码最下方,使用OpenHarmony启动模块接口SYS_RUN()启动业务。
从上一节内容得到,连接WiFi核心就三个:启动STA模式,连接WiFi,设置IP。
因此,最终的wifi_app.c的函数代码如下:
  1. /**
  2.   ******************************************************************************
  3.   * @file                wifi_app.c
  4.   * @author              BruceOu
  5.   * @version             V1.0
  6.   * @date                2022-06-18
  7.   * @blog                https://blog.bruceou.cn/
  8.   * @Official Accounts   嵌入式实验楼
  9.   * @brief               
  10.   ******************************************************************************
  11.   */
  12. #include <stdio.h>
  13. #include <unistd.h>
  14. #include "ohos_init.h"
  15. #include "cmsis_os2.h"
  16. #include <unistd.h>
  17. #include "hi_wifi_api.h"
  18. #include "lwip/ip_addr.h"
  19. #include "lwip/netifapi.h"
  20. #define SSID      "media"
  21. #define PASSWORD  "12345678"
  22. static struct netif *g_lwip_netif = NULL;
  23. /**
  24.   * @brief  Set netif's ip, gateway and netmask
  25.   * @param  pst_lwip_netif
  26.   * @retval None
  27.   */
  28. void hi_sta_set_addr(struct netif *pst_lwip_netif)
  29. {
  30.     ip4_addr_t st_gw;
  31.     ip4_addr_t st_ipaddr;
  32.     ip4_addr_t st_netmask;
  33.     if (pst_lwip_netif == NULL)
  34.     {
  35.         printf("hisi_reset_addr::Null param of netdev\r\n");
  36.         return;
  37.     }
  38.     IP4_ADDR(&st_gw, 192, 168, 101, 1);
  39.     IP4_ADDR(&st_ipaddr, 192, 168, 101, 100);
  40.     IP4_ADDR(&st_netmask, 255, 255, 255, 0);
  41.     netifapi_netif_set_addr(pst_lwip_netif, &st_ipaddr, &st_netmask, &st_gw);
  42. }
  43. /**
  44.   * @brief  Wifi connect
  45.   * @param  None
  46.   * @retval None
  47.   */
  48. int hi_wifi_start_connect(void)
  49. {
  50.     int ret;
  51.     errno_t rc;
  52.     hi_wifi_assoc_request assoc_req = {0};
  53.     // Copy SSID to assoc_req
  54.     rc = memcpy_s(assoc_req.ssid, HI_WIFI_MAX_SSID_LEN + 1, SSID, strlen(PASSWORD));
  55.     if (rc != EOK)
  56.     {
  57.         printf("[Wifi Connnect] hi_wifi_sta_connect fail");
  58.         printf("%s %d \r\n", __FILE__, __LINE__);
  59.         return -1;
  60.     }
  61.     //Set encryption method
  62.     assoc_req.auth = HI_WIFI_SECURITY_WPA2PSK;
  63.     // Wifi password
  64.     memcpy(assoc_req.key, PASSWORD, strlen(PASSWORD));
  65.     ret = hi_wifi_sta_connect(&assoc_req);
  66.     if (ret != HISI_OK)
  67.     {
  68.         printf("[Wifi Connnect] hi_wifi_sta_connect fail");
  69.         printf("%s %d \r\n", __FILE__, __LINE__);
  70.         return -1;
  71.     }
  72.         return 0;
  73. }
  74. /**
  75.   * @brief  wifi task
  76.   * @param  None
  77.   * @retval None
  78.   */
  79. void wifi_task(void)
  80. {
  81.     int ret;
  82.     char ifname[WIFI_IFNAME_MAX_SIZE + 1] = {0};
  83.     int len = sizeof(ifname);
  84.     unsigned int  num = WIFI_SCAN_AP_LIMIT;
  85.         // Step 1: Start STA mode, AT+STARTSTA
  86.     ret = hi_wifi_sta_start(ifname, &len);
  87.     if (ret != HISI_OK)
  88.     {
  89.         printf("[Wifi Connnect] hi_wifi_sta_start fail");
  90.         printf("%s %d \r\n", __FILE__, __LINE__);
  91.         return;
  92.     }
  93.     // Step 2: Connect to the specified AP:, AT+CONN="SSID", ,2,"PASSWORD"
  94.     ret = hi_wifi_start_connect();
  95.     if (ret != 0)
  96.     {
  97.         printf("[Wifi Connnect] hi_wifi_start_connect fail");
  98.         printf("%s %d \r\n", __FILE__, __LINE__);
  99.         return ;
  100.     }
  101.     // Step 3: DHCP requests the IP address of wlan0 from the AP, AT+DHCP=wlan0,1  
  102.     g_lwip_netif = netifapi_netif_find(ifname);
  103.     if(NULL == g_lwip_netif)
  104.     {
  105.         printf("[Wifi Connnect] netifapi_netif_find fail");
  106.         printf("%s %d \r\n", __FILE__, __LINE__);
  107.         return;
  108.     }       
  109.     //DHCP automatically assigns IP
  110.     if(ret != netifapi_dhcp_start(g_lwip_netif))
  111.     {
  112.         printf("[Wifi Connnect] netifapi_dhcp_start fail");
  113.         return;
  114.     }       
  115.     printf("[Wifi Connnect] Connect to wifi successfully\n");
  116. }
  117. SYS_RUN(wifi_task);
复制代码
5.2.3新建编译组织文件

新建./applications/sample/wifi-iot/app/wifi_connect/BUILD.gn文件,内容如下所示:
  1. static_library(wifiapp") {
  2.     sources = [
  3.         "wifi_app.c"
  4.     ]
  5.     include_dirs = [
  6.         "//utils/native/lite/include"
  7.     ]
  8. }
复制代码

5.2.4新增组件

将wifiapp添加到组件中。即修改applications/sample/wifi-iot/app/BUILD.gn文件,修改后如下所示。
import(“//build/lite/config/component/lite_component.gni”)
  1. lite_component("app") {
  2.     features = [
  3.         "wifi_connect:wifiapp"
  4.     ]
  5. }
复制代码

5.2.5编译下载测试

最后,编译下载固件,我们就可以自动连接Wifi了。

接下来ping下网络:

说明自动连接网络成功。
官网手册


   欢迎访问我的网站

BruceOu的哔哩哔哩
BruceOu的主页
BruceOu的博客
BruceOu的CSDN博客
BruceOu的简书
BruceOu的知乎

   欢迎订阅我的微信公众号

关注公众号[嵌入式实验楼]获取更多资讯

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!




欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) Powered by Discuz! X3.4