Hello team!
I am working on a project where the client should be informed about a data update via a push from the server. The server is an ESP32 running esp_http_server and the data push is triggered by e.g., an SPI triggered event running in a seperate task.
What's the best way to accomplish this? All websocket examples (e.g., https://github.com/espressif/esp-idf/bl ... o_server.c) assume that the relevant code to trigger an update is called from within the request handler that is associated with the websocket (in particular regarding the access to the *req pointer).
To be able do something like [1], [2], it seems like I need access to the socket fds, that are associated with a previous websocket request as well as the httpd_handle_t that was initialized when the server was started. While I can pass the latter to other freertos task, I have no idea how to obtain the FDs in a nice manner and especially how to track whether they are related to a WS socket.
[1] https://github.com/espressif/esp-idf/bl ... rver.c#L40
[2] https://github.com/espressif/esp-idf/bl ... rver.c#L56
I have found the API function httpd_get_client_list() - is this the best way to accomplish this with manual tracking in the WS request handler which of those is related to a WS?
Thank you,
Tom
Websockets: Async send within an interrupt
Re: Websockets: Async send within an interrupt
I just found out that a lot of useful stuff (e.g. sock_db and its members ws_handshake_detect) can be retrieved from the struct
struct httpd_data
defined in esp_httpd_priv.h However it seems like this data is not meant to be accessed.
Any other way?
struct httpd_data
defined in esp_httpd_priv.h However it seems like this data is not meant to be accessed.
Any other way?
Re: Websockets: Async send within an interrupt
I know this is old and likely solved for the OP, but thought I would offer help for anyone else working with websockets on the esp32.
I started down the same path with the example found at:
eps-idf/examples/protocols/http_server/ws_server
This was a good basic starting point.
A more complete example provided by espressif can be found at:
eps-idf/examples/protocols/https_server/wss_server
This example includes additional useful tools. For example registering a function for when a new client connects, when a client disconnects and provides for keep alive functionality.
Additionally it shows how to send to connected clients. Again, this example is much more complete than ws_server example. Here is the code where clients are accessed using only a handle to the server.
In this function, they do use the function httpd_get_client_list. A handle to the server is passed in and a pointer for size and client list. The size gets filled and the list as well which is the client_fds for each client.
Look at the rest of the example to see how the actual send happens after bing queued.
I started down the same path with the example found at:
eps-idf/examples/protocols/http_server/ws_server
This was a good basic starting point.
A more complete example provided by espressif can be found at:
eps-idf/examples/protocols/https_server/wss_server
This example includes additional useful tools. For example registering a function for when a new client connects, when a client disconnects and provides for keep alive functionality.
Additionally it shows how to send to connected clients. Again, this example is much more complete than ws_server example. Here is the code where clients are accessed using only a handle to the server.
Code: Untitled.c Select all
// Get all clients and send async message
static void wss_server_send_messages(httpd_handle_t* server)
{
bool send_messages = true;
// Send async message to all connected clients that use websocket protocol every 10 seconds
while (send_messages) {
vTaskDelay(10000 / portTICK_PERIOD_MS);
if (!*server) { // httpd might not have been created by now
continue;
}
size_t clients = max_clients;
int client_fds[max_clients];
if (httpd_get_client_list(*server, &clients, client_fds) == ESP_OK) {
for (size_t i=0; i < clients; ++i) {
int sock = client_fds[i];
if (httpd_ws_get_fd_info(*server, sock) == HTTPD_WS_CLIENT_WEBSOCKET) {
ESP_LOGI(TAG, "Active client (fd=%d) -> sending async message", sock);
struct async_resp_arg *resp_arg = malloc(sizeof(struct async_resp_arg));
resp_arg->hd = *server;
resp_arg->fd = sock;
if (httpd_queue_work(resp_arg->hd, send_hello, resp_arg) != ESP_OK) {
ESP_LOGE(TAG, "httpd_queue_work failed!");
send_messages = false;
break;
}
}
}
} else {
ESP_LOGE(TAG, "httpd_get_client_list failed!");
return;
}
}
}Look at the rest of the example to see how the actual send happens after bing queued.
Who is online
Users browsing this forum: Applebot, Baidu [Spider], Perplexity-User, PetalBot and 18 guests