ESP32S3 + IDF 5.2.2 扫描WiFi

ESP32S3 + IDF 5.2.2 扫描WiFi


目录

1 资料
2 通过Wi-Fi库扫描附近的网络
  2.1 通过idf命令创建工程
  2.2 编写测试用例
  2.3 优化测试用例
3 小结


1 资料

    在ESP平台基于IDF开发WiFi相关功能,主要就是基于IDF的Wi-Fi库进行二次开发。可供参考的官方资料:

         ESP-IDF 编程指南 » API 参考 » 连网 API » Wi-Fi 库


2 通过Wi-Fi库扫描附近的网络

2.1 通过idf命令创建工程

    执行以下idf命令,创建工程:
idf.py create-project wifi_scan_test
cd wifi_scan_test/
idf.py set-target esp32s3

    执行menuconfig命令,配置工程(这里博主使用的是N8R8 版本的ESP32-S3-WROOM-1):

idf.py menuconfig

    这里主要需要配置的是Flash和RAM,使其和你的模组、板级匹配。
在这里插入图片描述

在这里插入图片描述

    配置完成后,保存配置,然后执行build:

idf.py save-defconfig
idf.py build

2.2 编写测试用例

    打开工程,创建wifi_scan目录并创建对应的源文件和头文件。创建完成后,将头文件路径和源文件添加进CMakeLists。

在这里插入图片描述

    完善wifi_scan.h头文件,申明一个wifi_scan()接口,供外部调用。

#ifndef _WIFI_SCAN_H_
#define __WIFI_SCAN_H_

#ifdef __cplusplus
extern "C" {
#endif

void wifi_scan(void);

#ifdef __cplusplus
} /* extern "C" */
#endif

#endif 

    在wifi_scan_test.c源文件的app_main()中调用wifi_scan()接口。
在这里插入图片描述

    在wifi_scan.c源文件中实现wifi_scan()接口。主要需要进行的操作包括:网络接口初始化、配置设备wifi工作在STA模式、启动wifi、扫描附近wifi、获取扫描结果。
    网络接口初始化已经在 app_main()中处理了,这里就不用再处理。

/**
 * @brief       将Wi-Fi初始化为sta并设置扫描方法
 * @param       无
 * @retval      无
 */
void wifi_scan(void)
{
    /* 用户初始化STA模式 */
    esp_netif_t *sta_netif = esp_netif_create_default_wifi_sta();
    assert(sta_netif);

    /* wifi配置初始化 */
    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
    ESP_ERROR_CHECK(esp_wifi_init(&cfg));
    memset(ap_info, 0, sizeof(ap_info));

    /* 设置WIFI为STA模式 */
    ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));

    /* 启动WIFI */
    ESP_ERROR_CHECK(esp_wifi_start());

    /* 开始扫描附件的WIFI, 并等待扫描结束 */
    esp_wifi_scan_start(NULL, true);

    /* 获取扫描结果 */
    get_wifi_scan_result();

    return;
}

    实现get_wifi_scan_result()接口。这里需要注意esp_wifi_scan_get_ap_num()需要在esp_wifi_scan_get_ap_records()之前调用,否则无法获取到正确的ap_count值。

/**
 * @brief       获取Wi-Fi扫描结果
 * @param       无
 * @retval      无
 */
static void get_wifi_scan_result(void)
{
    number = DEFAULT_SCAN_LIST_SIZE;
    ap_count = 0;

    /* 获取上次扫描中找到的AP数量 */
    ESP_ERROR_CHECK(esp_wifi_scan_get_ap_num(&ap_count));
    /* 获取上次扫描中找到的AP列表 */
    ESP_ERROR_CHECK(esp_wifi_scan_get_ap_records(&number, ap_info));

    /* 打印WIFI扫描结果 */
    print_wifi_scan_result(ap_count, number);

    return;
}

    实现print_wifi_scan_result()接口。

/**
 * @brief       身份认证模式
 * @param       authmode :身份验证模式
 * @retval      无
 */
