【ESP32】打造全网最强esp-idf基础教程——16.SmartConfig一键配网

SmartConfig一键配网

一、SmartConfig知识扫盲
       在讲STA课程的时候,我们用的是代码里面固定的SSID和密码去连接热点,但实际应用中不可能这么弄,我们得有办法把家里的WiFi SSID和密码输入到设备里面去,对于带屏带输入设备还好,因为可以人为手动输入,但很多IOT设备都不具备这种能力,因此我们需要其他方法。把SSID和密码告诉给设备,让设备能正确连接WiFi热点接入到物联网的过程,称为配网。

       配网方式有很多种,比如AP配网、蓝牙配网,还有本课介绍的SmartConfig一键配网,SmartConfig对用户来说操作是最简单的配网方式,其配网原理比较巧妙,我们来看下SmartConfig的基本原理到底如何。
       首先要让WiFi芯片处于混杂模式下,监听网络中的所有报文;手机APP将SSID和密码编码到 UDP 报文中,通过广播包或组播报发送,智能硬件接收到 UDP 报文后解码,得到正确的 SSID 和密码,然后主动连接指定 SSID 的路由完成连接。

       具体是如何接收报文的?另外在802.11协议中,MAC帧数据域是加密的,设备没有连上WiFi是无法读取这部分内容的。具体帧格式如下图,我们只关注MAC帧中的数据域(MSDU) 

       解析我们知道这部分数据的长度,这部分数据是由20字节IPv4头部+8字节UDP报文头部+UDP内容组成的IP报文,假如IP报文长度为500字节,则UDP内容长度为500-20-8=472字节,这里我们定义,500字节称为明文长度。 

       我们再制定一个定义,密文长度=明文长度+算法常量,算法常量往往是一个固定值,由APP和WIFI设备默认。 

       假如算法常量是10。现在手机APP要传输1234这个数据,只需要在UDP报文内容中填充(1234-20(Ipv4头)-8(UDP报头)-10(算法常量))个字节即可(内容任意),也就是  

        IP报文总长1224
       Ipv4头:20字节
       UDP头:8字节
       UDP内容:1196字节

       也就是说我们通过UDP广播发送1196个字节就行,内容任意。

       当设备收到这个UDP报文后需要解码,先得到IP报文长度1224,然后我们要加上算法常量10,得到1234,因此设备最终获得了1234这个数据。 

       那么对于设备来说,如何知道这个UDP广播包就是SmartConfig发出的呢?这里涉及到一个前导码的概念,当设备WIFI开启混杂模式时,会在所处环境中快速切换各条信道来抓取每个信道中的数据包,当遇到正在发送前导码数据包的信道时,锁定该信道并继续接收广播数据,直到收到足够的数据来解码出其中的WiFi密码然后连接WiFi,因此前导码一般由几个特殊的字节组成,方便和其他UDP包区分。 

       假设手机APP要发送”test”四个字符,算法常量为16,流程如下:
      1)APP连续发送3个UDP广播包,数据为均为前导码。
      2)APP发送1个UDP广播包,IP报文数据长度为’t’-16。
      3)APP发送1个UDP广播包,IP报文数据长度为’e’-16。
      4)APP发送1个UDP广播包,IP报文数据长度为’s’-16。
      5)APP发送1个UDP广播包,IP报文数据长度为’t’-16。
      6)APP切换WIFI信道重复上述步骤

       上述是数据传输的基本原理,但由于每一家厂商的算法常量、传输内容格式、前导码等都不一样,因此不同厂家之间的SmartConfig一般无法通用。

二、ESP32中的SmartConfig
       通过查看esp-idf的源码,发现ESP32上的SmartConfig实现是看不到源码的,但不妨碍我们使用,而使用方式也比较简单,当然需要配合APP来使用,乐鑫官方也提供了demo版本的APP,这个是开源的,我们可以集成到自己的APP应用中,下载地址是: 

       安卓:
https://github.com/EspressifApp/EsptouchForAndroid/releases/tag/v2.0.0/esptouch-v2.0.0.apk

       IOS:
