- 音视频
- 音频处理
- 嵌入式
- 物联网
- 语音
【免费下载链接】esp-adf
Espressif Advanced Development Framework for Multimedia Applications
esp_wifi_service 是 ESP-ADF 中面向 Espressif 设备的产品级 Wi-Fi 服务组件,将凭据存储、配网交互、自动连接、网络选择与质量探测统一收敛到同一套服务接口。本文以 components/esp_wifi_service/README_CN.md 为主体,结合组件头文件与源码实现,完整讲解 Profile 存储、HTTP/BluFi 配网、HTTP API 契约、selector 智能选网与网络质量探测,并给出可直接落地的初始化示例与 Kconfig 配置速查,帮助你在量产联网产品中快速构建稳定、可维护、便于现场运维的 Wi-Fi 能力。
组件定位与核心能力
esp_wifi_service的出发点是把设备联网流程中的四类工作统一到同一服务接口:配置保存、配网交互、自动连接、网络选择与质量探测。应用使用该模块后,不需要分别维护凭据存储、SoftAP/Web 配网、BluFi 配网、断线重连和多 AP 选择逻辑,可以更快构建稳定、可维护、便于现场运维的联网产品,缩短从原型验证到量产落地的开发周期。
组件核心能力包括:
- Profile 管理:维护多组 Wi-Fi 凭据,支持新增、更新、启用、禁用、删除和清理,并通过统一 profile manager 供配网与连接选择共享
- 可替换存储介质:支持 NVS、文件系统、双分区 raw flash 或用户自定义存储适配层,并可通过加密回调保护已保存凭据
- 多通道配网:支持 HTTP SoftAP/Web UI、DNS captive portal、BluFi,以及应用自定义配网流程,所有通道都可以写入共享 profile
- 自动启动策略:服务启动时会根据是否存在已启用配置,自动进入连接选择流程或启动已配置的配网流程
- 智能选择与切换:根据用户优先级、RSSI、历史连通性、临时黑名单等因素选择更合适的 SSID/BSSID,并在断线或链路退化后重新评估
- 直接连接请求:保存或更新指定 profile 后请求 selector 立即连接该 SSID,并可选择等待 STA 获取 IP
- 网络质量探测:支持连通性、延迟和吞吐退化判断,处理"已连接 Wi-Fi 但业务不可用"的场景
- 服务化事件与 API:通过统一的服务生命周期和事件机制上报连接、配网、凭据、STA 配置和错误状态,便于应用层统一订阅和控制
从 esp_wifi_service.h 的事件枚举可以看到,服务对外发布的事件覆盖了完整的生命周期:ESP_WIFI_SERVICE_EVENT_CONNECTED/DISCONNECTED、PROV_STARTED/PROV_STOPPED、PROV_CREDENTIAL_RECEIVED、PROV_ERROR、STA_CONFIG/STA_GOT_IP/STA_LOST_IP,以及 selector 侧的SELECTOR_CANDIDATE、SELECTOR_SWITCHING、SELECTOR_SWITCH_FAILED、SELECTOR_BLACKLISTED、SELECTOR_ACCESS_FAILED、SELECTOR_LATENCY_DEGRADED、SELECTOR_THROUGHPUT_DEGRADED、SELECTOR_RSSI_LOW。应用只需在事件回调中按事件 ID 分发处理即可统一订阅和控制联网行为。
WiFi Profile 存储与凭据管理
Profile 存储支持多种存储介质,常见包括:
- NVS
- 文件系统
- 双分区原始 flash
- 用户自定义存储适配层
这些介质通过 esp_config_storage 统一抽象,profile manager 不关心底层介质差异。存储层同时支持加密回调:
- 可在写入前加密、读取后解密
- 可配置额外冗余空间(
crypto_extra_size),用于处理加密后体积增长
若不配置crypto接口,则配置信息将按明文存储。
Profile 的数据结构定义在 esp_wifi_service_profile_mgr.h:每条 profile 包含flags(其中ESP_WIFI_SERVICE_PROFILE_FLAG_ENABLED位决定该配置是否参与自动选择)、priority(0~20,数值越大越优先)、SSID(最长 32 字节)与 password(最长 64 字节)。对应的 profile manager API 包括:
| API | 作用 |
|---|---|
esp_wifi_service_profile_mgr_init()/deinit() | 创建/销毁 profile manager,max_profiles必须大于 0 |
esp_wifi_service_profile_mgr_count() | 查询已保存 profile 数量 |
esp_wifi_service_profile_mgr_foreach() | 按插入顺序遍历所有 profile |
esp_wifi_service_profile_mgr_get() | 按 SSID 查询单条 profile |
esp_wifi_service_profile_mgr_add() | 按 SSID 新增或更新(追加或替换)凭据 |
esp_wifi_service_profile_mgr_set_enabled() | 按 SSID 启用/禁用某条 profile |
esp_wifi_service_profile_mgr_set_last_working()/get_last_working() | 记录/读取最近一次成功联网的 SSID(供 selector 排序使用) |
esp_wifi_service_profile_mgr_delete() | 按 SSID 删除 profile |
esp_wifi_service_profile_mgr_clear_all() | 清空所有 profile 并复位存储 |
从 esp_wifi_service_selector.c 源码可见,"最近一次可正常访问网络"的标记会在 STA 获取到 IP(IP_EVENT_STA_GOT_IP)时由 selector 自动写入;HTTP 配网提交成功后也会通过esp_wifi_service_profile_mgr_set_last_working()更新该记录,从而让"历史连通性"成为候选排序的可靠输入。
多通道配网:HTTP、BluFi 与自定义流程
配网支持多种通道并行启用:
- 网页方式(HTTP + Web UI)
- 蓝牙方式(BluFi)
服务启动时遵循自动启动策略:如果存在至少一个已启用的配置,则启动连接流程(selector);否则启动所有已配置的配网流程。配网成功凭据写入共享 profile 后停止配网,随后服务重新启动 selector 逻辑接管连接与切换,即文档流程图中的主线闭环。
BluFi 通道
BLUFI 通道用于手机侧蓝牙配网,典型流程是:
- 手机发送网络信息
- 设备尝试连接并上报状态
- 凭据保存到共享的 profile 管理器
- 配网停止后,服务重新启动 selector 逻辑
BLUFI 凭据提交会通过 service 事件上报:
ESP_WIFI_SERVICE_EVENT_PROV_CREDENTIAL_RECEIVED:返回接收到的 WiFi 信息ESP_WIFI_SERVICE_EVENT_PROV_ERROR:应用或保存凭据失败时触发esp_wifi_service_prov_send()可向已连接的 BLUFI peer 发送自定义数据;HTTP 配网当前对下行 peer 数据返回ESP_ERR_NOT_SUPPORTED
CONFIG_WIFI_SERVICE_PROV_BLUFI_ENABLE依赖 ESP-BLUFI 协议栈(BT_BLE_BLUFI_ENABLE或BT_NIMBLE_BLUFI_ENABLE)。如果当前构建中 BLUFI 不可用,HTTP 配网仍可独立使用。配网事件的公共载荷结构见 esp_wifi_service_prov.h,其中错误类型枚举(ESP_WIFI_SERVICE_PROV_ERR_TRANSPORT、INVALID_CREDENTIAL、APPLY_FAILED、TIMEOUT、NOT_SUPPORTED等)为应用层区分失败原因提供了统一口径。
HTTP 配网整体架构
HTTP 配网会启动 SoftAP、DNS captive portal 辅助功能、HTTP server、周期性扫描缓存,以及默认或自定义 Web UI。未配置 SoftAP SSID 时,默认名称为ESP_SVC_XXXXXX,其中XXXXXX来自设备 SoftAP MAC 地址。它提供状态查询、配置管理、扫描结果和停止配网 API。
从 esp_wifi_service_prov_http.c 源码可以看到几个关键实现常量:扫描周期HTTP_SCAN_PERIOD_MS为 10 秒、STA 连接等待超时HTTP_STA_CONNECT_TIMEOUT_MS为 15 秒、JSON 请求体上限HTTP_MAX_JSON_BODY_LEN为 4096 字节;SoftAP 配置项(SSID、密码、信道、最大连接数)定义在 esp_wifi_service_prov_http.h,其中ssid为 NULL 时才使用默认ESP_SVC_XXXXXX。
两个重要的实现细节值得注意:
- 扫描归口:为避免阻塞
httpd任务并防止多个模块竞争消费扫描结果,Wi-Fi service scan agent 统一负责非阻塞 driver 扫描(接口见 esp_wifi_service_scan.h,支持请求合并、回调去注册与批量取消)。HTTP 配网会在 scan callback 中把结果拷贝到自己的 AP 记录缓存(受scan_lock互斥保护),再用于响应GET /prov/scan_result - Captive portal 友好行为默认开启:
s_http_captive_route_table注册了 iOS/Android/Windows/macOS 等系统常见的连通性检测 URL(如/hotspot-detect.html、/generate_204*、/ncsi.txt、/fwlink/*等),统一 302 重定向到入口页面,同时 SoftAP DNS 响应会指向设备自身,用户连接 SoftAP 后会自动弹出配网页
默认 HTTP API 契约
默认 API 前缀为/prov(注册路由见源码s_http_route_table),完整契约如下:
GET /prov/status
返回 HTTP 配网和 STA 状态。响应示例:
{"agent":"http","running":true,"connected":true,"ssid":"Office","bssid":"aa:bb:cc:dd:ee:ff","rssi":-45,"ip":"192.168.4.2","netmask":"255.255.255.0","gw":"192.168.4.1"}字段说明:
agent:配网通道名称,默认为httprunning:HTTP 配网通道是否正在运行connected:STA 是否已关联到 APssid、bssid、rssi:已连接时的当前 AP 信息ip、netmask、gw:当前 STA IPv4 信息
GET /prov/profiles
返回已保存的配置列表。响应示例:
{"count":2,"profiles":[{"index":0,"ssid":"Office","priority":10,"enabled":true}]}字段说明:
count:已保存配置数量profiles[]:配置数组index:配置索引,可用于后续删除操作ssid:网络名称priority:用户优先级(0~20,数值越大越优先)enabled:该配置是否参与自动选择
POST /prov/profiles
先连接提交的 AP,连接成功后添加或更新凭据。要求Content-Type: application/json。
请求字段:
ssid(必填):目标网络名称;空值会返回错误password(可选):网络密码;开放网络可为空字符串priority(可选):优先级;超出范围的值会被限制到0~20
JSON 请求示例:{"ssid":"Office","password":"12345678","priority":10}
成功响应包含当前状态:{"result":"ok","message":"Connected and profile saved.","status":{...}}
源码层面,该接口会先切换 Wi-Fi 模式(AP→APSTA),通过ESP_WIFI_SERVICE_PROV_EVT_STA_CONFIG事件让应用有机会调整wifi_config_t,再esp_wifi_set_config()+esp_wifi_connect()并阻塞等待最多 15 秒的IP_EVENT_STA_GOT_IP(esp_wifi_service_prov_http.c)。连接失败会通过PROV_ERROR(APPLY_FAILED)事件上报,成功后写入 profile 并返回200 OK。
DELETE /prov/profiles?ssid=...或DELETE /prov/profiles?index=...
按 SSID 或索引删除一个配置。参数:
ssid:按网络名称删除(与index互斥)index:按配置索引删除(与ssid互斥)
成功响应:{"result":"ok"}
POST /prov/profiles/clear
清空所有已保存配置。成功响应:{"result":"ok"}
POST /prov/profiles/enabled
启用或禁用指定配置。JSON 示例:{"ssid":"Office","enabled":true}
字段:
ssid:目标网络名称enabled:布尔值;true表示启用,false表示禁用
成功响应:{"result":"ok"}
POST /prov/credentials
当前实现未注册该 API,请使用POST /prov/profiles。
GET /prov/scan_result
返回配网通道周期性非阻塞扫描得到的缓存扫描结果。结果按 RSSI 排序,并按 SSID 去重,保留信号更强的条目。响应示例:
{"aps":[{"ssid":"Office","rssi":-45,"channel":1,"encrypted":true}]}字段说明:
aps[]:扫描结果数组ssid:网络名称rssi:信号强度,单位 dBm(越接近 0 通常越好)channel:AP 信道号encrypted:AP 认证模式是否非开放
POST /prov/stop
异步结束当前 HTTP 配网流程(源码中通过独立任务延迟 500ms 后调用esp_wifi_service_prov_stop(),避免在 httpd 任务上下文中直接停服)。成功响应:{"result":"ok"}
JSON 是通用响应格式,凭据提交当前仅接受 JSON。
自定义业务 API
除默认 API 外,也可以注册业务路由:
- 在服务启动时挂载自定义 handler
- 复用同一个 HTTP server 上下文
- 适用于设备信息、诊断、区域配置等 API
简单示例(在默认配网 server 上追加一个自定义路由):
#include "esp_http_server.h" static esp_err_t app_version_get(httpd_req_t *req) { (void)req; return httpd_resp_sendstr(req, "{\"version\":\"1.0.0\"}"); } static esp_err_t app_register_http_routes(void *httpd_handle, void *user_ctx) { (void)user_ctx; httpd_handle_t server = (httpd_handle_t)httpd_handle; httpd_uri_t version_uri = { .uri = "/app/version", .method = HTTP_GET, .handler = app_version_get, .user_ctx = NULL, }; return httpd_register_uri_handler(server, &version_uri); } esp_wifi_service_prov_http_config_t http_cfg = { .name = "http", .register_cb = app_register_http_routes, .register_ctx = app_ctx, // 可选用户上下文 };Web UI
Web UI 与 HTTP 通道配合使用,提供浏览器端交互。
默认 Web UI提供从扫描到凭据提交的完整流程:
- 扫描并选择可见网络
- 填写并提交凭据
- 查看和管理已保存配置
- 查看状态并主动停止配网
当CONFIG_WIFI_SERVICE_PROV_HTTP_DEFAULT_WEBUI_ENABLE启用且未提供esp_wifi_service_prov_web_ui_config_t.data时,会使用内置页面(页面资源编译为_binary_esp_wifi_service_prov_default_webui_html_start符号嵌入固件,源码见 esp_wifi_service_prov_default_webui.html)。
自定义 Web UI可以替换为自定义页面资源:
- 指定页面内容和挂载路径
- 指定 content type
- 保持与默认 API 契约兼容,尤其是
POST /prov/profiles和GET /prov/scan_result
简单示例(Hello World 页面调用上面的GET /app/version):
static const char hello_world_web_ui[] = "<!doctype html><html><body>" "<h1>Hello World</h1>" "<p id='ver'>loading...</p>" "<script>" "fetch('/app/version').then(r=>r.json()).then(d=>{" "document.getElementById('ver').textContent='version: '+(d.version||'unknown');" "}).catch(()=>{document.getElementById('ver').textContent='version: request failed';});" "</script>" "</body></html>"; esp_wifi_service_prov_http_config_t http_cfg = { .name = "http", .web_ui = { .data = (const uint8_t *)hello_world_web_ui, .data_len = sizeof(hello_world_web_ui) - 1, .path = "/", .content_type = "text/html", }, };自定义配网流程
如果不使用内置交互通道,也可以在应用层实现自己的配网流程:
- 收集凭据并写入 profile storage
- 按需启动或停止配网通道
- 后续由 selector 逻辑接管连接和切换
常用服务 API:
esp_wifi_service_start_provisioning()/esp_wifi_service_stop_provisioning()esp_wifi_service_is_provisioning_running()esp_wifi_service_request_connect():会保存或更新指定 profile,按需停止配网、启动 selector,并请求立即连接该 SSID。wait_sec设为0时在请求被接受后返回,设为非零值时会等待 STA 获取 IP 直到超时(超时返回ESP_ERR_TIMEOUT)- 可以通过
esp_wifi_service_profile_mgr_add()、esp_wifi_service_profile_mgr_delete()及相关 profile manager API 直接写入配置
WiFi 选择与切换(Selector)
WiFi 选择与切换用于解决设备在多网络环境中的自动连接问题。设备可能保存了家庭、办公室、热点等多组 WiFi 配置,也可能在同一 SSID 下看到多个 AP。该模块会在合适的时机重新评估可用网络,尽量让设备连接到更稳定、更符合用户偏好的 AP。
典型触发场景包括:
- 信号变差
- 当前网络访问外部服务失败
- 网络延迟持续偏高
- 实际吞吐低于预期
- 设备断开后需要重新寻找可用网络
候选排序
重评估时,系统会扫描周围 AP,并只保留能匹配已保存且已启用配置的候选项。候选网络会按业务优先级排序,而不是简单选择信号最强的 AP。排序时主要考虑:
- 用户配置的优先级,适合表达"优先连公司网络"或"优先连主路由"等偏好
- 当前 AP 信号质量,避免连接到过弱或不稳定的网络
- 最近一次可正常访问网络的配置,减少反复尝试明显不可用网络
- 临时黑名单,避开刚刚发生探测失败或质量退化的 BSSID
源码实现印证了这套排序逻辑:esp_wifi_service_selector.c 中每个候选 AP 会被计算quality(RSSI)、priority(profile 优先级)、probe_trusted(是否与 last-working SSID 一致)与blocked(是否在黑名单)四个维度,再按照select_order指定的判据顺序逐一比较。此外,wifi_selector_profile_ap_compatible()还会校验认证模式与 profile 密码是否匹配(开放网络必须对应WIFI_AUTH_OPEN,密码网络会排除 WEP 与企业级认证),保证候选真正可连接。
排序完成后,系统按当前连接状态执行不同动作:
- 如果设备尚未连接 WiFi,则直接连接最佳候选
- 如果当前连接已经是最佳候选,则保持当前连接
- 如果发现更合适的 AP,则先断开当前连接,再连接新候选
- 如果候选网络没有明显优势,则保持当前连接,避免频繁切换
应用也可以调用esp_wifi_service_request_connect()跳过一次扫描和重新评估流程。该直接连接请求仍然使用共享 profile manager 和 selector 状态,但会立即应用指定的已保存 SSID。它适用于命令行工具、配置流程,或远程管理侧已经明确目标 AP 的场景。从源码看,该路径会先校验 profile 存在且启用,然后取消在途扫描、停止健康监控,直接下发esp_wifi_set_config()+esp_wifi_connect()(必要时先断开当前 AP)。
重试行为
当没有找到可用候选网络时,selector 会按照退避表重试扫描。内置退避表为1000, 5000, 10000, 20000, 30000ms(源码s_default_reeval_scan_retry_ms)。应用可以通过selector_policy.retry.scan_retry_ms和scan_retry_num覆盖该表;配置会在服务创建时被拷贝(调用方提供的数组只需在 init 调用期间有效),每个间隔必须非 0,重试次数超过表长度后会继续使用最后一个间隔。
selector_policy.retry.max_connect_retry用于限制 selector 已选中候选网络后的连续连接失败次数。0保持原有行为,即持续重试。非 0 值表示连续失败达到该次数后停止自动重新评估(并上报SELECTOR_SWITCH_FAILED);计数会在 STA 获取 IP、显式调用esp_wifi_service_request_connect()、显式调用esp_wifi_service_request_reeval()或 selector 停止时清零。
STA 配置事件
在配网通道或 selector 调用esp_wifi_set_config()前,服务会发布ESP_WIFI_SERVICE_EVENT_STA_CONFIG,payload 为esp_wifi_service_sta_config_event_t。使用 callback 方式订阅的应用可以在同步事件分发期间修改其中的wifi_config_t。该事件适合统一设置应用侧持有的 STA 参数,例如listen_interval、PMF 策略,或其他需要同时作用于 HTTP 配网、BluFi 配网、selector 切换和直接连接请求的字段。该机制在 HTTP 通道、selector 切换路径与直接连接路径中均有调用(如wifi_selector_apply_connect()/wifi_selector_apply_direct_connect())。
网络质量探测
网络质量探测用于处理"WiFi 已连接但业务不可用"的情况。例如设备已经拿到 IP,但云端接口访问失败、网络延迟过高,或下载吞吐长期不足。此时仅依赖 WiFi 连接状态不足以判断网络是否可用,需要进一步从业务访问角度评估链路质量。
探测逻辑可以覆盖:
- 访问指定 URL,确认网络具备外部连通性
- 统计请求耗时,判断链路延迟是否持续偏高
- 读取固定大小的数据,估算实际吞吐是否满足最低要求
- 在连续失败或持续退化后触发重新选择
连通性检查用于确认当前网络是否真的可以访问目标服务。若连续访问失败,系统会认为当前 AP 虽然已经连接,但不适合作为业务网络继续使用。此时可以将当前 BSSID 临时加入黑名单,并触发新一轮候选选择。
吞吐/延迟检查用于发现"能访问但体验差"的网络。比如 AP 信号看起来还可以,但实际访问云服务很慢,或吞吐长时间低于业务要求。系统不会因为一次偶发抖动立即切换,而是在连续退化达到阈值(latency_degraded_consecutive/throughput_degraded_consecutive)后再触发处理,减少误判。当质量退化被确认后,当前 BSSID 可以被临时避开(时长由blocked_seconds控制),selector 会重新扫描并选择更合适的候选网络。
退化处理的核心目标是在稳定性和可用性之间取得平衡:
- 对轻微或偶发问题,只上报事件(
SELECTOR_ACCESS_FAILED/LATENCY_DEGRADED/THROUGHPUT_DEGRADED/RSSI_LOW),不立即切换 - 对连续失败或持续退化,触发重新扫描和候选选择
- 对刚失败的 BSSID 设置临时避让时间,避免在短时间内反复连接同一个不可用 AP
需要说明的是:探测与吞吐监视是可选功能,需在 Kconfig 中分别开启CONFIG_WIFI_SERVICE_SELECTOR_PROBE_ENABLE与CONFIG_WIFI_SERVICE_SELECTOR_THROUGHPUT_ENABLE,并配置合法的http://或https://探测 URL(源码会对 URL 做格式校验)。探测事件与触发重评估的联动关系见wifi_selector_probe_event_handler()/wifi_selector_throughput_event_handler():探测失败或退化时先把当前 BSSID 加入黑名单,再按triggers_mask决定是否请求重评估。
服务整体流程
最小初始化示例与事件订阅
以下为最小初始化示例(NVS profile store + HTTP 配网 + 自定义 selector 策略),完整演示 profile manager、HTTP 配网 agent、selector 策略与服务实例的组装顺序:
#include "esp_config_storage.h" #include "esp_config_manager.h" #include "esp_service.h" #include "esp_wifi_service_prov_http.h" #include "esp_wifi_service.h" static esp_wifi_service_t *s_wifi_service; static void on_wifi_service_event(const adf_event_t *event, void *ctx) { (void)ctx; if (event->event_id == ESP_WIFI_SERVICE_EVENT_STA_GOT_IP) { // Network is ready. } else if (event->event_id == ESP_WIFI_SERVICE_EVENT_STA_CONFIG) { const esp_wifi_service_sta_config_event_t *info = (const esp_wifi_service_sta_config_event_t *)event->payload; if (info && info->config) { info->config->sta.listen_interval = 3; } } } void wifi_service_startup(void) { static esp_config_storage_nvs_t nvs_cfg = { .nvs_namespace = "wifi_store", .key_primary = "profile_p", .key_backup = "profile_b", }; esp_config_storage_t profile_store = NULL; ESP_ERROR_CHECK(esp_config_storage_init_nvs(&nvs_cfg, &profile_store)); esp_wifi_service_profile_mgr_cfg_t profile_cfg = { .max_profiles = 8, .storage = profile_store, .crypto = NULL, .crypto_extra_size = 0, }; esp_wifi_service_profile_mgr_t profile_manager = NULL; ESP_ERROR_CHECK(esp_wifi_service_profile_mgr_init(&profile_cfg, &profile_manager)); esp_wifi_service_prov_t *http_agent = NULL; esp_wifi_service_prov_http_config_t http_cfg = { .name = "http", .port = 80, .profile_manager = profile_manager, .default_priority = 10, }; ESP_ERROR_CHECK(esp_wifi_service_prov_http_create(&http_cfg, &http_agent)); // 以下配置演示自定义 selector 策略;实际使用时可将 selector_policy 设为 NULL 使用内置默认策略。 static const uint32_t scan_retry_ms[] = {1000, 5000, 10000, 30000}; esp_wifi_service_selector_cfg_t selector_cfg = { .triggers_mask = ESP_WIFI_SERVICE_SELECTOR_TRIGGER_RSSI_LOW | ESP_WIFI_SERVICE_SELECTOR_TRIGGER_PROBE_FAILED, .select_order = { ESP_WIFI_SERVICE_SELECTOR_CRITERION_PRIORITY, ESP_WIFI_SERVICE_SELECTOR_CRITERION_QUALITY, ESP_WIFI_SERVICE_SELECTOR_CRITERION_PROBE_TRUSTED, }, .rssi = { .threshold_dbm = -75, .check_period_ms = 5000, }, .probe = { .url = "http://connectivitycheck.gstatic.com/generate_204", .check_period_min = 5, .timeout_ms = 5000, .expected_status = 204, .blocked_seconds = 15, }, .retry = { .scan_retry_ms = scan_retry_ms, .scan_retry_num = sizeof(scan_retry_ms) / sizeof(scan_retry_ms[0]), .max_connect_retry = 0, // 0 表示持续重试,直到 profile 被禁用或移除 }, }; esp_wifi_service_config_t cfg = { .name = "wifi_service", .profile_manager = profile_manager, .prov_list = &http_agent, .prov_num = 1, .selector_policy = &selector_cfg, /* 设为 NULL 时使用内置策略:低 RSSI 时重新评估网络, * 使用默认扫描重试退避,连接失败时持续重试, * 并按探测可信度、信号质量和 profile 优先级选择候选网络。 */ }; ESP_ERROR_CHECK(esp_wifi_service_create(&cfg, &s_wifi_service)); esp_service_t *base = (esp_service_t *)s_wifi_service; adf_event_subscribe_info_t sub_info = ADF_EVENT_SUBSCRIBE_INFO_DEFAULT(); sub_info.event_id = ADF_EVENT_ANY_ID; sub_info.handler = on_wifi_service_event; ESP_ERROR_CHECK(esp_service_event_subscribe(base, &sub_info)); ESP_ERROR_CHECK(esp_service_start(base)); }示例中.probe.url仅作为连通性探测 URL 的配置示例,实际部署时应替换为业务侧可达的探测地址。若不需要连通性探测,可直接将probe.url留空(url为空时探测被禁用,见 esp_wifi_service_selector.h 中url字段说明)。
关于默认 selector 策略,源码wifi_selector_cfg_fill_defaults()给出其精确内容:触发条件为ESP_WIFI_SERVICE_SELECTOR_TRIGGER_RSSI_LOW;排序判据顺序为PROBE_TRUSTED → QUALITY → PRIORITY;RSSI 阈值为 -75 dBm、检查周期 5 秒;探测超时 5 秒、期望状态码 204、失败避让 15 秒;扫描重试使用内置退避表。
MCP Tool 远程管理
同时启用CONFIG_ESP_MCP_ENABLE和CONFIG_WIFI_SERVICE_MCP_ENABLE后,组件会编译 MCP tool handler,可注册到esp_service_manager,并通过现有esp_serviceMCP server 及其 transport 对外提供远程状态查询和管理操作(工具注册与 schema 见 esp_wifi_service_mcp.h 与src/mcp/目录)。
当前提供的工具:
esp_wifi_service_get_status:返回 service 状态、STA 连接信息、IP 信息、配网状态和 profile 数量esp_wifi_service_list_profiles:列出已保存 profile,不返回密码esp_wifi_service_add_profile:按 SSID 新增或更新一个已保存 profileesp_wifi_service_set_profile_enabled:按 SSID 启用或禁用一个 profileesp_wifi_service_delete_profile:按索引或 SSID 删除一个 profileesp_wifi_service_clear_profiles:清空所有已保存 profileesp_wifi_service_prov_start:启动已配置的配网实例esp_wifi_service_prov_stop:停止正在运行的配网实例esp_wifi_service_request_reeval:请求 selector 执行一次扫描和重新评估esp_wifi_service_request_connect:保存或更新一个 profile,并请求立即连接该 SSID;参数包括ssid,以及可选的password、priority和wait_sec
MCP 工具响应不会暴露已保存密码。如果应用将 MCP transport 暴露到可信调试通道之外,应自行增加鉴权和传输安全策略。完整示例可参考 wifi_service_example,其测试脚本 test_wifi_service_mcp_uart.py 展示了通过 UART transport 调用上述工具的实际流程。
Kconfig 配置项速查
组件的编译期行为由 Kconfig 控制:
| 配置项 | 默认值 | 说明 |
|---|---|---|
CONFIG_WIFI_SERVICE_PROV_HTTP_ENABLE | y | 启用 HTTP 配网 agent 及其 SoftAP captive portal 辅助;仅使用非 HTTP 配网时关闭 |
CONFIG_WIFI_SERVICE_PROV_HTTP_DEFAULT_WEBUI_ENABLE | y | 嵌入默认 HTTP 配网 Web UI;关闭后应用必须提供web_ui.data |
CONFIG_WIFI_SERVICE_PROV_BLUFI_ENABLE | y | 启用 BLUFI 配网 agent;依赖BT_BLE_BLUFI_ENABLE或BT_NIMBLE_BLUFI_ENABLE |
CONFIG_WIFI_SERVICE_PROV_BLUFI_BLE_SMP_ENABLE | n | 在 BLUFI 配网中启用 BLE SMP(需 Bluedroid 协议栈) |
CONFIG_WIFI_SERVICE_SELECTOR_PROBE_ENABLE | n | 启用 selector HTTP 探测监视(连通性检查与延迟退化事件) |
CONFIG_WIFI_SERVICE_SELECTOR_THROUGHPUT_ENABLE | n | 启用 selector 吞吐监视(吞吐退化检查与事件) |
CONFIG_WIFI_SERVICE_MCP_ENABLE | n | 构建 Wi-Fi service MCP 工具 handler;依赖全局CONFIG_ESP_MCP_ENABLE |
注意:探测/吞吐监视默认关闭,若需要在 selector 策略中配置probe.url、throughput字段,务必先在 menuconfig 中开启对应选项,否则相关监视不会初始化(源码会打印probe disabled by configuration日志)。
组件源码结构导读
如需深入阅读实现,可按以下路径继续探索:
- 服务主入口:esp_wifi_service.c —— 服务实例创建/销毁、配网启停、
request_connect/request_reeval封装与事件转发 - 公共头文件:include/ —— 服务(
esp_wifi_service.h)、profile manager(esp_wifi_service_profile_mgr.h)、配网(esp_wifi_service_prov.h/esp_wifi_service_prov_http.h/esp_wifi_service_prov_blufi.h)、扫描(esp_wifi_service_scan.h)、selector(esp_wifi_service_selector.h)、MCP(esp_wifi_service_mcp.h) - 配网实现:src/provisioning/ —— HTTP agent(含默认 Web UI 资源)、BLUFI agent、SoftAP 启动逻辑
- selector 实现:src/selector/ —— 主状态机(
esp_wifi_service_selector.c)、黑名单(esp_wifi_service_sel_blacklist.c)、探测(esp_wifi_service_sel_probe.c)、吞吐(esp_wifi_service_sel_throughput.c) - 示例工程:wifi_service_example —— 含控制台命令实现
wifi_service_console.c与 MCP UART 测试脚本,是学习request_connect、request_reeval等 API 实际用法的首选入口 - 测试工程:test_apps/ —— 覆盖 profile 增删改查、HTTP API 契约、selector 排序与配网流程的自动化用例
通过本文的 API 契约、源码证据与初始化示例,你可以在自己的 ESP-ADF 产品中直接组装出"凭据持久化 + 双通道配网 + 智能选网 + 质量探测 + 远程管理"的完整联网方案;如需深度定制排序策略、退避节奏或探测阈值,以上源码路径即为对应的扩展点。
- 音视频
- 音频处理
- 嵌入式
- 物联网
- 语音
【免费下载链接】esp-adf
Espressif Advanced Development Framework for Multimedia Applications
相关推荐
esp-adf 的 esp_wifi_service 组件深度实战:凭据存储、双通道配网与智能网络选择切换
esp adf 的 esp_wifi_service 组件深度实战:凭据存储、双通道配网与智能网络选择切换 esp_wifi_service 是 Espress
音视频音频处理嵌入式物联网语音esp-adf Wi-Fi Service 全解析:多通道配网、Profile 管理与智能网络选择
esp adf Wi Fi Service 全解析:多通道配网、Profile 管理与智能网络选择 esp adf 的 Wi Fi Service 将设备联网流
音视频音频处理嵌入式物联网语音Fuel网络智能合约存储优化:sway-farm数据结构选择
Fuel网络智能合约存储优化:sway farm数据结构选择 在区块链应用开发中,智能合约的存储优化直接影响用户体验和运营成本。Fuel网络作为高性能公链,其S
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考