static void print_auth_mode(int authmode)
{
    switch (authmode) {
        case WIFI_AUTH_OPEN:
            ESP_LOGI(TAG, "Authmode \tWIFI_AUTH_OPEN");
            break;
        case WIFI_AUTH_OWE:
            ESP_LOGI(TAG, "Authmode \tWIFI_AUTH_OWE");
            break;
        case WIFI_AUTH_WEP:
            ESP_LOGI(TAG, "Authmode \tWIFI_AUTH_WEP");
            break;
        case WIFI_AUTH_WPA_PSK:
            ESP_LOGI(TAG, "Authmode \tWIFI_AUTH_WPA_PSK");
            break;
        case WIFI_AUTH_WPA2_PSK:
            ESP_LOGI(TAG, "Authmode \tWIFI_AUTH_WPA2_PSK");
            break;
        case WIFI_AUTH_WPA_WPA2_PSK:
            ESP_LOGI(TAG, "Authmode \tWIFI_AUTH_WPA_WPA2_PSK");
            break;
        case WIFI_AUTH_WPA2_ENTERPRISE:
            ESP_LOGI(TAG, "Authmode \tWIFI_AUTH_WPA2_ENTERPRISE");
            break;
        case WIFI_AUTH_WPA3_PSK:
            ESP_LOGI(TAG, "Authmode \tWIFI_AUTH_WPA3_PSK");
            break;
        case WIFI_AUTH_WPA2_WPA3_PSK:
            ESP_LOGI(TAG, "Authmode \tWIFI_AUTH_WPA2_WPA3_PSK");
            break;
        default:
            ESP_LOGI(TAG, "Authmode \tWIFI_AUTH_UNKNOWN");
            break;
    }
}

/**
 * @brief       打印WIFI密码类型
 * @param       pairwise_cipher :密码类型
 * @param       group_cipher    :群密码类型
 * @retval      无
 */
static void print_cipher_type(int pairwise_cipher, int group_cipher)
{
    switch (pairwise_cipher) {
        case WIFI_CIPHER_TYPE_NONE:
            ESP_LOGI(TAG, "Pairwise Cipher \tWIFI_CIPHER_TYPE_NONE");
            break;
        case WIFI_CIPHER_TYPE_WEP40:
            ESP_LOGI(TAG, "Pairwise Cipher \tWIFI_CIPHER_TYPE_WEP40");
            break;
        case WIFI_CIPHER_TYPE_WEP104:
            ESP_LOGI(TAG, "Pairwise Cipher \tWIFI_CIPHER_TYPE_WEP104");
            break;
        case WIFI_CIPHER_TYPE_TKIP:
            ESP_LOGI(TAG, "Pairwise Cipher \tWIFI_CIPHER_TYPE_TKIP");
            break;
        case WIFI_CIPHER_TYPE_CCMP:
            ESP_LOGI(TAG, "Pairwise Cipher \tWIFI_CIPHER_TYPE_CCMP");
            break;
        case WIFI_CIPHER_TYPE_TKIP_CCMP:
            ESP_LOGI(TAG, "Pairwise Cipher \tWIFI_CIPHER_TYPE_TKIP_CCMP");
            break;
        default:
            ESP_LOGI(TAG, "Pairwise Cipher \tWIFI_CIPHER_TYPE_UNKNOWN");
            break;
    }

    switch (group_cipher) {
        case WIFI_CIPHER_TYPE_NONE:
            ESP_LOGI(TAG, "Group Cipher \tWIFI_CIPHER_TYPE_NONE");
            break;
        case WIFI_CIPHER_TYPE_WEP40:
            ESP_LOGI(TAG, "Group Cipher \tWIFI_CIPHER_TYPE_WEP40");
            break;
        case WIFI_CIPHER_TYPE_WEP104:
            ESP_LOGI(TAG, "Group Cipher \tWIFI_CIPHER_TYPE_WEP104");
            break;
        case WIFI_CIPHER_TYPE_TKIP:
            ESP_LOGI(TAG, "Group Cipher \tWIFI_CIPHER_TYPE_TKIP");
            break;
        case WIFI_CIPHER_TYPE_CCMP:
            ESP_LOGI(TAG, "Group Cipher \tWIFI_CIPHER_TYPE_CCMP");
            break;
        case WIFI_CIPHER_TYPE_TKIP_CCMP:
            ESP_LOGI(TAG, "Group Cipher \tWIFI_CIPHER_TYPE_TKIP_CCMP");
            break;
        default:
            ESP_LOGI(TAG, "Group Cipher \tWIFI_CIPHER_TYPE_UNKNOWN");
            break;
    }
}