https://apps.apple.com/cn/app/espressif-esptouch/id1071176700

       接下来看下ESP32源码,源码位于esp32-board/wifi_smartconfig
       由于在实际应用工程中,进入SmartConfig一般都是长按某个按键,因此这个例程中也把之前按键短按长按处理的例程搬过来用了,长按3秒触发SmartConfig。

       app_main()如下 

//按键事件组
static EventGroupHandle_t s_pressEvent;
#define SHORT_EV    BIT0    //短按
#define LONG_EV     BIT1    //长按
#define BTN_GPIO    GPIO_NUM_39/** 长按按键回调函数* @param 无* @return 无
*/
void long_press_handle(void)
{xEventGroupSetBits(s_pressEvent,LONG_EV);
}
void app_main(void)
{nvs_flash_init();           //初始化NVSinitialise_wifi();          //初始化wifis_pressEvent = xEventGroupCreate();button_config_t btn_cfg = {.gpio_num = BTN_GPIO,       //gpio号.active_level = 0,          //按下的电平.long_press_time = 3000,    //长按时间.short_cb = NULL,           //短按回调函数.long_cb = smartconfig_start             //长按回调函数};button_event_set(&btn_cfg);     //添加按键响应事件处理EventBits_t ev;while(1){ev = xEventGroupWaitBits(s_pressEvent,LONG_EV,pdTRUE,pdFALSE,portMAX_DELAY);if(ev & LONG_EV){smartconfig_start();    //检测到长按事件,启动smartconfig}}
}

       app_main()中注册了长按按键事件,主循环中检测到了长按事件,执行smartconfig_start函数,启动SmartConfig。 

       接下来看下main/wifi_smartconfig.c文件对SmartConfig的处理 

/** 启动smartconfig* @param 无* @return 无
*/
void smartconfig_start(void)
{if(!s_is_smartconfig){s_is_smartconfig = true;esp_wifi_disconnect();xTaskCreate(smartconfig_example_task, "smartconfig_example_task", 4096, NULL, 3, NULL);}
}

       smartconfig_start函数里面,会断开wifi连接然后启用一个smartconfig任务,s_is_smartconfig标志是SmartConfig运行标志,防止重复执行SmartConfig。 

/** smartconfig处理任务* @param 无* @return 无
*/
static void smartconfig_example_task(void * parm)
{EventBits_t uxBits;ESP_ERROR_CHECK( esp_smartconfig_set_type(SC_TYPE_ESPTOUCH_V2) );           //设定SmartConfig版本smartconfig_start_config_t cfg = SMARTCONFIG_START_CONFIG_DEFAULT();ESP_ERROR_CHECK( esp_smartconfig_start(&cfg) ); //启动SmartConfigwhile (1) {uxBits = xEventGroupWaitBits(s_wifi_event_group, CONNECTED_BIT | ESPTOUCH_DONE_BIT, true, false, portMAX_DELAY);if(uxBits & CONNECTED_BIT) {ESP_LOGI(TAG, "WiFi Connected to ap");}if(uxBits & ESPTOUCH_DONE_BIT) {    //收到smartconfig配网完成通知ESP_LOGI(TAG, "smartconfig over");esp_smartconfig_stop();         //停止smartconfig配网write_nvs_ssid(s_ssid_value);   //将ssid写入NVSwrite_nvs_password(s_password_value);   //将password写入NVSs_is_smartconfig = false;       vTaskDelete(NULL);              //退出任务}}
}

       在smartconfig_example_task中会设定SmartConfig的版本,可以选V1、V2、AirKiss(微信用的),版本之间不兼容,我这边选用了V2,然后esp_smartconfig_start(&cfg)启动SmartConfig,后面会监听两个事件,一个是WiFi连接成功事件,一个是SmartConfig完成事件,当SmartConfig完成后,我们把SSID和密码保存到NVS中,然后退出任务,结束整个SmartConfig流程。 

       

