Now screen freezed on "Start Screen" until connecting to wifi is done.

This commit is contained in:
2025-11-05 19:16:26 +00:00
parent 17fd36ab4c
commit 2a18995886
30 changed files with 50365 additions and 49554 deletions

1
.gitignore vendored
View File

@@ -2,3 +2,4 @@
.vscode/c_cpp_properties.json
.vscode/launch.json
.vscode/ipch
.pio/build

Binary file not shown.

Binary file not shown.

File diff suppressed because one or more lines are too long

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -644,4 +644,5 @@
.pio/libdeps/esp32dev/lvgl/src/libs/bmp/../../../src/libs/ffmpeg/lv_ffmpeg.h \
.pio/libdeps/esp32dev/lvgl/src/libs/bmp/../../../src/widgets/lottie/lv_lottie_private.h \
.pio/libdeps/esp32dev/lvgl/src/libs/bmp/../../../src/widgets/lottie/../../lv_conf_internal.h \
.pio/libdeps/esp32dev/lvgl/src/libs/bmp/../../../src/osal/lv_os_private.h
.pio/libdeps/esp32dev/lvgl/src/libs/bmp/../../../src/osal/lv_os_private.h \
.pio/libdeps/esp32dev/lvgl/src/libs/bmp/../../core/lv_global.h

View File

@@ -644,8 +644,7 @@
.pio/libdeps/esp32dev/PicoMQTT/src/../../lvgl/src/widgets/lottie/lv_lottie_private.h \
.pio/libdeps/esp32dev/PicoMQTT/src/../../lvgl/src/widgets/lottie/../../lv_conf_internal.h \
.pio/libdeps/esp32dev/PicoMQTT/src/../../lvgl/src/osal/lv_os_private.h \
include/main.h .pio/libdeps/esp32dev/lvgl/lvgl.h \
.pio/libdeps/esp32dev/TFT_eSPI/TFT_eSPI.h \
include/main.h \
/home/ricardo/.platformio/packages/framework-arduinoespressif32/cores/esp32/Arduino.h \
/home/ricardo/.platformio/packages/framework-arduinoespressif32/cores/esp32/esp_arduino_version.h \
/home/ricardo/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/freertos/include/freertos/FreeRTOS.h \
@@ -777,6 +776,8 @@
/home/ricardo/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp_hw_support/include/soc/esp32/spiram.h \
/home/ricardo/.platformio/packages/framework-arduinoespressif32/cores/esp32/io_pin_remap.h \
/home/ricardo/.platformio/packages/framework-arduinoespressif32/cores/esp32/Arduino.h \
.pio/libdeps/esp32dev/lvgl/lvgl.h \
.pio/libdeps/esp32dev/TFT_eSPI/TFT_eSPI.h \
/home/ricardo/.platformio/packages/framework-arduinoespressif32/cores/esp32/Print.h \
/home/ricardo/.platformio/packages/framework-arduinoespressif32/libraries/SPI/src/SPI.h \
/home/ricardo/.platformio/packages/framework-arduinoespressif32/cores/esp32/esp32-hal-spi.h \

Binary file not shown.

Binary file not shown.

View File

@@ -1 +1 @@
585029fd5dea105349553f100fe484e4b45d8dde
b0b59a03059a1839dcd48ce903cafe9cc110a793

View File

@@ -664,7 +664,7 @@
#define LV_USE_LIBPNG 0
/*BMP decoder library*/
#define LV_USE_BMP 0
#define LV_USE_BMP 1
/* JPG + split JPG decoder library.
* Split JPG is a custom format optimized for embedded systems. */

View File