/**
 * @brief       打印Wi-Fi扫描结果
 * @param       ap_count :实际扫描出的AP数量
 * @param       number :可打印输出的AP信息数量
 * @retval      无
 */
static void print_wifi_scan_result(uint16_t ap_count, uint16_t number)
{
    /* 打印附件的WIFI信息 */
    ESP_LOGI(TAG, "wifi scan result, ap_count = %u, number = %u", ap_count, number);

    for (int i = 0; (i < DEFAULT_SCAN_LIST_SIZE) && (i < ap_count); i++) {
        ESP_LOGI(TAG, "SSID \t\t%s", ap_info[i].ssid);
        ESP_LOGI(TAG, "RSSI \t\t%d(level:%d)", ap_info[i].rssi, rssi_to_5_level(ap_info[i].rssi));

        /* 加密方式 */
        print_auth_mode(ap_info[i].authmode);
        /* 密码类型 */
        if (ap_info[i].authmode != WIFI_AUTH_WEP) {
            print_cipher_type(ap_info[i].pairwise_cipher, ap_info[i].group_cipher);
        }

        ESP_LOGI(TAG, "Channel \t\t%d\n", ap_info[i].primary);
    }

    return;
}

2.3 优化测试用例

    esp_wifi_scan_start(NULL, true),方式会等到扫描完成后才返回,这样会导致wifi_scan()长时间不返回,更好的处理方式是在这里不等待扫描完成,发起了扫描后就返回调用,在真实的扫描完成事件发生后再去打印扫描结果。这就需要用到IDF的WiFi框架,主要是在默认事件循环中注册相关的事件处理函数

/**
 * @brief       Wi-Fi扫描完成事件 处理函数
 * @param       默认事件处理标准参数列表
 * @retval      无
 */
static void wifi_scan_completed_event_handler(void* arg,
                                              esp_event_base_t event_base,
                                              int32_t event_id,
                                              void* event_data)
{
    if((event_base == WIFI_EVENT) && (event_id == WIFI_EVENT_SCAN_DONE)) {
        wifi_event_sta_scan_done_t* scan_done = (wifi_event_sta_scan_done_t*) event_data;
        ESP_LOGI(TAG, "wifi scan done, status:%lu, number:%u", scan_done->status, scan_done->number);
        /* 获取wifi扫描结果 */
        get_wifi_scan_result();    
    }

    return;
}

/**
 * @brief       将Wi-Fi初始化为sta并设置扫描方法
 * @param       无
 * @retval      无
 */
void wifi_scan(void)
{
    /* 用户初始化STA模式 */
    esp_netif_t *sta_netif = esp_netif_create_default_wifi_sta();
    assert(sta_netif);

    /* wifi配置初始化 */
    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
    ESP_ERROR_CHECK(esp_wifi_init(&cfg));
    memset(ap_info, 0, sizeof(ap_info));

    /* 设置WIFI为STA模式 */
    ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));

    /* 根据ESP32 Wi-Fi 编程模型, 向 默认事件循环 注册事件处理函数 */
    esp_event_handler_instance_register(WIFI_EVENT,
                                        ESP_EVENT_ANY_ID,
                                        &wifi_scan_completed_event_handler,
                                        NULL,
                                        NULL);
    /* 启动WIFI */
    ESP_ERROR_CHECK(esp_wifi_start());

    /* 开始扫描附件的WIFI, 不等待扫描结束 */
    esp_wifi_scan_start(NULL, false);

    /* 扫描结果处理在 wifi_scan_completed_event_handler() 中进行 */

    return;
}



3 烧录、测试

    编译完成后,将固件烧录进设备,可以看到以下log输出,符合预期。

在这里插入图片描述

工程完整代码,可自行下载、测试:
         ESP32S3 + IDF5.2.2 wifi扫描 Demo

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/947401.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

