尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

arduino-esp32 WPS 配网实战:Push Button 与 PIN 模式的串口日志全解读

发布时间:2026/9/14 17:27:27

资讯中心
01
ARTICLE

arduino-esp32 WPS 配网实战:Push Button 与 PIN 模式的串口日志全解读

arduino-esp32 WPS 配网实战:Push Button 与 PIN 模式的串口日志全解读
arduino-esp32 WPS 配网实战Push Button 与 PIN 模式的串口日志全解读【免费下载链接】arduino-esp32Arduino core for the ESP32 family of SoCs项目地址: https://gitcode.com/GitHub_Trending/ar/arduino-esp32本篇围绕 arduino-esp32 中libraries/WiFi的 WPS 示例展开讲清 ESP32 如何通过 WPSWi-Fi Protected SetupWi-Fi 保护配置免密/免手输口令接入路由器Push ButtonPBC与 PIN 两种模式的正确操作步骤、四种典型串口日志成功/失败 × 两种模式逐行解读以及示例代码背后的事件驱动流程。读完之后你可以直接烧录 WPS 示例完成配网并能准确判断卡在哪一步、为什么没连上。WPS 是什么为什么适合设备配网WPS 是路由器与设备之间的一套免手输口令的配网协议主流路由器普遍支持两种方式Push ButtonPBC按钮模式ESP32 启动 WPS 后按下路由器上的 WPS 按钮通常为机身背面或侧面的小按钮标有 WPS 字样或环形箭头图标路由器自动下发 SSID 和密码设备完成配网PIN 模式ESP32 生成一个 8 位数字 PIN 并通过串口打印你在路由器管理页面常见地址 192.168.0.1的 WPS 设置中手动输入该 PIN 完成配网。PIN 在成功连接前会每 2 分钟刷新一次需要在新 PIN 生成的窗口期内及时输入。相比手动输入密码WPS 适合设备上没有屏幕、不方便交互的量产场景相比 SmartConfig 等 App 配网方案WPS 无需额外 App。示例自带的 README.md 正是以串口日志的形式给出四种场景下 ESP32 的完整输出作为本文解读的基准。示例工程与运行前提示例代码位于 WPS.ino硬件需求仅两块ESP32 开发板 一台支持 WPS 的路由器。工程顶部有一处硬约束直接编译即可验证#include sdkconfig.h #if CONFIG_ESP_HOSTED_ENABLED #error WPS is only supported in SoCs with native Wi-Fi support #endif即启用了 esp_hosted无线功能由协处理器承担的 SoC 不支持 WPS只有自带原生 Wi-Fi 射频的芯片经典 ESP32、ESP32-S2/S3/C3/C5/C6 等才能运行此示例。两种模式如何切换模式由一个宏决定/* Change the definition of the WPS mode from WPS_TYPE_PBC to WPS_TYPE_PIN in the case that you are using pin type WPS (pin is 00000000) */ #define ESP_WPS_MODE WPS_TYPE_PBC按钮模式保持WPS_TYPE_PBCPIN 模式改为WPS_TYPE_PIN届时串口会打印WPS_PIN 8位数字。注意此处注释中的00000000是初始化配置时填入config.pin的占位值见下文wpsStart()中snprintf(config.pin, ...)的写法实际配网使用的 PIN 由 Wi-Fi 协议栈动态生成并通过ARDUINO_EVENT_WPS_ER_PIN事件回调上报到串口两者不是同一个东西。示例代码逐段剖析启动 WPSwpsStart()核心配置与启动逻辑在 WPS.inovoid wpsStart() { esp_wps_config_t config; memset(config, 0, sizeof(esp_wps_config_t)); //Same as config WPS_CONFIG_INIT_DEFAULT(ESP_WPS_MODE); config.wps_type ESP_WPS_MODE; snprintf(config.factory_info.manufacturer, sizeof(config.factory_info.manufacturer), ESPRESSIF); snprintf(config.factory_info.model_number, sizeof(config.factory_info.model_number), %s, CONFIG_IDF_TARGET); snprintf(config.factory_info.model_name, sizeof(config.factory_info.model_name), ESPRESSIF IOT); snprintf(config.factory_info.device_name, sizeof(config.factory_info.device_name), ESP DEVICE); snprintf(config.pin, sizeof(config.pin), 00000000); esp_err_t err esp_wifi_wps_enable(config); if (err ! ESP_OK) { Serial.printf(WPS Enable Failed: 0x%x: %s\n, err, esp_err_to_name(err)); return; } #if ESP_IDF_VERSION ESP_IDF_VERSION_VAL(6, 0, 0) err esp_wifi_wps_start(); #else err esp_wifi_wps_start(0); #endif if (err ! ESP_OK) { Serial.printf(WPS Start Failed: 0x%x: %s\n, err, esp_err_to_name(err)); } }几个关键点esp_wps_config_t全零初始化后只填必要字段。factory_info制造商、型号、设备名等是 WPS 协议要求携带的设备信息路由器在认证时会用到model_number直接取编译目标CONFIG_IDF_TARGET如esp32、esp32s3无需手写。流程分两步esp_wifi_wps_enable(config)使能并写入配置随后esp_wifi_wps_start()开始监听/发起 WPS 会话。任一步失败都会通过esp_err_to_name打印可读错误码便于定位是配置阶段还是启动阶段出错。代码对 ESP-IDF 版本做了兼容IDF 6.0 起esp_wifi_wps_start不再需要参数旧版本需传0。示例同时支持新旧两条 IDF 基线。停止 WPS 的wpsStop()仅调用esp_wifi_wps_disable()失败时打印WPS Disable Failed。事件回调WPS 的成败全靠它WPS 是异步协议所有结果通过 FreeRTOS 事件任务回调。WPS.ino 中的WiFiEvent()处理了全部关键事件// WARNING: WiFiEvent is called from a separate FreeRTOS task (thread)! void WiFiEvent(WiFiEvent_t event, arduino_event_info_t info) { switch (event) { case ARDUINO_EVENT_WIFI_STA_START: Serial.println(Station Mode Started); break; case ARDUINO_EVENT_WIFI_STA_GOT_IP: Serial.println(Connected to : String(WiFi.SSID())); Serial.print(Got IP: ); Serial.println(WiFi.localIP()); break; case ARDUINO_EVENT_WIFI_STA_DISCONNECTED: Serial.println(Disconnected from station, attempting reconnection); WiFi.reconnect(); break; case ARDUINO_EVENT_WPS_ER_SUCCESS: Serial.println(WPS Successful, stopping WPS and connecting to: String(WiFi.SSID())); wpsStop(); delay(10); WiFi.begin(); break; case ARDUINO_EVENT_WPS_ER_FAILED: Serial.println(WPS Failed, retrying); wpsStop(); wpsStart(); break; case ARDUINO_EVENT_WPS_ER_TIMEOUT: Serial.println(WPS Timedout, retrying); wpsStop(); wpsStart(); break; case ARDUINO_EVENT_WPS_ER_PIN: Serial.println(WPS_PIN wpspin2string(info.wps_er_pin.pin_code)); break; default: break; } }事件语义与对应的串口打印一一映射事件含义示例行为ARDUINO_EVENT_WIFI_STA_STARTSTA 模式已启动WPS 开始监听打印Station Mode StartedARDUINO_EVENT_WPS_ER_PINPIN 模式下新 PIN 已生成打印WPS_PIN xxxxxxxx8 位ARDUINO_EVENT_WPS_ER_SUCCESSWPS 交换完成凭证已写入停止 WPS稍等 10ms 后WiFi.begin()用新凭证连接ARDUINO_EVENT_WPS_ER_FAILED本次 WPS 失败停止后立即重启 WPS无限重试ARDUINO_EVENT_WPS_ER_TIMEOUT等待路由器响应超时停止后立即重启 WPS无限重试ARDUINO_EVENT_WIFI_STA_DISCONNECTED已连接但掉线打印提示并WiFi.reconnect()ARDUINO_EVENT_WIFI_STA_GOT_IP拿到 IP配网彻底完成打印 SSID 与Got IP: x.x.x.x注意回调开头的注释该函数运行在独立的 FreeRTOS 任务里回调内部不要做长时间阻塞操作。另外成功路径里有一个细节WPS 交换成功后设备已经拿到 SSID/密码示例仍调用一次WiFi.begin()触发正式连接——这正是日志中成功后又出现一次连接的原因。PIN 数组转字符串的工具函数wpspin2string()把 8 字节pin_code拼成以\0结尾的 C 字符串再转String输出WPS.ino。setup()则完成初始化115200 波特率串口 → 注册事件回调WiFi.onEvent(WiFiEvent)→WiFi.mode(WIFI_MODE_STA)→wpsStart()之后loop()留空全程由事件驱动。读懂串口日志四个典型场景README.md 给出的四段日志覆盖了两种模式 × 成功/失败的全部组合。下面逐段继承原文日志并解读。四段日志共享同一段启动横幅ets Jun 8 2016 00:22:57 rst:0x10 (RTCWDT_RTC_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT) configsip: 0, SPIWP:0xee clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00 mode:DIO, clock div:1 load:0x3fff0010,len:4 load:0x3fff0014,len:732 load:0x40078000,len:0 load:0x40078000,len:11572 entry 0x40078a14这是 ESP32 早期 BootROM 的标准输出rst:0x10 (RTCWDT_RTC_RESET)表示由 RTC 看门狗复位boot:0x13 (SPI_FAST_FLASH_BOOT)表示以 SPI 快读模式从 Flash 启动随后的load:0x...是各段镜像的加载过程entry 0x40078a14为程序入口。这部分与 WPS 本身无关属于板卡正常启动的基线。场景一Push Button 失败操作步骤ESP32 上电并打印 WPS 已启动后在短时间内按下路由器的 WPS 按钮若按钮 2 分钟窗口内未按下或路由器不响应即出现下述日志。若不确定自己的路由器是否支持 WPS 按钮需查看路由器规格说明。ets Jun 8 2016 00:22:57 rst:0x10 (RTCWDT_RTC_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT) configsip: 0, SPIWP:0xee clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00 mode:DIO, clock div:1 load:0x3fff0010,len:4 load:0x3fff0014,len:732 load:0x40078000,len:0 load:0x40078000,len:11572 entry 0x40078a14 Starting WPS Station Mode Started WPS Timedout, retrying WPS Timedout, retrying逐行解读Starting WPSsetup()中wpsStart()已执行Station Mode StartedARDUINO_EVENT_WIFI_STA_STARTWi-Fi STA 就绪WPS 监听已开启此时可以按路由器 WPS 键WPS Timedout, retrying反复出现ARDUINO_EVENT_WPS_ER_TIMEOUT每次超时后示例都会wpsStop()wpsStart()重新监听。也就是说按钮模式下设备会自动无限重试——只要你随后按下了 WPS 键下一轮监听窗口内就可能成功无需重新上电。场景二Push Button 成功ets Jun 8 2016 00:22:57 rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT) ets Jun 8 2016 00:22:57 rst:0x10 (RTCWDT_RTC_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT) configsip: 0, SPIWP:0xee clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00 mode:DIO, clock div:1 load:0x3fff0010,len:4 load:0x3fff0014,len:732 load:0x40078000,len:0 load:0x40078000,len:11572 entry 0x40078a14 Starting WPS Station Mode Started WPS Successful, stopping WPS and connecting to: Your Router SSID Disconnected from station, attempting reconnection Connected to : Your Router SSID Got IP: 192.168.1.100关键路径WPS Successful, stopping WPS and connecting to: Your Router SSID ARDUINO_EVENT_WPS_ER_SUCCESS凭证交换完成此时WiFi.SSID()已能读出路由器 SSIDDisconnected from station, attempting reconnection这是 WPS 收尾阶段的瞬态事件WIFI_STA_DISCONNECTED属正常现象不必当作故障Connected to : Your Router SSID ARDUINO_EVENT_WIFI_STA_GOT_IP前置的连接建立Got IP: 192.168.1.100DHCP 拿到地址配网完成。出现Got IP之后WPS 的使命已经结束之后的网络请求可走WiFiClient、HTTPClient等任意库。场景三PIN 模式失败操作方式与按钮模式不同串口会周期性打印 8 位 PIN你需要登录路由器管理页面一般为 192.168.0.1在 WPS 设置里输入。PIN 每 2 分钟刷新一次输入必须赶在当前 PIN 有效期内错过或输错就会出现连续超时ets Jun 8 2016 00:22:57 rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT) ets Jun 8 2016 00:22:57 rst:0x10 (RTCWDT_RTC_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT) configsip: 0, SPIWP:0xee clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00 mode:DIO, clock div:1 load:0x3fff0010,len:4 load:0x3fff0014,len:732 load:0x40078000,len:0 load:0x40078000,len:11572 entry 0x40078a14 Starting WPS Station Mode Started WPS_PIN 94842104 WPS Timedout, retrying WPS_PIN 55814171 WPS Timedout, retrying WPS_PIN 71321622日志节奏与代码行为完全吻合每轮 WPS 会话超时会打印WPS Timedout, retrying并重启 WPSPIN 模式下每个新会话都会通过ARDUINO_EVENT_WPS_ER_PIN事件生成并打印一个新的WPS_PIN。可以看到94842104 → 55814171 → 71321622三个 PIN 各不相同印证了PIN 会随会话刷新。排错要点路由器端输入的必须是当前这一轮打印出的 PIN且要在该轮 2 分钟窗口内完成提交。场景四PIN 模式成功ets Jun 8 2016 00:22:57 rst:0x10 (RTCWDT_RTC_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT) configsip: 0, SPIWP:0xee clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00 mode:DIO, clock div:1 load:0x3fff0010,len:4 load:0x3fff0014,len:732 load:0x40078000,len:0 load:0x40078000,len:11572 entry 0x40078a14 Starting WPS Station Mode Started WPS_PIN 36807581 WPS Successful, stopping WPS and connecting to: Your Router SSID Disconnected from station, attempting reconnection Connected to :Your Router SSID Got IP: 192.168.1.100与按钮模式成功日志的差异只有一处成功前多了一行WPS_PIN 36807581——即你在路由器端输入的那个 PIN。之后的WPS Successful → Disconnected瞬态→ Connected → Got IP四步与按钮模式完全一致。快速诊断速查串口现象含义处理建议只有Starting WPS无Station Mode StartedSTA 未就绪或使能失败检查是否打印了WPS Enable/Start Failed: 0x...错误码反复WPS Timedout, retryingPBC监听窗口内未按 WPS 键在下一轮窗口内及时按键确认路由器支持 WPS 按钮反复WPS Timedout 新WPS_PINPINPIN 未在有效期内输入或输错用当前打印的 PIN在 2 分钟内提交到路由器 WPS 设置页WPS Successful后无Got IP凭证已交换但连接失败查看是否持续Disconnected... attempting reconnection检查路由器侧是否允许新设备事件桥接机制从 IDF 事件到 Arduino 事件示例代码并不直接注册 Wi-Fi 事件而是通过WiFi.onEvent()注册 Arduino 层回调。底层桥接在 WiFiGeneric.cpp 的_arduino_event_cb()中完成ESP-IDF 的WIFI_EVENT_STA_WPS_ER_*事件被逐一映射为 Arduino 事件——} else if (event_base WIFI_EVENT event_id WIFI_EVENT_STA_WPS_ER_SUCCESS) { arduino_event.event_id ARDUINO_EVENT_WPS_ER_SUCCESS; } else if (event_base WIFI_EVENT event_id WIFI_EVENT_STA_WPS_ER_FAILED) { arduino_event.event_id ARDUINO_EVENT_WPS_ER_FAILED; memcpy(arduino_event.event_info.wps_fail_reason, event_data, sizeof(wifi_event_sta_wps_fail_reason_t)); } else if (event_base WIFI_EVENT event_id WIFI_EVENT_STA_WPS_ER_TIMEOUT) { arduino_event.event_id ARDUINO_EVENT_WPS_ER_TIMEOUT; } else if (event_base WIFI_EVENT event_id WIFI_EVENT_STA_WPS_ER_PIN) { arduino_event.event_id ARDUINO_EVENT_WPS_ER_PIN; memcpy(arduino_event.event_info.wps_er_pin, event_data, sizeof(wifi_event_sta_wps_er_pin_t)); }两个值得注意的实现细节失败原因可取WIFI_EVENT_STA_WPS_ER_FAILED的负载wifi_event_sta_wps_fail_reason_t含reason与status_code会被复制到arduino_event_info_t.wps_fail_reason字段示例没有打印它但在自定义配网程序中可以借此区分路由器拒绝协议错误等具体失败原因。PIN 载荷可取wifi_event_sta_wps_er_pin_t被复制到wps_er_pin字段示例正是从info.wps_er_pin.pin_code读出 8 字节 PIN。事件枚举与 info 字段定义分别位于 NetworkEvents.h 的ARDUINO_EVENT_WPS_ER_PIN等枚举项以及 NetworkEvents.h 中arduino_event_info_t联合体里的wps_er_pin/wps_fail_reason成员。从源码结构看这套映射是 Arduino 事件总线ARDUINO_EVENTS对 Wi-Fi 事件层统一封装的一部分因此 WPS 事件与扫描、SmartConfig、Provisioning 等事件共享同一回调通道写自定义配网固件时可以一次onEvent同时处理多种事件。使用建议与安全提示PBC 优先按钮模式无需登录路由器后台交互最简单PIN 模式涉及管理页面适合没有实体 WPS 键的无线路由器。窗口期意识无论哪种模式WPS 会话都是限时窗口超时即触发示例中的自动重启循环操作要紧跟串口打印的Station Mode Started/ 当前WPS_PIN。自动重试是双刃剑示例在失败/超时后无限重启 WPS方便晚按的键被下一轮捕获但也意味着配网失败时 WPS 端口长期开放。WPS 协议本身存在被离线攻击破解 PIN 的已知安全隐患PIN 空间小量产设备建议仅在配网阶段开启 WPS、取得 IP 后关闭示例已在WPS Successful后调用wpsStop()可作为参考。适用边界WPS 仅适用于原生 Wi-Fi SoC基于 esp_hosted 架构的芯片编译期即被#error拦截见前文请改用 SmartConfig 或 Network Provisioning 等其他配网方案可参见 WiFiSmartConfig 等示例。小结WPS 示例的完整链路是setup()以 STA 模式启动 →esp_wifi_wps_enable/start开启 WPS 监听 → 用户在路由器侧按键PBC或输入 PIN →ARDUINO_EVENT_WPS_ER_PIN/SUCCESS/FAILED/TIMEOUT事件经 WiFiGeneric.cpp 桥接回到WiFiEvent()回调 → 成功后停止 WPS 并WiFi.begin()正式联网、拿到Got IP。掌握四段串口日志的判读方式本文场景一四再配合事件表与诊断速查表即可独立完成配网开发与现场排障需要更多实现细节时可直接对照 WPS.ino 与 README.md 原文。【免费下载链接】arduino-esp32Arduino core for the ESP32 family of SoCs项目地址: https://gitcode.com/GitHub_Trending/ar/arduino-esp32创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。