目录
1. 概述
该组件提供控制 Wi-Fi 配网服务的 API,可以通过 SoftAP 或低功耗蓝牙建立 协议通信 安全会话,接收和配置 Wi-Fi 凭证。通过一组 wifi_prov_mgr_ API,可以快速实现配网服务,该服务具备必要功能、代码量少且足够灵活。
2. 初始化
调用 wifi_prov_mgr_init() 可以配置和初始化配网管理器;
wifi_prov_mgr_config_t config = {
.scheme = wifi_prov_scheme_ble,
.scheme_event_handler = WIFI_PROV_SCHEME_BLE_EVENT_HANDLER_FREE_BTDM
};
ESP_ERROR_CHECK( wifi_prov_mgr_init(config) );
-
wifi_prov_mgr_config_t::scheme - 用于指定配网方案。每个方案对应一种 protocomm 支持的传输模式,因此支持三个选项:
-
wifi_prov_scheme_ble
- 使用低功耗蓝牙传输和 GATT 服务器来处理配网命令。 -
wifi_prov_scheme_softap
- 使用 Wi-Fi SoftAP 传输和 HTTP 服务器来处理配网命令。 -
wifi_prov_scheme_console
- 使用串口传输和控制台来处理配网命令。
-
-
wifi_prov_mgr_config_t::scheme_event_handler - 为方案定义的专属事件处理程序。选择适当方案后,其专属事件处理程序支持管理器自动处理特定事项。目前,该选项不适用于 SoftAP 或基于控制台的配网方案,但对于低功耗蓝牙配网方案来说非常方便。因为蓝牙需要相当多内存才能正常工作,所以配网完成后,主应用程序需要使用低功耗蓝牙或经典蓝牙时,可能需要回收配网所占的全部或部分内存。此外,未来每当配网设备重启时,都需要再次回收内存。为了便于使用
wifi_prov_scheme_ble
选项,各方案定义了专属处理程序。设备会根据所选处理程序,在反初始化配网管理器时自动释放低功耗蓝牙、经典蓝牙或蓝牙双模的内存。可用选项包括:-
WIFI_PROV_SCHEME_BLE_EVENT_HANDLER_FREE_BTDM
- 同时释放经典蓝牙和低功耗蓝牙或蓝牙双模的内存,可以在主应用程序不需要蓝牙时使用该选项。 -
WIFI_PROV_SCHEME_BLE_EVENT_HANDLER_FREE_BLE
- 只释放低功耗蓝牙的内存,可以在主应用程序需要经典蓝牙时使用该选项。 -
WIFI_PROV_SCHEME_BLE_EVENT_HANDLER_FREE_BT
- 仅释放经典蓝牙的内存,可以在主应用程序需要低功耗蓝牙时使用该选项,内存会在初始化管理器时立即释放。 -
WIFI_PROV_EVENT_HANDLER_NONE
- 不使用任何特定方案的专属处理程序。以下情况可使用该选项:不使用低功耗蓝牙配网方案,即使用 SoftAP 或控制台方案;主应用程序需要自行回收内存;主应用程序需要同时使用低功耗蓝牙和经典蓝牙。
-
static void event_handler(void* arg, esp_event_base_t event_base,
int event_id, void* event_data)
{
if (event_base == WIFI_PROV_EVENT) {
switch (event_id) {
case WIFI_PROV_START:
ESP_LOGI(TAG, "Provisioning started");
break;
case WIFI_PROV_CRED_RECV: {
wifi_sta_config_t *wifi_sta_cfg = (wifi_sta_config_t *)event_data;
ESP_LOGI(TAG, "Received Wi-Fi credentials"
"\n\tSSID : %s\n\tPassword : %s",
(const char *) wifi_sta_cfg->ssid,
(const char *) wifi_sta_cfg->password);
break;
}
case WIFI_PROV_CRED_FAIL: {
wifi_prov_sta_fail_reason_t *reason = (wifi_prov_sta_fail_reason_t *)event_data;
ESP_LOGE(TAG, "Provisioning failed!\n\tReason : %s"
"\n\tPlease reset to factory and retry provisioning",
(*reason == WIFI_PROV_STA_AUTH_ERROR) ?
"Wi-Fi station authentication failed" : "Wi-Fi access-point not found");
break;
}
case WIFI_PROV_CRED_SUCCESS:
ESP_LOGI(TAG, "Provisioning successful");
break;
case WIFI_PROV_END:
/*配网完成后,反初始化管理器。*/
wifi_prov_mgr_deinit();
break;
default:
break;
}
}
}
调用 wifi_prov_mgr_deinit() 可以随时反初始化管理器。
3. 检查配网状态
在运行时,可以调用 wifi_prov_mgr_is_provisioned() 检查设备是否配网完成,该函数会在内部检查 Wi-Fi 凭据是否存储在 NVS 中。
请注意,目前管理器并没有自己的 NVS 命名空间来存储 Wi-Fi 凭据,而是依赖 esp_wifi_
API 来设置和获取存储在默认位置的 NVS 中的凭据。
可以采用以下任一方法重置配网状态:
手动擦除 NVS 分区的配网相关部分。
主应用程序必须实现某种逻辑,以在运行时调用
esp_wifi_
API 来擦除凭据。主应用程序必须实现某种逻辑,以在不考虑配网状态的情况下,强制启动配网。
bool provisioned = false;
ESP_ERROR_CHECK( wifi_prov_mgr_is_provisioned(&provisioned) );
4. 启动配网服务
在启动配网服务时,需要指定服务名称和相应密钥,即:
使用
wifi_prov_scheme_softap
方案时,服务名称对应 Wi-Fi SoftAP 的 SSID,密钥对应密码。使用
wifi_prov_scheme_ble
方案时,服务名称对应低功耗蓝牙设备名称,无需指定密钥。
此外,由于管理器内部使用了 protocomm
,可以选择其提供的任一安全功能:
Security 1 是安全通信,该安全通信需要先握手,其中涉及 X25519 密钥交换和使用所有权证明pop完成身份验证,随后使用 AES-CTR 加密或解密后续消息。
Security 0 是纯文本通信,会直接忽略
pop
。
关于安全功能的更多详情,请参阅 统一配网。
const char *service_name = "my_device";
const char *service_key = "password";
wifi_prov_security_t security = WIFI_PROV_SECURITY_1;
const char *pop = "abcd1234";
ESP_ERROR_CHECK( wifi_prov_mgr_start_provisioning(security, pop, service_name, service_key) );
如果收到有效的 Wi-Fi AP 凭据,且设备成功连接到该 AP 并获取了 IP,配网服务会自动结束。此外,调用 wifi_prov_mgr_stop_provisioning() 可以随时停止配网服务。
注意:如果设备使用提供的凭据无法连接,则它不再接受新的凭据,但在设备重新启动前,配网服务仍然会继续运行,并向客户端传递连接失败的信息。设备重新启动后配网状态将变为已配网,因为在 NVS 中找到了凭据,但除非出现与凭据匹配的可用 AP,否则设备仍然无法使用原凭据进行连接。可以通过重置 NVS 中的凭据或强制启动配网服务来解决这个问题,详情请参阅上文 检查配网状态。
5. 等待配网完成
主应用程序通常会等待配网服务完成,然后反初始化管理器以释放资源,最后开始执行自己的逻辑。
有两种方法可以实现这一点,其中调用阻塞 wifi_prov_mgr_wait() 更为简单。
// 启动配网服务
ESP_ERROR_CHECK( wifi_prov_mgr_start_provisioning(security, pop, service_name, service_key) );
// 等待服务完成
wifi_prov_mgr_wait();
// 最后反初始化管理器
wifi_prov_mgr_deinit();
另一种方法是使用默认的事件循环处理程序捕获 WIFI_PROV_EVENT
并在事件 ID 为 WIFI_PROV_END
时调用 wifi_prov_mgr_deinit():
static void event_handler(void* arg, esp_event_base_t event_base,
int event_id, void* event_data)
{
if (event_base == WIFI_PROV_EVENT && event_id == WIFI_PROV_END) {
/* 配网完成后反初始化管理器 */
wifi_prov_mgr_deinit();
}
}
6. 用户端实现
...
7. 附加端点
...
8. 何时以及如何停止配网服务?
当设备使用 apply_config
命令设置的 Wi-Fi 凭据成功连接,配网服务将默认停止,并在响应下一个 get_status
命令后自动关闭低功耗蓝牙或 softAP。如果设备没有收到 get_status
命令,配网服务将在超时 30 秒后停止。
如果设备因 SSID 或密码不正确等原因无法使用 Wi-Fi 凭据成功连接,配网服务将继续运行,并通过 get_status
命令持续响应为断连状态,并提供断连原因。此时设备不会再接受任何新的 Wi-Fi 凭据。除非强制启动配网服务或擦除 NVS 存储,这些凭据将保留。
可以调用 wifi_prov_mgr_disable_auto_stop() 来禁用默认设置。禁用后,只有在显式调用 wifi_prov_mgr_stop_provisioning() 之后,配网服务才会停止,且该函数会安排一个任务来停止配网服务,之后立即返回。配网服务将在一定延迟后停止,并触发 WIFI_PROV_END
事件。该延迟时间可以由 wifi_prov_mgr_disable_auto_stop() 的参数指定。
如果需要在成功建立 Wi-Fi 连接后的某个时间再停止配网服务,应用程序可以采取定制行为。例如,如果应用程序需要设备连接到某个云服务并获取另一组凭证,继而通过自定义 protocomm 端点交换凭证,那么成功完成此操作后,可以在 protocomm 处理程序中调用 wifi_prov_mgr_stop_provisioning() 来停止配网服务。设定适当的延迟时间可以确保 protocomm 处理程序的响应到达客户端应用程序后,才释放传输资源。
9. 应用程序示例
关于完整实现示例,请参阅 provisioning/wifi_prov_mgr。
成功试编译烧录成功!
10. 配网工具
以下为各平台相应的配网应用程序,并附带源代码:
-
Android:
-
iOS:
-
GitHub 上的源代码: esp-idf-provisioning-ios。
Linux/MacOS/Windows: 基于 Python 的命令行工具 tools/esp_prov,可用于设备配网。
手机应用程序界面简洁,便于用户使用,而开发者可以使用命令行应用程序,便于调试。
11. 编程指南参考
(* ̄︶ ̄)创作不易!期待你们的 点赞、收藏和评论喔。
本文来源网络,免费分享知识,版权归原作者所有。如涉及作品版权问题,请联系我进行删除!