2025-1-2-sklearn学习(30)模型选择与评估-验证曲线: 绘制分数以评估模型 真珠帘卷玉楼空,天淡银河垂地。

文章目录 sklearn学习(30) 模型选择与评估-验证曲线: 绘制分数以评估模型30.1. 验证曲线30.2. 学习曲线 sklearn学习(30) 模型选择与评估-验证曲线: 绘制分数以评估模型 文章参考网站&#xff1a; https://sklearn.apachecn.org/ 和 https://scikit-learn.org/stable/ 每种估…

统信系统设置代理的问题

统信系统设置代理的问题 问题表现方式一方式二 问题表现 统信系统下有系统代理和应用代理两个代理。设置系统代理时&#xff0c;git不能经过代理拉取代码。但是设置应用代理时&#xff0c;可以用git通过代理拉代码。 这是系统代理&#xff0c;在这里设置 ip 端口&#xff0c;…

STM32-笔记19-串口打印功能

复制项目文件夹03-流水灯&#xff0c;重命名为19-串口打印功能 打开项目 在主函数中&#xff0c;添加头文件、和串口初始化函数&#xff08;设置波特率&#xff09;和输出函数&#xff0c;如图所示&#xff1a; 软件部分就设置好了 下面是硬件部分 接线&#xff1a;使用USB…

JavaWeb——MySQL-DML(1/3)-添加数据insert(DML 操作概述、INSERT 语句插入数据、语句演示、总结)

目录 DML 操作概述 INSERT 语句插入数据 INSERT 语句基础语法 INSERT 语句演示 注意事项 总结 DML 操作概述 DML 简介 DML&#xff08;Data Manipulation Language&#xff09;即数据操作语言&#xff0c;用于对数据库表中的数据进行增删改操作&#xff0c;包括添加数据&…

Docker图形化界面工具Portainer最佳实践

前言 安装Portainer 实践-基于Portainer安装redis-sentinel部署 Spring Boot集成Redis Sentinel 前言 本篇文章笔者推荐一个笔者最常用的docker图形化管理工具——Portainer。 安装Portainer 编写docker-compose文件 Portainer部署的步骤比较简单&#xff0c;我们还是以…

Wonder Dynamics技术浅析(五):虚拟场景描述解析

虚拟场景描述解析模块是 Wonder Dynamics 平台的核心组件之一&#xff0c;其主要功能是将用户输入的自然语言场景描述转换为机器可理解的语义表示&#xff0c;为后续的虚拟场景生成提供基础数据。 一、文本预处理&#xff08;Text Preprocessing&#xff09; 1. 目标: 对用户…

基于SpringBoot在线竞拍平台系统功能实现十一

## 一、前言介绍&#xff1a;1.1 项目摘要 随着网络技术的飞速发展和电子商务的普及&#xff0c;竞拍系统作为一种新型的在线交易方式&#xff0c;已经逐渐深入到人们的日常生活中。传统的拍卖活动需要耗费大量的人力、物力和时间&#xff0c;从组织拍卖、宣传、报名、竞拍到成…

JavaScript基础 -- 变量、作用域与内存

1 原始值与引用值 原始值就是最简单的数据&#xff0c;引用值则是由多个值构成的对象。在把一个值赋给变量时&#xff0c;JavaScript引擎必须要确定这个值是原始值还是引用值 原始值大小固定&#xff0c;保存在栈内存上&#xff1b;引用值是对象&#xff0c;存储在堆内存上 它…

密钥登录服务器

1. 生成 SSH 密钥对 如果您还没有生成密钥对&#xff0c;可以使用以下命令生成&#xff1a; ssh-keygen 在 root 用户的家目录中生成了一个 .ssh 的隐藏目录&#xff0c;内含两个密钥文件&#xff1a;id_rsa 为私钥&#xff0c;id_rsa.pub 为公钥。 在提示时&#xff0c;您可…

nginx 部署前端vue项目

&#x1f468;‍⚕ 主页&#xff1a; gis分享者 &#x1f468;‍⚕ 感谢各位大佬 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍⚕ 收录于专栏&#xff1a;前端工程师 文章目录 一、&#x1f353;什么是nginx&#xff1f;二、&#x1f353;nginx 部署…

