diff --git a/CYD-Klipper/platformio.ini b/CYD-Klipper/platformio.ini index e756d90..c04f71d 100644 --- a/CYD-Klipper/platformio.ini +++ b/CYD-Klipper/platformio.ini @@ -18,7 +18,8 @@ lib_deps = lvgl/lvgl@^8.3.9 https://github.com/Bodmer/TFT_eSPI.git https://github.com/PaulStoffregen/XPT2046_Touchscreen.git - bblanchon/ArduinoJson@^6.21.3 + bblanchon/ArduinoJson@^7.0.0 +monitor_filters = esp32_exception_decoder build_flags = -DLV_CONF_PATH="../../../../src/conf/lv_conf.h" -DUSER_SETUP_LOADED=1 diff --git a/CYD-Klipper/src/conf/global_config.cpp b/CYD-Klipper/src/conf/global_config.cpp index 978e1b9..7e86626 100644 --- a/CYD-Klipper/src/conf/global_config.cpp +++ b/CYD-Klipper/src/conf/global_config.cpp @@ -5,13 +5,13 @@ GLOBAL_CONFIG global_config = {0}; COLOR_DEF color_defs[] = { - {LV_PALETTE_BLUE, LV_PALETTE_RED}, - {LV_PALETTE_GREEN, LV_PALETTE_PURPLE}, - {LV_PALETTE_GREY, LV_PALETTE_CYAN}, - {LV_PALETTE_YELLOW, LV_PALETTE_PINK}, - {LV_PALETTE_ORANGE, LV_PALETTE_BLUE}, - {LV_PALETTE_RED, LV_PALETTE_GREEN}, - {LV_PALETTE_PURPLE, LV_PALETTE_GREY}, + {LV_PALETTE_BLUE, 0, LV_PALETTE_RED}, + {LV_PALETTE_LIME, -2, LV_PALETTE_PURPLE}, + {LV_PALETTE_GREY, 0, LV_PALETTE_CYAN}, + {LV_PALETTE_YELLOW, -2, LV_PALETTE_PINK}, + {LV_PALETTE_ORANGE, -2, LV_PALETTE_BLUE}, + {LV_PALETTE_RED, 0, LV_PALETTE_GREEN}, + {LV_PALETTE_PURPLE, 0, LV_PALETTE_GREY}, }; void WriteGlobalConfig() { diff --git a/CYD-Klipper/src/conf/global_config.h b/CYD-Klipper/src/conf/global_config.h index 975315a..922b14e 100644 --- a/CYD-Klipper/src/conf/global_config.h +++ b/CYD-Klipper/src/conf/global_config.h @@ -10,9 +10,12 @@ typedef struct _GLOBAL_CONFIG { union { unsigned char raw; struct { + // Internal bool screenCalibrated : 1; bool wifiConfigured : 1; bool ipConfigured : 1; + + // External bool lightMode : 1; bool invertColors : 1; bool rotateScreen : 1; @@ -40,6 +43,7 @@ typedef struct _GLOBAL_CONFIG { typedef struct _COLOR_DEF { lv_palette_t primary_color; + short primary_color_light; lv_palette_t secondary_color; } COLOR_DEF; diff --git a/CYD-Klipper/src/core/data_setup.cpp b/CYD-Klipper/src/core/data_setup.cpp index 82d32f8..49713aa 100644 --- a/CYD-Klipper/src/core/data_setup.cpp +++ b/CYD-Klipper/src/core/data_setup.cpp @@ -15,8 +15,7 @@ Printer printer = {0}; int klipper_request_consecutive_fail_count = 0; char filename_buff[512] = {0}; SemaphoreHandle_t freezeRenderThreadSemaphore, freezeRequestThreadSemaphore; -long last_data_update = 0; -const long data_update_interval = 800; +const long data_update_interval = 780; void semaphore_init(){ freezeRenderThreadSemaphore = xSemaphoreCreateMutex(); @@ -70,18 +69,19 @@ void fetch_printer_data() char buff[256] = {}; sprintf(buff, "http://%s:%d/printer/objects/query?extruder&heater_bed&toolhead&gcode_move&virtual_sdcard&print_stats&webhooks", global_config.klipperHost, global_config.klipperPort); HTTPClient client; + client.useHTTP10(true); client.begin(buff); int httpCode = client.GET(); + delay(10); if (httpCode == 200) { klipper_request_consecutive_fail_count = 0; - String payload = client.getString(); - DynamicJsonDocument doc(4096); - deserializeJson(doc, payload); + JsonDocument doc; + deserializeJson(doc, client.getStream()); auto status = doc["result"]["status"]; bool emit_state_update = false; int printer_state = printer.state; - + delay(10); unfreeze_request_thread(); frozen = false; freeze_render_thread(); @@ -212,12 +212,8 @@ void data_loop() void data_loop_background(void * param){ while (true){ - delay(100); - if (millis() - last_data_update < data_update_interval) - continue; - + delay(data_update_interval); fetch_printer_data(); - last_data_update = millis(); } } @@ -230,5 +226,5 @@ void data_setup() fetch_printer_data(); macros_query_setup(); freeze_render_thread(); - xTaskCreatePinnedToCore(data_loop_background, "data_loop_background", 5000, NULL, 1, &background_loop, 0); + xTaskCreatePinnedToCore(data_loop_background, "data_loop_background", 5000, NULL, 0, &background_loop, 0); } diff --git a/CYD-Klipper/src/core/files_query.cpp b/CYD-Klipper/src/core/files_query.cpp index d6ebb42..85acfa1 100644 --- a/CYD-Klipper/src/core/files_query.cpp +++ b/CYD-Klipper/src/core/files_query.cpp @@ -9,7 +9,7 @@ // Always has +1 entry with a null'd name FILESYSTEM_FILE* last_query = NULL; -FILESYSTEM_FILE* get_files(){ +FILESYSTEM_FILE* get_files(int limit){ freeze_request_thread(); if (last_query != NULL){ @@ -23,37 +23,76 @@ FILESYSTEM_FILE* get_files(){ free(last_query); } + Serial.printf("Heap space pre-file-parse: %d bytes\n", esp_get_free_heap_size()); std::list files; + + auto timer_request = millis(); char buff[256] = {}; sprintf(buff, "http://%s:%d/server/files/list", global_config.klipperHost, global_config.klipperPort); HTTPClient client; + client.useHTTP10(true); client.begin(buff); int httpCode = client.GET(); - int count = 0; + auto timer_parse = millis(); + if (httpCode == 200){ - String payload = client.getString(); - DynamicJsonDocument doc(60000); - auto a = deserializeJson(doc, payload); - Serial.printf("JSON PARSE: %s\n", a.c_str()); + JsonDocument doc; + auto parseResult = deserializeJson(doc, client.getStream()); + Serial.printf("Json parse: %s\n", parseResult.c_str()); auto result = doc["result"].as(); + for (auto file : result){ FILESYSTEM_FILE f = {0}; const char* path = file["path"]; + float modified = file["modified"]; + auto file_iter = files.begin(); + + while (file_iter != files.end()){ + if ((*file_iter).modified < modified) + break; + + file_iter++; + } + + // Little inefficient as it always allocates a string, even if it doesn't have to f.name = (char*)malloc(strlen(path) + 1); + if (f.name == NULL){ + Serial.println("Failed to allocate memory"); + continue; + } strcpy(f.name, path); - f.modified = file["modified"]; - files.push_back(f); - count++; + f.modified = modified; + + if (file_iter != files.end()) + files.insert(file_iter, f); + else + files.push_back(f); + + if (files.size() > limit){ + auto last_entry = files.back(); + + if (last_entry.name != NULL) + free(last_entry.name); + + files.pop_back(); + } } } - //Serial.printf("Found %d files\n", count); - files.sort([](FILESYSTEM_FILE a, FILESYSTEM_FILE b){return a.modified < b.modified;}); - files.reverse(); // TODO: Reverse is unneeded here, we can iterate backwards - size_t size = sizeof(FILESYSTEM_FILE) * (files.size() + 1); FILESYSTEM_FILE* result = (FILESYSTEM_FILE*)malloc(size); - //Serial.printf("Allocated %d bytes\n", size); + + if (result == NULL){ + Serial.println("Failed to allocate memory"); + + for (auto file : files){ + free(file.name); + } + + unfreeze_request_thread(); + return NULL; + } + last_query = result; result[files.size()].name = NULL; @@ -62,6 +101,8 @@ FILESYSTEM_FILE* get_files(){ result += 1; } + Serial.printf("Heap space post-file-parse: %d bytes\n", esp_get_free_heap_size()); + Serial.printf("Got %d files. Request took %dms, parsing took %dms\n", files.size(), timer_parse - timer_request, millis() - timer_parse); unfreeze_request_thread(); return last_query; } \ No newline at end of file diff --git a/CYD-Klipper/src/core/files_query.h b/CYD-Klipper/src/core/files_query.h index a5c6cbc..efb8b12 100644 --- a/CYD-Klipper/src/core/files_query.h +++ b/CYD-Klipper/src/core/files_query.h @@ -19,4 +19,4 @@ typedef struct _FILESYSTEM_FILE { float modified; } FILESYSTEM_FILE; -FILESYSTEM_FILE* get_files(); \ No newline at end of file +FILESYSTEM_FILE* get_files(int limit); \ No newline at end of file diff --git a/CYD-Klipper/src/core/macros_query.cpp b/CYD-Klipper/src/core/macros_query.cpp index 11ddef3..909f4fc 100644 --- a/CYD-Klipper/src/core/macros_query.cpp +++ b/CYD-Klipper/src/core/macros_query.cpp @@ -15,12 +15,12 @@ static void on_state_change(void * s, lv_msg_t * m) { String url = "http://" + String(global_config.klipperHost) + ":" + String(global_config.klipperPort) + "/printer/gcode/help"; HTTPClient client; + client.useHTTP10(true); client.begin(url.c_str()); int httpCode = client.GET(); if (httpCode == 200){ - String payload = client.getString(); - DynamicJsonDocument doc(16384); - deserializeJson(doc, payload); + JsonDocument doc; + deserializeJson(doc, client.getStream()); auto result = doc["result"].as(); for (int i = 0; i < macros_count; i++){ diff --git a/CYD-Klipper/src/core/screen_driver.cpp b/CYD-Klipper/src/core/screen_driver.cpp index ce6bfa8..e419ab5 100644 --- a/CYD-Klipper/src/core/screen_driver.cpp +++ b/CYD-Klipper/src/core/screen_driver.cpp @@ -183,7 +183,20 @@ void screen_lv_touchRead(lv_indev_drv_t *indev_driver, lv_indev_data_t *data) void set_color_scheme(){ lv_disp_t *dispp = lv_disp_get_default(); - lv_theme_t *theme = lv_theme_default_init(dispp, lv_palette_main(color_defs[global_config.color_scheme].primary_color), lv_palette_main(color_defs[global_config.color_scheme].secondary_color), !global_config.lightMode, LV_FONT_DEFAULT); + lv_color_t main_color = {0}; + COLOR_DEF color_def = color_defs[global_config.color_scheme]; + + if (color_defs[global_config.color_scheme].primary_color_light > 0){ + main_color = lv_palette_lighten(color_def.primary_color, color_def.primary_color_light); + } + else if (color_defs[global_config.color_scheme].primary_color_light < 0) { + main_color = lv_palette_darken(color_def.primary_color, color_def.primary_color_light * -1); + } + else { + main_color = lv_palette_main(color_defs[global_config.color_scheme].primary_color); + } + + lv_theme_t *theme = lv_theme_default_init(dispp, main_color, lv_palette_main(color_def.secondary_color), !global_config.lightMode, LV_FONT_DEFAULT); lv_disp_set_theme(dispp, theme); } diff --git a/CYD-Klipper/src/ui/panels/print_panel.cpp b/CYD-Klipper/src/ui/panels/print_panel.cpp index a44d9b6..e0a1cd6 100644 --- a/CYD-Klipper/src/ui/panels/print_panel.cpp +++ b/CYD-Klipper/src/ui/panels/print_panel.cpp @@ -95,13 +95,20 @@ void print_panel_init(lv_obj_t* panel){ lv_obj_set_size(list, panel_width_margin, panel_height_margin); lv_obj_align(list, LV_ALIGN_CENTER, 0, 0); - FILESYSTEM_FILE* files = get_files(); + FILESYSTEM_FILE* files = get_files(25); int count = 0; - while (files->name != NULL && count <= 20){ + while (files != NULL && files->name != NULL && count <= 20){ lv_obj_t * btn = lv_list_add_btn(list, LV_SYMBOL_FILE, files->name); lv_obj_add_event_cb(btn, btn_print_file_verify, LV_EVENT_CLICKED, (void*)files); files += 1; count++; } + + if (count <= 0){ + lv_obj_del(list); + lv_obj_t * label = lv_label_create(panel); + lv_label_set_text(label, "Failed to read files."); + lv_obj_align(label, LV_ALIGN_CENTER, 0, 0); + } } \ No newline at end of file