/** 各种网络事件的回调函数* @param arg 自定义参数* @param event_base 事件类型* @param event_id 事件标识ID,不同的事件类型都有不同的实际标识ID* @param event_data 事件携带的数据
*/
static void 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_STA_START) {if(s_ssid_value[0] != 0)esp_wifi_connect();} else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) {//WIFI断开连接后,再次发起连接if(!s_is_smartconfig)esp_wifi_connect();//清除连接标志位xEventGroupClearBits(s_wifi_event_group, CONNECTED_BIT);} else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {//获取到IP,置位连接事件标志位xEventGroupSetBits(s_wifi_event_group, CONNECTED_BIT);} else if (event_base == SC_EVENT && event_id == SC_EVENT_SCAN_DONE) {//smartconfig 扫描完成ESP_LOGI(TAG, "Scan done");} else if (event_base == SC_EVENT && event_id == SC_EVENT_FOUND_CHANNEL) {//smartconfig 找到对应的通道ESP_LOGI(TAG, "Found channel");} else if (event_base == SC_EVENT && event_id == SC_EVENT_GOT_SSID_PSWD) {//smartconfig 获取到SSID和密码ESP_LOGI(TAG, "Got SSID and password");smartconfig_event_got_ssid_pswd_t *evt = (smartconfig_event_got_ssid_pswd_t *)event_data;wifi_config_t wifi_config;uint8_t ssid[33] = { 0 };uint8_t password[65] = { 0 };//从event_data中提取SSID和密码bzero(&wifi_config, sizeof(wifi_config_t));memcpy(wifi_config.sta.ssid, evt->ssid, sizeof(wifi_config.sta.ssid));memcpy(wifi_config.sta.password, evt->password, sizeof(wifi_config.sta.password));wifi_config.sta.bssid_set = evt->bssid_set;if (wifi_config.sta.bssid_set == true) {memcpy(wifi_config.sta.bssid, evt->bssid, sizeof(wifi_config.sta.bssid));}memcpy(ssid, evt->ssid, sizeof(evt->ssid));memcpy(password, evt->password, sizeof(evt->password));ESP_LOGI(TAG, "SSID:%s", ssid);ESP_LOGI(TAG, "PASSWORD:%s", password);snprintf(s_ssid_value,33,"%s",(char*)ssid);snprintf(s_password_value,65,"%s",(char*)password);//重新连接WIFIESP_ERROR_CHECK( esp_wifi_disconnect() );ESP_ERROR_CHECK( esp_wifi_set_config(WIFI_IF_STA, &wifi_config) );esp_wifi_connect();} else if (event_base == SC_EVENT && event_id == SC_EVENT_SEND_ACK_DONE) {//smartconfig 已发起回应xEventGroupSetBits(s_wifi_event_group, ESPTOUCH_DONE_BIT);}
}

       在事件处理回调函数中,包含了对SmartConfig的处理,比较关键的是SC_EVENT_GOT_SSID_PSWDSC_EVENT_SEND_ACK_DONE事件,SC_EVENT_GOT_SSID_PSWD事件表示已经获取到SSID和密码了,接下来我们可以发起连接。SC_EVENT_SEND_ACK_DON事件表示SmartConfig完成,配网可以结束了,通知SmartConfig任务退出。 

       由此可见,esp-idf对SmartConfig功能进行了高度封装,我们基本不用做复杂的处理就可以使用,十分方便,完整的代码请看esp32-board/wifi_smartconfig,idf.py build+idf.py flash烧录到开发板后,就可以运行。另外大家可以看下官方的demo APP

 

       左边是V1版本,右边是V2版本,在进入APP的时候可以选择,使用的时候,需要手机连接当前的2.4G WiFi,然后输入密码,点击确定的时候就开始了,开发板上长按按键3秒,查看串口打印开始了SmartConfig即可松手,过一会就会自动的完成配网。 

最后附上相关资料:

ESP32教程资料链接:
https://pan.baidu.com/s/1kCjD8yktZECSGmHomx_veg?pwd=q8er 
提取码:q8er 

