ESP-ADF wifi_service子模块esp_wifi_setting配网接口管理函数详解

ESP-ADF wifi_service子模块esp_wifi_setting配网接口管理函数详解

版本信息: v2.7-65-gcf908721

本章节分析的源码位于 /components/wifi_service/src/esp_wifi_setting.c 文件

内部数据结构

ESP-ADF的esp_wifi_setting模块内部定义了一个核心结构体,用于封装WiFi配网接口的实现:

struct esp_wifi_setting {
    wifi_setting_func           start;      /*!< 启动配网的函数指针 */
    wifi_setting_func           stop;       /*!< 停止配网的函数指针 */
    wifi_setting_teardown_func  teardown;   /*!< 清理配网资源的函数指针 */
    bool                        running;    /*!< 配网是否正在运行 */
    char                        *tag;       /*!< 配网方式的标签名称 */
    void                        *user_data; /*!< 用户自定义数据 */
    void                        *notify_handle; /*!< 通知句柄(通常是WiFi服务句柄) */
};

这个结构体设计体现了ESP-ADF中插件式架构的思想:

  1. 函数指针:通过三个函数指针(startstopteardown)实现多态行为
  2. 状态标志:使用running标志跟踪配网状态
  3. 扩展点:通过user_data指针支持自定义数据扩展
  4. 回调机制notify_handle实现配网结果的回传
  5. 调试支持:使用tag标签支持日志输出

结构体关系图

下面的图表展示了esp_wifi_setting结构与函数指针和外部组件的关系:

包含函数指针
包含函数指针
实现
实现
通过notify_handle引用
esp_wifi_setting
+wifi_setting_func start
+wifi_setting_func stop
+wifi_setting_teardown_func teardown
+bool running
+char* tag
+void* user_data
+void* notify_handle
«function»
wifi_setting_func
esp_err_t function(esp_wifi_setting_handle_t)
«function»
wifi_setting_teardown_func
esp_err_t function(esp_wifi_setting_handle_t, wifi_config_t*)
«interface»
ConfigImplementation
+start_function()
+stop_function()
+teardown_function()
«service»
wifi_service
+handle_wifi_info()

这个图表展示了esp_wifi_setting结构体如何通过函数指针关联具体配网实现,以及如何通过notify_handle与WiFi服务交互。这种设计模式实现了高度的解耦和可扩展性。

配网接口管理函数分析

1. esp_wifi_setting_create

esp_wifi_setting_create函数用于创建一个新的WiFi配置接口实例:

/**
 * @brief 创建WiFi配置接口实例
 * 
 * 该函数完成以下主要操作:
 * 1. 分配esp_wifi_setting结构体内存
 * 2. 设置配置实例的标签名
 * 3. 初始化结构体其他成员为默认值
 * 
 * @param tag 配置接口实例的标签名,用于调试输出识别
 * @return 成功返回esp_wifi_setting_handle_t句柄,失败返回NULL
 */
esp_wifi_setting_handle_t esp_wifi_setting_create(const char *tag)
{
    // 分配内存并初始化为全0
    esp_wifi_setting_handle_t new_entry = audio_calloc(1, sizeof(struct esp_wifi_setting));
    AUDIO_MEM_CHECK(TAG, new_entry, return NULL);
    
    // 设置标签名,如果未提供则使用默认标签"wifi_setting"
    if (tag) {
        new_entry->tag = audio_strdup(tag);
    } else {
        new_entry->tag = audio_strdup("wifi_setting");
    }
    
    // 检查标签名内存分配是否成功
    AUDIO_MEM_CHECK(TAG, new_entry->tag, {
        audio_free(new_entry);
        return NULL;
    })
    
    // 返回创建的实例句柄
    return new_entry;
}
函数工作原理
  1. 内存分配:使用audio_calloc分配并清零内存,确保所有字段初始值为0或NULL
  2. 标签命名:根据输入参数设置标签,支持默认值,增强可用性
  3. 错误处理:使用AUDIO_MEM_CHECK宏检查内存分配,失败时执行清理并返回NULL
  4. 隐式初始化:因使用calloc,其他字段自动初始化为零值
内存管理

