ESP-IDF v5.2.1 xTaskCreate 参数传递疑问

User avatar
SSSSSteven
Posts: 11
Joined: Tue Dec 05, 2023 1:53 pm
Location: Shanghai, China
Contact:

ESP-IDF v5.2.1 xTaskCreate 参数传递疑问

Postby SSSSSteven » Mon Mar 18, 2024 6:59 pm

我想用 ESP32-S3 和 ESP-IDF 实现一个 WebSocket 服务器,并且希望由服务器(ESP32-S3)主动推送数据给客户端

我的想法是监听 HTTP_SERVER_EVENT_ON_CONNECTED 事件,用 xTaskCreate 创建一个任务,在任务里用 httpd_ws_send_frame_async 来发送数据,但遇到了一个问题:httpd_ws_get_fd_info 返回的总是 HTTP_WS_CLIENT_INVALID。我在任务内把传入的 fd 打印出来,发现任务里获取到的参数和我传入的 fd 的值不一样。

代码如下:

Code: Select all

#include "stdio.h"
#include "esp_log.h"
#include "esp_http_server.h"
#include "esp_event.h"

httpd_handle_t server = NULL;
httpd_ws_frame_t wsFrame = ...; // WebSocket 帧

void websocketSend(void* pvParameters) {
    int fd = *((int *)pvParameters);
    ESP_LOGI(TAG, "Task Created, fd = %d, pointer of pvParameters = %p", fd, pvParameters);
    if(httpd_ws_get_fd_info(server, fd) == HTTPD_WS_CLIENT_WEBSOCKET) {
        httpd_ws_send_frame_async(server, fd, &wsFrame);
    }
}

void onHttpConnected(void* arg, esp_event_base_t eventBase, int32_t eventId, void* eventData) {
    int *fd = (int *)eventData;
    ESP_LOGI(TAG, "HTTP Connected, fd = %d, pointer = %p", *fd, fd);
    task = xTaskCreate(websocketSend, "websocket", 4096, (void *)fd, 5, NULL);
}

esp_err_t ws_handler(httpd_req_t *req) {
    if (req->method == HTTP_GET) {
        ESP_LOGI(TAG, "Handshake done, the new connection was opened");
        httpd_ws_send_frame_async(server, httpd_req_to_sockfd(req), &wsFrame);
        return ESP_OK;
    }
    return ESP_OK;
}

void main() {
    // Wi-Fi 连接部分省略
    
    httpd_config_t config = HTTPD_DEFAULT_CONFIG();
    httpd_start(&server, &config);
    
    httpd_uri_t websocket = {
        .uri = "/ws",
        .method = HTTP_GET,
        .handler = ws_handler,
        .user_ctx = NULL,
        .is_websocket = true,
    };

    ESP_ERROR_CHECK(httpd_register_uri_handler(server, &websocket));
    ESP_ERROR_CHECK(esp_event_handler_register(ESP_HTTP_SERVER_EVENT, HTTP_SERVER_EVENT_ON_CONNECTED, onHttpConnected, NULL));

}
输出:

Code: Select all

I (117268) TAG: HTTP Connected, fd = 57, pointer = 0x3fcb2790 // 在 event handler 中打印出的 fd 和地址
I (117278) TAG: Task Created, fd = 1070202036, pointer of pvParameters = 0x3fcb2790 // 在任务中打印出的传入的参数的值和地址,可以看到地址是一样的,但是值不一样
输出中可以看到我 xTaskCreate 中传入的参数的地址和 event handler 中 fd 的地址是同一块,但是值不一样了。

想请问一下这是为什么?我要怎么才能把 fd 正确传入任务里?

chegewara
Posts: 2375
Joined: Wed Jun 14, 2017 9:00 pm

Re: ESP-IDF v5.2.1 xTaskCreate 参数传递疑问

Postby chegewara » Tue Mar 19, 2024 2:53 pm

Code: Select all

void onHttpConnected(void* arg, esp_event_base_t eventBase, int32_t eventId, void* eventData) {
    int *fd = (int *)eventData;
    ESP_LOGI(TAG, "HTTP Connected, fd = %d, pointer = %p", *fd, fd);
    task = xTaskCreate(websocketSend, "websocket", 4096, (void *)fd, 5, NULL);
}
When this function quits "eventData" is no longer valid, because is destroyed/reused by low level API.
You can copy the value before you pass it to task.

Who is online

Users browsing this forum: No registered users and 172 guests