配套源码下载地址:
esp32-board: esp32开发板配套的经典例程

鉴于实验需要开发板的支持,我也设计了一款ESP32开发板,包含部分传感器模块,1.69寸LCD高亮屏,Type-C一键下载,方便大家学习和做各种实验。开发板链接如下:

https://item.taobao.com/item.htm?ft=t&id=802401650392&spm=a21dvs.23580594.0.0.4fee645eXpkfcp&skuId=5635015963649
 

​​

请大家多多支持。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C++报警:warning: zero as null pointer constantstddef.h

源码和警告内容 解决办法: select(0,nullptr,nullptr,nullptr,&delay); 关于NULL和nullptr的区别: 在C中,nullptr和null(通常指的是NULL宏,因为C标准中并没有直接定义null关键字)都用于表示空指针&am…

JSP入门基础

JSP入门基础 软件开发环境这门课程的复习资料 Web开发技术概述 URL的组成部分 协议、主机DNS名或IP地址和文件名 Tomcat服务器 Tomcat服务器的默认端口号是8080 概念 软件开发环境是围绕着软件开发的一定目标而组织在一起的一组相关软件工具的有机集合 JSP和HTML的区别…

系统数据加密传输的实现

文章目录 1、背景2、需求3、实现思路3.1 密码加密3.2 密码解密3.3 nacos密码加密 4、相关工具类4.1 非对称加密RSA4.2 对称加密AES4.3 Nacos加解密的实现:Jasypt 5、历史数据兼容处理 1、背景 用户在浏览器发送请求数据到后台系统,期间数据在网络传输&a…

Git常见命令和用法

Git 文件状态 Git 文件 2 种状态: 未跟踪:新文件,从未被 Git 管理过已跟踪:Git 已经知道和管理的文件 常用命令 命令作用注意git -v查看 git 版本git init初始化 git 仓库初始化之后有工作区、暂存区(本地库)、版本库git add 文件标识暂存某个文件文件标识以终…

springboot集成tika解析word,pdf,xls文件文本内容

介绍 Apache Tika 是一个开源的内容分析工具包,用于从各种文档格式中提取文本和元数据。它支持多种文档类型,包括但不限于文本文件、HTML、PDF、Microsoft Office 文档、图像文件等。Tika 的主要功能包括内容检测、文本提取和元数据提取。 官网 https…

GRPC使用之ProtoBuf

1. 入门指导 1. 基本定义 Protocol Buffers提供一种跨语言的结构化数据的序列化能力,类似于JSON,不过更小、更快,除此以外它还能用用接口定义(IDL interface define language),通protoc编译Protocol Buffer定义文件,…

Android14系统应用统一裁剪方案

Android14系统应用统一裁剪方案 背景 当前移除集成到系统里的应用,一般都是根据应用名,到各个mk文件里逐个在PRODUCT_PACKAGES中删除;这种方法,耗时而且不易管理集成到系统里的应用;需要有一个统一管理删除不需要应用的方案。 方案 参考PRODUCT_PACKAGES变量,添加PRO…

淘宝商品历史价格查询(免费)

当前资料来源于网络,禁止用于商用,仅限于学习。 淘宝联盟里面就可以看到历史价格 并且没有加密 淘宝商品历史价格查询可以通过以下步骤进行: 先下载后,登录app注册账户 打开淘宝网站或淘宝手机App。在搜索框中输入你想要查询的商…

短视频矩阵系统多账号搭建技术源码(saas开发者技术独立搭建)

在构建云服务环境以部署虚拟机方面,以Amazon Web Services(AWS)为示例,需采购并配置适当数量的EC2实例以及相关网络设施。 接下来,根据业务需求,应创建多个社交媒体平台如抖音和快手的官方账户,…

【计算机毕业设计】基于Springboot的B2B平台医疗病历交互系统【源码+lw+部署文档】

包含论文源码的压缩包较大,请私信或者加我的绿色小软件获取 免责声明:资料部分来源于合法的互联网渠道收集和整理,部分自己学习积累成果,供大家学习参考与交流。收取的费用仅用于收集和整理资料耗费时间的酬劳。 本人尊重原创作者…

