junhui93/wifi_provisioner

1.2.1

Latest
uploaded 5 hours ago
Commercial-friendly WiFi provisioning component with captive portal fallback and persistent auto-reconnect for ESP-IDF

Readme

# WiFi Provisioner / WiFi 配网组件

**EN** — Commercial-friendly WiFi provisioning component for ESP-IDF with captive-portal fallback, persistent auto-reconnect, and TX power fallback for antenna impedance mismatch.

**中文** — 面向 ESP-IDF 的商用级 WiFi 配网组件,支持 Soft-AP 强制门户配网、断连持续自动重连、以及天线阻抗不匹配时的发射功率降级重试。

> **EN | Why this component?** The original `esp-idf-wifi-provisioner` is licensed under GPL-3.0, which requires the entire project to be open-sourced. This component is independently implemented under the **MIT license** based on the general concept of WiFi provisioning and ESP-IDF official documentation — safe for commercial and closed-source products.
>
> **中文 | 为什么选它?** 原始的 `esp-idf-wifi-provisioner` 采用 GPL-3.0 协议,要求整个工程开源。本组件基于 WiFi 配网的通用概念和 ESP-IDF 官方文档**独立实现**,采用 **MIT 协议**——可安全用于商用及闭源产品。

---

## Features / 功能特性

**EN**
- **STA auto-connect** from credentials stored in NVS
- **Soft-AP + captive portal** fallback when no credentials are stored or connection fails
- **WiFi network scan** with signal strength display in the captive portal
- **Credential verification** — submitted credentials are tested before being saved
- **Persistent auto-reconnect** — after a successful connection, if the link drops the component keeps reconnecting with exponential back-off
- **TX power fallback** — if the AP can be scanned but connection fails with signal-quality-related reason codes (e.g. handshake timeout), TX power is progressively lowered to work around antenna impedance mismatch (high VSWR)
- **Non-blocking API** — `wifi_prov_start()` returns immediately; all work happens in a background task
- **Configurable** via menuconfig or runtime `wifi_prov_config_t`
- **Event callbacks** for connect, disconnect, and portal start

**中文**
- **STA 自动连接**:从 NVS 读取已保存的凭证自动联网
- **Soft-AP + 强制门户回退**:无凭证或连接失败时自动开启配网门户
- **WiFi 扫描**:配网页面展示附近网络及信号强度
- **凭证校验**:用户提交的密码先尝试连接验证,成功才保存
- **断连持续重连**:连接成功后若链路断开,以指数退避持续重连
- **发射功率降级**:当能扫描到 AP 但连接失败且原因码为信号质量类(如握手超时),逐步降低发射功率以应对天线阻抗不匹配(高 VSWR)
- **非阻塞 API**:`wifi_prov_start()` 立即返回,所有工作在后台任务中进行
- **灵活配置**:支持 menuconfig 或运行时 `wifi_prov_config_t` 配置
- **事件回调**:连接、断开、门户启动三种回调

---

## Requirements / 运行环境

**EN**
- ESP-IDF >= 5.0
- Targets: ESP32, ESP32-S2, ESP32-S3, ESP32-C3, ESP32-C6

**中文**
- ESP-IDF >= 5.0
- 支持目标:ESP32、ESP32-S2、ESP32-S3、ESP32-C3、ESP32-C6

---

## Installation / 安装

**EN** — Add the component to your project's `idf_component.yml`:

**中文** — 在工程的 `idf_component.yml` 中添加依赖:

```yaml
dependencies:
  junhui93/wifi_provisioner: "^1.2.0"
```

**EN** — Or copy the `wifi_provisioner` folder into your project's `components/` directory.

**中文** — 也可以将 `wifi_provisioner` 文件夹拷贝到工程的 `components/` 目录下。

---

## Quick Start / 快速开始