函数使用ESP-ADF的内存管理API进行内存操作:

  • audio_calloc:分配并清零内存
  • audio_strdup:复制字符串并分配新内存
  • audio_free:释放分配的内存

这种方式使得内存管理更一致,并便于调试内存问题。

错误处理流程
调用esp_wifi_setting_create(tag)
分配结构体内存
内存分配成功?
返回NULL
复制tag字符串
tag复制成功?
释放结构体内存并返回NULL
返回esp_wifi_setting_handle_t实例

2. esp_wifi_setting_destroy

esp_wifi_setting_destroy函数用于销毁WiFi配置接口实例并释放相关资源:

/**
 * @brief 销毁WiFi配置接口实例
 * 
 * 该函数完成以下主要操作:
 * 1. 验证传入的句柄参数
 * 2. 释放句柄占用的内存资源
 * 
 * @param handle 要销毁的WiFi配置接口实例句柄
 * @return 
 *     - ESP_OK 成功
 *     - ESP_ERR_INVALID_ARG 参数无效
 */
esp_err_t esp_wifi_setting_destroy(esp_wifi_setting_handle_t handle)
{
    // 参数检查,确保句柄有效
    AUDIO_NULL_CHECK(TAG, handle, return ESP_ERR_INVALID_ARG);
    
    // 释放实例内存
    audio_free(handle);
    
    // 返回操作成功
    return ESP_OK;
}
函数工作原理
  1. 参数验证:使用AUDIO_NULL_CHECK宏检查句柄是否为NULL
  2. 资源释放:释放句柄占用的内存资源
  3. 返回结果:返回操作结果状态码

需要注意的是,当前实现中有一个潜在问题:函数仅释放了handle本身,但没有释放handle->tag等内部分配的内存,这可能导致内存泄漏。完整的实现应该先释放内部资源,再释放句柄本身。

销毁流程
调用esp_wifi_setting_destroy(handle)
句柄有效?
返回ESP_ERR_INVALID_ARG
释放句柄内存
返回ESP_OK

3. esp_wifi_setting_register_function

esp_wifi_setting_register_function函数用于注册WiFi配置接口的三个核心函数:

/**
 * @brief 注册WiFi配置接口函数
 * 
 * 该函数完成以下主要操作:
 * 1. 注册启动配网的函数
 * 2. 注册停止配网的函数
 * 3. 注册清理配网资源的函数
 * 
 * @param handle 配置接口实例句柄
 * @param start 启动配网的函数指针
 * @param stop 停止配网的函数指针
 * @param teardown 清理配网资源的函数指针
 * @return ESP_OK表示成功
 */
esp_err_t esp_wifi_setting_register_function(esp_wifi_setting_handle_t handle,
        wifi_setting_func start,
        wifi_setting_func stop,
        wifi_setting_teardown_func teardown)
{
    // 设置启动配网函数
    handle->start = start;
    
    // 设置停止配网函数
    handle->stop = stop;
    
    // 设置清理资源函数
    handle->teardown = teardown;
    
    // 返回操作成功
    return ESP_OK;
}
函数工作原理
  1. 函数绑定:将三个回调函数指针绑定到配置接口实例
  2. 无参数检查:当前实现没有进行参数有效性检查,这是一个潜在风险点
  3. 简化设计:函数实现简洁,体现了接口设计的轻量级特性

这个函数是配网接口的核心部分,通过它可以将具体配网方式的实现函数注册到接口框架中,实现了接口与实现的分离。

注册流程
调用esp_wifi_setting_register_function(handle, start, stop, teardown)
设置start函数指针
设置stop函数指针
设置teardown函数指针
返回ESP_OK

配网接口管理函数调用示例

以下是一个完整的配网接口创建、注册和使用流程示例:

// 定义配网实现函数
static esp_err_t my_config_start(esp_wifi_setting_handle_t handle)
{
    ESP_LOGI(TAG, "启动自定义配网");
    // 实现启动配网的逻辑...
    return ESP_OK;
}

static esp_err_t my_config_stop(esp_wifi_setting_handle_t handle)
{
    ESP_LOGI(TAG, "停止自定义配网");
    // 实现停止配网的逻辑...
    return ESP_OK;
}

static esp_err_t my_config_teardown(esp_wifi_setting_handle_t handle, wifi_config_t *info)
{
    ESP_LOGI(TAG, "清理自定义配网资源");
    // 实现清理资源的逻辑...
    return ESP_OK;
}