三大行业案例:AI大模型+Agent实践全景

本文将从AI Agent和大模型的发展背景切入&#xff0c;结合51Talk、哈啰出行以及B站三个各具特色的行业案例&#xff0c;带你一窥事件驱动架构、RAG技术、人机协作流程&#xff0c;以及一整套行之有效的实操方法。具体包含内容有&#xff1a;51Talk如何让智能客服“主动进攻”&a…

HTML-CSS-常见标签与样式

目录 一. 央视新闻排版1.1 标题1.2 正文1.3 案例1.3.1 顶部导航栏1.3.2 flex布局1.3.3 表单标签1.3.4 表单项标签1.3.5 表格 1.3 课程总结 \quad 一. 央视新闻排版 \quad \quad 1.1 标题 \quad ALTp就是用AI快速生成 标题一共有6级 \quad 1.2 正文 \quad 定义视频 定义图片 样…

【信息安全设计】系统安全设计方案,系统安全保护设施设计实施方案(Word原件)

1.1 总体设计 1.1.1 设计原则 1.2 物理层安全 1.2.1 机房建设安全 1.2.2 电气安全特性 1.2.3 设备安全 1.2.4 介质安全措施 1.3 网络层安全 1.3.1 网络结构安全 1.3.2 划分子网络 1.3.3 异常流量管理 1.3.4 网络安全审计 1.3.5 网络访问控制 1.3.6 完整性检查 1.…

基于STP文件的智能比对系统:思通数科带来高效机械制造解决方案

在机械制造领域&#xff0c;设计图纸与实物之间的精准对比至关重要&#xff0c;传统的比对方式往往需要耗费大量时间且容易出现错误&#xff0c;导致生产效率低下并影响产品质量。为了解决这些问题推出了一套基于STP文件的智能比对系统&#xff0c;结合大模型技术&#xff0c;集…

【51项目】51单片机自制小霸王游戏机

视频演示效果&#xff1a; 纳新作品——小霸王游戏机 目录&#xff1a; 目录 视频演示效果&#xff1a; 目录&#xff1a; 前言&#xff1a; 一、连接方式&#xff1a; 1.1 控制引脚 1.2. 显示模块 1.3. 定时器 1.4. 游戏逻辑与硬件结合 1.5. 中断处理 二、源码分析&#xff1a…

SpringMVC(五)实现文件上传

目录 1.先导jar包 2.在Springmvc.xml配置文件上传解析器 3. 编写文件上传的html页面 4.在controller包中创建FileController.class文件 5.文件下载 6.重启服务器测试 1.先导jar包 <dependency><groupId>commons-fileupload</groupId><artifactId>…

LabVIEW声波谐振管自动化测量系统

开发了一种基于LabVIEW的声波谐振管自动化测量系统。该系统利用LabVIEW的强大功能&#xff0c;实现了对声波谐振频率的精确测量&#xff0c;提高了实验数据的采集效率和准确性。系统主要应用于物理教学和科研中&#xff0c;用于研究声波在谐振管中的传播特性。 项目背景 传统的…

docker Error response from daemon

问题 Error response from daemon: Get "https://index.docker.io/v1/search?qnginx&n25": read tcp 192.168.50.233:54354->54.198.86.24:443: read: connection reset by peer Unable to find image redis:latest locally docker: Error response from d…

PHP框架+gatewayworker实现在线1对1聊天--gatewayworker说明(2)

文章目录 gatewayworker使用说明onConnect 说明 gatewayworker使用说明 gatewayworker里只需要使用Applications\YourApp下的Events.php文件。 对文件的代码进行一下改造&#xff0c;如下&#xff0c;我们只需要用到onConnect方法&#xff0c;写法固定&#xff0c;其他方法都…

【Hadoop】Hadoop安全之Knox网关

目录 一、概述 2.1 knox介绍 2.2 版本信息 二、部署 三、验证Knox网关 3.1 Hdfs RESTFULL 3.2 HDFSUI 3.3 YARNUI 3.4 HBASEUI 一、概述 2.1 knox介绍 Apache Knox网关是一个用于与Apache Hadoop部署的REST api和ui交互的应用程序网关。Knox网关为所有与Apache Hadoop…