【记录】LaTex|LaTex 代码片段 Listings 添加带圆圈数字标号的箭头(又名 LaTex Tikz 库画箭头的简要介绍)

文章目录 前言注意事项1 Tikz 的调用方法:newcommand2 标号圆圈数字的添加方式:\large{\textcircled{\small{1}}}\normalsize3 快速掌握 Tikz 箭头写法:插入点相对位移标号node3.1 第一张图:插入点相对位移3.2 第二张图&#xff1…

如何玩转澳大利亚Facebook直播?

近年来,直播带货已经成为国内最赚钱的行业之一,各种玩法也越来越成熟。然而,在海外市场,尤其是澳大利亚,直播带货仍然是一片蓝海。作为社交媒体营销的主阵地,Facebook的直播功能却常常被卖家忽视。那么&…

贴脸细看Mixtral 8x7B- 稀疏混合专家模型(MoE)的创新与推动

贴脸细看Mixtral 8x7B- 稀疏混合专家模型(MoE)的创新与推动 原创 一路到底孟子敬 上堵吟 2024年01月15日 20:05 美国 I. 引言 A. Mixtral 8x7B的背景和目的 • 背景:随着大型语言模型在自然语言处理(NLP)领域的广泛…

【java计算机毕设】基于java的奶茶店管理系统的设计与实现MySQL ssm JSP maven项目代码源码+文档

目录 1项目功能 2项目介绍 3项目地址 1项目功能 【java计算机毕设】奶茶店管理系统java MySQL ssm JSP maven项目源码代码万字文档 小组设计 2项目介绍 系统功能: 奶茶店管理系统包括管理员、用户俩种角色。 管理员功能包括个人中心模块用于修改个人信息和密码、…

游戏AI的创造思路-技术基础-情感计算(1)

游戏中的AI也是可以和你打情感牌的哦,不要以为NPC是没有感情的,不过,不要和NPC打过多的情感牌,你会深陷其中无法自拔的~~~~~~ 目录 1. 情感计算算法定义 2. 发展历史 3. 公式和函数 3.1. 特征提取阶段 TF-IDF(词频…

AJAX-个人版2.0

AJAX(Asynchronous Javascript And Xml) 传统请求及缺点 传统的请求都有哪些? 直接在浏览器地址栏上输入URL。点击超链接提交form表单使用JS代码发送请求 window.open(url)document.location.href urlwindow.location.href url… 传统请…

一键换衣,这个AI可以让你实现穿衣自由

基于图像的虚拟穿衣是一种流行且前景广阔的图像合成技术,能够显著改善消费者的购物体验,并降低服装商家的广告成本。顾名思义,虚拟穿衣任务旨在生成目标人穿着给定服装的图像。 OOTDiffusion简述 图1 虚拟换衣 基于图像的虚拟穿衣目前面临两…

系统分析师-基础知识

基础知识 一、计算机组成与结构1、计算机系统基础知识1.1 计算机硬件组成1.2 中央处理单元(CPU)1.3 数据表示1.3.1 R进制转十进制:1.3.2 十进制转R进制: 1.4 校验码(3种校验码)1.4.1 基本知识1.4.2 奇偶校验…

2024-07抖音/快手/小红书/视频号/美团无人直播技术:最新不封号无人直播的操作方法详细介绍

2024年最新研究出来的无人直播技术,目前不封号,用途大大的,可带货,可引流,可获客。 手机自动直播源码通常涉及到实时流媒体技术和应用开发,它涉及以下几个关键部分: 摄像头接入:使用…

vue3 学习笔记01 -- 搭建项目及基础配置

vue3 学习笔记01 – 搭建项目及基础配置 确保你已经安装了Node.js(建议使用最新的LTS版本) 搭建项目 初始化项目 如果选择npm创建项目再执行 npm create vitelatest my-vue3-app --template vue-ts使用yarn,如果电脑没有安装yarn cnpm i ya…