```c
#include "wifi_provisioner.h"

void app_main(void)
{
    /* EN: Initialise config with Kconfig defaults.
       中文: 用 Kconfig 默认值初始化配置。 */
    wifi_prov_config_t config = WIFI_PROV_DEFAULT_CONFIG();
    config.ap_ssid = "MyDevice-Setup";

    /* EN: Enable persistent auto-reconnect after disconnection.
       中文: 开启断连后持续自动重连。 */
    config.auto_reconnect          = true;
    config.reconnect_interval_ms   = 5000;    /* base retry interval / 基础重试间隔 */
    config.reconnect_max_delay_ms  = 60000;   /* cap back-off at 60 s / 退避上限 60 秒 */

    /* EN: TX power fallback is enabled by default. It lowers TX power
       on signal-quality-related connection failures to work around
       antenna impedance mismatch.
       中文: 发射功率降级默认开启,在信号质量类连接失败时
       逐步降低功率以应对天线阻抗不匹配。 */
    config.tx_power_fallback = true;
    config.tx_power_min      = 0;             /* 0 = 0 dBm, lowest / 最低 0 dBm */

    ESP_ERROR_CHECK(wifi_prov_start(&config));

    /* EN: wifi_prov_start() returns immediately. Use the on_connected
       callback or wifi_prov_wait_for_connection() to know when WiFi is ready.
       中文: wifi_prov_start() 立即返回,通过 on_connected 回调或
       wifi_prov_wait_for_connection() 获知 WiFi 就绪。 */

    while (1) {
        if (wifi_prov_is_connected()) {
            /* do your network work here / 在此执行业务逻辑 */
        }
        vTaskDelay(pdMS_TO_TICKS(5000));
    }
}
```

---

## Architecture / 架构设计

**EN** — The component uses a context-based architecture that differs from typical ESP-IDF examples:

| Module | Pattern | Description |
|---|---|---|
| `wifi_provisioner.c` | Background task + signal bits | `wifi_prov_start()` launches a worker task; connection-state tracking uses named event-group bits (`SIG_CONNECTED`, `SIG_STOP`) |
| `wifi_ap.c` | Builder + state struct | AP configuration is built by a separate `build_ap_config()` helper; state managed via `ap_state_t` struct |
| `wifi_sta.c` | Per-attempt context | Each connect call uses a stack-allocated `sta_conn_ctx_t` passed as the event-handler argument — no bare statics for per-attempt state |
| `nvs_store.c` | Simple wrapper | Thin NVS abstraction for credential and TX-power persistence |
| `http_server.c` | Async event-driven | HTTP server posts `WIFI_PROV_EVENT_CREDENTIALS_SET` on success |
| `dns_server.c` | UDP socket | Minimal DNS hijack for captive-portal detection |

**中文** — 组件采用基于上下文的架构,与典型 ESP-IDF 示例不同:

| 模块 | 模式 | 说明 |
|---|---|---|
| `wifi_provisioner.c` | 后台任务 + 信号位 | `wifi_prov_start()` 启动工作任务;连接状态用事件组命名位跟踪(`SIG_CONNECTED`、`SIG_STOP`) |
| `wifi_ap.c` | 构建器 + 状态结构体 | AP 配置由独立的 `build_ap_config()` 构建;状态通过 `ap_state_t` 结构体管理 |
| `wifi_sta.c` | 每次连接的上下文 | 每次连接使用栈上分配的 `sta_conn_ctx_t`,通过事件处理器参数传递——不用裸 static 变量 |
| `nvs_store.c` | 简单封装 | NVS 凭证和功率持久化的薄封装 |
| `http_server.c` | 异步事件驱动 | HTTP 服务器在验证成功后发送 `WIFI_PROV_EVENT_CREDENTIALS_SET` 事件 |
| `dns_server.c` | UDP socket | 强制门户检测的最小 DNS 劫持 |

---

## How It Works / 工作原理

**EN**
1. On `wifi_prov_start()`, the component reads the SSID and password stored in NVS.
2. If credentials exist, it tries to connect as a station (up to `max_retries` times).
3. On success, the device is online and auto-reconnect is armed.
4. On failure (or if no credentials are stored), the component starts a Soft-AP and a captive portal HTTP server.
5. The user connects to the AP, opens any URL (or `192.168.4.1`), selects a network, enters the password, and submits.
6. The component verifies the credentials by connecting; on success it saves them to NVS and switches to STA mode.

**中文**
1. 调用 `wifi_prov_start()` 后,组件从 NVS 读取已保存的 SSID 和密码。
2. 若存在凭证,尝试以 STA 模式连接(最多重试 `max_retries` 次)。
3. 连接成功后设备上线,同时启用断连自动重连。
4. 连接失败(或无凭证)时,组件启动 Soft-AP 和强制门户 HTTP 服务器。
5. 用户连接该 AP,打开任意网址(或直接访问 `192.168.4.1`),选择网络并输入密码提交。
6. 组件先尝试连接验证凭证,成功后将其保存到 NVS 并切换为 STA 模式。

---

## Persistent Auto-Reconnect / 断连持续重连

**EN** — After a successful connection, if the WiFi link drops, the component automatically attempts to reconnect:
- A single background task handles reconnection (no duplicate `esp_wifi_connect()` calls).
- **Exponential back-off**: `delay = min(interval × 2^attempts, max_delay_ms)`.
- Can be toggled at runtime with `wifi_prov_set_auto_reconnect(bool)`.
- An `on_disconnected` callback notifies the application with the disconnect reason.