@@ -47,7 +47,7 @@ static void event_handler_cb_vote_session_question_name(lv_event_t *e) {
}
}
static void event_handler_cb_vote_results_obj8(lv_event_t *e) {
static void event_handler_cb_vote_results_obj9(lv_event_t *e) {
lv_event_code_t event = lv_event_get_code(e);
if (event == LV_EVENT_VALUE_CHANGED) {
lv_obj_t *ta = lv_event_get_target(e);
@@ -58,7 +58,7 @@ static void event_handler_cb_vote_results_obj8(lv_event_t *e) {
}
}
static void event_handler_cb_ibvs_processor_obj10(lv_event_t *e) {
static void event_handler_cb_ibvs_processor_obj11(lv_event_t *e) {
lv_event_code_t event = lv_event_get_code(e);
if (event == LV_EVENT_VALUE_CHANGED) {
lv_obj_t *ta = lv_event_get_target(e);
@@ -85,6 +85,14 @@ void create_screen_start() {
lv_obj_set_size(obj, LV_SIZE_CONTENT, LV_SIZE_CONTENT);
lv_image_set_src(obj, &img_logo);
}
{
lv_obj_t *obj = lv_spinner_create(parent_obj);
objects.obj0 = obj;
lv_obj_set_pos(obj, 0, 196);
lv_obj_set_size(obj, 50, 44);
lv_spinner_set_anim_params(obj, 1000, 60);
lv_obj_set_style_arc_color(obj, lv_color_hex(0xff104905), LV_PART_MAIN | LV_STATE_DEFAULT);
}
}
tick_screen_start();
@@ -125,7 +133,7 @@ void create_screen_configurations() {
}
{
lv_obj_t *obj = lv_label_create(parent_obj);
objects.obj0 = obj;
objects.obj1 = obj;
lv_obj_set_pos(obj, 0, 120);
lv_obj_set_size(obj, 320, 75);
lv_obj_set_style_text_color(obj, lv_color_hex(0xff1c52db), LV_PART_MAIN | LV_STATE_DEFAULT);
@@ -172,7 +180,7 @@ void create_screen_vote_wait() {
}
{
lv_obj_t *obj = lv_label_create(parent_obj);
objects.obj1 = obj;
objects.obj2 = obj;
lv_obj_set_pos(obj, 1, 120);
lv_obj_set_size(obj, 319, 35);
lv_label_set_long_mode(obj, LV_LABEL_LONG_SCROLL);
@@ -254,7 +262,7 @@ void create_screen_vote_session() {
objects.picture = obj;
lv_obj_set_pos(obj, 190, 85);
lv_obj_set_size(obj, 130, 150);
lv_image_set_src(obj, &img_john_does_2);
lv_image_set_src(obj, &img_john_doe_1);
}
{
// item1
@@ -267,7 +275,7 @@ void create_screen_vote_session() {
lv_obj_t *parent_obj = obj;
{
lv_obj_t *obj = lv_label_create(parent_obj);
objects.obj2 = obj;
objects.obj3 = obj;
lv_obj_set_pos(obj, 0, 0);
lv_obj_set_size(obj, LV_SIZE_CONTENT, LV_SIZE_CONTENT);
lv_obj_set_style_align(obj, LV_ALIGN_CENTER, LV_PART_MAIN | LV_STATE_DEFAULT);
@@ -286,7 +294,7 @@ void create_screen_vote_session() {
lv_obj_t *parent_obj = obj;
{
lv_obj_t *obj = lv_label_create(parent_obj);
objects.obj3 = obj;
objects.obj4 = obj;
lv_obj_set_pos(obj, 0, 0);
lv_obj_set_size(obj, LV_SIZE_CONTENT, LV_SIZE_CONTENT);
lv_obj_set_style_align(obj, LV_ALIGN_CENTER, LV_PART_MAIN | LV_STATE_DEFAULT);
@@ -305,7 +313,7 @@ void create_screen_vote_session() {
lv_obj_t *parent_obj = obj;
{
lv_obj_t *obj = lv_label_create(parent_obj);
objects.obj4 = obj;
objects.obj5 = obj;
lv_obj_set_pos(obj, 0, 0);
lv_obj_set_size(obj, LV_SIZE_CONTENT, LV_SIZE_CONTENT);
lv_obj_set_style_align(obj, LV_ALIGN_CENTER, LV_PART_MAIN | LV_STATE_DEFAULT);
@@ -324,7 +332,7 @@ void create_screen_vote_session() {
lv_obj_t *parent_obj = obj;
{
lv_obj_t *obj = lv_label_create(parent_obj);
objects.obj5 = obj;
objects.obj6 = obj;
lv_obj_set_pos(obj, 0, 0);
lv_obj_set_size(obj, LV_SIZE_CONTENT, LV_SIZE_CONTENT);
lv_obj_set_style_align(obj, LV_ALIGN_CENTER, LV_PART_MAIN | LV_STATE_DEFAULT);
@@ -343,7 +351,7 @@ void create_screen_vote_session() {
lv_obj_t *parent_obj = obj;
{
lv_obj_t *obj = lv_label_create(parent_obj);
objects.obj6 = obj;
objects.obj7 = obj;
lv_obj_set_pos(obj, 0, 0);
lv_obj_set_size(obj, LV_SIZE_CONTENT, LV_SIZE_CONTENT);
lv_obj_set_style_align(obj, LV_ALIGN_CENTER, LV_PART_MAIN | LV_STATE_DEFAULT);
@@ -389,15 +397,6 @@ void tick_screen_vote_session() {
}
{
const char *new_val = get_var_ui_item1();
const char *cur_val = lv_label_get_text(objects.obj2);
if (strcmp(new_val, cur_val) != 0) {
tick_value_change_obj = objects.obj2;
lv_label_set_text(objects.obj2, new_val);
tick_value_change_obj = NULL;
}
}
{
const char *new_val = get_var_ui_item2();
const char *cur_val = lv_label_get_text(objects.obj3);
if (strcmp(new_val, cur_val) != 0) {
tick_value_change_obj = objects.obj3;
@@ -406,7 +405,7 @@ void tick_screen_vote_session() {
}
}
{
const char *new_val = get_var_ui_item3();
const char *new_val = get_var_ui_item2();
const char *cur_val = lv_label_get_text(objects.obj4);
if (strcmp(new_val, cur_val) != 0) {
tick_value_change_obj = objects.obj4;
@@ -415,7 +414,7 @@ void tick_screen_vote_session() {
}
}
{
const char *new_val = get_var_ui_item4();
const char *new_val = get_var_ui_item3();
const char *cur_val = lv_label_get_text(objects.obj5);
if (strcmp(new_val, cur_val) != 0) {
tick_value_change_obj = objects.obj5;
@@ -424,7 +423,7 @@ void tick_screen_vote_session() {
}
}
{
const char *new_val = get_var_ui_item5();
const char *new_val = get_var_ui_item4();
const char *cur_val = lv_label_get_text(objects.obj6);
if (strcmp(new_val, cur_val) != 0) {
tick_value_change_obj = objects.obj6;
@@ -432,6 +431,15 @@ void tick_screen_vote_session() {
tick_value_change_obj = NULL;
}
}
{
const char *new_val = get_var_ui_item5();
const char *cur_val = lv_label_get_text(objects.obj7);
if (strcmp(new_val, cur_val) != 0) {
tick_value_change_obj = objects.obj7;
lv_label_set_text(objects.obj7, new_val);
tick_value_change_obj = NULL;
}
}
}
void create_screen_vote_wait_results() {
@@ -466,7 +474,7 @@ void create_screen_vote_wait_results() {
}
{
lv_obj_t *obj = lv_label_create(parent_obj);
objects.obj7 = obj;
objects.obj8 = obj;
lv_obj_set_pos(obj, 1, 120);
lv_obj_set_size(obj, 319, 35);
lv_label_set_long_mode(obj, LV_LABEL_LONG_SCROLL);
@@ -492,13 +500,13 @@ void create_screen_vote_results() {
lv_obj_t *parent_obj = obj;
{
lv_obj_t *obj = lv_textarea_create(parent_obj);
objects.obj8 = obj;
objects.obj9 = obj;
lv_obj_set_pos(obj, 10, 71);
lv_obj_set_size(obj, 300, 135);
lv_textarea_set_max_length(obj, 128);
lv_textarea_set_one_line(obj, false);
lv_textarea_set_password_mode(obj, false);
lv_obj_add_event_cb(obj, event_handler_cb_vote_results_obj8, LV_EVENT_ALL, 0);
lv_obj_add_event_cb(obj, event_handler_cb_vote_results_obj9, LV_EVENT_ALL, 0);
lv_obj_set_style_text_font(obj, &lv_font_montserrat_38, LV_PART_MAIN | LV_STATE_DEFAULT);
lv_obj_set_style_text_color(obj, lv_color_hex(0xff212121), LV_PART_MAIN | LV_STATE_DEFAULT);
lv_obj_set_style_bg_color(obj, lv_color_hex(0xffe480ba), LV_PART_MAIN | LV_STATE_DEFAULT);
@@ -526,11 +534,11 @@ void create_screen_vote_results() {
void tick_screen_vote_results() {
{
const char *new_val = get_var_ui_winner();
const char *cur_val = lv_textarea_get_text(objects.obj8);
uint32_t max_length = lv_textarea_get_max_length(objects.obj8);
const char *cur_val = lv_textarea_get_text(objects.obj9);
uint32_t max_length = lv_textarea_get_max_length(objects.obj9);
if (strncmp(new_val, cur_val, max_length) != 0) {
tick_value_change_obj = objects.obj8;
lv_textarea_set_text(objects.obj8, new_val);
tick_value_change_obj = objects.obj9;
lv_textarea_set_text(objects.obj9, new_val);
tick_value_change_obj = NULL;
}
}
@@ -578,7 +586,7 @@ void create_screen_ibvs_mode() {
}
{
lv_obj_t *obj = lv_textarea_create(parent_obj);
objects.obj9 = obj;
objects.obj10 = obj;
lv_obj_set_pos(obj, 0, 0);
lv_obj_set_size(obj, 320, 93);
lv_textarea_set_max_length(obj, 128);
@@ -628,13 +636,13 @@ void create_screen_ibvs_processor() {
}
{
lv_obj_t *obj = lv_textarea_create(parent_obj);
objects.obj10 = obj;
objects.obj11 = obj;
lv_obj_set_pos(obj, 10, 180);
lv_obj_set_size(obj, 180, 50);
lv_textarea_set_max_length(obj, 128);
lv_textarea_set_one_line(obj, false);
lv_textarea_set_password_mode(obj, false);
lv_obj_add_event_cb(obj, event_handler_cb_ibvs_processor_obj10, LV_EVENT_ALL, 0);
lv_obj_add_event_cb(obj, event_handler_cb_ibvs_processor_obj11, LV_EVENT_ALL, 0);
lv_obj_set_style_text_align(obj, LV_TEXT_ALIGN_CENTER, LV_PART_MAIN | LV_STATE_DEFAULT);
lv_obj_set_style_text_font(obj, &lv_font_montserrat_24, LV_PART_MAIN | LV_STATE_DEFAULT);
}
@@ -658,11 +666,11 @@ void create_screen_ibvs_processor() {
void tick_screen_ibvs_processor() {
{
const char *new_val = get_var_ui_ip();
const char *cur_val = lv_textarea_get_text(objects.obj10);
uint32_t max_length = lv_textarea_get_max_length(objects.obj10);
const char *cur_val = lv_textarea_get_text(objects.obj11);
uint32_t max_length = lv_textarea_get_max_length(objects.obj11);
if (strncmp(new_val, cur_val, max_length) != 0) {
tick_value_change_obj = objects.obj10;
lv_textarea_set_text(objects.obj10, new_val);
tick_value_change_obj = objects.obj11;
lv_textarea_set_text(objects.obj11, new_val);
tick_value_change_obj = NULL;
}
}

View File

@@ -18,6 +18,7 @@ typedef struct _objects_t {
lv_obj_t *ibvs_processor;
lv_obj_t *obj0;
lv_obj_t *obj1;
lv_obj_t *obj2;
lv_obj_t *orgenv_name;
lv_obj_t *name_name;
lv_obj_t *question_name;
@@ -27,7 +28,6 @@ typedef struct _objects_t {
lv_obj_t *item3;
lv_obj_t *item4;
lv_obj_t *item5;
lv_obj_t *obj2;
lv_obj_t *obj3;
lv_obj_t *obj4;
lv_obj_t *obj5;
@@ -36,6 +36,7 @@ typedef struct _objects_t {
lv_obj_t *obj8;
lv_obj_t *obj9;
lv_obj_t *obj10;
lv_obj_t *obj11;
} objects_t;
extern objects_t objects;

View File

@@ -1,6 +1,7 @@
#ifndef MAIN_H
#define MAIN_H
#include <Arduino.h>
#include <lvgl.h>
#include <TFT_eSPI.h>
#include <XPT2046_Touchscreen.h>
@@ -8,12 +9,14 @@
#include <ui.h>
#include <WiFi.h>
#include <PicoMQTT.h>
#include <SPIFFS.h>
#include "vars.h"
#include "actions.h"
#define IBVS_BADGE 1
#define IBVS_PROCESSOR 2
// Struct objects for main data
struct ShortText {
char text[20];
@@ -32,12 +35,16 @@ extern int ibvs_mode;
// Funcion declarations
void serial_config();
bool connect_wifi();
void mqtt_subs();
void mqtt_send_result(char result);
void Winner_Screen();
void badge_registration();
void log_print(lv_log_level_t level, const char * buf);
void touchscreen_read(lv_indev_t * indev, lv_indev_data_t * data);
void screen_manager(void *pvParameters);
void mqtt_manager(void *pvParameters);
void get_image();
bool load_image(const char* filename);
#endif

View File

@@ -13,6 +13,8 @@ platform = espressif32
board = esp32dev
framework = arduino
board_build.partitions = huge_app.csv
board_build.filesystem = spiffs
monitor_speed = 115200
lib_deps =
bodmer/TFT_eSPI@^2.5.43
lvgl/lvgl@9.2.2

View File

@@ -1,10 +1,10 @@
#include <Arduino.h>
#include "main.h"
#define START_SCREEN_WAIT 4 * 1000 / 5 // First number is the time in seconds
#define START_SCREEN_WAIT 4 * 200 // First number is the time in seconds
const char *ssid = "CIA";
const char *password = "passespacarola";
const char *ssid = "";
const char *password = "";
// Touchscreen pinout
#define XPT2046_IRQ 36
@@ -17,7 +17,7 @@ int x, y, z;
#define SCREEN_HEIGHT 320
// MQTT settings
const char* mqtt_server_ip = "10.164.67.154";
const char* mqtt_server_ip = "10.164.67.98";
const int mqtt_port = 1883;
//const char* mqtt_user = "badge_device";
//const char* mqtt_password = "letmein";
@@ -32,7 +32,10 @@ unsigned long last_publish_time = 0;
bool ibvs_mode_done = false;
bool screenNeedsUpdate = true;
bool configDone = false;
bool get_imageDone = true;
bool winnerDone = false;
bool vote_end = false;
bool wifi_connected = false;
char current_screen = 'A';
char winner = '0';
char Badge_ID[9];
@@ -47,6 +50,8 @@ ShortText item3 = {"Maybe", 4, 140};
ShortText item4 = {"Abstain", 4, 170};
ShortText item5 = {"Null", 4, 200};
//lv_image_dsc_t dynamic_image;
#define DRAW_BUF_SIZE (SCREEN_WIDTH * SCREEN_HEIGHT / 10 * (LV_COLOR_DEPTH / 8))
uint32_t draw_buf[DRAW_BUF_SIZE / 4];
@@ -54,33 +59,15 @@ void setup() {
Serial.begin(115200);
// Connect to WiFi network
Serial.println();
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED)
{
delay(500);
Serial.print(".");
// Initialize SPIFFS
if (!SPIFFS.begin(true)) {
Serial.println("SPIFFS Mount Failed");
return;
}
Serial.println("");
Serial.println("WiFi connected");
// Print the IP address
Serial.print("My ip: ");
Serial.println(WiFi.localIP());
set_var_ui_ip(WiFi.localIP().toString().c_str());
// Create Badge ID from MAC address
String mac = WiFi.macAddress();
mac.replace(":", ""); // Remove all colons
strcpy(Badge_ID, mac.substring(0, 8).c_str()); // Get first 8 characters, 4 bytes
Serial.println("SPIFFS Mounted Successfully");
String LVGL_Arduino = String("LVGL Library Version: ") + lv_version_major() + "." + lv_version_minor() + "." + lv_version_patch();
Serial.println(LVGL_Arduino);
// Start LVGL
lv_init();
// Register print function for debugging
@@ -107,22 +94,31 @@ void setup() {
// Function to draw the GUI (text, buttons and sliders)
ui_init();
xTaskCreate(screen_manager, "Manage_screen", 8192, NULL, 1, NULL);
xTaskCreate(mqtt_manager, "Manage_mqtt", 8192, NULL, 1, NULL);
wifi_connected = connect_wifi();
}
void loop() {
if (ibvs_mode == IBVS_BADGE) {
if (!configDone) {
Serial.println("Entering badge mode...");
serial_config();
configDone = true;
Serial.println("Entering badge mode...");
serial_config();
configDone = true;
}
if (!get_imageDone) {
get_image();
get_imageDone = true;
}
get_image();
if (winner != '0' && !winnerDone) {
Winner_Screen();
winnerDone = true;
@@ -132,18 +128,23 @@ void loop() {
if (ibvs_mode == IBVS_PROCESSOR) {
if (!configDone) {
Serial.println("Entering processor mode...");
badge_registration();
configDone = true;
}
if (millis() - last_publish_time >= 60000) {
/* if (millis() - last_publish_time >= 60000) {
message = "MQTT server ping #" + String(ping_number++);
Serial.printf("Publishing message in topic '%s': %s\r\n", topic_test.c_str(), message.c_str());
mqtt_server.publish(topic_test, message);
last_publish_time = millis();
} */
if (vote_end) {
}
}
vTaskDelay(10 / portTICK_PERIOD_MS);
vTaskDelay(8000 / portTICK_PERIOD_MS);
}
void serial_config() {
@@ -301,7 +302,6 @@ void mqtt_subs() {
}
if (ibvs_mode == IBVS_PROCESSOR) {
mqtt_server.subscribe("#", [](const char * topic, const char * payload) {
// payload might be binary, but PicoMQTT guarantees that it's zero-terminated
Serial.printf("Received message in topic '%s': %s\r\n", topic, payload);
});
}
@@ -314,7 +314,6 @@ void mqtt_send_result(char result) {
mqtt_client.publish(topic, String(result).c_str());
Serial.printf("Published \'%c\' to topic : ", result);
Serial.println(topic);
// vote_end = true;
current_screen = 'E';
screenNeedsUpdate = true;
}
@@ -377,11 +376,14 @@ void touchscreen_read(lv_indev_t * indev, lv_indev_data_t * data) {
void screen_manager(void *pvParameters) {
while (1) {
if (start_screen < START_SCREEN_WAIT) {
start_screen++;
if (start_screen < START_SCREEN_WAIT) { // If not the wanted seconds keep counting
start_screen++;
// Serial.printf("Counting: %d\r\n", start_screen); // Debug
}
else if (start_screen == START_SCREEN_WAIT) {
else if (start_screen == START_SCREEN_WAIT && !wifi_connected) {
start_screen = START_SCREEN_WAIT - 600; // If wanted seconds but no wifi wait 1 second
}
else if (start_screen == START_SCREEN_WAIT && wifi_connected) {
Serial.println("Switching to screen G"); // Debug
current_screen = 'G';
screenNeedsUpdate = true;
@@ -438,9 +440,7 @@ void screen_manager(void *pvParameters) {
void mqtt_manager(void *pvParameters) {
while (1) {
if (ibvs_mode == IBVS_BADGE) {
if (!ibvs_mode_done){
mqtt_client.begin();
mqtt_subs();
@@ -463,6 +463,141 @@ void mqtt_manager(void *pvParameters) {
else {
vTaskDelay(5 / portTICK_PERIOD_MS);
}
}
}
void badge_registration() {
}
void get_image() {
Serial.println("DEBUG: get_image() called");
if (Serial.available() > 0) {
Serial.println("DEBUG: Data available!");
String command = Serial.readStringUntil('\n');
command.trim();
Serial.print("DEBUG: Command = '");
Serial.print(command);
Serial.println("'");
if (command.startsWith("UPLOAD_IMAGE:")) {
// Extract filename and size
int colonPos = command.indexOf(':', 13);
String filename = command.substring(13, colonPos);
int fileSize = command.substring(colonPos + 1).toInt();
Serial.println("Ready to receive image");
Serial.print("Filename: ");
Serial.println(filename);
Serial.print("Size: ");
Serial.println(fileSize);
// Read data as it arrives
Serial.println("DEBUG: Starting to receive data...");
fs::File file = SPIFFS.open("/" + filename, FILE_WRITE);
if (file) {
Serial.println("DEBUG: File opened");
byte buffer[128]; // Smaller buffer
int remaining = fileSize;
int bytesReceived = 0;
unsigned long startTime = millis();
while (remaining > 0 && (millis() - startTime < 30000)) {
int available = Serial.available();
if (available > 0) {
int toRead = min(remaining, min(128, available));
int actualRead = Serial.readBytes(buffer, toRead);
file.write(buffer, actualRead);
remaining -= actualRead;
bytesReceived += actualRead;
// Print progress every 10KB
if (bytesReceived % 10000 < 128) {
Serial.print("Received: ");
Serial.print(bytesReceived);
Serial.print(" / ");
Serial.println(fileSize);
}
}
yield(); // Feed watchdog
}
file.close();
Serial.print("DEBUG: File closed. Bytes received: ");
Serial.println(bytesReceived);
if (remaining == 0) {
Serial.println("Image uploaded successfully!");
String fullPath = "/" + filename;
Serial.println("DEBUG: Calling load_image...");
load_image(fullPath.c_str());
} else {
Serial.print("ERROR: Incomplete upload. Remaining: ");
Serial.println(remaining);
}
} else {
Serial.println("Failed to open file for writing");
}
}
}
}
bool load_image(const char* filename) {
fs::File file = SPIFFS.open(filename, FILE_READ);
if (!file) {
Serial.println("Failed to open image file");
return false;
}
size_t fileSize = file.size();
Serial.print("Image file size: ");
Serial.println(fileSize);
// Allocate memory for the image data
uint8_t* imageData = (uint8_t*)malloc(fileSize);
if (!imageData) {
Serial.println("Failed to allocate memory for image");
file.close();
return false;
}
// Read the entire file into memory
file.read(imageData, fileSize);
file.close();
// Set the image source to the loaded data
// LVGL will decode the BMP automatically
lv_image_set_src(objects.picture, imageData);
Serial.println("Image loaded successfully!");
return true;
}
bool connect_wifi() {
// Connect to WiFi network
Serial.println();
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED)
{
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
// Print the IP address
Serial.print("My ip: ");
Serial.println(WiFi.localIP());
set_var_ui_ip(WiFi.localIP().toString().c_str());
// Create Badge ID from MAC address
String mac = WiFi.macAddress();
mac.replace(":", ""); // Remove all colons
strcpy(Badge_ID, mac.substring(0, 8).c_str()); // Get first 8 characters, 4 bytes
return true;
}