// 创建和注册配网接口
esp_wifi_setting_handle_t create_my_config(void)
{
    // 1. 创建配网接口实例
    esp_wifi_setting_handle_t handle = esp_wifi_setting_create("my_config");
    if (handle == NULL) {
        ESP_LOGE(TAG, "创建配网接口失败");
        return NULL;
    }
    
    // 2. 注册配网实现函数
    esp_wifi_setting_register_function(handle, 
                                      my_config_start, 
                                      my_config_stop, 
                                      my_config_teardown);
    
    // 3. 设置用户自定义数据(可选)
    my_config_t *config = audio_calloc(1, sizeof(my_config_t));
    if (config) {
        // 设置配置参数...
        esp_wifi_setting_set_data(handle, config);
    }
    
    return handle;
}

// 使用配网接口
void use_wifi_config(void)
{
    // 1. 创建WiFi服务
    periph_service_handle_t wifi_service = wifi_service_create(&wifi_cfg);
    
    // 2. 创建配网接口
    esp_wifi_setting_handle_t my_config = create_my_config();
    
    // 3. 注册配网接口到WiFi服务
    int index = 0;
    wifi_service_register_setting_handle(wifi_service, my_config, &index);
    
    // 4. 设置通知句柄
    esp_wifi_setting_register_notify_handle(my_config, wifi_service);
    
    // 5. 启动配网
    wifi_service_setting_start(wifi_service, index);
    
    // ... 其他代码 ...
    
    // 6. 销毁资源
    wifi_service_destroy(wifi_service); // 会自动清理关联的配网接口
}

时序图

下面的时序图展示了配网接口的创建、注册和使用流程:

应用程序 WiFi服务 配网接口 配网实现 esp_wifi_setting_create("my_config") 返回接口句柄handle esp_wifi_setting_register_function(handle, start, stop, teardown) 返回ESP_OK wifi_service_register_setting_handle(service, handle, &index) 返回ESP_OK esp_wifi_setting_register_notify_handle(handle, service) 返回ESP_OK wifi_service_setting_start(service, index) esp_wifi_setting_start(handle) start(handle) 返回ESP_OK 返回ESP_OK 返回ESP_OK 配网过程完成,获取到WiFi信息 esp_wifi_setting_info_notify(handle, wifi_info) wifi_service_update_sta_info(service, wifi_info) 返回ESP_OK 返回ESP_OK wifi_service_setting_stop(service, index) esp_wifi_setting_stop(handle) stop(handle) 返回ESP_OK 返回ESP_OK 返回ESP_OK wifi_service_destroy(service) esp_wifi_setting_destroy(handle) 返回ESP_OK 返回ESP_OK 应用程序 WiFi服务 配网接口 配网实现

资源管理总结

ESP-ADF的wifi_service模块中的esp_wifi_setting配网接口管理函数遵循了以下设计原则:

  1. 接口抽象:通过函数指针实现接口抽象,支持多种配网方式的统一管理
  2. 生命周期管理:提供完整的创建和销毁函数,确保资源的正确分配和释放
  3. 轻量级设计:接口设计简洁明了,减少系统负担
  4. 可扩展性:通过user_data指针支持自定义数据扩展,提高灵活性
  5. 多态行为:不同配网实现可以提供各自的函数实现,表现出多态行为

改进空间

当前实现中存在一些可改进的地方:

  1. 参数检查esp_wifi_setting_register_function函数没有检查参数有效性
  2. 内存管理esp_wifi_setting_destroy函数未释放tag等内部分配的内存
  3. 状态管理:缺少对running标志的统一管理
  4. 线程安全:接口函数未考虑并发调用的安全性

使用建议

在使用这些配网接口管理函数时,建议遵循以下最佳实践:

  1. 资源匹配:确保每个create调用都有对应的destroy调用
  2. 空指针检查:使用前检查返回的句柄是否为NULL
  3. 完整注册:确保注册所有必要的函数实现
  4. 通知机制:正确设置和使用通知句柄,确保配网结果能够回传
  5. 用户数据管理:如果设置了用户数据,确保在适当时机释放
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

omnibots

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值