**中文** — 连接成功后若 WiFi 链路断开,组件自动尝试重连:
- 单一后台任务处理重连(避免重复调用 `esp_wifi_connect()`)。
- **指数退避**:`delay = min(interval × 2^attempts, max_delay_ms)`。
- 可通过 `wifi_prov_set_auto_reconnect(bool)` 运行时开关。
- `on_disconnected` 回调通知应用层断开原因。

---

## TX Power Fallback / 发射功率降级

**EN** — When the target AP can be scanned (signal is received) but the connection fails with signal-quality-related reason codes, the cause may be **antenna impedance mismatch** (high VSWR). At high TX power, reflected energy distorts the transmitted signal. Lowering TX power reduces reflections and can restore a usable link.

**中文** — 当目标 AP 能被扫描到(能收到信号)但连接失败,且失败原因码为信号质量类时,原因可能是**天线阻抗不匹配**(高 VSWR)。高功率下反射能量会扭曲发射信号,降低功率可减少反射,恢复可用链路。

### Power Ladder / 功率阶梯

| Step / 级 | Value / 值 | Power / 功率 |
|---|---|---|
| 0 | 80 | 20.0 dBm (default / 默认) |
| 1 | 64 | 16.0 dBm |
| 2 | 48 | 12.0 dBm |
| 3 | 32 | 8.0 dBm |
| 4 | 16 | 4.0 dBm |
| 5 | 0 | 0.0 dBm (minimum / 最小) |

### Triggered Reason Codes / 触发降级的失败码

**EN** — Only signal-quality-related reasons trigger the fallback. Known errors (wrong password, cipher mismatch, AP not found) do **not** trigger it.

**中文** — 只有信号质量类失败码触发降级。已知错误(密码错误、加密不匹配、AP 找不到)**不触发**。

| Reason Code | Name | Trigger / 触发 |
|---|---|---|
| 2 | AUTH_EXPIRE | ✅ Yes |
| 4 | ASSOC_EXPIRE | ✅ Yes |
| 15 | 4WAY_HANDSHAKE_TIMEOUT | ✅ Yes |
| 23 | 802_1X_AUTH_FAILED | ✅ Yes |
| 200 | BEACON_TIMEOUT | ✅ Yes |
| 203 | AUTH_FAIL | ✅ Yes |
| 204 | HANDSHAKE_TIMEOUT / ASSOC_FAIL | ✅ Yes |
| 205 | CONNECTION_FAIL | ✅ Yes |
| 201 | NO_AP_FOUND | ❌ No (scan issue / 扫描问题) |
| 14 | MIC_FAILURE | ❌ No (wrong password / 密码错误) |
| 18-22 | CIPHER / AKMP invalid | ❌ No (config mismatch / 配置不匹配) |

### Behaviour / 行为说明

**EN**
- Each power level retries up to `max_retries` times before stepping down.
- On success at a lowered power, the working level is **saved to NVS** so subsequent boots skip the failure cycle.
- All three connection paths are covered: initial connect, portal credential verification, and persistent reconnect.
- In the reconnect task, TX power is lowered after every 3 consecutive failures with impedance-related reasons.

**中文**
- 每个功率级重试 `max_retries` 次后才降一级。
- 在低功率下连接成功时,工作功率**保存到 NVS**,下次开机直接使用,跳过失败周期。
- 三个连接路径全覆盖:开机连接、门户凭证验证、断连重连。
- 重连任务中,每 3 次连续失败且原因为阻抗类时降一级功率。

---

## API Reference / API 参考

| Function | EN Description | 中文说明 |
|---|---|---|
| `wifi_prov_init()` | Initialise NVS, netif, event loop. Called automatically by `wifi_prov_start()`. | 初始化 NVS、网络接口、事件循环,`wifi_prov_start()` 会自动调用。 |
| `wifi_prov_start(config)` | Start the provisioner. Returns immediately; work runs in a background task. | 启动配网器,立即返回,工作在后台任务中运行。 |
| `wifi_prov_stop()` | Stop and release all resources. | 停止并释放所有资源。 |
| `wifi_prov_wait_for_connection(ticks)` | Block until connected (with timeout). Returns `ESP_OK` or `ESP_ERR_TIMEOUT`. | 阻塞等待连接(带超时),返回 `ESP_OK` 或 `ESP_ERR_TIMEOUT`。 |
| `wifi_prov_is_connected()` | Check if connected with a valid IP. | 查询是否已连接并获得有效 IP。 |
| `wifi_prov_get_ip_info(ip_info)` | Get current station IP information. | 获取当前 STA 的 IP 信息。 |
| `wifi_prov_erase_credentials()` | Erase stored WiFi credentials from NVS. | 清除 NVS 中保存的 WiFi 凭证。 |
| `wifi_prov_set_auto_reconnect(enable)` | Enable or disable persistent auto-reconnect at runtime. | 运行时开启或关闭断连持续重连。 |
| `wifi_prov_get_auto_reconnect()` | Query whether auto-reconnect is enabled. | 查询重连是否已开启。 |

