I’m making an api wrapper for Firebase API using C and ESP32, I’m able to pull and push data to RTDB. Currently I’ve been struggling to stream data from RTDB.
This is the current code I have that is able to stream data from my custom sse_server that I made in Python, and a random url that streams an mp3 file.
void Firebase_listen(void *pvParameters)
{
Firebase *fb = (Firebase *)pvParameters;
response_buffer_t *response = malloc(sizeof(response_buffer_t));
if (response == NULL) {
ESP_LOGE(TAG, "Failed to allocate memory for response_buffer_t");
return;
}
response->response_buffer = calloc(sizeof(char), 8192);
if (response->response_buffer == NULL) {
ESP_LOGE(TAG, "Failed to allocate memory for response buffer");
free(response);
return;
}
response->response_length = 0;
response->buffer_size = 8192;
// .url = firebase_build_request_url(fb, "cookies"),
// .url = "http://192.168.188.96:5000/stream",
// .url = "https://st01.sslstream.dlf.de/dlf/01/128/mp3/stream.mp3"
esp_http_client_config_t config = {
.url = "https://firebase_url/cookies.json",
.event_handler = chunked_stream_response_handler,
.method = HTTP_METHOD_GET,
.timeout_ms = 0,
.buffer_size = 8192,
.buffer_size_tx = 8192,
.keep_alive_enable = true,
.user_data = response,
};
esp_http_client_handle_t client = esp_http_client_init(&config);
esp_http_client_set_header(client, "Accept", "text/event-stream");
esp_http_client_set_header(client, "Cache-Control", "no-cache");
esp_http_client_set_header(client, "Connection", "keep-alive");
esp_err_t err = esp_http_client_perform(client);
if (err != ESP_OK) {
ESP_LOGE(TAG, "HTTP client SSE error: %s", esp_err_to_name(err));
}
vTaskDelay(5000 / portTICK_PERIOD_MS);
esp_http_client_cleanup(client);
free(response->response_buffer);
free(response);
}
static esp_err_t chunked_stream_response_handler(esp_http_client_event_t *evt) {
response_buffer_t *response = (response_buffer_t *)evt->user_data;
switch (evt->event_id) {
case HTTP_EVENT_REDIRECT:
ESP_LOGI(TAG, "HTTP_EVENT_REDIRECT");
case HTTP_EVENT_ERROR:
ESP_LOGI(TAG, "HTTP_EVENT_ERROR");
break;
case HTTP_EVENT_ON_CONNECTED:
ESP_LOGI(TAG, "HTTP_EVENT_ON_CONNECTED");
break;
case HTTP_EVENT_HEADER_SENT:
ESP_LOGI(TAG, "HTTP_EVENT_HEADER_SENT");
break;
case HTTP_EVENT_ON_HEADER:
ESP_LOGI(TAG, "HTTP_EVENT_ON_HEADER, key=%s, value=%s", evt->header_key, evt->header_value);
break;
case HTTP_EVENT_ON_DATA:
ESP_LOGI(TAG, "HTTP_EVENT_ON_DATA, len=%d, data=%s", evt->data_len, (char *)evt->data);
if (!esp_http_client_is_chunked_response(evt->client)) {
if (response->response_length + evt->data_len < response->buffer_size) {
memcpy(response->response_buffer + response->response_length, evt->data, evt->data_len);
response->response_length += evt->data_len;
response->response_buffer[response->response_length] = 0;
const char *line = response->response_buffer;
const char *next_line;
while ((next_line = strstr(line, "n")) != NULL) {
size_t line_length = next_line - line;
if (line_length > 0 && strncmp(line, "data:", 5) == 0) {
// Skip "data: "
const char *message = line + 5;
ESP_LOGI(TAG, "Received data: %.*s", (int)(line_length - 5), message);
}
line = next_line + 1;
}
response->response_length = 0; // Reset buffer size after processing
} else {
ESP_LOGE(TAG, "Buffer overflow, data is too large");
}
}
break;
case HTTP_EVENT_ON_FINISH:
ESP_LOGI(TAG, "HTTP_EVENT_ON_FINISH");
break;
case HTTP_EVENT_DISCONNECTED:
ESP_LOGI(TAG, "HTTP_EVENT_DISCONNECTED");
break;
}
return ESP_OK;
}
And this is the current output I get:
(7625) firebase_api: HTTP_EVENT_ON_CONNECTED
(7635) firebase_api: HTTP_EVENT_HEADER_SENT
(7665) firebase_api: HTTP_EVENT_ON_HEADER, key=Server, value=nginx
(7665) firebase_api: HTTP_EVENT_ON_HEADER, key=Date, value=Mon, 15 Jul 2024 11:23:17 GMT
(7675) firebase_api: HTTP_EVENT_ON_HEADER, key=Content-Type, value=text/event-stream; charset=utf-8
(7685) firebase_api: HTTP_EVENT_ON_HEADER, key=Connection, value=close
(7685) firebase_api: HTTP_EVENT_ON_HEADER, key=Cache-Control, value=no-cache
(7695) firebase_api: HTTP_EVENT_ON_HEADER, key=Access-Control-Allow-Origin, value=*
(7705) firebase_api: HTTP_EVENT_ON_HEADER, key=Strict-Transport-Security, value=max-age=31556926; includeSubDomains; preload
(7715) firebase_api: HTTP_EVENT_ON_DATA, len=71, data=event: put
**data: {"path":"/","data":{"cookies":30,"currentValue":30}}**
ntent-Type: text/event-stream; charset=utf-8
Connection: close
Cache-Control: no-cache
Access-Control-Allow-Origin: *
Strict-Transport-Security: max-age=31556926; includeSubDomains; preload
Z␚�qD�yd����.hWe��h�+�@␘��c��ʱ�F$�z�R�␁�����q1FoX������Y;���<���-�Z�)��J�O�&M�a�l������`�ϓq[(�AR�␋l�␗��2=��L��?b��␃6ج#ђ��␅␘�␂��/�E�hl�9_␗���9��L�␓`"�����8�G'Ug�!Y��␐_�4`��#␗���l���l��<�o����`���h␚ա��O[�x␌C�␆�␘ZPO��]��␏��P3ƙ��␟P!��G���w6]N�?�
(12785) firebase_api: HTTP_EVENT_ON_FINISH
(12785) firebase_api: HTTP_EVENT_DISCONNECTED
(17785) firebase_api: HTTP_EVENT_DISCONNECTED
if I use another URL (Not Firebase) , the event never disconnects, and just keeps streaming data, I’m allowing full access in RTDB rules, so that is not the issue
Is there a header or something that I am missing here? I’m really desperate to move on, I’ve been stuck for more than a week on this.
Thanks for your help.