domotic/components/image_downloader/image_downloader.c
2025-03-31 07:44:12 +02:00

204 lines
6.9 KiB
C

// Note: Run menuconfig to set the WiFi Credentials -> CALE Configuration
// Requirements: Needs to have an EPD Class defined. Needs PSRAM.
// This example does not use a decoded buffer hence leaves more external RAM free
// At the same time it looses the JPG_DITHER functionality in favour of render speed.
// As default only configured for parallel epapers
#include "esp_heap_caps.h"
#include "esp_log.h"
#include "esp_types.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include "esp_sleep.h"
// WiFi related
#include "esp_event.h"
#include "esp_log.h"
#include "esp_timer.h"
#include "lwip/err.h"
#include "lwip/sys.h"
// HTTP Client + time
#include "esp_http_client.h"
#include "esp_sntp.h"
#include <string.h>
#include <sys/unistd.h>
#include <sys/stat.h>
#define EXAMPLE_MAX_CHAR_SIZE 64
#include "esp_task_wdt.h"
#include <stdio.h>
#include <string.h>
#include <math.h> // round + pow
#include "image_downloader.h"
#define MOUNT_POINT "/sdcard"
static const char *TAG = "ImgDwn";
// Image URL and jpg settings. Make sure to update EPD_WIDTH/HEIGHT if using loremflickr
// Note: Only HTTP protocol supported (Check README to use SSL secure URLs) loremflickr
#define STR_HELPER(x) #x
#define STR(x) STR_HELPER(x)
#define IMGDWN_WIDTH_STR "500"
#define IMGDWN_WIDTH 620
#define IMGDWN_HEIGHT_STR "300"
#define IMGDWN_HEIGHT 460
#define IMGDWN_URL2 ("http://vps-edf71efa.vps.ovh.net:3000/render/d-solo/7BtRMrv4k/temperatures?orgId=1&var-emplacement=entree_ECS&var-emplacement=entree_reseauSol&panelId=4&width=650&height=460&scale=1&tz=Europe%2FParis/")
#define IMGDWN_URL ("http://vps-edf71efa.vps.ovh.net:3000/render/d-solo/bOcPeysGz/hauteur-cuve?orgId=1&from=now-2d&refresh=1m&panelId=4&width=" IMGDWN_WIDTH_STR "&height=" IMGDWN_HEIGHT_STR "&scale=1&tz=Europe%2FParis") // 650 460
// As default is 512 without setting buffer_size property in esp_http_client_config_t
#define HTTP_RECEIVE_BUFFER_SIZE 1938
#define DEBUG_VERBOSE false
// Buffers
uint8_t *fb; // EPD 2bpp buffer
uint8_t *source_buf; // JPG download buffer
uint8_t *decoded_image; // RAW decoded image
uint32_t buffer_pos = 0;
uint32_t time_download = 0;
uint32_t time_decomp = 0;
uint32_t time_render = 0;
uint16_t countDataEventCalls = 0;
uint32_t countDataBytes = 0;
uint32_t img_buf_pos = 0;
uint32_t dataLenTotal = 0;
uint64_t startTime = 0;
void create_file_app(uint8_t *buffer, uint32_t size)
{
ESP_LOGI(TAG, "Opening file");
//ESP_LOGI(TAG, "output buffer to spiffs: %s \n", buffer);
FILE* f = fopen(MOUNT_POINT"/hello2.png", "wb+");
if (f == NULL) {
ESP_LOGE(TAG, "Failed to open file for writing");
return;
}
for(int i=0; i<size;i++){
fprintf(f, "%c", buffer[i]);
}
fclose(f);
ESP_LOGI(TAG, "File written");
}
// Handles Htpp events and is in charge of buffering source_buf (jpg compressed image)
esp_err_t _http_event_handler_id(esp_http_client_event_t *evt)
{
switch (evt->event_id)
{
case HTTP_EVENT_ERROR:
ESP_LOGE(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:
#if DEBUG_VERBOSE
ESP_LOGI(TAG, "HTTP_EVENT_ON_HEADER, key=%s, value=%s", evt->header_key, evt->header_value);
#endif
break;
case HTTP_EVENT_ON_DATA:
++countDataEventCalls;
#if DEBUG_VERBOSE
if (countDataEventCalls%10==0) {
ESP_LOGI(TAG, "%d len:%d\n", countDataEventCalls, evt->data_len);
}
#endif
dataLenTotal += evt->data_len;
if (countDataEventCalls == 1) startTime = esp_timer_get_time();
// Append received data into source_buf
memcpy(&source_buf[img_buf_pos], evt->data, evt->data_len);
img_buf_pos += evt->data_len;
// Optional hexa dump
//ESP_LOG_BUFFER_HEX(TAG, source_buf, 100);
break;
case HTTP_EVENT_REDIRECT:
break;
case HTTP_EVENT_ON_FINISH:
// Do not draw if it's a redirect (302)
if (esp_http_client_get_status_code(evt->client) == 200) {
printf("%li bytes read from %s\nIMG_BUF size: %li\n", img_buf_pos, IMGDWN_URL, img_buf_pos);
//drawBufJpeg(source_buf, 0, 0);
create_file_app(source_buf,img_buf_pos); //function which opens and records data to spiffs file
time_download = (esp_timer_get_time()-startTime)/1000;
ESP_LOGI("www-dw", "%li ms - download", time_download);
// Refresh display
//display.update();
ESP_LOGI("total", "%li ms - total time spent\n", time_download+time_decomp+time_render);
} else {
printf("HTTP on finish got status code: %d\n", esp_http_client_get_status_code(evt->client));
}
break;
case HTTP_EVENT_DISCONNECTED:
ESP_LOGI(TAG, "HTTP_EVENT_DISCONNECTED\n");
break;
}
return ESP_OK;
}
// Handles http request
static void download(void)
{
esp_http_client_config_t config = {
.url = IMGDWN_URL,
.disable_auto_redirect = false,
.event_handler = _http_event_handler_id,
.buffer_size = HTTP_RECEIVE_BUFFER_SIZE,
.timeout_ms = 50000
};
esp_http_client_handle_t client = esp_http_client_init(&config);
#if DEBUG_VERBOSE
printf("Free heap before HTTP download: %d\n", xPortGetFreeHeapSize());
#endif
esp_err_t err = esp_http_client_perform(client);
if (err == ESP_OK)
{
ESP_LOGI(TAG, "\nIMAGE URL: %s\n\nHTTP GET Status = %d, content_length = %lli\n",
IMGDWN_URL,
esp_http_client_get_status_code(client),
esp_http_client_get_content_length(client));
}
else
{
ESP_LOGE(TAG, "\nHTTP GET request failed: %s", esp_err_to_name(err));
}
//printf("Go to sleep %d minutes\n", CONFIG_DEEPSLEEP_MINUTES_AFTER_RENDER);
esp_http_client_cleanup(client);
vTaskDelay(3600000 / portTICK_PERIOD_MS);
//deepsleep();
}
void imgdwn(void *pvParameter) {
ESP_LOGE(TAG, "beginning");
// Should be big enough to allocate the JPEG file size, width * height should suffice
source_buf = (uint8_t *)heap_caps_malloc(IMGDWN_HEIGHT * IMGDWN_WIDTH, MALLOC_CAP_SPIRAM);
if (source_buf == NULL) {
ESP_LOGE(TAG, "Initial alloc source_buf failed!");
}
printf("Free heap after buffers allocation: %d\n", xPortGetFreeHeapSize());
download();
heap_caps_free(source_buf);
printf("Free heap after buffers allocation: %d\n", xPortGetFreeHeapSize());
}