---

## Configuration / 配置

**EN** — All parameters can be set via **menuconfig** (`Component config → WiFi Provisioner`) or by overriding fields in `wifi_prov_config_t` at runtime.

**中文** — 所有参数可通过 **menuconfig**(`Component config → WiFi Provisioner`)或运行时覆盖 `wifi_prov_config_t` 字段设置。

### Soft-AP

| Field / 字段 | Kconfig | Default / 默认值 |
|---|---|---|
| `ap_ssid` | `CONFIG_WIFI_PROV_AP_SSID` | `"ESP32-Setup"` |
| `ap_password` | `CONFIG_WIFI_PROV_AP_PASSWORD` | `""` (open / 开放) |
| `ap_channel` | `CONFIG_WIFI_PROV_AP_CHANNEL` | `1` |
| `ap_max_connections` | `CONFIG_WIFI_PROV_AP_MAX_CONNECTIONS` | `4` |

### STA Connection / STA 连接

| Field / 字段 | Kconfig | Default / 默认值 |
|---|---|---|
| `max_retries` | `CONFIG_WIFI_PROV_STA_MAX_RETRIES` | `5` |

### Auto-Reconnect / 自动重连

| Field / 字段 | Kconfig | Default / 默认值 |
|---|---|---|
| `auto_reconnect` | `CONFIG_WIFI_PROV_AUTO_RECONNECT` | `true` |
| `reconnect_interval_ms` | `CONFIG_WIFI_PROV_RECONNECT_INTERVAL_MS` | `5000` |
| `reconnect_max_delay_ms` | `CONFIG_WIFI_PROV_RECONNECT_MAX_DELAY_MS` | `60000` |

### TX Power Fallback / 发射功率降级

| Field / 字段 | Kconfig | Default / 默认值 |
|---|---|---|
| `tx_power_fallback` | `CONFIG_WIFI_PROV_TX_POWER_FALLBACK` | `true` |
| `tx_power_min` | `CONFIG_WIFI_PROV_TX_POWER_MIN` | `0` (0.25 dBm units, 0 = 0 dBm) |

### Portal / 配网门户

| Field / 字段 | Kconfig | Default / 默认值 |
|---|---|---|
| `portal_timeout` | `CONFIG_WIFI_PROV_PORTAL_TIMEOUT` | `300` (s) |
| `http_port` | `CONFIG_WIFI_PROV_HTTP_PORT` | `80` |

---

## Callbacks / 回调函数

```c
typedef void (*wifi_prov_on_connected_cb_t)(void);
typedef void (*wifi_prov_on_disconnected_cb_t)(uint8_t reason);
typedef void (*wifi_prov_on_portal_start_cb_t)(void);
```

**EN** — Set them in `wifi_prov_config_t`:

**中文** — 在 `wifi_prov_config_t` 中设置:

```c
config.on_connected    = my_on_connected;
config.on_disconnected = my_on_disconnected;
config.on_portal_start = my_on_portal_start;
```

---

## Examples / 示例

**EN** — A complete example is available in [`examples/basic/`](examples/basic/). It demonstrates:
- Non-blocking startup
- Persistent auto-reconnect configuration
- TX power fallback configuration
- Connect/disconnect/portal callbacks
- Main loop with connection state polling

**中文** — 完整示例见 [`examples/basic/`](examples/basic/),演示:
- 非阻塞启动
- 断连持续重连配置
- 发射功率降级配置
- 连接 / 断开 / 门户启动回调
- 主循环中轮询连接状态

---

## License / 许可证

**EN** — MIT — free for commercial and closed-source use. See [LICENSE](LICENSE).

**中文** — MIT 协议——可免费用于商用及闭源项目。详见 [LICENSE](LICENSE)。

Links

To add this component to your project, run:

idf.py add-dependency "junhui93/wifi_provisioner^1.2.1"

download archive

Stats

  • Archive size
    Archive size ~ 31.29 KB
  • Downloaded in total
    Downloaded in total 0 times
  • Downloaded this version
    This version: 0 times

Badge

junhui93/wifi_provisioner version: 1.2.1
|