From 9a6fce854cd5b4990567968a7be67c93aa25770f Mon Sep 17 00:00:00 2001 From: suchmememanyskill <38142618+suchmememanyskill@users.noreply.github.com> Date: Sun, 20 Oct 2024 22:27:31 +0200 Subject: [PATCH 01/63] In progress --- .../klipper/klipper_printer_integration.cpp | 148 +++++++++++++++++ .../klipper/klipper_printer_integration.hpp | 44 +++++ CYD-Klipper/src/core/printer_integration.cpp | 0 CYD-Klipper/src/core/printer_integration.hpp | 150 ++++++++++++++++++ CYD-Klipper/src/ui/panels/error_panel.cpp | 2 +- 5 files changed, 343 insertions(+), 1 deletion(-) create mode 100644 CYD-Klipper/src/core/klipper/klipper_printer_integration.cpp create mode 100644 CYD-Klipper/src/core/klipper/klipper_printer_integration.hpp create mode 100644 CYD-Klipper/src/core/printer_integration.cpp create mode 100644 CYD-Klipper/src/core/printer_integration.hpp diff --git a/CYD-Klipper/src/core/klipper/klipper_printer_integration.cpp b/CYD-Klipper/src/core/klipper/klipper_printer_integration.cpp new file mode 100644 index 0000000..2f38c0c --- /dev/null +++ b/CYD-Klipper/src/core/klipper/klipper_printer_integration.cpp @@ -0,0 +1,148 @@ +#include "klipper_printer_integration.hpp" +#include "../../conf/global_config.h" +#include +#include + +void configure_http_client(HTTPClient &client, String url_part, bool stream, int timeout, PRINTER_CONFIG* printer) +{ + if (stream){ + client.useHTTP10(true); + } + + if (timeout > 0){ + client.setTimeout(timeout); + client.setConnectTimeout(timeout); + } + + client.begin("http://" + String(printer->klipper_host) + ":" + String(printer->klipper_port) + url_part); + + if (printer->auth_configured) { + client.addHeader("X-Api-Key", printer->klipper_auth); + } +} + +bool KlipperPrinter::send_gcode(const char *gcode, bool wait) +{ + HTTPClient client; + configure_http_client(client, "/printer/gcode/script?script=" + urlEncode(gcode), false, wait ? 5000 : 750, printer_config); + LOG_F(("Sending gcode: %s\n", gcode)) + + try + { + client.GET(); + return true; + } + catch (...) + { + LOG_LN("Failed to send gcode"); + return false; + } +} + +bool KlipperPrinter::move_printer(const char* axis, float amount, bool relative) +{ + if (!printer_data.homed_axis || printer_data.state == PrinterStatePrinting) + return true; + + char gcode[64]; + const char* extra = (amount > 0) ? "+" : ""; + const char* start = ""; + const char* end = ""; + + if (printer_data.absolute_coords && relative) { + start = "G91\n"; + } + else if (!printer_data.absolute_coords && !relative) { + start = "G90\n"; + } + + if (printer_data.absolute_coords && relative) { + end = "\nG90"; + } + else if (!printer_data.absolute_coords && !relative) { + end = "\nG91"; + } + + sprintf(gcode, "%sG1 %s%s%.3f F6000%s", start, axis, extra, amount, end); + send_gcode(gcode); + + lock_absolute_relative_mode_swap = 2; +} + +bool KlipperPrinter::execute_feature(PrinterFeatures feature) +{ + HTTPClient client; + + switch (feature) + { + case PrinterFeatureRestart: + return send_gcode("RESTART", false); + case PrinterFeatureFirmwareRestart: + return send_gcode("FIRMWARE_RESTART", false); + case PrinterFeatureHome: + return send_gcode("G28"); + case PrinterFeatureDisableSteppers: + return send_gcode("M18"); + case PrinterFeaturePause: + return send_gcode("PAUSE"); + case PrinterFeatureResume: + return send_gcode("RESUME"); + case PrinterFeatureStop: + return send_gcode("CANCEL_PRINT"); + case PrinterFeatureEmergencyStop: + LOG_LN("Sending estop"); + send_gcode("M112", false); + configure_http_client(client, "/printer/emergency_stop", false, 5000, printer_config); + + try + { + client.GET(); + } + catch (...) + { + LOG_LN("Failed to send estop"); + } + + return true; + case PrinterFeatureExtrude: + if (printer_data.state == PrinterStatePrinting) + { + return false; + } + + if (printer_config->custom_filament_move_macros) + { + return send_gcode("FILAMENT_EXTRUDE"); + } + else + { + return send_gcode("M83") && send_gcode("G1 E25 F300"); + } + case PrinterFeatureRetract: + if (printer_data.state == PrinterStatePrinting) + { + return false; + } + + if (get_current_printer_config()->custom_filament_move_macros) + { + return send_gcode("FILAMENT_RETRACT"); + } + else + { + return send_gcode("M83") && send_gcode("G1 E-25 F300"); + } + case PrinterFeatureCooldown: + return send_gcode("M104 S0") && send_gcode("M140 S0"); + default: + LOG_F(("Unsupported printer feature %d", feature)); + return false; + } +} + +bool KlipperPrinter::connect() +{ + // Pass +} + + diff --git a/CYD-Klipper/src/core/klipper/klipper_printer_integration.hpp b/CYD-Klipper/src/core/klipper/klipper_printer_integration.hpp new file mode 100644 index 0000000..ea299ef --- /dev/null +++ b/CYD-Klipper/src/core/klipper/klipper_printer_integration.hpp @@ -0,0 +1,44 @@ +#pragma once + +#include "../printer_integration.hpp" + +class KlipperPrinter : BasePrinter +{ + private: + unsigned char lock_absolute_relative_mode_swap{}; + + public: + KlipperPrinter(int index) : BasePrinter(index) + { + supported_features = PrinterFeatureRestart + | PrinterFeatureFirmwareRestart + | PrinterFeatureHome + | PrinterFeatureDisableSteppers + | PrinterFeaturePause + | PrinterFeatureResume + | PrinterFeatureStop + | PrinterFeatureEmergencyStop + | PrinterFeatureExtrude + | PrinterFeatureRetract + | PrinterFeatureCooldown; + + supported_temperature_devices = PrinterTemperatureDeviceBed + | PrinterTemperatureDeviceNozzle1; + } + + bool move_printer(const char* axis, float amount, bool relative) = 0; + bool execute_feature(PrinterFeatures feature) = 0; + bool connect() = 0; + bool fetch(PrinterData& data) = 0; + void commit_fetch(PrinterData& data) = 0; + bool fetch_min(PrinterDataMinimal& data) = 0; + void disconnect() = 0; + bool get_macros(Macros& macros) = 0; + bool execute_macro(const char* macro) = 0; + bool get_power_devices(PowerDevices& power_devices) = 0; + bool set_power_device_state(const char* device_name, bool state) = 0; + bool get_files(Files& files) = 0; + bool start_file(const char* file) = 0; + bool set_target_temperature(PrinterTemperatureDevice device, float temperature) = 0; + bool send_gcode(const char* gcode, bool wait = true); +}; \ No newline at end of file diff --git a/CYD-Klipper/src/core/printer_integration.cpp b/CYD-Klipper/src/core/printer_integration.cpp new file mode 100644 index 0000000..e69de29 diff --git a/CYD-Klipper/src/core/printer_integration.hpp b/CYD-Klipper/src/core/printer_integration.hpp new file mode 100644 index 0000000..7bd233b --- /dev/null +++ b/CYD-Klipper/src/core/printer_integration.hpp @@ -0,0 +1,150 @@ +#pragma once +#include "lvgl.h" +#include "../conf/global_config.h" + +#define BIT(x) 1 << x + +enum PrinterFeatures { + PrinterFeatureRestart = BIT(0), + PrinterFeatureFirmwareRestart = BIT(1), + PrinterFeatureHome = BIT(2), + PrinterFeatureDisableSteppers = BIT(3), + PrinterFeaturePause = BIT(4), + PrinterFeatureResume = BIT(5), + PrinterFeatureStop = BIT(6), + PrinterFeatureEmergencyStop = BIT(7), + PrinterFeatureExtrude = BIT(8), + PrinterFeatureRetract = BIT(9), + PrinterFeatureLoadFilament = BIT(10), + PrinterFeatureUnloadFilament = BIT(11), + PrinterFeatureCooldown = BIT(12), +}; + +inline PrinterFeatures operator|(PrinterFeatures a, PrinterFeatures b) +{ + return static_cast(static_cast(a) | static_cast(b)); +} + +enum PrinterTemperatureDevice +{ + PrinterTemperatureDeviceBed = BIT(0), + PrinterTemperatureDeviceNozzle1 = BIT(1), + PrinterTemperatureDeviceNozzle2 = BIT(2), + PrinterTemperatureDeviceNozzle3 = BIT(3), + PrinterTemperatureDeviceNozzle4 = BIT(4), + PrinterTemperatureDeviceNozzle5 = BIT(5), + PrinterTemperatureDeviceNozzle6 = BIT(6), + PrinterTemperatureDeviceNozzle7 = BIT(7), + PrinterTemperatureDeviceNozzle8 = BIT(8), + PrinterTemperatureDeviceChamber = BIT(9), +}; + +inline PrinterTemperatureDevice operator|(PrinterTemperatureDevice a, PrinterTemperatureDevice b) +{ + return static_cast(static_cast(a) | static_cast(b)); +} + +enum PrinterState { + PrinterStateOffline = 0, + PrinterStateError = 1, + PrinterStateIdle = 2, + PrinterStatePrinting = 3, + PrinterStatePaused = 4, +}; + +typedef struct _PrinterData { + union { + struct { + bool can_extrude : 1; + bool homed_axis : 1; + bool absolute_coords : 1; + }; + unsigned char rawState; + }; + PrinterState state; + char* state_message; + float temperatures[10]; + float target_temperatures[10]; + PrinterTemperatureDevice AvailableDevices; + float position[3]; + float elapsed_time_s; + float printed_time_s; + float remaining_time_s; + float filament_used_mm; + char* print_filename; + float print_progress; // 0 -> 1 + float fan_speed; // 0 -> 1 + float speed_mult; + float extrude_mult; + int total_layers; + int current_layer; + float pressure_advance; + float smooth_time; + int feedrate_mm_per_s; +} PrinterData; + +typedef struct _PrinterDataMinimal { + unsigned char state; + float print_progress; // 0 -> 1 + unsigned int power_devices; +} PrinterDataMinimal; + +typedef struct { + const char** macros; + unsigned int count; +} Macros; + +typedef struct { + const char** power_devices; + const bool* power_states; + unsigned int count; +} PowerDevices; + +typedef struct { + const char** available_files; + unsigned int count; +} Files; + +typedef struct { + lv_event_ct_b set_label; + lv_event_ct_b open_panel; +} PrinterUiPanel; + +class BasePrinter +{ + protected: + unsigned char config_index{}; + + public: + PrinterData printer_data{}; + PrinterFeatures supported_features{}; + PrinterTemperatureDevice supported_temperature_devices{}; + PrinterUiPanel* custom_menus{}; + PRINTER_CONFIG* printer_config{}; + GLOBAL_CONFIG* global_config{}; + unsigned char custom_menus_count{}; + + virtual bool move_printer(const char* axis, float amount, bool relative) = 0; + virtual bool execute_feature(PrinterFeatures feature) = 0; + virtual bool connect() = 0; + virtual bool fetch(PrinterData& data) = 0; + virtual void commit_fetch(PrinterData& data) = 0; + virtual bool fetch_min(PrinterDataMinimal& data) = 0; + virtual void disconnect() = 0; + virtual bool get_macros(Macros& macros) = 0; + virtual bool execute_macro(const char* macro) = 0; + virtual bool get_power_devices(PowerDevices& power_devices) = 0; + virtual bool set_power_device_state(const char* device_name, bool state) = 0; + virtual bool get_files(Files& files) = 0; + virtual bool start_file(const char* file) = 0; + virtual bool set_target_temperature(PrinterTemperatureDevice device, float temperature) = 0; + + BasePrinter(unsigned char index) { + config_index = index; + // TODO: Fetch printer config and global config + } +}; + +BasePrinter* get_current_printer(); +BasePrinter* get_printer(int idx); +void initialize_printer(); \ No newline at end of file diff --git a/CYD-Klipper/src/ui/panels/error_panel.cpp b/CYD-Klipper/src/ui/panels/error_panel.cpp index 10a28ba..d24e0c5 100644 --- a/CYD-Klipper/src/ui/panels/error_panel.cpp +++ b/CYD-Klipper/src/ui/panels/error_panel.cpp @@ -28,7 +28,7 @@ void error_panel_init(lv_obj_t* panel) lv_label_set_text(label, printer.state_message); lv_obj_set_width(label, CYD_SCREEN_PANEL_WIDTH_PX - CYD_SCREEN_GAP_PX * 2); lv_label_set_long_mode(label, LV_LABEL_LONG_WRAP); - + lv_obj_t * button_row = lv_create_empty_panel(panel); lv_obj_set_size(button_row, CYD_SCREEN_PANEL_WIDTH_PX - CYD_SCREEN_GAP_PX * 2, CYD_SCREEN_MIN_BUTTON_HEIGHT_PX); lv_layout_flex_row(button_row); From 22fc25ccc77a6a188bc81aea4ee9e8b18533202d Mon Sep 17 00:00:00 2001 From: suchmememanyskill <38142618+suchmememanyskill@users.noreply.github.com> Date: Mon, 21 Oct 2024 23:08:53 +0200 Subject: [PATCH 02/63] Port more --- CYD-Klipper/.vscode/settings.json | 3 +- .../klipper/klipper_printer_integration.cpp | 334 +++++++++++++++++- .../klipper/klipper_printer_integration.hpp | 35 +- CYD-Klipper/src/core/printer_integration.cpp | 96 +++++ CYD-Klipper/src/core/printer_integration.hpp | 46 ++- 5 files changed, 477 insertions(+), 37 deletions(-) diff --git a/CYD-Klipper/.vscode/settings.json b/CYD-Klipper/.vscode/settings.json index 8be69ef..55d6dcc 100644 --- a/CYD-Klipper/.vscode/settings.json +++ b/CYD-Klipper/.vscode/settings.json @@ -13,7 +13,8 @@ "cstddef": "cpp", "functional": "cpp", "*.tcc": "cpp", - "cmath": "cpp" + "cmath": "cpp", + "system_error": "cpp" }, "cmake.configureOnOpen": false } \ No newline at end of file diff --git a/CYD-Klipper/src/core/klipper/klipper_printer_integration.cpp b/CYD-Klipper/src/core/klipper/klipper_printer_integration.cpp index 2f38c0c..7271847 100644 --- a/CYD-Klipper/src/core/klipper/klipper_printer_integration.cpp +++ b/CYD-Klipper/src/core/klipper/klipper_printer_integration.cpp @@ -2,8 +2,9 @@ #include "../../conf/global_config.h" #include #include +#include -void configure_http_client(HTTPClient &client, String url_part, bool stream, int timeout, PRINTER_CONFIG* printer) +void KlipperPrinter::configure_http_client(HTTPClient &client, String url_part, bool stream, int timeout) { if (stream){ client.useHTTP10(true); @@ -14,17 +15,36 @@ void configure_http_client(HTTPClient &client, String url_part, bool stream, int client.setConnectTimeout(timeout); } - client.begin("http://" + String(printer->klipper_host) + ":" + String(printer->klipper_port) + url_part); + client.begin("http://" + String(printer_config->klipper_host) + ":" + String(printer_config->klipper_port) + url_part); - if (printer->auth_configured) { - client.addHeader("X-Api-Key", printer->klipper_auth); + if (printer_config->auth_configured) { + client.addHeader("X-Api-Key", printer_config->klipper_auth); } } +int KlipperPrinter::get_slicer_time_estimate_s() +{ + if (printer_data.state != PrinterStatePrinting && printer_data.state != PrinterStatePaused) + return 0; + + HTTPClient client; + configure_http_client(client, "/server/files/metadata?filename=" + urlEncode(printer_data.print_filename), true, 5000); + int httpCode = client.GET(); + + if (httpCode != 200) + return 0; + + JsonDocument doc; + deserializeJson(doc, client.getStream()); + int time_estimate_s = doc["result"]["estimated_time"]; + LOG_F(("Got slicer time estimate: %ds\n", time_estimate_s)) + return time_estimate_s; +} + bool KlipperPrinter::send_gcode(const char *gcode, bool wait) { HTTPClient client; - configure_http_client(client, "/printer/gcode/script?script=" + urlEncode(gcode), false, wait ? 5000 : 750, printer_config); + configure_http_client(client, "/printer/gcode/script?script=" + urlEncode(gcode), false, wait ? 5000 : 750); LOG_F(("Sending gcode: %s\n", gcode)) try @@ -92,7 +112,7 @@ bool KlipperPrinter::execute_feature(PrinterFeatures feature) case PrinterFeatureEmergencyStop: LOG_LN("Sending estop"); send_gcode("M112", false); - configure_http_client(client, "/printer/emergency_stop", false, 5000, printer_config); + configure_http_client(client, "/printer/emergency_stop", false, 5000); try { @@ -116,7 +136,7 @@ bool KlipperPrinter::execute_feature(PrinterFeatures feature) } else { - return send_gcode("M83") && send_gcode("G1 E25 F300"); + return send_gcode("M83\nG1 E25 F300"); } case PrinterFeatureRetract: if (printer_data.state == PrinterStatePrinting) @@ -130,10 +150,10 @@ bool KlipperPrinter::execute_feature(PrinterFeatures feature) } else { - return send_gcode("M83") && send_gcode("G1 E-25 F300"); + return send_gcode("M83\nG1 E-25 F300"); } case PrinterFeatureCooldown: - return send_gcode("M104 S0") && send_gcode("M140 S0"); + return send_gcode("M104 S0\nM140 S0"); default: LOG_F(("Unsupported printer feature %d", feature)); return false; @@ -142,7 +162,301 @@ bool KlipperPrinter::execute_feature(PrinterFeatures feature) bool KlipperPrinter::connect() { - // Pass + HTTPClient client; + configure_http_client(client, "/printer/info", false, 1000); + + int httpCode; + try { + httpCode = client.GET(); + return httpCode == 200; + } + catch (...) { + LOG_LN("Failed to connect"); + return false; + } } +bool KlipperPrinter::fetch() +{ + HTTPClient client; + configure_http_client(client, "/printer/objects/query?extruder&heater_bed&toolhead&gcode_move&virtual_sdcard&print_stats&webhooks&fan&display_status", true, 1000); + + int httpCode = client.GET(); + if (httpCode == 200) + { + if (printer_data.state == PrinterStateOffline) + { + printer_data.state = PrinterStateError; + } + + klipper_request_consecutive_fail_count = 0; + JsonDocument doc; + deserializeJson(doc, client.getStream()); + auto status = doc["result"]["status"]; + bool emit_state_update = false; + + if (status.containsKey("webhooks")) + { + const char *state = status["webhooks"]["state"]; + const char *message = status["webhooks"]["state_message"]; + + if (strcmp(state, "ready") == 0 && printer_data.state == PrinterStateError) + { + printer_data.state = PrinterStateIdle; + } + else if ((strcmp(state, "shutdown") == 0 || strcmp(state, "error") == 0) && printer_data.state != PrinterStateError) + { + printer_data.state = PrinterStateError; + } + + if (printer_data.state_message == NULL || strcmp(printer_data.state_message, message)) + { + if (printer_data.state_message != NULL) + { + free(printer_data.state_message); + } + + printer_data.state_message = (char *)malloc(strlen(message) + 1); + strcpy(printer_data.state_message, message); + } + } + + if (printer_data.state != PrinterStateError) + { + if (status.containsKey("extruder")) + { + printer_data.temperatures[PrinterTemperatureDeviceIndexNozzle1] = status["extruder"]["temperature"]; + printer_data.target_temperatures[PrinterTemperatureDeviceIndexNozzle1] = status["extruder"]["target"]; + bool can_extrude = status["extruder"]["can_extrude"]; + printer_data.pressure_advance = status["extruder"]["pressure_advance"]; + printer_data.smooth_time = status["extruder"]["smooth_time"]; + printer_data.can_extrude = can_extrude == true; + } + + if (status.containsKey("heater_bed")) + { + printer_data.temperatures[PrinterTemperatureDeviceIndexBed] = status["heater_bed"]["temperature"]; + printer_data.target_temperatures[PrinterTemperatureDeviceIndexBed] = status["heater_bed"]["target"]; + } + + if (status.containsKey("toolhead")) + { + const char *homed_axis = status["toolhead"]["homed_axes"]; + printer_data.homed_axis = strcmp(homed_axis, "xyz") == 0; + } + + if (status.containsKey("gcode_move")) + { + printer_data.position[0] = status["gcode_move"]["gcode_position"][0]; + printer_data.position[1] = status["gcode_move"]["gcode_position"][1]; + printer_data.position[2] = status["gcode_move"]["gcode_position"][2]; + gcode_offset[0] = status["gcode_move"]["homing_origin"][0]; + gcode_offset[1] = status["gcode_move"]["homing_origin"][1]; + gcode_offset[2] = status["gcode_move"]["homing_origin"][2]; + bool absolute_coords = status["gcode_move"]["absolute_coordinates"]; + + if (lock_absolute_relative_mode_swap > 0) + { + lock_absolute_relative_mode_swap--; + } + else + { + printer_data.absolute_coords = absolute_coords == true; + } + + printer_data.speed_mult = status["gcode_move"]["speed_factor"]; + printer_data.extrude_mult = status["gcode_move"]["extrude_factor"]; + printer_data.feedrate_mm_per_s = status["gcode_move"]["speed"]; + printer_data.feedrate_mm_per_s /= 60; // convert mm/m to mm/s + } + + if (status.containsKey("fan")) + { + printer_data.fan_speed = status["fan"]["speed"]; + } + + if (status.containsKey("virtual_sdcard")) + { + printer_data.print_progress = status["virtual_sdcard"]["progress"]; + } + + if (status.containsKey("print_stats")) + { + const char *filename = status["print_stats"]["filename"]; + + if (filename != NULL && (printer_data.print_filename == NULL || strcmp(printer_data.print_filename, filename))) + { + if (printer_data.print_filename != NULL) + { + free(printer_data.print_filename); + } + + printer_data.print_filename = (char *)malloc(strlen(filename) + 1); + strcpy(printer_data.print_filename, filename); + } + + printer_data.elapsed_time_s = status["print_stats"]["total_duration"]; + printer_data.printed_time_s = status["print_stats"]["print_duration"]; + printer_data.filament_used_mm = status["print_stats"]["filament_used"]; + printer_data.total_layers = status["print_stats"]["info"]["total_layer"]; + printer_data.current_layer = status["print_stats"]["info"]["current_layer"]; + + const char *state = status["print_stats"]["state"]; + if (state == nullptr) + { + // Continue + } + else if (strcmp(state, "printing") == 0) + { + printer_data.state = PrinterStatePrinting; + } + else if (strcmp(state, "paused") == 0) + { + printer_data.state = PrinterStatePaused; + } + else if (strcmp(state, "complete") == 0 || strcmp(state, "cancelled") == 0 || strcmp(state, "standby") == 0) + { + printer_data.state = PrinterStateIdle; + } + } + + if (status.containsKey("display_status")) + { + printer_data.print_progress = status["display_status"]["progress"]; + const char* message = status["display_status"]["message"]; + store_available_popup_message(message); + } + + if (printer_data.state == PrinterStatePrinting && printer_data.print_progress > 0) + { + float remaining_time_s_percentage = (printer_data.printed_time_s / printer_data.print_progress) - printer_data.printed_time_s; + float remaining_time_s_slicer = 0; + + if (slicer_estimated_print_time_s > 0) + { + remaining_time_s_slicer = slicer_estimated_print_time_s - printer_data.printed_time_s; + } + + if (remaining_time_s_slicer <= 0 || printer_config->remaining_time_calc_mode == REMAINING_TIME_CALC_PERCENTAGE) + { + printer_data.remaining_time_s = remaining_time_s_percentage; + } + else if (printer_config->remaining_time_calc_mode == REMAINING_TIME_CALC_INTERPOLATED) + { + printer_data.remaining_time_s = remaining_time_s_percentage * printer_data.print_progress + remaining_time_s_slicer * (1 - printer_data.print_progress); + } + else if (printer_config->remaining_time_calc_mode == REMAINING_TIME_CALC_SLICER) + { + printer_data.remaining_time_s = remaining_time_s_slicer; + } + } + + if (printer_data.remaining_time_s < 0) + { + printer_data.remaining_time_s = 0; + } + + if (printer_data.state == PrinterStateIdle) + { + slicer_estimated_print_time_s = 0; + } + } + + if (printer_data.state == PrinterStatePrinting && millis() - last_slicer_time_query > 30000 && slicer_estimated_print_time_s <= 0) + { + last_slicer_time_query = millis(); + slicer_estimated_print_time_s = get_slicer_time_estimate_s(); + } + } + else + { + klipper_request_consecutive_fail_count++; + LOG_F(("Failed to fetch printer data: %d\n", httpCode)); + + if (klipper_request_consecutive_fail_count >= 5) + { + printer_data.state = PrinterStateOffline; + return false; + } + } + + return true; +} + +int KlipperPrinter::get_power_devices_count() +{ + return 0; +} + +PrinterDataMinimal KlipperPrinter::fetch_min() +{ + PrinterDataMinimal data = {0}; + + if (!printer_config->ip_configured) + { + data.state = PrinterStateOffline; + return data; + } + + data.success = true; + + HTTPClient client; + configure_http_client(client, "/printer/objects/query?webhooks&print_stats&virtual_sdcard", true, 1000); + + int httpCode = client.GET(); + if (httpCode == 200) + { + data.state = PrinterStateIdle; + data.power_devices = get_power_devices_count(); + + JsonDocument doc; + deserializeJson(doc, client.getStream()); + auto status = doc["result"]["status"]; + + if (status.containsKey("webhooks")) + { + const char *state = status["webhooks"]["state"]; + + if (strcmp(state, "shutdown") == 0) + { + data.state = PrinterStateError; + } + } + + if (data.state != PrinterStateError) + { + if (status.containsKey("virtual_sdcard")) + { + data.print_progress = status["virtual_sdcard"]["progress"]; + } + + if (status.containsKey("print_stats")) + { + const char *state = status["print_stats"]["state"]; + + if (state == nullptr) + { + data.state = PrinterStateError; + } + else if (strcmp(state, "printing") == 0) + { + data.state = PrinterStatePrinting; + } + else if (strcmp(state, "paused") == 0) + { + data.state = PrinterStatePaused; + } + else if (strcmp(state, "complete") == 0 || strcmp(state, "cancelled") == 0 || strcmp(state, "standby") == 0) + { + data.state = PrinterStateIdle; + } + } + } + } + else + { + data.state = PrinterStateOffline; + data.power_devices = get_power_devices_count(); + } +} \ No newline at end of file diff --git a/CYD-Klipper/src/core/klipper/klipper_printer_integration.hpp b/CYD-Klipper/src/core/klipper/klipper_printer_integration.hpp index ea299ef..8849830 100644 --- a/CYD-Klipper/src/core/klipper/klipper_printer_integration.hpp +++ b/CYD-Klipper/src/core/klipper/klipper_printer_integration.hpp @@ -6,6 +6,10 @@ class KlipperPrinter : BasePrinter { private: unsigned char lock_absolute_relative_mode_swap{}; + unsigned char klipper_request_consecutive_fail_count{}; + unsigned int slicer_estimated_print_time_s{}; + unsigned int last_slicer_time_query{}; + float gcode_offset[3]{}; public: KlipperPrinter(int index) : BasePrinter(index) @@ -26,19 +30,22 @@ class KlipperPrinter : BasePrinter | PrinterTemperatureDeviceNozzle1; } - bool move_printer(const char* axis, float amount, bool relative) = 0; - bool execute_feature(PrinterFeatures feature) = 0; - bool connect() = 0; - bool fetch(PrinterData& data) = 0; - void commit_fetch(PrinterData& data) = 0; - bool fetch_min(PrinterDataMinimal& data) = 0; - void disconnect() = 0; - bool get_macros(Macros& macros) = 0; - bool execute_macro(const char* macro) = 0; - bool get_power_devices(PowerDevices& power_devices) = 0; - bool set_power_device_state(const char* device_name, bool state) = 0; - bool get_files(Files& files) = 0; - bool start_file(const char* file) = 0; - bool set_target_temperature(PrinterTemperatureDevice device, float temperature) = 0; + bool move_printer(const char* axis, float amount, bool relative); + bool execute_feature(PrinterFeatures feature); + bool connect(); + bool fetch(); + PrinterDataMinimal fetch_min(); + void disconnect(); + Macros get_macros(); + int get_macros_count(); + bool execute_macro(const char* macro); + PowerDevices get_power_devices(); + int get_power_devices_count(); + bool set_power_device_state(const char* device_name, bool state); + Files get_files(); + bool start_file(const char* file); + bool set_target_temperature(PrinterTemperatureDevice device, float temperature); bool send_gcode(const char* gcode, bool wait = true); + int get_slicer_time_estimate_s(); + void configure_http_client(HTTPClient &client, String url_part, bool stream, int timeout); }; \ No newline at end of file diff --git a/CYD-Klipper/src/core/printer_integration.cpp b/CYD-Klipper/src/core/printer_integration.cpp index e69de29..a5afdec 100644 --- a/CYD-Klipper/src/core/printer_integration.cpp +++ b/CYD-Klipper/src/core/printer_integration.cpp @@ -0,0 +1,96 @@ +#include "printer_integration.hpp" + +unsigned char current_printer_index = 0; +BasePrinter* registered_printers; + +PrinterData* printer_data_copy; +char* state_message_copy; +char* print_filename_copy; +char* popup_message_copy = NULL; + +bool available_data_message; +bool available_state_message; +bool available_popup_message; + +BasePrinter::BasePrinter(unsigned char index) + { + config_index = index; + // TODO: Fetch printer config and global config +} + +PrinterData* BasePrinter::CopyPrinterData() +{ + available_data_message = true; + available_state_message = printer_data.state != printer_data_copy->state; + + memcpy(printer_data_copy, &printer_data, sizeof(PrinterData)); + printer_data_copy->state_message = state_message_copy; + printer_data_copy->print_filename = print_filename_copy; + strcpy(state_message_copy, printer_data.state_message); + strcpy(print_filename_copy, printer_data.print_filename); +} + +void initialize_printers() +{ + printer_data_copy = (PrinterData*)malloc(sizeof(PrinterData)); + state_message_copy = (char*)malloc(256); + print_filename_copy = (char*)malloc(256); +} + +BasePrinter* get_current_printer() +{ + return get_printer(current_printer_index); +} + +BasePrinter* get_printer(int idx) +{ + return registered_printers + idx; +} + +void store_available_popup_message(const char *message) +{ + if (message != NULL && (!get_current_printer()->global_config->disable_m117_messaging) && (popup_message_copy == NULL || strcmp(popup_message_copy, message))) + { + if (popup_message_copy != NULL) + { + free(popup_message_copy); + } + + popup_message_copy = (char*)malloc(strlen(message) + 1); + strcpy(popup_message_copy, message); + available_popup_message = true; + } +} + +#define DATA_PRINTER_STATE 1 +#define DATA_PRINTER_DATA 2 +#define DATA_PRINTER_TEMP_PRESET 3 +#define DATA_PRINTER_MINIMAL 4 +#define DATA_PRINTER_POPUP 5 + +void send_available_popup_message() +{ + if (available_popup_message) + { + available_data_message = false; + lv_msg_send(DATA_PRINTER_POPUP, popup_message_copy); + } +} + +void send_available_data_message() +{ + if (available_data_message) + { + available_data_message = false; + lv_msg_send(DATA_PRINTER_DATA, get_current_printer()); + } +} + +void send_available_state_message() +{ + if (available_state_message) + { + available_state_message = false; + lv_msg_send(DATA_PRINTER_STATE, get_current_printer()); + } +} \ No newline at end of file diff --git a/CYD-Klipper/src/core/printer_integration.hpp b/CYD-Klipper/src/core/printer_integration.hpp index 7bd233b..54ee345 100644 --- a/CYD-Klipper/src/core/printer_integration.hpp +++ b/CYD-Klipper/src/core/printer_integration.hpp @@ -39,6 +39,20 @@ enum PrinterTemperatureDevice PrinterTemperatureDeviceChamber = BIT(9), }; +enum PrinterTemperatureDeviceIndex +{ + PrinterTemperatureDeviceIndexBed = 0, + PrinterTemperatureDeviceIndexNozzle1 = 1, + PrinterTemperatureDeviceIndexNozzle2 = 2, + PrinterTemperatureDeviceIndexNozzle3 = 3, + PrinterTemperatureDeviceIndexNozzle4 = 4, + PrinterTemperatureDeviceIndexNozzle5 = 5, + PrinterTemperatureDeviceIndexNozzle6 = 6, + PrinterTemperatureDeviceIndexNozzle7 = 7, + PrinterTemperatureDeviceIndexNozzle8 = 8, + PrinterTemperatureDeviceIndexChamber = 9, +}; + inline PrinterTemperatureDevice operator|(PrinterTemperatureDevice a, PrinterTemperatureDevice b) { return static_cast(static_cast(a) | static_cast(b)); @@ -83,26 +97,30 @@ typedef struct _PrinterData { int feedrate_mm_per_s; } PrinterData; -typedef struct _PrinterDataMinimal { +typedef struct { unsigned char state; float print_progress; // 0 -> 1 unsigned int power_devices; + bool success; } PrinterDataMinimal; typedef struct { const char** macros; unsigned int count; + bool success; } Macros; typedef struct { const char** power_devices; const bool* power_states; unsigned int count; + bool success; } PowerDevices; typedef struct { const char** available_files; unsigned int count; + bool success; } Files; typedef struct { @@ -127,24 +145,28 @@ class BasePrinter virtual bool move_printer(const char* axis, float amount, bool relative) = 0; virtual bool execute_feature(PrinterFeatures feature) = 0; virtual bool connect() = 0; - virtual bool fetch(PrinterData& data) = 0; - virtual void commit_fetch(PrinterData& data) = 0; - virtual bool fetch_min(PrinterDataMinimal& data) = 0; + virtual bool fetch() = 0; + virtual PrinterDataMinimal fetch_min() = 0; virtual void disconnect() = 0; - virtual bool get_macros(Macros& macros) = 0; + virtual Macros get_macros() = 0; + virtual int get_macros_count() = 0; virtual bool execute_macro(const char* macro) = 0; - virtual bool get_power_devices(PowerDevices& power_devices) = 0; + virtual PowerDevices get_power_devices() = 0; + virtual int get_power_devices_count() = 0; virtual bool set_power_device_state(const char* device_name, bool state) = 0; - virtual bool get_files(Files& files) = 0; + virtual Files get_files() = 0; virtual bool start_file(const char* file) = 0; virtual bool set_target_temperature(PrinterTemperatureDevice device, float temperature) = 0; - BasePrinter(unsigned char index) { - config_index = index; - // TODO: Fetch printer config and global config - } + BasePrinter(unsigned char index); + PrinterData* CopyPrinterData(); }; BasePrinter* get_current_printer(); BasePrinter* get_printer(int idx); -void initialize_printer(); \ No newline at end of file +void initialize_printers(); + +void store_available_popup_message(const char *message); +void send_available_popup_message(); +void send_available_data_message(); +void send_available_state_message(); \ No newline at end of file From eed4b3efef4b565a8a720032a4432cbc1b19fbcf Mon Sep 17 00:00:00 2001 From: suchmememanyskill <38142618+suchmememanyskill@users.noreply.github.com> Date: Tue, 22 Oct 2024 22:56:04 +0200 Subject: [PATCH 03/63] Cleanup --- .../klipper/klipper_printer_integration.cpp | 37 ++++-- CYD-Klipper/src/core/printer_integration.cpp | 108 +++++++----------- CYD-Klipper/src/core/printer_integration.hpp | 10 +- 3 files changed, 71 insertions(+), 84 deletions(-) diff --git a/CYD-Klipper/src/core/klipper/klipper_printer_integration.cpp b/CYD-Klipper/src/core/klipper/klipper_printer_integration.cpp index 7271847..7ecbcf4 100644 --- a/CYD-Klipper/src/core/klipper/klipper_printer_integration.cpp +++ b/CYD-Klipper/src/core/klipper/klipper_printer_integration.cpp @@ -211,11 +211,6 @@ bool KlipperPrinter::fetch() if (printer_data.state_message == NULL || strcmp(printer_data.state_message, message)) { - if (printer_data.state_message != NULL) - { - free(printer_data.state_message); - } - printer_data.state_message = (char *)malloc(strlen(message) + 1); strcpy(printer_data.state_message, message); } @@ -286,11 +281,6 @@ bool KlipperPrinter::fetch() if (filename != NULL && (printer_data.print_filename == NULL || strcmp(printer_data.print_filename, filename))) { - if (printer_data.print_filename != NULL) - { - free(printer_data.print_filename); - } - printer_data.print_filename = (char *)malloc(strlen(filename) + 1); strcpy(printer_data.print_filename, filename); } @@ -325,7 +315,12 @@ bool KlipperPrinter::fetch() { printer_data.print_progress = status["display_status"]["progress"]; const char* message = status["display_status"]["message"]; - store_available_popup_message(message); + + if (message != NULL && (printer_data.popup_message == NULL || strcmp(printer_data.popup_message, message))) + { + printer_data.popup_message = (char*)malloc(strlen(message) + 1); + strcpy(printer_data.popup_message, message); + } } if (printer_data.state == PrinterStatePrinting && printer_data.print_progress > 0) @@ -459,4 +454,24 @@ PrinterDataMinimal KlipperPrinter::fetch_min() data.state = PrinterStateOffline; data.power_devices = get_power_devices_count(); } +} + +void KlipperPrinter::disconnect() +{ + // Nothing to disconnect, everything is http request based + + if (printer_data.state_message != NULL) + { + free(printer_data.state_message); + } + + if (printer_data.print_filename != NULL) + { + free(printer_data.print_filename); + } + + if (printer_data.popup_message != NULL) + { + free(printer_data.popup_message); + } } \ No newline at end of file diff --git a/CYD-Klipper/src/core/printer_integration.cpp b/CYD-Klipper/src/core/printer_integration.cpp index a5afdec..da8cfb5 100644 --- a/CYD-Klipper/src/core/printer_integration.cpp +++ b/CYD-Klipper/src/core/printer_integration.cpp @@ -2,39 +2,63 @@ unsigned char current_printer_index = 0; BasePrinter* registered_printers; - PrinterData* printer_data_copy; -char* state_message_copy; -char* print_filename_copy; -char* popup_message_copy = NULL; - -bool available_data_message; -bool available_state_message; -bool available_popup_message; BasePrinter::BasePrinter(unsigned char index) - { +{ config_index = index; + + printer_data.state_message = (char*)malloc(1); + printer_data.print_filename = (char*)malloc(1); + printer_data.popup_message = (char*)malloc(1); + *printer_data.state_message = '\0'; + *printer_data.print_filename = '\0'; + *printer_data.popup_message = '\0'; + // TODO: Fetch printer config and global config } -PrinterData* BasePrinter::CopyPrinterData() +#define DATA_PRINTER_STATE 1 +#define DATA_PRINTER_DATA 2 +#define DATA_PRINTER_TEMP_PRESET 3 +#define DATA_PRINTER_MINIMAL 4 +#define DATA_PRINTER_POPUP 5 + +PrinterData* BasePrinter::AnnouncePrinterData() { - available_data_message = true; - available_state_message = printer_data.state != printer_data_copy->state; + char* old_state_message = printer_data_copy->state_message; + char* old_print_filename = printer_data_copy->print_filename; + char* old_popup_message = printer_data_copy->print_filename; memcpy(printer_data_copy, &printer_data, sizeof(PrinterData)); - printer_data_copy->state_message = state_message_copy; - printer_data_copy->print_filename = print_filename_copy; - strcpy(state_message_copy, printer_data.state_message); - strcpy(print_filename_copy, printer_data.print_filename); + + if (old_state_message != printer_data_copy->state_message) + { + free(old_state_message); + lv_msg_send(DATA_PRINTER_STATE, get_current_printer()); + } + else if (printer_data.state != printer_data_copy->state) + { + lv_msg_send(DATA_PRINTER_STATE, get_current_printer()); + } + + if (old_print_filename != printer_data_copy->print_filename) + { + free(old_print_filename); + } + + if (old_popup_message != printer_data_copy->popup_message) + { + free(old_popup_message); + lv_msg_send(DATA_PRINTER_POPUP, get_current_printer()); + } + + lv_msg_send(DATA_PRINTER_DATA, get_current_printer()); } void initialize_printers() { printer_data_copy = (PrinterData*)malloc(sizeof(PrinterData)); - state_message_copy = (char*)malloc(256); - print_filename_copy = (char*)malloc(256); } BasePrinter* get_current_printer() @@ -45,52 +69,4 @@ BasePrinter* get_current_printer() BasePrinter* get_printer(int idx) { return registered_printers + idx; -} - -void store_available_popup_message(const char *message) -{ - if (message != NULL && (!get_current_printer()->global_config->disable_m117_messaging) && (popup_message_copy == NULL || strcmp(popup_message_copy, message))) - { - if (popup_message_copy != NULL) - { - free(popup_message_copy); - } - - popup_message_copy = (char*)malloc(strlen(message) + 1); - strcpy(popup_message_copy, message); - available_popup_message = true; - } -} - -#define DATA_PRINTER_STATE 1 -#define DATA_PRINTER_DATA 2 -#define DATA_PRINTER_TEMP_PRESET 3 -#define DATA_PRINTER_MINIMAL 4 -#define DATA_PRINTER_POPUP 5 - -void send_available_popup_message() -{ - if (available_popup_message) - { - available_data_message = false; - lv_msg_send(DATA_PRINTER_POPUP, popup_message_copy); - } -} - -void send_available_data_message() -{ - if (available_data_message) - { - available_data_message = false; - lv_msg_send(DATA_PRINTER_DATA, get_current_printer()); - } -} - -void send_available_state_message() -{ - if (available_state_message) - { - available_state_message = false; - lv_msg_send(DATA_PRINTER_STATE, get_current_printer()); - } } \ No newline at end of file diff --git a/CYD-Klipper/src/core/printer_integration.hpp b/CYD-Klipper/src/core/printer_integration.hpp index 54ee345..def2719 100644 --- a/CYD-Klipper/src/core/printer_integration.hpp +++ b/CYD-Klipper/src/core/printer_integration.hpp @@ -77,6 +77,7 @@ typedef struct _PrinterData { }; PrinterState state; char* state_message; + char* popup_message; float temperatures[10]; float target_temperatures[10]; PrinterTemperatureDevice AvailableDevices; @@ -159,14 +160,9 @@ class BasePrinter virtual bool set_target_temperature(PrinterTemperatureDevice device, float temperature) = 0; BasePrinter(unsigned char index); - PrinterData* CopyPrinterData(); + PrinterData* AnnouncePrinterData(); }; BasePrinter* get_current_printer(); BasePrinter* get_printer(int idx); -void initialize_printers(); - -void store_available_popup_message(const char *message); -void send_available_popup_message(); -void send_available_data_message(); -void send_available_state_message(); \ No newline at end of file +void initialize_printers(); \ No newline at end of file From 2078a1541d2e3f0b1ed7267836454ffc55547794 Mon Sep 17 00:00:00 2001 From: suchmememanyskill <38142618+suchmememanyskill@users.noreply.github.com> Date: Wed, 23 Oct 2024 23:15:43 +0200 Subject: [PATCH 04/63] More work --- CYD-Klipper/.vscode/settings.json | 3 +- .../klipper/klipper_printer_integration.cpp | 374 +++++++++++++++++- .../klipper/klipper_printer_integration.hpp | 3 +- CYD-Klipper/src/core/printer_integration.hpp | 13 +- CYD-Klipper/src/ui/ui_utils.cpp | 11 + CYD-Klipper/src/ui/ui_utils.h | 1 + 6 files changed, 378 insertions(+), 27 deletions(-) diff --git a/CYD-Klipper/.vscode/settings.json b/CYD-Klipper/.vscode/settings.json index 55d6dcc..0ddaeec 100644 --- a/CYD-Klipper/.vscode/settings.json +++ b/CYD-Klipper/.vscode/settings.json @@ -14,7 +14,8 @@ "functional": "cpp", "*.tcc": "cpp", "cmath": "cpp", - "system_error": "cpp" + "system_error": "cpp", + "random": "cpp" }, "cmake.configureOnOpen": false } \ No newline at end of file diff --git a/CYD-Klipper/src/core/klipper/klipper_printer_integration.cpp b/CYD-Klipper/src/core/klipper/klipper_printer_integration.cpp index 7ecbcf4..11e15f5 100644 --- a/CYD-Klipper/src/core/klipper/klipper_printer_integration.cpp +++ b/CYD-Klipper/src/core/klipper/klipper_printer_integration.cpp @@ -3,12 +3,11 @@ #include #include #include +#include void KlipperPrinter::configure_http_client(HTTPClient &client, String url_part, bool stream, int timeout) { - if (stream){ - client.useHTTP10(true); - } + client.useHTTP10(stream); if (timeout > 0){ client.setTimeout(timeout); @@ -29,9 +28,9 @@ int KlipperPrinter::get_slicer_time_estimate_s() HTTPClient client; configure_http_client(client, "/server/files/metadata?filename=" + urlEncode(printer_data.print_filename), true, 5000); - int httpCode = client.GET(); + int http_code = client.GET(); - if (httpCode != 200) + if (http_code != 200) return 0; JsonDocument doc; @@ -165,10 +164,10 @@ bool KlipperPrinter::connect() HTTPClient client; configure_http_client(client, "/printer/info", false, 1000); - int httpCode; + int http_code; try { - httpCode = client.GET(); - return httpCode == 200; + http_code = client.GET(); + return http_code == 200; } catch (...) { LOG_LN("Failed to connect"); @@ -181,8 +180,8 @@ bool KlipperPrinter::fetch() HTTPClient client; configure_http_client(client, "/printer/objects/query?extruder&heater_bed&toolhead&gcode_move&virtual_sdcard&print_stats&webhooks&fan&display_status", true, 1000); - int httpCode = client.GET(); - if (httpCode == 200) + int http_code = client.GET(); + if (http_code == 200) { if (printer_data.state == PrinterStateOffline) { @@ -367,7 +366,7 @@ bool KlipperPrinter::fetch() else { klipper_request_consecutive_fail_count++; - LOG_F(("Failed to fetch printer data: %d\n", httpCode)); + LOG_F(("Failed to fetch printer data: %d\n", http_code)); if (klipper_request_consecutive_fail_count >= 5) { @@ -399,8 +398,8 @@ PrinterDataMinimal KlipperPrinter::fetch_min() HTTPClient client; configure_http_client(client, "/printer/objects/query?webhooks&print_stats&virtual_sdcard", true, 1000); - int httpCode = client.GET(); - if (httpCode == 200) + int http_code = client.GET(); + if (http_code == 200) { data.state = PrinterStateIdle; data.power_devices = get_power_devices_count(); @@ -459,19 +458,356 @@ PrinterDataMinimal KlipperPrinter::fetch_min() void KlipperPrinter::disconnect() { // Nothing to disconnect, everything is http request based +} + +Macros KlipperPrinter::get_macros() +{ + HTTPClient client; + Macros macros; + + configure_http_client(client, "/printer/gcode/help", true, 1000); + int http_code = client.GET(); + + if (http_code == 200){ + JsonDocument doc; + deserializeJson(doc, client.getStream()); + auto result = doc["result"].as(); + macros.macros = (char**)malloc(sizeof(char*) * 32); + macros.count = 0; + macros.success = true; + + for (JsonPair i : result){ + const char *key = i.key().c_str(); + const char *value = i.value().as().c_str(); + if (strcmp(value, "CYD_SCREEN_MACRO") == 0) { + char* macro = (char*)malloc(strlen(key) + 1); + strcpy(macro, key); + macros.macros[macros.count++] = macro; + } + } + + if (global_config->sort_macros) + { + std::sort(macros.macros, macros.macros + macros.count, [](const char* a, const char* b) { + return strcmp(a, b) < 0; + }); + } + } + + return macros; +} + +int KlipperPrinter::get_macros_count() +{ + HTTPClient client; + configure_http_client(client, "/printer/gcode/help", true, 1000); + + int http_code = client.GET(); + + if (http_code == 200){ + JsonDocument doc; + deserializeJson(doc, client.getStream()); + auto result = doc["result"].as(); + + int count = 0; + + for (JsonPair i : result){ + const char *value = i.value().as().c_str(); + if (strcmp(value, "CYD_SCREEN_MACRO") == 0) { + count++; + } + } + + return count; + } + else { + return 0; + } +} + +bool KlipperPrinter::execute_macro(const char* macro) +{ + return send_gcode(macro); +} + +PowerDevices KlipperPrinter::get_power_devices() +{ + HTTPClient client; + PowerDevices power_devices; + configure_http_client(client, "/machine/device_power/devices", true, 1000); + + int http_code = client.GET(); + + if (http_code == 200){ + JsonDocument doc; + deserializeJson(doc, client.getStream()); + auto result = doc["result"]["devices"].as(); + power_devices.power_devices = (char**)malloc(sizeof(char*) * 16); + power_devices.power_states = (bool*)malloc(sizeof(bool) * 16); + power_devices.count = 0; + power_devices.success = true; + + for (auto i : result){ + const char * device_name = i["device"]; + const char * device_state = i["status"]; + power_devices.power_devices[power_devices.count] = (char*)malloc(strlen(device_name) + 1); + strcpy(power_devices.power_devices[power_devices.count], device_name); + power_devices.power_states[power_devices.count] = strcmp(device_state, "on") == 0; + power_devices.count++; + } + } + + return power_devices; +} + +int KlipperPrinter::get_power_devices_count() +{ + HTTPClient client; + configure_http_client(client, "/machine/device_power/devices", true, 1000); + + int http_code = client.GET(); + + if (http_code == 200){ + JsonDocument doc; + deserializeJson(doc, client.getStream()); + auto result = doc["result"]["devices"].as(); + + int count = 0; + + for (auto i : result){ + count++; + } + + return count; + } + else { + return 0; + } +} + +bool KlipperPrinter::set_power_device_state(const char* device_name, bool state) +{ + HTTPClient client; + configure_http_client(client, "/machine/device_power/device?device=" + urlEncode(device_name) + "&action=" + (state ? "on" : "off"), true, 1000); + return client.POST("") == 200; +} + +typedef struct { + char* name; + float modified; +} FileSystemFile; + +#define KLIPPER_FILE_FETCH_LIMIT 20 + +Files KlipperPrinter::get_files() +{ + Files files_result; + HTTPClient client; + LOG_F(("Heap space pre-file-parse: %d bytes\n", esp_get_free_heap_size())) + std::list files; + + auto timer_request = millis(); + configure_http_client(client, "/server/files/list", true, 5000); + + int http_code = client.GET(); + auto timer_parse = millis(); + + if (http_code == 200){ + JsonDocument doc; + auto parseResult = deserializeJson(doc, client.getStream()); + LOG_F(("Json parse: %s\n", parseResult.c_str())) + auto result = doc["result"].as(); + + for (auto file : result){ + FileSystemFile 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; - if (printer_data.state_message != NULL) + file_iter++; + } + + if (file_iter == files.end() && files.size() >= KLIPPER_FILE_FETCH_LIMIT) + continue; + + f.name = (char*)malloc(strlen(path) + 1); + if (f.name == NULL){ + LOG_LN("Failed to allocate memory"); + continue; + } + strcpy(f.name, path); + f.modified = modified; + + if (file_iter != files.end()) + files.insert(file_iter, f); + else + files.push_back(f); + + if (files.size() > KLIPPER_FILE_FETCH_LIMIT){ + auto last_entry = files.back(); + + if (last_entry.name != NULL) + free(last_entry.name); + + files.pop_back(); + } + } + } + + files_result.available_files = (char**)malloc(sizeof(char*) * files.size()); + + if (files_result.available_files == NULL){ + LOG_LN("Failed to allocate memory"); + + for (auto file : files){ + free(file.name); + } + + return files_result; + } + + for (auto file : files){ + files_result.available_files[files_result.count++] = file.name; + } + + files_result.success = true; + + LOG_F(("Heap space post-file-parse: %d bytes\n", esp_get_free_heap_size())) + LOG_F(("Got %d files. Request took %dms, parsing took %dms\n", files.size(), timer_parse - timer_request, millis() - timer_parse)) + return files_result; +} + +bool KlipperPrinter::start_file(const char *filename) +{ + HTTPClient client; + configure_http_client(client, "/printer/print/start?filename=" + urlEncode(filename), false, 1000); + + int httpCode = client.POST(""); + LOG_F(("Print start: HTTP %d\n", httpCode)) +} + +bool KlipperPrinter::set_target_temperature(PrinterTemperatureDevice device, float temperature) +{ + char gcode[64] = {0}; + + switch (device) + { + case PrinterTemperatureDeviceBed: + sprintf(gcode, "M140 S%d", temperature); + break; + case PrinterTemperatureDeviceNozzle1: + sprintf(gcode, "M104 S%d", temperature); + break; + default: + LOG_F(("Unknown temperature device %d was requested to heat to %.2f", device, temperature)); + return false; + } + + return send_gcode(gcode); +} + +unsigned char* KlipperPrinter::get_32_32_png_image_thumbnail(const char* gcode_filename) +{ + HTTPClient client; + configure_http_client(client, "/server/files/thumbnails?filename=", true, 1000); + char* img_filename_path = NULL; + unsigned char* data_png = NULL; + + int http_code = 0; + try { - free(printer_data.state_message); + http_code = client.GET(); } + catch (...) + { + LOG_LN("Exception while fetching gcode img location"); + return NULL; + } + + if (http_code == 200) + { + JsonDocument doc; + deserializeJson(doc, client.getStream()); + auto result = doc["result"].as(); + const char* chosen_thumb = NULL; + + for (auto file : result){ + int width = file["width"]; + int height = file["height"]; + int size = file["size"]; + const char* thumbnail = file["thumbnail_path"]; + + if (width != height || width != 32) + continue; - if (printer_data.print_filename != NULL) + if (strcmp(thumbnail + strlen(thumbnail) - 4, ".png")) + continue; + + chosen_thumb = thumbnail; + break; + } + + if (chosen_thumb != NULL){ + LOG_F(("Found 32x32 PNG gcode img at %s\n", gcode_filename)) + img_filename_path = (char*)malloc(strlen(chosen_thumb) + 1); + strcpy(img_filename_path, chosen_thumb); + } + } + else { - free(printer_data.print_filename); + LOG_F(("Failed to fetch gcode image data: %d\n", http_code)) } - if (printer_data.popup_message != NULL) + if (img_filename_path == NULL) { - free(printer_data.popup_message); + return NULL; } + + client.end(); + + configure_http_client(client, "/server/files/gcodes/" + urlEncode(img_filename_path), false, 2000); + + int http_code = 0; + try + { + http_code = client.GET(); + } + catch (...) + { + LOG_LN("Exception while fetching gcode img"); + return NULL; + } + + if (http_code == 200) + { + size_t len = client.getSize(); + if (len <= 0) + { + LOG_LN("No gcode img data"); + return NULL; + } + + data_png = (unsigned char*)malloc(len + 1); + + if (data_png != NULL) + { + if (len != client.getStream().readBytes(data_png, len)) + { + LOG_LN("Failed to read gcode img data"); + free(data_png); + } + else + { + free(img_filename_path); + return data_png; + } + } + } + + free(img_filename_path); + return NULL; } \ No newline at end of file diff --git a/CYD-Klipper/src/core/klipper/klipper_printer_integration.hpp b/CYD-Klipper/src/core/klipper/klipper_printer_integration.hpp index 8849830..25c552b 100644 --- a/CYD-Klipper/src/core/klipper/klipper_printer_integration.hpp +++ b/CYD-Klipper/src/core/klipper/klipper_printer_integration.hpp @@ -43,7 +43,8 @@ class KlipperPrinter : BasePrinter int get_power_devices_count(); bool set_power_device_state(const char* device_name, bool state); Files get_files(); - bool start_file(const char* file); + bool start_file(const char* filename); + unsigned char* get_32_32_png_image_thumbnail(const char* gcode_filename); bool set_target_temperature(PrinterTemperatureDevice device, float temperature); bool send_gcode(const char* gcode, bool wait = true); int get_slicer_time_estimate_s(); diff --git a/CYD-Klipper/src/core/printer_integration.hpp b/CYD-Klipper/src/core/printer_integration.hpp index def2719..540b212 100644 --- a/CYD-Klipper/src/core/printer_integration.hpp +++ b/CYD-Klipper/src/core/printer_integration.hpp @@ -106,14 +106,14 @@ typedef struct { } PrinterDataMinimal; typedef struct { - const char** macros; + char** macros; unsigned int count; bool success; } Macros; typedef struct { - const char** power_devices; - const bool* power_states; + char** power_devices; + bool* power_states; unsigned int count; bool success; } PowerDevices; @@ -125,8 +125,8 @@ typedef struct { } Files; typedef struct { - lv_event_ct_b set_label; - lv_event_ct_b open_panel; + lv_event_cb_t set_label; + lv_event_cb_t open_panel; } PrinterUiPanel; class BasePrinter @@ -156,7 +156,8 @@ class BasePrinter virtual int get_power_devices_count() = 0; virtual bool set_power_device_state(const char* device_name, bool state) = 0; virtual Files get_files() = 0; - virtual bool start_file(const char* file) = 0; + virtual bool start_file(const char* filename) = 0; + virtual unsigned char* get_32_32_png_image_thumbnail(const char* gcode_filename); virtual bool set_target_temperature(PrinterTemperatureDevice device, float temperature) = 0; BasePrinter(unsigned char index); diff --git a/CYD-Klipper/src/ui/ui_utils.cpp b/CYD-Klipper/src/ui/ui_utils.cpp index 013a13a..eff5efa 100644 --- a/CYD-Klipper/src/ui/ui_utils.cpp +++ b/CYD-Klipper/src/ui/ui_utils.cpp @@ -34,6 +34,17 @@ void destroy_event_user_data(lv_event_t * e){ lv_obj_del(obj); } +void destroy_event_free_data(lv_event_t * e) +{ + void* data = lv_event_get_user_data(e); + free(data); +} + +void on_destroy_free_data(lv_obj_t * element, void* ptr) +{ + lv_obj_add_event_cb(element, destroy_event_free_data, LV_EVENT_DELETE, ptr); +} + void lv_create_fullscreen_button_matrix_popup(lv_obj_t * root, lv_event_cb_t title, lv_button_column_t* columns, int column_count){ const auto full_panel_width = CYD_SCREEN_WIDTH_PX - CYD_SCREEN_GAP_PX * 3; const auto full_panel_inner_width = full_panel_width - CYD_SCREEN_GAP_PX * 2 - 4; diff --git a/CYD-Klipper/src/ui/ui_utils.h b/CYD-Klipper/src/ui/ui_utils.h index 66dd6fc..e50ead5 100644 --- a/CYD-Klipper/src/ui/ui_utils.h +++ b/CYD-Klipper/src/ui/ui_utils.h @@ -38,6 +38,7 @@ void lv_layout_flex_column(lv_obj_t* obj, lv_flex_align_t allign = LV_FLEX_ALIGN void lv_layout_flex_row(lv_obj_t* obj, lv_flex_align_t allign = LV_FLEX_ALIGN_START, lv_coord_t pad_column = CYD_SCREEN_GAP_PX, lv_coord_t pad_row = CYD_SCREEN_GAP_PX); void lv_create_fullscreen_button_matrix_popup(lv_obj_t * root, lv_event_cb_t title, lv_button_column_t* columns, int column_count); void destroy_event_user_data(lv_event_t * e); +void on_destroy_free_data(lv_obj_t * element, void* ptr); void lv_create_keyboard_text_entry(lv_event_cb_t keyboard_callback, const char* title = NULL, lv_keyboard_mode_t keyboard_mode = LV_KEYBOARD_MODE_NUMBER, lv_coord_t width = CYD_SCREEN_PANEL_WIDTH_PX / 2, uint8_t max_length = 3, const char* fill_text = "", bool contain_in_panel= true); void lv_create_custom_menu_entry(const char* label_text, lv_obj_t* object, lv_obj_t* root_panel, bool set_height = true, const char * comment = NULL); void lv_create_custom_menu_button(const char *label_text, lv_obj_t* root_panel, lv_event_cb_t on_click, const char *btn_text, void * user_data = NULL, const char * comment = NULL); From 6a9023eb8d269476658069247120a05159f53bc4 Mon Sep 17 00:00:00 2001 From: Sims <38142618+suchmememanyskill@users.noreply.github.com> Date: Thu, 24 Oct 2024 18:18:15 +0200 Subject: [PATCH 05/63] Implement klipper custom ui panels --- .../klipper/klipper_printer_integration.cpp | 13 +- .../klipper/klipper_printer_integration.hpp | 8 +- .../core/klipper/klipper_printer_panels.cpp | 185 ++++++++++++++++++ CYD-Klipper/src/core/printer_integration.hpp | 5 +- CYD-Klipper/src/ui/ui_utils.cpp | 2 +- CYD-Klipper/src/ui/ui_utils.h | 2 +- 6 files changed, 204 insertions(+), 11 deletions(-) create mode 100644 CYD-Klipper/src/core/klipper/klipper_printer_panels.cpp diff --git a/CYD-Klipper/src/core/klipper/klipper_printer_integration.cpp b/CYD-Klipper/src/core/klipper/klipper_printer_integration.cpp index 11e15f5..8709e2d 100644 --- a/CYD-Klipper/src/core/klipper/klipper_printer_integration.cpp +++ b/CYD-Klipper/src/core/klipper/klipper_printer_integration.cpp @@ -61,7 +61,7 @@ bool KlipperPrinter::send_gcode(const char *gcode, bool wait) bool KlipperPrinter::move_printer(const char* axis, float amount, bool relative) { if (!printer_data.homed_axis || printer_data.state == PrinterStatePrinting) - return true; + return false; char gcode[64]; const char* extra = (amount > 0) ? "+" : ""; @@ -86,6 +86,7 @@ bool KlipperPrinter::move_printer(const char* axis, float amount, bool relative) send_gcode(gcode); lock_absolute_relative_mode_swap = 2; + return true; } bool KlipperPrinter::execute_feature(PrinterFeatures feature) @@ -155,8 +156,9 @@ bool KlipperPrinter::execute_feature(PrinterFeatures feature) return send_gcode("M104 S0\nM140 S0"); default: LOG_F(("Unsupported printer feature %d", feature)); - return false; } + + return false; } bool KlipperPrinter::connect() @@ -453,6 +455,8 @@ PrinterDataMinimal KlipperPrinter::fetch_min() data.state = PrinterStateOffline; data.power_devices = get_power_devices_count(); } + + return data; } void KlipperPrinter::disconnect() @@ -686,8 +690,9 @@ bool KlipperPrinter::start_file(const char *filename) HTTPClient client; configure_http_client(client, "/printer/print/start?filename=" + urlEncode(filename), false, 1000); - int httpCode = client.POST(""); - LOG_F(("Print start: HTTP %d\n", httpCode)) + int http_code = client.POST(""); + LOG_F(("Print start: HTTP %d\n", http_code)) + return http_code == 200; } bool KlipperPrinter::set_target_temperature(PrinterTemperatureDevice device, float temperature) diff --git a/CYD-Klipper/src/core/klipper/klipper_printer_integration.hpp b/CYD-Klipper/src/core/klipper/klipper_printer_integration.hpp index 25c552b..445c652 100644 --- a/CYD-Klipper/src/core/klipper/klipper_printer_integration.hpp +++ b/CYD-Klipper/src/core/klipper/klipper_printer_integration.hpp @@ -2,16 +2,17 @@ #include "../printer_integration.hpp" -class KlipperPrinter : BasePrinter +class KlipperPrinter : public BasePrinter { private: unsigned char lock_absolute_relative_mode_swap{}; unsigned char klipper_request_consecutive_fail_count{}; unsigned int slicer_estimated_print_time_s{}; unsigned int last_slicer_time_query{}; - float gcode_offset[3]{}; public: + float gcode_offset[3]{}; + KlipperPrinter(int index) : BasePrinter(index) { supported_features = PrinterFeatureRestart @@ -28,6 +29,8 @@ class KlipperPrinter : BasePrinter supported_temperature_devices = PrinterTemperatureDeviceBed | PrinterTemperatureDeviceNozzle1; + + init_ui_panels(); } bool move_printer(const char* axis, float amount, bool relative); @@ -49,4 +52,5 @@ class KlipperPrinter : BasePrinter bool send_gcode(const char* gcode, bool wait = true); int get_slicer_time_estimate_s(); void configure_http_client(HTTPClient &client, String url_part, bool stream, int timeout); + void init_ui_panels(); }; \ No newline at end of file diff --git a/CYD-Klipper/src/core/klipper/klipper_printer_panels.cpp b/CYD-Klipper/src/core/klipper/klipper_printer_panels.cpp new file mode 100644 index 0000000..04226e1 --- /dev/null +++ b/CYD-Klipper/src/core/klipper/klipper_printer_panels.cpp @@ -0,0 +1,185 @@ +#include "klipper_printer_integration.hpp" +#include "lvgl.h" +#include "../../ui/ui_utils.h" +#include + + +static void set_fan_speed_text(lv_event_t * e) { + lv_obj_t * label = lv_event_get_target(e); + KlipperPrinter* printer = (KlipperPrinter*)get_current_printer(); // TODO: pass by ref + char data[16]; + sprintf(data, "Fan: %.0f%%", printer->printer_data.fan_speed * 100); + lv_label_set_text(label, data); +} + +static void set_fan_speed(lv_event_t * e){ + int speed = (int)lv_event_get_user_data(e); + KlipperPrinter* printer = (KlipperPrinter*)get_current_printer(); // TODO: pass by ref + char gcode[16]; + sprintf(gcode, "M106 S%d", speed); + printer->send_gcode(gcode); +} + +const char* fan_speeds[] = { "0%", "15%", "25%", "35%" }; +const int fan_speeds_values[] = { 0, 38, 64, 90 }; + +const char* fan_speeds_2[] = { "50%", "75%", "100%"}; +const int fan_speeds_values_2[] = { 128, 192, 255 }; + +lv_button_column_t fan_speed_columns[] = { + { set_fan_speed, fan_speeds, (const void**)fan_speeds_values, 4}, + { set_fan_speed, fan_speeds_2, (const void**)fan_speeds_values_2, 3} +}; + +static void set_zoffset_text(lv_event_t * e) { + lv_obj_t * label = lv_event_get_target(e); + KlipperPrinter* printer = (KlipperPrinter*)get_current_printer(); // TODO: pass by ref + char data[24]; + sprintf(data, "Z Offset: %.03f", printer->gcode_offset[2]); + lv_label_set_text(label, data); +} + +static void set_zoffset_text_ex(lv_event_t * e) { + lv_obj_t * label = lv_event_get_target(e); + KlipperPrinter* printer = (KlipperPrinter*)get_current_printer(); // TODO: pass by ref + char data[32]; + sprintf(data, "Z Offset: %.03f, Z: %.03f", printer->gcode_offset[2], printer->printer_data.position[2]); + lv_label_set_text(label, data); +} + +static void set_zoffset(lv_event_t * e){ + char* offset = (char*)lv_event_get_user_data(e); + KlipperPrinter* printer = (KlipperPrinter*)get_current_printer(); // TODO: pass by ref + + char gcode[48]; + sprintf(gcode, "SET_GCODE_OFFSET Z_ADJUST=%s MOVE=1", offset); + printer->send_gcode(gcode); +} + +static void set_z(lv_event_t * e){ + void* ptr = lv_event_get_user_data(e); + float value = *(float *)(&ptr); + KlipperPrinter* printer = (KlipperPrinter*)get_current_printer(); // TODO: pass by ref + + if (value < 0) { + printer->send_gcode("SET_GCODE_OFFSET Z=0 MOVE=1"); + return; + } + + printer->move_printer("Z", value, false); +} + +const char* zoffsets[] = { "-0.01", "-0.025", "-0.05", "-0.2" }; +const char* zoffsets_2[] = { "+0.01", "+0.025", "+0.05", "+0.2" }; +const char* zabs[] = { "Z=0", "Z=0.1", "Z=1", "Clear" }; +const float zabsvalues[] = { 0, 0.1f, 1.0f, -1.0f }; + +lv_button_column_t zoffset_columns[] = { + { set_zoffset, zoffsets, (const void**)zoffsets, 4}, + { set_zoffset, zoffsets_2, (const void**)zoffsets_2, 4}, + { set_z, zabs, (const void**)zabsvalues, 4} +}; + +static void set_speed_mult_text(lv_event_t * e){ + lv_obj_t * label = lv_event_get_target(e); + KlipperPrinter* printer = (KlipperPrinter*)get_current_printer(); // TODO: pass by ref + char data[16]; + sprintf(data, "Speed: %.0f%%", printer->printer_data.speed_mult * 100); + lv_label_set_text(label, data); +} + +static void set_speed_mult(lv_event_t * e){ + int speed = (int)lv_event_get_user_data(e); + KlipperPrinter* printer = (KlipperPrinter*)get_current_printer(); // TODO: pass by ref + char gcode[16]; + sprintf(gcode, "M220 S%d", speed); + printer->send_gcode(gcode); +} + +static void set_speed_mult_offset(lv_event_t * e){ + int speed = (int)lv_event_get_user_data(e); + KlipperPrinter* printer = (KlipperPrinter*)get_current_printer(); // TODO: pass by ref + float result = printer->printer_data.speed_mult * 100 + speed; + printer->printer_data.speed_mult = result / 100; + char gcode[16]; + sprintf(gcode, "M220 S%.0f", result); + printer->send_gcode(gcode); +} + +const char* speed_presets[] = { "50%", "100%", "150%", "200%" }; +const int speed_presets_values[] = { 50, 100, 150, 200 }; +const char* speed_presets_minus[] = { "-1%", "-5%", "-10%", "-25%" }; +const int speed_presets_minus_values[] = { -1, -5, -10, -25 }; +const char* speed_presets_plus[] = { "+1%", "+5%", "+10%", "+25%" }; +const int speed_presets_plus_values[] = { 1, 5, 10, 25 }; + +lv_button_column_t speed_mult_columns[] = { + { set_speed_mult, speed_presets, (const void**)speed_presets_values, 4}, + { set_speed_mult_offset, speed_presets_minus, (const void**)speed_presets_minus_values, 4}, + { set_speed_mult_offset, speed_presets_plus, (const void**)speed_presets_plus_values, 4} +}; + +static void set_extrude_mult_text(lv_event_t * e){ + lv_obj_t * label = lv_event_get_target(e); + KlipperPrinter* printer = (KlipperPrinter*)get_current_printer(); // TODO: pass by ref + char data[16]; + sprintf(data, "Flow: %.0f%%", printer->printer_data.extrude_mult * 100); + lv_label_set_text(label, data); +} + +static void set_extrude_mult(lv_event_t * e){ + int speed = (int)lv_event_get_user_data(e); + KlipperPrinter* printer = (KlipperPrinter*)get_current_printer(); // TODO: pass by ref + char gcode[16]; + sprintf(gcode, "M221 S%d", speed); + printer->send_gcode(gcode); +} + +static void set_extrude_mult_offset(lv_event_t * e){ + int speed = (int)lv_event_get_user_data(e); + KlipperPrinter* printer = (KlipperPrinter*)get_current_printer(); // TODO: pass by ref + float result = printer->printer_data.extrude_mult * 100 + speed; + printer->printer_data.extrude_mult = result / 100; + char gcode[16]; + sprintf(gcode, "M221 S%.0f", result); + printer->send_gcode(gcode); +} + +const char* extrude_presets[] = { "95%", "100%", "105%", "110%" }; +const int extrude_presets_values[] = { 95, 100, 105, 110 }; +const char* extrude_offset[] = { "+5%", "+1%", "-1%", "-5%" }; +const int extrude_offset_values[] = { 5, 1, -1, -5 }; + +lv_button_column_t extrude_mult_columns[] = { + { set_extrude_mult, extrude_presets, (const void**)extrude_presets_values, 4}, + { set_extrude_mult_offset, extrude_offset, (const void**)extrude_offset_values, 4} +}; + +static void open_fan_speed_panel(lv_event_t * e){ + lv_create_fullscreen_button_matrix_popup(lv_scr_act(), set_fan_speed_text, fan_speed_columns, 2); +} + +static void open_zoffset_panel(lv_event_t * e){ + lv_create_fullscreen_button_matrix_popup(lv_scr_act(), set_zoffset_text_ex, zoffset_columns, (get_current_printer()->printer_data.state == PrinterStateIdle) ? 3 : 2); +} + +static void open_speed_mult_panel(lv_event_t * e){ + lv_create_fullscreen_button_matrix_popup(lv_scr_act(), set_speed_mult_text, speed_mult_columns, 3); +} + +static void open_extrude_mult_panel(lv_event_t * e){ + lv_create_fullscreen_button_matrix_popup(lv_scr_act(), set_extrude_mult_text, extrude_mult_columns, 2); +} + +static PrinterUiPanel klipper_ui_panels[4] { + { .set_label = set_fan_speed_text, .open_panel = open_fan_speed_panel }, + { .set_label = set_zoffset_text, .open_panel = open_zoffset_panel }, + { .set_label = set_speed_mult_text, .open_panel = open_speed_mult_panel }, + { .set_label = set_extrude_mult_text, .open_panel = open_extrude_mult_panel } +}; + +void KlipperPrinter::init_ui_panels() +{ + custom_menus_count = 4; + custom_menus = klipper_ui_panels; +} \ No newline at end of file diff --git a/CYD-Klipper/src/core/printer_integration.hpp b/CYD-Klipper/src/core/printer_integration.hpp index 540b212..8847a9a 100644 --- a/CYD-Klipper/src/core/printer_integration.hpp +++ b/CYD-Klipper/src/core/printer_integration.hpp @@ -1,5 +1,4 @@ #pragma once -#include "lvgl.h" #include "../conf/global_config.h" #define BIT(x) 1 << x @@ -125,8 +124,8 @@ typedef struct { } Files; typedef struct { - lv_event_cb_t set_label; - lv_event_cb_t open_panel; + void* set_label; // type lv_event_cb_t + void* open_panel; // type lv_event_cb_t } PrinterUiPanel; class BasePrinter diff --git a/CYD-Klipper/src/ui/ui_utils.cpp b/CYD-Klipper/src/ui/ui_utils.cpp index eff5efa..12c9053 100644 --- a/CYD-Klipper/src/ui/ui_utils.cpp +++ b/CYD-Klipper/src/ui/ui_utils.cpp @@ -40,7 +40,7 @@ void destroy_event_free_data(lv_event_t * e) free(data); } -void on_destroy_free_data(lv_obj_t * element, void* ptr) +void lv_on_destroy_free_data(lv_obj_t * element, void* ptr) { lv_obj_add_event_cb(element, destroy_event_free_data, LV_EVENT_DELETE, ptr); } diff --git a/CYD-Klipper/src/ui/ui_utils.h b/CYD-Klipper/src/ui/ui_utils.h index e50ead5..32790b3 100644 --- a/CYD-Klipper/src/ui/ui_utils.h +++ b/CYD-Klipper/src/ui/ui_utils.h @@ -38,7 +38,7 @@ void lv_layout_flex_column(lv_obj_t* obj, lv_flex_align_t allign = LV_FLEX_ALIGN void lv_layout_flex_row(lv_obj_t* obj, lv_flex_align_t allign = LV_FLEX_ALIGN_START, lv_coord_t pad_column = CYD_SCREEN_GAP_PX, lv_coord_t pad_row = CYD_SCREEN_GAP_PX); void lv_create_fullscreen_button_matrix_popup(lv_obj_t * root, lv_event_cb_t title, lv_button_column_t* columns, int column_count); void destroy_event_user_data(lv_event_t * e); -void on_destroy_free_data(lv_obj_t * element, void* ptr); +void lv_on_destroy_free_data(lv_obj_t * element, void* ptr); void lv_create_keyboard_text_entry(lv_event_cb_t keyboard_callback, const char* title = NULL, lv_keyboard_mode_t keyboard_mode = LV_KEYBOARD_MODE_NUMBER, lv_coord_t width = CYD_SCREEN_PANEL_WIDTH_PX / 2, uint8_t max_length = 3, const char* fill_text = "", bool contain_in_panel= true); void lv_create_custom_menu_entry(const char* label_text, lv_obj_t* object, lv_obj_t* root_panel, bool set_height = true, const char * comment = NULL); void lv_create_custom_menu_button(const char *label_text, lv_obj_t* root_panel, lv_event_cb_t on_click, const char *btn_text, void * user_data = NULL, const char * comment = NULL); From 337a26be3db79a041db3cadc1cab9e37d24094fc Mon Sep 17 00:00:00 2001 From: suchmememanyskill <38142618+suchmememanyskill@users.noreply.github.com> Date: Thu, 24 Oct 2024 23:08:03 +0200 Subject: [PATCH 06/63] Start integration --- CYD-Klipper/src/core/data_setup.cpp | 318 +----------------- .../klipper/klipper_printer_integration.cpp | 1 + .../core/klipper/klipper_printer_panels.cpp | 21 +- CYD-Klipper/src/core/printer_integration.cpp | 5 + CYD-Klipper/src/core/printer_integration.hpp | 9 +- 5 files changed, 38 insertions(+), 316 deletions(-) diff --git a/CYD-Klipper/src/core/data_setup.cpp b/CYD-Klipper/src/core/data_setup.cpp index ee9955f..dc6d5a3 100644 --- a/CYD-Klipper/src/core/data_setup.cpp +++ b/CYD-Klipper/src/core/data_setup.cpp @@ -9,6 +9,7 @@ #include "http_client.h" #include "../ui/ui_utils.h" #include "macros_query.h" +#include "printer_integration.hpp" Printer printer = {0}; PrinterMinimal *printer_minimal; @@ -128,317 +129,34 @@ int last_slicer_time_query = -15000; void fetch_printer_data() { freeze_request_thread(); - PRINTER_CONFIG *config = get_current_printer_config(); - SETUP_HTTP_CLIENT("/printer/objects/query?extruder&heater_bed&toolhead&gcode_move&virtual_sdcard&print_stats&webhooks&fan&display_status") - int httpCode = client.GET(); - delay(10); - if (httpCode == 200) + if (get_current_printer_data()->state == PrinterStateOffline) { - int printer_state = printer.state; - - if (printer.state == PRINTER_STATE_OFFLINE) - { - printer.state = PRINTER_STATE_ERROR; - } - - klipper_request_consecutive_fail_count = 0; - JsonDocument doc; - deserializeJson(doc, client.getStream()); - auto status = doc["result"]["status"]; - bool emit_state_update = false; - - delay(10); - unfreeze_request_thread(); - freeze_render_thread(); - - if (status.containsKey("webhooks")) + if (!get_current_printer()->connect()) { - const char *state = status["webhooks"]["state"]; - const char *message = status["webhooks"]["state_message"]; - - if (strcmp(state, "ready") == 0 && printer.state == PRINTER_STATE_ERROR) - { - printer_state = PRINTER_STATE_IDLE; - } - else if ((strcmp(state, "shutdown") == 0 || strcmp(state, "error") == 0) && printer.state != PRINTER_STATE_ERROR) - { - printer_state = PRINTER_STATE_ERROR; - } - - if (printer.state_message == NULL || strcmp(printer.state_message, message)) - { - if (printer.state_message != NULL) - { - free(printer.state_message); - } - - printer.state_message = (char *)malloc(strlen(message) + 1); - strcpy(printer.state_message, message); - emit_state_update = true; - } - } - - if (printer_state != PRINTER_STATE_ERROR) - { - if (status.containsKey("extruder")) - { - printer.extruder_temp = status["extruder"]["temperature"]; - printer.extruder_target_temp = status["extruder"]["target"]; - bool can_extrude = status["extruder"]["can_extrude"]; - printer.pressure_advance = status["extruder"]["pressure_advance"]; - printer.smooth_time = status["extruder"]["smooth_time"]; - printer.can_extrude = can_extrude == true; - } - - if (status.containsKey("heater_bed")) - { - printer.bed_temp = status["heater_bed"]["temperature"]; - printer.bed_target_temp = status["heater_bed"]["target"]; - } - - if (status.containsKey("toolhead")) - { - const char *homed_axis = status["toolhead"]["homed_axes"]; - printer.homed_axis = strcmp(homed_axis, "xyz") == 0; - } - - if (status.containsKey("gcode_move")) - { - printer.position[0] = status["gcode_move"]["gcode_position"][0]; - printer.position[1] = status["gcode_move"]["gcode_position"][1]; - printer.position[2] = status["gcode_move"]["gcode_position"][2]; - printer.gcode_offset[0] = status["gcode_move"]["homing_origin"][0]; - printer.gcode_offset[1] = status["gcode_move"]["homing_origin"][1]; - printer.gcode_offset[2] = status["gcode_move"]["homing_origin"][2]; - bool absolute_coords = status["gcode_move"]["absolute_coordinates"]; - - if (lock_absolute_relative_mode_swap > 0) - { - lock_absolute_relative_mode_swap--; - } - else - { - printer.absolute_coords = absolute_coords == true; - } - - printer.speed_mult = status["gcode_move"]["speed_factor"]; - printer.extrude_mult = status["gcode_move"]["extrude_factor"]; - printer.feedrate_mm_per_s = status["gcode_move"]["speed"]; - printer.feedrate_mm_per_s /= 60; // convert mm/m to mm/s - } - - if (status.containsKey("fan")) - { - printer.fan_speed = status["fan"]["speed"]; - } - - if (status.containsKey("virtual_sdcard")) - { - printer.print_progress = status["virtual_sdcard"]["progress"]; - } - - if (status.containsKey("print_stats")) - { - const char *filename = status["print_stats"]["filename"]; - strcpy(filename_buff, filename == NULL ? "" : filename); - printer.print_filename = filename_buff; - printer.elapsed_time_s = status["print_stats"]["total_duration"]; - printer.printed_time_s = status["print_stats"]["print_duration"]; - printer.filament_used_mm = status["print_stats"]["filament_used"]; - printer.total_layers = status["print_stats"]["info"]["total_layer"]; - printer.current_layer = status["print_stats"]["info"]["current_layer"]; - - const char *state = status["print_stats"]["state"]; - - if (state == nullptr) - { - // Continue - } - else if (strcmp(state, "printing") == 0) - { - printer_state = PRINTER_STATE_PRINTING; - } - else if (strcmp(state, "paused") == 0) - { - printer_state = PRINTER_STATE_PAUSED; - } - else if (strcmp(state, "complete") == 0 || strcmp(state, "cancelled") == 0 || strcmp(state, "standby") == 0) - { - printer_state = PRINTER_STATE_IDLE; - } - } - - if (status.containsKey("display_status")) - { - printer.print_progress = status["display_status"]["progress"]; - const char* message = status["display_status"]["message"]; - - if (!global_config.disable_m117_messaging) - { - lv_create_popup_message(message, 10000); - } - } - - if (printer.state == PRINTER_STATE_PRINTING && printer.print_progress > 0) - { - float remaining_time_s_percentage = (printer.printed_time_s / printer.print_progress) - printer.printed_time_s; - float remaining_time_s_slicer = 0; - - if (printer.slicer_estimated_print_time_s > 0) - { - remaining_time_s_slicer = printer.slicer_estimated_print_time_s - printer.printed_time_s; - } - - if (remaining_time_s_slicer <= 0 || config->remaining_time_calc_mode == REMAINING_TIME_CALC_PERCENTAGE) - { - printer.remaining_time_s = remaining_time_s_percentage; - } - else if (config->remaining_time_calc_mode == REMAINING_TIME_CALC_INTERPOLATED) - { - printer.remaining_time_s = remaining_time_s_percentage * printer.print_progress + remaining_time_s_slicer * (1 - printer.print_progress); - } - else if (config->remaining_time_calc_mode == REMAINING_TIME_CALC_SLICER) - { - printer.remaining_time_s = remaining_time_s_slicer; - } - } - - if (printer.remaining_time_s < 0) - { - printer.remaining_time_s = 0; - } - - if (printer.state == PRINTER_STATE_IDLE) - { - printer.slicer_estimated_print_time_s = 0; - } - - lv_msg_send(DATA_PRINTER_DATA, &printer); - } - - if (printer.state != printer_state || emit_state_update) - { - printer.state = printer_state; - lv_msg_send(DATA_PRINTER_STATE, &printer); - } - - if (printer.state == PRINTER_STATE_PRINTING && millis() - last_slicer_time_query > 30000 && printer.slicer_estimated_print_time_s <= 0) - { - delay(10); - last_slicer_time_query = millis(); - printer.slicer_estimated_print_time_s = get_slicer_time_estimate_s(); + LOG_LN("Failed to connect to printer"); + unfreeze_request_thread(); + return; } - - unfreeze_render_thread(); } - else - { - unfreeze_request_thread(); - klipper_request_consecutive_fail_count++; - if (klipper_request_consecutive_fail_count == 5) - { - freeze_render_thread(); - printer.state = PRINTER_STATE_OFFLINE; - lv_msg_send(DATA_PRINTER_STATE, &printer); - unfreeze_render_thread(); - } + bool fetch_result = get_current_printer()->fetch(); + unfreeze_request_thread(); - LOG_F(("Failed to fetch printer data: %d\n", httpCode)) + freeze_render_thread(); + if (!fetch_result) + { + LOG_LN("Failed to fetch printer data") + get_current_printer()->disconnect(); } + + get_current_printer()->AnnouncePrinterData(); + unfreeze_render_thread(); } void fetch_printer_data_minimal() { - PrinterMinimal data[PRINTER_CONFIG_COUNT] = {0}; - - for (int i = 0; i < PRINTER_CONFIG_COUNT; i++){ - PRINTER_CONFIG *config = &global_config.printer_config[i]; - - if (!config->ip_configured) - { - data[i].state = PRINTER_STATE_OFFLINE; - continue; - } - - delay(10); - HTTPClient client; - configure_http_client(client, get_full_url("/printer/objects/query?webhooks&print_stats&virtual_sdcard", config), true, 1000, config); - freeze_request_thread(); - - int httpCode = client.GET(); - delay(10); - if (httpCode == 200) - { - if (data[i].state == PRINTER_STATE_OFFLINE) - { - data[i].state = PRINTER_STATE_ERROR; - } - - data[i].power_devices = power_devices_count(config); - JsonDocument doc; - deserializeJson(doc, client.getStream()); - auto status = doc["result"]["status"]; - - unfreeze_request_thread(); - - if (status.containsKey("webhooks")) - { - const char *state = status["webhooks"]["state"]; - - if (strcmp(state, "ready") == 0 && data[i].state == PRINTER_STATE_ERROR) - { - data[i].state = PRINTER_STATE_IDLE; - } - else if (strcmp(state, "shutdown") == 0 && data[i].state != PRINTER_STATE_ERROR) - { - data[i].state = PRINTER_STATE_ERROR; - } - } - - if (data[i].state != PRINTER_STATE_ERROR) - { - if (status.containsKey("virtual_sdcard")) - { - data[i].print_progress = status["virtual_sdcard"]["progress"]; - } - - if (status.containsKey("print_stats")) - { - const char *state = status["print_stats"]["state"]; - - if (state == nullptr) - { - data[i].state = PRINTER_STATE_ERROR; - } - else if (strcmp(state, "printing") == 0) - { - data[i].state = PRINTER_STATE_PRINTING; - } - else if (strcmp(state, "paused") == 0) - { - data[i].state = PRINTER_STATE_PAUSED; - } - else if (strcmp(state, "complete") == 0 || strcmp(state, "cancelled") == 0 || strcmp(state, "standby") == 0) - { - data[i].state = PRINTER_STATE_IDLE; - } - } - } - } - else - { - data[i].state = PRINTER_STATE_OFFLINE; - data[i].power_devices = power_devices_count(config); - unfreeze_request_thread(); - } - } - - freeze_render_thread(); - memcpy(printer_minimal, data, sizeof(PrinterMinimal) * PRINTER_CONFIG_COUNT); - lv_msg_send(DATA_PRINTER_MINIMAL, NULL); - unfreeze_render_thread(); + // TODO } void data_loop() @@ -468,7 +186,7 @@ TaskHandle_t background_loop; void data_setup() { - printer_minimal = (PrinterMinimal *)calloc(sizeof(PrinterMinimal), PRINTER_CONFIG_COUNT); + printer_minimal = (PrinterMinimal*)calloc(sizeof(PrinterMinimal), PRINTER_CONFIG_COUNT); semaphore_init(); printer.print_filename = filename_buff; fetch_printer_data(); diff --git a/CYD-Klipper/src/core/klipper/klipper_printer_integration.cpp b/CYD-Klipper/src/core/klipper/klipper_printer_integration.cpp index 8709e2d..657e27d 100644 --- a/CYD-Klipper/src/core/klipper/klipper_printer_integration.cpp +++ b/CYD-Klipper/src/core/klipper/klipper_printer_integration.cpp @@ -462,6 +462,7 @@ PrinterDataMinimal KlipperPrinter::fetch_min() void KlipperPrinter::disconnect() { // Nothing to disconnect, everything is http request based + printer_data.state = PrinterStateOffline; } Macros KlipperPrinter::get_macros() diff --git a/CYD-Klipper/src/core/klipper/klipper_printer_panels.cpp b/CYD-Klipper/src/core/klipper/klipper_printer_panels.cpp index 04226e1..b65bfb1 100644 --- a/CYD-Klipper/src/core/klipper/klipper_printer_panels.cpp +++ b/CYD-Klipper/src/core/klipper/klipper_printer_panels.cpp @@ -6,9 +6,8 @@ static void set_fan_speed_text(lv_event_t * e) { lv_obj_t * label = lv_event_get_target(e); - KlipperPrinter* printer = (KlipperPrinter*)get_current_printer(); // TODO: pass by ref char data[16]; - sprintf(data, "Fan: %.0f%%", printer->printer_data.fan_speed * 100); + sprintf(data, "Fan: %.0f%%", get_current_printer_data()->fan_speed * 100); lv_label_set_text(label, data); } @@ -43,7 +42,7 @@ static void set_zoffset_text_ex(lv_event_t * e) { lv_obj_t * label = lv_event_get_target(e); KlipperPrinter* printer = (KlipperPrinter*)get_current_printer(); // TODO: pass by ref char data[32]; - sprintf(data, "Z Offset: %.03f, Z: %.03f", printer->gcode_offset[2], printer->printer_data.position[2]); + sprintf(data, "Z Offset: %.03f, Z: %.03f", printer->gcode_offset[2], get_current_printer_data()->position[2]); lv_label_set_text(label, data); } @@ -82,9 +81,8 @@ lv_button_column_t zoffset_columns[] = { static void set_speed_mult_text(lv_event_t * e){ lv_obj_t * label = lv_event_get_target(e); - KlipperPrinter* printer = (KlipperPrinter*)get_current_printer(); // TODO: pass by ref char data[16]; - sprintf(data, "Speed: %.0f%%", printer->printer_data.speed_mult * 100); + sprintf(data, "Speed: %.0f%%", get_current_printer_data()->speed_mult * 100); lv_label_set_text(label, data); } @@ -99,8 +97,8 @@ static void set_speed_mult(lv_event_t * e){ static void set_speed_mult_offset(lv_event_t * e){ int speed = (int)lv_event_get_user_data(e); KlipperPrinter* printer = (KlipperPrinter*)get_current_printer(); // TODO: pass by ref - float result = printer->printer_data.speed_mult * 100 + speed; - printer->printer_data.speed_mult = result / 100; + float result = get_current_printer_data()->speed_mult * 100 + speed; + get_current_printer_data()->speed_mult = result / 100; char gcode[16]; sprintf(gcode, "M220 S%.0f", result); printer->send_gcode(gcode); @@ -121,9 +119,8 @@ lv_button_column_t speed_mult_columns[] = { static void set_extrude_mult_text(lv_event_t * e){ lv_obj_t * label = lv_event_get_target(e); - KlipperPrinter* printer = (KlipperPrinter*)get_current_printer(); // TODO: pass by ref char data[16]; - sprintf(data, "Flow: %.0f%%", printer->printer_data.extrude_mult * 100); + sprintf(data, "Flow: %.0f%%", get_current_printer_data()->extrude_mult * 100); lv_label_set_text(label, data); } @@ -138,8 +135,8 @@ static void set_extrude_mult(lv_event_t * e){ static void set_extrude_mult_offset(lv_event_t * e){ int speed = (int)lv_event_get_user_data(e); KlipperPrinter* printer = (KlipperPrinter*)get_current_printer(); // TODO: pass by ref - float result = printer->printer_data.extrude_mult * 100 + speed; - printer->printer_data.extrude_mult = result / 100; + float result = get_current_printer_data()->extrude_mult * 100 + speed; + get_current_printer_data()->extrude_mult = result / 100; char gcode[16]; sprintf(gcode, "M221 S%.0f", result); printer->send_gcode(gcode); @@ -160,7 +157,7 @@ static void open_fan_speed_panel(lv_event_t * e){ } static void open_zoffset_panel(lv_event_t * e){ - lv_create_fullscreen_button_matrix_popup(lv_scr_act(), set_zoffset_text_ex, zoffset_columns, (get_current_printer()->printer_data.state == PrinterStateIdle) ? 3 : 2); + lv_create_fullscreen_button_matrix_popup(lv_scr_act(), set_zoffset_text_ex, zoffset_columns, get_current_printer_data()->state == PrinterStateIdle ? 3 : 2); } static void open_speed_mult_panel(lv_event_t * e){ diff --git a/CYD-Klipper/src/core/printer_integration.cpp b/CYD-Klipper/src/core/printer_integration.cpp index da8cfb5..6fa2800 100644 --- a/CYD-Klipper/src/core/printer_integration.cpp +++ b/CYD-Klipper/src/core/printer_integration.cpp @@ -69,4 +69,9 @@ BasePrinter* get_current_printer() BasePrinter* get_printer(int idx) { return registered_printers + idx; +} + +PrinterData* get_current_printer_data() +{ + return printer_data_copy; } \ No newline at end of file diff --git a/CYD-Klipper/src/core/printer_integration.hpp b/CYD-Klipper/src/core/printer_integration.hpp index 8847a9a..249d6e8 100644 --- a/CYD-Klipper/src/core/printer_integration.hpp +++ b/CYD-Klipper/src/core/printer_integration.hpp @@ -132,14 +132,14 @@ class BasePrinter { protected: unsigned char config_index{}; + GLOBAL_CONFIG* global_config{}; + PrinterData printer_data{}; + PRINTER_CONFIG* printer_config{}; public: - PrinterData printer_data{}; PrinterFeatures supported_features{}; PrinterTemperatureDevice supported_temperature_devices{}; PrinterUiPanel* custom_menus{}; - PRINTER_CONFIG* printer_config{}; - GLOBAL_CONFIG* global_config{}; unsigned char custom_menus_count{}; virtual bool move_printer(const char* axis, float amount, bool relative) = 0; @@ -165,4 +165,5 @@ class BasePrinter BasePrinter* get_current_printer(); BasePrinter* get_printer(int idx); -void initialize_printers(); \ No newline at end of file +void initialize_printers(); +PrinterData* get_current_printer_data(); \ No newline at end of file From ec7e6f180ded67495e20790a0d38a6cf944cff8d Mon Sep 17 00:00:00 2001 From: Sims <38142618+suchmememanyskill@users.noreply.github.com> Date: Fri, 25 Oct 2024 08:28:26 +0200 Subject: [PATCH 07/63] Implement fetchdatamin --- CYD-Klipper/src/core/data_setup.cpp | 9 ++++++++- CYD-Klipper/src/core/printer_integration.cpp | 13 +++++++++++++ CYD-Klipper/src/core/printer_integration.hpp | 4 +++- 3 files changed, 24 insertions(+), 2 deletions(-) diff --git a/CYD-Klipper/src/core/data_setup.cpp b/CYD-Klipper/src/core/data_setup.cpp index dc6d5a3..38fd60f 100644 --- a/CYD-Klipper/src/core/data_setup.cpp +++ b/CYD-Klipper/src/core/data_setup.cpp @@ -156,7 +156,14 @@ void fetch_printer_data() void fetch_printer_data_minimal() { - // TODO + PrinterDataMinimal* data = (PrinterDataMinimal*)malloc(sizeof(PrinterDataMinimal) * get_printer_count()); + for (int i = 0; i < get_printer_count(); i++) + { + BasePrinter* printer = get_printer(i); + *(data + i) = printer->fetch_min(); + } + announce_printer_data_minimal(data); + free(data); } void data_loop() diff --git a/CYD-Klipper/src/core/printer_integration.cpp b/CYD-Klipper/src/core/printer_integration.cpp index 6fa2800..4f78e28 100644 --- a/CYD-Klipper/src/core/printer_integration.cpp +++ b/CYD-Klipper/src/core/printer_integration.cpp @@ -1,7 +1,9 @@ #include "printer_integration.hpp" unsigned char current_printer_index = 0; +unsigned char total_printers; BasePrinter* registered_printers; +PrinterDataMinimal* minimal_data_copy; PrinterData* printer_data_copy; BasePrinter::BasePrinter(unsigned char index) @@ -74,4 +76,15 @@ BasePrinter* get_printer(int idx) PrinterData* get_current_printer_data() { return printer_data_copy; +} + +unsigned int get_printer_count() +{ + return total_printers; +} + +void announce_printer_data_minimal(PrinterDataMinimal* printer_data) +{ + memcpy(printer_data_copy, printer_data, sizeof(PrinterDataMinimal) * total_printers); + lv_msg_send(DATA_PRINTER_MINIMAL, get_current_printer()); } \ No newline at end of file diff --git a/CYD-Klipper/src/core/printer_integration.hpp b/CYD-Klipper/src/core/printer_integration.hpp index 249d6e8..b2623d4 100644 --- a/CYD-Klipper/src/core/printer_integration.hpp +++ b/CYD-Klipper/src/core/printer_integration.hpp @@ -166,4 +166,6 @@ class BasePrinter BasePrinter* get_current_printer(); BasePrinter* get_printer(int idx); void initialize_printers(); -PrinterData* get_current_printer_data(); \ No newline at end of file +PrinterData* get_current_printer_data(); +unsigned int get_printer_count(); +void announce_printer_data_minimal(PrinterDataMinimal* printer_data); \ No newline at end of file From 309a6865a58577f705f4fb52d3c23f56d03547bc Mon Sep 17 00:00:00 2001 From: suchmememanyskill <38142618+suchmememanyskill@users.noreply.github.com> Date: Sun, 27 Oct 2024 00:06:37 +0200 Subject: [PATCH 08/63] More progress --- CYD-Klipper/.vscode/settings.json | 7 +- CYD-Klipper/src/conf/global_config.cpp | 14 +- CYD-Klipper/src/conf/global_config.h | 41 ++-- CYD-Klipper/src/core/data_setup.cpp | 103 +--------- CYD-Klipper/src/core/data_setup.h | 55 ------ CYD-Klipper/src/core/files_query.cpp | 113 ----------- CYD-Klipper/src/core/files_query.h | 23 --- CYD-Klipper/src/core/http_client.cpp | 32 --- CYD-Klipper/src/core/http_client.h | 10 - .../klipper/klipper_printer_integration.cpp | 4 +- CYD-Klipper/src/core/lv_setup.cpp | 5 +- CYD-Klipper/src/core/macros_query.cpp | 185 ------------------ CYD-Klipper/src/core/macros_query.h | 27 --- CYD-Klipper/src/core/printer_integration.cpp | 46 +++-- CYD-Klipper/src/core/printer_integration.hpp | 25 ++- CYD-Klipper/src/ui/macros.cpp | 79 +++++--- CYD-Klipper/src/ui/macros.h | 10 +- CYD-Klipper/src/ui/main_ui.cpp | 14 +- .../src/ui/panels/connecting_panel.cpp | 6 +- CYD-Klipper/src/ui/panels/error_panel.cpp | 13 +- CYD-Klipper/src/ui/panels/files_panel.cpp | 50 +++-- CYD-Klipper/src/ui/panels/macros_panel.cpp | 14 +- CYD-Klipper/src/ui/panels/move_panel.cpp | 37 ++-- CYD-Klipper/src/ui/panels/panel.h | 1 - CYD-Klipper/src/ui/panels/printer_panel.cpp | 136 ++++++------- CYD-Klipper/src/ui/switch_printer.cpp | 4 +- CYD-Klipper/src/ui/ui_utils.cpp | 4 +- CYD-Klipper/src/ui/ui_utils.h | 2 +- 28 files changed, 295 insertions(+), 765 deletions(-) delete mode 100644 CYD-Klipper/src/core/files_query.cpp delete mode 100644 CYD-Klipper/src/core/files_query.h delete mode 100644 CYD-Klipper/src/core/http_client.cpp delete mode 100644 CYD-Klipper/src/core/http_client.h delete mode 100644 CYD-Klipper/src/core/macros_query.cpp delete mode 100644 CYD-Klipper/src/core/macros_query.h diff --git a/CYD-Klipper/.vscode/settings.json b/CYD-Klipper/.vscode/settings.json index 0ddaeec..425aa19 100644 --- a/CYD-Klipper/.vscode/settings.json +++ b/CYD-Klipper/.vscode/settings.json @@ -15,7 +15,12 @@ "*.tcc": "cpp", "cmath": "cpp", "system_error": "cpp", - "random": "cpp" + "random": "cpp", + "optional": "cpp", + "limits": "cpp", + "memory": "cpp", + "new": "cpp", + "type_traits": "cpp" }, "cmake.configureOnOpen": false } \ No newline at end of file diff --git a/CYD-Klipper/src/conf/global_config.cpp b/CYD-Klipper/src/conf/global_config.cpp index 42cbf3c..613e635 100644 --- a/CYD-Klipper/src/conf/global_config.cpp +++ b/CYD-Klipper/src/conf/global_config.cpp @@ -2,10 +2,10 @@ #include "global_config.h" #include "lvgl.h" -GLOBAL_CONFIG global_config = {0}; -TEMPORARY_CONFIG temporary_config = {0}; +GlobalConfig global_config = {0}; +TemporaryConfig temporary_config = {0}; -COLOR_DEF color_defs[] = { +ColorDefinition color_defs[] = { {LV_PALETTE_BLUE, 0, LV_PALETTE_RED}, {LV_PALETTE_GREEN, 0, LV_PALETTE_PURPLE}, {LV_PALETTE_LIME, -2, LV_PALETTE_PURPLE}, @@ -30,7 +30,7 @@ void verify_version() if (!preferences.begin("global_config", false)) return; - GLOBAL_CONFIG config = {0}; + GlobalConfig config = {0}; preferences.getBytes("global_config", &config, sizeof(config)); LOG_F(("Config version: %d\n", config.version)) if (config.version != CONFIG_VERSION) { @@ -41,7 +41,7 @@ void verify_version() preferences.end(); } -PRINTER_CONFIG* get_current_printer_config() +PrinterConfiguration* get_current_printer_config() { return &global_config.printer_config[global_config.printer_index]; } @@ -70,8 +70,8 @@ void set_printer_config_index(int index) if (index < 0 || index >= PRINTER_CONFIG_COUNT) return; - PRINTER_CONFIG* old_config = &global_config.printer_config[global_config.printer_index]; - PRINTER_CONFIG* new_config = &global_config.printer_config[index]; + PrinterConfiguration* old_config = &global_config.printer_config[global_config.printer_index]; + PrinterConfiguration* new_config = &global_config.printer_config[index]; global_config.printer_index = index; diff --git a/CYD-Klipper/src/conf/global_config.h b/CYD-Klipper/src/conf/global_config.h index 8e6ac3b..c9a7c06 100644 --- a/CYD-Klipper/src/conf/global_config.h +++ b/CYD-Klipper/src/conf/global_config.h @@ -20,7 +20,14 @@ enum { SHOW_STATS_ON_PROGRESS_PANEL_ALL = 3, }; -typedef struct _PRINTER_CONFIG { +enum PrinterType { + PrinterTypeKlipper = 0, + PrinterTypeKlipperSerial = 1, + PrinterTypeBambu = 2, + PrinterTypeOctoprint = 3, +}; + +typedef struct { union { unsigned int raw; struct { @@ -35,6 +42,7 @@ typedef struct _PRINTER_CONFIG { unsigned char show_stats_on_progress_panel : 2; bool custom_filament_move_macros : 1; + PrinterType printer_type : 3; }; }; @@ -51,9 +59,9 @@ typedef struct _PRINTER_CONFIG { unsigned short printer_move_x_steps[3]; unsigned short printer_move_y_steps[3]; unsigned short printer_move_z_steps[3]; -} PRINTER_CONFIG; +} PrinterConfiguration; -typedef struct _GLOBAL_CONFIG { +typedef struct { unsigned char version; union { unsigned int raw; @@ -75,7 +83,7 @@ typedef struct _GLOBAL_CONFIG { }; }; - PRINTER_CONFIG printer_config[PRINTER_CONFIG_COUNT]; + PrinterConfiguration printer_config[PRINTER_CONFIG_COUNT]; float screen_cal_x_offset; float screen_cal_x_mult; @@ -88,24 +96,23 @@ typedef struct _GLOBAL_CONFIG { unsigned char brightness; unsigned char screen_timeout; unsigned char printer_index; -} GLOBAL_CONFIG; +} GlobalConfig; // Volatile/temporary config that doesn't survive a reset -typedef struct _TEMPORARY_CONFIG { +typedef struct { bool debug : 1; bool remote_echo : 1; -} TEMPORARY_CONFIG; +} TemporaryConfig; - -typedef struct _COLOR_DEF { +typedef struct { lv_palette_t primary_color; short primary_color_light; lv_palette_t secondary_color; -} COLOR_DEF; +} ColorDefinition; -extern GLOBAL_CONFIG global_config; -extern TEMPORARY_CONFIG temporary_config; -extern COLOR_DEF color_defs[]; +extern GlobalConfig global_config; +extern TemporaryConfig temporary_config; +extern ColorDefinition color_defs[]; #define LOG(x) if(temporary_config.debug){ Serial.print(x);} #define LOG_LN(x) if(temporary_config.debug){ Serial.println(x);} @@ -115,9 +122,9 @@ void write_global_config(); void verify_version(); void load_global_config(); -PRINTER_CONFIG* get_current_printer_config(); -int get_printer_config_count(); -void set_printer_config_index(int index); -int get_printer_config_free_index(); +//PRINTER_CONFIG* get_current_printer_config(); +//int get_printer_config_count(); +//void set_printer_config_index(int index); +//int get_printer_config_free_index(); #endif // !_GLOBAL_CONFIG_INIT \ No newline at end of file diff --git a/CYD-Klipper/src/core/data_setup.cpp b/CYD-Klipper/src/core/data_setup.cpp index 38fd60f..89053b5 100644 --- a/CYD-Klipper/src/core/data_setup.cpp +++ b/CYD-Klipper/src/core/data_setup.cpp @@ -1,23 +1,11 @@ #include "data_setup.h" -#include "lvgl.h" -#include "../conf/global_config.h" -#include #include -#include "macros_query.h" #include -#include "http_client.h" -#include "../ui/ui_utils.h" -#include "macros_query.h" #include "printer_integration.hpp" -Printer printer = {0}; -PrinterMinimal *printer_minimal; -int klipper_request_consecutive_fail_count = 999; -char filename_buff[512] = {0}; SemaphoreHandle_t freezeRenderThreadSemaphore, freezeRequestThreadSemaphore; const long data_update_interval = 780; -unsigned char lock_absolute_relative_mode_swap = 0; void semaphore_init(){ freezeRenderThreadSemaphore = xSemaphoreCreateMutex(); @@ -42,90 +30,6 @@ void unfreeze_render_thread(){ xSemaphoreGive(freezeRenderThreadSemaphore); } -void send_gcode(bool wait, const char *gcode) -{ - LOG_F(("Sending gcode: %s\n", gcode)) - - SETUP_HTTP_CLIENT_FULL("/printer/gcode/script?script=" + urlEncode(gcode), false, wait ? 5000 : 750); - try - { - client.GET(); - } - catch (...) - { - LOG_LN("Failed to send gcode"); - } -} - -void send_estop() -{ - LOG_LN("Sending estop"); - - SETUP_HTTP_CLIENT_FULL("/printer/emergency_stop", false, 5000); - try - { - client.GET(); - } - catch (...) - { - LOG_LN("Failed to send estop"); - } -} - -int get_slicer_time_estimate_s() -{ - if (printer.state == PRINTER_STATE_IDLE) - return 0; - - delay(10); - - SETUP_HTTP_CLIENT("/server/files/metadata?filename=" + urlEncode(printer.print_filename)); - - int httpCode = client.GET(); - - if (httpCode != 200) - return 0; - - JsonDocument doc; - deserializeJson(doc, client.getStream()); - int time_estimate_s = doc["result"]["estimated_time"]; - LOG_F(("Got slicer time estimate: %ds\n", time_estimate_s)) - return time_estimate_s; -} - -void move_printer(const char* axis, float amount, bool relative) { - if (!printer.homed_axis || printer.state == PRINTER_STATE_PRINTING) - return; - - char gcode[64]; - const char* extra = (amount > 0) ? "+" : ""; - const char* start = ""; - const char* end = ""; - - bool absolute_coords = printer.absolute_coords; - - if (absolute_coords && relative) { - start = "G91\n"; - } - else if (!absolute_coords && !relative) { - start = "G90\n"; - } - - if (absolute_coords && relative) { - end = "\nG90"; - } - else if (!absolute_coords && !relative) { - end = "\nG91"; - } - - sprintf(gcode, "%sG1 %s%s%.3f F6000%s", start, axis, extra, amount, end); - send_gcode(true, gcode); - - lock_absolute_relative_mode_swap = 2; -} - -int last_slicer_time_query = -15000; - void fetch_printer_data() { freeze_request_thread(); @@ -159,10 +63,14 @@ void fetch_printer_data_minimal() PrinterDataMinimal* data = (PrinterDataMinimal*)malloc(sizeof(PrinterDataMinimal) * get_printer_count()); for (int i = 0; i < get_printer_count(); i++) { + freeze_request_thread(); BasePrinter* printer = get_printer(i); + unfreeze_request_thread(); *(data + i) = printer->fetch_min(); } + freeze_render_thread(); announce_printer_data_minimal(data); + unfreeze_render_thread(); free(data); } @@ -193,11 +101,8 @@ TaskHandle_t background_loop; void data_setup() { - printer_minimal = (PrinterMinimal*)calloc(sizeof(PrinterMinimal), PRINTER_CONFIG_COUNT); semaphore_init(); - printer.print_filename = filename_buff; fetch_printer_data(); - freeze_render_thread(); xTaskCreatePinnedToCore(data_loop_background, "data_loop_background", 5000, NULL, 2, &background_loop, 0); } diff --git a/CYD-Klipper/src/core/data_setup.h b/CYD-Klipper/src/core/data_setup.h index d1fad06..6aebf01 100644 --- a/CYD-Klipper/src/core/data_setup.h +++ b/CYD-Klipper/src/core/data_setup.h @@ -1,62 +1,7 @@ #pragma once -enum { - PRINTER_STATE_OFFLINE = 0, - PRINTER_STATE_ERROR = 1, - PRINTER_STATE_IDLE = 2, - PRINTER_STATE_PRINTING = 3, - PRINTER_STATE_PAUSED = 4, -}; - -typedef struct _Printer { - unsigned char state; - char* state_message; - float extruder_temp; - float extruder_target_temp; - float bed_temp; - float bed_target_temp; - float position[3]; - unsigned char can_extrude; - unsigned char homed_axis; - unsigned char absolute_coords; - float elapsed_time_s; - float printed_time_s; - float remaining_time_s; - float filament_used_mm; - char* print_filename; - float print_progress; // 0 -> 1 - float fan_speed; // 0 -> 1 - float gcode_offset[3]; - float speed_mult; - float extrude_mult; - int total_layers; - int current_layer; - float pressure_advance; - float smooth_time; - int feedrate_mm_per_s; - int slicer_estimated_print_time_s; -} Printer; - -typedef struct _PrinterMinimal { - unsigned char state; - float print_progress; // 0 -> 1 - unsigned int power_devices; -} PrinterMinimal; - -extern Printer printer; -extern PrinterMinimal *printer_minimal; -extern int klipper_request_consecutive_fail_count; - -#define DATA_PRINTER_STATE 1 -#define DATA_PRINTER_DATA 2 -#define DATA_PRINTER_TEMP_PRESET 3 -#define DATA_PRINTER_MINIMAL 4 - void data_loop(); void data_setup(); -void send_estop(); -void send_gcode(bool wait, const char* gcode); -void move_printer(const char* axis, float amount, bool relative); void freeze_request_thread(); void unfreeze_request_thread(); \ No newline at end of file diff --git a/CYD-Klipper/src/core/files_query.cpp b/CYD-Klipper/src/core/files_query.cpp deleted file mode 100644 index e154ea9..0000000 --- a/CYD-Klipper/src/core/files_query.cpp +++ /dev/null @@ -1,113 +0,0 @@ -#include -#include "files_query.h" -#include "../conf/global_config.h" -#include "data_setup.h" -#include -#include -#include "http_client.h" - -// Always has +1 entry with a null'd name -FILESYSTEM_FILE* last_query = NULL; - -void clear_files() -{ - if (last_query != NULL){ - FILESYSTEM_FILE* current = last_query; - - while (current->name != NULL){ - free(current->name); - current += 1; - } - - free(last_query); - last_query = NULL; - } -} - -FILESYSTEM_FILE* get_files(int limit) -{ - freeze_request_thread(); - clear_files(); - - LOG_F(("Heap space pre-file-parse: %d bytes\n", esp_get_free_heap_size())) - std::list files; - - auto timer_request = millis(); - SETUP_HTTP_CLIENT_FULL("/server/files/list", true, 5000); - - int httpCode = client.GET(); - auto timer_parse = millis(); - - if (httpCode == 200){ - JsonDocument doc; - auto parseResult = deserializeJson(doc, client.getStream()); - LOG_F(("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++; - } - - if (file_iter == files.end() && files.size() >= limit) - continue; - - f.name = (char*)malloc(strlen(path) + 1); - if (f.name == NULL){ - LOG_LN("Failed to allocate memory"); - continue; - } - strcpy(f.name, path); - 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(); - } - } - } - - size_t size = sizeof(FILESYSTEM_FILE) * (files.size() + 1); - FILESYSTEM_FILE* result = (FILESYSTEM_FILE*)malloc(size); - - if (result == NULL){ - LOG_LN("Failed to allocate memory"); - - for (auto file : files){ - free(file.name); - } - - unfreeze_request_thread(); - return NULL; - } - - last_query = result; - result[files.size()].name = NULL; - - for (auto file : files){ - *result = file; - result += 1; - } - - LOG_F(("Heap space post-file-parse: %d bytes\n", esp_get_free_heap_size())) - LOG_F(("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 deleted file mode 100644 index 822cad8..0000000 --- a/CYD-Klipper/src/core/files_query.h +++ /dev/null @@ -1,23 +0,0 @@ -/* -At some point it may be a fun challenge to try to implement a virtual folder structure, but not today. - -typedef struct _FILESYSTEM_FILE { - char* name; - char* parent_folder_name; - long level; -} FILESYSTEM_FILE; - -typedef struct _FILESYSTEM_FOLDER { - char** files; - char* folder_path; - FILESYSTEM_FOLDER* folders; -} FILESYSTEM_FOLDER; -*/ - -typedef struct _FILESYSTEM_FILE { - char* name; - float modified; -} FILESYSTEM_FILE; - -FILESYSTEM_FILE* get_files(int limit); -void clear_files(); \ No newline at end of file diff --git a/CYD-Klipper/src/core/http_client.cpp b/CYD-Klipper/src/core/http_client.cpp deleted file mode 100644 index a27945b..0000000 --- a/CYD-Klipper/src/core/http_client.cpp +++ /dev/null @@ -1,32 +0,0 @@ -#include "http_client.h" - -String get_full_url(String url_part, PRINTER_CONFIG * config) -{ - if (config == NULL){ - config = get_current_printer_config(); - } - - return "http://" + String(config->klipper_host) + ":" + String(config->klipper_port) + url_part; -} - -void configure_http_client(HTTPClient &client, String url, bool stream, int timeout, PRINTER_CONFIG * config) -{ - if (config == NULL){ - config = get_current_printer_config(); - } - - if (stream){ - client.useHTTP10(true); - } - - if (timeout > 0){ - client.setTimeout(timeout); - client.setConnectTimeout(timeout); - } - - client.begin(url); - - if (config->auth_configured) { - client.addHeader("X-Api-Key", config->klipper_auth); - } -} \ No newline at end of file diff --git a/CYD-Klipper/src/core/http_client.h b/CYD-Klipper/src/core/http_client.h deleted file mode 100644 index 87ca30f..0000000 --- a/CYD-Klipper/src/core/http_client.h +++ /dev/null @@ -1,10 +0,0 @@ -#pragma once - -#include -#include "../conf/global_config.h" - -String get_full_url(String url_part, PRINTER_CONFIG * config = NULL); -void configure_http_client(HTTPClient &client, String url, bool stream = true, int timeout = 1000, PRINTER_CONFIG * config = NULL); - -#define SETUP_HTTP_CLIENT(url_part) HTTPClient client; configure_http_client(client, get_full_url(url_part)); -#define SETUP_HTTP_CLIENT_FULL(url_part, stream, timeout) HTTPClient client; configure_http_client(client, get_full_url(url_part), stream, timeout); \ No newline at end of file diff --git a/CYD-Klipper/src/core/klipper/klipper_printer_integration.cpp b/CYD-Klipper/src/core/klipper/klipper_printer_integration.cpp index 657e27d..017aed1 100644 --- a/CYD-Klipper/src/core/klipper/klipper_printer_integration.cpp +++ b/CYD-Klipper/src/core/klipper/klipper_printer_integration.cpp @@ -144,7 +144,7 @@ bool KlipperPrinter::execute_feature(PrinterFeatures feature) return false; } - if (get_current_printer_config()->custom_filament_move_macros) + if (get_current_printer()->printer_config->custom_filament_move_macros) { return send_gcode("FILAMENT_RETRACT"); } @@ -491,7 +491,7 @@ Macros KlipperPrinter::get_macros() } } - if (global_config->sort_macros) + if (global_config.sort_macros) { std::sort(macros.macros, macros.macros + macros.count, [](const char* a, const char* b) { return strcmp(a, b) < 0; diff --git a/CYD-Klipper/src/core/lv_setup.cpp b/CYD-Klipper/src/core/lv_setup.cpp index b3c7d55..c408dc8 100644 --- a/CYD-Klipper/src/core/lv_setup.cpp +++ b/CYD-Klipper/src/core/lv_setup.cpp @@ -5,6 +5,7 @@ #include "../ui/ui_utils.h" #include #include "../ui/serial/serial_console.h" +#include "printer_integration.hpp" #ifndef CPU_FREQ_HIGH #define CPU_FREQ_HIGH 240 @@ -254,10 +255,10 @@ void set_screen_timer_period() void set_color_scheme() { - PRINTER_CONFIG *config = get_current_printer_config(); + PrinterConfiguration *config = get_current_printer()->printer_config; lv_disp_t *dispp = lv_disp_get_default(); lv_color_t main_color = {0}; - COLOR_DEF color_def = color_defs[config->color_scheme]; + ColorDefinition color_def = color_defs[config->color_scheme]; if (color_defs[config->color_scheme].primary_color_light > 0){ main_color = lv_palette_lighten(color_def.primary_color, color_def.primary_color_light); diff --git a/CYD-Klipper/src/core/macros_query.cpp b/CYD-Klipper/src/core/macros_query.cpp deleted file mode 100644 index 958b3e7..0000000 --- a/CYD-Klipper/src/core/macros_query.cpp +++ /dev/null @@ -1,185 +0,0 @@ -#include "lvgl.h" -#include "macros_query.h" -#include "./data_setup.h" -#include -#include -#include "http_client.h" - -static char* macros[64] = {0}; -static int macros_count = 0; - -static char* power_devices[16] = {0}; -static bool power_device_states[16] = {0}; -static unsigned int stored_power_devices_count = 0; - -void macros_clear() -{ - for (int i = 0; i < macros_count; i++){ - free(macros[i]); - } - - macros_count = 0; -} - -MACROSQUERY macros_query(PRINTER_CONFIG * config) -{ - HTTPClient client; - configure_http_client(client, get_full_url("/printer/gcode/help", config), true, 1000); - - int httpCode = client.GET(); - - if (httpCode == 200){ - JsonDocument doc; - deserializeJson(doc, client.getStream()); - auto result = doc["result"].as(); - - macros_clear(); - - for (JsonPair i : result){ - const char *key = i.key().c_str(); - const char *value = i.value().as().c_str(); - if (strcmp(value, "CYD_SCREEN_MACRO") == 0) { - char* macro = (char*)malloc(strlen(key) + 1); - strcpy(macro, key); - macros[macros_count++] = macro; - } - } - - if (global_config.sort_macros) - { - std::sort(macros, macros + macros_count, [](const char* a, const char* b) { - return strcmp(a, b) < 0; - }); - } - - return {(const char**)macros, (unsigned int)macros_count}; - } - else { - return {NULL, 0}; - } -} - -MACROSQUERY macros_query() -{ - return macros_query(get_current_printer_config()); -} - -unsigned int macro_count(PRINTER_CONFIG * config) -{ - HTTPClient client; - configure_http_client(client, get_full_url("/printer/gcode/help", config), true, 1000); - - int httpCode = client.GET(); - - if (httpCode == 200){ - JsonDocument doc; - deserializeJson(doc, client.getStream()); - auto result = doc["result"].as(); - - unsigned int count = 0; - - for (JsonPair i : result){ - const char *value = i.value().as().c_str(); - if (strcmp(value, "CYD_SCREEN_MACRO") == 0) { - count++; - } - } - - return count; - } - else { - return 0; - } -} - -unsigned int macro_count() -{ - return macro_count(get_current_printer_config()); -} - -void power_devices_clear() -{ - for (int i = 0; i < stored_power_devices_count; i++){ - free(power_devices[i]); - } - - stored_power_devices_count = 0; -} - -POWERQUERY power_devices_query(PRINTER_CONFIG * config) -{ - HTTPClient client; - configure_http_client(client, get_full_url("/machine/device_power/devices", config), true, 1000); - - int httpCode = client.GET(); - - if (httpCode == 200){ - JsonDocument doc; - deserializeJson(doc, client.getStream()); - auto result = doc["result"]["devices"].as(); - - power_devices_clear(); - - for (auto i : result){ - const char * device_name = i["device"]; - const char * device_state = i["status"]; - power_devices[stored_power_devices_count] = (char*)malloc(strlen(device_name) + 1); - strcpy(power_devices[stored_power_devices_count], device_name); - power_device_states[stored_power_devices_count] = strcmp(device_state, "on") == 0; - stored_power_devices_count++; - } - - return {(const char**)power_devices, (const bool*)power_device_states, (unsigned int)stored_power_devices_count}; - } - else { - return {NULL, NULL, 0}; - } -} - -POWERQUERY power_devices_query() -{ - return power_devices_query(get_current_printer_config()); -} - -unsigned int power_devices_count(PRINTER_CONFIG * config) -{ - HTTPClient client; - configure_http_client(client, get_full_url("/machine/device_power/devices", config), true, 1000); - - int httpCode = client.GET(); - - if (httpCode == 200){ - JsonDocument doc; - deserializeJson(doc, client.getStream()); - auto result = doc["result"]["devices"].as(); - - unsigned int count = 0; - - for (auto i : result){ - count++; - } - - return count; - } - else { - return 0; - } -} - -unsigned int power_devices_count() -{ - return power_devices_count(get_current_printer_config()); -} - -bool set_power_state(const char* device_name, bool state, PRINTER_CONFIG * config) -{ - HTTPClient client; - configure_http_client(client, get_full_url("/machine/device_power/device?device=" + urlEncode(device_name) + "&action=" + (state ? "on" : "off"), config), true, 1000); - - return client.POST("") == 200; -} - -bool set_power_state(const char* device_name, bool state) -{ - return set_power_state(device_name, state, get_current_printer_config()); -} \ No newline at end of file diff --git a/CYD-Klipper/src/core/macros_query.h b/CYD-Klipper/src/core/macros_query.h deleted file mode 100644 index 9022cc5..0000000 --- a/CYD-Klipper/src/core/macros_query.h +++ /dev/null @@ -1,27 +0,0 @@ -#pragma once - -#include "../conf/global_config.h" - -typedef struct { - const char** macros; - uint32_t count; -} MACROSQUERY; - -typedef struct { - const char** power_devices; - const bool* power_states; - uint32_t count; -} POWERQUERY; - -MACROSQUERY macros_query(PRINTER_CONFIG * config); -MACROSQUERY macros_query(); -unsigned int macro_count(PRINTER_CONFIG * config); -unsigned int macro_count(); -POWERQUERY power_devices_query(PRINTER_CONFIG * config); -POWERQUERY power_devices_query(); -unsigned int power_devices_count(PRINTER_CONFIG * config); -unsigned int power_devices_count(); -bool set_power_state(const char* device_name, bool state, PRINTER_CONFIG * config); -bool set_power_state(const char* device_name, bool state); -void macros_clear(); -void power_devices_clear(); \ No newline at end of file diff --git a/CYD-Klipper/src/core/printer_integration.cpp b/CYD-Klipper/src/core/printer_integration.cpp index 4f78e28..725369c 100644 --- a/CYD-Klipper/src/core/printer_integration.cpp +++ b/CYD-Klipper/src/core/printer_integration.cpp @@ -1,4 +1,6 @@ #include "printer_integration.hpp" +#include "lv_setup.h" +#include "screen_driver.h" unsigned char current_printer_index = 0; unsigned char total_printers; @@ -20,12 +22,6 @@ BasePrinter::BasePrinter(unsigned char index) // TODO: Fetch printer config and global config } -#define DATA_PRINTER_STATE 1 -#define DATA_PRINTER_DATA 2 -#define DATA_PRINTER_TEMP_PRESET 3 -#define DATA_PRINTER_MINIMAL 4 -#define DATA_PRINTER_POPUP 5 - PrinterData* BasePrinter::AnnouncePrinterData() { char* old_state_message = printer_data_copy->state_message; @@ -37,11 +33,6 @@ PrinterData* BasePrinter::AnnouncePrinterData() if (old_state_message != printer_data_copy->state_message) { free(old_state_message); - lv_msg_send(DATA_PRINTER_STATE, get_current_printer()); - } - else if (printer_data.state != printer_data_copy->state) - { - lv_msg_send(DATA_PRINTER_STATE, get_current_printer()); } if (old_print_filename != printer_data_copy->print_filename) @@ -49,6 +40,11 @@ PrinterData* BasePrinter::AnnouncePrinterData() free(old_print_filename); } + if (printer_data.state != printer_data_copy->state) + { + lv_msg_send(DATA_PRINTER_STATE, get_current_printer()); + } + if (old_popup_message != printer_data_copy->popup_message) { free(old_popup_message); @@ -73,6 +69,11 @@ BasePrinter* get_printer(int idx) return registered_printers + idx; } +int get_current_printer_index() +{ + return current_printer_index; +} + PrinterData* get_current_printer_data() { return printer_data_copy; @@ -87,4 +88,27 @@ void announce_printer_data_minimal(PrinterDataMinimal* printer_data) { memcpy(printer_data_copy, printer_data, sizeof(PrinterDataMinimal) * total_printers); lv_msg_send(DATA_PRINTER_MINIMAL, get_current_printer()); +} + +PrinterDataMinimal* get_printer_data_minimal(int idx) +{ + return &(minimal_data_copy[idx]); +} + +void BasePrinter::save_printer_config() +{ + // TODO +} + + +void add_printer() +{ + +} + +void set_current_printer(int idx) +{ + //set_printer_config_index(index); + set_color_scheme(); + set_invert_display(); } \ No newline at end of file diff --git a/CYD-Klipper/src/core/printer_integration.hpp b/CYD-Klipper/src/core/printer_integration.hpp index b2623d4..06298d8 100644 --- a/CYD-Klipper/src/core/printer_integration.hpp +++ b/CYD-Klipper/src/core/printer_integration.hpp @@ -97,7 +97,7 @@ typedef struct _PrinterData { int feedrate_mm_per_s; } PrinterData; -typedef struct { +typedef struct { unsigned char state; float print_progress; // 0 -> 1 unsigned int power_devices; @@ -118,7 +118,7 @@ typedef struct { } PowerDevices; typedef struct { - const char** available_files; + char** available_files; unsigned int count; bool success; } Files; @@ -132,11 +132,10 @@ class BasePrinter { protected: unsigned char config_index{}; - GLOBAL_CONFIG* global_config{}; PrinterData printer_data{}; - PRINTER_CONFIG* printer_config{}; - + public: + PrinterConfiguration* printer_config{}; PrinterFeatures supported_features{}; PrinterTemperatureDevice supported_temperature_devices{}; PrinterUiPanel* custom_menus{}; @@ -148,12 +147,15 @@ class BasePrinter virtual bool fetch() = 0; virtual PrinterDataMinimal fetch_min() = 0; virtual void disconnect() = 0; + // Free macros externally when done virtual Macros get_macros() = 0; virtual int get_macros_count() = 0; virtual bool execute_macro(const char* macro) = 0; + // Free power devices externally when done virtual PowerDevices get_power_devices() = 0; virtual int get_power_devices_count() = 0; virtual bool set_power_device_state(const char* device_name, bool state) = 0; + // Free files externally when done virtual Files get_files() = 0; virtual bool start_file(const char* filename) = 0; virtual unsigned char* get_32_32_png_image_thumbnail(const char* gcode_filename); @@ -161,11 +163,22 @@ class BasePrinter BasePrinter(unsigned char index); PrinterData* AnnouncePrinterData(); + void save_printer_config(); }; +#define DATA_PRINTER_STATE 1 +#define DATA_PRINTER_DATA 2 +#define DATA_PRINTER_TEMP_PRESET 3 +#define DATA_PRINTER_MINIMAL 4 +#define DATA_PRINTER_POPUP 5 + BasePrinter* get_current_printer(); BasePrinter* get_printer(int idx); void initialize_printers(); PrinterData* get_current_printer_data(); unsigned int get_printer_count(); -void announce_printer_data_minimal(PrinterDataMinimal* printer_data); \ No newline at end of file +void announce_printer_data_minimal(PrinterDataMinimal* printer_data); +PrinterDataMinimal* get_printer_data_minimal(int idx); +int get_current_printer_index(); +void add_printer(); +void set_current_printer(int idx); \ No newline at end of file diff --git a/CYD-Klipper/src/ui/macros.cpp b/CYD-Klipper/src/ui/macros.cpp index 9338e8a..f0f90a9 100644 --- a/CYD-Klipper/src/ui/macros.cpp +++ b/CYD-Klipper/src/ui/macros.cpp @@ -3,52 +3,80 @@ #include #include "../core/data_setup.h" -PRINTER_CONFIG * curernt_config = NULL; +typedef struct { + const char* power_device_name; + BasePrinter* printer; +} DoubleStorage; -static void btn_press(lv_event_t * e){ +static void macro_run(lv_event_t * e){ lv_obj_t * btn = lv_event_get_target(e); const char* macro = (const char*)lv_event_get_user_data(e); LOG_F(("Macro: %s\n", macro)) - send_gcode(false, macro); + get_current_printer()->execute_macro(macro); } -void macros_add_macros_to_panel(lv_obj_t * root_panel, MACROSQUERY query) +int macros_add_macros_to_panel(lv_obj_t * root_panel, BasePrinter* printer) { - for (int i = 0; i < query.count; i++){ - const char* macro = query.macros[i]; - lv_create_custom_menu_button(macro, root_panel, btn_press, "Run", (void*)macro); + freeze_request_thread(); + Macros macros = printer->get_macros(); + unfreeze_request_thread(); + + if (!macros.success) + { + return 0; + } + + for (int i = 0; i < macros.count; i++) + { + const char* macro = macros.macros[i]; + lv_obj_on_destroy_free_data(root_panel, macro); + lv_create_custom_menu_button(macro, root_panel, macro_run, "Run", (void*)macro); } + + free(macros.macros); + return macros.count; } static void power_device_toggle(lv_event_t * e) { auto state = lv_obj_get_state(lv_event_get_target(e)); bool checked = (state & LV_STATE_CHECKED == LV_STATE_CHECKED); - const char* power_device_name = (const char*)lv_event_get_user_data(e); - LOG_F(("Power Device: %s, State: %d -> %d\n", power_device_name, !checked, checked)) + DoubleStorage* device = (DoubleStorage*)lv_event_get_user_data(e); + LOG_F(("Power Device: %s, State: %d -> %d\n", device->power_device_name, !checked, checked)) - if (curernt_config != NULL) - set_power_state(power_device_name, checked, curernt_config); + device->printer->set_power_device_state(device->power_device_name, checked); } -void macros_add_power_devices_to_panel(lv_obj_t * root_panel, POWERQUERY query) +int macros_add_power_devices_to_panel(lv_obj_t * root_panel, BasePrinter* printer) { - for (int i = 0; i < query.count; i++){ - const char* power_device_name = query.power_devices[i]; - const bool power_device_state = query.power_states[i]; - lv_create_custom_menu_switch(power_device_name, root_panel, power_device_toggle, power_device_state, (void*)power_device_name); + freeze_request_thread(); + PowerDevices devices = printer->get_power_devices(); + unfreeze_request_thread(); + + if (!devices.success) + { + return 0; } -} -void macros_set_current_config(PRINTER_CONFIG * config) -{ - curernt_config = config; + for (int i = 0; i < devices.count; i++) + { + const char* power_device_name = devices.power_devices[i]; + const bool power_device_state = devices.power_states[i]; + DoubleStorage* storage = (DoubleStorage*)malloc(sizeof(DoubleStorage)); + storage->printer = printer; + storage->power_device_name = power_device_name; + lv_obj_on_destroy_free_data(root_panel, storage); + lv_obj_on_destroy_free_data(root_panel, power_device_name); + lv_create_custom_menu_switch(power_device_name, root_panel, power_device_toggle, power_device_state, (void*)storage); + } + + free(devices.power_devices); + free(devices.power_states); + return devices.count; } -void macros_draw_power_fullscreen(PRINTER_CONFIG * config) +void macros_draw_power_fullscreen(BasePrinter* printer) { - macros_set_current_config(config); - lv_obj_t * parent = lv_create_empty_panel(lv_scr_act()); lv_obj_set_style_bg_opa(parent, LV_OPA_100, 0); lv_obj_align(parent, LV_ALIGN_TOP_RIGHT, 0, 0); @@ -67,11 +95,10 @@ void macros_draw_power_fullscreen(PRINTER_CONFIG * config) lv_label_set_text(label, LV_SYMBOL_CLOSE " Close"); lv_obj_center(label); - POWERQUERY power = power_devices_query(config); - macros_add_power_devices_to_panel(parent, power); + macros_add_power_devices_to_panel(parent, printer); } void macros_draw_power_fullscreen() { - macros_draw_power_fullscreen(get_current_printer_config()); + macros_draw_power_fullscreen(get_current_printer()); } \ No newline at end of file diff --git a/CYD-Klipper/src/ui/macros.h b/CYD-Klipper/src/ui/macros.h index 0e6b690..a41d90e 100644 --- a/CYD-Klipper/src/ui/macros.h +++ b/CYD-Klipper/src/ui/macros.h @@ -1,10 +1,10 @@ #pragma once #include "lvgl.h" -#include "../core/macros_query.h" +#include "../conf/global_config.h" +#include "../core/printer_integration.hpp" -void macros_add_macros_to_panel(lv_obj_t * root_panel, MACROSQUERY query); -void macros_add_power_devices_to_panel(lv_obj_t * root_panel, POWERQUERY query); -void macros_set_current_config(PRINTER_CONFIG * config); -void macros_draw_power_fullscreen(PRINTER_CONFIG * config); +int macros_add_macros_to_panel(lv_obj_t * root_panel, BasePrinter* printer); +int macros_add_power_devices_to_panel(lv_obj_t * root_panel, BasePrinter* printer); +void macros_draw_power_fullscreen(BasePrinter* printer); void macros_draw_power_fullscreen(); \ No newline at end of file diff --git a/CYD-Klipper/src/ui/main_ui.cpp b/CYD-Klipper/src/ui/main_ui.cpp index 3a081dc..9df1686 100644 --- a/CYD-Klipper/src/ui/main_ui.cpp +++ b/CYD-Klipper/src/ui/main_ui.cpp @@ -2,17 +2,17 @@ #include "../core/data_setup.h" #include "../conf/global_config.h" #include "../core/screen_driver.h" +#include "../core/printer_integration.hpp" #include "lvgl.h" #include "nav_buttons.h" #include "ui_utils.h" #include "panels/panel.h" -#include "../core/macros_query.h" #include "../core/lv_setup.h" #include "switch_printer.h" #include "macros.h" void check_if_screen_needs_to_be_disabled(){ - if (global_config.on_during_print && printer.state == PRINTER_STATE_PRINTING){ + if (global_config.on_during_print && get_current_printer_data()->state == PrinterState::PrinterStatePrinting){ screen_timer_wake(); screen_timer_stop(); } @@ -24,18 +24,22 @@ void check_if_screen_needs_to_be_disabled(){ static void on_state_change(void * s, lv_msg_t * m){ check_if_screen_needs_to_be_disabled(); - if (printer.state == PRINTER_STATE_OFFLINE){ + PrinterData* printer = get_current_printer_data(); + + if (printer->state == PrinterState::PrinterStateOffline){ nav_buttons_setup(PANEL_CONNECTING); } - else if (printer.state == PRINTER_STATE_ERROR){ + else if (printer->state == PrinterState::PrinterStateError){ nav_buttons_setup(PANEL_ERROR); } - else if (printer.state == PRINTER_STATE_IDLE) { + else if (printer->state == PrinterState::PrinterStateIdle) { nav_buttons_setup(PANEL_FILES); } else { nav_buttons_setup(PANEL_PROGRESS); } + + lv_msg_send(DATA_PRINTER_DATA, get_current_printer()); } void main_ui_setup(){ diff --git a/CYD-Klipper/src/ui/panels/connecting_panel.cpp b/CYD-Klipper/src/ui/panels/connecting_panel.cpp index d39b9d6..a182548 100644 --- a/CYD-Klipper/src/ui/panels/connecting_panel.cpp +++ b/CYD-Klipper/src/ui/panels/connecting_panel.cpp @@ -1,9 +1,11 @@ #include "panel.h" -#include "../../conf/global_config.h" +#include "../../core/printer_integration.hpp" void connecting_panel_init(lv_obj_t* panel) { lv_obj_t* label = lv_label_create(panel); - lv_label_set_text_fmt(label, "Connecting to %s...", (get_current_printer_config()->printer_name[0] == 0) ? get_current_printer_config()->klipper_host : get_current_printer_config()->printer_name); + lv_label_set_text_fmt(label, "Connecting to %s...", (get_current_printer()->printer_config->printer_name[0] == 0) + ? get_current_printer()->printer_config->klipper_host + : get_current_printer()->printer_config->printer_name); lv_obj_align(label, LV_ALIGN_CENTER, 0, 0); } \ No newline at end of file diff --git a/CYD-Klipper/src/ui/panels/error_panel.cpp b/CYD-Klipper/src/ui/panels/error_panel.cpp index d24e0c5..3641c4d 100644 --- a/CYD-Klipper/src/ui/panels/error_panel.cpp +++ b/CYD-Klipper/src/ui/panels/error_panel.cpp @@ -1,13 +1,19 @@ #include "panel.h" #include "../../core/data_setup.h" #include "../ui_utils.h" +#include "../../core/printer_integration.hpp" static void btn_click_restart(lv_event_t * e){ - send_gcode(false, "RESTART"); + get_current_printer()->execute_feature(PrinterFeatureRestart); } static void btn_click_firmware_restart(lv_event_t * e){ - send_gcode(false, "FIRMWARE_RESTART"); + get_current_printer()->execute_feature(PrinterFeatureFirmwareRestart); +} + +static void set_state_message_text(lv_event_t * e) { + lv_obj_t * label = lv_event_get_target(e); + lv_label_set_text(label, get_current_printer_data()->state_message); } void error_panel_init(lv_obj_t* panel) @@ -25,9 +31,10 @@ void error_panel_init(lv_obj_t* panel) lv_obj_set_width(panel_with_text, CYD_SCREEN_PANEL_WIDTH_PX - CYD_SCREEN_GAP_PX * 2); label = lv_label_create(panel_with_text); - lv_label_set_text(label, printer.state_message); lv_obj_set_width(label, CYD_SCREEN_PANEL_WIDTH_PX - CYD_SCREEN_GAP_PX * 2); lv_label_set_long_mode(label, LV_LABEL_LONG_WRAP); + lv_obj_add_event_cb(label, set_state_message_text, LV_EVENT_MSG_RECEIVED, NULL); + lv_msg_subscribe_obj(DATA_PRINTER_DATA, label, NULL); lv_obj_t * button_row = lv_create_empty_panel(panel); lv_obj_set_size(button_row, CYD_SCREEN_PANEL_WIDTH_PX - CYD_SCREEN_GAP_PX * 2, CYD_SCREEN_MIN_BUTTON_HEIGHT_PX); diff --git a/CYD-Klipper/src/ui/panels/files_panel.cpp b/CYD-Klipper/src/ui/panels/files_panel.cpp index fe22a56..b6c29a5 100644 --- a/CYD-Klipper/src/ui/panels/files_panel.cpp +++ b/CYD-Klipper/src/ui/panels/files_panel.cpp @@ -1,36 +1,33 @@ #include "lvgl.h" #include "panel.h" + #include "../../core/data_setup.h" -#include "../../core/files_query.h" #include "../../conf/global_config.h" #include #include "../ui_utils.h" #include "../../core/lv_setup.h" #include "../gcode_img.h" -#include "../../core/http_client.h" #include +#include "../../core/printer_integration.hpp" -FILESYSTEM_FILE* selected_file = NULL; +const char* selected_file = NULL; static void btn_print_file(lv_event_t * e){ lv_obj_t * panel = (lv_obj_t*)lv_event_get_user_data(e); lv_obj_del(panel); - SETUP_HTTP_CLIENT("/printer/print/start?filename=" + urlEncode(selected_file->name)); - - int httpCode = client.POST(""); - LOG_F(("Print start: HTTP %d\n", httpCode)) + get_current_printer()->start_file(selected_file); } static void btn_print_file_verify(lv_event_t * e){ - if (printer.state != PRINTER_STATE_IDLE){ + if (get_current_printer_data()->state != PrinterState::PrinterStateIdle){ return; } const auto button_size_mult = 1.3f; lv_obj_t * btn = lv_event_get_target(e); - selected_file = (FILESYSTEM_FILE*)lv_event_get_user_data(e); + selected_file = (char*)lv_event_get_user_data(e); lv_obj_t * panel = lv_obj_create(lv_scr_act()); lv_obj_set_style_pad_all(panel, CYD_SCREEN_GAP_PX * 2, 0); @@ -42,7 +39,7 @@ static void btn_print_file_verify(lv_event_t * e){ lv_obj_align(label_print_file, LV_ALIGN_TOP_LEFT, 0, 0); lv_obj_t * label = lv_label_create(panel); - lv_label_set_text(label, selected_file->name); + lv_label_set_text(label, selected_file); lv_obj_align(label, LV_ALIGN_CENTER, 0, -20); lv_obj_set_width(label, CYD_SCREEN_WIDTH_PX - CYD_SCREEN_GAP_PX * 10); lv_label_set_long_mode(label, LV_LABEL_LONG_WRAP); @@ -65,7 +62,7 @@ static void btn_print_file_verify(lv_event_t * e){ lv_label_set_text(label, LV_SYMBOL_OK); lv_obj_center(label); - lv_obj_t* img = show_gcode_img(selected_file->name); + lv_obj_t* img = show_gcode_img(selected_file); if (img != NULL){ lv_obj_set_parent(img, panel); @@ -81,7 +78,14 @@ static void btn_print_file_verify(lv_event_t * e){ } void files_panel_init(lv_obj_t* panel){ - clear_img_mem(); + Files files = get_current_printer()->get_files(); + + if (!files.success || files.count <= 0){ + 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); + return; + } lv_obj_t * list = lv_list_create(panel); lv_obj_set_style_radius(list, 0, 0); @@ -90,25 +94,19 @@ void files_panel_init(lv_obj_t* panel){ lv_obj_set_size(list, CYD_SCREEN_PANEL_WIDTH_PX, CYD_SCREEN_PANEL_HEIGHT_PX); lv_obj_align(list, LV_ALIGN_CENTER, 0, 0); - FILESYSTEM_FILE* files = get_files(25); - int count = 0; - while (files != NULL && files->name != NULL && count <= 20){ - lv_obj_t * btn = lv_list_add_btn(list, LV_SYMBOL_FILE, files->name); + for (int i = 0; i < files.count; i++) + { + lv_obj_t * btn = lv_list_add_btn(list, LV_SYMBOL_FILE, files.available_files[i]); lv_obj_set_style_bg_opa(btn, LV_OPA_TRANSP, 0); if (global_config.full_filenames){ lv_label_set_long_mode(lv_obj_get_child(btn, 1), LV_LABEL_LONG_WRAP); } - lv_obj_add_event_cb(btn, btn_print_file_verify, LV_EVENT_CLICKED, (void*)files); - - files += 1; - count++; + lv_obj_add_event_cb(btn, btn_print_file_verify, LV_EVENT_CLICKED, (void*)(files.available_files[i])); + lv_obj_on_destroy_free_data(btn, files.available_files[i]); } - 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); - } + // Not deallocating filenames in this scope will cause double allocation, oh well. + // TODO: read label text + free(files.available_files); } \ No newline at end of file diff --git a/CYD-Klipper/src/ui/panels/macros_panel.cpp b/CYD-Klipper/src/ui/panels/macros_panel.cpp index f48d935..ef7b762 100644 --- a/CYD-Klipper/src/ui/panels/macros_panel.cpp +++ b/CYD-Klipper/src/ui/panels/macros_panel.cpp @@ -11,8 +11,6 @@ static void btn_goto_settings(lv_event_t * e){ } void macros_panel_init(lv_obj_t* panel) { - macros_set_current_config(get_current_printer_config()); - lv_obj_t * btn = lv_btn_create(panel); lv_obj_add_event_cb(btn, btn_goto_settings, LV_EVENT_CLICKED, NULL); lv_obj_set_size(btn, CYD_SCREEN_PANEL_WIDTH_PX - CYD_SCREEN_GAP_PX * 2, CYD_SCREEN_MIN_BUTTON_HEIGHT_PX); @@ -22,27 +20,23 @@ void macros_panel_init(lv_obj_t* panel) { lv_label_set_text(label, LV_SYMBOL_SETTINGS " Screen Settings"); lv_obj_center(label); - MACROSQUERY macros = macros_query(); - POWERQUERY power = power_devices_query(); - lv_obj_t * root_panel = lv_create_empty_panel(panel); lv_obj_set_scrollbar_mode(root_panel, LV_SCROLLBAR_MODE_OFF); lv_obj_set_size(root_panel, CYD_SCREEN_PANEL_WIDTH_PX, CYD_SCREEN_PANEL_HEIGHT_PX - CYD_SCREEN_MIN_BUTTON_HEIGHT_PX - CYD_SCREEN_GAP_PX * 2); lv_obj_align(root_panel, LV_ALIGN_TOP_MID, 0, CYD_SCREEN_MIN_BUTTON_HEIGHT_PX + CYD_SCREEN_GAP_PX * 2); lv_layout_flex_column(root_panel); - macros_add_power_devices_to_panel(root_panel, power); + int power_count = macros_add_power_devices_to_panel(root_panel, get_current_printer()); + int macros_count = macros_add_macros_to_panel(root_panel, get_current_printer()); - if (macros.count == 0){ + if (macros_count <= 0){ label = lv_label_create(root_panel); lv_label_set_text(label, "No macros found.\nMacros with the description\n\"CYD_SCREEN_MACRO\"\nwill show up here."); - if (power.count == 0){ + if (power_count <= 0){ lv_layout_flex_column(root_panel, LV_FLEX_ALIGN_CENTER); } return; } - - macros_add_macros_to_panel(root_panel, macros); } \ No newline at end of file diff --git a/CYD-Klipper/src/ui/panels/move_panel.cpp b/CYD-Klipper/src/ui/panels/move_panel.cpp index 0c24c05..55ffe6e 100644 --- a/CYD-Klipper/src/ui/panels/move_panel.cpp +++ b/CYD-Klipper/src/ui/panels/move_panel.cpp @@ -5,6 +5,7 @@ #include "../ui_utils.h" #include #include +#include "../../core/printer_integration.hpp" static bool last_homing_state = false; static bool move_edit_mode = false; @@ -21,7 +22,7 @@ char z_offset_labels[6 * OFFSET_LABEL_SIZE] = {0}; static void calculate_offsets_from_current_printer() { - unsigned short* items[] = {get_current_printer_config()->printer_move_x_steps, get_current_printer_config()->printer_move_y_steps, get_current_printer_config()->printer_move_z_steps}; + unsigned short* items[] = {get_current_printer()->printer_config->printer_move_x_steps, get_current_printer()->printer_config->printer_move_y_steps, get_current_printer()->printer_config->printer_move_z_steps}; float* offsets[] = {(float*)x_offsets, (float*)y_offsets, (float*)z_offsets}; char * labels[] = {(char*)x_offset_labels, (char*)y_offset_labels, (char*)z_offset_labels}; @@ -74,7 +75,7 @@ static void keyboard_cb_edit_move_increment(lv_event_t * e) return; } - unsigned short* items[] = {get_current_printer_config()->printer_move_x_steps, get_current_printer_config()->printer_move_y_steps, get_current_printer_config()->printer_move_z_steps}; + unsigned short* items[] = {get_current_printer()->printer_config->printer_move_x_steps, get_current_printer()->printer_config->printer_move_y_steps, get_current_printer()->printer_config->printer_move_z_steps}; LOG_F(("Setting increment %d %d %f\n", selected_column, selected_row, increment)) items[selected_column][selected_row] = increment * 10; write_global_config(); @@ -109,7 +110,7 @@ static void x_line_button_press(lv_event_t * e) { } float data = *data_pointer; - move_printer("X", data, true); + get_current_printer()->move_printer("X", data, true); } static void y_line_button_press(lv_event_t * e) { @@ -122,7 +123,7 @@ static void y_line_button_press(lv_event_t * e) { } float data = *data_pointer; - move_printer("Y", data, true); + get_current_printer()->move_printer("Y", data, true); } static void z_line_button_press(lv_event_t * e) { @@ -135,27 +136,27 @@ static void z_line_button_press(lv_event_t * e) { } float data = *data_pointer; - move_printer("Z", data, true); + get_current_printer()->move_printer("Z", data, true); } static void x_pos_update(lv_event_t * e){ lv_obj_t * label = lv_event_get_target(e); char x_pos_buff[12]; - sprintf(x_pos_buff, "X: %.1f", printer.position[0]); + sprintf(x_pos_buff, "X: %.1f", get_current_printer_data()->position[0]); lv_label_set_text(label, x_pos_buff); } static void y_pos_update(lv_event_t * e){ lv_obj_t * label = lv_event_get_target(e); char y_pos_buff[12]; - sprintf(y_pos_buff, "Y: %.1f", printer.position[1]); + sprintf(y_pos_buff, "Y: %.1f", get_current_printer_data()->position[1]); lv_label_set_text(label, y_pos_buff); } static void z_pos_update(lv_event_t * e){ lv_obj_t * label = lv_event_get_target(e); char z_pos_buff[12]; - sprintf(z_pos_buff, "Z: %.2f", printer.position[2]); + sprintf(z_pos_buff, "Z: %.2f", get_current_printer_data()->position[2]); lv_label_set_text(label, z_pos_buff); } @@ -163,17 +164,17 @@ lv_event_cb_t button_callbacks[] = {x_line_button_press, y_line_button_press, z_ lv_event_cb_t position_callbacks[] = {x_pos_update, y_pos_update, z_pos_update}; static void home_button_click(lv_event_t * e) { - if (printer.state == PRINTER_STATE_PRINTING) + if (get_current_printer_data()->state == PrinterState::PrinterStatePrinting) return; - send_gcode(false, "G28"); + get_current_printer()->execute_feature(PrinterFeatures::PrinterFeatureHome); } static void disable_steppers_click(lv_event_t * e) { - if (printer.state == PRINTER_STATE_PRINTING) + if (get_current_printer_data()->state == PrinterState::PrinterStatePrinting) return; - send_gcode(true, "M18"); + get_current_printer()->execute_feature(PrinterFeatures::PrinterFeatureDisableSteppers); } static void switch_to_stat_panel(lv_event_t * e) { @@ -194,7 +195,7 @@ static void line_custom_set(const char * axis, const char *text) if (pos < 0 || pos > 500) return; - move_printer(axis, pos, false); + get_current_printer()->move_printer(axis, pos, false); } static void x_line_custom_callback(lv_event_t * e) { @@ -339,28 +340,28 @@ inline void root_panel_steppers_unlocked(lv_obj_t * root_panel){ } static void root_panel_state_update(lv_event_t * e){ - if (last_homing_state == printer.homed_axis) + if (last_homing_state == get_current_printer_data()->homed_axis) return; lv_obj_t * panel = lv_event_get_target(e); - last_homing_state = printer.homed_axis; + last_homing_state = get_current_printer_data()->homed_axis; lv_obj_clean(panel); - if (printer.homed_axis) + if (get_current_printer_data()->homed_axis) root_panel_steppers_locked(panel); else root_panel_steppers_unlocked(panel); } void move_panel_init(lv_obj_t* panel){ - if (printer.state == PRINTER_STATE_PRINTING){ + if (get_current_printer_data()->state == PrinterState::PrinterStatePrinting){ stats_panel_init(panel); return; } calculate_offsets_from_current_printer(); - last_homing_state = !printer.homed_axis; + last_homing_state = !get_current_printer_data()->homed_axis; lv_obj_add_event_cb(panel, root_panel_state_update, LV_EVENT_MSG_RECEIVED, NULL); lv_msg_subsribe_obj(DATA_PRINTER_DATA, panel, NULL); diff --git a/CYD-Klipper/src/ui/panels/panel.h b/CYD-Klipper/src/ui/panels/panel.h index 7c3c283..ef8b27e 100644 --- a/CYD-Klipper/src/ui/panels/panel.h +++ b/CYD-Klipper/src/ui/panels/panel.h @@ -1,5 +1,4 @@ #include "lvgl.h" -#include "../../core/macros_query.h" #define SIZEOF(arr) (sizeof(arr) / sizeof(*arr)) diff --git a/CYD-Klipper/src/ui/panels/printer_panel.cpp b/CYD-Klipper/src/ui/panels/printer_panel.cpp index 19a29d2..b048437 100644 --- a/CYD-Klipper/src/ui/panels/printer_panel.cpp +++ b/CYD-Klipper/src/ui/panels/printer_panel.cpp @@ -5,7 +5,6 @@ #include "../../core/lv_setup.h" #include #include "../nav_buttons.h" -#include "../../core/macros_query.h" #include "../switch_printer.h" #include "../macros.h" @@ -22,41 +21,32 @@ const static lv_point_t line_points[] = { {0, 0}, {(short int)((CYD_SCREEN_PANEL static void update_printer_name_text(lv_event_t * e) { lv_obj_t * label = lv_event_get_target(e); - PRINTER_CONFIG * config = (PRINTER_CONFIG*)lv_event_get_user_data(e); - int index = config - global_config.printer_config; - PrinterMinimal * printer = &printer_minimal[index]; - - lv_label_set_text(label, config->printer_name[0] == 0 ? config->klipper_host : config->printer_name); + int config_index = (int)lv_event_get_user_data(e); + BasePrinter* printer = get_printer(config_index); + lv_label_set_text(label, printer->printer_config->printer_name[0] == 0 ? printer->printer_config->klipper_host : printer->printer_config->printer_name); } static void update_printer_status_text(lv_event_t * e) { lv_obj_t * label = lv_event_get_target(e); - PRINTER_CONFIG * config = (PRINTER_CONFIG*)lv_event_get_user_data(e); - int index = config - global_config.printer_config; - PrinterMinimal * printer = &printer_minimal[index]; + int config_index = (int)lv_event_get_user_data(e); + PrinterDataMinimal* printer = get_printer_data_minimal(config_index); - if (config == get_current_printer_config()) + if (config_index == get_current_printer_index()) { lv_label_set_text(label, "In Control"); return; } - if (printer->state == PRINTER_STATE_OFFLINE) - { - lv_label_set_text(label, "Offline"); - return; - } - lv_label_set_text(label, printer_status[printer->state]); } static void update_printer_label_visible_active_printer(lv_event_t * e) { lv_obj_t * label = lv_event_get_target(e); - PRINTER_CONFIG * config = (PRINTER_CONFIG*)lv_event_get_user_data(e); + int config_index = (int)lv_event_get_user_data(e); - if (config == get_current_printer_config()) + if (config_index == get_current_printer_index()) { lv_label_set_text(label, LV_SYMBOL_WIFI); } @@ -69,14 +59,15 @@ static void update_printer_label_visible_active_printer(lv_event_t * e) static void update_printer_percentage_bar(lv_event_t * e) { lv_obj_t * percentage = lv_event_get_target(e); - PRINTER_CONFIG * config = (PRINTER_CONFIG*)lv_event_get_user_data(e); - int index = config - global_config.printer_config; - PrinterMinimal * printer = &printer_minimal[index]; + int config_index = (int)lv_event_get_user_data(e); + PrinterDataMinimal* printer = get_printer_data_minimal(config_index); - if (printer->state != PRINTER_STATE_OFFLINE && (printer->state == PRINTER_STATE_PRINTING || printer->state == PRINTER_STATE_PAUSED)){ + if (printer->state == PrinterState::PrinterStatePrinting || printer->state == PrinterState::PrinterStatePaused) + { lv_bar_set_value(percentage, printer->print_progress * 100, LV_ANIM_OFF); } - else { + else + { lv_bar_set_value(percentage, 0, LV_ANIM_OFF); } } @@ -84,11 +75,10 @@ static void update_printer_percentage_bar(lv_event_t * e) static void update_printer_percentage_text(lv_event_t * e) { lv_obj_t * label = lv_event_get_target(e); - PRINTER_CONFIG * config = (PRINTER_CONFIG*)lv_event_get_user_data(e); - int index = config - global_config.printer_config; - PrinterMinimal * printer = &printer_minimal[index]; + int config_index = (int)lv_event_get_user_data(e); + PrinterDataMinimal* printer = get_printer_data_minimal(config_index); - if (printer->state != PRINTER_STATE_OFFLINE && (printer->state == PRINTER_STATE_PRINTING || printer->state == PRINTER_STATE_PAUSED)) + if (printer->state == PrinterState::PrinterStatePrinting || printer->state == PrinterState::PrinterStatePaused) { char percentage_buffer[12]; sprintf(percentage_buffer, "%.2f%%", printer->print_progress * 100); @@ -103,11 +93,10 @@ static void update_printer_percentage_text(lv_event_t * e) static void update_printer_control_button_text(lv_event_t * e) { lv_obj_t * label = lv_event_get_target(e); - PRINTER_CONFIG * config = (PRINTER_CONFIG*)lv_event_get_user_data(e); - int index = config - global_config.printer_config; - PrinterMinimal * printer = &printer_minimal[index]; + int config_index = (int)lv_event_get_user_data(e); + PrinterDataMinimal* printer = get_printer_data_minimal(config_index); - if (printer->power_devices > 0 && (config == get_current_printer_config() || printer->state == PRINTER_STATE_OFFLINE)) + if (printer->power_devices > 0 && (config_index == get_current_printer_index() || printer->state == PrinterState::PrinterStateOffline)) { lv_label_set_text(label, "Power"); } @@ -120,9 +109,10 @@ static void update_printer_control_button_text(lv_event_t * e) static void btn_set_secondary_button_text(lv_event_t * e) { lv_obj_t * label = lv_event_get_target(e); - PRINTER_CONFIG * config = (PRINTER_CONFIG*)lv_event_get_user_data(e); + int config_index = (int)lv_event_get_user_data(e); + PrinterDataMinimal* printer = get_printer_data_minimal(config_index); - if (config == get_current_printer_config()) + if (config_index == get_current_printer_index()) { lv_label_set_text(label, LV_SYMBOL_SETTINGS); } @@ -135,11 +125,10 @@ static void btn_set_secondary_button_text(lv_event_t * e) static void btn_enable_control(lv_event_t * e) { lv_obj_t * btn = lv_event_get_target(e); - PRINTER_CONFIG * config = (PRINTER_CONFIG*)lv_event_get_user_data(e); - int index = config - global_config.printer_config; - PrinterMinimal * printer = &printer_minimal[index]; + int config_index = (int)lv_event_get_user_data(e); + PrinterDataMinimal* printer = get_printer_data_minimal(config_index); - if ((config == get_current_printer_config() || printer->state == PRINTER_STATE_OFFLINE) && printer->power_devices <= 0) + if ((config_index == get_current_printer_index() || printer->state == PrinterState::PrinterStateOffline) && printer->power_devices <= 0) { // Disable lv_obj_add_state(btn, LV_STATE_DISABLED); @@ -152,7 +141,7 @@ static void btn_enable_control(lv_event_t * e) } } -PRINTER_CONFIG * keyboard_config = NULL; +PrinterConfiguration * keyboard_config = NULL; static void keyboard_callback(lv_event_t * e){ lv_obj_t * ta = lv_event_get_target(e); @@ -167,15 +156,16 @@ static void keyboard_callback(lv_event_t * e){ static void btn_printer_secondary(lv_event_t * e) { lv_obj_t * btn = lv_event_get_target(e); - PRINTER_CONFIG * config = (PRINTER_CONFIG*)lv_event_get_user_data(e); - - if (config == get_current_printer_config()) + int config_index = (int)lv_event_get_user_data(e); + BasePrinter* printer = get_printer(config_index); + + if (config_index == get_current_printer_index()) { nav_buttons_setup(PANEL_SETTINGS); return; } - config->ip_configured = false; + printer->printer_config->ip_configured = false; write_global_config(); nav_buttons_setup(PANEL_PRINTER); @@ -183,33 +173,33 @@ static void btn_printer_secondary(lv_event_t * e) static void btn_printer_rename(lv_event_t * e) { - keyboard_config = (PRINTER_CONFIG*)lv_event_get_user_data(e); + keyboard_config = (PrinterConfiguration*)lv_event_get_user_data(e); lv_create_keyboard_text_entry(keyboard_callback, "Rename Printer", LV_KEYBOARD_MODE_TEXT_LOWER, CYD_SCREEN_WIDTH_PX * 0.75, 24, keyboard_config->printer_name, false); } static void btn_printer_activate(lv_event_t * e) { lv_obj_t * label = lv_event_get_target(e); - PRINTER_CONFIG * config = (PRINTER_CONFIG*)lv_event_get_user_data(e); - int index = config - global_config.printer_config; - PrinterMinimal * printer = &printer_minimal[index]; + int config_index = (int)lv_event_get_user_data(e); + PrinterDataMinimal* printer = get_printer_data_minimal(config_index); + BasePrinter* printer_full = get_printer(config_index); - if (printer->power_devices > 0 && (config == get_current_printer_config() || printer->state == PRINTER_STATE_OFFLINE)) + if (printer->power_devices > 0 && (config_index == get_current_printer_index() || printer->state == PrinterState::PrinterStateOffline)) { - macros_draw_power_fullscreen(config); + macros_draw_power_fullscreen(printer_full); return; } - switch_printer(index); + set_current_printer(config_index); lv_msg_send(DATA_PRINTER_MINIMAL, NULL); } static void btn_printer_add(lv_event_t * e) { - set_printer_config_index(get_printer_config_free_index()); + add_printer(); } -void create_printer_ui(PRINTER_CONFIG * config, lv_obj_t * root) +void create_printer_ui(PrinterConfiguration * config, lv_obj_t * root) { int index = config - global_config.printer_config; auto width = CYD_SCREEN_PANEL_WIDTH_PX - CYD_SCREEN_GAP_PX * 2; @@ -219,16 +209,16 @@ void create_printer_ui(PRINTER_CONFIG * config, lv_obj_t * root) lv_obj_set_size(data_row_name, width, LV_SIZE_CONTENT); lv_obj_t * label = lv_label_create(data_row_name); - lv_obj_add_event_cb(label, update_printer_name_text, LV_EVENT_MSG_RECEIVED, config); - lv_msg_subsribe_obj(DATA_PRINTER_MINIMAL, label, config); + lv_obj_add_event_cb(label, update_printer_name_text, LV_EVENT_MSG_RECEIVED, (void*)index); + lv_msg_subsribe_obj(DATA_PRINTER_MINIMAL, label, (void*)index); label = lv_label_create(data_row_name); - lv_obj_add_event_cb(label, update_printer_label_visible_active_printer, LV_EVENT_MSG_RECEIVED, config); - lv_msg_subsribe_obj(DATA_PRINTER_MINIMAL, label, config); + lv_obj_add_event_cb(label, update_printer_label_visible_active_printer, LV_EVENT_MSG_RECEIVED, (void*)index); + lv_msg_subsribe_obj(DATA_PRINTER_MINIMAL, label, (void*)index); label = lv_label_create(data_row_name); - lv_obj_add_event_cb(label, update_printer_status_text, LV_EVENT_MSG_RECEIVED, config); - lv_msg_subsribe_obj(DATA_PRINTER_MINIMAL, label, config); + lv_obj_add_event_cb(label, update_printer_status_text, LV_EVENT_MSG_RECEIVED, (void*)index); + lv_msg_subsribe_obj(DATA_PRINTER_MINIMAL, label, (void*)index); lv_obj_t * progress_row = lv_create_empty_panel(root); lv_layout_flex_row(progress_row); @@ -236,13 +226,13 @@ void create_printer_ui(PRINTER_CONFIG * config, lv_obj_t * root) lv_obj_t * progress_bar = lv_bar_create(progress_row); lv_obj_set_flex_grow(progress_bar, 1); - lv_obj_add_event_cb(progress_bar, update_printer_percentage_bar, LV_EVENT_MSG_RECEIVED, config); - lv_msg_subsribe_obj(DATA_PRINTER_MINIMAL, progress_bar, config); + lv_obj_add_event_cb(progress_bar, update_printer_percentage_bar, LV_EVENT_MSG_RECEIVED, (void*)index); + lv_msg_subsribe_obj(DATA_PRINTER_MINIMAL, progress_bar, (void*)index); label = lv_label_create(progress_row); lv_obj_set_style_text_font(label, &CYD_SCREEN_FONT_SMALL, 0); - lv_obj_add_event_cb(label, update_printer_percentage_text, LV_EVENT_MSG_RECEIVED, config); - lv_msg_subsribe_obj(DATA_PRINTER_MINIMAL, label, config); + lv_obj_add_event_cb(label, update_printer_percentage_text, LV_EVENT_MSG_RECEIVED, (void*)index); + lv_msg_subsribe_obj(DATA_PRINTER_MINIMAL, label, (void*)index); lv_obj_t * button_row = lv_create_empty_panel(root); lv_layout_flex_row(button_row); @@ -250,16 +240,16 @@ void create_printer_ui(PRINTER_CONFIG * config, lv_obj_t * root) lv_obj_t * btn = lv_btn_create(button_row); lv_obj_set_flex_grow(btn, 1); - lv_obj_add_event_cb(btn, btn_printer_secondary, LV_EVENT_CLICKED, config); + lv_obj_add_event_cb(btn, btn_printer_secondary, LV_EVENT_CLICKED, (void*)index); label = lv_label_create(btn); lv_obj_center(label); - lv_obj_add_event_cb(label, btn_set_secondary_button_text, LV_EVENT_MSG_RECEIVED, config); - lv_msg_subsribe_obj(DATA_PRINTER_MINIMAL, label, config); + lv_obj_add_event_cb(label, btn_set_secondary_button_text, LV_EVENT_MSG_RECEIVED, (void*)index); + lv_msg_subsribe_obj(DATA_PRINTER_MINIMAL, label, (void*)index); btn = lv_btn_create(button_row); lv_obj_set_flex_grow(btn, 2); - lv_obj_add_event_cb(btn, btn_printer_rename, LV_EVENT_CLICKED, config); + lv_obj_add_event_cb(btn, btn_printer_rename, LV_EVENT_CLICKED, (void*)index); label = lv_label_create(btn); lv_label_set_text(label, "Rename"); @@ -267,14 +257,14 @@ void create_printer_ui(PRINTER_CONFIG * config, lv_obj_t * root) btn = lv_btn_create(button_row); lv_obj_set_flex_grow(btn, 2); - lv_obj_add_event_cb(btn, btn_printer_activate, LV_EVENT_CLICKED, config); - lv_obj_add_event_cb(btn, btn_enable_control, LV_EVENT_MSG_RECEIVED, config); - lv_msg_subsribe_obj(DATA_PRINTER_MINIMAL, btn, config); + lv_obj_add_event_cb(btn, btn_printer_activate, LV_EVENT_CLICKED, (void*)index); + lv_obj_add_event_cb(btn, btn_enable_control, LV_EVENT_MSG_RECEIVED, (void*)index); + lv_msg_subsribe_obj(DATA_PRINTER_MINIMAL, btn, (void*)index); label = lv_label_create(btn); lv_obj_center(label); - lv_obj_add_event_cb(label, update_printer_control_button_text, LV_EVENT_MSG_RECEIVED, config); - lv_msg_subsribe_obj(DATA_PRINTER_MINIMAL, label, config); + lv_obj_add_event_cb(label, update_printer_control_button_text, LV_EVENT_MSG_RECEIVED, (void*)index); + lv_msg_subsribe_obj(DATA_PRINTER_MINIMAL, label, (void*)index); lv_obj_t * line = lv_line_create(root); lv_line_set_points(line, line_points, 2); @@ -293,14 +283,14 @@ void printer_panel_init(lv_obj_t* panel) lv_obj_set_size(lv_create_empty_panel(inner_panel), 0, 0); for (int i = 0; i < PRINTER_CONFIG_COUNT; i++){ - PRINTER_CONFIG * config = &global_config.printer_config[i]; + PrinterConfiguration * config = &global_config.printer_config[i]; if (config->ip_configured) { create_printer_ui(&global_config.printer_config[i], inner_panel); } } // Add Printer Button - if (get_printer_config_free_index() != -1){ + if (get_printer_count() == PRINTER_CONFIG_COUNT){ lv_obj_t * btn = lv_btn_create(inner_panel); lv_obj_set_size(btn, CYD_SCREEN_PANEL_WIDTH_PX - CYD_SCREEN_GAP_PX * 2, CYD_SCREEN_MIN_BUTTON_HEIGHT_PX); lv_obj_add_event_cb(btn, btn_printer_add, LV_EVENT_CLICKED, NULL); @@ -311,6 +301,4 @@ void printer_panel_init(lv_obj_t* panel) } lv_obj_set_size(lv_create_empty_panel(inner_panel), 0, 0); - - lv_msg_send(DATA_PRINTER_MINIMAL, NULL); } \ No newline at end of file diff --git a/CYD-Klipper/src/ui/switch_printer.cpp b/CYD-Klipper/src/ui/switch_printer.cpp index 708de3a..a703178 100644 --- a/CYD-Klipper/src/ui/switch_printer.cpp +++ b/CYD-Klipper/src/ui/switch_printer.cpp @@ -17,7 +17,7 @@ void switch_printer(int index) static void btn_switch_printer(lv_event_t *e){ lv_obj_t *btn = lv_event_get_target(e); - PRINTER_CONFIG * config = (PRINTER_CONFIG*)lv_event_get_user_data(e); + PrinterConfiguration * config = (PrinterConfiguration*)lv_event_get_user_data(e); int index = config - global_config.printer_config; switch_printer(index); @@ -45,7 +45,7 @@ void switch_printer_init() { lv_obj_center(label); for (int i = 0; i < PRINTER_CONFIG_COUNT; i++){ - PRINTER_CONFIG * config = &global_config.printer_config[i]; + PrinterConfiguration * config = &global_config.printer_config[i]; const char* printer_name = (config->printer_name[0] == 0) ? config->klipper_host : config->printer_name; if (config == get_current_printer_config() && config->ip_configured) diff --git a/CYD-Klipper/src/ui/ui_utils.cpp b/CYD-Klipper/src/ui/ui_utils.cpp index 12c9053..391c0d1 100644 --- a/CYD-Klipper/src/ui/ui_utils.cpp +++ b/CYD-Klipper/src/ui/ui_utils.cpp @@ -40,9 +40,9 @@ void destroy_event_free_data(lv_event_t * e) free(data); } -void lv_on_destroy_free_data(lv_obj_t * element, void* ptr) +void lv_obj_on_destroy_free_data(lv_obj_t * element, const void* ptr) { - lv_obj_add_event_cb(element, destroy_event_free_data, LV_EVENT_DELETE, ptr); + lv_obj_add_event_cb(element, destroy_event_free_data, LV_EVENT_DELETE, (void*)ptr); } void lv_create_fullscreen_button_matrix_popup(lv_obj_t * root, lv_event_cb_t title, lv_button_column_t* columns, int column_count){ diff --git a/CYD-Klipper/src/ui/ui_utils.h b/CYD-Klipper/src/ui/ui_utils.h index 32790b3..020ba71 100644 --- a/CYD-Klipper/src/ui/ui_utils.h +++ b/CYD-Klipper/src/ui/ui_utils.h @@ -38,7 +38,7 @@ void lv_layout_flex_column(lv_obj_t* obj, lv_flex_align_t allign = LV_FLEX_ALIGN void lv_layout_flex_row(lv_obj_t* obj, lv_flex_align_t allign = LV_FLEX_ALIGN_START, lv_coord_t pad_column = CYD_SCREEN_GAP_PX, lv_coord_t pad_row = CYD_SCREEN_GAP_PX); void lv_create_fullscreen_button_matrix_popup(lv_obj_t * root, lv_event_cb_t title, lv_button_column_t* columns, int column_count); void destroy_event_user_data(lv_event_t * e); -void lv_on_destroy_free_data(lv_obj_t * element, void* ptr); +void lv_obj_on_destroy_free_data(lv_obj_t * element, const void* ptr); void lv_create_keyboard_text_entry(lv_event_cb_t keyboard_callback, const char* title = NULL, lv_keyboard_mode_t keyboard_mode = LV_KEYBOARD_MODE_NUMBER, lv_coord_t width = CYD_SCREEN_PANEL_WIDTH_PX / 2, uint8_t max_length = 3, const char* fill_text = "", bool contain_in_panel= true); void lv_create_custom_menu_entry(const char* label_text, lv_obj_t* object, lv_obj_t* root_panel, bool set_height = true, const char * comment = NULL); void lv_create_custom_menu_button(const char *label_text, lv_obj_t* root_panel, lv_event_cb_t on_click, const char *btn_text, void * user_data = NULL, const char * comment = NULL); From e55c2871d977f1bb084a0b58b8ae925211f8419b Mon Sep 17 00:00:00 2001 From: suchmememanyskill <38142618+suchmememanyskill@users.noreply.github.com> Date: Sun, 27 Oct 2024 01:46:31 +0200 Subject: [PATCH 09/63] Finish all panels --- .../klipper/klipper_printer_integration.cpp | 2 +- .../klipper/klipper_printer_integration.hpp | 2 +- CYD-Klipper/src/core/printer_integration.hpp | 2 +- CYD-Klipper/src/ui/panels/files_panel.cpp | 2 + CYD-Klipper/src/ui/panels/progress_panel.cpp | 35 ++-- CYD-Klipper/src/ui/panels/settings_panel.cpp | 29 +-- CYD-Klipper/src/ui/panels/stats_panel.cpp | 186 ++---------------- CYD-Klipper/src/ui/panels/temp_panel.cpp | 108 +++++----- 8 files changed, 96 insertions(+), 270 deletions(-) diff --git a/CYD-Klipper/src/core/klipper/klipper_printer_integration.cpp b/CYD-Klipper/src/core/klipper/klipper_printer_integration.cpp index 017aed1..5edd7dd 100644 --- a/CYD-Klipper/src/core/klipper/klipper_printer_integration.cpp +++ b/CYD-Klipper/src/core/klipper/klipper_printer_integration.cpp @@ -696,7 +696,7 @@ bool KlipperPrinter::start_file(const char *filename) return http_code == 200; } -bool KlipperPrinter::set_target_temperature(PrinterTemperatureDevice device, float temperature) +bool KlipperPrinter::set_target_temperature(PrinterTemperatureDevice device, unsigned int temperature) { char gcode[64] = {0}; diff --git a/CYD-Klipper/src/core/klipper/klipper_printer_integration.hpp b/CYD-Klipper/src/core/klipper/klipper_printer_integration.hpp index 445c652..d758c91 100644 --- a/CYD-Klipper/src/core/klipper/klipper_printer_integration.hpp +++ b/CYD-Klipper/src/core/klipper/klipper_printer_integration.hpp @@ -48,7 +48,7 @@ class KlipperPrinter : public BasePrinter Files get_files(); bool start_file(const char* filename); unsigned char* get_32_32_png_image_thumbnail(const char* gcode_filename); - bool set_target_temperature(PrinterTemperatureDevice device, float temperature); + bool set_target_temperature(PrinterTemperatureDevice device, unsigned int temperature); bool send_gcode(const char* gcode, bool wait = true); int get_slicer_time_estimate_s(); void configure_http_client(HTTPClient &client, String url_part, bool stream, int timeout); diff --git a/CYD-Klipper/src/core/printer_integration.hpp b/CYD-Klipper/src/core/printer_integration.hpp index 06298d8..7c34875 100644 --- a/CYD-Klipper/src/core/printer_integration.hpp +++ b/CYD-Klipper/src/core/printer_integration.hpp @@ -159,7 +159,7 @@ class BasePrinter virtual Files get_files() = 0; virtual bool start_file(const char* filename) = 0; virtual unsigned char* get_32_32_png_image_thumbnail(const char* gcode_filename); - virtual bool set_target_temperature(PrinterTemperatureDevice device, float temperature) = 0; + virtual bool set_target_temperature(PrinterTemperatureDevice device, unsigned int temperature) = 0; BasePrinter(unsigned char index); PrinterData* AnnouncePrinterData(); diff --git a/CYD-Klipper/src/ui/panels/files_panel.cpp b/CYD-Klipper/src/ui/panels/files_panel.cpp index b6c29a5..e720d8e 100644 --- a/CYD-Klipper/src/ui/panels/files_panel.cpp +++ b/CYD-Klipper/src/ui/panels/files_panel.cpp @@ -78,7 +78,9 @@ static void btn_print_file_verify(lv_event_t * e){ } void files_panel_init(lv_obj_t* panel){ + freeze_request_thread(); Files files = get_current_printer()->get_files(); + unfreeze_request_thread(); if (!files.success || files.count <= 0){ lv_obj_t * label = lv_label_create(panel); diff --git a/CYD-Klipper/src/ui/panels/progress_panel.cpp b/CYD-Klipper/src/ui/panels/progress_panel.cpp index 643656a..92d1fcd 100644 --- a/CYD-Klipper/src/ui/panels/progress_panel.cpp +++ b/CYD-Klipper/src/ui/panels/progress_panel.cpp @@ -1,7 +1,7 @@ #include "panel.h" -#include "../../core/data_setup.h" #include #include "../ui_utils.h" +#include "../../core/printer_integration.hpp" char time_buffer[12]; @@ -15,35 +15,35 @@ char* time_display(unsigned long time){ static void progress_bar_update(lv_event_t* e){ lv_obj_t * bar = lv_event_get_target(e); - lv_bar_set_value(bar, printer.print_progress * 100, LV_ANIM_ON); + lv_bar_set_value(bar, get_current_printer_data()->print_progress * 100, LV_ANIM_ON); } static void update_printer_data_elapsed_time(lv_event_t * e){ lv_obj_t * label = lv_event_get_target(e); - lv_label_set_text(label, time_display(printer.elapsed_time_s)); + lv_label_set_text(label, time_display(get_current_printer_data()->elapsed_time_s)); } static void update_printer_data_remaining_time(lv_event_t * e){ lv_obj_t * label = lv_event_get_target(e); - lv_label_set_text(label, time_display(printer.remaining_time_s)); + lv_label_set_text(label, time_display(get_current_printer_data()->remaining_time_s)); } static void update_printer_data_stats(lv_event_t * e){ lv_obj_t * label = lv_event_get_target(e); char buff[256] = {0}; - switch (get_current_printer_config()->show_stats_on_progress_panel) + switch (get_current_printer()->printer_config->show_stats_on_progress_panel) { case SHOW_STATS_ON_PROGRESS_PANEL_LAYER: - sprintf(buff, "Layer %d of %d", printer.current_layer, printer.total_layers); + sprintf(buff, "Layer %d of %d", get_current_printer_data()->current_layer, get_current_printer_data()->total_layers); break; case SHOW_STATS_ON_PROGRESS_PANEL_PARTIAL: sprintf(buff, "Position: X%.2f Y%.2f\nFeedrate: %d mm/s\nFilament Used: %.2f m\nLayer %d of %d", - printer.position[0], printer.position[1], printer.feedrate_mm_per_s, printer.filament_used_mm / 1000, printer.current_layer, printer.total_layers); + get_current_printer_data()->position[0], get_current_printer_data()->position[1], get_current_printer_data()->feedrate_mm_per_s, get_current_printer_data()->filament_used_mm / 1000, get_current_printer_data()->current_layer, get_current_printer_data()->total_layers); break; case SHOW_STATS_ON_PROGRESS_PANEL_ALL: sprintf(buff, "Pressure Advance: %.3f (%.2fs)\nPosition: X%.2f Y%.2f Z%.2f\nFeedrate: %d mm/s\nFilament Used: %.2f m\nFan: %.0f%%\nSpeed: %.0f%%\nFlow: %.0f%%\nLayer %d of %d", - printer.pressure_advance, printer.smooth_time, printer.position[0], printer.position[1], printer.position[2], printer.feedrate_mm_per_s, printer.filament_used_mm / 1000, printer.fan_speed * 100, printer.speed_mult * 100, printer.extrude_mult * 100, printer.current_layer, printer.total_layers); + get_current_printer_data()->pressure_advance, get_current_printer_data()->smooth_time, get_current_printer_data()->position[0], get_current_printer_data()->position[1], get_current_printer_data()->position[2], get_current_printer_data()->feedrate_mm_per_s, get_current_printer_data()->filament_used_mm / 1000, get_current_printer_data()->fan_speed * 100, get_current_printer_data()->speed_mult * 100, get_current_printer_data()->extrude_mult * 100, get_current_printer_data()->current_layer, get_current_printer_data()->total_layers); break; } @@ -53,25 +53,24 @@ static void update_printer_data_stats(lv_event_t * e){ static void update_printer_data_percentage(lv_event_t * e){ lv_obj_t * label = lv_event_get_target(e); char percentage_buffer[12]; - sprintf(percentage_buffer, "%.2f%%", printer.print_progress * 100); + sprintf(percentage_buffer, "%.2f%%", get_current_printer_data()->print_progress * 100); lv_label_set_text(label, percentage_buffer); } static void btn_click_stop(lv_event_t * e){ - send_gcode(true, "CANCEL_PRINT"); + get_current_printer()->execute_feature(PrinterFeatures::PrinterFeatureStop); } static void btn_click_pause(lv_event_t * e){ - send_gcode(true, "PAUSE"); + get_current_printer()->execute_feature(PrinterFeatures::PrinterFeaturePause); } static void btn_click_resume(lv_event_t * e){ - send_gcode(true, "RESUME"); + get_current_printer()->execute_feature(PrinterFeatures::PrinterFeatureResume); } static void btn_click_estop(lv_event_t * e){ - send_estop(); - send_gcode(false, "M112"); + get_current_printer()->execute_feature(PrinterFeatures::PrinterFeatureEmergencyStop); } void progress_panel_init(lv_obj_t* panel){ @@ -97,7 +96,7 @@ void progress_panel_init(lv_obj_t* panel){ lv_layout_flex_column(center_panel); // Only align progress bar to top mid if necessary to make room for all extras - if (get_current_printer_config()->show_stats_on_progress_panel == SHOW_STATS_ON_PROGRESS_PANEL_ALL && CYD_SCREEN_HEIGHT_PX <= 320) + if (get_current_printer()->printer_config->show_stats_on_progress_panel == SHOW_STATS_ON_PROGRESS_PANEL_ALL && CYD_SCREEN_HEIGHT_PX <= 320) { lv_obj_align(center_panel, LV_ALIGN_TOP_MID, 0, CYD_SCREEN_MIN_BUTTON_HEIGHT_PX+(3 * CYD_SCREEN_GAP_PX)); } @@ -108,7 +107,7 @@ void progress_panel_init(lv_obj_t* panel){ // Filename lv_obj_t * label = lv_label_create(center_panel); - lv_label_set_text(label, printer.print_filename); + lv_label_set_text(label, get_current_printer_data()->print_filename); if (global_config.full_filenames) lv_label_set_long_mode(label, LV_LABEL_LONG_WRAP); else lv_label_set_long_mode(label, LV_LABEL_LONG_SCROLL_CIRCULAR); lv_obj_set_width(label, panel_width); @@ -155,7 +154,7 @@ void progress_panel_init(lv_obj_t* panel){ lv_obj_center(label); // Resume Button - if (printer.state == PRINTER_STATE_PAUSED){ + if (get_current_printer_data()->state == PrinterState::PrinterStatePaused){ btn = lv_btn_create(panel); lv_obj_add_event_cb(btn, btn_click_resume, LV_EVENT_CLICKED, NULL); @@ -176,7 +175,7 @@ void progress_panel_init(lv_obj_t* panel){ lv_obj_align(btn, LV_ALIGN_BOTTOM_RIGHT, -2 * CYD_SCREEN_GAP_PX - CYD_SCREEN_MIN_BUTTON_WIDTH_PX * button_size_mult, -1 * CYD_SCREEN_GAP_PX); lv_obj_set_size(btn, CYD_SCREEN_MIN_BUTTON_WIDTH_PX * button_size_mult, CYD_SCREEN_MIN_BUTTON_HEIGHT_PX * button_size_mult); - if (get_current_printer_config()->show_stats_on_progress_panel > SHOW_STATS_ON_PROGRESS_PANEL_NONE) + if (get_current_printer()->printer_config->show_stats_on_progress_panel > SHOW_STATS_ON_PROGRESS_PANEL_NONE) { label = lv_label_create(panel); lv_obj_align(label, LV_ALIGN_BOTTOM_LEFT, CYD_SCREEN_GAP_PX, -1 * CYD_SCREEN_GAP_PX); diff --git a/CYD-Klipper/src/ui/panels/settings_panel.cpp b/CYD-Klipper/src/ui/panels/settings_panel.cpp index 47866c0..8e867aa 100644 --- a/CYD-Klipper/src/ui/panels/settings_panel.cpp +++ b/CYD-Klipper/src/ui/panels/settings_panel.cpp @@ -8,6 +8,7 @@ #include "../../core/lv_setup.h" #include "../ota_setup.h" #include "../nav_buttons.h" +#include "../../core/printer_integration.hpp" #ifndef REPO_VERSION #define REPO_VERSION "Unknown" @@ -16,7 +17,7 @@ static void invert_color_switch(lv_event_t * e){ auto state = lv_obj_get_state(lv_event_get_target(e)); bool checked = (state & LV_STATE_CHECKED == LV_STATE_CHECKED); - get_current_printer_config()->invert_colors = checked; + get_current_printer()->printer_config->invert_colors = checked; write_global_config(); set_invert_display(); } @@ -38,8 +39,8 @@ static void reset_wifi_click(lv_event_t * e){ } static void reset_ip_click(lv_event_t * e){ - get_current_printer_config()->ip_configured = false; - get_current_printer_config()->auth_configured = false; + get_current_printer()->printer_config->ip_configured = false; + get_current_printer()->printer_config->auth_configured = false; write_global_config(); ESP.restart(); } @@ -47,7 +48,7 @@ static void reset_ip_click(lv_event_t * e){ static void light_mode_switch(lv_event_t * e){ auto state = lv_obj_get_state(lv_event_get_target(e)); bool checked = (state & LV_STATE_CHECKED == LV_STATE_CHECKED); - get_current_printer_config()->light_mode = checked; + get_current_printer()->printer_config->light_mode = checked; write_global_config(); set_color_scheme(); } @@ -55,20 +56,20 @@ static void light_mode_switch(lv_event_t * e){ static void filament_move_mode_switch(lv_event_t * e){ auto state = lv_obj_get_state(lv_event_get_target(e)); bool checked = (state & LV_STATE_CHECKED == LV_STATE_CHECKED); - get_current_printer_config()->custom_filament_move_macros = checked; + get_current_printer()->printer_config->custom_filament_move_macros = checked; write_global_config(); } static void show_stats_on_progress_panel_dropdown(lv_event_t * e){ auto selected = lv_dropdown_get_selected(lv_event_get_target(e)); - get_current_printer_config()->show_stats_on_progress_panel = selected; + get_current_printer()->printer_config->show_stats_on_progress_panel = selected; write_global_config(); } static void theme_dropdown(lv_event_t * e){ lv_obj_t * dropdown = lv_event_get_target(e); auto selected = lv_dropdown_get_selected(dropdown); - get_current_printer_config()->color_scheme = selected; + get_current_printer()->printer_config->color_scheme = selected; set_color_scheme(); write_global_config(); } @@ -171,7 +172,7 @@ const char* estimated_time_options = "Percentage\nInterpolated\nSlicer"; static void estimated_time_dropdown(lv_event_t * e){ lv_obj_t * dropdown = lv_event_get_target(e); - get_current_printer_config()->remaining_time_calc_mode = lv_dropdown_get_selected(dropdown); + get_current_printer()->printer_config->remaining_time_calc_mode = lv_dropdown_get_selected(dropdown); write_global_config(); } @@ -182,10 +183,10 @@ void settings_section_theming(lv_obj_t* panel) lv_obj_t * label = lv_label_create(panel); lv_label_set_text(label, "Theming"); - lv_create_custom_menu_dropdown("Theme", panel, theme_dropdown, "Blue\nGreen\nLime\nGrey\nYellow\nOrange\nRed\nPurple", get_current_printer_config()->color_scheme, NULL, PRINTER_SPECIFIC_SETTING); + lv_create_custom_menu_dropdown("Theme", panel, theme_dropdown, "Blue\nGreen\nLime\nGrey\nYellow\nOrange\nRed\nPurple", get_current_printer()->printer_config->color_scheme, NULL, PRINTER_SPECIFIC_SETTING); #ifndef CYD_SCREEN_DISABLE_INVERT_COLORS - lv_create_custom_menu_switch("Invert Colors", panel, invert_color_switch, get_current_printer_config()->invert_colors, NULL, (global_config.multi_printer_mode) ? "Stored per printer" + lv_create_custom_menu_switch("Invert Colors", panel, invert_color_switch, get_current_printer()->printer_config->invert_colors, NULL, (global_config.multi_printer_mode) ? "Stored per printer" #ifdef CYD_SCREEN_DRIVER_ESP32_2432S028R "\nIntended for the 2.8\" dual USB model screen" : "Intended for the 2.8\" dual USB model screen" #else @@ -194,7 +195,7 @@ void settings_section_theming(lv_obj_t* panel) ); #endif // CYD_SCREEN_DISABLE_INVERT_COLORS - lv_create_custom_menu_switch("Light Mode", panel, light_mode_switch, get_current_printer_config()->light_mode, NULL, PRINTER_SPECIFIC_SETTING); + lv_create_custom_menu_switch("Light Mode", panel, light_mode_switch, get_current_printer()->printer_config->light_mode, NULL, PRINTER_SPECIFIC_SETTING); } void settings_section_behaviour(lv_obj_t* panel) @@ -202,8 +203,8 @@ void settings_section_behaviour(lv_obj_t* panel) lv_obj_t * label = lv_label_create(panel); lv_label_set_text(label, "\nBehaviour"); - lv_create_custom_menu_dropdown("Estimated Time", panel, estimated_time_dropdown, estimated_time_options, get_current_printer_config()->remaining_time_calc_mode, NULL, PRINTER_SPECIFIC_SETTING); - lv_create_custom_menu_dropdown("Stats in Progress Screen", panel, show_stats_on_progress_panel_dropdown, "None\nLayers\nPartial\nAll", get_current_printer_config()->show_stats_on_progress_panel, NULL, PRINTER_SPECIFIC_SETTING); + lv_create_custom_menu_dropdown("Estimated Time", panel, estimated_time_dropdown, estimated_time_options, get_current_printer()->printer_config->remaining_time_calc_mode, NULL, PRINTER_SPECIFIC_SETTING); + lv_create_custom_menu_dropdown("Stats in Progress Screen", panel, show_stats_on_progress_panel_dropdown, "None\nLayers\nPartial\nAll", get_current_printer()->printer_config->show_stats_on_progress_panel, NULL, PRINTER_SPECIFIC_SETTING); #ifndef CYD_SCREEN_DISABLE_TIMEOUT int wake_timeout_settings_index = 0; @@ -225,7 +226,7 @@ void settings_section_behaviour(lv_obj_t* panel) lv_create_custom_menu_switch("Disable M117 Messaging", panel, disable_m117_messaging_switch, global_config.disable_m117_messaging); lv_create_custom_menu_button("Configure Printer IP", panel, reset_ip_click, "Restart"); - lv_create_custom_menu_switch("Custom Filament Move Macros", panel, filament_move_mode_switch, get_current_printer_config()->custom_filament_move_macros, NULL, + lv_create_custom_menu_switch("Custom Filament Move Macros", panel, filament_move_mode_switch, get_current_printer()->printer_config->custom_filament_move_macros, NULL, global_config.multi_printer_mode ? "Calls FILAMENT_RETRACT and\nFILAMENT_EXTRUDE in temperature menu\nwhen enabled. Stored per printer." : "Calls FILAMENT_RETRACT and\nFILAMENT_EXTRUDE in temperature menu\nwhen enabled"); diff --git a/CYD-Klipper/src/ui/panels/stats_panel.cpp b/CYD-Klipper/src/ui/panels/stats_panel.cpp index df19e41..22a34b5 100644 --- a/CYD-Klipper/src/ui/panels/stats_panel.cpp +++ b/CYD-Klipper/src/ui/panels/stats_panel.cpp @@ -1,173 +1,14 @@ #include "panel.h" #include "../ui_utils.h" -#include "../../core/data_setup.h" #include "../nav_buttons.h" #include #include +#include "../../core/printer_integration.hpp" static void swap_to_files_menu(lv_event_t * e) { nav_buttons_setup(PANEL_FILES); } -static void set_fan_speed_text(lv_event_t * e) { - lv_obj_t * label = lv_event_get_target(e); - char data[64]; - sprintf(data, "Fan: %.0f%%", printer.fan_speed * 100); - lv_label_set_text(label, data); -} - -static void set_fan_speed(lv_event_t * e){ - int speed = (int)lv_event_get_user_data(e); - char gcode[64]; - sprintf(gcode, "M106 S%d", speed); - send_gcode(true, gcode); -} - -const char* fan_speeds[] = { "0%", "15%", "25%", "35%" }; -const int fan_speeds_values[] = { 0, 38, 64, 90 }; - -const char* fan_speeds_2[] = { "50%", "75%", "100%"}; -const int fan_speeds_values_2[] = { 128, 192, 255 }; - -lv_button_column_t fan_speed_columns[] = { - { set_fan_speed, fan_speeds, (const void**)fan_speeds_values, 4}, - { set_fan_speed, fan_speeds_2, (const void**)fan_speeds_values_2, 3} -}; - -static void set_zoffset_text(lv_event_t * e) { - lv_obj_t * label = lv_event_get_target(e); - char data[64]; - sprintf(data, "Z Offset: %.03f", printer.gcode_offset[2]); - lv_label_set_text(label, data); -} - -static void set_zoffset_text_ex(lv_event_t * e) { - lv_obj_t * label = lv_event_get_target(e); - char data[64]; - sprintf(data, "Z Offset: %.03f, Z: %.03f", printer.gcode_offset[2], printer.position[2]); - lv_label_set_text(label, data); -} - -static void set_zoffset(lv_event_t * e){ - char* offset = (char*)lv_event_get_user_data(e); - - char gcode[64]; - sprintf(gcode, "SET_GCODE_OFFSET Z_ADJUST=%s MOVE=1", offset); - send_gcode(true, gcode); -} - -static void set_z(lv_event_t * e){ - void* ptr = lv_event_get_user_data(e); - float value = *(float *)(&ptr); - - if (value < 0) { - send_gcode(true, "SET_GCODE_OFFSET Z=0 MOVE=1"); - return; - } - - move_printer("Z", value, false); -} - -const char* zoffsets[] = { "-0.01", "-0.025", "-0.05", "-0.2" }; -const char* zoffsets_2[] = { "+0.01", "+0.025", "+0.05", "+0.2" }; -const char* zabs[] = { "Z=0", "Z=0.1", "Z=1", "Clear" }; -const float zabsvalues[] = { 0, 0.1f, 1.0f, -1.0f }; - -lv_button_column_t zoffset_columns[] = { - { set_zoffset, zoffsets, (const void**)zoffsets, 4}, - { set_zoffset, zoffsets_2, (const void**)zoffsets_2, 4}, - { set_z, zabs, (const void**)zabsvalues, 4} -}; - -static void set_speed_mult_text(lv_event_t * e){ - lv_obj_t * label = lv_event_get_target(e); - char data[64]; - sprintf(data, "Speed: %.0f%%", printer.speed_mult * 100); - lv_label_set_text(label, data); -} - -static void set_speed_mult(lv_event_t * e){ - int speed = (int)lv_event_get_user_data(e); - char gcode[64]; - sprintf(gcode, "M220 S%d", speed); - send_gcode(true, gcode); -} - -static void set_speed_mult_offset(lv_event_t * e){ - int speed = (int)lv_event_get_user_data(e); - float result = printer.speed_mult * 100 + speed; - printer.speed_mult = result / 100; - char gcode[64]; - sprintf(gcode, "M220 S%.0f", result); - send_gcode(true, gcode); -} - -const char* speed_presets[] = { "50%", "100%", "150%", "200%" }; -const int speed_presets_values[] = { 50, 100, 150, 200 }; -const char* speed_presets_minus[] = { "-1%", "-5%", "-10%", "-25%" }; -const int speed_presets_minus_values[] = { -1, -5, -10, -25 }; -const char* speed_presets_plus[] = { "+1%", "+5%", "+10%", "+25%" }; -const int speed_presets_plus_values[] = { 1, 5, 10, 25 }; - -lv_button_column_t speed_mult_columns[] = { - { set_speed_mult, speed_presets, (const void**)speed_presets_values, 4}, - { set_speed_mult_offset, speed_presets_minus, (const void**)speed_presets_minus_values, 4}, - { set_speed_mult_offset, speed_presets_plus, (const void**)speed_presets_plus_values, 4} -}; - -static void set_extrude_mult_text(lv_event_t * e){ - lv_obj_t * label = lv_event_get_target(e); - char data[64]; - sprintf(data, "Flow: %.0f%%", printer.extrude_mult * 100); - lv_label_set_text(label, data); -} - -static void set_extrude_mult(lv_event_t * e){ - int speed = (int)lv_event_get_user_data(e); - char gcode[64]; - sprintf(gcode, "M221 S%d", speed); - send_gcode(true, gcode); -} - -static void set_extrude_mult_offset(lv_event_t * e){ - int speed = (int)lv_event_get_user_data(e); - float result = printer.extrude_mult * 100 + speed; - printer.extrude_mult = result / 100; - char gcode[64]; - sprintf(gcode, "M221 S%.0f", result); - send_gcode(true, gcode); -} - -const char* extrude_presets[] = { "95%", "100%", "105%", "110%" }; -const int extrude_presets_values[] = { 95, 100, 105, 110 }; -const char* extrude_offset[] = { "+5%", "+1%", "-1%", "-5%" }; -const int extrude_offset_values[] = { 5, 1, -1, -5 }; - -lv_button_column_t extrude_mult_columns[] = { - { set_extrude_mult, extrude_presets, (const void**)extrude_presets_values, 4}, - { set_extrude_mult_offset, extrude_offset, (const void**)extrude_offset_values, 4} -}; - -static void open_fan_speed_panel(lv_event_t * e){ - lv_create_fullscreen_button_matrix_popup(lv_scr_act(), set_fan_speed_text, fan_speed_columns, 2); - lv_msg_send(DATA_PRINTER_DATA, &printer); -} - -static void open_zoffset_panel(lv_event_t * e){ - lv_create_fullscreen_button_matrix_popup(lv_scr_act(), set_zoffset_text_ex, zoffset_columns, (printer.state == PRINTER_STATE_IDLE) ? 3 : 2); - lv_msg_send(DATA_PRINTER_DATA, &printer); -} - -static void open_speed_mult_panel(lv_event_t * e){ - lv_create_fullscreen_button_matrix_popup(lv_scr_act(), set_speed_mult_text, speed_mult_columns, 3); - lv_msg_send(DATA_PRINTER_DATA, &printer); -} - -static void open_extrude_mult_panel(lv_event_t * e){ - lv_create_fullscreen_button_matrix_popup(lv_scr_act(), set_extrude_mult_text, extrude_mult_columns, 2); - lv_msg_send(DATA_PRINTER_DATA, &printer); -} - void create_state_button(lv_obj_t * root, lv_event_cb_t label, lv_event_cb_t button){ lv_obj_t * btn = lv_btn_create(root); lv_obj_set_size(btn, CYD_SCREEN_PANEL_WIDTH_PX / 2 - CYD_SCREEN_GAP_PX * 3, CYD_SCREEN_MIN_BUTTON_HEIGHT_PX); @@ -182,35 +23,35 @@ void create_state_button(lv_obj_t * root, lv_event_cb_t label, lv_event_cb_t but static void label_pos(lv_event_t * e){ lv_obj_t * label = lv_event_get_target(e); char x_pos_buff[32]; - sprintf(x_pos_buff, "X%.2f Y%.2f", printer.position[0], printer.position[1]); + sprintf(x_pos_buff, "X%.2f Y%.2f", get_current_printer_data()->position[0], get_current_printer_data()->position[1]); lv_label_set_text(label, x_pos_buff); } static void label_filament_used_m(lv_event_t * e){ lv_obj_t * label = lv_event_get_target(e); char filament_buff[32]; - sprintf(filament_buff, "%.2f m", printer.filament_used_mm / 1000); + sprintf(filament_buff, "%.2f m", get_current_printer_data()->filament_used_mm / 1000); lv_label_set_text(label, filament_buff); } static void label_total_layers(lv_event_t * e){ lv_obj_t * label = lv_event_get_target(e); char layers_buff[32]; - sprintf(layers_buff, "%d of %d", printer.current_layer, printer.total_layers); + sprintf(layers_buff, "%d of %d", get_current_printer_data()->current_layer, get_current_printer_data()->total_layers); lv_label_set_text(label, layers_buff); } static void label_pressure_advance(lv_event_t * e){ lv_obj_t * label = lv_event_get_target(e); char pressure_buff[32]; - sprintf(pressure_buff, "%.3f (%.2fs)", printer.pressure_advance, printer.smooth_time); + sprintf(pressure_buff, "%.3f (%.2fs)", get_current_printer_data()->pressure_advance, get_current_printer_data()->smooth_time); lv_label_set_text(label, pressure_buff); } static void label_feedrate(lv_event_t * e){ lv_obj_t * label = lv_event_get_target(e); char feedrate_buff[32]; - sprintf(feedrate_buff, "%d mm/s", printer.feedrate_mm_per_s); + sprintf(feedrate_buff, "%d mm/s", get_current_printer_data()->feedrate_mm_per_s); lv_label_set_text(label, feedrate_buff); } @@ -241,7 +82,7 @@ void stats_panel_init(lv_obj_t* panel) { create_stat_text_block(left_panel, "Position:", label_pos); - if (printer.state != PRINTER_STATE_IDLE){ + if (get_current_printer_data()->state != PrinterState::PrinterStateIdle){ create_stat_text_block(left_panel, "Filament Used:", label_filament_used_m); create_stat_text_block(left_panel, "Layer:", label_total_layers); } @@ -254,7 +95,7 @@ void stats_panel_init(lv_obj_t* panel) { lv_layout_flex_column(right_panel, LV_FLEX_ALIGN_CENTER); lv_obj_align(right_panel, LV_ALIGN_TOP_RIGHT, -1 * CYD_SCREEN_GAP_PX, CYD_SCREEN_GAP_PX); - if (printer.state >= PRINTER_STATE_PRINTING){ + if (get_current_printer_data()->state >= PrinterState::PrinterStatePrinting){ lv_obj_t * btn = lv_btn_create(right_panel); lv_obj_set_size(btn, CYD_SCREEN_PANEL_WIDTH_PX / 2 - CYD_SCREEN_GAP_PX * 3, CYD_SCREEN_MIN_BUTTON_HEIGHT_PX); lv_obj_add_event_cb(btn, swap_to_files_menu, LV_EVENT_CLICKED, NULL); @@ -263,9 +104,10 @@ void stats_panel_init(lv_obj_t* panel) { lv_label_set_text(label, "Files"); lv_obj_align(label, LV_ALIGN_CENTER, 0, 0); } - - create_state_button(right_panel, set_fan_speed_text, open_fan_speed_panel); - create_state_button(right_panel, set_zoffset_text, open_zoffset_panel); - create_state_button(right_panel, set_speed_mult_text, open_speed_mult_panel); - create_state_button(right_panel, set_extrude_mult_text, open_extrude_mult_panel); + + BasePrinter* printer = get_current_printer(); + for (int i = 0; i < printer->custom_menus_count; i++) + { + create_state_button(right_panel, (lv_event_cb_t)printer->custom_menus[i].set_label, (lv_event_cb_t)printer->custom_menus[i].open_panel); + } } \ No newline at end of file diff --git a/CYD-Klipper/src/ui/panels/temp_panel.cpp b/CYD-Klipper/src/ui/panels/temp_panel.cpp index 5880eaf..c360946 100644 --- a/CYD-Klipper/src/ui/panels/temp_panel.cpp +++ b/CYD-Klipper/src/ui/panels/temp_panel.cpp @@ -1,8 +1,8 @@ #include "lvgl.h" -#include "../../core/data_setup.h" #include "../../conf/global_config.h" #include #include "../ui_utils.h" +#include "../../core/printer_integration.hpp" enum temp_target{ TARGET_HOTEND, @@ -16,37 +16,43 @@ enum temp_target{ }; static temp_target keyboard_target; -static char hotend_buff[40]; -static char bed_buff[40]; + + static bool temp_edit_mode = false; lv_obj_t* root_panel; static void update_printer_data_hotend_temp(lv_event_t * e){ lv_obj_t * label = lv_event_get_target(e); - sprintf(hotend_buff, "Hotend: %.0f C (Target: %.0f C)", printer.extruder_temp, printer.extruder_target_temp); + char hotend_buff[40]; + sprintf(hotend_buff, "Hotend: %.0f C (Target: %.0f C)", + get_current_printer_data()->temperatures[PrinterTemperatureDeviceIndex::PrinterTemperatureDeviceIndexNozzle1], + get_current_printer_data()->target_temperatures[PrinterTemperatureDeviceIndex::PrinterTemperatureDeviceIndexNozzle1]); lv_label_set_text(label, hotend_buff); } static void update_printer_data_bed_temp(lv_event_t * e){ lv_obj_t * label = lv_event_get_target(e); - sprintf(bed_buff, "Bed: %.0f C (Target: %.0f C)", printer.bed_temp, printer.bed_target_temp); + char bed_buff[40]; + sprintf(bed_buff, "Bed: %.0f C (Target: %.0f C)", + get_current_printer_data()->temperatures[PrinterTemperatureDeviceIndex::PrinterTemperatureDeviceIndexBed], + get_current_printer_data()->target_temperatures[PrinterTemperatureDeviceIndex::PrinterTemperatureDeviceIndexBed]); lv_label_set_text(label, bed_buff); } static short get_temp_preset(int target){ switch (target){ case TARGET_HOTEND_CONFIG_1: - return get_current_printer_config()->hotend_presets[0]; + return get_current_printer()->printer_config->hotend_presets[0]; case TARGET_HOTEND_CONFIG_2: - return get_current_printer_config()->hotend_presets[1]; + return get_current_printer()->printer_config->hotend_presets[1]; case TARGET_HOTEND_CONFIG_3: - return get_current_printer_config()->hotend_presets[2]; + return get_current_printer()->printer_config->hotend_presets[2]; case TARGET_BED_CONFIG_1: - return get_current_printer_config()->bed_presets[0]; + return get_current_printer()->printer_config->bed_presets[0]; case TARGET_BED_CONFIG_2: - return get_current_printer_config()->bed_presets[1]; + return get_current_printer()->printer_config->bed_presets[1]; case TARGET_BED_CONFIG_3: - return get_current_printer_config()->bed_presets[2]; + return get_current_printer()->printer_config->bed_presets[2]; default: return -1; } @@ -63,7 +69,7 @@ static void update_temp_preset_label(lv_event_t * e){ void UpdateConfig(){ write_global_config(); - lv_msg_send(DATA_PRINTER_TEMP_PRESET, &printer); + lv_msg_send(DATA_PRINTER_TEMP_PRESET, get_current_printer()); } static void keyboard_callback(lv_event_t * e){ @@ -76,40 +82,36 @@ static void keyboard_callback(lv_event_t * e){ if (temp < 0 || temp > 500){ return; } - - char gcode[64]; switch (keyboard_target){ case TARGET_HOTEND: - sprintf(gcode, "M104 S%d", temp); - send_gcode(true, gcode); + get_current_printer()->set_target_temperature(PrinterTemperatureDevice::PrinterTemperatureDeviceNozzle1, temp); break; case TARGET_BED: - sprintf(gcode, "M140 S%d", temp); - send_gcode(true, gcode); + get_current_printer()->set_target_temperature(PrinterTemperatureDevice::PrinterTemperatureDeviceBed, temp); break; case TARGET_HOTEND_CONFIG_1: - get_current_printer_config()->hotend_presets[0] = temp; + get_current_printer()->printer_config->hotend_presets[0] = temp; UpdateConfig(); break; case TARGET_HOTEND_CONFIG_2: - get_current_printer_config()->hotend_presets[1] = temp; + get_current_printer()->printer_config->hotend_presets[1] = temp; UpdateConfig(); break; case TARGET_HOTEND_CONFIG_3: - get_current_printer_config()->hotend_presets[2] = temp; + get_current_printer()->printer_config->hotend_presets[2] = temp; UpdateConfig(); break; case TARGET_BED_CONFIG_1: - get_current_printer_config()->bed_presets[0] = temp; + get_current_printer()->printer_config->bed_presets[0] = temp; UpdateConfig(); break; case TARGET_BED_CONFIG_2: - get_current_printer_config()->bed_presets[1] = temp; + get_current_printer()->printer_config->bed_presets[1] = temp; UpdateConfig(); break; case TARGET_BED_CONFIG_3: - get_current_printer_config()->bed_presets[2] = temp; + get_current_printer()->printer_config->bed_presets[2] = temp; UpdateConfig(); break; } @@ -126,28 +128,19 @@ static void show_keyboard_with_bed(lv_event_t * e){ } static void cooldown_temp(lv_event_t * e){ - if (printer.state == PRINTER_STATE_PRINTING){ + if (get_current_printer_data()->state == PrinterState::PrinterStatePrinting){ return; } - send_gcode(true, "M104 S0"); - send_gcode(true, "M140 S0"); + get_current_printer()->execute_feature(PrinterFeatures::PrinterFeatureCooldown); } static void btn_extrude(lv_event_t * e){ - if (printer.state == PRINTER_STATE_PRINTING){ + if (get_current_printer_data()->state == PrinterState::PrinterStatePrinting){ return; } - if (get_current_printer_config()->custom_filament_move_macros) - { - send_gcode(true, "FILAMENT_EXTRUDE"); - } - else - { - send_gcode(true, "M83"); - send_gcode(true, "G1 E25 F300"); - } + get_current_printer()->execute_feature(PrinterFeatures::PrinterFeatureExtrude); } static void set_temp_via_preset(lv_event_t * e){ @@ -160,13 +153,10 @@ static void set_temp_via_preset(lv_event_t * e){ return; } - char gcode[64]; - if (target <= TARGET_HOTEND_CONFIG_3) - sprintf(gcode, "M104 S%d", value); - else - sprintf(gcode, "M140 S%d", value); - - send_gcode(true, gcode); + get_current_printer()->set_target_temperature(TARGET_HOTEND_CONFIG_3 + ? PrinterTemperatureDevice::PrinterTemperatureDeviceNozzle1 + : PrinterTemperatureDevice::PrinterTemperatureDeviceBed + , value); } static void btn_toggleable_edit(lv_event_t * e){ @@ -176,19 +166,11 @@ static void btn_toggleable_edit(lv_event_t * e){ } static void btn_retract(lv_event_t * e){ - if (printer.state == PRINTER_STATE_PRINTING){ + if (get_current_printer_data()->state == PrinterState::PrinterStatePrinting){ return; } - if (get_current_printer_config()->custom_filament_move_macros) - { - send_gcode(true, "FILAMENT_RETRACT"); - } - else - { - send_gcode(true, "M83"); - send_gcode(true, "G1 E-25 F300"); - } + get_current_printer()->execute_feature(PrinterFeatures::PrinterFeatureRetract); } static void set_chart_range(lv_event_t * e) { @@ -218,25 +200,25 @@ static void set_chart_range(lv_event_t * e) { static void set_hotend_temp_chart(lv_event_t * e){ lv_obj_t * chart = lv_event_get_target(e); lv_chart_series_t * series = (lv_chart_series_t *)lv_event_get_user_data(e); - lv_chart_set_next_value(chart, series, printer.extruder_temp); + lv_chart_set_next_value(chart, series, get_current_printer_data()->temperatures[PrinterTemperatureDeviceIndex::PrinterTemperatureDeviceIndexNozzle1]); } static void set_hotend_target_temp_chart(lv_event_t * e){ lv_obj_t * chart = lv_event_get_target(e); lv_chart_series_t * series = (lv_chart_series_t *)lv_event_get_user_data(e); - lv_chart_set_next_value(chart, series, printer.extruder_target_temp); + lv_chart_set_next_value(chart, series, get_current_printer_data()->target_temperatures[PrinterTemperatureDeviceIndex::PrinterTemperatureDeviceIndexNozzle1]); } static void set_bed_temp_chart(lv_event_t * e){ lv_obj_t * chart = lv_event_get_target(e); lv_chart_series_t * series = (lv_chart_series_t *)lv_event_get_user_data(e); - lv_chart_set_next_value(chart, series, printer.bed_temp); + lv_chart_set_next_value(chart, series, get_current_printer_data()->temperatures[PrinterTemperatureDeviceIndex::PrinterTemperatureDeviceIndexBed]); } static void set_bed_target_temp_chart(lv_event_t * e){ lv_obj_t * chart = lv_event_get_target(e); lv_chart_series_t * series = (lv_chart_series_t *)lv_event_get_user_data(e); - lv_chart_set_next_value(chart, series, printer.bed_target_temp); + lv_chart_set_next_value(chart, series, get_current_printer_data()->target_temperatures[PrinterTemperatureDeviceIndex::PrinterTemperatureDeviceIndexBed]); } void create_charts(lv_obj_t * root) @@ -251,13 +233,13 @@ void create_charts(lv_obj_t * root) lv_chart_set_update_mode(chart, LV_CHART_UPDATE_MODE_SHIFT); lv_chart_series_t * ser1 = lv_chart_add_series(chart, lv_palette_main(LV_PALETTE_ORANGE), LV_CHART_AXIS_PRIMARY_Y); - lv_chart_set_all_value(chart, ser1, printer.extruder_target_temp); + lv_chart_set_all_value(chart, ser1, get_current_printer_data()->target_temperatures[PrinterTemperatureDeviceIndex::PrinterTemperatureDeviceIndexNozzle1]); lv_chart_series_t * ser2 = lv_chart_add_series(chart, lv_palette_main(LV_PALETTE_RED), LV_CHART_AXIS_PRIMARY_Y); - lv_chart_set_all_value(chart, ser2, printer.extruder_temp); + lv_chart_set_all_value(chart, ser2, get_current_printer_data()->temperatures[PrinterTemperatureDeviceIndex::PrinterTemperatureDeviceIndexNozzle1]); lv_chart_series_t * ser3 = lv_chart_add_series(chart, lv_palette_main(LV_PALETTE_TEAL), LV_CHART_AXIS_PRIMARY_Y); - lv_chart_set_all_value(chart, ser3, printer.bed_target_temp); + lv_chart_set_all_value(chart, ser3, get_current_printer_data()->temperatures[PrinterTemperatureDeviceIndex::PrinterTemperatureDeviceIndexBed]); lv_chart_series_t * ser4 = lv_chart_add_series(chart, lv_palette_main(LV_PALETTE_BLUE), LV_CHART_AXIS_PRIMARY_Y); - lv_chart_set_all_value(chart, ser4, printer.bed_temp); + lv_chart_set_all_value(chart, ser4, get_current_printer_data()->target_temperatures[PrinterTemperatureDeviceIndex::PrinterTemperatureDeviceIndexBed]); lv_obj_add_event_cb(chart, set_hotend_target_temp_chart, LV_EVENT_MSG_RECEIVED, ser1); lv_obj_add_event_cb(chart, set_hotend_temp_chart, LV_EVENT_MSG_RECEIVED, ser2); @@ -391,5 +373,5 @@ void temp_panel_init(lv_obj_t * panel){ lv_obj_center(label); lv_obj_scroll_to_y(root_temp_panel, 9999, LV_ANIM_OFF); - lv_msg_send(DATA_PRINTER_TEMP_PRESET, &printer); + lv_msg_send(DATA_PRINTER_TEMP_PRESET, get_current_printer()); } \ No newline at end of file From c35b14676264a5e48e2cb96be859729edb3e6b60 Mon Sep 17 00:00:00 2001 From: suchmememanyskill <38142618+suchmememanyskill@users.noreply.github.com> Date: Sun, 27 Oct 2024 01:53:00 +0200 Subject: [PATCH 10/63] Explicit cast to void* --- CYD-Klipper/src/core/klipper/klipper_printer_panels.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/CYD-Klipper/src/core/klipper/klipper_printer_panels.cpp b/CYD-Klipper/src/core/klipper/klipper_printer_panels.cpp index b65bfb1..2e1a27f 100644 --- a/CYD-Klipper/src/core/klipper/klipper_printer_panels.cpp +++ b/CYD-Klipper/src/core/klipper/klipper_printer_panels.cpp @@ -169,10 +169,10 @@ static void open_extrude_mult_panel(lv_event_t * e){ } static PrinterUiPanel klipper_ui_panels[4] { - { .set_label = set_fan_speed_text, .open_panel = open_fan_speed_panel }, - { .set_label = set_zoffset_text, .open_panel = open_zoffset_panel }, - { .set_label = set_speed_mult_text, .open_panel = open_speed_mult_panel }, - { .set_label = set_extrude_mult_text, .open_panel = open_extrude_mult_panel } + { .set_label = (void*)set_fan_speed_text, .open_panel = (void*)open_fan_speed_panel }, + { .set_label = (void*)set_zoffset_text, .open_panel = (void*)open_zoffset_panel }, + { .set_label = (void*)set_speed_mult_text, .open_panel = (void*)open_speed_mult_panel }, + { .set_label = (void*)set_extrude_mult_text, .open_panel = (void*)open_extrude_mult_panel } }; void KlipperPrinter::init_ui_panels() From be0bf0fc71d8eeddb4cd525ca10de72127eb8b59 Mon Sep 17 00:00:00 2001 From: suchmememanyskill <38142618+suchmememanyskill@users.noreply.github.com> Date: Sun, 27 Oct 2024 15:23:25 +0100 Subject: [PATCH 11/63] Printer init --- CYD-Klipper/src/conf/global_config.cpp | 66 ++++++++++++++++++- CYD-Klipper/src/conf/global_config.h | 14 ++-- CYD-Klipper/src/core/data_setup.cpp | 17 +++++ .../core/klipper/klipper_printer_panels.cpp | 1 - CYD-Klipper/src/core/printer_integration.cpp | 27 ++++---- CYD-Klipper/src/core/printer_integration.hpp | 4 +- CYD-Klipper/src/ui/panels/printer_panel.cpp | 6 +- 7 files changed, 103 insertions(+), 32 deletions(-) diff --git a/CYD-Klipper/src/conf/global_config.cpp b/CYD-Klipper/src/conf/global_config.cpp index 613e635..91b42b0 100644 --- a/CYD-Klipper/src/conf/global_config.cpp +++ b/CYD-Klipper/src/conf/global_config.cpp @@ -46,11 +46,11 @@ PrinterConfiguration* get_current_printer_config() return &global_config.printer_config[global_config.printer_index]; } -int get_printer_config_count() +int global_config_get_printer_config_count() { int count = 0; for (int i = 0; i < PRINTER_CONFIG_COUNT; i++) { - if (global_config.printer_config[i].ip_configured) + if (global_config.printer_config[i].setup_complete) count++; } return count; @@ -59,12 +59,72 @@ int get_printer_config_count() int get_printer_config_free_index() { for (int i = 0; i < PRINTER_CONFIG_COUNT; i++) { - if (!global_config.printer_config[i].ip_configured) + if (!global_config.printer_config[i].setup_complete) return i; } return -1; } +void global_config_add_new_printer() +{ + int free_index = get_printer_config_free_index(); + if (free_index <= -1) + { + return; + } + + PrinterConfiguration* old_config = &global_config.printer_config[global_config.printer_index]; + PrinterConfiguration* new_config = &global_config.printer_config[free_index]; + + new_config->raw = old_config->raw; + new_config->ip_configured = false; + new_config->auth_configured = false; + + new_config->printer_name[0] = 0; + new_config->klipper_host[0] = 0; + new_config->klipper_auth[0] = 0; + new_config->klipper_port = 0; + + new_config->color_scheme = old_config->color_scheme; + + // TODO: Replace with memcpy + for (int i = 0; i < 3; i++){ + new_config->hotend_presets[i] = old_config->hotend_presets[i]; + new_config->bed_presets[i] = old_config->bed_presets[i]; + } + + for (int i = 0; i < 3; i++){ + new_config->printer_move_x_steps[i] = old_config->printer_move_x_steps[i]; + new_config->printer_move_y_steps[i] = old_config->printer_move_y_steps[i]; + new_config->printer_move_z_steps[i] = old_config->printer_move_z_steps[i]; + } + + write_global_config(); + ESP.restart(); +} + +void global_config_set_printer(int idx) +{ + if (idx < 0 || idx >= PRINTER_CONFIG_COUNT) + return; + + global_config.printer_index = idx; + write_global_config(); +} + +void global_config_delete_printer(int idx) +{ + if (global_config.printer_index == idx) + { + return; + } + + PrinterConfiguration* config = &global_config.printer_config[idx]; + config->setup_complete = false; + write_global_config(); + ESP.restart(); +} + void set_printer_config_index(int index) { if (index < 0 || index >= PRINTER_CONFIG_COUNT) diff --git a/CYD-Klipper/src/conf/global_config.h b/CYD-Klipper/src/conf/global_config.h index c9a7c06..2dcf3c1 100644 --- a/CYD-Klipper/src/conf/global_config.h +++ b/CYD-Klipper/src/conf/global_config.h @@ -3,7 +3,7 @@ #include "lvgl.h" -#define CONFIG_VERSION 6 +#define CONFIG_VERSION 7 #define PRINTER_CONFIG_COUNT 8 #define DISPLAY_SECRETS 0 @@ -32,17 +32,17 @@ typedef struct { unsigned int raw; struct { // Internal + bool setup_complete : 1; bool ip_configured : 1; bool auth_configured : 1; + bool custom_filament_move_macros : 1; + PrinterType printer_type : 3; // External bool light_mode : 1; bool invert_colors : 1; unsigned char remaining_time_calc_mode : 2; unsigned char show_stats_on_progress_panel : 2; - - bool custom_filament_move_macros : 1; - PrinterType printer_type : 3; }; }; @@ -122,8 +122,12 @@ void write_global_config(); void verify_version(); void load_global_config(); +void global_config_add_new_printer(); +void global_config_set_printer(int idx); +void global_config_delete_printer(int idx); + //PRINTER_CONFIG* get_current_printer_config(); -//int get_printer_config_count(); +int global_config_get_printer_config_count(); //void set_printer_config_index(int index); //int get_printer_config_free_index(); diff --git a/CYD-Klipper/src/core/data_setup.cpp b/CYD-Klipper/src/core/data_setup.cpp index 89053b5..fdcb89c 100644 --- a/CYD-Klipper/src/core/data_setup.cpp +++ b/CYD-Klipper/src/core/data_setup.cpp @@ -3,6 +3,7 @@ #include #include #include "printer_integration.hpp" +#include "klipper/klipper_printer_integration.hpp" SemaphoreHandle_t freezeRenderThreadSemaphore, freezeRequestThreadSemaphore; const long data_update_interval = 780; @@ -101,6 +102,22 @@ TaskHandle_t background_loop; void data_setup() { + BasePrinter** available_printers = (BasePrinter**)malloc(sizeof(BasePrinter*) * PRINTER_CONFIG_COUNT); + int count = 0; + + for (int i = 0; i < PRINTER_CONFIG_COUNT; i++) + { + if (global_config.printer_config[i].setup_complete) + { + switch (global_config.printer_config[i].printer_type) + { + case PrinterType::PrinterTypeKlipper: + available_printers[count++] = new KlipperPrinter(i); + } + } + } + + initialize_printers(available_printers, count); semaphore_init(); fetch_printer_data(); freeze_render_thread(); diff --git a/CYD-Klipper/src/core/klipper/klipper_printer_panels.cpp b/CYD-Klipper/src/core/klipper/klipper_printer_panels.cpp index 2e1a27f..de9e394 100644 --- a/CYD-Klipper/src/core/klipper/klipper_printer_panels.cpp +++ b/CYD-Klipper/src/core/klipper/klipper_printer_panels.cpp @@ -3,7 +3,6 @@ #include "../../ui/ui_utils.h" #include - static void set_fan_speed_text(lv_event_t * e) { lv_obj_t * label = lv_event_get_target(e); char data[16]; diff --git a/CYD-Klipper/src/core/printer_integration.cpp b/CYD-Klipper/src/core/printer_integration.cpp index 725369c..5130862 100644 --- a/CYD-Klipper/src/core/printer_integration.cpp +++ b/CYD-Klipper/src/core/printer_integration.cpp @@ -4,13 +4,14 @@ unsigned char current_printer_index = 0; unsigned char total_printers; -BasePrinter* registered_printers; +BasePrinter** registered_printers; PrinterDataMinimal* minimal_data_copy; PrinterData* printer_data_copy; BasePrinter::BasePrinter(unsigned char index) { config_index = index; + printer_config = &global_config.printer_config[index]; printer_data.state_message = (char*)malloc(1); printer_data.print_filename = (char*)malloc(1); @@ -54,9 +55,13 @@ PrinterData* BasePrinter::AnnouncePrinterData() lv_msg_send(DATA_PRINTER_DATA, get_current_printer()); } -void initialize_printers() +void initialize_printers(BasePrinter** printers, unsigned char total) { printer_data_copy = (PrinterData*)malloc(sizeof(PrinterData)); + minimal_data_copy = (PrinterDataMinimal*)malloc(sizeof(PrinterDataMinimal) * total_printers); + memset(minimal_data_copy, 0, sizeof(PrinterDataMinimal) * total_printers); + registered_printers = printers; + total_printers = total; } BasePrinter* get_current_printer() @@ -66,7 +71,7 @@ BasePrinter* get_current_printer() BasePrinter* get_printer(int idx) { - return registered_printers + idx; + return registered_printers[idx]; } int get_current_printer_index() @@ -86,7 +91,7 @@ unsigned int get_printer_count() void announce_printer_data_minimal(PrinterDataMinimal* printer_data) { - memcpy(printer_data_copy, printer_data, sizeof(PrinterDataMinimal) * total_printers); + memcpy(minimal_data_copy, printer_data, sizeof(PrinterDataMinimal) * total_printers); lv_msg_send(DATA_PRINTER_MINIMAL, get_current_printer()); } @@ -95,20 +100,10 @@ PrinterDataMinimal* get_printer_data_minimal(int idx) return &(minimal_data_copy[idx]); } -void BasePrinter::save_printer_config() -{ - // TODO -} - - -void add_printer() -{ - -} - void set_current_printer(int idx) { - //set_printer_config_index(index); + current_printer_index = idx; + global_config_set_printer(idx); set_color_scheme(); set_invert_display(); } \ No newline at end of file diff --git a/CYD-Klipper/src/core/printer_integration.hpp b/CYD-Klipper/src/core/printer_integration.hpp index 7c34875..3381165 100644 --- a/CYD-Klipper/src/core/printer_integration.hpp +++ b/CYD-Klipper/src/core/printer_integration.hpp @@ -163,7 +163,6 @@ class BasePrinter BasePrinter(unsigned char index); PrinterData* AnnouncePrinterData(); - void save_printer_config(); }; #define DATA_PRINTER_STATE 1 @@ -174,11 +173,10 @@ class BasePrinter BasePrinter* get_current_printer(); BasePrinter* get_printer(int idx); -void initialize_printers(); +void initialize_printers(BasePrinter** printers, unsigned char total); PrinterData* get_current_printer_data(); unsigned int get_printer_count(); void announce_printer_data_minimal(PrinterDataMinimal* printer_data); PrinterDataMinimal* get_printer_data_minimal(int idx); int get_current_printer_index(); -void add_printer(); void set_current_printer(int idx); \ No newline at end of file diff --git a/CYD-Klipper/src/ui/panels/printer_panel.cpp b/CYD-Klipper/src/ui/panels/printer_panel.cpp index b048437..fefca49 100644 --- a/CYD-Klipper/src/ui/panels/printer_panel.cpp +++ b/CYD-Klipper/src/ui/panels/printer_panel.cpp @@ -165,9 +165,7 @@ static void btn_printer_secondary(lv_event_t * e) return; } - printer->printer_config->ip_configured = false; - write_global_config(); - + global_config_delete_printer(config_index); nav_buttons_setup(PANEL_PRINTER); } @@ -196,7 +194,7 @@ static void btn_printer_activate(lv_event_t * e) static void btn_printer_add(lv_event_t * e) { - add_printer(); + global_config_add_new_printer(); } void create_printer_ui(PrinterConfiguration * config, lv_obj_t * root) From 75bb334b09b0155d1044e706c8a58b4c50117b1f Mon Sep 17 00:00:00 2001 From: suchmememanyskill <38142618+suchmememanyskill@users.noreply.github.com> Date: Sun, 27 Oct 2024 17:15:46 +0100 Subject: [PATCH 12/63] Use new image system --- .../klipper/klipper_printer_integration.cpp | 18 ++- .../klipper/klipper_printer_integration.hpp | 2 +- CYD-Klipper/src/core/printer_integration.hpp | 9 +- CYD-Klipper/src/ui/gcode_img.cpp | 141 ------------------ CYD-Klipper/src/ui/gcode_img.h | 6 - CYD-Klipper/src/ui/panels/files_panel.cpp | 23 ++- 6 files changed, 38 insertions(+), 161 deletions(-) delete mode 100644 CYD-Klipper/src/ui/gcode_img.cpp delete mode 100644 CYD-Klipper/src/ui/gcode_img.h diff --git a/CYD-Klipper/src/core/klipper/klipper_printer_integration.cpp b/CYD-Klipper/src/core/klipper/klipper_printer_integration.cpp index 5edd7dd..e8e8d7e 100644 --- a/CYD-Klipper/src/core/klipper/klipper_printer_integration.cpp +++ b/CYD-Klipper/src/core/klipper/klipper_printer_integration.cpp @@ -716,8 +716,9 @@ bool KlipperPrinter::set_target_temperature(PrinterTemperatureDevice device, uns return send_gcode(gcode); } -unsigned char* KlipperPrinter::get_32_32_png_image_thumbnail(const char* gcode_filename) +Thumbnail KlipperPrinter::get_32_32_png_image_thumbnail(const char* gcode_filename) { + Thumbnail thumbnail = {0}; HTTPClient client; configure_http_client(client, "/server/files/thumbnails?filename=", true, 1000); char* img_filename_path = NULL; @@ -731,7 +732,7 @@ unsigned char* KlipperPrinter::get_32_32_png_image_thumbnail(const char* gcode_f catch (...) { LOG_LN("Exception while fetching gcode img location"); - return NULL; + return thumbnail; } if (http_code == 200) @@ -770,7 +771,7 @@ unsigned char* KlipperPrinter::get_32_32_png_image_thumbnail(const char* gcode_f if (img_filename_path == NULL) { - return NULL; + return thumbnail; } client.end(); @@ -785,7 +786,7 @@ unsigned char* KlipperPrinter::get_32_32_png_image_thumbnail(const char* gcode_f catch (...) { LOG_LN("Exception while fetching gcode img"); - return NULL; + return thumbnail; } if (http_code == 200) @@ -794,7 +795,7 @@ unsigned char* KlipperPrinter::get_32_32_png_image_thumbnail(const char* gcode_f if (len <= 0) { LOG_LN("No gcode img data"); - return NULL; + return thumbnail; } data_png = (unsigned char*)malloc(len + 1); @@ -808,12 +809,13 @@ unsigned char* KlipperPrinter::get_32_32_png_image_thumbnail(const char* gcode_f } else { - free(img_filename_path); - return data_png; + thumbnail.png = data_png; + thumbnail.size = len; + thumbnail.success = true; } } } free(img_filename_path); - return NULL; + return thumbnail; } \ No newline at end of file diff --git a/CYD-Klipper/src/core/klipper/klipper_printer_integration.hpp b/CYD-Klipper/src/core/klipper/klipper_printer_integration.hpp index d758c91..e67e518 100644 --- a/CYD-Klipper/src/core/klipper/klipper_printer_integration.hpp +++ b/CYD-Klipper/src/core/klipper/klipper_printer_integration.hpp @@ -47,7 +47,7 @@ class KlipperPrinter : public BasePrinter bool set_power_device_state(const char* device_name, bool state); Files get_files(); bool start_file(const char* filename); - unsigned char* get_32_32_png_image_thumbnail(const char* gcode_filename); + Thumbnail get_32_32_png_image_thumbnail(const char* gcode_filename); bool set_target_temperature(PrinterTemperatureDevice device, unsigned int temperature); bool send_gcode(const char* gcode, bool wait = true); int get_slicer_time_estimate_s(); diff --git a/CYD-Klipper/src/core/printer_integration.hpp b/CYD-Klipper/src/core/printer_integration.hpp index 3381165..1b377af 100644 --- a/CYD-Klipper/src/core/printer_integration.hpp +++ b/CYD-Klipper/src/core/printer_integration.hpp @@ -128,6 +128,12 @@ typedef struct { void* open_panel; // type lv_event_cb_t } PrinterUiPanel; +typedef struct { + bool success; + unsigned int size; + unsigned char* png; +} Thumbnail; + class BasePrinter { protected: @@ -158,7 +164,8 @@ class BasePrinter // Free files externally when done virtual Files get_files() = 0; virtual bool start_file(const char* filename) = 0; - virtual unsigned char* get_32_32_png_image_thumbnail(const char* gcode_filename); + // Free thumbnail externally when done + virtual Thumbnail get_32_32_png_image_thumbnail(const char* gcode_filename); virtual bool set_target_temperature(PrinterTemperatureDevice device, unsigned int temperature) = 0; BasePrinter(unsigned char index); diff --git a/CYD-Klipper/src/ui/gcode_img.cpp b/CYD-Klipper/src/ui/gcode_img.cpp deleted file mode 100644 index bae3057..0000000 --- a/CYD-Klipper/src/ui/gcode_img.cpp +++ /dev/null @@ -1,141 +0,0 @@ -#include "gcode_img.h" -#include "lvgl.h" -#include "ui_utils.h" -#include -#include -#include -#include "../conf/global_config.h" -#include "../core/http_client.h" - -static unsigned char * data_png = NULL; -static char img_filename_path[256] = {0}; -static lv_img_dsc_t img_header = {0}; - -bool has_32_32_gcode_img(const char* filename) -{ - if (filename == NULL){ - LOG_LN("No gcode filename"); - return false; - } - - SETUP_HTTP_CLIENT("/server/files/thumbnails?filename=" + urlEncode(filename)); - int httpCode = 0; - try { - httpCode = client.GET(); - } - catch (...){ - LOG_LN("Exception while fetching gcode img location"); - return false; - } - - if (httpCode == 200) - { - JsonDocument doc; - deserializeJson(doc, client.getStream()); - auto result = doc["result"].as(); - const char* chosen_thumb = NULL; - - for (auto file : result){ - int width = file["width"]; - int height = file["height"]; - int size = file["size"]; - const char* thumbnail = file["thumbnail_path"]; - - if (width != height || width != 32) - continue; - - if (strcmp(thumbnail + strlen(thumbnail) - 4, ".png")) - continue; - - chosen_thumb = thumbnail; - break; - } - - if (chosen_thumb != NULL){ - LOG_F(("Found 32x32 PNG gcode img at %s\n", filename)) - strcpy(img_filename_path, chosen_thumb); - return true; - } - } - else - { - LOG_F(("Failed to fetch gcode image data: %d\n", httpCode)) - } - - return false; -} - -lv_obj_t* draw_gcode_img() -{ - clear_img_mem(); - - if (img_filename_path[0] == 0){ - LOG_LN("No gcode img path"); - return NULL; - } - - SETUP_HTTP_CLIENT_FULL("/server/files/gcodes/" + urlEncode(img_filename_path), false, 2000); - - int httpCode = 0; - try { - httpCode = client.GET(); - } - catch (...){ - LOG_LN("Exception while fetching gcode img"); - return NULL; - } - - if (httpCode == 200) - { - size_t len = client.getSize(); - if (len <= 0) - { - LOG_LN("No gcode img data"); - return NULL; - } - - data_png = (unsigned char*)malloc(len + 1); - if (len != client.getStream().readBytes(data_png, len)){ - LOG_LN("Failed to read gcode img data"); - clear_img_mem(); - return NULL; - } - - memset(&img_header, 0, sizeof(img_header)); - img_header.header.w = 32; - img_header.header.h = 32; - img_header.data_size = len; - img_header.header.cf = LV_IMG_CF_RAW_ALPHA; - img_header.data = data_png; - - lv_obj_t * img = lv_img_create(lv_scr_act()); - lv_img_set_src(img, &img_header); - - return img; - } - - return NULL; -} - -lv_obj_t* show_gcode_img(const char* filename) -{ - if (filename == NULL){ - LOG_LN("No gcode filename"); - return NULL; - } - - if (!has_32_32_gcode_img(filename)){ - LOG_LN("No 32x32 gcode img found"); - return NULL; - } - - return draw_gcode_img(); -} - -void clear_img_mem() -{ - if (data_png != NULL){ - free(data_png); - data_png = NULL; - } -} \ No newline at end of file diff --git a/CYD-Klipper/src/ui/gcode_img.h b/CYD-Klipper/src/ui/gcode_img.h deleted file mode 100644 index ba591a9..0000000 --- a/CYD-Klipper/src/ui/gcode_img.h +++ /dev/null @@ -1,6 +0,0 @@ -#pragma once -#include "lvgl.h" - -lv_obj_t* show_gcode_img(const char* filename); -bool has_32_32_gcode_img(const char* filename); -void clear_img_mem(); \ No newline at end of file diff --git a/CYD-Klipper/src/ui/panels/files_panel.cpp b/CYD-Klipper/src/ui/panels/files_panel.cpp index e720d8e..87aa77e 100644 --- a/CYD-Klipper/src/ui/panels/files_panel.cpp +++ b/CYD-Klipper/src/ui/panels/files_panel.cpp @@ -6,7 +6,6 @@ #include #include "../ui_utils.h" #include "../../core/lv_setup.h" -#include "../gcode_img.h" #include #include "../../core/printer_integration.hpp" @@ -62,10 +61,26 @@ static void btn_print_file_verify(lv_event_t * e){ lv_label_set_text(label, LV_SYMBOL_OK); lv_obj_center(label); - lv_obj_t* img = show_gcode_img(selected_file); + freeze_request_thread(); + Thumbnail thumbnail = get_current_printer()->get_32_32_png_image_thumbnail(selected_file); + unfreeze_request_thread(); - if (img != NULL){ - lv_obj_set_parent(img, panel); + lv_obj_t * img = NULL; + + if (thumbnail.success) + { + lv_img_dsc_t* img_header = (lv_img_dsc_t*)malloc(sizeof(lv_img_dsc_t)); + lv_obj_on_destroy_free_data(panel, img_header); + + memset(img_header, 0, sizeof(img_header)); + img_header->header.w = 32; + img_header->header.h = 32; + img_header->data_size = thumbnail.size; + img_header->header.cf = LV_IMG_CF_RAW_ALPHA; + img_header->data = thumbnail.png; + + img = lv_img_create(panel); + lv_img_set_src(img, img_header); lv_obj_align(img, LV_ALIGN_TOP_LEFT, 0, 0); lv_obj_t * text_center_panel = lv_create_empty_panel(panel); From 6273e10e5a408ec414ca12da07e09cf9f7c55f77 Mon Sep 17 00:00:00 2001 From: suchmememanyskill <38142618+suchmememanyskill@users.noreply.github.com> Date: Sun, 27 Oct 2024 19:08:21 +0100 Subject: [PATCH 13/63] More --- CYD-Klipper/platformio.ini | 3 -- CYD-Klipper/src/ui/main_ui.cpp | 8 +++- CYD-Klipper/src/ui/nav_buttons.cpp | 22 +++++------ CYD-Klipper/src/ui/ota_setup.cpp | 8 ---- CYD-Klipper/src/ui/serial/serial_commands.cpp | 37 ++++++++++--------- CYD-Klipper/src/ui/ui_utils.cpp | 14 +------ 6 files changed, 37 insertions(+), 55 deletions(-) diff --git a/CYD-Klipper/platformio.ini b/CYD-Klipper/platformio.ini index 87de374..3969297 100644 --- a/CYD-Klipper/platformio.ini +++ b/CYD-Klipper/platformio.ini @@ -33,7 +33,6 @@ lib_deps = https://github.com/PaulStoffregen/XPT2046_Touchscreen.git bblanchon/ArduinoJson@^7.0.0 plageoj/UrlEncode@^1.0.1 - erriez/ErriezCRC32 @ ^1.0.1 [env:esp32-3248S035C] board = esp32-3248S035C @@ -44,7 +43,6 @@ lib_deps = https://github.com/OperatorB/gt911-arduino-fixed-reset.git bblanchon/ArduinoJson@^7.0.0 plageoj/UrlEncode@^1.0.1 - erriez/ErriezCRC32 @ ^1.0.1 [env:esp32-3248S035C-V] board = esp32-3248S035C-vertical @@ -55,7 +53,6 @@ lib_deps = https://github.com/OperatorB/gt911-arduino-fixed-reset.git bblanchon/ArduinoJson@^7.0.0 plageoj/UrlEncode@^1.0.1 - erriez/ErriezCRC32 @ ^1.0.1 [env:esp32-2432S024C-SD] board = esp32-2432S024C-smartdisplay diff --git a/CYD-Klipper/src/ui/main_ui.cpp b/CYD-Klipper/src/ui/main_ui.cpp index 9df1686..c18a300 100644 --- a/CYD-Klipper/src/ui/main_ui.cpp +++ b/CYD-Klipper/src/ui/main_ui.cpp @@ -38,11 +38,15 @@ static void on_state_change(void * s, lv_msg_t * m){ else { nav_buttons_setup(PANEL_PROGRESS); } - - lv_msg_send(DATA_PRINTER_DATA, get_current_printer()); +} + +static void on_popup_message(void * s, lv_msg_t * m) +{ + lv_create_popup_message(get_current_printer_data()->popup_message, 10000); } void main_ui_setup(){ lv_msg_subscribe(DATA_PRINTER_STATE, on_state_change, NULL); + lv_msg_subscribe(DATA_PRINTER_POPUP, on_popup_message, NULL); on_state_change(NULL, NULL); } \ No newline at end of file diff --git a/CYD-Klipper/src/ui/nav_buttons.cpp b/CYD-Klipper/src/ui/nav_buttons.cpp index d02f5de..bc2fcc8 100644 --- a/CYD-Klipper/src/ui/nav_buttons.cpp +++ b/CYD-Klipper/src/ui/nav_buttons.cpp @@ -1,10 +1,10 @@ #include "lvgl.h" #include "panels/panel.h" -#include "../core/data_setup.h" #include "nav_buttons.h" #include "ui_utils.h" #include #include "../conf/global_config.h" +#include "../core/printer_integration.hpp" static lv_style_t nav_button_style; @@ -17,31 +17,31 @@ static lv_style_t nav_button_text_style; static void update_printer_data_z_pos(lv_event_t * e) { lv_obj_t * label = lv_event_get_target(e); - sprintf(z_pos_buffer, "Z%.2f", printer.position[2]); + sprintf(z_pos_buffer, "Z%.2f", get_current_printer_data()->position[2]); lv_label_set_text(label, z_pos_buffer); } static void update_printer_data_temp(lv_event_t * e) { lv_obj_t * label = lv_event_get_target(e); - sprintf(temp_buffer, "%.0f/%.0f", printer.extruder_temp, printer.bed_temp); + sprintf(temp_buffer, "%.0f/%.0f", get_current_printer_data()->temperatures[PrinterTemperatureDeviceIndex::PrinterTemperatureDeviceIndexNozzle1], get_current_printer_data()->temperatures[PrinterTemperatureDeviceIndex::PrinterTemperatureDeviceIndexBed]); lv_label_set_text(label, temp_buffer); } static void update_printer_data_time(lv_event_t * e){ lv_obj_t * label = lv_event_get_target(e); - if (printer.state == PRINTER_STATE_IDLE){ + if (get_current_printer_data()->state == PrinterState::PrinterStateIdle){ lv_label_set_text(label, "Idle"); return; } - if (printer.state == PRINTER_STATE_PAUSED){ + if (get_current_printer_data()->state == PrinterState::PrinterStatePaused){ lv_label_set_text(label, "Paused"); return; } - unsigned long time = printer.remaining_time_s; + unsigned long time = get_current_printer_data()->remaining_time_s; unsigned long hours = time / 3600; unsigned long minutes = (time % 3600) / 60; unsigned long seconds = (time % 3600) % 60; @@ -136,9 +136,9 @@ void nav_buttons_setup(PANEL_TYPE active_panel){ #endif - if (printer.state > PRINTER_STATE_ERROR){ + if (get_current_printer_data()->state > PrinterState::PrinterStateError){ // Files/Print - if (printer.state == PRINTER_STATE_IDLE) + if (get_current_printer_data()->state == PrinterState::PrinterStateIdle) { create_button(LV_SYMBOL_COPY, "Idle", btn_click_files, update_printer_data_time, root_panel); } @@ -148,12 +148,12 @@ void nav_buttons_setup(PANEL_TYPE active_panel){ } // Move - create_button(printer.state == PRINTER_STATE_PRINTING ? LV_SYMBOL_EDIT : LV_SYMBOL_CHARGE, "Z?", btn_click_move, update_printer_data_z_pos, root_panel); + create_button(get_current_printer_data()->state == PrinterState::PrinterStatePrinting ? LV_SYMBOL_EDIT : LV_SYMBOL_CHARGE, "Z?", btn_click_move, update_printer_data_z_pos, root_panel); // Extrude/Temp create_button(LV_SYMBOL_WARNING, "?/?", btn_click_extrude, update_printer_data_temp, root_panel); } - else if (printer.state == PRINTER_STATE_ERROR) { + else if (get_current_printer_data()->state == PrinterState::PrinterStateError) { // Error UI create_button(LV_SYMBOL_WARNING, "Error", btn_click_err, NULL, root_panel); } @@ -208,7 +208,7 @@ void nav_buttons_setup(PANEL_TYPE active_panel){ break; } - lv_msg_send(DATA_PRINTER_DATA, &printer); + lv_msg_send(DATA_PRINTER_DATA, get_current_printer()); } void nav_style_setup(){ diff --git a/CYD-Klipper/src/ui/ota_setup.cpp b/CYD-Klipper/src/ui/ota_setup.cpp index 1501f52..aa4d0a6 100644 --- a/CYD-Klipper/src/ui/ota_setup.cpp +++ b/CYD-Klipper/src/ui/ota_setup.cpp @@ -5,9 +5,6 @@ #include "../core/data_setup.h" #include "../conf/global_config.h" #include "ota_setup.h" -#include "../core/macros_query.h" -#include "../core/files_query.h" -#include "gcode_img.h" //const char *ota_url = "https://gist.githubusercontent.com/suchmememanyskill/ece418fe199e155340de6c224a0badf2/raw/0d6762d68bc807cbecc71e40d55b76692397a7b3/update.json"; // Test url const char *ota_url = "https://suchmememanyskill.github.io/CYD-Klipper/OTA.json"; // Prod url @@ -77,11 +74,6 @@ void ota_do_update(bool variant_automatic) lv_timer_handler(); lv_task_handler(); - macros_clear(); - power_devices_clear(); - clear_files(); - clear_img_mem(); - ota_pull.SetCallback(do_update_callback); ota_pull.CheckForOTAUpdate(ota_url, REPO_VERSION, ESP32OTAPull::ActionType::UPDATE_AND_BOOT); } diff --git a/CYD-Klipper/src/ui/serial/serial_commands.cpp b/CYD-Klipper/src/ui/serial/serial_commands.cpp index f72a306..0e135b8 100644 --- a/CYD-Klipper/src/ui/serial/serial_commands.cpp +++ b/CYD-Klipper/src/ui/serial/serial_commands.cpp @@ -4,6 +4,7 @@ #include #include "../../conf/global_config.h" #include "../switch_printer.h" +#include "../../core/printer_integration.hpp" namespace serial_console { @@ -94,20 +95,20 @@ void sets(String argv[]) Serial.printf("erase ssid\n"); } - if(get_current_printer_config()->ip_configured) + if(get_current_printer()->printer_config->ip_configured) { - Serial.printf("ip %s %d\n",get_current_printer_config()->klipper_host, get_current_printer_config()->klipper_port); + Serial.printf("ip %s %d\n",get_current_printer()->printer_config->klipper_host, get_current_printer()->printer_config->klipper_port); } else { Serial.printf("erase ip\n"); } - if(get_current_printer_config()->auth_configured) + if(get_current_printer()->printer_config->auth_configured) { Serial.printf("key %s\n", #if DISPLAY_SECRETS - get_current_printer_config()->klipper_auth + get_current_printer()->printer_config->klipper_auth #else "[redacted]" #endif @@ -135,9 +136,9 @@ void sets(String argv[]) void settings(String argv[]) { - if(get_current_printer_config()->printer_name[0] != 0) + if(get_current_printer()->printer_config->printer_name[0] != 0) { - Serial.printf("Current printer# %d name: %s",global_config.printer_index, get_current_printer_config()->printer_name); + Serial.printf("Current printer# %d name: %s",global_config.printer_index, get_current_printer()->printer_config->printer_name); } else { @@ -162,20 +163,20 @@ void settings(String argv[]) Serial.printf("Wifi not configured\n"); } - if(get_current_printer_config()->ip_configured) + if(get_current_printer()->printer_config->ip_configured) { - Serial.printf("Moonraker address: %s:%d\n",get_current_printer_config()->klipper_host, get_current_printer_config()->klipper_port); + Serial.printf("Moonraker address: %s:%d\n",get_current_printer()->printer_config->klipper_host, get_current_printer()->printer_config->klipper_port); } else { Serial.printf("Moonraker address not configured\n"); } - if(get_current_printer_config()->auth_configured) + if(get_current_printer()->printer_config->auth_configured) { Serial.printf("Moonraker API key: %s\n", #if DISPLAY_SECRETS - get_current_printer_config()->klipper_auth + get_current_printer()->printer_config->klipper_auth #else "[redacted]" #endif @@ -205,14 +206,14 @@ void erase_one(const String arg) { if(arg == "key") { - get_current_printer_config()->auth_configured = false; + get_current_printer()->printer_config->auth_configured = false; // overwrite the key to make it unrecoverable for 3rd parties - memset(get_current_printer_config()->klipper_auth,0,32); + memset(get_current_printer()->printer_config->klipper_auth,0,32); write_global_config(); } else if(arg == "ip") { - get_current_printer_config()->ip_configured = false; + get_current_printer()->printer_config->ip_configured = false; write_global_config(); } else if(arg == "touch") @@ -257,8 +258,8 @@ void key(String argv[]) return; } - get_current_printer_config()->auth_configured = true; - strncpy(get_current_printer_config()->klipper_auth, argv[1].c_str(), sizeof(global_config.printer_config[0].klipper_auth)); + get_current_printer()->printer_config->auth_configured = true; + strncpy(get_current_printer()->printer_config->klipper_auth, argv[1].c_str(), sizeof(global_config.printer_config[0].klipper_auth)); write_global_config(); } @@ -282,9 +283,9 @@ void ssid(String argv[]) void ip(String argv[]) { - strncpy(get_current_printer_config()->klipper_host, argv[1].c_str(), sizeof(global_config.printer_config[0].klipper_host)-1); - get_current_printer_config()->klipper_port = argv[2].toInt(); - get_current_printer_config()->ip_configured = true; + strncpy(get_current_printer()->printer_config->klipper_host, argv[1].c_str(), sizeof(global_config.printer_config[0].klipper_host)-1); + get_current_printer()->printer_config->klipper_port = argv[2].toInt(); + get_current_printer()->printer_config->ip_configured = true; write_global_config(); } diff --git a/CYD-Klipper/src/ui/ui_utils.cpp b/CYD-Klipper/src/ui/ui_utils.cpp index 391c0d1..4d645f0 100644 --- a/CYD-Klipper/src/ui/ui_utils.cpp +++ b/CYD-Klipper/src/ui/ui_utils.cpp @@ -2,7 +2,7 @@ #include "ui_utils.h" #include "../core/data_setup.h" #include "../core/lv_setup.h" -#include +#include "../core/printer_integration.hpp" lv_obj_t* lv_create_empty_panel(lv_obj_t* root) { lv_obj_t* panel = lv_obj_create(root); @@ -234,7 +234,6 @@ void lv_create_custom_menu_label(const char *label_text, lv_obj_t* root_panel, c lv_create_custom_menu_entry(label_text, label, root_panel, false); } -uint32_t message_hash = 0; lv_timer_t* timer = NULL; void on_timer_destroy(lv_event_t * e) @@ -256,15 +255,6 @@ void lv_create_popup_message(const char* message, uint16_t timeout_ms) return; } - uint32_t new_hash = crc32String(message); - - if (new_hash == message_hash) - { - return; - } - - message_hash = new_hash; - lv_obj_t* panel = lv_obj_create(lv_scr_act()); lv_obj_set_style_pad_all(panel, CYD_SCREEN_GAP_PX, CYD_SCREEN_GAP_PX); lv_obj_set_size(panel, CYD_SCREEN_PANEL_WIDTH_PX - CYD_SCREEN_GAP_PX * 2, LV_SIZE_CONTENT); @@ -278,8 +268,6 @@ void lv_create_popup_message(const char* message, uint16_t timeout_ms) lv_label_set_text_fmt(label, "%s", message); lv_obj_set_size(label, CYD_SCREEN_PANEL_WIDTH_PX - CYD_SCREEN_GAP_PX * 6, LV_SIZE_CONTENT); lv_label_set_long_mode(label, LV_LABEL_LONG_WRAP); - - timer = lv_timer_create(timer_callback, timeout_ms, panel); } lv_obj_t * lv_label_btn_create(lv_obj_t * parent, lv_event_cb_t btn_callback, void* user_data) From c0e329c57d49ac4b943f7cb1236e108c125e8312 Mon Sep 17 00:00:00 2001 From: suchmememanyskill <38142618+suchmememanyskill@users.noreply.github.com> Date: Sun, 27 Oct 2024 20:39:51 +0100 Subject: [PATCH 14/63] :) --- .../src/core/device/ESP32-2432S028R.cpp | 2 +- .../src/core/device/ESP32-3248S035C.cpp | 2 +- .../src/core/device/ESP32-smartdisplay.cpp | 2 +- .../klipper/klipper_printer_integration.hpp | 1 + CYD-Klipper/src/core/lv_setup.cpp | 3 +-- CYD-Klipper/src/ui/ip_setup.cpp | 25 +++++++++-------- CYD-Klipper/src/ui/switch_printer.cpp | 27 +++++-------------- CYD-Klipper/src/ui/switch_printer.h | 1 - 8 files changed, 23 insertions(+), 40 deletions(-) diff --git a/CYD-Klipper/src/core/device/ESP32-2432S028R.cpp b/CYD-Klipper/src/core/device/ESP32-2432S028R.cpp index d35cb34..110a90b 100644 --- a/CYD-Klipper/src/core/device/ESP32-2432S028R.cpp +++ b/CYD-Klipper/src/core/device/ESP32-2432S028R.cpp @@ -67,7 +67,7 @@ void screen_lv_touchRead(lv_indev_drv_t *indev_driver, lv_indev_data_t *data) } void set_invert_display(){ - tft.invertDisplay(get_current_printer_config()->invert_colors); + tft.invertDisplay(global_config.printer_config[global_config.printer_index].invert_colors); } void screen_setup() diff --git a/CYD-Klipper/src/core/device/ESP32-3248S035C.cpp b/CYD-Klipper/src/core/device/ESP32-3248S035C.cpp index 75c39b7..5688010 100644 --- a/CYD-Klipper/src/core/device/ESP32-3248S035C.cpp +++ b/CYD-Klipper/src/core/device/ESP32-3248S035C.cpp @@ -86,7 +86,7 @@ void screen_lv_touchRead(lv_indev_drv_t *indev_driver, lv_indev_data_t *data) void set_invert_display() { - tft.invertDisplay(get_current_printer_config()->invert_colors); + tft.invertDisplay(global_config.printer_config[global_config.printer_index].invert_colors); } void set_LED_color(uint8_t rgbVal[3]) diff --git a/CYD-Klipper/src/core/device/ESP32-smartdisplay.cpp b/CYD-Klipper/src/core/device/ESP32-smartdisplay.cpp index 4f723cf..dd3b997 100644 --- a/CYD-Klipper/src/core/device/ESP32-smartdisplay.cpp +++ b/CYD-Klipper/src/core/device/ESP32-smartdisplay.cpp @@ -21,7 +21,7 @@ void set_invert_display() void lv_screen_intercept(_lv_disp_drv_t *disp_drv, const lv_area_t *area, lv_color_t *color_p) { - if (get_current_printer_config()->invert_colors) { + if (global_config.printer_config[global_config.printer_index].invert_colors) { uint32_t w = (area->x2 - area->x1 + 1); uint32_t h = (area->y2 - area->y1 + 1); diff --git a/CYD-Klipper/src/core/klipper/klipper_printer_integration.hpp b/CYD-Klipper/src/core/klipper/klipper_printer_integration.hpp index e67e518..b43cae0 100644 --- a/CYD-Klipper/src/core/klipper/klipper_printer_integration.hpp +++ b/CYD-Klipper/src/core/klipper/klipper_printer_integration.hpp @@ -1,6 +1,7 @@ #pragma once #include "../printer_integration.hpp" +#include class KlipperPrinter : public BasePrinter { diff --git a/CYD-Klipper/src/core/lv_setup.cpp b/CYD-Klipper/src/core/lv_setup.cpp index c408dc8..e478bd5 100644 --- a/CYD-Klipper/src/core/lv_setup.cpp +++ b/CYD-Klipper/src/core/lv_setup.cpp @@ -5,7 +5,6 @@ #include "../ui/ui_utils.h" #include #include "../ui/serial/serial_console.h" -#include "printer_integration.hpp" #ifndef CPU_FREQ_HIGH #define CPU_FREQ_HIGH 240 @@ -255,7 +254,7 @@ void set_screen_timer_period() void set_color_scheme() { - PrinterConfiguration *config = get_current_printer()->printer_config; + PrinterConfiguration *config = &global_config.printer_config[global_config.printer_index]; lv_disp_t *dispp = lv_disp_get_default(); lv_color_t main_color = {0}; ColorDefinition color_def = color_defs[config->color_scheme]; diff --git a/CYD-Klipper/src/ui/ip_setup.cpp b/CYD-Klipper/src/ui/ip_setup.cpp index 6070e92..6a4af88 100644 --- a/CYD-Klipper/src/ui/ip_setup.cpp +++ b/CYD-Klipper/src/ui/ip_setup.cpp @@ -4,9 +4,7 @@ #include #include "core/data_setup.h" #include "ui_utils.h" -#include "../core/macros_query.h" #include "panels/panel.h" -#include "../core/http_client.h" #include "switch_printer.h" #include "macros.h" #include "../core/lv_setup.h" @@ -101,13 +99,13 @@ static void keyboard_event_ip_entry(lv_event_t * e) { } else if (code == LV_EVENT_READY) { - strcpy(get_current_printer_config()->klipper_host, lv_textarea_get_text(hostEntry)); - get_current_printer_config()->klipper_port = atoi(lv_textarea_get_text(portEntry)); + strcpy(global_config.printer_config[global_config.printer_index].klipper_host, lv_textarea_get_text(hostEntry)); + global_config.printer_config[global_config.printer_index].klipper_port = atoi(lv_textarea_get_text(portEntry)); connection_status_t status = verify_ip(); if (status == CONNECT_OK) { - get_current_printer_config()->ip_configured = true; + global_config.printer_config[global_config.printer_index].ip_configured = true; write_global_config(); } else if (status == CONNECT_AUTH_REQUIRED) @@ -136,12 +134,13 @@ static void keyboard_event_auth_entry(lv_event_t * e) { int len = strlen(txt); if (len > 0) { - get_current_printer_config()->auth_configured = true; - strcpy(get_current_printer_config()->klipper_auth, txt); + global_config.printer_config[global_config.printer_index].auth_configured = true; + strcpy(global_config.printer_config[global_config.printer_index].klipper_auth, txt); if (verify_ip() == CONNECT_OK) { - get_current_printer_config()->ip_configured = true; + global_config.printer_config[global_config.printer_index].ip_configured = true; + global_config.printer_config[global_config.printer_index].setup_complete = true; write_global_config(); } else @@ -158,7 +157,7 @@ static void keyboard_event_auth_entry(lv_event_t * e) { void show_auth_entry() { - get_current_printer_config()->klipper_auth[32] = 0; + global_config.printer_config[global_config.printer_index].klipper_auth[32] = 0; lv_obj_clean(lv_scr_act()); lv_obj_t * root = lv_create_empty_panel(lv_scr_act()); @@ -180,8 +179,8 @@ void show_auth_entry() lv_textarea_set_max_length(passEntry, 32); lv_textarea_set_one_line(passEntry, true); - if (get_current_printer_config()->auth_configured) - lv_textarea_set_text(passEntry, get_current_printer_config()->klipper_auth); + if (global_config.printer_config[global_config.printer_index].auth_configured) + lv_textarea_set_text(passEntry, global_config.printer_config[global_config.printer_index].klipper_auth); else lv_textarea_set_text(passEntry, ""); @@ -246,12 +245,12 @@ void show_ip_entry() } void ip_init(){ - if (!get_current_printer_config()->ip_configured) + if (!global_config.printer_config[global_config.printer_index].setup_complete) { show_ip_entry(); } - while (!get_current_printer_config()->ip_configured) + while (!global_config.printer_config[global_config.printer_index].setup_complete) { lv_handler(); serial_console::run(); diff --git a/CYD-Klipper/src/ui/switch_printer.cpp b/CYD-Klipper/src/ui/switch_printer.cpp index a703178..be95674 100644 --- a/CYD-Klipper/src/ui/switch_printer.cpp +++ b/CYD-Klipper/src/ui/switch_printer.cpp @@ -1,27 +1,17 @@ #include "switch_printer.h" #include "../conf/global_config.h" #include "ui_utils.h" -#include "../core/http_client.h" #include "../core/lv_setup.h" -#include "../core/macros_query.h" #include "../core/screen_driver.h" -#include "../core/data_setup.h" - -void switch_printer(int index) -{ - set_printer_config_index(index); - set_color_scheme(); - set_invert_display(); - printer.slicer_estimated_print_time_s = 0; -} static void btn_switch_printer(lv_event_t *e){ lv_obj_t *btn = lv_event_get_target(e); PrinterConfiguration * config = (PrinterConfiguration*)lv_event_get_user_data(e); int index = config - global_config.printer_config; - switch_printer(index); - + global_config_set_printer(index); + set_color_scheme(); + set_invert_display(); lv_obj_del(lv_obj_get_parent(lv_obj_get_parent(btn))); } @@ -48,19 +38,14 @@ void switch_printer_init() { PrinterConfiguration * config = &global_config.printer_config[i]; const char* printer_name = (config->printer_name[0] == 0) ? config->klipper_host : config->printer_name; - if (config == get_current_printer_config() && config->ip_configured) + if (i == global_config.printer_index && config->setup_complete) { lv_create_custom_menu_label(printer_name, parent, "Active"); continue; } - if (config->ip_configured) { - HTTPClient client; - configure_http_client(client, get_full_url("/printer/objects/query?webhooks&print_stats&virtual_sdcard", config), true, 1000); - - - int httpCode = client.GET(); - lv_create_custom_menu_button(printer_name, parent, btn_switch_printer, (httpCode == 200) ? "Switch" : "Offline", config); + if (config->setup_complete) { + lv_create_custom_menu_button(printer_name, parent, btn_switch_printer, "Switch", config); } } } diff --git a/CYD-Klipper/src/ui/switch_printer.h b/CYD-Klipper/src/ui/switch_printer.h index 070ef72..2926047 100644 --- a/CYD-Klipper/src/ui/switch_printer.h +++ b/CYD-Klipper/src/ui/switch_printer.h @@ -1,6 +1,5 @@ #pragma once #include "lvgl.h" -void switch_printer(int index); void switch_printer_init(); lv_obj_t * draw_switch_printer_button(); \ No newline at end of file From fcdce6c5bf01bb64e74e1fb814ed7641a9b7c281 Mon Sep 17 00:00:00 2001 From: suchmememanyskill <38142618+suchmememanyskill@users.noreply.github.com> Date: Sun, 27 Oct 2024 21:49:43 +0100 Subject: [PATCH 15/63] A --- .../klipper/klipper_printer_integration.cpp | 44 +++++++++++++------ .../klipper/klipper_printer_integration.hpp | 10 ++++- CYD-Klipper/src/ui/ip_setup.cpp | 33 +++----------- CYD-Klipper/src/ui/panels/printer_panel.cpp | 1 - 4 files changed, 45 insertions(+), 43 deletions(-) diff --git a/CYD-Klipper/src/core/klipper/klipper_printer_integration.cpp b/CYD-Klipper/src/core/klipper/klipper_printer_integration.cpp index e8e8d7e..e639282 100644 --- a/CYD-Klipper/src/core/klipper/klipper_printer_integration.cpp +++ b/CYD-Klipper/src/core/klipper/klipper_printer_integration.cpp @@ -163,18 +163,7 @@ bool KlipperPrinter::execute_feature(PrinterFeatures feature) bool KlipperPrinter::connect() { - HTTPClient client; - configure_http_client(client, "/printer/info", false, 1000); - - int http_code; - try { - http_code = client.GET(); - return http_code == 200; - } - catch (...) { - LOG_LN("Failed to connect"); - return false; - } + return connection_test_klipper(printer_config) == ConnectionStatus::ConnectOk; } bool KlipperPrinter::fetch() @@ -778,7 +767,7 @@ Thumbnail KlipperPrinter::get_32_32_png_image_thumbnail(const char* gcode_filena configure_http_client(client, "/server/files/gcodes/" + urlEncode(img_filename_path), false, 2000); - int http_code = 0; + http_code = 0; try { http_code = client.GET(); @@ -818,4 +807,33 @@ Thumbnail KlipperPrinter::get_32_32_png_image_thumbnail(const char* gcode_filena free(img_filename_path); return thumbnail; +} + +ConnectionStatus connection_test_klipper(PrinterConfiguration* config) +{ + HTTPClient client; + + client.setTimeout(1000); + client.setConnectTimeout(1000); + client.begin("http://" + String(config->klipper_host) + ":" + String(config->klipper_port) + "/printer/info"); + + if (config->auth_configured) { + client.addHeader("X-Api-Key", config->klipper_auth); + } + + int http_code; + try { + http_code = client.GET(); + + if (http_code == 403) + { + return ConnectionStatus::ConnectAuthRequired; + } + + return http_code == 200 ? ConnectionStatus::ConnectOk : ConnectionStatus::ConnectFail; + } + catch (...) { + LOG_LN("Failed to connect"); + return ConnectionStatus::ConnectFail; + } } \ No newline at end of file diff --git a/CYD-Klipper/src/core/klipper/klipper_printer_integration.hpp b/CYD-Klipper/src/core/klipper/klipper_printer_integration.hpp index b43cae0..a144667 100644 --- a/CYD-Klipper/src/core/klipper/klipper_printer_integration.hpp +++ b/CYD-Klipper/src/core/klipper/klipper_printer_integration.hpp @@ -54,4 +54,12 @@ class KlipperPrinter : public BasePrinter int get_slicer_time_estimate_s(); void configure_http_client(HTTPClient &client, String url_part, bool stream, int timeout); void init_ui_panels(); -}; \ No newline at end of file +}; + +enum ConnectionStatus { + ConnectFail = 0, + ConnectOk = 1, + ConnectAuthRequired = 2, +}; + +ConnectionStatus connection_test_klipper(PrinterConfiguration* config); \ No newline at end of file diff --git a/CYD-Klipper/src/ui/ip_setup.cpp b/CYD-Klipper/src/ui/ip_setup.cpp index 6a4af88..859c15e 100644 --- a/CYD-Klipper/src/ui/ip_setup.cpp +++ b/CYD-Klipper/src/ui/ip_setup.cpp @@ -9,6 +9,7 @@ #include "macros.h" #include "../core/lv_setup.h" #include "serial/serial_console.h" +#include "../core/klipper/klipper_printer_integration.hpp" lv_obj_t * hostEntry; lv_obj_t * portEntry; @@ -46,30 +47,6 @@ static const lv_btnmatrix_ctrl_t hex_numpad_ctrl[] = { 1, 1, 1, 1, LV_KEYBOARD_CTRL_BTN_FLAGS | 1, }; -enum connection_status_t { - CONNECT_FAIL = 0, - CONNECT_OK = 1, - CONNECT_AUTH_REQUIRED = 2, -}; - -connection_status_t verify_ip(){ - SETUP_HTTP_CLIENT_FULL("/printer/info", true, 1000); - - int httpCode; - try { - httpCode = client.GET(); - - if (httpCode == 401) - return CONNECT_AUTH_REQUIRED; - - return httpCode == 200 ? CONNECT_OK : CONNECT_FAIL; - } - catch (...) { - LOG_LN("Failed to connect"); - return CONNECT_FAIL; - } -} - static void keyboard_event_ip_entry(lv_event_t * e) { lv_event_code_t code = lv_event_get_code(e); lv_obj_t * ta = lv_event_get_target(e); @@ -102,13 +79,13 @@ static void keyboard_event_ip_entry(lv_event_t * e) { strcpy(global_config.printer_config[global_config.printer_index].klipper_host, lv_textarea_get_text(hostEntry)); global_config.printer_config[global_config.printer_index].klipper_port = atoi(lv_textarea_get_text(portEntry)); - connection_status_t status = verify_ip(); - if (status == CONNECT_OK) + ConnectionStatus status = connection_test_klipper(&global_config.printer_config[global_config.printer_index]); + if (status == ConnectionStatus::ConnectOk) { global_config.printer_config[global_config.printer_index].ip_configured = true; write_global_config(); } - else if (status == CONNECT_AUTH_REQUIRED) + else if (status == ConnectionStatus::ConnectAuthRequired) { show_auth_entry(); } @@ -137,7 +114,7 @@ static void keyboard_event_auth_entry(lv_event_t * e) { global_config.printer_config[global_config.printer_index].auth_configured = true; strcpy(global_config.printer_config[global_config.printer_index].klipper_auth, txt); - if (verify_ip() == CONNECT_OK) + if (connection_test_klipper(&global_config.printer_config[global_config.printer_index]) == ConnectionStatus::ConnectOk) { global_config.printer_config[global_config.printer_index].ip_configured = true; global_config.printer_config[global_config.printer_index].setup_complete = true; diff --git a/CYD-Klipper/src/ui/panels/printer_panel.cpp b/CYD-Klipper/src/ui/panels/printer_panel.cpp index fefca49..765be06 100644 --- a/CYD-Klipper/src/ui/panels/printer_panel.cpp +++ b/CYD-Klipper/src/ui/panels/printer_panel.cpp @@ -166,7 +166,6 @@ static void btn_printer_secondary(lv_event_t * e) } global_config_delete_printer(config_index); - nav_buttons_setup(PANEL_PRINTER); } static void btn_printer_rename(lv_event_t * e) From 1516b785f50ee13b768bcc08aa7da42b963c7a95 Mon Sep 17 00:00:00 2001 From: suchmememanyskill <38142618+suchmememanyskill@users.noreply.github.com> Date: Sun, 27 Oct 2024 21:55:41 +0100 Subject: [PATCH 16/63] A --- CYD-Klipper/src/core/klipper/klipper_printer_integration.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/CYD-Klipper/src/core/klipper/klipper_printer_integration.cpp b/CYD-Klipper/src/core/klipper/klipper_printer_integration.cpp index e639282..d919747 100644 --- a/CYD-Klipper/src/core/klipper/klipper_printer_integration.cpp +++ b/CYD-Klipper/src/core/klipper/klipper_printer_integration.cpp @@ -369,11 +369,6 @@ bool KlipperPrinter::fetch() return true; } -int KlipperPrinter::get_power_devices_count() -{ - return 0; -} - PrinterDataMinimal KlipperPrinter::fetch_min() { PrinterDataMinimal data = {0}; From 69d98a9e19e9e5ff5576ce3c3e993302b063a4ff Mon Sep 17 00:00:00 2001 From: suchmememanyskill <38142618+suchmememanyskill@users.noreply.github.com> Date: Sun, 27 Oct 2024 22:00:20 +0100 Subject: [PATCH 17/63] Fix serial console printer switching --- CYD-Klipper/src/ui/serial/serial_commands.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/CYD-Klipper/src/ui/serial/serial_commands.cpp b/CYD-Klipper/src/ui/serial/serial_commands.cpp index 0e135b8..5c57202 100644 --- a/CYD-Klipper/src/ui/serial/serial_commands.cpp +++ b/CYD-Klipper/src/ui/serial/serial_commands.cpp @@ -317,15 +317,15 @@ void brightness(String argv[]) void printer(String argv[]) { int ndx = argv[1].toInt(); - if(ndx == -1) + if(ndx <= -1) { global_config.multi_printer_mode = false; - switch_printer(0); + set_current_printer(0); } - else if( ndx >=0 && ndx < PRINTER_CONFIG_COUNT) + else if( ndx >= 0 && ndx < get_printer_count()) { global_config.multi_printer_mode = true; - switch_printer(ndx); + set_current_printer(ndx); } else { From 5bb4fd2b3c5a6c7f753df0645bb349e989dab851 Mon Sep 17 00:00:00 2001 From: suchmememanyskill <38142618+suchmememanyskill@users.noreply.github.com> Date: Sun, 27 Oct 2024 22:06:12 +0100 Subject: [PATCH 18/63] Fix virtual definition --- CYD-Klipper/src/core/printer_integration.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CYD-Klipper/src/core/printer_integration.hpp b/CYD-Klipper/src/core/printer_integration.hpp index 1b377af..f29e15b 100644 --- a/CYD-Klipper/src/core/printer_integration.hpp +++ b/CYD-Klipper/src/core/printer_integration.hpp @@ -165,7 +165,7 @@ class BasePrinter virtual Files get_files() = 0; virtual bool start_file(const char* filename) = 0; // Free thumbnail externally when done - virtual Thumbnail get_32_32_png_image_thumbnail(const char* gcode_filename); + virtual Thumbnail get_32_32_png_image_thumbnail(const char* gcode_filename) = 0; virtual bool set_target_temperature(PrinterTemperatureDevice device, unsigned int temperature) = 0; BasePrinter(unsigned char index); From d6e788f0c85994d6dcc0e4b8a13c6f7b34148696 Mon Sep 17 00:00:00 2001 From: suchmememanyskill <38142618+suchmememanyskill@users.noreply.github.com> Date: Sun, 27 Oct 2024 22:15:39 +0100 Subject: [PATCH 19/63] Fix some warnings --- CYD-Klipper/src/core/printer_integration.cpp | 1 + CYD-Klipper/src/core/printer_integration.hpp | 3 +-- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CYD-Klipper/src/core/printer_integration.cpp b/CYD-Klipper/src/core/printer_integration.cpp index 5130862..3f754f6 100644 --- a/CYD-Klipper/src/core/printer_integration.cpp +++ b/CYD-Klipper/src/core/printer_integration.cpp @@ -53,6 +53,7 @@ PrinterData* BasePrinter::AnnouncePrinterData() } lv_msg_send(DATA_PRINTER_DATA, get_current_printer()); + return printer_data_copy; } void initialize_printers(BasePrinter** printers, unsigned char total) diff --git a/CYD-Klipper/src/core/printer_integration.hpp b/CYD-Klipper/src/core/printer_integration.hpp index f29e15b..e03be81 100644 --- a/CYD-Klipper/src/core/printer_integration.hpp +++ b/CYD-Klipper/src/core/printer_integration.hpp @@ -1,7 +1,6 @@ #pragma once #include "../conf/global_config.h" - -#define BIT(x) 1 << x +#include enum PrinterFeatures { PrinterFeatureRestart = BIT(0), From b99e00d79c2c199a8a330f52ab7c10ac3dfd9eb5 Mon Sep 17 00:00:00 2001 From: suchmememanyskill <38142618+suchmememanyskill@users.noreply.github.com> Date: Mon, 28 Oct 2024 01:23:07 +0100 Subject: [PATCH 20/63] Fixes --- .../klipper/klipper_printer_integration.cpp | 19 +++---- CYD-Klipper/src/core/printer_integration.cpp | 51 ++++++++++++------- CYD-Klipper/src/ui/ip_setup.cpp | 1 + CYD-Klipper/src/ui/panels/stats_panel.cpp | 5 ++ CYD-Klipper/src/ui/panels/temp_panel.cpp | 4 +- CYD-Klipper/src/ui/ui_utils.cpp | 2 + 6 files changed, 53 insertions(+), 29 deletions(-) diff --git a/CYD-Klipper/src/core/klipper/klipper_printer_integration.cpp b/CYD-Klipper/src/core/klipper/klipper_printer_integration.cpp index d919747..29844ae 100644 --- a/CYD-Klipper/src/core/klipper/klipper_printer_integration.cpp +++ b/CYD-Klipper/src/core/klipper/klipper_printer_integration.cpp @@ -187,8 +187,8 @@ bool KlipperPrinter::fetch() if (status.containsKey("webhooks")) { - const char *state = status["webhooks"]["state"]; - const char *message = status["webhooks"]["state_message"]; + const char* state = status["webhooks"]["state"]; + const char* message = status["webhooks"]["state_message"]; if (strcmp(state, "ready") == 0 && printer_data.state == PrinterStateError) { @@ -199,7 +199,7 @@ bool KlipperPrinter::fetch() printer_data.state = PrinterStateError; } - if (printer_data.state_message == NULL || strcmp(printer_data.state_message, message)) + if (message != NULL && (printer_data.state_message == NULL || strcmp(printer_data.state_message, message))) { printer_data.state_message = (char *)malloc(strlen(message) + 1); strcpy(printer_data.state_message, message); @@ -452,7 +452,7 @@ void KlipperPrinter::disconnect() Macros KlipperPrinter::get_macros() { HTTPClient client; - Macros macros; + Macros macros = {0}; configure_http_client(client, "/printer/gcode/help", true, 1000); int http_code = client.GET(); @@ -522,7 +522,7 @@ bool KlipperPrinter::execute_macro(const char* macro) PowerDevices KlipperPrinter::get_power_devices() { HTTPClient client; - PowerDevices power_devices; + PowerDevices power_devices = {0}; configure_http_client(client, "/machine/device_power/devices", true, 1000); int http_code = client.GET(); @@ -590,7 +590,7 @@ typedef struct { Files KlipperPrinter::get_files() { - Files files_result; + Files files_result = {0}; HTTPClient client; LOG_F(("Heap space pre-file-parse: %d bytes\n", esp_get_free_heap_size())) std::list files; @@ -704,7 +704,7 @@ Thumbnail KlipperPrinter::get_32_32_png_image_thumbnail(const char* gcode_filena { Thumbnail thumbnail = {0}; HTTPClient client; - configure_http_client(client, "/server/files/thumbnails?filename=", true, 1000); + configure_http_client(client, "/server/files/thumbnails?filename=" + urlEncode(gcode_filename), true, 1000); char* img_filename_path = NULL; unsigned char* data_png = NULL; @@ -725,7 +725,6 @@ Thumbnail KlipperPrinter::get_32_32_png_image_thumbnail(const char* gcode_filena deserializeJson(doc, client.getStream()); auto result = doc["result"].as(); const char* chosen_thumb = NULL; - for (auto file : result){ int width = file["width"]; int height = file["height"]; @@ -735,9 +734,10 @@ Thumbnail KlipperPrinter::get_32_32_png_image_thumbnail(const char* gcode_filena if (width != height || width != 32) continue; + if (strcmp(thumbnail + strlen(thumbnail) - 4, ".png")) continue; - + chosen_thumb = thumbnail; break; } @@ -755,6 +755,7 @@ Thumbnail KlipperPrinter::get_32_32_png_image_thumbnail(const char* gcode_filena if (img_filename_path == NULL) { + LOG_LN("No compatible thumbnail found"); return thumbnail; } diff --git a/CYD-Klipper/src/core/printer_integration.cpp b/CYD-Klipper/src/core/printer_integration.cpp index 3f754f6..9168da4 100644 --- a/CYD-Klipper/src/core/printer_integration.cpp +++ b/CYD-Klipper/src/core/printer_integration.cpp @@ -1,25 +1,20 @@ #include "printer_integration.hpp" #include "lv_setup.h" #include "screen_driver.h" +#include -unsigned char current_printer_index = 0; -unsigned char total_printers; -BasePrinter** registered_printers; -PrinterDataMinimal* minimal_data_copy; -PrinterData* printer_data_copy; +static char blank[] = { '\0' }; +static unsigned char current_printer_index = 0; +static unsigned char total_printers; +static BasePrinter** registered_printers; +static PrinterDataMinimal* minimal_data_copy; +static PrinterData* printer_data_copy; BasePrinter::BasePrinter(unsigned char index) { config_index = index; printer_config = &global_config.printer_config[index]; - - printer_data.state_message = (char*)malloc(1); - printer_data.print_filename = (char*)malloc(1); - printer_data.popup_message = (char*)malloc(1); - *printer_data.state_message = '\0'; - *printer_data.print_filename = '\0'; - *printer_data.popup_message = '\0'; - + memset(&printer_data, 0, sizeof(PrinterData)); // TODO: Fetch printer config and global config } @@ -27,27 +22,46 @@ PrinterData* BasePrinter::AnnouncePrinterData() { char* old_state_message = printer_data_copy->state_message; char* old_print_filename = printer_data_copy->print_filename; - char* old_popup_message = printer_data_copy->print_filename; + char* old_popup_message = printer_data_copy->popup_message; + PrinterState old_state = printer_data_copy->state; memcpy(printer_data_copy, &printer_data, sizeof(PrinterData)); - if (old_state_message != printer_data_copy->state_message) + if (printer_data_copy->state_message == NULL) + { + printer_data_copy->state_message = blank; + } + + if (printer_data_copy->print_filename == NULL) + { + printer_data_copy->print_filename = blank; + } + + if (printer_data_copy->popup_message == NULL) + { + printer_data_copy->popup_message = blank; + } + + if (old_state_message != printer_data_copy->state_message && old_state_message != NULL && old_state_message != blank) { + LOG_F(("Freeing state message '%s' (%x)\n", old_state_message, old_state_message)); free(old_state_message); } - if (old_print_filename != printer_data_copy->print_filename) + if (old_print_filename != printer_data_copy->print_filename && old_print_filename != NULL && old_print_filename != blank) { + LOG_F(("Freeing print filename '%s' (%x)\n", old_print_filename, old_print_filename)); free(old_print_filename); } - if (printer_data.state != printer_data_copy->state) + if (old_state != printer_data_copy->state) { lv_msg_send(DATA_PRINTER_STATE, get_current_printer()); } - if (old_popup_message != printer_data_copy->popup_message) + if (old_popup_message != printer_data_copy->popup_message && old_popup_message != NULL && old_popup_message != blank) { + LOG_F(("Freeing popup message '%s' (%x)\n", old_popup_message, old_popup_message)); free(old_popup_message); lv_msg_send(DATA_PRINTER_POPUP, get_current_printer()); } @@ -60,6 +74,7 @@ void initialize_printers(BasePrinter** printers, unsigned char total) { printer_data_copy = (PrinterData*)malloc(sizeof(PrinterData)); minimal_data_copy = (PrinterDataMinimal*)malloc(sizeof(PrinterDataMinimal) * total_printers); + memset(printer_data_copy, 0, sizeof(PrinterData)); memset(minimal_data_copy, 0, sizeof(PrinterDataMinimal) * total_printers); registered_printers = printers; total_printers = total; diff --git a/CYD-Klipper/src/ui/ip_setup.cpp b/CYD-Klipper/src/ui/ip_setup.cpp index 859c15e..f7e22f2 100644 --- a/CYD-Klipper/src/ui/ip_setup.cpp +++ b/CYD-Klipper/src/ui/ip_setup.cpp @@ -83,6 +83,7 @@ static void keyboard_event_ip_entry(lv_event_t * e) { if (status == ConnectionStatus::ConnectOk) { global_config.printer_config[global_config.printer_index].ip_configured = true; + global_config.printer_config[global_config.printer_index].setup_complete = true; write_global_config(); } else if (status == ConnectionStatus::ConnectAuthRequired) diff --git a/CYD-Klipper/src/ui/panels/stats_panel.cpp b/CYD-Klipper/src/ui/panels/stats_panel.cpp index 22a34b5..c964b62 100644 --- a/CYD-Klipper/src/ui/panels/stats_panel.cpp +++ b/CYD-Klipper/src/ui/panels/stats_panel.cpp @@ -9,10 +9,15 @@ static void swap_to_files_menu(lv_event_t * e) { nav_buttons_setup(PANEL_FILES); } +static void update_data(lv_event_t * e) { + lv_msg_send(DATA_PRINTER_DATA, get_current_printer()); +} + void create_state_button(lv_obj_t * root, lv_event_cb_t label, lv_event_cb_t button){ lv_obj_t * btn = lv_btn_create(root); lv_obj_set_size(btn, CYD_SCREEN_PANEL_WIDTH_PX / 2 - CYD_SCREEN_GAP_PX * 3, CYD_SCREEN_MIN_BUTTON_HEIGHT_PX); lv_obj_add_event_cb(btn, button, LV_EVENT_CLICKED, NULL); + lv_obj_add_event_cb(btn, update_data, LV_EVENT_CLICKED, NULL); lv_obj_t * label_obj = lv_label_create(btn); lv_obj_add_event_cb(label_obj, label, LV_EVENT_MSG_RECEIVED, NULL); diff --git a/CYD-Klipper/src/ui/panels/temp_panel.cpp b/CYD-Klipper/src/ui/panels/temp_panel.cpp index c360946..c0c1507 100644 --- a/CYD-Klipper/src/ui/panels/temp_panel.cpp +++ b/CYD-Klipper/src/ui/panels/temp_panel.cpp @@ -237,9 +237,9 @@ void create_charts(lv_obj_t * root) lv_chart_series_t * ser2 = lv_chart_add_series(chart, lv_palette_main(LV_PALETTE_RED), LV_CHART_AXIS_PRIMARY_Y); lv_chart_set_all_value(chart, ser2, get_current_printer_data()->temperatures[PrinterTemperatureDeviceIndex::PrinterTemperatureDeviceIndexNozzle1]); lv_chart_series_t * ser3 = lv_chart_add_series(chart, lv_palette_main(LV_PALETTE_TEAL), LV_CHART_AXIS_PRIMARY_Y); - lv_chart_set_all_value(chart, ser3, get_current_printer_data()->temperatures[PrinterTemperatureDeviceIndex::PrinterTemperatureDeviceIndexBed]); + lv_chart_set_all_value(chart, ser3, get_current_printer_data()->target_temperatures[PrinterTemperatureDeviceIndex::PrinterTemperatureDeviceIndexBed]); lv_chart_series_t * ser4 = lv_chart_add_series(chart, lv_palette_main(LV_PALETTE_BLUE), LV_CHART_AXIS_PRIMARY_Y); - lv_chart_set_all_value(chart, ser4, get_current_printer_data()->target_temperatures[PrinterTemperatureDeviceIndex::PrinterTemperatureDeviceIndexBed]); + lv_chart_set_all_value(chart, ser4, get_current_printer_data()->temperatures[PrinterTemperatureDeviceIndex::PrinterTemperatureDeviceIndexBed]); lv_obj_add_event_cb(chart, set_hotend_target_temp_chart, LV_EVENT_MSG_RECEIVED, ser1); lv_obj_add_event_cb(chart, set_hotend_temp_chart, LV_EVENT_MSG_RECEIVED, ser2); diff --git a/CYD-Klipper/src/ui/ui_utils.cpp b/CYD-Klipper/src/ui/ui_utils.cpp index 4d645f0..3fcf4fc 100644 --- a/CYD-Klipper/src/ui/ui_utils.cpp +++ b/CYD-Klipper/src/ui/ui_utils.cpp @@ -268,6 +268,8 @@ void lv_create_popup_message(const char* message, uint16_t timeout_ms) lv_label_set_text_fmt(label, "%s", message); lv_obj_set_size(label, CYD_SCREEN_PANEL_WIDTH_PX - CYD_SCREEN_GAP_PX * 6, LV_SIZE_CONTENT); lv_label_set_long_mode(label, LV_LABEL_LONG_WRAP); + + timer = lv_timer_create(timer_callback, timeout_ms, panel); } lv_obj_t * lv_label_btn_create(lv_obj_t * parent, lv_event_cb_t btn_callback, void* user_data) From ccc58177998273c854bcfbacae3334501a7c74bc Mon Sep 17 00:00:00 2001 From: suchmememanyskill <38142618+suchmememanyskill@users.noreply.github.com> Date: Mon, 28 Oct 2024 13:57:18 +0100 Subject: [PATCH 21/63] More fixes --- CYD-Klipper/src/conf/global_config.cpp | 4 ++- CYD-Klipper/src/core/data_setup.cpp | 5 ++- .../klipper/klipper_printer_integration.cpp | 19 ++++++----- CYD-Klipper/src/core/lv_setup.cpp | 1 + CYD-Klipper/src/core/printer_integration.cpp | 5 +-- CYD-Klipper/src/core/printer_integration.hpp | 2 +- CYD-Klipper/src/ui/ip_setup.cpp | 16 +++++++-- CYD-Klipper/src/ui/nav_buttons.cpp | 33 +++++++++++++++---- CYD-Klipper/src/ui/panels/printer_panel.cpp | 17 +++++----- CYD-Klipper/src/ui/panels/settings_panel.cpp | 3 +- 10 files changed, 70 insertions(+), 35 deletions(-) diff --git a/CYD-Klipper/src/conf/global_config.cpp b/CYD-Klipper/src/conf/global_config.cpp index 91b42b0..c1e0e4c 100644 --- a/CYD-Klipper/src/conf/global_config.cpp +++ b/CYD-Klipper/src/conf/global_config.cpp @@ -70,6 +70,7 @@ void global_config_add_new_printer() int free_index = get_printer_config_free_index(); if (free_index <= -1) { + LOG_LN("No available slot for new printer"); return; } @@ -77,6 +78,7 @@ void global_config_add_new_printer() PrinterConfiguration* new_config = &global_config.printer_config[free_index]; new_config->raw = old_config->raw; + new_config->setup_complete = false; new_config->ip_configured = false; new_config->auth_configured = false; @@ -99,7 +101,7 @@ void global_config_add_new_printer() new_config->printer_move_z_steps[i] = old_config->printer_move_z_steps[i]; } - write_global_config(); + global_config_set_printer(free_index); ESP.restart(); } diff --git a/CYD-Klipper/src/core/data_setup.cpp b/CYD-Klipper/src/core/data_setup.cpp index fdcb89c..4cdb4d6 100644 --- a/CYD-Klipper/src/core/data_setup.cpp +++ b/CYD-Klipper/src/core/data_setup.cpp @@ -61,18 +61,17 @@ void fetch_printer_data() void fetch_printer_data_minimal() { - PrinterDataMinimal* data = (PrinterDataMinimal*)malloc(sizeof(PrinterDataMinimal) * get_printer_count()); + PrinterDataMinimal data[PRINTER_CONFIG_COUNT] = {{}}; for (int i = 0; i < get_printer_count(); i++) { freeze_request_thread(); BasePrinter* printer = get_printer(i); unfreeze_request_thread(); - *(data + i) = printer->fetch_min(); + data[i] = printer->fetch_min(); } freeze_render_thread(); announce_printer_data_minimal(data); unfreeze_render_thread(); - free(data); } void data_loop() diff --git a/CYD-Klipper/src/core/klipper/klipper_printer_integration.cpp b/CYD-Klipper/src/core/klipper/klipper_printer_integration.cpp index 29844ae..ae60526 100644 --- a/CYD-Klipper/src/core/klipper/klipper_printer_integration.cpp +++ b/CYD-Klipper/src/core/klipper/klipper_printer_integration.cpp @@ -371,9 +371,10 @@ bool KlipperPrinter::fetch() PrinterDataMinimal KlipperPrinter::fetch_min() { - PrinterDataMinimal data = {0}; + PrinterDataMinimal data = {}; + data.success = false; - if (!printer_config->ip_configured) + if (!printer_config->setup_complete) { data.state = PrinterStateOffline; return data; @@ -387,7 +388,7 @@ PrinterDataMinimal KlipperPrinter::fetch_min() int http_code = client.GET(); if (http_code == 200) { - data.state = PrinterStateIdle; + data.state = PrinterState::PrinterStateIdle; data.power_devices = get_power_devices_count(); JsonDocument doc; @@ -400,7 +401,7 @@ PrinterDataMinimal KlipperPrinter::fetch_min() if (strcmp(state, "shutdown") == 0) { - data.state = PrinterStateError; + data.state = PrinterState::PrinterStateError; } } @@ -417,26 +418,26 @@ PrinterDataMinimal KlipperPrinter::fetch_min() if (state == nullptr) { - data.state = PrinterStateError; + data.state = PrinterState::PrinterStateError; } else if (strcmp(state, "printing") == 0) { - data.state = PrinterStatePrinting; + data.state = PrinterState::PrinterStatePrinting; } else if (strcmp(state, "paused") == 0) { - data.state = PrinterStatePaused; + data.state = PrinterState::PrinterStatePaused; } else if (strcmp(state, "complete") == 0 || strcmp(state, "cancelled") == 0 || strcmp(state, "standby") == 0) { - data.state = PrinterStateIdle; + data.state = PrinterState::PrinterStateIdle; } } } } else { - data.state = PrinterStateOffline; + data.state = PrinterState::PrinterStateOffline; data.power_devices = get_power_devices_count(); } diff --git a/CYD-Klipper/src/core/lv_setup.cpp b/CYD-Klipper/src/core/lv_setup.cpp index e478bd5..d094c8f 100644 --- a/CYD-Klipper/src/core/lv_setup.cpp +++ b/CYD-Klipper/src/core/lv_setup.cpp @@ -72,6 +72,7 @@ void lv_touch_intercept(lv_indev_drv_t *indev_driver, lv_indev_data_t *data) } data->state = LV_INDEV_STATE_REL; + delay(300); // Some screens don't debounce their signal properly } screen_timer_wake(); diff --git a/CYD-Klipper/src/core/printer_integration.cpp b/CYD-Klipper/src/core/printer_integration.cpp index 9168da4..8b9565f 100644 --- a/CYD-Klipper/src/core/printer_integration.cpp +++ b/CYD-Klipper/src/core/printer_integration.cpp @@ -72,10 +72,11 @@ PrinterData* BasePrinter::AnnouncePrinterData() void initialize_printers(BasePrinter** printers, unsigned char total) { + LOG_F(("Initializing %d printers\n", total)) printer_data_copy = (PrinterData*)malloc(sizeof(PrinterData)); - minimal_data_copy = (PrinterDataMinimal*)malloc(sizeof(PrinterDataMinimal) * total_printers); + minimal_data_copy = (PrinterDataMinimal*)malloc(sizeof(PrinterDataMinimal) * total); memset(printer_data_copy, 0, sizeof(PrinterData)); - memset(minimal_data_copy, 0, sizeof(PrinterDataMinimal) * total_printers); + memset(minimal_data_copy, 0, sizeof(PrinterDataMinimal) * total); registered_printers = printers; total_printers = total; } diff --git a/CYD-Klipper/src/core/printer_integration.hpp b/CYD-Klipper/src/core/printer_integration.hpp index e03be81..2e6b3cb 100644 --- a/CYD-Klipper/src/core/printer_integration.hpp +++ b/CYD-Klipper/src/core/printer_integration.hpp @@ -97,7 +97,7 @@ typedef struct _PrinterData { } PrinterData; typedef struct { - unsigned char state; + PrinterState state; float print_progress; // 0 -> 1 unsigned int power_devices; bool success; diff --git a/CYD-Klipper/src/ui/ip_setup.cpp b/CYD-Klipper/src/ui/ip_setup.cpp index f7e22f2..e6990e3 100644 --- a/CYD-Klipper/src/ui/ip_setup.cpp +++ b/CYD-Klipper/src/ui/ip_setup.cpp @@ -198,15 +198,27 @@ void show_ip_entry() lv_textarea_set_one_line(hostEntry, true); lv_obj_add_flag(hostEntry, LV_OBJ_FLAG_USER_1); lv_textarea_set_max_length(hostEntry, 63); - lv_textarea_set_text(hostEntry, ""); lv_obj_set_flex_grow(hostEntry, 3); portEntry = lv_textarea_create(textbow_row); lv_textarea_set_one_line(portEntry, true); lv_textarea_set_max_length(portEntry, 5); - lv_textarea_set_text(portEntry, "80"); + lv_obj_set_flex_grow(portEntry, 1); + if (global_config.printer_config[global_config.printer_index].ip_configured) + { + char buff[7] = {0}; + sprintf(buff, "%d", global_config.printer_config[global_config.printer_index].klipper_port); + lv_textarea_set_text(hostEntry, global_config.printer_config[global_config.printer_index].klipper_host); + lv_textarea_set_text(portEntry, buff); + } + else + { + lv_textarea_set_text(hostEntry, ""); + lv_textarea_set_text(portEntry, "80"); + } + lv_obj_t * keyboard = lv_keyboard_create(root); lv_keyboard_set_map(keyboard, LV_KEYBOARD_MODE_USER_1, kb_map, kb_ctrl); lv_obj_add_event_cb(hostEntry, keyboard_event_ip_entry, LV_EVENT_ALL, keyboard); diff --git a/CYD-Klipper/src/ui/nav_buttons.cpp b/CYD-Klipper/src/ui/nav_buttons.cpp index bc2fcc8..7a517ff 100644 --- a/CYD-Klipper/src/ui/nav_buttons.cpp +++ b/CYD-Klipper/src/ui/nav_buttons.cpp @@ -7,15 +7,11 @@ #include "../core/printer_integration.hpp" static lv_style_t nav_button_style; - -static char temp_buffer[10]; -static char z_pos_buffer[10]; -static char time_buffer[10]; - static lv_style_t nav_button_text_style; static void update_printer_data_z_pos(lv_event_t * e) { lv_obj_t * label = lv_event_get_target(e); + char z_pos_buffer[10]; sprintf(z_pos_buffer, "Z%.2f", get_current_printer_data()->position[2]); lv_label_set_text(label, z_pos_buffer); @@ -23,6 +19,7 @@ static void update_printer_data_z_pos(lv_event_t * e) { static void update_printer_data_temp(lv_event_t * e) { lv_obj_t * label = lv_event_get_target(e); + char temp_buffer[10]; sprintf(temp_buffer, "%.0f/%.0f", get_current_printer_data()->temperatures[PrinterTemperatureDeviceIndex::PrinterTemperatureDeviceIndexNozzle1], get_current_printer_data()->temperatures[PrinterTemperatureDeviceIndex::PrinterTemperatureDeviceIndexBed]); lv_label_set_text(label, temp_buffer); @@ -30,6 +27,7 @@ static void update_printer_data_temp(lv_event_t * e) { static void update_printer_data_time(lv_event_t * e){ lv_obj_t * label = lv_event_get_target(e); + char time_buffer[10]; if (get_current_printer_data()->state == PrinterState::PrinterStateIdle){ lv_label_set_text(label, "Idle"); @@ -57,6 +55,29 @@ static void update_printer_data_time(lv_event_t * e){ lv_label_set_text(label, time_buffer); } +static void update_multi_printer_label(lv_event_t * e) { + lv_obj_t * label = lv_event_get_target(e); + + int idle_count = 0; + for (int i = 0; i < get_printer_count(); i++) + { + PrinterDataMinimal* data = get_printer_data_minimal(i); + if (data->state == PrinterState::PrinterStateIdle) + { + idle_count++; + } + } + + if (idle_count > 0) + { + lv_label_set_text_fmt(label, "%d idle", idle_count); + } + else + { + lv_label_set_text(label, "Printer"); + } +} + static void btn_click_files(lv_event_t * e){ nav_buttons_setup(PANEL_FILES); } @@ -168,7 +189,7 @@ void nav_buttons_setup(PANEL_TYPE active_panel){ if (global_config.multi_printer_mode) { // Printers - create_button(LV_SYMBOL_HOME, "Printer", btn_click_printer, NULL, root_panel); + create_button(LV_SYMBOL_HOME, "Printer", btn_click_printer, update_multi_printer_label, root_panel); } lv_obj_t * panel = lv_create_empty_panel(lv_scr_act()); diff --git a/CYD-Klipper/src/ui/panels/printer_panel.cpp b/CYD-Klipper/src/ui/panels/printer_panel.cpp index 765be06..71e8778 100644 --- a/CYD-Klipper/src/ui/panels/printer_panel.cpp +++ b/CYD-Klipper/src/ui/panels/printer_panel.cpp @@ -170,7 +170,9 @@ static void btn_printer_secondary(lv_event_t * e) static void btn_printer_rename(lv_event_t * e) { - keyboard_config = (PrinterConfiguration*)lv_event_get_user_data(e); + int config_index = (int)lv_event_get_user_data(e); + BasePrinter* printer = get_printer(config_index); + keyboard_config = printer->printer_config; lv_create_keyboard_text_entry(keyboard_callback, "Rename Printer", LV_KEYBOARD_MODE_TEXT_LOWER, CYD_SCREEN_WIDTH_PX * 0.75, 24, keyboard_config->printer_name, false); } @@ -196,9 +198,8 @@ static void btn_printer_add(lv_event_t * e) global_config_add_new_printer(); } -void create_printer_ui(PrinterConfiguration * config, lv_obj_t * root) +void create_printer_ui(int index, lv_obj_t * root) { - int index = config - global_config.printer_config; auto width = CYD_SCREEN_PANEL_WIDTH_PX - CYD_SCREEN_GAP_PX * 2; lv_obj_t * data_row_name = lv_create_empty_panel(root); @@ -279,15 +280,12 @@ void printer_panel_init(lv_obj_t* panel) lv_obj_set_size(lv_create_empty_panel(inner_panel), 0, 0); - for (int i = 0; i < PRINTER_CONFIG_COUNT; i++){ - PrinterConfiguration * config = &global_config.printer_config[i]; - if (config->ip_configured) { - create_printer_ui(&global_config.printer_config[i], inner_panel); - } + for (int i = 0; i < get_printer_count(); i++){ + create_printer_ui(i, inner_panel); } // Add Printer Button - if (get_printer_count() == PRINTER_CONFIG_COUNT){ + if (get_printer_count() < PRINTER_CONFIG_COUNT){ lv_obj_t * btn = lv_btn_create(inner_panel); lv_obj_set_size(btn, CYD_SCREEN_PANEL_WIDTH_PX - CYD_SCREEN_GAP_PX * 2, CYD_SCREEN_MIN_BUTTON_HEIGHT_PX); lv_obj_add_event_cb(btn, btn_printer_add, LV_EVENT_CLICKED, NULL); @@ -298,4 +296,5 @@ void printer_panel_init(lv_obj_t* panel) } lv_obj_set_size(lv_create_empty_panel(inner_panel), 0, 0); + lv_msg_send(DATA_PRINTER_MINIMAL, NULL); } \ No newline at end of file diff --git a/CYD-Klipper/src/ui/panels/settings_panel.cpp b/CYD-Klipper/src/ui/panels/settings_panel.cpp index 8e867aa..f114497 100644 --- a/CYD-Klipper/src/ui/panels/settings_panel.cpp +++ b/CYD-Klipper/src/ui/panels/settings_panel.cpp @@ -39,8 +39,7 @@ static void reset_wifi_click(lv_event_t * e){ } static void reset_ip_click(lv_event_t * e){ - get_current_printer()->printer_config->ip_configured = false; - get_current_printer()->printer_config->auth_configured = false; + get_current_printer()->printer_config->setup_complete = false; write_global_config(); ESP.restart(); } From 572d27dc8ad921e497c86cd166ef886a25a7ff20 Mon Sep 17 00:00:00 2001 From: suchmememanyskill <38142618+suchmememanyskill@users.noreply.github.com> Date: Mon, 28 Oct 2024 14:00:53 +0100 Subject: [PATCH 22/63] Update serial comms --- CYD-Klipper/src/ui/serial/serial_commands.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CYD-Klipper/src/ui/serial/serial_commands.cpp b/CYD-Klipper/src/ui/serial/serial_commands.cpp index 5c57202..7771b2d 100644 --- a/CYD-Klipper/src/ui/serial/serial_commands.cpp +++ b/CYD-Klipper/src/ui/serial/serial_commands.cpp @@ -213,6 +213,7 @@ void erase_one(const String arg) } else if(arg == "ip") { + get_current_printer()->printer_config->setup_complete = false; get_current_printer()->printer_config->ip_configured = false; write_global_config(); } @@ -286,6 +287,7 @@ void ip(String argv[]) strncpy(get_current_printer()->printer_config->klipper_host, argv[1].c_str(), sizeof(global_config.printer_config[0].klipper_host)-1); get_current_printer()->printer_config->klipper_port = argv[2].toInt(); get_current_printer()->printer_config->ip_configured = true; + get_current_printer()->printer_config->setup_complete = true; write_global_config(); } From b1138d95100b3c0fc23abe321fe9029b75f8a370 Mon Sep 17 00:00:00 2001 From: suchmememanyskill <38142618+suchmememanyskill@users.noreply.github.com> Date: Mon, 28 Oct 2024 15:33:17 +0100 Subject: [PATCH 23/63] Split json parsing from printer impl --- CYD-Klipper/.vscode/settings.json | 30 +- .../klipper/klipper_printer_integration.cpp | 380 ++--------------- .../klipper/klipper_printer_integration.hpp | 26 +- .../core/klipper/klipper_printer_parsers.cpp | 394 ++++++++++++++++++ 4 files changed, 476 insertions(+), 354 deletions(-) create mode 100644 CYD-Klipper/src/core/klipper/klipper_printer_parsers.cpp diff --git a/CYD-Klipper/.vscode/settings.json b/CYD-Klipper/.vscode/settings.json index 425aa19..e1ffb15 100644 --- a/CYD-Klipper/.vscode/settings.json +++ b/CYD-Klipper/.vscode/settings.json @@ -20,7 +20,35 @@ "limits": "cpp", "memory": "cpp", "new": "cpp", - "type_traits": "cpp" + "type_traits": "cpp", + "atomic": "cpp", + "cctype": "cpp", + "clocale": "cpp", + "cstdarg": "cpp", + "cstdint": "cpp", + "cstdio": "cpp", + "cstdlib": "cpp", + "cstring": "cpp", + "ctime": "cpp", + "cwchar": "cpp", + "cwctype": "cpp", + "exception": "cpp", + "iterator": "cpp", + "map": "cpp", + "memory_resource": "cpp", + "numeric": "cpp", + "tuple": "cpp", + "utility": "cpp", + "fstream": "cpp", + "iomanip": "cpp", + "iosfwd": "cpp", + "istream": "cpp", + "ostream": "cpp", + "sstream": "cpp", + "stdexcept": "cpp", + "streambuf": "cpp", + "cinttypes": "cpp", + "typeinfo": "cpp" }, "cmake.configureOnOpen": false } \ No newline at end of file diff --git a/CYD-Klipper/src/core/klipper/klipper_printer_integration.cpp b/CYD-Klipper/src/core/klipper/klipper_printer_integration.cpp index ae60526..9b91c34 100644 --- a/CYD-Klipper/src/core/klipper/klipper_printer_integration.cpp +++ b/CYD-Klipper/src/core/klipper/klipper_printer_integration.cpp @@ -35,9 +35,7 @@ int KlipperPrinter::get_slicer_time_estimate_s() JsonDocument doc; deserializeJson(doc, client.getStream()); - int time_estimate_s = doc["result"]["estimated_time"]; - LOG_F(("Got slicer time estimate: %ds\n", time_estimate_s)) - return time_estimate_s; + return parse_slicer_time_estimate(doc); } bool KlipperPrinter::send_gcode(const char *gcode, bool wait) @@ -89,6 +87,22 @@ bool KlipperPrinter::move_printer(const char* axis, float amount, bool relative) return true; } +bool KlipperPrinter::send_emergency_stop() +{ + HTTPClient client; + configure_http_client(client, "/printer/emergency_stop", false, 5000); + + try + { + return client.GET() == 200; + } + catch (...) + { + LOG_LN("Failed to send estop"); + return false; + } +} + bool KlipperPrinter::execute_feature(PrinterFeatures feature) { HTTPClient client; @@ -112,16 +126,7 @@ bool KlipperPrinter::execute_feature(PrinterFeatures feature) case PrinterFeatureEmergencyStop: LOG_LN("Sending estop"); send_gcode("M112", false); - configure_http_client(client, "/printer/emergency_stop", false, 5000); - - try - { - client.GET(); - } - catch (...) - { - LOG_LN("Failed to send estop"); - } + send_emergency_stop(); return true; case PrinterFeatureExtrude: @@ -182,177 +187,7 @@ bool KlipperPrinter::fetch() klipper_request_consecutive_fail_count = 0; JsonDocument doc; deserializeJson(doc, client.getStream()); - auto status = doc["result"]["status"]; - bool emit_state_update = false; - - if (status.containsKey("webhooks")) - { - const char* state = status["webhooks"]["state"]; - const char* message = status["webhooks"]["state_message"]; - - if (strcmp(state, "ready") == 0 && printer_data.state == PrinterStateError) - { - printer_data.state = PrinterStateIdle; - } - else if ((strcmp(state, "shutdown") == 0 || strcmp(state, "error") == 0) && printer_data.state != PrinterStateError) - { - printer_data.state = PrinterStateError; - } - - if (message != NULL && (printer_data.state_message == NULL || strcmp(printer_data.state_message, message))) - { - printer_data.state_message = (char *)malloc(strlen(message) + 1); - strcpy(printer_data.state_message, message); - } - } - - if (printer_data.state != PrinterStateError) - { - if (status.containsKey("extruder")) - { - printer_data.temperatures[PrinterTemperatureDeviceIndexNozzle1] = status["extruder"]["temperature"]; - printer_data.target_temperatures[PrinterTemperatureDeviceIndexNozzle1] = status["extruder"]["target"]; - bool can_extrude = status["extruder"]["can_extrude"]; - printer_data.pressure_advance = status["extruder"]["pressure_advance"]; - printer_data.smooth_time = status["extruder"]["smooth_time"]; - printer_data.can_extrude = can_extrude == true; - } - - if (status.containsKey("heater_bed")) - { - printer_data.temperatures[PrinterTemperatureDeviceIndexBed] = status["heater_bed"]["temperature"]; - printer_data.target_temperatures[PrinterTemperatureDeviceIndexBed] = status["heater_bed"]["target"]; - } - - if (status.containsKey("toolhead")) - { - const char *homed_axis = status["toolhead"]["homed_axes"]; - printer_data.homed_axis = strcmp(homed_axis, "xyz") == 0; - } - - if (status.containsKey("gcode_move")) - { - printer_data.position[0] = status["gcode_move"]["gcode_position"][0]; - printer_data.position[1] = status["gcode_move"]["gcode_position"][1]; - printer_data.position[2] = status["gcode_move"]["gcode_position"][2]; - gcode_offset[0] = status["gcode_move"]["homing_origin"][0]; - gcode_offset[1] = status["gcode_move"]["homing_origin"][1]; - gcode_offset[2] = status["gcode_move"]["homing_origin"][2]; - bool absolute_coords = status["gcode_move"]["absolute_coordinates"]; - - if (lock_absolute_relative_mode_swap > 0) - { - lock_absolute_relative_mode_swap--; - } - else - { - printer_data.absolute_coords = absolute_coords == true; - } - - printer_data.speed_mult = status["gcode_move"]["speed_factor"]; - printer_data.extrude_mult = status["gcode_move"]["extrude_factor"]; - printer_data.feedrate_mm_per_s = status["gcode_move"]["speed"]; - printer_data.feedrate_mm_per_s /= 60; // convert mm/m to mm/s - } - - if (status.containsKey("fan")) - { - printer_data.fan_speed = status["fan"]["speed"]; - } - - if (status.containsKey("virtual_sdcard")) - { - printer_data.print_progress = status["virtual_sdcard"]["progress"]; - } - - if (status.containsKey("print_stats")) - { - const char *filename = status["print_stats"]["filename"]; - - if (filename != NULL && (printer_data.print_filename == NULL || strcmp(printer_data.print_filename, filename))) - { - printer_data.print_filename = (char *)malloc(strlen(filename) + 1); - strcpy(printer_data.print_filename, filename); - } - - printer_data.elapsed_time_s = status["print_stats"]["total_duration"]; - printer_data.printed_time_s = status["print_stats"]["print_duration"]; - printer_data.filament_used_mm = status["print_stats"]["filament_used"]; - printer_data.total_layers = status["print_stats"]["info"]["total_layer"]; - printer_data.current_layer = status["print_stats"]["info"]["current_layer"]; - - const char *state = status["print_stats"]["state"]; - - if (state == nullptr) - { - // Continue - } - else if (strcmp(state, "printing") == 0) - { - printer_data.state = PrinterStatePrinting; - } - else if (strcmp(state, "paused") == 0) - { - printer_data.state = PrinterStatePaused; - } - else if (strcmp(state, "complete") == 0 || strcmp(state, "cancelled") == 0 || strcmp(state, "standby") == 0) - { - printer_data.state = PrinterStateIdle; - } - } - - if (status.containsKey("display_status")) - { - printer_data.print_progress = status["display_status"]["progress"]; - const char* message = status["display_status"]["message"]; - - if (message != NULL && (printer_data.popup_message == NULL || strcmp(printer_data.popup_message, message))) - { - printer_data.popup_message = (char*)malloc(strlen(message) + 1); - strcpy(printer_data.popup_message, message); - } - } - - if (printer_data.state == PrinterStatePrinting && printer_data.print_progress > 0) - { - float remaining_time_s_percentage = (printer_data.printed_time_s / printer_data.print_progress) - printer_data.printed_time_s; - float remaining_time_s_slicer = 0; - - if (slicer_estimated_print_time_s > 0) - { - remaining_time_s_slicer = slicer_estimated_print_time_s - printer_data.printed_time_s; - } - - if (remaining_time_s_slicer <= 0 || printer_config->remaining_time_calc_mode == REMAINING_TIME_CALC_PERCENTAGE) - { - printer_data.remaining_time_s = remaining_time_s_percentage; - } - else if (printer_config->remaining_time_calc_mode == REMAINING_TIME_CALC_INTERPOLATED) - { - printer_data.remaining_time_s = remaining_time_s_percentage * printer_data.print_progress + remaining_time_s_slicer * (1 - printer_data.print_progress); - } - else if (printer_config->remaining_time_calc_mode == REMAINING_TIME_CALC_SLICER) - { - printer_data.remaining_time_s = remaining_time_s_slicer; - } - } - - if (printer_data.remaining_time_s < 0) - { - printer_data.remaining_time_s = 0; - } - - if (printer_data.state == PrinterStateIdle) - { - slicer_estimated_print_time_s = 0; - } - } - - if (printer_data.state == PrinterStatePrinting && millis() - last_slicer_time_query > 30000 && slicer_estimated_print_time_s <= 0) - { - last_slicer_time_query = millis(); - slicer_estimated_print_time_s = get_slicer_time_estimate_s(); - } + parse_state(doc); } else { @@ -393,47 +228,7 @@ PrinterDataMinimal KlipperPrinter::fetch_min() JsonDocument doc; deserializeJson(doc, client.getStream()); - auto status = doc["result"]["status"]; - - if (status.containsKey("webhooks")) - { - const char *state = status["webhooks"]["state"]; - - if (strcmp(state, "shutdown") == 0) - { - data.state = PrinterState::PrinterStateError; - } - } - - if (data.state != PrinterStateError) - { - if (status.containsKey("virtual_sdcard")) - { - data.print_progress = status["virtual_sdcard"]["progress"]; - } - - if (status.containsKey("print_stats")) - { - const char *state = status["print_stats"]["state"]; - - if (state == nullptr) - { - data.state = PrinterState::PrinterStateError; - } - else if (strcmp(state, "printing") == 0) - { - data.state = PrinterState::PrinterStatePrinting; - } - else if (strcmp(state, "paused") == 0) - { - data.state = PrinterState::PrinterStatePaused; - } - else if (strcmp(state, "complete") == 0 || strcmp(state, "cancelled") == 0 || strcmp(state, "standby") == 0) - { - data.state = PrinterState::PrinterStateIdle; - } - } - } + return parse_state_min(doc); } else { @@ -461,27 +256,7 @@ Macros KlipperPrinter::get_macros() if (http_code == 200){ JsonDocument doc; deserializeJson(doc, client.getStream()); - auto result = doc["result"].as(); - macros.macros = (char**)malloc(sizeof(char*) * 32); - macros.count = 0; - macros.success = true; - - for (JsonPair i : result){ - const char *key = i.key().c_str(); - const char *value = i.value().as().c_str(); - if (strcmp(value, "CYD_SCREEN_MACRO") == 0) { - char* macro = (char*)malloc(strlen(key) + 1); - strcpy(macro, key); - macros.macros[macros.count++] = macro; - } - } - - if (global_config.sort_macros) - { - std::sort(macros.macros, macros.macros + macros.count, [](const char* a, const char* b) { - return strcmp(a, b) < 0; - }); - } + return parse_macros(doc); } return macros; @@ -497,18 +272,7 @@ int KlipperPrinter::get_macros_count() if (http_code == 200){ JsonDocument doc; deserializeJson(doc, client.getStream()); - auto result = doc["result"].as(); - - int count = 0; - - for (JsonPair i : result){ - const char *value = i.value().as().c_str(); - if (strcmp(value, "CYD_SCREEN_MACRO") == 0) { - count++; - } - } - - return count; + return parse_macros_count(doc); } else { return 0; @@ -531,20 +295,7 @@ PowerDevices KlipperPrinter::get_power_devices() if (http_code == 200){ JsonDocument doc; deserializeJson(doc, client.getStream()); - auto result = doc["result"]["devices"].as(); - power_devices.power_devices = (char**)malloc(sizeof(char*) * 16); - power_devices.power_states = (bool*)malloc(sizeof(bool) * 16); - power_devices.count = 0; - power_devices.success = true; - - for (auto i : result){ - const char * device_name = i["device"]; - const char * device_state = i["status"]; - power_devices.power_devices[power_devices.count] = (char*)malloc(strlen(device_name) + 1); - strcpy(power_devices.power_devices[power_devices.count], device_name); - power_devices.power_states[power_devices.count] = strcmp(device_state, "on") == 0; - power_devices.count++; - } + return parse_power_devices(doc); } return power_devices; @@ -560,15 +311,7 @@ int KlipperPrinter::get_power_devices_count() if (http_code == 200){ JsonDocument doc; deserializeJson(doc, client.getStream()); - auto result = doc["result"]["devices"].as(); - - int count = 0; - - for (auto i : result){ - count++; - } - - return count; + return parse_power_devices_count(doc); } else { return 0; @@ -582,11 +325,6 @@ bool KlipperPrinter::set_power_device_state(const char* device_name, bool state) return client.POST("") == 200; } -typedef struct { - char* name; - float modified; -} FileSystemFile; - #define KLIPPER_FILE_FETCH_LIMIT 20 Files KlipperPrinter::get_files() @@ -606,46 +344,7 @@ Files KlipperPrinter::get_files() JsonDocument doc; auto parseResult = deserializeJson(doc, client.getStream()); LOG_F(("Json parse: %s\n", parseResult.c_str())) - auto result = doc["result"].as(); - - for (auto file : result){ - FileSystemFile 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++; - } - - if (file_iter == files.end() && files.size() >= KLIPPER_FILE_FETCH_LIMIT) - continue; - - f.name = (char*)malloc(strlen(path) + 1); - if (f.name == NULL){ - LOG_LN("Failed to allocate memory"); - continue; - } - strcpy(f.name, path); - f.modified = modified; - - if (file_iter != files.end()) - files.insert(file_iter, f); - else - files.push_back(f); - - if (files.size() > KLIPPER_FILE_FETCH_LIMIT){ - auto last_entry = files.back(); - - if (last_entry.name != NULL) - free(last_entry.name); - - files.pop_back(); - } - } + parse_file_list(doc, files, KLIPPER_FILE_FETCH_LIMIT); } files_result.available_files = (char**)malloc(sizeof(char*) * files.size()); @@ -724,30 +423,7 @@ Thumbnail KlipperPrinter::get_32_32_png_image_thumbnail(const char* gcode_filena { JsonDocument doc; deserializeJson(doc, client.getStream()); - auto result = doc["result"].as(); - const char* chosen_thumb = NULL; - for (auto file : result){ - int width = file["width"]; - int height = file["height"]; - int size = file["size"]; - const char* thumbnail = file["thumbnail_path"]; - - if (width != height || width != 32) - continue; - - - if (strcmp(thumbnail + strlen(thumbnail) - 4, ".png")) - continue; - - chosen_thumb = thumbnail; - break; - } - - if (chosen_thumb != NULL){ - LOG_F(("Found 32x32 PNG gcode img at %s\n", gcode_filename)) - img_filename_path = (char*)malloc(strlen(chosen_thumb) + 1); - strcpy(img_filename_path, chosen_thumb); - } + img_filename_path = parse_thumbnails(doc); } else { @@ -759,6 +435,10 @@ Thumbnail KlipperPrinter::get_32_32_png_image_thumbnail(const char* gcode_filena LOG_LN("No compatible thumbnail found"); return thumbnail; } + else + { + LOG_F(("Found 32x32 PNG gcode img at %s\n", gcode_filename)); + } client.end(); diff --git a/CYD-Klipper/src/core/klipper/klipper_printer_integration.hpp b/CYD-Klipper/src/core/klipper/klipper_printer_integration.hpp index a144667..758c9ba 100644 --- a/CYD-Klipper/src/core/klipper/klipper_printer_integration.hpp +++ b/CYD-Klipper/src/core/klipper/klipper_printer_integration.hpp @@ -2,6 +2,13 @@ #include "../printer_integration.hpp" #include +#include +#include + +typedef struct { + char* name; + float modified; +} FileSystemFile; class KlipperPrinter : public BasePrinter { @@ -10,6 +17,22 @@ class KlipperPrinter : public BasePrinter unsigned char klipper_request_consecutive_fail_count{}; unsigned int slicer_estimated_print_time_s{}; unsigned int last_slicer_time_query{}; + void configure_http_client(HTTPClient &client, String url_part, bool stream, int timeout); + + protected: + bool send_emergency_stop(); + int get_slicer_time_estimate_s(); + void init_ui_panels(); + + int parse_slicer_time_estimate(JsonDocument& in); + void parse_state(JsonDocument& in); + PrinterDataMinimal parse_state_min(JsonDocument& in); + Macros parse_macros(JsonDocument &in); + int parse_macros_count(JsonDocument &in); + PowerDevices parse_power_devices(JsonDocument &in); + int parse_power_devices_count(JsonDocument &in); + void parse_file_list(JsonDocument &in, std::list &files, int fetch_limit); + char *parse_thumbnails(JsonDocument &in); public: float gcode_offset[3]{}; @@ -51,9 +74,6 @@ class KlipperPrinter : public BasePrinter Thumbnail get_32_32_png_image_thumbnail(const char* gcode_filename); bool set_target_temperature(PrinterTemperatureDevice device, unsigned int temperature); bool send_gcode(const char* gcode, bool wait = true); - int get_slicer_time_estimate_s(); - void configure_http_client(HTTPClient &client, String url_part, bool stream, int timeout); - void init_ui_panels(); }; enum ConnectionStatus { diff --git a/CYD-Klipper/src/core/klipper/klipper_printer_parsers.cpp b/CYD-Klipper/src/core/klipper/klipper_printer_parsers.cpp new file mode 100644 index 0000000..eab6d02 --- /dev/null +++ b/CYD-Klipper/src/core/klipper/klipper_printer_parsers.cpp @@ -0,0 +1,394 @@ +#include "../printer_integration.hpp" +#include "klipper_printer_integration.hpp" +#include + +int KlipperPrinter::parse_slicer_time_estimate(JsonDocument &in) +{ + int time_estimate_s = in["result"]["estimated_time"]; + LOG_F(("Got slicer time estimate: %ds\n", time_estimate_s)) + return time_estimate_s; +} + +void KlipperPrinter::parse_state(JsonDocument &in) +{ + auto status = in["result"]["status"]; + + if (status.containsKey("webhooks")) + { + const char *state = status["webhooks"]["state"]; + const char *message = status["webhooks"]["state_message"]; + + if (strcmp(state, "ready") == 0 && printer_data.state == PrinterStateError) + { + printer_data.state = PrinterStateIdle; + } + else if ((strcmp(state, "shutdown") == 0 || strcmp(state, "error") == 0) && printer_data.state != PrinterStateError) + { + printer_data.state = PrinterStateError; + } + + if (message != NULL && (printer_data.state_message == NULL || strcmp(printer_data.state_message, message))) + { + printer_data.state_message = (char *)malloc(strlen(message) + 1); + strcpy(printer_data.state_message, message); + } + } + + if (printer_data.state != PrinterStateError) + { + if (status.containsKey("extruder")) + { + printer_data.temperatures[PrinterTemperatureDeviceIndexNozzle1] = status["extruder"]["temperature"]; + printer_data.target_temperatures[PrinterTemperatureDeviceIndexNozzle1] = status["extruder"]["target"]; + bool can_extrude = status["extruder"]["can_extrude"]; + printer_data.pressure_advance = status["extruder"]["pressure_advance"]; + printer_data.smooth_time = status["extruder"]["smooth_time"]; + printer_data.can_extrude = can_extrude == true; + } + + if (status.containsKey("heater_bed")) + { + printer_data.temperatures[PrinterTemperatureDeviceIndexBed] = status["heater_bed"]["temperature"]; + printer_data.target_temperatures[PrinterTemperatureDeviceIndexBed] = status["heater_bed"]["target"]; + } + + if (status.containsKey("toolhead")) + { + const char *homed_axis = status["toolhead"]["homed_axes"]; + printer_data.homed_axis = strcmp(homed_axis, "xyz") == 0; + } + + if (status.containsKey("gcode_move")) + { + printer_data.position[0] = status["gcode_move"]["gcode_position"][0]; + printer_data.position[1] = status["gcode_move"]["gcode_position"][1]; + printer_data.position[2] = status["gcode_move"]["gcode_position"][2]; + gcode_offset[0] = status["gcode_move"]["homing_origin"][0]; + gcode_offset[1] = status["gcode_move"]["homing_origin"][1]; + gcode_offset[2] = status["gcode_move"]["homing_origin"][2]; + bool absolute_coords = status["gcode_move"]["absolute_coordinates"]; + + if (lock_absolute_relative_mode_swap > 0) + { + lock_absolute_relative_mode_swap--; + } + else + { + printer_data.absolute_coords = absolute_coords == true; + } + + printer_data.speed_mult = status["gcode_move"]["speed_factor"]; + printer_data.extrude_mult = status["gcode_move"]["extrude_factor"]; + printer_data.feedrate_mm_per_s = status["gcode_move"]["speed"]; + printer_data.feedrate_mm_per_s /= 60; // convert mm/m to mm/s + } + + if (status.containsKey("fan")) + { + printer_data.fan_speed = status["fan"]["speed"]; + } + + if (status.containsKey("virtual_sdcard")) + { + printer_data.print_progress = status["virtual_sdcard"]["progress"]; + } + + if (status.containsKey("print_stats")) + { + const char *filename = status["print_stats"]["filename"]; + + if (filename != NULL && (printer_data.print_filename == NULL || strcmp(printer_data.print_filename, filename))) + { + printer_data.print_filename = (char *)malloc(strlen(filename) + 1); + strcpy(printer_data.print_filename, filename); + } + + printer_data.elapsed_time_s = status["print_stats"]["total_duration"]; + printer_data.printed_time_s = status["print_stats"]["print_duration"]; + printer_data.filament_used_mm = status["print_stats"]["filament_used"]; + printer_data.total_layers = status["print_stats"]["info"]["total_layer"]; + printer_data.current_layer = status["print_stats"]["info"]["current_layer"]; + + const char *state = status["print_stats"]["state"]; + + if (state == nullptr) + { + // Continue + } + else if (strcmp(state, "printing") == 0) + { + printer_data.state = PrinterStatePrinting; + } + else if (strcmp(state, "paused") == 0) + { + printer_data.state = PrinterStatePaused; + } + else if (strcmp(state, "complete") == 0 || strcmp(state, "cancelled") == 0 || strcmp(state, "standby") == 0) + { + printer_data.state = PrinterStateIdle; + } + } + + if (status.containsKey("display_status")) + { + printer_data.print_progress = status["display_status"]["progress"]; + const char *message = status["display_status"]["message"]; + + if (message != NULL && (printer_data.popup_message == NULL || strcmp(printer_data.popup_message, message))) + { + printer_data.popup_message = (char *)malloc(strlen(message) + 1); + strcpy(printer_data.popup_message, message); + } + } + + if (printer_data.state == PrinterStatePrinting && printer_data.print_progress > 0) + { + float remaining_time_s_percentage = (printer_data.printed_time_s / printer_data.print_progress) - printer_data.printed_time_s; + float remaining_time_s_slicer = 0; + + if (slicer_estimated_print_time_s > 0) + { + remaining_time_s_slicer = slicer_estimated_print_time_s - printer_data.printed_time_s; + } + + if (remaining_time_s_slicer <= 0 || printer_config->remaining_time_calc_mode == REMAINING_TIME_CALC_PERCENTAGE) + { + printer_data.remaining_time_s = remaining_time_s_percentage; + } + else if (printer_config->remaining_time_calc_mode == REMAINING_TIME_CALC_INTERPOLATED) + { + printer_data.remaining_time_s = remaining_time_s_percentage * printer_data.print_progress + remaining_time_s_slicer * (1 - printer_data.print_progress); + } + else if (printer_config->remaining_time_calc_mode == REMAINING_TIME_CALC_SLICER) + { + printer_data.remaining_time_s = remaining_time_s_slicer; + } + } + + if (printer_data.remaining_time_s < 0) + { + printer_data.remaining_time_s = 0; + } + + if (printer_data.state == PrinterStateIdle) + { + slicer_estimated_print_time_s = 0; + } + } + + if (printer_data.state == PrinterStatePrinting && millis() - last_slicer_time_query > 30000 && slicer_estimated_print_time_s <= 0) + { + last_slicer_time_query = millis(); + slicer_estimated_print_time_s = get_slicer_time_estimate_s(); + } +} + +PrinterDataMinimal KlipperPrinter::parse_state_min(JsonDocument &in) +{ + auto status = in["result"]["status"]; + PrinterDataMinimal data = {}; + data.success = true; + + if (status.containsKey("webhooks")) + { + const char *state = status["webhooks"]["state"]; + + if (strcmp(state, "shutdown") == 0) + { + data.state = PrinterState::PrinterStateError; + } + } + + if (data.state != PrinterStateError) + { + if (status.containsKey("virtual_sdcard")) + { + data.print_progress = status["virtual_sdcard"]["progress"]; + } + + if (status.containsKey("print_stats")) + { + const char *state = status["print_stats"]["state"]; + + if (state == nullptr) + { + data.state = PrinterState::PrinterStateError; + } + else if (strcmp(state, "printing") == 0) + { + data.state = PrinterState::PrinterStatePrinting; + } + else if (strcmp(state, "paused") == 0) + { + data.state = PrinterState::PrinterStatePaused; + } + else if (strcmp(state, "complete") == 0 || strcmp(state, "cancelled") == 0 || strcmp(state, "standby") == 0) + { + data.state = PrinterState::PrinterStateIdle; + } + } + } + + return data; +} + +Macros KlipperPrinter::parse_macros(JsonDocument &in) +{ + auto result = in["result"].as(); + Macros macros = {0}; + macros.macros = (char **)malloc(sizeof(char *) * 32); + macros.count = 0; + macros.success = true; + + for (JsonPair i : result) + { + const char *key = i.key().c_str(); + const char *value = i.value().as().c_str(); + if (strcmp(value, "CYD_SCREEN_MACRO") == 0) + { + char *macro = (char *)malloc(strlen(key) + 1); + strcpy(macro, key); + macros.macros[macros.count++] = macro; + } + } + + if (global_config.sort_macros) + { + std::sort(macros.macros, macros.macros + macros.count, [](const char *a, const char *b) + { return strcmp(a, b) < 0; }); + } + + return macros; +} + +int KlipperPrinter::parse_macros_count(JsonDocument &in) +{ + auto result = in["result"].as(); + + int count = 0; + + for (JsonPair i : result) + { + const char *value = i.value().as().c_str(); + if (strcmp(value, "CYD_SCREEN_MACRO") == 0) + { + count++; + } + } + + return count; +} + +PowerDevices KlipperPrinter::parse_power_devices(JsonDocument &in) +{ + PowerDevices power_devices = {0}; + auto result = in["result"]["devices"].as(); + power_devices.power_devices = (char **)malloc(sizeof(char *) * 16); + power_devices.power_states = (bool *)malloc(sizeof(bool) * 16); + power_devices.count = 0; + power_devices.success = true; + + for (auto i : result) + { + const char *device_name = i["device"]; + const char *device_state = i["status"]; + power_devices.power_devices[power_devices.count] = (char *)malloc(strlen(device_name) + 1); + strcpy(power_devices.power_devices[power_devices.count], device_name); + power_devices.power_states[power_devices.count] = strcmp(device_state, "on") == 0; + power_devices.count++; + } + + return power_devices; +} + +int KlipperPrinter::parse_power_devices_count(JsonDocument &in) +{ + auto result = in["result"]["devices"].as(); + int count = 0; + + for (auto i : result) + { + count++; + } + + return count; +} + +void KlipperPrinter::parse_file_list(JsonDocument &in, std::list &files, int fetch_limit) +{ + auto result = in["result"].as(); + + for (auto file : result) + { + FileSystemFile 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++; + } + + if (file_iter == files.end() && files.size() >= fetch_limit) + continue; + + f.name = (char *)malloc(strlen(path) + 1); + if (f.name == NULL) + { + LOG_LN("Failed to allocate memory"); + continue; + } + strcpy(f.name, path); + f.modified = modified; + + if (file_iter != files.end()) + files.insert(file_iter, f); + else + files.push_back(f); + + if (files.size() > fetch_limit) + { + auto last_entry = files.back(); + + if (last_entry.name != NULL) + free(last_entry.name); + + files.pop_back(); + } + } +} + +char *KlipperPrinter::parse_thumbnails(JsonDocument &in) +{ + auto result = in["result"].as(); + const char *chosen_thumb = NULL; + for (auto file : result) + { + int width = file["width"]; + int height = file["height"]; + int size = file["size"]; + const char *thumbnail = file["thumbnail_path"]; + + if (width != height || width != 32) + continue; + + if (strcmp(thumbnail + strlen(thumbnail) - 4, ".png")) + continue; + + chosen_thumb = thumbnail; + break; + } + + if (chosen_thumb != NULL) + { + char* img_filename_path = (char *)malloc(strlen(chosen_thumb) + 1); + strcpy(img_filename_path, chosen_thumb); + return img_filename_path; + } + + return NULL; +} \ No newline at end of file From 4207d82a7efb9431188b156043d90bfde3e796d0 Mon Sep 17 00:00:00 2001 From: suchmememanyskill <38142618+suchmememanyskill@users.noreply.github.com> Date: Tue, 29 Oct 2024 17:57:20 +0100 Subject: [PATCH 24/63] Basic bambu implementation --- CYD-Klipper/platformio.ini | 7 +- CYD-Klipper/src/conf/global_config.cpp | 1 + CYD-Klipper/src/conf/global_config.h | 12 +- .../core/bambu/bambu_printer_integration.cpp | 371 +++++++++++++++++ .../core/bambu/bambu_printer_integration.hpp | 78 ++++ .../src/core/bambu/bambu_printer_parsers.cpp | 207 ++++++++++ CYD-Klipper/src/core/data_setup.cpp | 3 + .../klipper/klipper_printer_integration.cpp | 12 +- .../klipper/klipper_printer_integration.hpp | 5 +- CYD-Klipper/src/core/printer_integration.cpp | 9 +- CYD-Klipper/src/core/printer_integration.hpp | 9 +- CYD-Klipper/src/ui/ip_setup.cpp | 385 +++++++++++++----- CYD-Klipper/src/ui/main_ui.cpp | 3 +- CYD-Klipper/src/ui/panels/error_panel.cpp | 58 ++- CYD-Klipper/src/ui/panels/printer_panel.cpp | 1 - CYD-Klipper/src/ui/serial/serial_commands.cpp | 1 - CYD-Klipper/src/ui/switch_printer.cpp | 74 ---- CYD-Klipper/src/ui/switch_printer.h | 5 - CYD-Klipper/src/ui/ui_utils.cpp | 2 +- 19 files changed, 1010 insertions(+), 233 deletions(-) create mode 100644 CYD-Klipper/src/core/bambu/bambu_printer_integration.cpp create mode 100644 CYD-Klipper/src/core/bambu/bambu_printer_integration.hpp create mode 100644 CYD-Klipper/src/core/bambu/bambu_printer_parsers.cpp delete mode 100644 CYD-Klipper/src/ui/switch_printer.cpp delete mode 100644 CYD-Klipper/src/ui/switch_printer.h diff --git a/CYD-Klipper/platformio.ini b/CYD-Klipper/platformio.ini index 3969297..4d45bf8 100644 --- a/CYD-Klipper/platformio.ini +++ b/CYD-Klipper/platformio.ini @@ -18,6 +18,7 @@ lib_deps = bblanchon/ArduinoJson@^7.0.0 plageoj/UrlEncode@^1.0.1 erriez/ErriezCRC32 @ ^1.0.1 + knolleary/PubSubClient@^2.8 monitor_filters = esp32_exception_decoder build_flags = -DLV_CONF_PATH="../../../../src/conf/lv_conf.h" @@ -33,6 +34,7 @@ lib_deps = https://github.com/PaulStoffregen/XPT2046_Touchscreen.git bblanchon/ArduinoJson@^7.0.0 plageoj/UrlEncode@^1.0.1 + knolleary/PubSubClient@^2.8 [env:esp32-3248S035C] board = esp32-3248S035C @@ -43,6 +45,7 @@ lib_deps = https://github.com/OperatorB/gt911-arduino-fixed-reset.git bblanchon/ArduinoJson@^7.0.0 plageoj/UrlEncode@^1.0.1 + knolleary/PubSubClient@^2.8 [env:esp32-3248S035C-V] board = esp32-3248S035C-vertical @@ -53,6 +56,7 @@ lib_deps = https://github.com/OperatorB/gt911-arduino-fixed-reset.git bblanchon/ArduinoJson@^7.0.0 plageoj/UrlEncode@^1.0.1 + knolleary/PubSubClient@^2.8 [env:esp32-2432S024C-SD] board = esp32-2432S024C-smartdisplay @@ -79,5 +83,4 @@ board = esp32-4827S043C-smartdisplay board = esp32-4827S043C-smartdisplay [env:esp32-8048S043C-SD] -board = esp32-8048S043C-smartdisplay - +board = esp32-8048S043C-smartdisplay \ No newline at end of file diff --git a/CYD-Klipper/src/conf/global_config.cpp b/CYD-Klipper/src/conf/global_config.cpp index c1e0e4c..56c05b2 100644 --- a/CYD-Klipper/src/conf/global_config.cpp +++ b/CYD-Klipper/src/conf/global_config.cpp @@ -81,6 +81,7 @@ void global_config_add_new_printer() new_config->setup_complete = false; new_config->ip_configured = false; new_config->auth_configured = false; + new_config->printer_type = PrinterType::PrinterTypeNone; new_config->printer_name[0] = 0; new_config->klipper_host[0] = 0; diff --git a/CYD-Klipper/src/conf/global_config.h b/CYD-Klipper/src/conf/global_config.h index 2dcf3c1..5cfad49 100644 --- a/CYD-Klipper/src/conf/global_config.h +++ b/CYD-Klipper/src/conf/global_config.h @@ -21,10 +21,12 @@ enum { }; enum PrinterType { - PrinterTypeKlipper = 0, - PrinterTypeKlipperSerial = 1, - PrinterTypeBambu = 2, - PrinterTypeOctoprint = 3, + PrinterTypeNone = 0, + PrinterTypeKlipper = 1, + PrinterTypeKlipperSerial = 2, + PrinterTypeBambuLocal = 3, + PrinterTypeBambuCloud = 3, + PrinterTypeOctoprint = 4, }; typedef struct { @@ -49,7 +51,7 @@ typedef struct { char printer_name[25]; char klipper_host[65]; char klipper_auth[33]; - unsigned short klipper_port; + unsigned int klipper_port; unsigned char color_scheme; diff --git a/CYD-Klipper/src/core/bambu/bambu_printer_integration.cpp b/CYD-Klipper/src/core/bambu/bambu_printer_integration.cpp new file mode 100644 index 0000000..511b754 --- /dev/null +++ b/CYD-Klipper/src/core/bambu/bambu_printer_integration.cpp @@ -0,0 +1,371 @@ +#include "bambu_printer_integration.hpp" +#include +#include + +WiFiClientSecure wifi_client; +PubSubClient client(wifi_client); +BambuPrinter* current_printer = NULL; + +const char* COMMAND_FETCH_ALL = "{\"pushing\":{\"sequence_id\":\"0\",\"command\":\"pushall\",\"version\":1,\"push_target\":1}}"; +const char* COMMAND_LIGHTCTL = "{\"system\":{\"sequence_id\":\"0\",\"command\":\"ledctrl\",\"led_node\":\"%s\",\"led_mode\":\"%s\"}}"; +const char* COMMAND_SEND_GCODE = "{\"print\":{\"sequence_id\":\"0\",\"command\":\"gcode_line\",\"param\":\"%s\"}}"; +const char* COMMAND_PRINT_STOP = "{\"print\":{\"sequence_id\":\"0\",\"command\":\"stop\",\"param\":\"\"}}"; +const char* COMMAND_PRINT_PAUSE = "{\"print\":{\"sequence_id\":\"0\",\"command\":\"pause\",\"param\":\"\"}}"; +const char* COMMAND_PRINT_RESUME = "{\"print\":{\"sequence_id\":\"0\",\"command\":\"resume\",\"param\":\"\"}}"; +const char* COMMAND_FILAMENT_UNLOAD = "{\"print\":{\"sequence_id\":\"0\",\"command\":\"unload_filament\"}}"; +const char* COMMAND_FILAMENT_LOAD_EXTERNAL = "{\"print\":{\"sequence_id\":\"0\",\"command\":\"ams_change_filament\",\"target\":254,\"curr_temp\":215,\"tar_temp\":250}}"; +const char* COMMAND_AMS_CONTOL_DONE = "{\"print\":{\"sequence_id\":\"0\",\"command\":\"ams_control\",\"param\":\"done\"}}"; +const char* COMMAND_AMS_CONTOL_RETRY = "{\"print\":{\"sequence_id\":\"0\",\"command\":\"ams_control\",\"param\":\"resume\"}}"; + +static void callback(char* topic, byte* payload, unsigned int length) +{ + if (current_printer != NULL) + { + current_printer->receive_data(payload, length); + } +} + +void BambuPrinter::receive_data(unsigned char* data, unsigned int length) +{ + data[length] = 0; + JsonDocument doc; + deserializeJson(doc, data); + parse_state(doc); +} + +bool BambuPrinter::publish_mqtt_command(const char* command) +{ + if (!client.connected()) + { + return false; + } + + char auth[48] = {0}; + sprintf(auth, "device/%s/request", printer_config->klipper_auth); + + return client.publish(auth, command); +} + +bool BambuPrinter::move_printer(const char* axis, float amount, bool relative) +{ + if (!printer_data.homed_axis || printer_data.state == PrinterStatePrinting) + return false; + + char gcode[64]; + const char* extra = (amount > 0) ? "+" : ""; + const char* start = ""; + const char* end = ""; + + if (relative) { + start = "G91\n"; + } + else { + start = "G90\n"; + } + + sprintf(gcode, "%sG1 %s%s%.3f F6000", start, axis, extra, amount); + send_gcode(gcode); + + return true; +} + +bool BambuPrinter::execute_feature(PrinterFeatures feature) +{ + switch (feature) + { + case PrinterFeatureHome: + return send_gcode("G28"); + case PrinterFeatureDisableSteppers: + return send_gcode("M18 X Y Z"); + case PrinterFeaturePause: + return publish_mqtt_command(COMMAND_PRINT_PAUSE); + case PrinterFeatureResume: + return publish_mqtt_command(COMMAND_PRINT_RESUME); + case PrinterFeatureStop: + return publish_mqtt_command(COMMAND_PRINT_STOP); + case PrinterFeatureExtrude: + if (printer_data.state == PrinterStatePrinting) + { + return false; + } + + return send_gcode("M83\nG1 E25 F300"); + case PrinterFeatureRetract: + if (printer_data.state == PrinterStatePrinting) + { + return false; + } + + return send_gcode("M83\nG1 E-25 F300"); + case PrinterFeatureCooldown: + return send_gcode("M104 S0\nM140 S0"); + case PrinterFeatureContinueError: + return publish_mqtt_command(COMMAND_AMS_CONTOL_DONE); + case PrinterFeatureRetryError: + return publish_mqtt_command(COMMAND_AMS_CONTOL_RETRY); + case PrinterFeatureIgnoreError: + ignore_error = last_error; + publish_mqtt_command(COMMAND_FETCH_ALL); + return true; + default: + LOG_F(("Unsupported printer feature %d", feature)); + } + + return false; +} + +bool BambuPrinter::connect() +{ + wifi_client.setInsecure(); + client.setBufferSize(4096); + client.setServer(printer_config->klipper_host, 8883); + current_printer = this; + client.setCallback(NULL); + char buff[10] = {0}; + sprintf(buff, "%d", printer_config->klipper_port); + if (!client.connect("id", "bblp", buff)) + { + LOG_LN(("Bambu: Wrong IP or LAN code.")); + return false; + } + + char auth[48] = {0}; + sprintf(auth, "device/%s/report", printer_config->klipper_auth); + + if (!client.subscribe(auth)) + { + LOG_LN(("Bambu: Wrong serial number.")); + return false; + } + + delay(100); + client.loop(); + + if (!client.connected()) + { + LOG_LN(("Bambu: Connection lost. Likely wrong serial number.")); + return false; + } + + client.setCallback(callback); + printer_data.state = PrinterState::PrinterStateIdle; + return publish_mqtt_command(COMMAND_FETCH_ALL); +} + +void BambuPrinter::disconnect() +{ + current_printer = NULL; + printer_data.state = PrinterState::PrinterStateOffline; + client.disconnect(); + client.setCallback(NULL); + client.setBufferSize(16); +} + +bool BambuPrinter::fetch() +{ + if (!client.connected()) + { + LOG_LN("Failed to fetch printer data: Not connected"); + return false; + } + + if (!client.loop()) + { + LOG_LN("Failed to fetch printer data: Fetching data failed"); + return false; + } + + return true; +} + +PrinterDataMinimal BambuPrinter::fetch_min() +{ + PrinterDataMinimal min = {}; + min.success = true; + min.state = PrinterState::PrinterStateIdle; + min.print_progress = 0; + min.power_devices = 0; + return min; +} + +const char * MACRO_UNLOAD = "Unload filament"; +const char * MACRO_LOAD = "Load filament (External)"; + +Macros BambuPrinter::get_macros() +{ + Macros macros = {0}; + macros.success = true; + macros.count = get_macros_count(); + macros.macros = (char **)malloc(sizeof(char *) * macros.count); + + macros.macros[0] = (char *)malloc(25); + strcpy(macros.macros[0], MACRO_LOAD); + + macros.macros[1] = (char *)malloc(16); + strcpy(macros.macros[1], MACRO_UNLOAD); + + return macros; +} + +int BambuPrinter::get_macros_count() +{ + return 2; +} + +bool BambuPrinter::execute_macro(const char* macro) +{ + if (strcmp(macro, MACRO_LOAD) == 0) + { + return publish_mqtt_command(COMMAND_FILAMENT_LOAD_EXTERNAL); + } + else if (strcmp(macro, MACRO_UNLOAD) == 0) + { + return publish_mqtt_command(COMMAND_FILAMENT_UNLOAD); + } + + return false; +} + +const char* WORK_LIGHT = "Work Light"; +const char* CHAMBER_LIGHT = "Chamber Light"; + +PowerDevices BambuPrinter::get_power_devices() +{ + PowerDevices power_devices = {0}; + power_devices.success = true; + int count = get_power_devices_count(); + + if (count == 0) + { + return power_devices; + } + + power_devices.power_devices = (char **)malloc(sizeof(char *) * count); + power_devices.power_states = (bool *)malloc(sizeof(bool) * count); + + if (work_light_available) + { + power_devices.power_devices[power_devices.count] = (char *)malloc(10 + 1); + strcpy(power_devices.power_devices[power_devices.count], WORK_LIGHT); + power_devices.power_states[power_devices.count] = work_light_on; + power_devices.count++; + } + + if (chamber_light_available) + { + power_devices.power_devices[power_devices.count] = (char *)malloc(13 + 1); + strcpy(power_devices.power_devices[power_devices.count], CHAMBER_LIGHT); + power_devices.power_states[power_devices.count] = chamber_light_on; + power_devices.count++; + } + + return power_devices; +} + +int BambuPrinter::get_power_devices_count() +{ + return (work_light_available ? 1 : 0) + (chamber_light_available ? 1 : 0); +} + +bool BambuPrinter::set_power_device_state(const char* device_name, bool state) +{ + char buff[128] = {0}; + const char* device; + + if (strcmp(device_name, WORK_LIGHT) == 0) + { + device = "work_light"; + } + else if (strcmp(device_name, CHAMBER_LIGHT) == 0) + { + device = "chamber_light"; + } + else + { + return false; + } + + sprintf(buff, COMMAND_LIGHTCTL, device, state ? "on" : "off"); + return publish_mqtt_command(buff); +} + +Files BambuPrinter::get_files() +{ + Files files = {0}; + return files; +} + +bool BambuPrinter::start_file(const char* filename) +{ + return false; +} + +Thumbnail BambuPrinter::get_32_32_png_image_thumbnail(const char* gcode_filename) +{ + Thumbnail thumbnail = {0}; + return thumbnail; +} + +bool BambuPrinter::set_target_temperature(PrinterTemperatureDevice device, unsigned int temperature) +{ + char gcode[64] = {0}; + + switch (device) + { + case PrinterTemperatureDeviceBed: + sprintf(gcode, "M140 S%d", temperature); + break; + case PrinterTemperatureDeviceNozzle1: + sprintf(gcode, "M104 S%d", temperature); + break; + default: + LOG_F(("Unknown temperature device %d was requested to heat to %.2f", device, temperature)); + return false; + } + + return send_gcode(gcode); +} + +bool BambuPrinter::send_gcode(const char* gcode, bool wait) +{ + char* buff = (char *)malloc(strlen(gcode) + 70); + sprintf(buff, COMMAND_SEND_GCODE, gcode); + return publish_mqtt_command(buff); +} + +BambuConnectionStatus connection_test_bambu(PrinterConfiguration* config) +{ + WiFiClientSecure connection_test_wifi_client; + PubSubClient connection_test_client(connection_test_wifi_client); + connection_test_wifi_client.setInsecure(); + connection_test_client.setServer(config->klipper_host, 8883); + char buff[10] = {0}; + sprintf(buff, "%d", config->klipper_port); + if (!connection_test_client.connect("id", "bblp", buff)) + { + LOG_LN(("Bambu: Wrong IP or LAN code.")); + return BambuConnectionStatus::BambuConnectFail; + } + + char auth[48] = {0}; + sprintf(auth, "device/%s/report", config->klipper_auth); + + if (!connection_test_client.subscribe(auth)) + { + LOG_LN(("Bambu: Wrong serial number.")); + return BambuConnectionStatus::BambuConnectSNFail; + } + + delay(100); + connection_test_client.loop(); + + if (!connection_test_client.connected()) + { + LOG_LN(("Bambu: Connection lost. Likely wrong serial number.")); + return BambuConnectionStatus::BambuConnectSNFail; + } + + connection_test_client.disconnect(); + LOG_LN("Bambu: Connection test successful!"); + return BambuConnectionStatus::BambuConnectOk; +} \ No newline at end of file diff --git a/CYD-Klipper/src/core/bambu/bambu_printer_integration.hpp b/CYD-Klipper/src/core/bambu/bambu_printer_integration.hpp new file mode 100644 index 0000000..924a784 --- /dev/null +++ b/CYD-Klipper/src/core/bambu/bambu_printer_integration.hpp @@ -0,0 +1,78 @@ +#pragma once + +#include "../printer_integration.hpp" +#include + +class BambuPrinter : public BasePrinter +{ + private: + unsigned int last_error = 0; + unsigned int ignore_error = 0; + bool publish_mqtt_command(const char* command); + unsigned char speed_profile = 2; + unsigned long print_start; + + union { + struct { + bool chamber_light_available : 1; + bool chamber_light_on : 1; + bool work_light_available : 1; + bool work_light_on : 1; + }; + unsigned char bambu_misc; + }; + + protected: + void parse_state(JsonDocument& in); + + public: + BambuPrinter(int index) : BasePrinter(index) + { + supported_features = PrinterFeatureHome + | PrinterFeatureDisableSteppers + | PrinterFeaturePause + | PrinterFeatureResume + | PrinterFeatureStop + | PrinterFeatureEmergencyStop + | PrinterFeatureCooldown + | PrinterFeatureContinueError + | PrinterFeatureExtrude + | PrinterFeatureRetract + | PrinterFeatureIgnoreError + | PrinterFeatureRetryError; + + supported_temperature_devices = PrinterTemperatureDeviceBed + | PrinterTemperatureDeviceNozzle1; + + popup_message_timeout_s = -1; + bambu_misc = 0; + printer_data.error_screen_features = PrinterFeatureRetryError | PrinterFeatureIgnoreError | PrinterFeatureContinueError; + } + + bool move_printer(const char* axis, float amount, bool relative); + bool execute_feature(PrinterFeatures feature); + bool connect(); + bool fetch(); + PrinterDataMinimal fetch_min(); + void disconnect(); + Macros get_macros(); + int get_macros_count(); + bool execute_macro(const char* macro); + PowerDevices get_power_devices(); + int get_power_devices_count(); + bool set_power_device_state(const char* device_name, bool state); + Files get_files(); + bool start_file(const char* filename); + Thumbnail get_32_32_png_image_thumbnail(const char* gcode_filename); + bool set_target_temperature(PrinterTemperatureDevice device, unsigned int temperature); + bool send_gcode(const char* gcode, bool wait = true); + void receive_data(unsigned char* data, unsigned int length); +}; + +enum BambuConnectionStatus { + BambuConnectFail = 0, + BambuConnectOk = 1, + BambuConnectSNFail = 2, +}; + +BambuConnectionStatus connection_test_bambu(PrinterConfiguration* config); \ No newline at end of file diff --git a/CYD-Klipper/src/core/bambu/bambu_printer_parsers.cpp b/CYD-Klipper/src/core/bambu/bambu_printer_parsers.cpp new file mode 100644 index 0000000..01528cc --- /dev/null +++ b/CYD-Klipper/src/core/bambu/bambu_printer_parsers.cpp @@ -0,0 +1,207 @@ +#include "bambu_printer_integration.hpp" +#include + +#define BIT_X_AXIS_HOMED BIT(0) +#define BIT_Y_AXIS_HOMED BIT(1) +#define BIT_Z_AXIS_HOMED BIT(2) + +void BambuPrinter::parse_state(JsonDocument& in) +{ + if (!in.containsKey("print")) + { + return; + } + + auto print = in["print"]; + + if (print.containsKey("print_error")) + { + unsigned int error = print["print_error"].as(); + if (error != last_error) + { + last_error = error; + + if (error > 0) + { + HTTPClient client; + client.setTimeout(1000); + client.setConnectTimeout(1000); + + LOG_F(("Free heap: %d bytes\n", esp_get_free_heap_size())) + + char buff[10] = {0}; + sprintf(buff, "%X_%X", error >> 16, error & 0xFFFF); + int http_status_code = 0; + + try + { + client.begin("http://bambu.suchmeme.nl/" + String(buff)); + LOG_F(("Sending request to http://bambu.suchmeme.nl/%s", buff)); + http_status_code = client.GET(); + LOG_F(("Response: %d", http_status_code)); + } + catch (...) + { + LOG_LN("Error downloading error code page"); + } + + if (http_status_code == 200) + { + printer_data.state_message = (char *)malloc(client.getSize() + 20); + sprintf(printer_data.state_message, "%s: %s", buff, client.getString().c_str()); + } + else + { + printer_data.state_message = (char *)malloc(20); + sprintf(printer_data.state_message, "Error: %s", buff); + } + } + } + } + + if (print.containsKey("nozzle_temper")) + { + printer_data.temperatures[PrinterTemperatureDeviceIndexNozzle1] = print["nozzle_temper"]; + printer_data.can_extrude = printer_data.temperatures[PrinterTemperatureDeviceIndexNozzle1] > 175; + } + + if (print.containsKey("nozzle_target_temper")) + { + printer_data.target_temperatures[PrinterTemperatureDeviceIndexNozzle1] = print["nozzle_target_temper"]; + } + + if (print.containsKey("bed_temper")) + { + printer_data.temperatures[PrinterTemperatureDeviceIndexBed] = print["bed_temper"]; + } + + if (print.containsKey("bed_target_temper")) + { + printer_data.target_temperatures[PrinterTemperatureDeviceIndexBed] = print["bed_target_temper"]; + } + + if (print.containsKey("spd_lvl")) + { + speed_profile = print["spd_lvl"]; + + switch (speed_profile) + { + case 1: + printer_data.speed_mult = 0.5f; + break; + case 2: + printer_data.speed_mult = 1.0f; + break; + case 3: + printer_data.speed_mult = 1.24f; + break; + case 4: + printer_data.speed_mult = 1.66f; + } + } + + if (print.containsKey("home_flag")) + { + unsigned int home_flag = print["home_flag"].as(); + printer_data.homed_axis = (home_flag & (BIT_X_AXIS_HOMED | BIT_Y_AXIS_HOMED | BIT_Z_AXIS_HOMED)) == (BIT_X_AXIS_HOMED | BIT_Y_AXIS_HOMED | BIT_Z_AXIS_HOMED); + } + + if (last_error > 0 && last_error != ignore_error) + { + printer_data.state = PrinterState::PrinterStateError; + } + else if (print.containsKey("gcode_state")) + { + const char* state = print["gcode_state"]; + + if (strcasecmp(state, "pause") == 0) + { + printer_data.state = PrinterState::PrinterStatePaused; + } + else if (strcasecmp(state, "running") == 0 || strcasecmp(state, "prepare") == 0) + { + if (print_start <= 0) + { + print_start = millis(); + } + + printer_data.state = PrinterState::PrinterStatePrinting; + } + else + { + print_start = 0; + printer_data.state = PrinterState::PrinterStateIdle; + } + } + + + + if (printer_data.state == PrinterState::PrinterStatePrinting) + { + printer_data.elapsed_time_s = (millis() - print_start) / 1000; + } + + if (print.containsKey("mc_remaining_time")) + { + printer_data.remaining_time_s = print["mc_remaining_time"]; + printer_data.remaining_time_s *= 60; + } + + if (print.containsKey("mc_percent")) + { + printer_data.print_progress = print["mc_percent"]; + printer_data.print_progress /= 100; + } + + if (print.containsKey("layer_num")) + { + printer_data.current_layer = print["layer_num"]; + } + + if (print.containsKey("total_layer_num")) + { + printer_data.total_layers = print["total_layer_num"]; + } + + if (print.containsKey("lights_report")) + { + for (auto lights : print["lights_report"].as()) + { + if (lights.containsKey("node") && lights.containsKey("mode")) + { + bool mode = !(lights["mode"] == "off"); + const char* node = lights["node"]; + + if (node == NULL) + { + continue; + } + + if (strcmp(node, "chamber_light") == 0) + { + chamber_light_available = true; + chamber_light_on = mode; + } + else if (strcmp(node, "work_light") == 0) + { + work_light_available = true; + work_light_on = mode; + } + } + } + } + + if (print.containsKey("gcode_file")) + { + const char* filename = print["gcode_file"]; + + if (filename != NULL && (printer_data.print_filename == NULL || strcmp(printer_data.print_filename, filename))) + { + printer_data.print_filename = (char *)malloc(strlen(filename) + 1); + strcpy(printer_data.print_filename, filename); + } + } + + printer_data.extrude_mult = 1; +} + diff --git a/CYD-Klipper/src/core/data_setup.cpp b/CYD-Klipper/src/core/data_setup.cpp index 4cdb4d6..0e948e9 100644 --- a/CYD-Klipper/src/core/data_setup.cpp +++ b/CYD-Klipper/src/core/data_setup.cpp @@ -4,6 +4,7 @@ #include #include "printer_integration.hpp" #include "klipper/klipper_printer_integration.hpp" +#include "bambu/bambu_printer_integration.hpp" SemaphoreHandle_t freezeRenderThreadSemaphore, freezeRequestThreadSemaphore; const long data_update_interval = 780; @@ -112,6 +113,8 @@ void data_setup() { case PrinterType::PrinterTypeKlipper: available_printers[count++] = new KlipperPrinter(i); + case PrinterType::PrinterTypeBambuLocal: + available_printers[count++] = new BambuPrinter(i); } } } diff --git a/CYD-Klipper/src/core/klipper/klipper_printer_integration.cpp b/CYD-Klipper/src/core/klipper/klipper_printer_integration.cpp index 9b91c34..c7acac9 100644 --- a/CYD-Klipper/src/core/klipper/klipper_printer_integration.cpp +++ b/CYD-Klipper/src/core/klipper/klipper_printer_integration.cpp @@ -105,8 +105,6 @@ bool KlipperPrinter::send_emergency_stop() bool KlipperPrinter::execute_feature(PrinterFeatures feature) { - HTTPClient client; - switch (feature) { case PrinterFeatureRestart: @@ -168,7 +166,7 @@ bool KlipperPrinter::execute_feature(PrinterFeatures feature) bool KlipperPrinter::connect() { - return connection_test_klipper(printer_config) == ConnectionStatus::ConnectOk; + return connection_test_klipper(printer_config) == KlipperConnectionStatus::ConnectOk; } bool KlipperPrinter::fetch() @@ -486,7 +484,7 @@ Thumbnail KlipperPrinter::get_32_32_png_image_thumbnail(const char* gcode_filena return thumbnail; } -ConnectionStatus connection_test_klipper(PrinterConfiguration* config) +KlipperConnectionStatus connection_test_klipper(PrinterConfiguration* config) { HTTPClient client; @@ -504,13 +502,13 @@ ConnectionStatus connection_test_klipper(PrinterConfiguration* config) if (http_code == 403) { - return ConnectionStatus::ConnectAuthRequired; + return KlipperConnectionStatus::ConnectAuthRequired; } - return http_code == 200 ? ConnectionStatus::ConnectOk : ConnectionStatus::ConnectFail; + return http_code == 200 ? KlipperConnectionStatus::ConnectOk : KlipperConnectionStatus::ConnectFail; } catch (...) { LOG_LN("Failed to connect"); - return ConnectionStatus::ConnectFail; + return KlipperConnectionStatus::ConnectFail; } } \ No newline at end of file diff --git a/CYD-Klipper/src/core/klipper/klipper_printer_integration.hpp b/CYD-Klipper/src/core/klipper/klipper_printer_integration.hpp index 758c9ba..9187280 100644 --- a/CYD-Klipper/src/core/klipper/klipper_printer_integration.hpp +++ b/CYD-Klipper/src/core/klipper/klipper_printer_integration.hpp @@ -55,6 +55,7 @@ class KlipperPrinter : public BasePrinter | PrinterTemperatureDeviceNozzle1; init_ui_panels(); + printer_data.error_screen_features = PrinterFeatureRestart | PrinterFeatureFirmwareRestart; } bool move_printer(const char* axis, float amount, bool relative); @@ -76,10 +77,10 @@ class KlipperPrinter : public BasePrinter bool send_gcode(const char* gcode, bool wait = true); }; -enum ConnectionStatus { +enum KlipperConnectionStatus { ConnectFail = 0, ConnectOk = 1, ConnectAuthRequired = 2, }; -ConnectionStatus connection_test_klipper(PrinterConfiguration* config); \ No newline at end of file +KlipperConnectionStatus connection_test_klipper(PrinterConfiguration* config); \ No newline at end of file diff --git a/CYD-Klipper/src/core/printer_integration.cpp b/CYD-Klipper/src/core/printer_integration.cpp index 8b9565f..05d1460 100644 --- a/CYD-Klipper/src/core/printer_integration.cpp +++ b/CYD-Klipper/src/core/printer_integration.cpp @@ -5,6 +5,7 @@ static char blank[] = { '\0' }; static unsigned char current_printer_index = 0; +static unsigned char last_announced_printer_index = 0; static unsigned char total_printers; static BasePrinter** registered_printers; static PrinterDataMinimal* minimal_data_copy; @@ -24,7 +25,9 @@ PrinterData* BasePrinter::AnnouncePrinterData() char* old_print_filename = printer_data_copy->print_filename; char* old_popup_message = printer_data_copy->popup_message; PrinterState old_state = printer_data_copy->state; + bool no_free = current_printer_index != last_announced_printer_index; + last_announced_printer_index = current_printer_index; memcpy(printer_data_copy, &printer_data, sizeof(PrinterData)); if (printer_data_copy->state_message == NULL) @@ -42,13 +45,13 @@ PrinterData* BasePrinter::AnnouncePrinterData() printer_data_copy->popup_message = blank; } - if (old_state_message != printer_data_copy->state_message && old_state_message != NULL && old_state_message != blank) + if (old_state_message != printer_data_copy->state_message && old_state_message != NULL && old_state_message != blank && !no_free) { LOG_F(("Freeing state message '%s' (%x)\n", old_state_message, old_state_message)); free(old_state_message); } - if (old_print_filename != printer_data_copy->print_filename && old_print_filename != NULL && old_print_filename != blank) + if (old_print_filename != printer_data_copy->print_filename && old_print_filename != NULL && old_print_filename != blank && !no_free) { LOG_F(("Freeing print filename '%s' (%x)\n", old_print_filename, old_print_filename)); free(old_print_filename); @@ -59,7 +62,7 @@ PrinterData* BasePrinter::AnnouncePrinterData() lv_msg_send(DATA_PRINTER_STATE, get_current_printer()); } - if (old_popup_message != printer_data_copy->popup_message && old_popup_message != NULL && old_popup_message != blank) + if (old_popup_message != printer_data_copy->popup_message && old_popup_message != NULL && old_popup_message != blank && !no_free) { LOG_F(("Freeing popup message '%s' (%x)\n", old_popup_message, old_popup_message)); free(old_popup_message); diff --git a/CYD-Klipper/src/core/printer_integration.hpp b/CYD-Klipper/src/core/printer_integration.hpp index 2e6b3cb..f90af31 100644 --- a/CYD-Klipper/src/core/printer_integration.hpp +++ b/CYD-Klipper/src/core/printer_integration.hpp @@ -13,9 +13,10 @@ enum PrinterFeatures { PrinterFeatureEmergencyStop = BIT(7), PrinterFeatureExtrude = BIT(8), PrinterFeatureRetract = BIT(9), - PrinterFeatureLoadFilament = BIT(10), - PrinterFeatureUnloadFilament = BIT(11), + PrinterFeatureIgnoreError = BIT(10), + PrinterFeatureContinueError = BIT(11), PrinterFeatureCooldown = BIT(12), + PrinterFeatureRetryError = BIT(13), }; inline PrinterFeatures operator|(PrinterFeatures a, PrinterFeatures b) @@ -78,7 +79,6 @@ typedef struct _PrinterData { char* popup_message; float temperatures[10]; float target_temperatures[10]; - PrinterTemperatureDevice AvailableDevices; float position[3]; float elapsed_time_s; float printed_time_s; @@ -94,6 +94,7 @@ typedef struct _PrinterData { float pressure_advance; float smooth_time; int feedrate_mm_per_s; + PrinterFeatures error_screen_features; } PrinterData; typedef struct { @@ -140,6 +141,8 @@ class BasePrinter PrinterData printer_data{}; public: + short popup_message_timeout_s = 10; + PrinterConfiguration* printer_config{}; PrinterFeatures supported_features{}; PrinterTemperatureDevice supported_temperature_devices{}; diff --git a/CYD-Klipper/src/ui/ip_setup.cpp b/CYD-Klipper/src/ui/ip_setup.cpp index e6990e3..0f2c27d 100644 --- a/CYD-Klipper/src/ui/ip_setup.cpp +++ b/CYD-Klipper/src/ui/ip_setup.cpp @@ -5,18 +5,17 @@ #include "core/data_setup.h" #include "ui_utils.h" #include "panels/panel.h" -#include "switch_printer.h" #include "macros.h" #include "../core/lv_setup.h" #include "serial/serial_console.h" #include "../core/klipper/klipper_printer_integration.hpp" - -lv_obj_t * hostEntry; -lv_obj_t * portEntry; -lv_obj_t * label = NULL; +#include "../core/bambu/bambu_printer_integration.hpp" +#include "../core/screen_driver.h" void show_ip_entry(); -void show_auth_entry(); +void choose_printer_type(); + +lv_obj_t * main_label; /* Create a custom keyboard to allow hostnames or ip addresses (a-z, 0 - 9, and -) */ static const char * kb_map[] = { @@ -34,10 +33,10 @@ static const lv_btnmatrix_ctrl_t kb_ctrl[] = { }; static const char * hex_numpad_map[] = { - "1", "2", "3", "f", LV_SYMBOL_BACKSPACE, "\n", - "4", "5", "6", "e", LV_SYMBOL_OK, "\n", - "7", "8", "9", "d", LV_SYMBOL_LEFT, "\n", - "0", "a", "b", "c", LV_SYMBOL_RIGHT, NULL + "1", "2", "3", "F", LV_SYMBOL_BACKSPACE, "\n", + "4", "5", "6", "E", LV_SYMBOL_OK, "\n", + "7", "8", "9", "D", LV_SYMBOL_LEFT, "\n", + "0", "A", "B", "C", LV_SYMBOL_RIGHT, NULL }; static const lv_btnmatrix_ctrl_t hex_numpad_ctrl[] = { @@ -47,6 +46,87 @@ static const lv_btnmatrix_ctrl_t hex_numpad_ctrl[] = { 1, 1, 1, 1, LV_KEYBOARD_CTRL_BTN_FLAGS | 1, }; +static void btn_switch_printer(lv_event_t *e){ + lv_obj_t *btn = lv_event_get_target(e); + PrinterConfiguration * config = (PrinterConfiguration*)lv_event_get_user_data(e); + int index = config - global_config.printer_config; + + global_config_set_printer(index); + set_color_scheme(); + set_invert_display(); + lv_obj_del(lv_obj_get_parent(lv_obj_get_parent(btn))); +} + +void switch_printer_init() { + lv_obj_t * parent = lv_create_empty_panel(lv_scr_act()); + lv_obj_set_style_bg_opa(parent, LV_OPA_100, 0); + lv_obj_align(parent, LV_ALIGN_TOP_RIGHT, 0, 0); + lv_obj_set_size(parent, CYD_SCREEN_WIDTH_PX, CYD_SCREEN_HEIGHT_PX); + lv_layout_flex_column(parent); + + lv_obj_set_size(lv_create_empty_panel(parent), 0, 0); + + auto width = CYD_SCREEN_WIDTH_PX - CYD_SCREEN_GAP_PX * 2; + + lv_obj_t * btn = lv_btn_create(parent); + lv_obj_set_size(btn, width, CYD_SCREEN_MIN_BUTTON_HEIGHT_PX); + lv_obj_add_event_cb(btn, destroy_event_user_data, LV_EVENT_CLICKED, parent); + + lv_obj_t * label = lv_label_create(btn); + lv_label_set_text(label, LV_SYMBOL_CLOSE " Close"); + lv_obj_center(label); + + for (int i = 0; i < PRINTER_CONFIG_COUNT; i++){ + PrinterConfiguration * config = &global_config.printer_config[i]; + const char* printer_name = (config->printer_name[0] == 0) ? config->klipper_host : config->printer_name; + + if (i == global_config.printer_index && config->setup_complete) + { + lv_create_custom_menu_label(printer_name, parent, "Active"); + continue; + } + + if (config->setup_complete) { + lv_create_custom_menu_button(printer_name, parent, btn_switch_printer, "Switch", config); + } + } +} + +static void show_switch_printer_screen(lv_event_t * e){ + switch_printer_init(); +} + +static void host_update(lv_event_t * e) +{ + lv_obj_t * ta = lv_event_get_target(e); + const char* text = lv_textarea_get_text(ta); + strcpy(global_config.printer_config[global_config.printer_index].klipper_host, text); + global_config.printer_config[global_config.printer_index].ip_configured = text[0] != '\0'; +} + +static void port_update(lv_event_t * e) +{ + lv_obj_t * ta = lv_event_get_target(e); + const char* text = lv_textarea_get_text(ta); + if (text[0] != '\0') + { + global_config.printer_config[global_config.printer_index].klipper_port = atoi(text); + } +} + +static void auth_update(lv_event_t * e) +{ + lv_obj_t * ta = lv_event_get_target(e); + const char* text = lv_textarea_get_text(ta); + strcpy(global_config.printer_config[global_config.printer_index].klipper_auth, text); + global_config.printer_config[global_config.printer_index].auth_configured = text[0] != '\0'; +} + +static void return_to_choose_printer_type(lv_event_t * e) +{ + choose_printer_type(); +} + static void keyboard_event_ip_entry(lv_event_t * e) { lv_event_code_t code = lv_event_get_code(e); lv_obj_t * ta = lv_event_get_target(e); @@ -60,6 +140,10 @@ static void keyboard_event_ip_entry(lv_event_t * e) { { lv_keyboard_set_mode(kb, LV_KEYBOARD_MODE_USER_1); } + else if (lv_obj_has_flag(ta, LV_OBJ_FLAG_USER_2)) + { + lv_keyboard_set_mode(kb, LV_KEYBOARD_MODE_USER_2); + } else { lv_keyboard_set_mode(kb, LV_KEYBOARD_MODE_NUMBER); @@ -76,168 +160,243 @@ static void keyboard_event_ip_entry(lv_event_t * e) { } else if (code == LV_EVENT_READY) { - strcpy(global_config.printer_config[global_config.printer_index].klipper_host, lv_textarea_get_text(hostEntry)); - global_config.printer_config[global_config.printer_index].klipper_port = atoi(lv_textarea_get_text(portEntry)); + PrinterType type = global_config.printer_config[global_config.printer_index].printer_type; - ConnectionStatus status = connection_test_klipper(&global_config.printer_config[global_config.printer_index]); - if (status == ConnectionStatus::ConnectOk) - { - global_config.printer_config[global_config.printer_index].ip_configured = true; - global_config.printer_config[global_config.printer_index].setup_complete = true; - write_global_config(); - } - else if (status == ConnectionStatus::ConnectAuthRequired) + if (type == PrinterType::PrinterTypeKlipper) { - show_auth_entry(); - } - else - { - lv_label_set_text(label, "Failed to connect"); + KlipperConnectionStatus klipper_status = connection_test_klipper(&global_config.printer_config[global_config.printer_index]); + if (klipper_status == KlipperConnectionStatus::ConnectOk) + { + global_config.printer_config[global_config.printer_index].setup_complete = true; + write_global_config(); + } + else if (klipper_status == KlipperConnectionStatus::ConnectAuthRequired) + { + lv_label_set_text(main_label, "Incorrect authorisation"); + } + else + { + lv_label_set_text(main_label, "Failed to connect"); + } } - } - else - { - return; - } -} - -static void keyboard_event_auth_entry(lv_event_t * e) { - lv_event_code_t code = lv_event_get_code(e); - lv_obj_t * ta = lv_event_get_target(e); - lv_obj_t * kb = (lv_obj_t *)lv_event_get_user_data(e); - - if (code == LV_EVENT_READY) - { - const char * txt = lv_textarea_get_text(ta); - int len = strlen(txt); - if (len > 0) + else if (type == PrinterType::PrinterTypeBambuLocal) { - global_config.printer_config[global_config.printer_index].auth_configured = true; - strcpy(global_config.printer_config[global_config.printer_index].klipper_auth, txt); - - if (connection_test_klipper(&global_config.printer_config[global_config.printer_index]) == ConnectionStatus::ConnectOk) + BambuConnectionStatus bambu_status = connection_test_bambu(&global_config.printer_config[global_config.printer_index]); + if (bambu_status == BambuConnectionStatus::BambuConnectOk) { - global_config.printer_config[global_config.printer_index].ip_configured = true; global_config.printer_config[global_config.printer_index].setup_complete = true; write_global_config(); } - else + else if (bambu_status == BambuConnectionStatus::BambuConnectSNFail) + { + lv_label_set_text(main_label, "Incorrect serial number"); + } + else { - lv_label_set_text(label, "Failed to connect"); + lv_label_set_text(main_label, "Incorrect IP/Access code"); } } } - else if (code == LV_EVENT_CANCEL) + else { - show_ip_entry(); + return; } } -void show_auth_entry() +void show_ip_entry() { - global_config.printer_config[global_config.printer_index].klipper_auth[32] = 0; lv_obj_clean(lv_scr_act()); lv_obj_t * root = lv_create_empty_panel(lv_scr_act()); lv_obj_set_size(root, CYD_SCREEN_WIDTH_PX, CYD_SCREEN_HEIGHT_PX); lv_layout_flex_column(root); + lv_obj_clear_flag(root, LV_OBJ_FLAG_SCROLLABLE); lv_obj_t * top_root = lv_create_empty_panel(root); lv_obj_set_width(top_root, CYD_SCREEN_WIDTH_PX); lv_layout_flex_column(top_root); lv_obj_set_flex_grow(top_root, 1); lv_obj_set_style_pad_all(top_root, CYD_SCREEN_GAP_PX, 0); + lv_obj_clear_flag(top_root, LV_OBJ_FLAG_SCROLLABLE); - label = lv_label_create(top_root); - lv_label_set_text(label, "Enter API Key"); - lv_obj_set_width(label, CYD_SCREEN_WIDTH_PX - CYD_SCREEN_GAP_PX * 2); + lv_obj_t * button_row = lv_create_empty_panel(top_root); + lv_obj_set_size(button_row, CYD_SCREEN_WIDTH_PX - CYD_SCREEN_GAP_PX * 2, LV_SIZE_CONTENT); + lv_layout_flex_row(button_row); - lv_obj_t * keyboard = lv_keyboard_create(root); - lv_obj_t * passEntry = lv_textarea_create(top_root); - lv_textarea_set_max_length(passEntry, 32); - lv_textarea_set_one_line(passEntry, true); + lv_obj_t * button_back = lv_btn_create(button_row); + lv_obj_set_height(button_back, CYD_SCREEN_MIN_BUTTON_HEIGHT_PX / 2); + lv_obj_set_flex_grow(button_back, 1); + lv_obj_add_event_cb(button_back, return_to_choose_printer_type, LV_EVENT_CLICKED, NULL); - if (global_config.printer_config[global_config.printer_index].auth_configured) - lv_textarea_set_text(passEntry, global_config.printer_config[global_config.printer_index].klipper_auth); - else - lv_textarea_set_text(passEntry, ""); - - lv_obj_set_width(passEntry, CYD_SCREEN_WIDTH_PX - CYD_SCREEN_GAP_PX * 2); - lv_obj_add_event_cb(passEntry, keyboard_event_auth_entry, LV_EVENT_ALL, keyboard); - lv_obj_set_flex_grow(passEntry, 1); - lv_keyboard_set_textarea(keyboard, passEntry); - lv_keyboard_set_map(keyboard, LV_KEYBOARD_MODE_USER_2, hex_numpad_map, hex_numpad_ctrl); - lv_keyboard_set_mode(keyboard, LV_KEYBOARD_MODE_USER_2); -} + lv_obj_t * label = lv_label_create(button_back); + lv_label_set_text(label, LV_SYMBOL_LEFT); + lv_obj_center(label); -void show_ip_entry() -{ - lv_obj_clean(lv_scr_act()); + main_label = lv_label_create(button_row); - lv_obj_t * root = lv_create_empty_panel(lv_scr_act()); - lv_obj_set_size(root, CYD_SCREEN_WIDTH_PX, CYD_SCREEN_HEIGHT_PX); - lv_layout_flex_column(root); + if (global_config.multi_printer_mode) + { + lv_obj_t * button_switch_printer = lv_btn_create(button_row); + lv_obj_set_height(button_switch_printer, CYD_SCREEN_MIN_BUTTON_HEIGHT_PX / 2); + lv_obj_set_flex_grow(button_switch_printer, 1); + lv_obj_add_event_cb(button_switch_printer, show_switch_printer_screen, LV_EVENT_CLICKED, NULL); - lv_obj_t * top_root = lv_create_empty_panel(root); - lv_obj_set_width(top_root, CYD_SCREEN_WIDTH_PX); - lv_layout_flex_column(top_root); - lv_obj_set_flex_grow(top_root, 1); - lv_obj_set_style_pad_all(top_root, CYD_SCREEN_GAP_PX, 0); + label = lv_label_create(button_switch_printer); + lv_label_set_text(label, LV_SYMBOL_HOME); + lv_obj_center(label); + } - label = lv_label_create(top_root); - lv_label_set_text(label, "Enter Klipper IP/Hostname and Port"); - lv_obj_set_width(label, CYD_SCREEN_WIDTH_PX - CYD_SCREEN_GAP_PX * 2); + lv_obj_t * ip_row = lv_create_empty_panel(top_root); + lv_obj_set_size(ip_row, CYD_SCREEN_WIDTH_PX - CYD_SCREEN_GAP_PX * 2, LV_SIZE_CONTENT); + lv_layout_flex_row(ip_row); - lv_obj_t * textbow_row = lv_create_empty_panel(top_root); - lv_obj_set_width(textbow_row, CYD_SCREEN_WIDTH_PX - CYD_SCREEN_GAP_PX * 2); - lv_obj_set_flex_grow(textbow_row, 1); - lv_layout_flex_row(textbow_row); + lv_obj_t * host_entry = lv_textarea_create(ip_row); + lv_textarea_set_one_line(host_entry, true); + lv_obj_add_flag(host_entry, LV_OBJ_FLAG_USER_1); + lv_textarea_set_max_length(host_entry, 64); + lv_obj_set_flex_grow(host_entry, 2); - hostEntry = lv_textarea_create(textbow_row); - lv_textarea_set_one_line(hostEntry, true); - lv_obj_add_flag(hostEntry, LV_OBJ_FLAG_USER_1); - lv_textarea_set_max_length(hostEntry, 63); - lv_obj_set_flex_grow(hostEntry, 3); + lv_obj_t * port_entry = lv_textarea_create(ip_row); + lv_textarea_set_one_line(port_entry, true); + lv_obj_set_flex_grow(port_entry, 1); - portEntry = lv_textarea_create(textbow_row); - lv_textarea_set_one_line(portEntry, true); - lv_textarea_set_max_length(portEntry, 5); - - lv_obj_set_flex_grow(portEntry, 1); + lv_obj_t * auth_row = lv_create_empty_panel(top_root); + lv_obj_set_size(auth_row, CYD_SCREEN_WIDTH_PX - CYD_SCREEN_GAP_PX * 2, LV_SIZE_CONTENT); + lv_layout_flex_row(auth_row); + + lv_obj_t * auth_entry = lv_textarea_create(auth_row); + lv_textarea_set_one_line(auth_entry, true); + lv_obj_add_flag(auth_entry, LV_OBJ_FLAG_USER_2); + lv_obj_set_flex_grow(auth_entry, 1); + lv_textarea_set_max_length(auth_entry, 32); if (global_config.printer_config[global_config.printer_index].ip_configured) { - char buff[7] = {0}; + char buff[10] = {0}; sprintf(buff, "%d", global_config.printer_config[global_config.printer_index].klipper_port); - lv_textarea_set_text(hostEntry, global_config.printer_config[global_config.printer_index].klipper_host); - lv_textarea_set_text(portEntry, buff); + lv_textarea_set_text(host_entry, global_config.printer_config[global_config.printer_index].klipper_host); + lv_textarea_set_text(port_entry, buff); } else { - lv_textarea_set_text(hostEntry, ""); - lv_textarea_set_text(portEntry, "80"); + lv_textarea_set_text(host_entry, ""); + + if (global_config.printer_config[global_config.printer_index].printer_type == PrinterType::PrinterTypeBambuLocal) + { + lv_textarea_set_text(port_entry, ""); + global_config.printer_config[global_config.printer_index].klipper_port = 0; + } + else + { + lv_textarea_set_text(port_entry, "80"); + global_config.printer_config[global_config.printer_index].klipper_port = 80; + } + + global_config.printer_config[global_config.printer_index].klipper_host[0] = '\0'; + + } + + if (global_config.printer_config[global_config.printer_index].auth_configured) + { + lv_textarea_set_text(auth_entry, global_config.printer_config[global_config.printer_index].klipper_auth); } + else + { + lv_textarea_set_text(auth_entry, ""); + global_config.printer_config[global_config.printer_index].klipper_auth[0] = '\0'; + } + + lv_obj_add_event_cb(host_entry, host_update, LV_EVENT_VALUE_CHANGED, NULL); + lv_obj_add_event_cb(port_entry, port_update, LV_EVENT_VALUE_CHANGED, NULL); + lv_obj_add_event_cb(auth_entry, auth_update, LV_EVENT_VALUE_CHANGED, NULL); lv_obj_t * keyboard = lv_keyboard_create(root); lv_keyboard_set_map(keyboard, LV_KEYBOARD_MODE_USER_1, kb_map, kb_ctrl); - lv_obj_add_event_cb(hostEntry, keyboard_event_ip_entry, LV_EVENT_ALL, keyboard); - lv_obj_add_event_cb(portEntry, keyboard_event_ip_entry, LV_EVENT_ALL, keyboard); + lv_keyboard_set_map(keyboard, LV_KEYBOARD_MODE_USER_2, hex_numpad_map, hex_numpad_ctrl); + lv_obj_add_event_cb(host_entry, keyboard_event_ip_entry, LV_EVENT_ALL, keyboard); + lv_obj_add_event_cb(port_entry, keyboard_event_ip_entry, LV_EVENT_ALL, keyboard); + lv_obj_add_event_cb(auth_entry, keyboard_event_ip_entry, LV_EVENT_ALL, keyboard); lv_keyboard_set_mode(keyboard, LV_KEYBOARD_MODE_USER_1); - lv_keyboard_set_textarea(keyboard, hostEntry); + lv_keyboard_set_textarea(keyboard, host_entry); - if (global_config.multi_printer_mode) + switch (global_config.printer_config[global_config.printer_index].printer_type) { - lv_obj_t * btn = draw_switch_printer_button(); - lv_obj_set_parent(btn, textbow_row); - lv_obj_align(btn, LV_ALIGN_DEFAULT, 0, 0); + case PrinterType::PrinterTypeKlipper: + lv_label_set_text(main_label, "Klipper Setup"); + lv_textarea_set_max_length(port_entry, 5); + lv_textarea_set_placeholder_text(host_entry, "Klipper host"); + lv_textarea_set_placeholder_text(port_entry, "Port"); + lv_textarea_set_placeholder_text(auth_entry, "Autorisation key (optional)"); + break; + case PrinterType::PrinterTypeBambuLocal: + lv_label_set_text(main_label, "Bambu (Local) Setup"); + lv_obj_set_flex_grow(port_entry, 4); + lv_obj_set_flex_grow(host_entry, 6); + lv_textarea_set_max_length(port_entry, 8); + lv_textarea_set_placeholder_text(host_entry, "Printer IP"); + lv_textarea_set_placeholder_text(port_entry, "Access code"); + lv_textarea_set_placeholder_text(auth_entry, "Printer serial number"); + break; } } +static void printer_type_klipper(lv_event_t * e) +{ + global_config.printer_config[global_config.printer_index].printer_type = PrinterType::PrinterTypeKlipper; + show_ip_entry(); +} + +static void printer_type_bambu_local(lv_event_t * e) +{ + global_config.printer_config[global_config.printer_index].printer_type = PrinterType::PrinterTypeBambuLocal; + show_ip_entry(); +} + +void choose_printer_type() +{ + lv_obj_clean(lv_scr_act()); + global_config.printer_config[global_config.printer_index].ip_configured = false; + global_config.printer_config[global_config.printer_index].auth_configured = false; + + lv_obj_t * root = lv_create_empty_panel(lv_scr_act()); + lv_obj_set_size(root, CYD_SCREEN_WIDTH_PX, CYD_SCREEN_HEIGHT_PX); + lv_layout_flex_column(root); + lv_obj_set_flex_grow(root, 1); + lv_obj_set_style_pad_all(root, CYD_SCREEN_GAP_PX, 0); + lv_obj_clear_flag(root, LV_OBJ_FLAG_SCROLLABLE); + + lv_obj_t * label = lv_label_create(root); + lv_label_set_text(label, "Choose printer type"); + + lv_obj_t * btn = lv_btn_create(root); + lv_obj_set_size(btn, CYD_SCREEN_WIDTH_PX - CYD_SCREEN_GAP_PX * 2, CYD_SCREEN_MIN_BUTTON_HEIGHT_PX); + lv_obj_add_event_cb(btn, printer_type_klipper, LV_EVENT_CLICKED, NULL); + + label = lv_label_create(btn); + lv_label_set_text(label, "Klipper"); + lv_obj_center(label); + + btn = lv_btn_create(root); + lv_obj_set_size(btn, CYD_SCREEN_WIDTH_PX - CYD_SCREEN_GAP_PX * 2, CYD_SCREEN_MIN_BUTTON_HEIGHT_PX); + lv_obj_add_event_cb(btn, printer_type_bambu_local, LV_EVENT_CLICKED, NULL); + + label = lv_label_create(btn); + lv_label_set_text(label, "Bambu (Local)"); + lv_obj_center(label); +} + void ip_init(){ if (!global_config.printer_config[global_config.printer_index].setup_complete) { - show_ip_entry(); + if (global_config.printer_config[global_config.printer_index].printer_type == PrinterType::PrinterTypeNone) + { + choose_printer_type(); + } + else + { + show_ip_entry(); + } } while (!global_config.printer_config[global_config.printer_index].setup_complete) diff --git a/CYD-Klipper/src/ui/main_ui.cpp b/CYD-Klipper/src/ui/main_ui.cpp index c18a300..31c49d7 100644 --- a/CYD-Klipper/src/ui/main_ui.cpp +++ b/CYD-Klipper/src/ui/main_ui.cpp @@ -8,7 +8,6 @@ #include "ui_utils.h" #include "panels/panel.h" #include "../core/lv_setup.h" -#include "switch_printer.h" #include "macros.h" void check_if_screen_needs_to_be_disabled(){ @@ -42,7 +41,7 @@ static void on_state_change(void * s, lv_msg_t * m){ static void on_popup_message(void * s, lv_msg_t * m) { - lv_create_popup_message(get_current_printer_data()->popup_message, 10000); + lv_create_popup_message(get_current_printer_data()->popup_message, get_current_printer()->popup_message_timeout_s * 1000); } void main_ui_setup(){ diff --git a/CYD-Klipper/src/ui/panels/error_panel.cpp b/CYD-Klipper/src/ui/panels/error_panel.cpp index 3641c4d..8272137 100644 --- a/CYD-Klipper/src/ui/panels/error_panel.cpp +++ b/CYD-Klipper/src/ui/panels/error_panel.cpp @@ -11,11 +11,34 @@ static void btn_click_firmware_restart(lv_event_t * e){ get_current_printer()->execute_feature(PrinterFeatureFirmwareRestart); } +static void btn_click_error_ignore(lv_event_t * e){ + get_current_printer()->execute_feature(PrinterFeatureIgnoreError); +} + +static void btn_click_error_continue(lv_event_t * e){ + get_current_printer()->execute_feature(PrinterFeatureContinueError); +} + +static void btn_click_error_retry(lv_event_t * e){ + get_current_printer()->execute_feature(PrinterFeatureRetryError); +} + static void set_state_message_text(lv_event_t * e) { lv_obj_t * label = lv_event_get_target(e); lv_label_set_text(label, get_current_printer_data()->state_message); } +void create_button(const char* label, lv_event_cb_t on_click, lv_obj_t * root){ + lv_obj_t* btn = lv_btn_create(root); + lv_obj_set_flex_grow(btn, 1); + lv_obj_set_height(btn, CYD_SCREEN_MIN_BUTTON_HEIGHT_PX); + lv_obj_add_event_cb(btn, on_click, LV_EVENT_CLICKED, NULL); + + lv_obj_t * label_obj = lv_label_create(btn); + lv_label_set_text(label_obj, label); + lv_obj_center(label_obj); +} + void error_panel_init(lv_obj_t* panel) { lv_layout_flex_column(panel, LV_FLEX_ALIGN_SPACE_BETWEEN); @@ -40,21 +63,28 @@ void error_panel_init(lv_obj_t* panel) lv_obj_set_size(button_row, CYD_SCREEN_PANEL_WIDTH_PX - CYD_SCREEN_GAP_PX * 2, CYD_SCREEN_MIN_BUTTON_HEIGHT_PX); lv_layout_flex_row(button_row); - lv_obj_t * btn = lv_btn_create(button_row); - lv_obj_set_height(btn, CYD_SCREEN_MIN_BUTTON_HEIGHT_PX); - lv_obj_add_event_cb(btn, btn_click_restart, LV_EVENT_CLICKED, NULL); - lv_obj_set_flex_grow(btn, 1); + if (get_current_printer_data()->error_screen_features & PrinterFeatureRestart) + { + create_button("Restart", btn_click_restart, button_row); + } - label = lv_label_create(btn); - lv_label_set_text(label, "Restart"); - lv_obj_center(label); + if (get_current_printer_data()->error_screen_features & PrinterFeatureFirmwareRestart) + { + create_button("FW Restart", btn_click_firmware_restart, button_row); + } - btn = lv_btn_create(button_row); - lv_obj_set_height(btn, CYD_SCREEN_MIN_BUTTON_HEIGHT_PX); - lv_obj_add_event_cb(btn, btn_click_firmware_restart, LV_EVENT_CLICKED, NULL); - lv_obj_set_flex_grow(btn, 1); + if (get_current_printer_data()->error_screen_features & PrinterFeatureIgnoreError) + { + create_button("Ignore", btn_click_error_ignore, button_row); + } + + if (get_current_printer_data()->error_screen_features & PrinterFeatureContinueError) + { + create_button("Continue", btn_click_error_continue, button_row); + } - label = lv_label_create(btn); - lv_label_set_text(label, "FW Restart"); - lv_obj_center(label); + if (get_current_printer_data()->error_screen_features & PrinterFeatureRetryError) + { + create_button("Retry", btn_click_error_retry, button_row); + } } \ No newline at end of file diff --git a/CYD-Klipper/src/ui/panels/printer_panel.cpp b/CYD-Klipper/src/ui/panels/printer_panel.cpp index 71e8778..5e22797 100644 --- a/CYD-Klipper/src/ui/panels/printer_panel.cpp +++ b/CYD-Klipper/src/ui/panels/printer_panel.cpp @@ -5,7 +5,6 @@ #include "../../core/lv_setup.h" #include #include "../nav_buttons.h" -#include "../switch_printer.h" #include "../macros.h" const char * printer_status[] = { diff --git a/CYD-Klipper/src/ui/serial/serial_commands.cpp b/CYD-Klipper/src/ui/serial/serial_commands.cpp index 7771b2d..8dfe71c 100644 --- a/CYD-Klipper/src/ui/serial/serial_commands.cpp +++ b/CYD-Klipper/src/ui/serial/serial_commands.cpp @@ -3,7 +3,6 @@ #include #include #include "../../conf/global_config.h" -#include "../switch_printer.h" #include "../../core/printer_integration.hpp" namespace serial_console { diff --git a/CYD-Klipper/src/ui/switch_printer.cpp b/CYD-Klipper/src/ui/switch_printer.cpp deleted file mode 100644 index be95674..0000000 --- a/CYD-Klipper/src/ui/switch_printer.cpp +++ /dev/null @@ -1,74 +0,0 @@ -#include "switch_printer.h" -#include "../conf/global_config.h" -#include "ui_utils.h" -#include "../core/lv_setup.h" -#include "../core/screen_driver.h" - -static void btn_switch_printer(lv_event_t *e){ - lv_obj_t *btn = lv_event_get_target(e); - PrinterConfiguration * config = (PrinterConfiguration*)lv_event_get_user_data(e); - int index = config - global_config.printer_config; - - global_config_set_printer(index); - set_color_scheme(); - set_invert_display(); - lv_obj_del(lv_obj_get_parent(lv_obj_get_parent(btn))); -} - -void switch_printer_init() { - lv_obj_t * parent = lv_create_empty_panel(lv_scr_act()); - lv_obj_set_style_bg_opa(parent, LV_OPA_100, 0); - lv_obj_align(parent, LV_ALIGN_TOP_RIGHT, 0, 0); - lv_obj_set_size(parent, CYD_SCREEN_WIDTH_PX, CYD_SCREEN_HEIGHT_PX); - lv_layout_flex_column(parent); - - lv_obj_set_size(lv_create_empty_panel(parent), 0, 0); - - auto width = CYD_SCREEN_WIDTH_PX - CYD_SCREEN_GAP_PX * 2; - - lv_obj_t * btn = lv_btn_create(parent); - lv_obj_set_size(btn, width, CYD_SCREEN_MIN_BUTTON_HEIGHT_PX); - lv_obj_add_event_cb(btn, destroy_event_user_data, LV_EVENT_CLICKED, parent); - - lv_obj_t * label = lv_label_create(btn); - lv_label_set_text(label, LV_SYMBOL_CLOSE " Close"); - lv_obj_center(label); - - for (int i = 0; i < PRINTER_CONFIG_COUNT; i++){ - PrinterConfiguration * config = &global_config.printer_config[i]; - const char* printer_name = (config->printer_name[0] == 0) ? config->klipper_host : config->printer_name; - - if (i == global_config.printer_index && config->setup_complete) - { - lv_create_custom_menu_label(printer_name, parent, "Active"); - continue; - } - - if (config->setup_complete) { - lv_create_custom_menu_button(printer_name, parent, btn_switch_printer, "Switch", config); - } - } -} - -static void show_switch_printer_screen(lv_event_t * e){ - switch_printer_init(); -} - -lv_obj_t * draw_switch_printer_button() -{ - if (!global_config.multi_printer_mode) - { - return NULL; - } - - lv_obj_t * btn = lv_btn_create(lv_scr_act()); - lv_obj_set_size(btn, CYD_SCREEN_MIN_BUTTON_WIDTH_PX, CYD_SCREEN_MIN_BUTTON_HEIGHT_PX); - lv_obj_align(btn, LV_ALIGN_TOP_RIGHT, -CYD_SCREEN_GAP_PX, CYD_SCREEN_GAP_PX); - lv_obj_add_event_cb(btn, show_switch_printer_screen, LV_EVENT_CLICKED, NULL); - - lv_obj_t * label = lv_label_create(btn); - lv_label_set_text(label, LV_SYMBOL_HOME); - lv_obj_center(label); - - return btn; -} \ No newline at end of file diff --git a/CYD-Klipper/src/ui/switch_printer.h b/CYD-Klipper/src/ui/switch_printer.h deleted file mode 100644 index 2926047..0000000 --- a/CYD-Klipper/src/ui/switch_printer.h +++ /dev/null @@ -1,5 +0,0 @@ -#pragma once -#include "lvgl.h" - -void switch_printer_init(); -lv_obj_t * draw_switch_printer_button(); \ No newline at end of file diff --git a/CYD-Klipper/src/ui/ui_utils.cpp b/CYD-Klipper/src/ui/ui_utils.cpp index 3fcf4fc..3730fb7 100644 --- a/CYD-Klipper/src/ui/ui_utils.cpp +++ b/CYD-Klipper/src/ui/ui_utils.cpp @@ -269,7 +269,7 @@ void lv_create_popup_message(const char* message, uint16_t timeout_ms) lv_obj_set_size(label, CYD_SCREEN_PANEL_WIDTH_PX - CYD_SCREEN_GAP_PX * 6, LV_SIZE_CONTENT); lv_label_set_long_mode(label, LV_LABEL_LONG_WRAP); - timer = lv_timer_create(timer_callback, timeout_ms, panel); + timer = lv_timer_create(timer_callback, timeout_ms > 0 ? timeout_ms : 0xFFFFFFFF, panel); } lv_obj_t * lv_label_btn_create(lv_obj_t * parent, lv_event_cb_t btn_callback, void* user_data) From 650b055fcd1dd438e5c2448aebe3639f9480b37e Mon Sep 17 00:00:00 2001 From: suchmememanyskill <38142618+suchmememanyskill@users.noreply.github.com> Date: Tue, 29 Oct 2024 18:14:52 +0100 Subject: [PATCH 25/63] Attempt to fix CI --- .github/workflows/compile.yaml | 12 ++++++------ CYD-Klipper/platformio.ini | 1 - CYD-Klipper/src/core/data_setup.cpp | 2 ++ 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/.github/workflows/compile.yaml b/.github/workflows/compile.yaml index d79bf3a..520034d 100644 --- a/.github/workflows/compile.yaml +++ b/.github/workflows/compile.yaml @@ -24,12 +24,12 @@ jobs: with: fetch-depth: 0 - - uses: actions/cache@v3 - with: - path: | - ~/.cache/pip - ~/.platformio/.cache - key: ${{ runner.os }}-pio-cyd-klipper + #- uses: actions/cache@v3 + # with: + # path: | + # ~/.cache/pip + # ~/.platformio/.cache + # key: ${{ runner.os }}-pio-cyd-klipper - uses: actions/setup-python@v4 with: diff --git a/CYD-Klipper/platformio.ini b/CYD-Klipper/platformio.ini index 4d45bf8..8af9310 100644 --- a/CYD-Klipper/platformio.ini +++ b/CYD-Klipper/platformio.ini @@ -17,7 +17,6 @@ lib_deps = https://github.com/suchmememanyskill/esp32-smartdisplay#9c1d737 bblanchon/ArduinoJson@^7.0.0 plageoj/UrlEncode@^1.0.1 - erriez/ErriezCRC32 @ ^1.0.1 knolleary/PubSubClient@^2.8 monitor_filters = esp32_exception_decoder build_flags = diff --git a/CYD-Klipper/src/core/data_setup.cpp b/CYD-Klipper/src/core/data_setup.cpp index 0e948e9..ce768c4 100644 --- a/CYD-Klipper/src/core/data_setup.cpp +++ b/CYD-Klipper/src/core/data_setup.cpp @@ -113,8 +113,10 @@ void data_setup() { case PrinterType::PrinterTypeKlipper: available_printers[count++] = new KlipperPrinter(i); + break; case PrinterType::PrinterTypeBambuLocal: available_printers[count++] = new BambuPrinter(i); + break; } } } From 9a915bedda89beaaee480b2585e49010452c14b0 Mon Sep 17 00:00:00 2001 From: suchmememanyskill <38142618+suchmememanyskill@users.noreply.github.com> Date: Tue, 29 Oct 2024 18:18:57 +0100 Subject: [PATCH 26/63] Explicitly define wifi client --- CYD-Klipper/platformio.ini | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CYD-Klipper/platformio.ini b/CYD-Klipper/platformio.ini index 8af9310..71502cc 100644 --- a/CYD-Klipper/platformio.ini +++ b/CYD-Klipper/platformio.ini @@ -18,6 +18,7 @@ lib_deps = bblanchon/ArduinoJson@^7.0.0 plageoj/UrlEncode@^1.0.1 knolleary/PubSubClient@^2.8 + WiFiClientSecure monitor_filters = esp32_exception_decoder build_flags = -DLV_CONF_PATH="../../../../src/conf/lv_conf.h" @@ -34,6 +35,7 @@ lib_deps = bblanchon/ArduinoJson@^7.0.0 plageoj/UrlEncode@^1.0.1 knolleary/PubSubClient@^2.8 + WiFiClientSecure [env:esp32-3248S035C] board = esp32-3248S035C @@ -45,6 +47,7 @@ lib_deps = bblanchon/ArduinoJson@^7.0.0 plageoj/UrlEncode@^1.0.1 knolleary/PubSubClient@^2.8 + WiFiClientSecure [env:esp32-3248S035C-V] board = esp32-3248S035C-vertical @@ -56,6 +59,7 @@ lib_deps = bblanchon/ArduinoJson@^7.0.0 plageoj/UrlEncode@^1.0.1 knolleary/PubSubClient@^2.8 + WiFiClientSecure [env:esp32-2432S024C-SD] board = esp32-2432S024C-smartdisplay From 205926364c0f5b42a2a5f95ffb8ee6f09a8916e7 Mon Sep 17 00:00:00 2001 From: suchmememanyskill <38142618+suchmememanyskill@users.noreply.github.com> Date: Tue, 29 Oct 2024 18:30:27 +0100 Subject: [PATCH 27/63] A --- CYD-Klipper/platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CYD-Klipper/platformio.ini b/CYD-Klipper/platformio.ini index 71502cc..22a63af 100644 --- a/CYD-Klipper/platformio.ini +++ b/CYD-Klipper/platformio.ini @@ -9,7 +9,7 @@ ; https://docs.platformio.org/page/projectconf.html [env] -platform = https://github.com/platformio/platform-espressif32#v6.4.0 +platform = espressif32@6.4.0 board = esp32dev framework = arduino monitor_speed = 115200 From 1483345e673f63ca7bec9eeb6ac69ae2de784bd7 Mon Sep 17 00:00:00 2001 From: suchmememanyskill <38142618+suchmememanyskill@users.noreply.github.com> Date: Tue, 29 Oct 2024 18:57:35 +0100 Subject: [PATCH 28/63] Test --- CYD-Klipper/src/core/bambu/bambu_printer_integration.cpp | 2 +- CYD-Klipper/src/ui/panels/error_panel.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CYD-Klipper/src/core/bambu/bambu_printer_integration.cpp b/CYD-Klipper/src/core/bambu/bambu_printer_integration.cpp index 511b754..a140988 100644 --- a/CYD-Klipper/src/core/bambu/bambu_printer_integration.cpp +++ b/CYD-Klipper/src/core/bambu/bambu_printer_integration.cpp @@ -1,6 +1,6 @@ #include "bambu_printer_integration.hpp" #include -#include +#include "WifiClientSecure.h" WiFiClientSecure wifi_client; PubSubClient client(wifi_client); diff --git a/CYD-Klipper/src/ui/panels/error_panel.cpp b/CYD-Klipper/src/ui/panels/error_panel.cpp index 8272137..a215f3c 100644 --- a/CYD-Klipper/src/ui/panels/error_panel.cpp +++ b/CYD-Klipper/src/ui/panels/error_panel.cpp @@ -80,7 +80,7 @@ void error_panel_init(lv_obj_t* panel) if (get_current_printer_data()->error_screen_features & PrinterFeatureContinueError) { - create_button("Continue", btn_click_error_continue, button_row); + create_button("Done", btn_click_error_continue, button_row); } if (get_current_printer_data()->error_screen_features & PrinterFeatureRetryError) From 49a1bd6e573de3b1cef7c994ae53700c43a2247d Mon Sep 17 00:00:00 2001 From: suchmememanyskill <38142618+suchmememanyskill@users.noreply.github.com> Date: Tue, 29 Oct 2024 21:05:38 +0100 Subject: [PATCH 29/63] Try windows compilation --- .github/workflows/compile.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/compile.yaml b/.github/workflows/compile.yaml index 520034d..411fc31 100644 --- a/.github/workflows/compile.yaml +++ b/.github/workflows/compile.yaml @@ -17,7 +17,7 @@ on: jobs: build: - runs-on: ubuntu-latest + runs-on: windows-latest steps: - uses: actions/checkout@v3 From f21b480611b67cd7c9f36f815432091f80334af0 Mon Sep 17 00:00:00 2001 From: suchmememanyskill <38142618+suchmememanyskill@users.noreply.github.com> Date: Wed, 30 Oct 2024 01:26:11 +0100 Subject: [PATCH 30/63] Scale numeric input to 75% screen --- CYD-Klipper/src/conf/global_config.cpp | 2 +- CYD-Klipper/src/core/data_setup.cpp | 8 +++++++- CYD-Klipper/src/ui/panels/move_panel.cpp | 8 ++++---- CYD-Klipper/src/ui/ui_utils.cpp | 9 ++++++++- CYD-Klipper/src/ui/ui_utils.h | 2 +- 5 files changed, 21 insertions(+), 8 deletions(-) diff --git a/CYD-Klipper/src/conf/global_config.cpp b/CYD-Klipper/src/conf/global_config.cpp index 56c05b2..2c7ef77 100644 --- a/CYD-Klipper/src/conf/global_config.cpp +++ b/CYD-Klipper/src/conf/global_config.cpp @@ -108,7 +108,7 @@ void global_config_add_new_printer() void global_config_set_printer(int idx) { - if (idx < 0 || idx >= PRINTER_CONFIG_COUNT) + if (idx < 0 || idx >= PRINTER_CONFIG_COUNT || global_config.printer_index == idx) return; global_config.printer_index = idx; diff --git a/CYD-Klipper/src/core/data_setup.cpp b/CYD-Klipper/src/core/data_setup.cpp index ce768c4..a76a40a 100644 --- a/CYD-Klipper/src/core/data_setup.cpp +++ b/CYD-Klipper/src/core/data_setup.cpp @@ -104,11 +104,16 @@ void data_setup() { BasePrinter** available_printers = (BasePrinter**)malloc(sizeof(BasePrinter*) * PRINTER_CONFIG_COUNT); int count = 0; - + int true_current_printer_index = 0; for (int i = 0; i < PRINTER_CONFIG_COUNT; i++) { if (global_config.printer_config[i].setup_complete) { + if (global_config.printer_index == i) + { + true_current_printer_index = count;; + } + switch (global_config.printer_config[i].printer_type) { case PrinterType::PrinterTypeKlipper: @@ -122,6 +127,7 @@ void data_setup() } initialize_printers(available_printers, count); + set_current_printer(true_current_printer_index); semaphore_init(); fetch_printer_data(); freeze_render_thread(); diff --git a/CYD-Klipper/src/ui/panels/move_panel.cpp b/CYD-Klipper/src/ui/panels/move_panel.cpp index 55ffe6e..6952379 100644 --- a/CYD-Klipper/src/ui/panels/move_panel.cpp +++ b/CYD-Klipper/src/ui/panels/move_panel.cpp @@ -97,7 +97,7 @@ static void edit_move_increment(int column, float* idx) } selected_column = column; - lv_create_keyboard_text_entry(keyboard_cb_edit_move_increment, "Set increment", LV_KEYBOARD_MODE_NUMBER, CYD_SCREEN_PANEL_WIDTH_PX / 2, 6); + lv_create_keyboard_text_entry(keyboard_cb_edit_move_increment, "Set increment", LV_KEYBOARD_MODE_NUMBER, LV_PCT(75), 6); } static void x_line_button_press(lv_event_t * e) { @@ -214,15 +214,15 @@ static void z_line_custom_callback(lv_event_t * e) { } static void x_line_custom(lv_event_t * e) { - lv_create_keyboard_text_entry(x_line_custom_callback, "Set X position", LV_KEYBOARD_MODE_NUMBER, CYD_SCREEN_PANEL_WIDTH_PX / 2, 6); + lv_create_keyboard_text_entry(x_line_custom_callback, "Set X position", LV_KEYBOARD_MODE_NUMBER, LV_PCT(75), 6); } static void y_line_custom(lv_event_t * e) { - lv_create_keyboard_text_entry(y_line_custom_callback, "Set Y position", LV_KEYBOARD_MODE_NUMBER, CYD_SCREEN_PANEL_WIDTH_PX / 2, 6); + lv_create_keyboard_text_entry(y_line_custom_callback, "Set Y position", LV_KEYBOARD_MODE_NUMBER, LV_PCT(75), 6); } static void z_line_custom(lv_event_t * e) { - lv_create_keyboard_text_entry(z_line_custom_callback, "Set Z position", LV_KEYBOARD_MODE_NUMBER, CYD_SCREEN_PANEL_WIDTH_PX / 2, 6); + lv_create_keyboard_text_entry(z_line_custom_callback, "Set Z position", LV_KEYBOARD_MODE_NUMBER, LV_PCT(75), 6); } lv_event_cb_t custom_callbacks[] = {x_line_custom, y_line_custom, z_line_custom}; diff --git a/CYD-Klipper/src/ui/ui_utils.cpp b/CYD-Klipper/src/ui/ui_utils.cpp index 3730fb7..0fcccf1 100644 --- a/CYD-Klipper/src/ui/ui_utils.cpp +++ b/CYD-Klipper/src/ui/ui_utils.cpp @@ -118,6 +118,7 @@ void lv_create_keyboard_text_entry(lv_event_cb_t keyboard_callback, const char* lv_obj_set_style_bg_opa(parent, LV_OPA_50, 0); lv_obj_align(parent, LV_ALIGN_TOP_RIGHT, 0, 0); lv_layout_flex_column(parent, LV_FLEX_ALIGN_SPACE_BETWEEN); + lv_obj_clear_flag(parent, LV_OBJ_FLAG_SCROLLABLE); if (contain_in_panel) { @@ -128,7 +129,7 @@ void lv_create_keyboard_text_entry(lv_event_cb_t keyboard_callback, const char* lv_obj_set_size(parent, CYD_SCREEN_WIDTH_PX, CYD_SCREEN_HEIGHT_PX); } - if (title != nullptr) + if (title != nullptr && keyboard_mode != LV_KEYBOARD_MODE_NUMBER) { lv_obj_t * empty_panel = lv_create_empty_panel(parent); lv_obj_set_size(empty_panel, 0, 0); @@ -147,6 +148,12 @@ void lv_create_keyboard_text_entry(lv_event_cb_t keyboard_callback, const char* lv_obj_t * ta = lv_textarea_create(parent); lv_obj_t * keyboard = lv_keyboard_create(parent); + if (keyboard_mode == LV_KEYBOARD_MODE_NUMBER) + { + lv_textarea_set_placeholder_text(ta, title); + lv_obj_set_height(keyboard, LV_PCT(75)); + } + lv_obj_set_width(ta, width); lv_textarea_set_max_length(ta, max_length); lv_textarea_set_one_line(ta, true); diff --git a/CYD-Klipper/src/ui/ui_utils.h b/CYD-Klipper/src/ui/ui_utils.h index 020ba71..1b3ca99 100644 --- a/CYD-Klipper/src/ui/ui_utils.h +++ b/CYD-Klipper/src/ui/ui_utils.h @@ -39,7 +39,7 @@ void lv_layout_flex_row(lv_obj_t* obj, lv_flex_align_t allign = LV_FLEX_ALIGN_ST void lv_create_fullscreen_button_matrix_popup(lv_obj_t * root, lv_event_cb_t title, lv_button_column_t* columns, int column_count); void destroy_event_user_data(lv_event_t * e); void lv_obj_on_destroy_free_data(lv_obj_t * element, const void* ptr); -void lv_create_keyboard_text_entry(lv_event_cb_t keyboard_callback, const char* title = NULL, lv_keyboard_mode_t keyboard_mode = LV_KEYBOARD_MODE_NUMBER, lv_coord_t width = CYD_SCREEN_PANEL_WIDTH_PX / 2, uint8_t max_length = 3, const char* fill_text = "", bool contain_in_panel= true); +void lv_create_keyboard_text_entry(lv_event_cb_t keyboard_callback, const char* title = NULL, lv_keyboard_mode_t keyboard_mode = LV_KEYBOARD_MODE_NUMBER, lv_coord_t width = LV_PCT(75), uint8_t max_length = 3, const char* fill_text = "", bool contain_in_panel= true); void lv_create_custom_menu_entry(const char* label_text, lv_obj_t* object, lv_obj_t* root_panel, bool set_height = true, const char * comment = NULL); void lv_create_custom_menu_button(const char *label_text, lv_obj_t* root_panel, lv_event_cb_t on_click, const char *btn_text, void * user_data = NULL, const char * comment = NULL); void lv_create_custom_menu_switch(const char *label_text, lv_obj_t* root_panel, lv_event_cb_t on_toggle, bool state, void * user_data = NULL, const char * comment = NULL); From 66e3a6765cfc14f818d81f3fc0201bd96735296d Mon Sep 17 00:00:00 2001 From: suchmememanyskill <38142618+suchmememanyskill@users.noreply.github.com> Date: Sat, 2 Nov 2024 14:42:14 +0100 Subject: [PATCH 31/63] Fix time in bambu integration --- .../core/bambu/bambu_printer_integration.hpp | 1 + .../src/core/bambu/bambu_printer_parsers.cpp | 22 ++++++++----------- 2 files changed, 10 insertions(+), 13 deletions(-) diff --git a/CYD-Klipper/src/core/bambu/bambu_printer_integration.hpp b/CYD-Klipper/src/core/bambu/bambu_printer_integration.hpp index 924a784..22a2061 100644 --- a/CYD-Klipper/src/core/bambu/bambu_printer_integration.hpp +++ b/CYD-Klipper/src/core/bambu/bambu_printer_integration.hpp @@ -47,6 +47,7 @@ class BambuPrinter : public BasePrinter popup_message_timeout_s = -1; bambu_misc = 0; printer_data.error_screen_features = PrinterFeatureRetryError | PrinterFeatureIgnoreError | PrinterFeatureContinueError; + print_start = millis(); } bool move_printer(const char* axis, float amount, bool relative); diff --git a/CYD-Klipper/src/core/bambu/bambu_printer_parsers.cpp b/CYD-Klipper/src/core/bambu/bambu_printer_parsers.cpp index 01528cc..86ecbe1 100644 --- a/CYD-Klipper/src/core/bambu/bambu_printer_parsers.cpp +++ b/CYD-Klipper/src/core/bambu/bambu_printer_parsers.cpp @@ -120,31 +120,22 @@ void BambuPrinter::parse_state(JsonDocument& in) } else if (strcasecmp(state, "running") == 0 || strcasecmp(state, "prepare") == 0) { - if (print_start <= 0) - { - print_start = millis(); - } - printer_data.state = PrinterState::PrinterStatePrinting; } else { - print_start = 0; printer_data.state = PrinterState::PrinterStateIdle; } } - - - if (printer_data.state == PrinterState::PrinterStatePrinting) - { - printer_data.elapsed_time_s = (millis() - print_start) / 1000; - } - if (print.containsKey("mc_remaining_time")) { printer_data.remaining_time_s = print["mc_remaining_time"]; printer_data.remaining_time_s *= 60; + if (printer_data.remaining_time_s > 300) + { + print_start = millis() - (printer_data.remaining_time_s / (1 - printer_data.print_progress) * printer_data.print_progress * 1000); + } } if (print.containsKey("mc_percent")) @@ -153,6 +144,11 @@ void BambuPrinter::parse_state(JsonDocument& in) printer_data.print_progress /= 100; } + if (printer_data.state == PrinterState::PrinterStatePrinting) + { + printer_data.elapsed_time_s = (millis() - print_start) / 1000; + } + if (print.containsKey("layer_num")) { printer_data.current_layer = print["layer_num"]; From 0e57aed87c4feb6204f0c9a989c29cabfe3224b5 Mon Sep 17 00:00:00 2001 From: suchmememanyskill <38142618+suchmememanyskill@users.noreply.github.com> Date: Mon, 4 Nov 2024 21:47:02 +0100 Subject: [PATCH 32/63] Add bambu file loading --- .../core/bambu/bambu_printer_integration.cpp | 19 ++- .../core/bambu/bambu_printer_integration.hpp | 2 + .../src/core/bambu/bambu_printer_parsers.cpp | 156 ++++++++++++++++++ CYD-Klipper/src/core/data_setup.cpp | 3 +- .../klipper/klipper_printer_integration.cpp | 2 +- CYD-Klipper/src/main.cpp | 5 + 6 files changed, 177 insertions(+), 10 deletions(-) diff --git a/CYD-Klipper/src/core/bambu/bambu_printer_integration.cpp b/CYD-Klipper/src/core/bambu/bambu_printer_integration.cpp index a140988..7b3ec3b 100644 --- a/CYD-Klipper/src/core/bambu/bambu_printer_integration.cpp +++ b/CYD-Klipper/src/core/bambu/bambu_printer_integration.cpp @@ -1,6 +1,5 @@ #include "bambu_printer_integration.hpp" #include -#include "WifiClientSecure.h" WiFiClientSecure wifi_client; PubSubClient client(wifi_client); @@ -125,7 +124,7 @@ bool BambuPrinter::connect() sprintf(buff, "%d", printer_config->klipper_port); if (!client.connect("id", "bblp", buff)) { - LOG_LN(("Bambu: Wrong IP or LAN code.")); + LOG_LN("Bambu: Wrong IP or LAN code."); return false; } @@ -134,7 +133,7 @@ bool BambuPrinter::connect() if (!client.subscribe(auth)) { - LOG_LN(("Bambu: Wrong serial number.")); + LOG_LN("Bambu: Wrong serial number."); return false; } @@ -143,7 +142,7 @@ bool BambuPrinter::connect() if (!client.connected()) { - LOG_LN(("Bambu: Connection lost. Likely wrong serial number.")); + LOG_LN("Bambu: Connection lost. Likely wrong serial number."); return false; } @@ -291,7 +290,11 @@ bool BambuPrinter::set_power_device_state(const char* device_name, bool state) Files BambuPrinter::get_files() { - Files files = {0}; + PrinterState state = printer_data.state; + disconnect(); + Files files = parse_files(wifi_client, 20); + connect(); + printer_data.state = state; return files; } @@ -343,7 +346,7 @@ BambuConnectionStatus connection_test_bambu(PrinterConfiguration* config) sprintf(buff, "%d", config->klipper_port); if (!connection_test_client.connect("id", "bblp", buff)) { - LOG_LN(("Bambu: Wrong IP or LAN code.")); + LOG_LN("Bambu: Wrong IP or LAN code."); return BambuConnectionStatus::BambuConnectFail; } @@ -352,7 +355,7 @@ BambuConnectionStatus connection_test_bambu(PrinterConfiguration* config) if (!connection_test_client.subscribe(auth)) { - LOG_LN(("Bambu: Wrong serial number.")); + LOG_LN("Bambu: Wrong serial number."); return BambuConnectionStatus::BambuConnectSNFail; } @@ -361,7 +364,7 @@ BambuConnectionStatus connection_test_bambu(PrinterConfiguration* config) if (!connection_test_client.connected()) { - LOG_LN(("Bambu: Connection lost. Likely wrong serial number.")); + LOG_LN("Bambu: Connection lost. Likely wrong serial number."); return BambuConnectionStatus::BambuConnectSNFail; } diff --git a/CYD-Klipper/src/core/bambu/bambu_printer_integration.hpp b/CYD-Klipper/src/core/bambu/bambu_printer_integration.hpp index 22a2061..c878be7 100644 --- a/CYD-Klipper/src/core/bambu/bambu_printer_integration.hpp +++ b/CYD-Klipper/src/core/bambu/bambu_printer_integration.hpp @@ -2,6 +2,7 @@ #include "../printer_integration.hpp" #include +#include class BambuPrinter : public BasePrinter { @@ -24,6 +25,7 @@ class BambuPrinter : public BasePrinter protected: void parse_state(JsonDocument& in); + Files parse_files(WiFiClientSecure& client, int max_files); public: BambuPrinter(int index) : BasePrinter(index) diff --git a/CYD-Klipper/src/core/bambu/bambu_printer_parsers.cpp b/CYD-Klipper/src/core/bambu/bambu_printer_parsers.cpp index 86ecbe1..621cbf1 100644 --- a/CYD-Klipper/src/core/bambu/bambu_printer_parsers.cpp +++ b/CYD-Klipper/src/core/bambu/bambu_printer_parsers.cpp @@ -1,5 +1,6 @@ #include "bambu_printer_integration.hpp" #include +#include #define BIT_X_AXIS_HOMED BIT(0) #define BIT_Y_AXIS_HOMED BIT(1) @@ -201,3 +202,158 @@ void BambuPrinter::parse_state(JsonDocument& in) printer_data.extrude_mult = 1; } +// Derived from https://github.com/ldab/ESP32_FTPClient/blob/master/src/ESP32_FTPClient.cpp +bool wifi_client_response_pass(WiFiClientSecure& client) +{ + unsigned long _m = millis(); + bool first_char = true; + while (!client.available() && millis() < _m + 500) delay(1); + + if(!client.available()) + { + LOG_LN("FTPS: No response from server"); + + return false; + } + + LOG_LN("[FTPS response]"); + bool response = true; + while (client.available()) + { + char byte = client.read(); + + if (first_char && (byte == '4' || byte == '5')) + { + LOG_LN("FTPS: Server returned an error"); + response = false; + } + + first_char = false; + + LOG_F(("%c", byte)); + } + + return response; +} + +bool wifi_client_response_parse(WiFiClientSecure& client, std::list &files, int max_files) +{ + unsigned long _m = millis(); + while (!client.available() && millis() < _m + 500) delay(1); + + if(!client.available()) + { + LOG_LN("FTPS: No response from server"); + return false; + } + + LOG_LN("[FTPS response]"); + char buff[128] = {0}; + int index = 0; + while (client.available()) { + int byte = client.read(); + LOG_F(("%c", byte)); + buff[index] = byte; + + if (byte == '\n' || byte == '\r' || byte <= 0) + { + buff[index] = 0; + if (index > 10) + { + char* file = (char*)malloc(index + 1); + + if (file != NULL) + { + strcpy(file, buff); + files.push_front(file); + + if (files.size() > max_files) + { + auto last_entry = files.back(); + + if (last_entry != NULL) + free(last_entry); + + files.pop_back(); + } + } + else + { + LOG_LN("Failed to allocate memory"); + } + } + + index = 0; + } + else + { + index++; + } + } + + return true; +} + +bool send_command_without_response(WiFiClientSecure& client, const char* command) +{ + client.println(command); + LOG_F(("[FTPS Command] %s\n", command)); + return wifi_client_response_pass(client); +} + +Files BambuPrinter::parse_files(WiFiClientSecure& wifi_client, int max_files) +{ + LOG_F(("Heap space pre-file-parse: %d bytes\n", esp_get_free_heap_size())); + + unsigned long timer_request = millis(); + Files result = {0}; + + if (!wifi_client.connect(printer_config->klipper_host, 990)) + { + LOG_LN("Failed to fetch files: connection failed"); + } + + wifi_client_response_pass(wifi_client); + + char auth_code_buff[16] = {0}; + sprintf(auth_code_buff, "PASS %d", printer_config->klipper_port); + send_command_without_response(wifi_client, "USER bblp"); + wifi_client_response_pass(wifi_client); + send_command_without_response(wifi_client, auth_code_buff); + send_command_without_response(wifi_client, "PASV"); + send_command_without_response(wifi_client, "NLST"); + wifi_client.stop(); + + if (wifi_client.connect(printer_config->klipper_host, 2024)) + { + unsigned long timer_parse = millis(); + std::list files; + wifi_client_response_parse(wifi_client, files, max_files); + result.available_files = (char**)malloc(sizeof(char*) * files.size()); + if (result.available_files == NULL) + { + LOG_LN("Failed to allocate memory"); + + for (auto file : files){ + free(file); + } + + return result; + } + + for (auto file : files){ + result.available_files[result.count++] = file; + } + + result.success = true; + LOG_F(("Heap space post-file-parse: %d bytes\n", esp_get_free_heap_size())) + LOG_F(("Got %d files. Request took %dms, parsing took %dms\n", files.size(), timer_parse - timer_request, millis() - timer_parse)) + } + else + { + LOG_LN("Failed to fetch files: data connection failed"); + } + + wifi_client.stop(); + return result; +} \ No newline at end of file diff --git a/CYD-Klipper/src/core/data_setup.cpp b/CYD-Klipper/src/core/data_setup.cpp index a76a40a..bbf7216 100644 --- a/CYD-Klipper/src/core/data_setup.cpp +++ b/CYD-Klipper/src/core/data_setup.cpp @@ -125,9 +125,10 @@ void data_setup() } } } - + initialize_printers(available_printers, count); set_current_printer(true_current_printer_index); + LOG_F(("Free heap after printer creation: %d bytes\n", esp_get_free_heap_size())); semaphore_init(); fetch_printer_data(); freeze_render_thread(); diff --git a/CYD-Klipper/src/core/klipper/klipper_printer_integration.cpp b/CYD-Klipper/src/core/klipper/klipper_printer_integration.cpp index c7acac9..c4e92b8 100644 --- a/CYD-Klipper/src/core/klipper/klipper_printer_integration.cpp +++ b/CYD-Klipper/src/core/klipper/klipper_printer_integration.cpp @@ -329,7 +329,7 @@ Files KlipperPrinter::get_files() { Files files_result = {0}; HTTPClient client; - LOG_F(("Heap space pre-file-parse: %d bytes\n", esp_get_free_heap_size())) + LOG_F(("Heap space pre-file-parse: %d bytes\n", esp_get_free_heap_size())); std::list files; auto timer_request = millis(); diff --git a/CYD-Klipper/src/main.cpp b/CYD-Klipper/src/main.cpp index a170329..900b24d 100644 --- a/CYD-Klipper/src/main.cpp +++ b/CYD-Klipper/src/main.cpp @@ -18,11 +18,16 @@ void setup() { screen_setup(); lv_setup(); LOG_LN("Screen init done"); + LOG_F(("Free heap: %d bytes\n", esp_get_free_heap_size())); wifi_init(); + LOG_F(("Free heap after wifi setup: %d bytes\n", esp_get_free_heap_size())); ota_init(); + LOG_F(("Free heap after ota setup: %d bytes\n", esp_get_free_heap_size())); ip_init(); + LOG_F(("Free heap after ip setup: %d bytes\n", esp_get_free_heap_size())); data_setup(); + LOG_F(("Free heap after data setup: %d bytes\n", esp_get_free_heap_size())); nav_style_setup(); main_ui_setup(); From d4ce7a71ba7f3fa72d2a464775b0c7233c09921f Mon Sep 17 00:00:00 2001 From: Sims <38142618+suchmememanyskill@users.noreply.github.com> Date: Fri, 8 Nov 2024 18:07:32 +0100 Subject: [PATCH 33/63] Klipper connection over serial --- .../src/core/bambu/bambu_printer_parsers.cpp | 1 + .../serial_klipper_printer_integration.cpp | 235 ++++++++++++++++++ .../serial_klipper_printer_integration.hpp | 23 ++ .../klipper/klipper_printer_integration.cpp | 2 +- .../klipper/klipper_printer_integration.hpp | 31 +-- .../core/klipper/klipper_printer_parsers.cpp | 20 +- 6 files changed, 284 insertions(+), 28 deletions(-) create mode 100644 CYD-Klipper/src/core/klipper-serial/serial_klipper_printer_integration.cpp create mode 100644 CYD-Klipper/src/core/klipper-serial/serial_klipper_printer_integration.hpp diff --git a/CYD-Klipper/src/core/bambu/bambu_printer_parsers.cpp b/CYD-Klipper/src/core/bambu/bambu_printer_parsers.cpp index 621cbf1..3add9df 100644 --- a/CYD-Klipper/src/core/bambu/bambu_printer_parsers.cpp +++ b/CYD-Klipper/src/core/bambu/bambu_printer_parsers.cpp @@ -301,6 +301,7 @@ bool send_command_without_response(WiFiClientSecure& client, const char* command return wifi_client_response_pass(client); } +// TODO: This isn't a 'pure' parser implementation. Remove network calls, only do parsing Files BambuPrinter::parse_files(WiFiClientSecure& wifi_client, int max_files) { LOG_F(("Heap space pre-file-parse: %d bytes\n", esp_get_free_heap_size())); diff --git a/CYD-Klipper/src/core/klipper-serial/serial_klipper_printer_integration.cpp b/CYD-Klipper/src/core/klipper-serial/serial_klipper_printer_integration.cpp new file mode 100644 index 0000000..1543b4e --- /dev/null +++ b/CYD-Klipper/src/core/klipper-serial/serial_klipper_printer_integration.cpp @@ -0,0 +1,235 @@ +#include "serial_klipper_printer_integration.hpp" +#include +#include + +enum HttpRequestType +{ + HttpPost, + HttpGet +}; + +void clear_serial_buffer() +{ + while (Serial.available()) + { + Serial.read(); + }; +} + +// Request: {timeout} {method} {endpoint} +// Response: {status code} {body} +int make_serial_request(JsonDocument &out, int timeout_ms, HttpRequestType requestType, const char* endpoint) +{ + clear_serial_buffer(); + // TODO: Add semaphore here + if (!Serial.availableForWrite()) + { + return -1; + } + + char buff[10]; + sprintf(buff, "%d ", timeout_ms); + + // TODO: Maybe use printf? + Serial.write(buff); + Serial.write(requestType == HttpGet ? "GET" : "POST"); + Serial.write(' '); + Serial.write(endpoint); + Serial.write('\n'); + + if (timeout_ms <= 0) + { + return 200; + } + unsigned long _m = millis(); + while (!Serial.available() && millis() < _m + timeout_ms + 10) delay(1); + + if (!Serial.available()) + { + return -2; + } + + Serial.readBytes(buff, 4); + buff[3] = 0; + + if (buff[0] < '0' || buff[0] > '9') + { + clear_serial_buffer(); + return -3; + } + + int status_code = atoi(buff); + + if (status_code < 200 || status_code >= 300) + { + clear_serial_buffer(); + return -4; + } + + auto result = deserializeJson(out, Serial); + return result == DeserializationError::Ok; +} + +bool make_serial_request_nocontent(HttpRequestType requestType, const char* endpoint) +{ + JsonDocument doc; + make_serial_request(doc, 0, requestType, endpoint); + return true; +} + +bool SerialKlipperPrinter::connect() +{ + return connection_test_serial_klipper(printer_config) == KlipperConnectionStatus::ConnectOk; +} + +bool SerialKlipperPrinter::fetch() +{ + JsonDocument doc; + if (make_serial_request(doc, 1000, HttpGet, "/printer/objects/query?extruder&heater_bed&toolhead&gcode_move&virtual_sdcard&print_stats&webhooks&fan&display_status") == 200) + { + if (printer_data.state == PrinterStateOffline) + { + printer_data.state = PrinterStateError; + } + + klipper_request_consecutive_fail_count = 0; + parse_state(doc); + } + else + { + klipper_request_consecutive_fail_count++; + if (klipper_request_consecutive_fail_count >= 5) + { + printer_data.state = PrinterStateOffline; + return false; + } + } + + return true; +} + +PrinterDataMinimal SerialKlipperPrinter::fetch_min() +{ + JsonDocument doc; + PrinterDataMinimal data = {}; + data.success = false; + + if (!printer_config->setup_complete) + { + data.state = PrinterStateOffline; + return data; + } + + data.success = true; + + if (make_serial_request(doc, 1000, HttpGet, "/printer/objects/query?webhooks&print_stats&virtual_sdcard") == 200) + { + data.state = PrinterState::PrinterStateIdle; + parse_state_min(doc, &data); + doc.clear(); + data.power_devices = get_power_devices_count(); + } + else + { + data.state = PrinterState::PrinterStateOffline; + data.power_devices = get_power_devices_count(); + } + + return data; +} + +Macros SerialKlipperPrinter::get_macros() +{ + Macros macros = {0}; + JsonDocument doc; + if (make_serial_request(doc, 1000, HttpGet, "/printer/gcode/help") == 200) + { + return parse_macros(doc); + } + + return macros; +} + +int SerialKlipperPrinter::get_macros_count() +{ + JsonDocument doc; + if (make_serial_request(doc, 1000, HttpGet, "/printer/gcode/help") == 200) + { + return parse_macros_count(doc); + } + + return 0; +} + +PowerDevices SerialKlipperPrinter::get_power_devices() +{ + PowerDevices power_devices = {0}; + JsonDocument doc; + if (make_serial_request(doc, 1000, HttpGet, "/machine/device_power/devices") == 200) + { + return parse_power_devices(doc); + } + + return power_devices; +} + +int SerialKlipperPrinter::get_power_devices_count() +{ + JsonDocument doc; + if (make_serial_request(doc, 1000, HttpGet, "/machine/device_power/devices") == 200) + { + return parse_power_devices_count(doc); + } + + return 0; +} + +bool SerialKlipperPrinter::set_power_device_state(const char* device_name, bool state) +{ + JsonDocument doc; + String request = "/machine/device_power/device?device=" + urlEncode(device_name) + "&action=" + (state ? "on" : "off"); + return make_serial_request(doc, 1000, HttpPost, request.c_str()); +} + +Files SerialKlipperPrinter::get_files() +{ + // TODO: Stubbed + Files files = {0}; + files.success = false; + return files; +} + +bool SerialKlipperPrinter::start_file(const char* filename) +{ + JsonDocument doc; + String request = "/printer/print/start?filename=" + urlEncode(filename); + return make_serial_request(doc, 1000, HttpPost, request.c_str()); +} + +Thumbnail SerialKlipperPrinter::get_32_32_png_image_thumbnail(const char* gcode_filename) +{ + // TODO: Stubbed + Thumbnail thumbnail = {0}; + thumbnail.success = false; + return thumbnail; +} + +bool SerialKlipperPrinter::send_gcode(const char* gcode, bool wait) +{ + JsonDocument doc; + String request = "/printer/gcode/script?script=" + urlEncode(gcode); + return wait + ? make_serial_request(doc, 5000, HttpGet, request.c_str()) + : make_serial_request_nocontent(HttpGet, request.c_str()); +} + +KlipperConnectionStatus connection_test_serial_klipper(PrinterConfiguration* config) +{ + JsonDocument doc; + if (make_serial_request(doc, 1000, HttpGet, "/printer/info") != 200) + { + return KlipperConnectionStatus::ConnectOk; + } + + return KlipperConnectionStatus::ConnectFail; +} \ No newline at end of file diff --git a/CYD-Klipper/src/core/klipper-serial/serial_klipper_printer_integration.hpp b/CYD-Klipper/src/core/klipper-serial/serial_klipper_printer_integration.hpp new file mode 100644 index 0000000..09e680b --- /dev/null +++ b/CYD-Klipper/src/core/klipper-serial/serial_klipper_printer_integration.hpp @@ -0,0 +1,23 @@ +#include "../klipper/klipper_printer_integration.hpp" + +class SerialKlipperPrinter : public KlipperPrinter +{ + public: + SerialKlipperPrinter(int index) : KlipperPrinter(index) + { + + } + + bool connect(); + bool fetch(); + PrinterDataMinimal fetch_min(); + Macros get_macros(); + int get_macros_count(); + PowerDevices get_power_devices(); + int get_power_devices_count(); + bool set_power_device_state(const char* device_name, bool state); + Files get_files(); + bool start_file(const char* filename); + Thumbnail get_32_32_png_image_thumbnail(const char* gcode_filename); + bool send_gcode(const char* gcode, bool wait = true); +}; \ No newline at end of file diff --git a/CYD-Klipper/src/core/klipper/klipper_printer_integration.cpp b/CYD-Klipper/src/core/klipper/klipper_printer_integration.cpp index c4e92b8..70c71cb 100644 --- a/CYD-Klipper/src/core/klipper/klipper_printer_integration.cpp +++ b/CYD-Klipper/src/core/klipper/klipper_printer_integration.cpp @@ -226,7 +226,7 @@ PrinterDataMinimal KlipperPrinter::fetch_min() JsonDocument doc; deserializeJson(doc, client.getStream()); - return parse_state_min(doc); + parse_state_min(doc, &data); } else { diff --git a/CYD-Klipper/src/core/klipper/klipper_printer_integration.hpp b/CYD-Klipper/src/core/klipper/klipper_printer_integration.hpp index 9187280..9309afd 100644 --- a/CYD-Klipper/src/core/klipper/klipper_printer_integration.hpp +++ b/CYD-Klipper/src/core/klipper/klipper_printer_integration.hpp @@ -13,20 +13,21 @@ typedef struct { class KlipperPrinter : public BasePrinter { private: - unsigned char lock_absolute_relative_mode_swap{}; - unsigned char klipper_request_consecutive_fail_count{}; unsigned int slicer_estimated_print_time_s{}; unsigned int last_slicer_time_query{}; void configure_http_client(HTTPClient &client, String url_part, bool stream, int timeout); protected: + unsigned char lock_absolute_relative_mode_swap{}; + unsigned char klipper_request_consecutive_fail_count{}; + bool send_emergency_stop(); int get_slicer_time_estimate_s(); void init_ui_panels(); int parse_slicer_time_estimate(JsonDocument& in); void parse_state(JsonDocument& in); - PrinterDataMinimal parse_state_min(JsonDocument& in); + void parse_state_min(JsonDocument &in, PrinterDataMinimal* data); Macros parse_macros(JsonDocument &in); int parse_macros_count(JsonDocument &in); PowerDevices parse_power_devices(JsonDocument &in); @@ -60,21 +61,21 @@ class KlipperPrinter : public BasePrinter bool move_printer(const char* axis, float amount, bool relative); bool execute_feature(PrinterFeatures feature); - bool connect(); - bool fetch(); - PrinterDataMinimal fetch_min(); + virtual bool connect(); + virtual bool fetch(); + virtual PrinterDataMinimal fetch_min(); void disconnect(); - Macros get_macros(); - int get_macros_count(); + virtual Macros get_macros(); + virtual int get_macros_count(); bool execute_macro(const char* macro); - PowerDevices get_power_devices(); - int get_power_devices_count(); - bool set_power_device_state(const char* device_name, bool state); - Files get_files(); - bool start_file(const char* filename); - Thumbnail get_32_32_png_image_thumbnail(const char* gcode_filename); + virtual PowerDevices get_power_devices(); + virtual int get_power_devices_count(); + virtual bool set_power_device_state(const char* device_name, bool state); + virtual Files get_files(); + virtual bool start_file(const char* filename); + virtual Thumbnail get_32_32_png_image_thumbnail(const char* gcode_filename); bool set_target_temperature(PrinterTemperatureDevice device, unsigned int temperature); - bool send_gcode(const char* gcode, bool wait = true); + virtual bool send_gcode(const char* gcode, bool wait = true); }; enum KlipperConnectionStatus { diff --git a/CYD-Klipper/src/core/klipper/klipper_printer_parsers.cpp b/CYD-Klipper/src/core/klipper/klipper_printer_parsers.cpp index eab6d02..391cd9f 100644 --- a/CYD-Klipper/src/core/klipper/klipper_printer_parsers.cpp +++ b/CYD-Klipper/src/core/klipper/klipper_printer_parsers.cpp @@ -183,11 +183,9 @@ void KlipperPrinter::parse_state(JsonDocument &in) } } -PrinterDataMinimal KlipperPrinter::parse_state_min(JsonDocument &in) +void KlipperPrinter::parse_state_min(JsonDocument &in, PrinterDataMinimal* data) { auto status = in["result"]["status"]; - PrinterDataMinimal data = {}; - data.success = true; if (status.containsKey("webhooks")) { @@ -195,15 +193,15 @@ PrinterDataMinimal KlipperPrinter::parse_state_min(JsonDocument &in) if (strcmp(state, "shutdown") == 0) { - data.state = PrinterState::PrinterStateError; + data->state = PrinterState::PrinterStateError; } } - if (data.state != PrinterStateError) + if (data->state != PrinterStateError) { if (status.containsKey("virtual_sdcard")) { - data.print_progress = status["virtual_sdcard"]["progress"]; + data->print_progress = status["virtual_sdcard"]["progress"]; } if (status.containsKey("print_stats")) @@ -212,24 +210,22 @@ PrinterDataMinimal KlipperPrinter::parse_state_min(JsonDocument &in) if (state == nullptr) { - data.state = PrinterState::PrinterStateError; + data->state = PrinterState::PrinterStateError; } else if (strcmp(state, "printing") == 0) { - data.state = PrinterState::PrinterStatePrinting; + data->state = PrinterState::PrinterStatePrinting; } else if (strcmp(state, "paused") == 0) { - data.state = PrinterState::PrinterStatePaused; + data->state = PrinterState::PrinterStatePaused; } else if (strcmp(state, "complete") == 0 || strcmp(state, "cancelled") == 0 || strcmp(state, "standby") == 0) { - data.state = PrinterState::PrinterStateIdle; + data->state = PrinterState::PrinterStateIdle; } } } - - return data; } Macros KlipperPrinter::parse_macros(JsonDocument &in) From 747ff4c79ca2c9e8e63a9f06c3e04a6c8adf18e0 Mon Sep 17 00:00:00 2001 From: suchmememanyskill <38142618+suchmememanyskill@users.noreply.github.com> Date: Sat, 9 Nov 2024 00:09:48 +0100 Subject: [PATCH 34/63] More serial --- CYD-Klipper/platformio.ini | 1 + CYD-Klipper/src/core/data_setup.cpp | 4 + .../serial_klipper_printer_integration.cpp | 167 ++++++++++++++---- .../serial_klipper_printer_integration.hpp | 8 +- CYD-Klipper/src/main.cpp | 5 - CYD-Klipper/src/ui/ip_setup.cpp | 54 ++++++ CYD-Klipper/src/ui/panels/files_panel.cpp | 2 +- CYD-Klipper/src/ui/panels/move_panel.cpp | 2 + CYD-Klipper/src/ui/serial/serial_console.cpp | 6 +- CYD-Klipper/src/ui/serial/serial_console.h | 2 + 10 files changed, 202 insertions(+), 49 deletions(-) diff --git a/CYD-Klipper/platformio.ini b/CYD-Klipper/platformio.ini index 22a63af..50bed7f 100644 --- a/CYD-Klipper/platformio.ini +++ b/CYD-Klipper/platformio.ini @@ -13,6 +13,7 @@ platform = espressif32@6.4.0 board = esp32dev framework = arduino monitor_speed = 115200 +debug_build_flags = -Os lib_deps = https://github.com/suchmememanyskill/esp32-smartdisplay#9c1d737 bblanchon/ArduinoJson@^7.0.0 diff --git a/CYD-Klipper/src/core/data_setup.cpp b/CYD-Klipper/src/core/data_setup.cpp index bbf7216..cda1c79 100644 --- a/CYD-Klipper/src/core/data_setup.cpp +++ b/CYD-Klipper/src/core/data_setup.cpp @@ -4,6 +4,7 @@ #include #include "printer_integration.hpp" #include "klipper/klipper_printer_integration.hpp" +#include "klipper-serial/serial_klipper_printer_integration.hpp" #include "bambu/bambu_printer_integration.hpp" SemaphoreHandle_t freezeRenderThreadSemaphore, freezeRequestThreadSemaphore; @@ -122,6 +123,9 @@ void data_setup() case PrinterType::PrinterTypeBambuLocal: available_printers[count++] = new BambuPrinter(i); break; + case PrinterType::PrinterTypeKlipperSerial: + available_printers[count++] = new SerialKlipperPrinter(i); + break; } } } diff --git a/CYD-Klipper/src/core/klipper-serial/serial_klipper_printer_integration.cpp b/CYD-Klipper/src/core/klipper-serial/serial_klipper_printer_integration.cpp index 1543b4e..0e2c181 100644 --- a/CYD-Klipper/src/core/klipper-serial/serial_klipper_printer_integration.cpp +++ b/CYD-Klipper/src/core/klipper-serial/serial_klipper_printer_integration.cpp @@ -1,6 +1,32 @@ #include "serial_klipper_printer_integration.hpp" #include #include +#include "../../ui/serial/serial_console.h" + +bool is_semaphores_initialized = false; +SemaphoreHandle_t freeze_serial_thread_semaphore; + +void semaphore_init_serial() +{ + if (is_semaphores_initialized) + { + return; + } + + freeze_serial_thread_semaphore = xSemaphoreCreateMutex(); + xSemaphoreGive(freeze_serial_thread_semaphore); + is_semaphores_initialized = true; +} + +void freeze_serial_thread() +{ + xSemaphoreTake(freeze_serial_thread_semaphore, portMAX_DELAY); +} + +void unfreeze_serial_thread() +{ + xSemaphoreGive(freeze_serial_thread_semaphore); +} enum HttpRequestType { @@ -18,35 +44,37 @@ void clear_serial_buffer() // Request: {timeout} {method} {endpoint} // Response: {status code} {body} -int make_serial_request(JsonDocument &out, int timeout_ms, HttpRequestType requestType, const char* endpoint) +bool make_serial_request(JsonDocument &out, int timeout_ms, HttpRequestType requestType, const char* endpoint) { + semaphore_init_serial(); + freeze_serial_thread(); + serial_console::global_disable_serial_console = true; + temporary_config.debug = false; + char buff[10]; clear_serial_buffer(); + // TODO: Add semaphore here if (!Serial.availableForWrite()) { - return -1; + unfreeze_serial_thread(); + return false; } - char buff[10]; - sprintf(buff, "%d ", timeout_ms); - - // TODO: Maybe use printf? - Serial.write(buff); - Serial.write(requestType == HttpGet ? "GET" : "POST"); - Serial.write(' '); - Serial.write(endpoint); - Serial.write('\n'); + Serial.printf("HTTP_REQUEST %d %s %s\n", timeout_ms, requestType == HttpGet ? "GET" : "POST", endpoint); if (timeout_ms <= 0) { - return 200; + unfreeze_serial_thread(); + return true; } unsigned long _m = millis(); while (!Serial.available() && millis() < _m + timeout_ms + 10) delay(1); if (!Serial.available()) { - return -2; + Serial.println("Timeout..."); + unfreeze_serial_thread(); + return false; } Serial.readBytes(buff, 4); @@ -54,26 +82,39 @@ int make_serial_request(JsonDocument &out, int timeout_ms, HttpRequestType reque if (buff[0] < '0' || buff[0] > '9') { + Serial.println("Invalid error code"); clear_serial_buffer(); - return -3; + unfreeze_serial_thread(); + return false; } int status_code = atoi(buff); if (status_code < 200 || status_code >= 300) { + Serial.println("Non-200 error code"); clear_serial_buffer(); - return -4; + unfreeze_serial_thread(); + return false; } auto result = deserializeJson(out, Serial); - return result == DeserializationError::Ok; + Serial.printf("Deserialization result: %s\n", result.c_str()); + bool success = result == DeserializationError::Ok; + + if (!success) + { + unfreeze_serial_thread(); + } + + return success; } bool make_serial_request_nocontent(HttpRequestType requestType, const char* endpoint) { JsonDocument doc; make_serial_request(doc, 0, requestType, endpoint); + unfreeze_serial_thread(); return true; } @@ -85,7 +126,7 @@ bool SerialKlipperPrinter::connect() bool SerialKlipperPrinter::fetch() { JsonDocument doc; - if (make_serial_request(doc, 1000, HttpGet, "/printer/objects/query?extruder&heater_bed&toolhead&gcode_move&virtual_sdcard&print_stats&webhooks&fan&display_status") == 200) + if (make_serial_request(doc, 1000, HttpGet, "/printer/objects/query?extruder&heater_bed&toolhead&gcode_move&virtual_sdcard&print_stats&webhooks&fan&display_status")) { if (printer_data.state == PrinterStateOffline) { @@ -94,6 +135,7 @@ bool SerialKlipperPrinter::fetch() klipper_request_consecutive_fail_count = 0; parse_state(doc); + unfreeze_serial_thread(); } else { @@ -122,11 +164,11 @@ PrinterDataMinimal SerialKlipperPrinter::fetch_min() data.success = true; - if (make_serial_request(doc, 1000, HttpGet, "/printer/objects/query?webhooks&print_stats&virtual_sdcard") == 200) + if (make_serial_request(doc, 1000, HttpGet, "/printer/objects/query?webhooks&print_stats&virtual_sdcard")) { data.state = PrinterState::PrinterStateIdle; parse_state_min(doc, &data); - doc.clear(); + unfreeze_serial_thread(); data.power_devices = get_power_devices_count(); } else @@ -142,9 +184,10 @@ Macros SerialKlipperPrinter::get_macros() { Macros macros = {0}; JsonDocument doc; - if (make_serial_request(doc, 1000, HttpGet, "/printer/gcode/help") == 200) + if (make_serial_request(doc, 1000, HttpGet, "/printer/gcode/help")) { - return parse_macros(doc); + macros = parse_macros(doc); + unfreeze_serial_thread(); } return macros; @@ -153,9 +196,11 @@ Macros SerialKlipperPrinter::get_macros() int SerialKlipperPrinter::get_macros_count() { JsonDocument doc; - if (make_serial_request(doc, 1000, HttpGet, "/printer/gcode/help") == 200) + if (make_serial_request(doc, 1000, HttpGet, "/printer/gcode/help")) { - return parse_macros_count(doc); + int count = parse_macros_count(doc); + unfreeze_serial_thread(); + return count; } return 0; @@ -165,9 +210,10 @@ PowerDevices SerialKlipperPrinter::get_power_devices() { PowerDevices power_devices = {0}; JsonDocument doc; - if (make_serial_request(doc, 1000, HttpGet, "/machine/device_power/devices") == 200) + if (make_serial_request(doc, 1000, HttpGet, "/machine/device_power/devices")) { - return parse_power_devices(doc); + power_devices = parse_power_devices(doc); + unfreeze_serial_thread(); } return power_devices; @@ -176,9 +222,11 @@ PowerDevices SerialKlipperPrinter::get_power_devices() int SerialKlipperPrinter::get_power_devices_count() { JsonDocument doc; - if (make_serial_request(doc, 1000, HttpGet, "/machine/device_power/devices") == 200) + if (make_serial_request(doc, 1000, HttpGet, "/machine/device_power/devices")) { - return parse_power_devices_count(doc); + int count = parse_power_devices_count(doc); + unfreeze_serial_thread(); + return count; } return 0; @@ -186,24 +234,58 @@ int SerialKlipperPrinter::get_power_devices_count() bool SerialKlipperPrinter::set_power_device_state(const char* device_name, bool state) { - JsonDocument doc; String request = "/machine/device_power/device?device=" + urlEncode(device_name) + "&action=" + (state ? "on" : "off"); - return make_serial_request(doc, 1000, HttpPost, request.c_str()); + return make_serial_request_nocontent(HttpGet, request.c_str()); } Files SerialKlipperPrinter::get_files() { - // TODO: Stubbed - Files files = {0}; - files.success = false; - return files; + Files files_result = {0}; + files_result.success = false; + JsonDocument doc; + LOG_F(("Heap space pre-file-parse: %d bytes\n", esp_get_free_heap_size())); + std::list files; + + auto timer_request = millis(); + bool result = make_serial_request(doc, 5000, HttpGet, "/server/files/list"); + auto timer_parse = millis(); + + if (!result) + { + return files_result; + } + + parse_file_list(doc, files, 20); + unfreeze_serial_thread(); + + files_result.available_files = (char**)malloc(sizeof(char*) * files.size()); + + if (files_result.available_files == NULL){ + LOG_LN("Failed to allocate memory"); + + for (auto file : files){ + free(file.name); + } + + return files_result; + } + + for (auto file : files){ + files_result.available_files[files_result.count++] = file.name; + } + + files_result.success = true; + + LOG_F(("Heap space post-file-parse: %d bytes\n", esp_get_free_heap_size())) + LOG_F(("Got %d files. Request took %dms, parsing took %dms\n", files.size(), timer_parse - timer_request, millis() - timer_parse)) + return files_result; } bool SerialKlipperPrinter::start_file(const char* filename) { JsonDocument doc; String request = "/printer/print/start?filename=" + urlEncode(filename); - return make_serial_request(doc, 1000, HttpPost, request.c_str()); + return make_serial_request_nocontent(HttpGet, request.c_str());; } Thumbnail SerialKlipperPrinter::get_32_32_png_image_thumbnail(const char* gcode_filename) @@ -218,16 +300,25 @@ bool SerialKlipperPrinter::send_gcode(const char* gcode, bool wait) { JsonDocument doc; String request = "/printer/gcode/script?script=" + urlEncode(gcode); - return wait - ? make_serial_request(doc, 5000, HttpGet, request.c_str()) - : make_serial_request_nocontent(HttpGet, request.c_str()); + + if (!wait) + { + return make_serial_request_nocontent(HttpGet, request.c_str()); + } + + bool result = make_serial_request(doc, 5000, HttpGet, request.c_str()); + unfreeze_serial_thread(); + return result; } KlipperConnectionStatus connection_test_serial_klipper(PrinterConfiguration* config) { + serial_console::global_disable_serial_console = true; + temporary_config.debug = false; JsonDocument doc; - if (make_serial_request(doc, 1000, HttpGet, "/printer/info") != 200) + if (make_serial_request(doc, 1000, HttpGet, "/printer/info")) { + unfreeze_serial_thread(); return KlipperConnectionStatus::ConnectOk; } diff --git a/CYD-Klipper/src/core/klipper-serial/serial_klipper_printer_integration.hpp b/CYD-Klipper/src/core/klipper-serial/serial_klipper_printer_integration.hpp index 09e680b..022de5b 100644 --- a/CYD-Klipper/src/core/klipper-serial/serial_klipper_printer_integration.hpp +++ b/CYD-Klipper/src/core/klipper-serial/serial_klipper_printer_integration.hpp @@ -4,9 +4,7 @@ class SerialKlipperPrinter : public KlipperPrinter { public: SerialKlipperPrinter(int index) : KlipperPrinter(index) - { - - } + {} bool connect(); bool fetch(); @@ -20,4 +18,6 @@ class SerialKlipperPrinter : public KlipperPrinter bool start_file(const char* filename); Thumbnail get_32_32_png_image_thumbnail(const char* gcode_filename); bool send_gcode(const char* gcode, bool wait = true); -}; \ No newline at end of file +}; + +KlipperConnectionStatus connection_test_serial_klipper(PrinterConfiguration* config); \ No newline at end of file diff --git a/CYD-Klipper/src/main.cpp b/CYD-Klipper/src/main.cpp index 900b24d..a170329 100644 --- a/CYD-Klipper/src/main.cpp +++ b/CYD-Klipper/src/main.cpp @@ -18,16 +18,11 @@ void setup() { screen_setup(); lv_setup(); LOG_LN("Screen init done"); - LOG_F(("Free heap: %d bytes\n", esp_get_free_heap_size())); wifi_init(); - LOG_F(("Free heap after wifi setup: %d bytes\n", esp_get_free_heap_size())); ota_init(); - LOG_F(("Free heap after ota setup: %d bytes\n", esp_get_free_heap_size())); ip_init(); - LOG_F(("Free heap after ip setup: %d bytes\n", esp_get_free_heap_size())); data_setup(); - LOG_F(("Free heap after data setup: %d bytes\n", esp_get_free_heap_size())); nav_style_setup(); main_ui_setup(); diff --git a/CYD-Klipper/src/ui/ip_setup.cpp b/CYD-Klipper/src/ui/ip_setup.cpp index 0f2c27d..cdf11eb 100644 --- a/CYD-Klipper/src/ui/ip_setup.cpp +++ b/CYD-Klipper/src/ui/ip_setup.cpp @@ -11,6 +11,7 @@ #include "../core/klipper/klipper_printer_integration.hpp" #include "../core/bambu/bambu_printer_integration.hpp" #include "../core/screen_driver.h" +#include "../core/klipper-serial/serial_klipper_printer_integration.hpp" void show_ip_entry(); void choose_printer_type(); @@ -57,6 +58,26 @@ static void btn_switch_printer(lv_event_t *e){ lv_obj_del(lv_obj_get_parent(lv_obj_get_parent(btn))); } +long last_request = 0; + +void serial_check_connection() +{ + if ((millis() - last_request) < 5000) + { + return; + } + + auto result = connection_test_serial_klipper(&global_config.printer_config[global_config.printer_index]); + last_request = millis(); + + if (result == KlipperConnectionStatus::ConnectOk) + { + global_config.printer_config[global_config.printer_index].setup_complete = true; + strcpy(global_config.printer_config[global_config.printer_index].klipper_host, "Serial"); + write_global_config(); + } +} + void switch_printer_init() { lv_obj_t * parent = lv_create_empty_panel(lv_scr_act()); lv_obj_set_style_bg_opa(parent, LV_OPA_100, 0); @@ -338,6 +359,20 @@ void show_ip_entry() lv_textarea_set_placeholder_text(port_entry, "Access code"); lv_textarea_set_placeholder_text(auth_entry, "Printer serial number"); break; + case PrinterType::PrinterTypeKlipperSerial: + lv_label_set_text(main_label, "Klipper (Serial) Setup"); + lv_obj_del(ip_row); + lv_obj_del(auth_row); + lv_obj_del(keyboard); + + lv_obj_t * bottom_root = lv_create_empty_panel(top_root); + lv_obj_set_width(bottom_root, CYD_SCREEN_WIDTH_PX); + lv_obj_set_flex_grow(bottom_root, 1); + + label = lv_label_create(bottom_root); + lv_obj_center(label); + lv_label_set_text(label, "Connect CYD-Klipper to a host\nrunning the CYD-Klipper server"); + break; } } @@ -353,6 +388,12 @@ static void printer_type_bambu_local(lv_event_t * e) show_ip_entry(); } +static void printer_type_serial_klipper(lv_event_t * e) +{ + global_config.printer_config[global_config.printer_index].printer_type = PrinterType::PrinterTypeKlipperSerial; + show_ip_entry(); +} + void choose_printer_type() { lv_obj_clean(lv_scr_act()); @@ -377,6 +418,14 @@ void choose_printer_type() lv_label_set_text(label, "Klipper"); lv_obj_center(label); + btn = lv_btn_create(root); + lv_obj_set_size(btn, CYD_SCREEN_WIDTH_PX - CYD_SCREEN_GAP_PX * 2, CYD_SCREEN_MIN_BUTTON_HEIGHT_PX); + lv_obj_add_event_cb(btn, printer_type_serial_klipper, LV_EVENT_CLICKED, NULL); + + label = lv_label_create(btn); + lv_label_set_text(label, "Klipper (Serial)"); + lv_obj_center(label); + btn = lv_btn_create(root); lv_obj_set_size(btn, CYD_SCREEN_WIDTH_PX - CYD_SCREEN_GAP_PX * 2, CYD_SCREEN_MIN_BUTTON_HEIGHT_PX); lv_obj_add_event_cb(btn, printer_type_bambu_local, LV_EVENT_CLICKED, NULL); @@ -401,6 +450,11 @@ void ip_init(){ while (!global_config.printer_config[global_config.printer_index].setup_complete) { + if (global_config.printer_config[global_config.printer_index].printer_type == PrinterType::PrinterTypeKlipperSerial) + { + serial_check_connection(); + } + lv_handler(); serial_console::run(); } diff --git a/CYD-Klipper/src/ui/panels/files_panel.cpp b/CYD-Klipper/src/ui/panels/files_panel.cpp index 87aa77e..5c312a4 100644 --- a/CYD-Klipper/src/ui/panels/files_panel.cpp +++ b/CYD-Klipper/src/ui/panels/files_panel.cpp @@ -72,7 +72,7 @@ static void btn_print_file_verify(lv_event_t * e){ lv_img_dsc_t* img_header = (lv_img_dsc_t*)malloc(sizeof(lv_img_dsc_t)); lv_obj_on_destroy_free_data(panel, img_header); - memset(img_header, 0, sizeof(img_header)); + memset(img_header, 0, sizeof(lv_img_dsc_t)); img_header->header.w = 32; img_header->header.h = 32; img_header->data_size = thumbnail.size; diff --git a/CYD-Klipper/src/ui/panels/move_panel.cpp b/CYD-Klipper/src/ui/panels/move_panel.cpp index 6952379..e4d2561 100644 --- a/CYD-Klipper/src/ui/panels/move_panel.cpp +++ b/CYD-Klipper/src/ui/panels/move_panel.cpp @@ -167,7 +167,9 @@ static void home_button_click(lv_event_t * e) { if (get_current_printer_data()->state == PrinterState::PrinterStatePrinting) return; + freeze_request_thread(); get_current_printer()->execute_feature(PrinterFeatures::PrinterFeatureHome); + unfreeze_request_thread(); } static void disable_steppers_click(lv_event_t * e) { diff --git a/CYD-Klipper/src/ui/serial/serial_console.cpp b/CYD-Klipper/src/ui/serial/serial_console.cpp index dc55551..0615cee 100644 --- a/CYD-Klipper/src/ui/serial/serial_console.cpp +++ b/CYD-Klipper/src/ui/serial/serial_console.cpp @@ -8,6 +8,7 @@ namespace serial_console { + bool global_disable_serial_console = false; /* * read_string_until: Non-blocking replacement for Serial.readStringUntil().. @@ -26,7 +27,7 @@ namespace serial_console { --cnt; - // backspace + // backspaceF if (c == 8) { if (index > 0) @@ -131,6 +132,9 @@ namespace serial_console // main "engine": non-blockingly read until newline found, parse, execute. void run() { + if (global_disable_serial_console) + return; + static char cmdline[MAX_COMDLINE_SIZE + 1] = {0}; if (!read_string_until('\n', cmdline, MAX_COMDLINE_SIZE)) return; diff --git a/CYD-Klipper/src/ui/serial/serial_console.h b/CYD-Klipper/src/ui/serial/serial_console.h index 31cd10c..e044c6e 100644 --- a/CYD-Klipper/src/ui/serial/serial_console.h +++ b/CYD-Klipper/src/ui/serial/serial_console.h @@ -5,4 +5,6 @@ namespace serial_console { void greet(); void run(); +extern bool global_disable_serial_console; + } \ No newline at end of file From 92b7b68dc5fa5488922e9c696fe81ad1dcf90108 Mon Sep 17 00:00:00 2001 From: suchmememanyskill <38142618+suchmememanyskill@users.noreply.github.com> Date: Sat, 9 Nov 2024 00:31:03 +0100 Subject: [PATCH 35/63] Get Serial to a functional state --- CYD-Klipper/src/core/current_printer.cpp | 99 ++++++++++++++++++++ CYD-Klipper/src/core/current_printer.h | 15 +++ CYD-Klipper/src/ui/macros.cpp | 5 +- CYD-Klipper/src/ui/panels/error_panel.cpp | 12 +-- CYD-Klipper/src/ui/panels/files_panel.cpp | 13 +-- CYD-Klipper/src/ui/panels/macros_panel.cpp | 1 - CYD-Klipper/src/ui/panels/move_panel.cpp | 15 ++- CYD-Klipper/src/ui/panels/progress_panel.cpp | 9 +- CYD-Klipper/src/ui/panels/temp_panel.cpp | 13 +-- serial.py | 79 ++++++++++++++++ 10 files changed, 226 insertions(+), 35 deletions(-) create mode 100644 CYD-Klipper/src/core/current_printer.cpp create mode 100644 CYD-Klipper/src/core/current_printer.h create mode 100644 serial.py diff --git a/CYD-Klipper/src/core/current_printer.cpp b/CYD-Klipper/src/core/current_printer.cpp new file mode 100644 index 0000000..31f594f --- /dev/null +++ b/CYD-Klipper/src/core/current_printer.cpp @@ -0,0 +1,99 @@ +#include "data_setup.h" +#include "current_printer.h" + +bool current_printer_move_printer(const char* axis, float amount, bool relative) +{ + freeze_request_thread(); + bool result = get_current_printer()->move_printer(axis, amount, relative); + unfreeze_request_thread(); + return result; +} + +bool current_printer_execute_feature(PrinterFeatures feature) +{ + freeze_request_thread(); + bool result = get_current_printer()->execute_feature(feature); + unfreeze_request_thread(); + return result; +} + +Macros current_printer_get_macros() +{ + freeze_request_thread(); + Macros macros = get_current_printer()->get_macros(); + unfreeze_request_thread(); + return macros; +} + +int current_printer_get_macros_count() +{ + freeze_request_thread(); + int count = get_current_printer()->get_macros_count(); + unfreeze_request_thread(); + return count; +} + +bool current_printer_execute_macro(const char* macro) +{ + freeze_request_thread(); + bool result = get_current_printer()->execute_macro(macro); + unfreeze_request_thread(); + return result; +} + +PowerDevices current_printer_get_power_devices() +{ + freeze_request_thread(); + PowerDevices power_devices = get_current_printer()->get_power_devices(); + unfreeze_request_thread(); + return power_devices; +} + +int current_printer_get_power_devices_count() +{ + freeze_request_thread(); + int count = get_current_printer()->get_power_devices_count(); + unfreeze_request_thread(); + return count; +} + +bool current_printer_set_power_device_state(const char* device_name, bool state) +{ + freeze_request_thread(); + bool result = get_current_printer()->set_power_device_state(device_name, state); + unfreeze_request_thread(); + return result; +} + +Files current_printer_get_files() +{ + freeze_request_thread(); + Files files = get_current_printer()->get_files(); + unfreeze_request_thread(); + return files; +} + +bool current_printer_start_file(const char* filename) +{ + freeze_request_thread(); + bool result = get_current_printer()->start_file(filename); + unfreeze_request_thread(); + return result; +} + +Thumbnail current_printer_get_32_32_png_image_thumbnail(const char* gcode_filename) +{ + freeze_request_thread(); + Thumbnail thumbnail = get_current_printer()->get_32_32_png_image_thumbnail(gcode_filename); + unfreeze_request_thread(); + return thumbnail; +} + +bool current_printer_set_target_temperature(PrinterTemperatureDevice device, unsigned int temperature) +{ + freeze_request_thread(); + bool result = get_current_printer()->set_target_temperature(device, temperature); + unfreeze_request_thread(); + return result; +} + diff --git a/CYD-Klipper/src/core/current_printer.h b/CYD-Klipper/src/core/current_printer.h new file mode 100644 index 0000000..a4146ba --- /dev/null +++ b/CYD-Klipper/src/core/current_printer.h @@ -0,0 +1,15 @@ +#pragma once +#include "printer_integration.hpp" + +bool current_printer_move_printer(const char* axis, float amount, bool relative); +bool current_printer_execute_feature(PrinterFeatures feature); +Macros current_printer_get_macros(); +int current_printer_get_macros_count(); +bool current_printer_execute_macro(const char* macro); +PowerDevices current_printer_get_power_devices(); +int current_printer_get_power_devices_count(); +bool current_printer_set_power_device_state(const char* device_name, bool state); +Files current_printer_get_files(); +bool current_printer_start_file(const char* filename); +Thumbnail current_printer_get_32_32_png_image_thumbnail(const char* gcode_filename); +bool current_printer_set_target_temperature(PrinterTemperatureDevice device, unsigned int temperature); \ No newline at end of file diff --git a/CYD-Klipper/src/ui/macros.cpp b/CYD-Klipper/src/ui/macros.cpp index f0f90a9..af176d3 100644 --- a/CYD-Klipper/src/ui/macros.cpp +++ b/CYD-Klipper/src/ui/macros.cpp @@ -1,6 +1,7 @@ #include "macros.h" #include "ui_utils.h" #include +#include "../core/current_printer.h" #include "../core/data_setup.h" typedef struct { @@ -12,7 +13,7 @@ static void macro_run(lv_event_t * e){ lv_obj_t * btn = lv_event_get_target(e); const char* macro = (const char*)lv_event_get_user_data(e); LOG_F(("Macro: %s\n", macro)) - get_current_printer()->execute_macro(macro); + current_printer_execute_macro(macro); } int macros_add_macros_to_panel(lv_obj_t * root_panel, BasePrinter* printer) @@ -44,7 +45,9 @@ static void power_device_toggle(lv_event_t * e) DoubleStorage* device = (DoubleStorage*)lv_event_get_user_data(e); LOG_F(("Power Device: %s, State: %d -> %d\n", device->power_device_name, !checked, checked)) + freeze_request_thread(); device->printer->set_power_device_state(device->power_device_name, checked); + unfreeze_request_thread(); } int macros_add_power_devices_to_panel(lv_obj_t * root_panel, BasePrinter* printer) diff --git a/CYD-Klipper/src/ui/panels/error_panel.cpp b/CYD-Klipper/src/ui/panels/error_panel.cpp index a215f3c..2372445 100644 --- a/CYD-Klipper/src/ui/panels/error_panel.cpp +++ b/CYD-Klipper/src/ui/panels/error_panel.cpp @@ -1,26 +1,26 @@ #include "panel.h" -#include "../../core/data_setup.h" +#include "../../core/current_printer.h" #include "../ui_utils.h" #include "../../core/printer_integration.hpp" static void btn_click_restart(lv_event_t * e){ - get_current_printer()->execute_feature(PrinterFeatureRestart); + current_printer_execute_feature(PrinterFeatureRestart); } static void btn_click_firmware_restart(lv_event_t * e){ - get_current_printer()->execute_feature(PrinterFeatureFirmwareRestart); + current_printer_execute_feature(PrinterFeatureFirmwareRestart); } static void btn_click_error_ignore(lv_event_t * e){ - get_current_printer()->execute_feature(PrinterFeatureIgnoreError); + current_printer_execute_feature(PrinterFeatureIgnoreError); } static void btn_click_error_continue(lv_event_t * e){ - get_current_printer()->execute_feature(PrinterFeatureContinueError); + current_printer_execute_feature(PrinterFeatureContinueError); } static void btn_click_error_retry(lv_event_t * e){ - get_current_printer()->execute_feature(PrinterFeatureRetryError); + current_printer_execute_feature(PrinterFeatureRetryError); } static void set_state_message_text(lv_event_t * e) { diff --git a/CYD-Klipper/src/ui/panels/files_panel.cpp b/CYD-Klipper/src/ui/panels/files_panel.cpp index 5c312a4..87ec141 100644 --- a/CYD-Klipper/src/ui/panels/files_panel.cpp +++ b/CYD-Klipper/src/ui/panels/files_panel.cpp @@ -1,7 +1,7 @@ #include "lvgl.h" #include "panel.h" -#include "../../core/data_setup.h" +#include "../../core/current_printer.h" #include "../../conf/global_config.h" #include #include "../ui_utils.h" @@ -15,7 +15,7 @@ static void btn_print_file(lv_event_t * e){ lv_obj_t * panel = (lv_obj_t*)lv_event_get_user_data(e); lv_obj_del(panel); - get_current_printer()->start_file(selected_file); + current_printer_start_file(selected_file); } static void btn_print_file_verify(lv_event_t * e){ @@ -61,10 +61,7 @@ static void btn_print_file_verify(lv_event_t * e){ lv_label_set_text(label, LV_SYMBOL_OK); lv_obj_center(label); - freeze_request_thread(); - Thumbnail thumbnail = get_current_printer()->get_32_32_png_image_thumbnail(selected_file); - unfreeze_request_thread(); - + Thumbnail thumbnail = current_printer_get_32_32_png_image_thumbnail(selected_file); lv_obj_t * img = NULL; if (thumbnail.success) @@ -93,9 +90,7 @@ static void btn_print_file_verify(lv_event_t * e){ } void files_panel_init(lv_obj_t* panel){ - freeze_request_thread(); - Files files = get_current_printer()->get_files(); - unfreeze_request_thread(); + Files files = current_printer_get_files(); if (!files.success || files.count <= 0){ lv_obj_t * label = lv_label_create(panel); diff --git a/CYD-Klipper/src/ui/panels/macros_panel.cpp b/CYD-Klipper/src/ui/panels/macros_panel.cpp index ef7b762..eaccf58 100644 --- a/CYD-Klipper/src/ui/panels/macros_panel.cpp +++ b/CYD-Klipper/src/ui/panels/macros_panel.cpp @@ -1,7 +1,6 @@ #include "../macros.h" #include "panel.h" #include "../nav_buttons.h" -#include "../../core/data_setup.h" #include "../../conf/global_config.h" #include "../ui_utils.h" #include diff --git a/CYD-Klipper/src/ui/panels/move_panel.cpp b/CYD-Klipper/src/ui/panels/move_panel.cpp index e4d2561..e4d9aa8 100644 --- a/CYD-Klipper/src/ui/panels/move_panel.cpp +++ b/CYD-Klipper/src/ui/panels/move_panel.cpp @@ -6,6 +6,7 @@ #include #include #include "../../core/printer_integration.hpp" +#include "../../core/current_printer.h" static bool last_homing_state = false; static bool move_edit_mode = false; @@ -110,7 +111,7 @@ static void x_line_button_press(lv_event_t * e) { } float data = *data_pointer; - get_current_printer()->move_printer("X", data, true); + current_printer_move_printer("X", data, true); } static void y_line_button_press(lv_event_t * e) { @@ -123,7 +124,7 @@ static void y_line_button_press(lv_event_t * e) { } float data = *data_pointer; - get_current_printer()->move_printer("Y", data, true); + current_printer_move_printer("Y", data, true); } static void z_line_button_press(lv_event_t * e) { @@ -136,7 +137,7 @@ static void z_line_button_press(lv_event_t * e) { } float data = *data_pointer; - get_current_printer()->move_printer("Z", data, true); + current_printer_move_printer("Z", data, true); } static void x_pos_update(lv_event_t * e){ @@ -167,16 +168,14 @@ static void home_button_click(lv_event_t * e) { if (get_current_printer_data()->state == PrinterState::PrinterStatePrinting) return; - freeze_request_thread(); - get_current_printer()->execute_feature(PrinterFeatures::PrinterFeatureHome); - unfreeze_request_thread(); + current_printer_execute_feature(PrinterFeatures::PrinterFeatureHome); } static void disable_steppers_click(lv_event_t * e) { if (get_current_printer_data()->state == PrinterState::PrinterStatePrinting) return; - get_current_printer()->execute_feature(PrinterFeatures::PrinterFeatureDisableSteppers); + current_printer_execute_feature(PrinterFeatures::PrinterFeatureDisableSteppers); } static void switch_to_stat_panel(lv_event_t * e) { @@ -197,7 +196,7 @@ static void line_custom_set(const char * axis, const char *text) if (pos < 0 || pos > 500) return; - get_current_printer()->move_printer(axis, pos, false); + current_printer_move_printer(axis, pos, false); } static void x_line_custom_callback(lv_event_t * e) { diff --git a/CYD-Klipper/src/ui/panels/progress_panel.cpp b/CYD-Klipper/src/ui/panels/progress_panel.cpp index 92d1fcd..60442c0 100644 --- a/CYD-Klipper/src/ui/panels/progress_panel.cpp +++ b/CYD-Klipper/src/ui/panels/progress_panel.cpp @@ -2,6 +2,7 @@ #include #include "../ui_utils.h" #include "../../core/printer_integration.hpp" +#include "../../core/current_printer.h" char time_buffer[12]; @@ -58,19 +59,19 @@ static void update_printer_data_percentage(lv_event_t * e){ } static void btn_click_stop(lv_event_t * e){ - get_current_printer()->execute_feature(PrinterFeatures::PrinterFeatureStop); + current_printer_execute_feature(PrinterFeatures::PrinterFeatureStop); } static void btn_click_pause(lv_event_t * e){ - get_current_printer()->execute_feature(PrinterFeatures::PrinterFeaturePause); + current_printer_execute_feature(PrinterFeatures::PrinterFeaturePause); } static void btn_click_resume(lv_event_t * e){ - get_current_printer()->execute_feature(PrinterFeatures::PrinterFeatureResume); + current_printer_execute_feature(PrinterFeatures::PrinterFeatureResume); } static void btn_click_estop(lv_event_t * e){ - get_current_printer()->execute_feature(PrinterFeatures::PrinterFeatureEmergencyStop); + current_printer_execute_feature(PrinterFeatures::PrinterFeatureEmergencyStop); } void progress_panel_init(lv_obj_t* panel){ diff --git a/CYD-Klipper/src/ui/panels/temp_panel.cpp b/CYD-Klipper/src/ui/panels/temp_panel.cpp index c0c1507..0d1045d 100644 --- a/CYD-Klipper/src/ui/panels/temp_panel.cpp +++ b/CYD-Klipper/src/ui/panels/temp_panel.cpp @@ -3,6 +3,7 @@ #include #include "../ui_utils.h" #include "../../core/printer_integration.hpp" +#include "../../core/current_printer.h" enum temp_target{ TARGET_HOTEND, @@ -85,10 +86,10 @@ static void keyboard_callback(lv_event_t * e){ switch (keyboard_target){ case TARGET_HOTEND: - get_current_printer()->set_target_temperature(PrinterTemperatureDevice::PrinterTemperatureDeviceNozzle1, temp); + current_printer_set_target_temperature(PrinterTemperatureDevice::PrinterTemperatureDeviceNozzle1, temp); break; case TARGET_BED: - get_current_printer()->set_target_temperature(PrinterTemperatureDevice::PrinterTemperatureDeviceBed, temp); + current_printer_set_target_temperature(PrinterTemperatureDevice::PrinterTemperatureDeviceBed, temp); break; case TARGET_HOTEND_CONFIG_1: get_current_printer()->printer_config->hotend_presets[0] = temp; @@ -132,7 +133,7 @@ static void cooldown_temp(lv_event_t * e){ return; } - get_current_printer()->execute_feature(PrinterFeatures::PrinterFeatureCooldown); + current_printer_execute_feature(PrinterFeatures::PrinterFeatureCooldown); } static void btn_extrude(lv_event_t * e){ @@ -140,7 +141,7 @@ static void btn_extrude(lv_event_t * e){ return; } - get_current_printer()->execute_feature(PrinterFeatures::PrinterFeatureExtrude); + current_printer_execute_feature(PrinterFeatures::PrinterFeatureExtrude); } static void set_temp_via_preset(lv_event_t * e){ @@ -153,7 +154,7 @@ static void set_temp_via_preset(lv_event_t * e){ return; } - get_current_printer()->set_target_temperature(TARGET_HOTEND_CONFIG_3 + current_printer_set_target_temperature(TARGET_HOTEND_CONFIG_3 ? PrinterTemperatureDevice::PrinterTemperatureDeviceNozzle1 : PrinterTemperatureDevice::PrinterTemperatureDeviceBed , value); @@ -170,7 +171,7 @@ static void btn_retract(lv_event_t * e){ return; } - get_current_printer()->execute_feature(PrinterFeatures::PrinterFeatureRetract); + current_printer_execute_feature(PrinterFeatures::PrinterFeatureRetract); } static void set_chart_range(lv_event_t * e) { diff --git a/serial.py b/serial.py new file mode 100644 index 0000000..3b449e8 --- /dev/null +++ b/serial.py @@ -0,0 +1,79 @@ +import serial +import requests +import time + +# Define serial port and parameters +SERIAL_PORT = 'COM6' # Change this to your serial port +BAUD_RATE = 115200 +HOSTNAME = 'http://localhost' # Change to your hostname +PORT = 7125 # Change to your port if necessary + +# --------- # + +ser = serial.Serial(SERIAL_PORT, BAUD_RATE, timeout=1) + +def truncuate(text : str, length : int = 50): + length = length - 3 + if len(text) > length: + return text[:length] + "..." + return text + +def write(text : str, write : bool): + if write: + ser.write((text + "\n").encode('utf-8')) + print(f"<<< {truncuate(text)}") + else: + print(f"(Ignored) <<< {truncuate(text)}") + +def main(): + while True: + # Read a line from the serial port + if ser.in_waiting > 0: + line = ser.readline().decode('utf-8').strip() + if line.startswith("HTTP_REQUEST"): + print(f">>> {line}") + # Parse the parameters + try: + parts = line.split(' ', 3) + timeout_ms, request_type, url_path = int(parts[1]), parts[2], parts[3] + + ignore_timeout = timeout_ms <= 0 + + if ignore_timeout: + timeout_ms = 1000; + + # Construct the full URL + full_url = f"{HOSTNAME}:{PORT}{url_path}" + + # Make the HTTP request based on the type + response = None + if request_type.upper() == "GET": + response = requests.get(full_url, timeout=timeout_ms / 1000) + elif request_type.upper() == "POST": + response = requests.post(full_url, timeout=timeout_ms / 1000) + else: + write("400 Unsupported request type", not ignore_timeout) + continue + + # Send response back over serial + if response != None: + status_code = response.status_code + body = response.text.replace('\n', ' ') # Trim and sanitize body for serial + message = f"{status_code} {body}" + write(message, not ignore_timeout) + except (IndexError, ValueError) as e: + write(f"400 Malformed request {str(e)}", not ignore_timeout) + except requests.exceptions.ReadTimeout as e: + print("Request timed out.") + pass + except requests.exceptions.RequestException as e: + write("500 Request failed", not ignore_timeout) + else: + print(f"[LOG] {line}") + +if __name__ == "__main__": + try: + main() + except KeyboardInterrupt: + print("\nExiting script.") + ser.close() \ No newline at end of file From f9444829ee8eaf6fc952ee760e99bb8ce0645bcb Mon Sep 17 00:00:00 2001 From: suchmememanyskill <38142618+suchmememanyskill@users.noreply.github.com> Date: Sat, 9 Nov 2024 01:30:40 +0100 Subject: [PATCH 36/63] Gcode images, fixes to serial --- .gitignore | 1 + .../serial_klipper_printer_integration.cpp | 133 +++++++++++++++++- .../serial_klipper_printer_integration.hpp | 3 + .../klipper/klipper_printer_integration.cpp | 2 +- .../klipper/klipper_printer_integration.hpp | 4 +- serial.py => serial_server.py | 20 ++- 6 files changed, 151 insertions(+), 12 deletions(-) rename serial.py => serial_server.py (73%) diff --git a/.gitignore b/.gitignore index ab1e7fe..48ddf06 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,4 @@ out/ lib lib64 +__pycache__/ \ No newline at end of file diff --git a/CYD-Klipper/src/core/klipper-serial/serial_klipper_printer_integration.cpp b/CYD-Klipper/src/core/klipper-serial/serial_klipper_printer_integration.cpp index 0e2c181..7100db0 100644 --- a/CYD-Klipper/src/core/klipper-serial/serial_klipper_printer_integration.cpp +++ b/CYD-Klipper/src/core/klipper-serial/serial_klipper_printer_integration.cpp @@ -110,6 +110,83 @@ bool make_serial_request(JsonDocument &out, int timeout_ms, HttpRequestType requ return success; } +typedef struct +{ + int len; + unsigned char* data; +} BinaryResponse; + +bool make_binary_request(BinaryResponse* data, int timeout_ms, HttpRequestType requestType, const char* endpoint) +{ + semaphore_init_serial(); + freeze_serial_thread(); + serial_console::global_disable_serial_console = true; + temporary_config.debug = false; + char buff[10]; + clear_serial_buffer(); + + // TODO: Add semaphore here + if (!Serial.availableForWrite() || timeout_ms <= 0) + { + unfreeze_serial_thread(); + return false; + } + + Serial.printf("HTTP_BINARY %d %s %s\n", timeout_ms, requestType == HttpGet ? "GET" : "POST", endpoint); + + unsigned long _m = millis(); + while (!Serial.available() && millis() < _m + timeout_ms + 10) delay(1); + + if (!Serial.available()) + { + Serial.println("Timeout..."); + unfreeze_serial_thread(); + return false; + } + + Serial.readBytes(buff, 8); + buff[9] = 0; + + if (buff[0] < '0' || buff[0] > '9') + { + Serial.println("Invalid length"); + clear_serial_buffer(); + unfreeze_serial_thread(); + return false; + } + + int data_length = atoi(buff); + + if (data_length <= 0) + { + Serial.println("0 Length"); + clear_serial_buffer(); + unfreeze_serial_thread(); + return false; + } + + data->len = data_length; + data->data = (unsigned char*)malloc(data_length); + + if (data->data == NULL) + { + Serial.println("Failed to allocate memory"); + clear_serial_buffer(); + unfreeze_serial_thread(); + return false; + } + + bool result = Serial.readBytes((char*)data->data, data_length) == data_length; + unfreeze_serial_thread(); + + if (!result) + { + free(data->data); + } + + return result; +} + bool make_serial_request_nocontent(HttpRequestType requestType, const char* endpoint) { JsonDocument doc; @@ -254,7 +331,7 @@ Files SerialKlipperPrinter::get_files() { return files_result; } - + parse_file_list(doc, files, 20); unfreeze_serial_thread(); @@ -285,14 +362,38 @@ bool SerialKlipperPrinter::start_file(const char* filename) { JsonDocument doc; String request = "/printer/print/start?filename=" + urlEncode(filename); - return make_serial_request_nocontent(HttpGet, request.c_str());; + return make_serial_request_nocontent(HttpPost, request.c_str());; } Thumbnail SerialKlipperPrinter::get_32_32_png_image_thumbnail(const char* gcode_filename) { - // TODO: Stubbed Thumbnail thumbnail = {0}; - thumbnail.success = false; + JsonDocument doc; + char* img_filename_path = NULL; + + String request = "/server/files/thumbnails?filename=" + urlEncode(gcode_filename); + if (make_serial_request(doc, 1000, HttpGet, request.c_str())) + { + img_filename_path = parse_thumbnails(doc); + unfreeze_serial_thread(); + doc.clear(); + } + + if (img_filename_path == NULL) + { + return thumbnail; + } + + request = "/server/files/gcodes/" + urlEncode(img_filename_path); + BinaryResponse data = {0}; + if (make_binary_request(&data, 2000, HttpGet, request.c_str())) + { + thumbnail.png = data.data; + thumbnail.size = data.len; + thumbnail.success = true; + } + + free(img_filename_path); return thumbnail; } @@ -311,6 +412,30 @@ bool SerialKlipperPrinter::send_gcode(const char* gcode, bool wait) return result; } +bool SerialKlipperPrinter::send_emergency_stop() +{ + return make_serial_request_nocontent(HttpGet, "/printer/emergency_stop"); +} + +int SerialKlipperPrinter::get_slicer_time_estimate_s() +{ + if (printer_data.state != PrinterStatePrinting && printer_data.state != PrinterStatePaused) + return 0; + + String request = "/server/files/metadata?filename=" + urlEncode(printer_data.print_filename); + JsonDocument doc; + + if (!make_serial_request(doc, 2000, HttpGet, request.c_str())) + { + return 0; + } + + int estimate = parse_slicer_time_estimate(doc); + unfreeze_serial_thread(); + + return estimate; +} + KlipperConnectionStatus connection_test_serial_klipper(PrinterConfiguration* config) { serial_console::global_disable_serial_console = true; diff --git a/CYD-Klipper/src/core/klipper-serial/serial_klipper_printer_integration.hpp b/CYD-Klipper/src/core/klipper-serial/serial_klipper_printer_integration.hpp index 022de5b..7d50ac4 100644 --- a/CYD-Klipper/src/core/klipper-serial/serial_klipper_printer_integration.hpp +++ b/CYD-Klipper/src/core/klipper-serial/serial_klipper_printer_integration.hpp @@ -2,6 +2,9 @@ class SerialKlipperPrinter : public KlipperPrinter { + protected: + bool send_emergency_stop(); + int get_slicer_time_estimate_s(); public: SerialKlipperPrinter(int index) : KlipperPrinter(index) {} diff --git a/CYD-Klipper/src/core/klipper/klipper_printer_integration.cpp b/CYD-Klipper/src/core/klipper/klipper_printer_integration.cpp index 70c71cb..7279453 100644 --- a/CYD-Klipper/src/core/klipper/klipper_printer_integration.cpp +++ b/CYD-Klipper/src/core/klipper/klipper_printer_integration.cpp @@ -147,7 +147,7 @@ bool KlipperPrinter::execute_feature(PrinterFeatures feature) return false; } - if (get_current_printer()->printer_config->custom_filament_move_macros) + if (printer_config->custom_filament_move_macros) { return send_gcode("FILAMENT_RETRACT"); } diff --git a/CYD-Klipper/src/core/klipper/klipper_printer_integration.hpp b/CYD-Klipper/src/core/klipper/klipper_printer_integration.hpp index 9309afd..3487029 100644 --- a/CYD-Klipper/src/core/klipper/klipper_printer_integration.hpp +++ b/CYD-Klipper/src/core/klipper/klipper_printer_integration.hpp @@ -21,8 +21,8 @@ class KlipperPrinter : public BasePrinter unsigned char lock_absolute_relative_mode_swap{}; unsigned char klipper_request_consecutive_fail_count{}; - bool send_emergency_stop(); - int get_slicer_time_estimate_s(); + virtual bool send_emergency_stop(); + virtual int get_slicer_time_estimate_s(); void init_ui_panels(); int parse_slicer_time_estimate(JsonDocument& in); diff --git a/serial.py b/serial_server.py similarity index 73% rename from serial.py rename to serial_server.py index 3b449e8..d75f6ae 100644 --- a/serial.py +++ b/serial_server.py @@ -30,7 +30,7 @@ def main(): # Read a line from the serial port if ser.in_waiting > 0: line = ser.readline().decode('utf-8').strip() - if line.startswith("HTTP_REQUEST"): + if line.startswith("HTTP_REQUEST") or line.startswith("HTTP_BINARY"): print(f">>> {line}") # Parse the parameters try: @@ -38,6 +38,7 @@ def main(): timeout_ms, request_type, url_path = int(parts[1]), parts[2], parts[3] ignore_timeout = timeout_ms <= 0 + binary = line.startswith("HTTP_BINARY") if ignore_timeout: timeout_ms = 1000; @@ -57,10 +58,19 @@ def main(): # Send response back over serial if response != None: - status_code = response.status_code - body = response.text.replace('\n', ' ') # Trim and sanitize body for serial - message = f"{status_code} {body}" - write(message, not ignore_timeout) + if binary: + if response.status_code != 200: + write("00000000", not ignore_timeout) + else: + length = len(response.content) + ser.write(f"{length:>08}".encode('utf-8')) + ser.write(response.content) + print(f"<<< (Binary data of {length} bytes)") + else: + status_code = response.status_code + body = response.text.replace('\n', ' ') # Trim and sanitize body for serial + message = f"{status_code} {body}" + write(message, not ignore_timeout) except (IndexError, ValueError) as e: write(f"400 Malformed request {str(e)}", not ignore_timeout) except requests.exceptions.ReadTimeout as e: From bf90803107406b25b30b0b71b6e9ec41991d7e4a Mon Sep 17 00:00:00 2001 From: suchmememanyskill <38142618+suchmememanyskill@users.noreply.github.com> Date: Sat, 9 Nov 2024 01:37:48 +0100 Subject: [PATCH 37/63] Remove serial semaphore --- .../serial_klipper_printer_integration.cpp | 87 +++---------------- 1 file changed, 14 insertions(+), 73 deletions(-) diff --git a/CYD-Klipper/src/core/klipper-serial/serial_klipper_printer_integration.cpp b/CYD-Klipper/src/core/klipper-serial/serial_klipper_printer_integration.cpp index 7100db0..4fe6f4d 100644 --- a/CYD-Klipper/src/core/klipper-serial/serial_klipper_printer_integration.cpp +++ b/CYD-Klipper/src/core/klipper-serial/serial_klipper_printer_integration.cpp @@ -3,31 +3,6 @@ #include #include "../../ui/serial/serial_console.h" -bool is_semaphores_initialized = false; -SemaphoreHandle_t freeze_serial_thread_semaphore; - -void semaphore_init_serial() -{ - if (is_semaphores_initialized) - { - return; - } - - freeze_serial_thread_semaphore = xSemaphoreCreateMutex(); - xSemaphoreGive(freeze_serial_thread_semaphore); - is_semaphores_initialized = true; -} - -void freeze_serial_thread() -{ - xSemaphoreTake(freeze_serial_thread_semaphore, portMAX_DELAY); -} - -void unfreeze_serial_thread() -{ - xSemaphoreGive(freeze_serial_thread_semaphore); -} - enum HttpRequestType { HttpPost, @@ -46,8 +21,6 @@ void clear_serial_buffer() // Response: {status code} {body} bool make_serial_request(JsonDocument &out, int timeout_ms, HttpRequestType requestType, const char* endpoint) { - semaphore_init_serial(); - freeze_serial_thread(); serial_console::global_disable_serial_console = true; temporary_config.debug = false; char buff[10]; @@ -56,7 +29,6 @@ bool make_serial_request(JsonDocument &out, int timeout_ms, HttpRequestType requ // TODO: Add semaphore here if (!Serial.availableForWrite()) { - unfreeze_serial_thread(); return false; } @@ -64,7 +36,6 @@ bool make_serial_request(JsonDocument &out, int timeout_ms, HttpRequestType requ if (timeout_ms <= 0) { - unfreeze_serial_thread(); return true; } unsigned long _m = millis(); @@ -73,7 +44,6 @@ bool make_serial_request(JsonDocument &out, int timeout_ms, HttpRequestType requ if (!Serial.available()) { Serial.println("Timeout..."); - unfreeze_serial_thread(); return false; } @@ -84,7 +54,7 @@ bool make_serial_request(JsonDocument &out, int timeout_ms, HttpRequestType requ { Serial.println("Invalid error code"); clear_serial_buffer(); - unfreeze_serial_thread(); + return false; } @@ -94,7 +64,7 @@ bool make_serial_request(JsonDocument &out, int timeout_ms, HttpRequestType requ { Serial.println("Non-200 error code"); clear_serial_buffer(); - unfreeze_serial_thread(); + return false; } @@ -102,11 +72,6 @@ bool make_serial_request(JsonDocument &out, int timeout_ms, HttpRequestType requ Serial.printf("Deserialization result: %s\n", result.c_str()); bool success = result == DeserializationError::Ok; - if (!success) - { - unfreeze_serial_thread(); - } - return success; } @@ -118,8 +83,6 @@ typedef struct bool make_binary_request(BinaryResponse* data, int timeout_ms, HttpRequestType requestType, const char* endpoint) { - semaphore_init_serial(); - freeze_serial_thread(); serial_console::global_disable_serial_console = true; temporary_config.debug = false; char buff[10]; @@ -128,7 +91,6 @@ bool make_binary_request(BinaryResponse* data, int timeout_ms, HttpRequestType r // TODO: Add semaphore here if (!Serial.availableForWrite() || timeout_ms <= 0) { - unfreeze_serial_thread(); return false; } @@ -140,7 +102,7 @@ bool make_binary_request(BinaryResponse* data, int timeout_ms, HttpRequestType r if (!Serial.available()) { Serial.println("Timeout..."); - unfreeze_serial_thread(); + return false; } @@ -151,7 +113,7 @@ bool make_binary_request(BinaryResponse* data, int timeout_ms, HttpRequestType r { Serial.println("Invalid length"); clear_serial_buffer(); - unfreeze_serial_thread(); + return false; } @@ -161,7 +123,7 @@ bool make_binary_request(BinaryResponse* data, int timeout_ms, HttpRequestType r { Serial.println("0 Length"); clear_serial_buffer(); - unfreeze_serial_thread(); + return false; } @@ -172,13 +134,11 @@ bool make_binary_request(BinaryResponse* data, int timeout_ms, HttpRequestType r { Serial.println("Failed to allocate memory"); clear_serial_buffer(); - unfreeze_serial_thread(); + return false; } bool result = Serial.readBytes((char*)data->data, data_length) == data_length; - unfreeze_serial_thread(); - if (!result) { free(data->data); @@ -191,7 +151,7 @@ bool make_serial_request_nocontent(HttpRequestType requestType, const char* endp { JsonDocument doc; make_serial_request(doc, 0, requestType, endpoint); - unfreeze_serial_thread(); + return true; } @@ -212,7 +172,6 @@ bool SerialKlipperPrinter::fetch() klipper_request_consecutive_fail_count = 0; parse_state(doc); - unfreeze_serial_thread(); } else { @@ -245,7 +204,6 @@ PrinterDataMinimal SerialKlipperPrinter::fetch_min() { data.state = PrinterState::PrinterStateIdle; parse_state_min(doc, &data); - unfreeze_serial_thread(); data.power_devices = get_power_devices_count(); } else @@ -264,7 +222,6 @@ Macros SerialKlipperPrinter::get_macros() if (make_serial_request(doc, 1000, HttpGet, "/printer/gcode/help")) { macros = parse_macros(doc); - unfreeze_serial_thread(); } return macros; @@ -275,9 +232,7 @@ int SerialKlipperPrinter::get_macros_count() JsonDocument doc; if (make_serial_request(doc, 1000, HttpGet, "/printer/gcode/help")) { - int count = parse_macros_count(doc); - unfreeze_serial_thread(); - return count; + return parse_macros_count(doc); } return 0; @@ -290,7 +245,6 @@ PowerDevices SerialKlipperPrinter::get_power_devices() if (make_serial_request(doc, 1000, HttpGet, "/machine/device_power/devices")) { power_devices = parse_power_devices(doc); - unfreeze_serial_thread(); } return power_devices; @@ -301,9 +255,7 @@ int SerialKlipperPrinter::get_power_devices_count() JsonDocument doc; if (make_serial_request(doc, 1000, HttpGet, "/machine/device_power/devices")) { - int count = parse_power_devices_count(doc); - unfreeze_serial_thread(); - return count; + return parse_power_devices_count(doc); } return 0; @@ -333,8 +285,7 @@ Files SerialKlipperPrinter::get_files() } parse_file_list(doc, files, 20); - unfreeze_serial_thread(); - + files_result.available_files = (char**)malloc(sizeof(char*) * files.size()); if (files_result.available_files == NULL){ @@ -375,7 +326,6 @@ Thumbnail SerialKlipperPrinter::get_32_32_png_image_thumbnail(const char* gcode_ if (make_serial_request(doc, 1000, HttpGet, request.c_str())) { img_filename_path = parse_thumbnails(doc); - unfreeze_serial_thread(); doc.clear(); } @@ -402,14 +352,9 @@ bool SerialKlipperPrinter::send_gcode(const char* gcode, bool wait) JsonDocument doc; String request = "/printer/gcode/script?script=" + urlEncode(gcode); - if (!wait) - { - return make_serial_request_nocontent(HttpGet, request.c_str()); - } - - bool result = make_serial_request(doc, 5000, HttpGet, request.c_str()); - unfreeze_serial_thread(); - return result; + return wait + ? make_serial_request(doc, 5000, HttpGet, request.c_str()) + : make_serial_request_nocontent(HttpGet, request.c_str()); } bool SerialKlipperPrinter::send_emergency_stop() @@ -430,10 +375,7 @@ int SerialKlipperPrinter::get_slicer_time_estimate_s() return 0; } - int estimate = parse_slicer_time_estimate(doc); - unfreeze_serial_thread(); - - return estimate; + return parse_slicer_time_estimate(doc); } KlipperConnectionStatus connection_test_serial_klipper(PrinterConfiguration* config) @@ -443,7 +385,6 @@ KlipperConnectionStatus connection_test_serial_klipper(PrinterConfiguration* con JsonDocument doc; if (make_serial_request(doc, 1000, HttpGet, "/printer/info")) { - unfreeze_serial_thread(); return KlipperConnectionStatus::ConnectOk; } From 17143d2878e1e049220b6236a2304f7f9ac32530 Mon Sep 17 00:00:00 2001 From: suchmememanyskill <38142618+suchmememanyskill@users.noreply.github.com> Date: Sat, 9 Nov 2024 02:06:04 +0100 Subject: [PATCH 38/63] Allow running wifi-less --- CYD-Klipper/src/conf/global_config.h | 1 + CYD-Klipper/src/ui/ip_setup.cpp | 49 +++++++++++++++----- CYD-Klipper/src/ui/panels/settings_panel.cpp | 1 + CYD-Klipper/src/ui/wifi_setup.cpp | 22 +++++++-- 4 files changed, 58 insertions(+), 15 deletions(-) diff --git a/CYD-Klipper/src/conf/global_config.h b/CYD-Klipper/src/conf/global_config.h index 5cfad49..f337225 100644 --- a/CYD-Klipper/src/conf/global_config.h +++ b/CYD-Klipper/src/conf/global_config.h @@ -71,6 +71,7 @@ typedef struct { // Internal bool screen_calibrated : 1; bool wifi_configured : 1; + bool wifi_configuration_skipped : 1; // External bool rotate_screen : 1; diff --git a/CYD-Klipper/src/ui/ip_setup.cpp b/CYD-Klipper/src/ui/ip_setup.cpp index cdf11eb..738cd20 100644 --- a/CYD-Klipper/src/ui/ip_setup.cpp +++ b/CYD-Klipper/src/ui/ip_setup.cpp @@ -394,8 +394,16 @@ static void printer_type_serial_klipper(lv_event_t * e) show_ip_entry(); } +static void return_to_wifi_configuration(lv_event_t * e) +{ + global_config.wifi_configuration_skipped = false; + write_global_config(); + ESP.restart(); +} + void choose_printer_type() { + lv_obj_t * btn; lv_obj_clean(lv_scr_act()); global_config.printer_config[global_config.printer_index].ip_configured = false; global_config.printer_config[global_config.printer_index].auth_configured = false; @@ -410,13 +418,16 @@ void choose_printer_type() lv_obj_t * label = lv_label_create(root); lv_label_set_text(label, "Choose printer type"); - lv_obj_t * btn = lv_btn_create(root); - lv_obj_set_size(btn, CYD_SCREEN_WIDTH_PX - CYD_SCREEN_GAP_PX * 2, CYD_SCREEN_MIN_BUTTON_HEIGHT_PX); - lv_obj_add_event_cb(btn, printer_type_klipper, LV_EVENT_CLICKED, NULL); + if (global_config.wifi_configured) + { + btn = lv_btn_create(root); + lv_obj_set_size(btn, CYD_SCREEN_WIDTH_PX - CYD_SCREEN_GAP_PX * 2, CYD_SCREEN_MIN_BUTTON_HEIGHT_PX); + lv_obj_add_event_cb(btn, printer_type_klipper, LV_EVENT_CLICKED, NULL); - label = lv_label_create(btn); - lv_label_set_text(label, "Klipper"); - lv_obj_center(label); + label = lv_label_create(btn); + lv_label_set_text(label, "Klipper"); + lv_obj_center(label); + } btn = lv_btn_create(root); lv_obj_set_size(btn, CYD_SCREEN_WIDTH_PX - CYD_SCREEN_GAP_PX * 2, CYD_SCREEN_MIN_BUTTON_HEIGHT_PX); @@ -426,13 +437,27 @@ void choose_printer_type() lv_label_set_text(label, "Klipper (Serial)"); lv_obj_center(label); - btn = lv_btn_create(root); - lv_obj_set_size(btn, CYD_SCREEN_WIDTH_PX - CYD_SCREEN_GAP_PX * 2, CYD_SCREEN_MIN_BUTTON_HEIGHT_PX); - lv_obj_add_event_cb(btn, printer_type_bambu_local, LV_EVENT_CLICKED, NULL); + if (global_config.wifi_configured) + { + btn = lv_btn_create(root); + lv_obj_set_size(btn, CYD_SCREEN_WIDTH_PX - CYD_SCREEN_GAP_PX * 2, CYD_SCREEN_MIN_BUTTON_HEIGHT_PX); + lv_obj_add_event_cb(btn, printer_type_bambu_local, LV_EVENT_CLICKED, NULL); - label = lv_label_create(btn); - lv_label_set_text(label, "Bambu (Local)"); - lv_obj_center(label); + label = lv_label_create(btn); + lv_label_set_text(label, "Bambu (Local)"); + lv_obj_center(label); + } + + if (global_config.wifi_configuration_skipped) + { + btn = lv_btn_create(root); + lv_obj_set_size(btn, CYD_SCREEN_WIDTH_PX - CYD_SCREEN_GAP_PX * 2, CYD_SCREEN_MIN_BUTTON_HEIGHT_PX); + lv_obj_add_event_cb(btn, return_to_wifi_configuration, LV_EVENT_CLICKED, NULL); + + label = lv_label_create(btn); + lv_label_set_text(label, "Return to WiFi configuration"); + lv_obj_center(label); + } } void ip_init(){ diff --git a/CYD-Klipper/src/ui/panels/settings_panel.cpp b/CYD-Klipper/src/ui/panels/settings_panel.cpp index f114497..d7865b3 100644 --- a/CYD-Klipper/src/ui/panels/settings_panel.cpp +++ b/CYD-Klipper/src/ui/panels/settings_panel.cpp @@ -34,6 +34,7 @@ static void reset_click(lv_event_t * e){ static void reset_wifi_click(lv_event_t * e){ global_config.wifi_configured = false; + global_config.wifi_configuration_skipped = false; write_global_config(); ESP.restart(); } diff --git a/CYD-Klipper/src/ui/wifi_setup.cpp b/CYD-Klipper/src/ui/wifi_setup.cpp index 14d6c6e..bad8f03 100644 --- a/CYD-Klipper/src/ui/wifi_setup.cpp +++ b/CYD-Klipper/src/ui/wifi_setup.cpp @@ -106,6 +106,10 @@ static void wifi_btn_manual_ssid(lv_event_t * e){ lv_create_keyboard_text_entry(wifi_keyboard_cb_manual_ssid, "Enter SSID Manually", LV_KEYBOARD_MODE_TEXT_LOWER, CYD_SCREEN_WIDTH_PX * 0.75, 31, "", false); } +static void wifi_btn_skip_setup(lv_event_t * e){ + global_config.wifi_configuration_skipped = true; +} + void wifi_init_inner(){ WiFi.disconnect(); lv_obj_clean(lv_scr_act()); @@ -162,6 +166,14 @@ void wifi_init_inner(){ lv_obj_set_flex_grow(label, 1); lv_obj_t * btn = lv_btn_create(top_row); + lv_obj_add_event_cb(btn, wifi_btn_skip_setup, LV_EVENT_CLICKED, NULL); + lv_obj_set_size(btn, CYD_SCREEN_MIN_BUTTON_WIDTH_PX * 2, CYD_SCREEN_MIN_BUTTON_HEIGHT_PX); + + label = lv_label_create(btn); + lv_label_set_text(label, "Skip"); + lv_obj_center(label); + + btn = lv_btn_create(top_row); lv_obj_add_event_cb(btn, wifi_btn_manual_ssid, LV_EVENT_CLICKED, NULL); lv_obj_set_size(btn, CYD_SCREEN_MIN_BUTTON_WIDTH_PX, CYD_SCREEN_MIN_BUTTON_HEIGHT_PX); @@ -216,10 +228,15 @@ const int print_freq = 1000; int print_timer = 0; void wifi_init(){ + if (global_config.wifi_configuration_skipped) + { + return; + } + WiFi.mode(WIFI_STA); wifi_init_inner(); - while (!global_config.wifi_configured || WiFi.status() != WL_CONNECTED){ + while (!global_config.wifi_configuration_skipped && (!global_config.wifi_configured || WiFi.status() != WL_CONNECTED)){ if (millis() - print_timer > print_freq){ print_timer = millis(); LOG_F(("WiFi Status: %s\n", errs[WiFi.status()])) @@ -227,14 +244,13 @@ void wifi_init(){ lv_handler(); serial_console::run(); - } } ulong start_time_recovery = 0; void wifi_ok(){ - if (WiFi.status() != WL_CONNECTED){ + if (global_config.wifi_configured && WiFi.status() != WL_CONNECTED){ LOG_LN("WiFi Connection Lost. Reconnecting..."); freeze_request_thread(); WiFi.disconnect(); From e5390e731f6f5b3654085cccca75a3a903358260 Mon Sep 17 00:00:00 2001 From: suchmememanyskill <38142618+suchmememanyskill@users.noreply.github.com> Date: Sat, 9 Nov 2024 12:30:38 +0100 Subject: [PATCH 39/63] Allow accessing device settings from wifi panel --- .../serial_klipper_printer_integration.cpp | 2 ++ CYD-Klipper/src/ui/panels/panel.h | 4 ++- CYD-Klipper/src/ui/wifi_setup.cpp | 28 ++++++++++++++++++- 3 files changed, 32 insertions(+), 2 deletions(-) diff --git a/CYD-Klipper/src/core/klipper-serial/serial_klipper_printer_integration.cpp b/CYD-Klipper/src/core/klipper-serial/serial_klipper_printer_integration.cpp index 4fe6f4d..a071e37 100644 --- a/CYD-Klipper/src/core/klipper-serial/serial_klipper_printer_integration.cpp +++ b/CYD-Klipper/src/core/klipper-serial/serial_klipper_printer_integration.cpp @@ -81,6 +81,8 @@ typedef struct unsigned char* data; } BinaryResponse; +// Request: {timeout} {method} {endpoint} +// Response: {8 char 0's padded body length}{body} bool make_binary_request(BinaryResponse* data, int timeout_ms, HttpRequestType requestType, const char* endpoint) { serial_console::global_disable_serial_console = true; diff --git a/CYD-Klipper/src/ui/panels/panel.h b/CYD-Klipper/src/ui/panels/panel.h index ef8b27e..9e97c49 100644 --- a/CYD-Klipper/src/ui/panels/panel.h +++ b/CYD-Klipper/src/ui/panels/panel.h @@ -11,4 +11,6 @@ void macros_panel_init(lv_obj_t* panel); void stats_panel_init(lv_obj_t* panel); void printer_panel_init(lv_obj_t* panel); void error_panel_init(lv_obj_t* panel); -void connecting_panel_init(lv_obj_t* panel); \ No newline at end of file +void connecting_panel_init(lv_obj_t* panel); + +void settings_section_device(lv_obj_t* panel); \ No newline at end of file diff --git a/CYD-Klipper/src/ui/wifi_setup.cpp b/CYD-Klipper/src/ui/wifi_setup.cpp index bad8f03..7a46e4e 100644 --- a/CYD-Klipper/src/ui/wifi_setup.cpp +++ b/CYD-Klipper/src/ui/wifi_setup.cpp @@ -6,6 +6,7 @@ #include "../core/data_setup.h" #include "../core/lv_setup.h" #include "serial/serial_console.h" +#include "panels/panel.h" void wifi_init_inner(); void wifi_pass_entry(const char* ssid); @@ -110,6 +111,23 @@ static void wifi_btn_skip_setup(lv_event_t * e){ global_config.wifi_configuration_skipped = true; } +static void wifi_btn_settings(lv_event_t * e){ + lv_obj_clean(lv_scr_act()); + lv_obj_t * panel = lv_create_empty_panel(lv_scr_act()); + lv_obj_set_size(panel, CYD_SCREEN_WIDTH_PX, CYD_SCREEN_HEIGHT_PX); + lv_layout_flex_column(panel); + + lv_obj_t * btn = lv_btn_create(panel); + lv_obj_add_event_cb(btn, reset_btn_event_handler, LV_EVENT_CLICKED, NULL); + lv_obj_set_size(btn, LV_PCT(100), CYD_SCREEN_MIN_BUTTON_HEIGHT_PX); + + lv_obj_t * label = lv_label_create(btn); + lv_label_set_text(label, "Return to WiFi Setup"); + lv_obj_center(label); + + settings_section_device(panel); +} + void wifi_init_inner(){ WiFi.disconnect(); lv_obj_clean(lv_scr_act()); @@ -166,8 +184,16 @@ void wifi_init_inner(){ lv_obj_set_flex_grow(label, 1); lv_obj_t * btn = lv_btn_create(top_row); + lv_obj_add_event_cb(btn, wifi_btn_settings, LV_EVENT_CLICKED, NULL); + lv_obj_set_size(btn, CYD_SCREEN_MIN_BUTTON_WIDTH_PX, CYD_SCREEN_MIN_BUTTON_HEIGHT_PX); + + label = lv_label_create(btn); + lv_label_set_text(label, LV_SYMBOL_SETTINGS); + lv_obj_center(label); + + btn = lv_btn_create(top_row); lv_obj_add_event_cb(btn, wifi_btn_skip_setup, LV_EVENT_CLICKED, NULL); - lv_obj_set_size(btn, CYD_SCREEN_MIN_BUTTON_WIDTH_PX * 2, CYD_SCREEN_MIN_BUTTON_HEIGHT_PX); + lv_obj_set_size(btn, CYD_SCREEN_MIN_BUTTON_WIDTH_PX * 1.5, CYD_SCREEN_MIN_BUTTON_HEIGHT_PX); label = lv_label_create(btn); lv_label_set_text(label, "Skip"); From 12781051ca38b7eb60ddb4c69b57a77bc3735230 Mon Sep 17 00:00:00 2001 From: suchmememanyskill <38142618+suchmememanyskill@users.noreply.github.com> Date: Sun, 10 Nov 2024 00:54:38 +0100 Subject: [PATCH 40/63] Serial installer --- CYD-Klipper/src/ui/wifi_setup.cpp | 1 + serial/README.md | 39 +++++++ serial/install.sh | 30 +++++ serial/requirements.txt | 2 + serial_server.py => serial/serial_server.py | 116 ++++++++++++++++++-- serial/uninstall.sh | 13 +++ 6 files changed, 190 insertions(+), 11 deletions(-) create mode 100644 serial/README.md create mode 100644 serial/install.sh create mode 100644 serial/requirements.txt rename serial_server.py => serial/serial_server.py (50%) create mode 100644 serial/uninstall.sh diff --git a/CYD-Klipper/src/ui/wifi_setup.cpp b/CYD-Klipper/src/ui/wifi_setup.cpp index 7a46e4e..9c25694 100644 --- a/CYD-Klipper/src/ui/wifi_setup.cpp +++ b/CYD-Klipper/src/ui/wifi_setup.cpp @@ -109,6 +109,7 @@ static void wifi_btn_manual_ssid(lv_event_t * e){ static void wifi_btn_skip_setup(lv_event_t * e){ global_config.wifi_configuration_skipped = true; + write_global_config(); } static void wifi_btn_settings(lv_event_t * e){ diff --git a/serial/README.md b/serial/README.md new file mode 100644 index 0000000..4931f72 --- /dev/null +++ b/serial/README.md @@ -0,0 +1,39 @@ +# Serial connection + +This section elaborates on how the host side (linux) should be set up to handle incoming CYD-Klipper requests. + +## Install (Linux) + +1. Log into your host running klipper +1. Cd into a folder where CYD-Klipper will live, for example your home folder + - To enter your home folder, type `cd ~` +1. `git clone https://github.com/suchmememanyskill/CYD-Klipper` +1. `cd CYD-Klipper/serial` +1. `chmod a+x install.sh` +1. `./install.sh` + +## Uninstall (Linux) +1. Log into your host running klipper +1. Cd into the folder where CYD-Klipper is installed +1. `cd serial` +1. `chmod a+x uninstall.sh` +1. `./uninstall.sh` + +## Configuration + +The installer creates a systemd service in `~/.config/systemd/user/cyd-klipper-serial.service`. If manual configuration is needed (for example, if moonraker runs on another port or another host, or if the esp32 could not be found), you can edit this file to add environment variables. + +To add an environemnt variable in a systemd unit file, inside the `[Service]` section, write `Environment="KEY=VALUE"`, where KEY is the environemnt variable's name, and VALUE is the environment variable's value. + +After editing the cyd-klipper-serial.service file, run `systemctl --user daemon-reload` then `systemctl --user restart cyd-klipper-serial` + +| Name | Description | Default Value | +| --- | --- | --- | +|KLIPPER_PROTOCOL|Protocol used. `http` or `https`|`http`| +|KLIPPER_HOST|The IP or hostname the Moonraker server runs on|`localhost`| +|KLIPPER_PORT|The port of the Moonraker webserver|[`80`, `7125`]| +|ESP32_SERIAL|Path to the serial device, like `/dev/ttyUSB0`|None, see below + +By default, a connection to moonraker is attempted to `http://localhost:80` and `http://localhost:7125`. If no connection can be made, the script refuses to continue. The script will indefinitely attempt to re-connect. See the logs generated for more information. + +By default, ESP32 devices are attempted to be located on the system. If too many are located, or none are located, the script refuses to continue. If one is found, an attempt is made to connect to the device. See the logs generated for more information. \ No newline at end of file diff --git a/serial/install.sh b/serial/install.sh new file mode 100644 index 0000000..b4acb4c --- /dev/null +++ b/serial/install.sh @@ -0,0 +1,30 @@ +#!/bin/bash + +if [ "$EUID" -eq 0 ]; then + echo "Please do not run as root" + exit +fi + +set -e + +# Install dependencies +pip3 install -r requirements.txt + +# Create systemd unit file +mkdir -p ~/.config/systemd/user +echo "[Unit]" > ~/.config/systemd/user/cyd-klipper-serial.service +echo "Description=CYD Klipper serial server" >> ~/.config/systemd/user/cyd-klipper-serial.service +echo "After=network.target" >> ~/.config/systemd/user/cyd-klipper-serial.service +echo "" >> ~/.config/systemd/user/cyd-klipper-serial.service +echo "[Service]" >> ~/.config/systemd/user/cyd-klipper-serial.service +echo "ExecStart=python3 $(pwd)/serial_server.py" >> ~/.config/systemd/user/cyd-klipper-serial.service +echo "WorkingDirectory=$(pwd)" >> ~/.config/systemd/user/cyd-klipper-serial.service +echo "Restart=always" >> ~/.config/systemd/user/cyd-klipper-serial.service +echo "" >> ~/.config/systemd/user/cyd-klipper-serial.service +echo "[Install]" >> ~/.config/systemd/user/cyd-klipper-serial.service +echo "WantedBy=multi-user.target" >> ~/.config/systemd/user/cyd-klipper-serial.service + +# Start the service +systemctl --user daemon-reload +systemctl --user enable cyd-klipper-serial +systemctl --user start cyd-klipper-serial \ No newline at end of file diff --git a/serial/requirements.txt b/serial/requirements.txt new file mode 100644 index 0000000..0ac686a --- /dev/null +++ b/serial/requirements.txt @@ -0,0 +1,2 @@ +pyserial +requests \ No newline at end of file diff --git a/serial_server.py b/serial/serial_server.py similarity index 50% rename from serial_server.py rename to serial/serial_server.py index d75f6ae..fadf1f9 100644 --- a/serial_server.py +++ b/serial/serial_server.py @@ -1,16 +1,93 @@ import serial import requests +import os +import serial.tools.list_ports import time -# Define serial port and parameters -SERIAL_PORT = 'COM6' # Change this to your serial port +SERIAL_PORT = 'COM6' BAUD_RATE = 115200 -HOSTNAME = 'http://localhost' # Change to your hostname -PORT = 7125 # Change to your port if necessary +PROTOCOL = "http" +HOSTNAME = 'localhost' +PORT = 80 +def test_request(protocol : str, hostname : str, port : int) -> bool: + try: + print(f"Sending test request to {hostname}:{port}") + response = requests.get(f"{protocol}://{hostname}:{port}/printer/info") + return response.status_code == 200 + except requests.exceptions.RequestException: + return False + +def find_klipper_host() -> bool: + global PROTOCOL, HOSTNAME, PORT + + protocol = PROTOCOL + host = HOSTNAME + port = PORT + + if "KLIPPER_PROTOCOL" in os.environ: + protocol = os.environ["KLIPPER_PROTOCOL"] + + if "KLIPPER_HOST" in os.environ: + host = os.environ["KLIPPER_HOST"] + + if "KLIPPER_PORT" in os.environ: + port = int(os.environ["KLIPPER_PORT"]) + + if test_request(protocol, host, port): + HOSTNAME = host + PORT = port + return True + + port = 80 + + if test_request(protocol, host, port): + HOSTNAME = host + PORT = port + return True + + port = 7125 + + if test_request(protocol, host, port): + HOSTNAME = host + PORT = port + return True + + print("Could not find Klipper host. Please specify the hostname and port using the KLIPPER_HOST and KLIPPER_PORT environment variables.") + return False + +def find_esp32() -> bool: + global SERIAL_PORT + + if "ESP32_SERIAL" in os.environ: + SERIAL_PORT = os.environ["ESP32_SERIAL"] + + if os.path.exists(SERIAL_PORT): + return True + else: + print(f"Specified serial port {SERIAL_PORT} does not exist.") + + possible_devices = [] + + for port in serial.tools.list_ports.comports(): + if port.vid == 0x10C4 and port.pid == 0xEA60: + possible_devices.append(port) + elif port.vid == 0x1A86 and port.pid == 0x7523: + possible_devices.append(port) + + if len(possible_devices) == 1: + SERIAL_PORT = possible_devices[0].device + return True + elif len(possible_devices) > 1: + print("Multiple ESP32 devices found. Please specify the serial port using the ESP32_SERIAL environment variable.") + return False + else: + print("No ESP32 devices found. Please specify the serial port using the ESP32_SERIAL environment variable.") + return False + # --------- # -ser = serial.Serial(SERIAL_PORT, BAUD_RATE, timeout=1) +ser : serial.Serial = None def truncuate(text : str, length : int = 50): length = length - 3 @@ -44,7 +121,7 @@ def main(): timeout_ms = 1000; # Construct the full URL - full_url = f"{HOSTNAME}:{PORT}{url_path}" + full_url = f"{PROTOCOL}://{HOSTNAME}:{PORT}{url_path}" # Make the HTTP request based on the type response = None @@ -82,8 +159,25 @@ def main(): print(f"[LOG] {line}") if __name__ == "__main__": - try: - main() - except KeyboardInterrupt: - print("\nExiting script.") - ser.close() \ No newline at end of file + while True: + try: + if not find_klipper_host(): + time.sleep(5); + continue + + if not find_esp32(): + time.sleep(5); + continue + + ser = serial.Serial(SERIAL_PORT, BAUD_RATE, timeout=1) + main() + except KeyboardInterrupt: + print("\nExiting script.") + ser.close() + break; + except Exception as e: + print(f"An error occurred: {str(e)}") + ser.close() + print("Retrying in 5 seconds...") + time.sleep(5) + \ No newline at end of file diff --git a/serial/uninstall.sh b/serial/uninstall.sh new file mode 100644 index 0000000..02735b2 --- /dev/null +++ b/serial/uninstall.sh @@ -0,0 +1,13 @@ +#!/bin/bash + +if [ "$EUID" -eq 0 ]; then + echo "Please do not run as root" + exit +fi + +systemctl --user stop cyd-klipper-serial +systemctl --user disable cyd-klipper-serial + +rm ~/.config/systemd/user/cyd-klipper-serial.service + +systemctl --user daemon-reload \ No newline at end of file From 1b0ca807e4b3eaaf59bae399863d1b4dff7affcf Mon Sep 17 00:00:00 2001 From: suchmememanyskill <38142618+suchmememanyskill@users.noreply.github.com> Date: Sat, 16 Nov 2024 12:41:06 +0100 Subject: [PATCH 41/63] Fix bed temp set, start octoprint impl --- CYD-Klipper/src/core/data_setup.cpp | 4 + .../serial_klipper_printer_integration.cpp | 6 - .../octoprint_printer_integration.cpp | 157 ++++++++++++++++++ .../octoprint_printer_integration.hpp | 58 +++++++ .../octoprint/octoprint_printer_parsers.cpp | 3 + CYD-Klipper/src/core/printer_integration.hpp | 6 + CYD-Klipper/src/ui/ip_setup.cpp | 95 ++++++----- CYD-Klipper/src/ui/panels/settings_panel.cpp | 23 ++- CYD-Klipper/src/ui/panels/temp_panel.cpp | 2 +- 9 files changed, 293 insertions(+), 61 deletions(-) create mode 100644 CYD-Klipper/src/core/octoprint/octoprint_printer_integration.cpp create mode 100644 CYD-Klipper/src/core/octoprint/octoprint_printer_integration.hpp create mode 100644 CYD-Klipper/src/core/octoprint/octoprint_printer_parsers.cpp diff --git a/CYD-Klipper/src/core/data_setup.cpp b/CYD-Klipper/src/core/data_setup.cpp index cda1c79..2427425 100644 --- a/CYD-Klipper/src/core/data_setup.cpp +++ b/CYD-Klipper/src/core/data_setup.cpp @@ -6,6 +6,7 @@ #include "klipper/klipper_printer_integration.hpp" #include "klipper-serial/serial_klipper_printer_integration.hpp" #include "bambu/bambu_printer_integration.hpp" +#include "octoprint/octoprint_printer_integration.hpp" SemaphoreHandle_t freezeRenderThreadSemaphore, freezeRequestThreadSemaphore; const long data_update_interval = 780; @@ -126,6 +127,9 @@ void data_setup() case PrinterType::PrinterTypeKlipperSerial: available_printers[count++] = new SerialKlipperPrinter(i); break; + case PrinterType::PrinterTypeOctoprint: + available_printers[count++] = new OctoPrinter(i); + break; } } } diff --git a/CYD-Klipper/src/core/klipper-serial/serial_klipper_printer_integration.cpp b/CYD-Klipper/src/core/klipper-serial/serial_klipper_printer_integration.cpp index a071e37..618c0be 100644 --- a/CYD-Klipper/src/core/klipper-serial/serial_klipper_printer_integration.cpp +++ b/CYD-Klipper/src/core/klipper-serial/serial_klipper_printer_integration.cpp @@ -3,12 +3,6 @@ #include #include "../../ui/serial/serial_console.h" -enum HttpRequestType -{ - HttpPost, - HttpGet -}; - void clear_serial_buffer() { while (Serial.available()) diff --git a/CYD-Klipper/src/core/octoprint/octoprint_printer_integration.cpp b/CYD-Klipper/src/core/octoprint/octoprint_printer_integration.cpp new file mode 100644 index 0000000..2a272e3 --- /dev/null +++ b/CYD-Klipper/src/core/octoprint/octoprint_printer_integration.cpp @@ -0,0 +1,157 @@ +#include "octoprint_printer_integration.hpp" +#include "../../conf/global_config.h" +#include +#include +#include +#include + +void configure_http_client(HTTPClient &client, String url_part, bool stream, int timeout, PrinterConfiguration* printer_config) +{ + client.useHTTP10(stream); + + if (timeout > 0){ + client.setTimeout(timeout); + client.setConnectTimeout(timeout); + } + + client.begin("http://" + String(printer_config->klipper_host) + ":" + String(printer_config->klipper_port) + url_part); + + if (printer_config->auth_configured) { + client.addHeader("X-Api-Key", printer_config->klipper_auth); + } +} + +bool OctoPrinter::make_request(const char* endpoint, HttpRequestType requestType, int timeout_ms, bool stream) +{ + HTTPClient client; + + if (timeout_ms <= 0) + { + timeout_ms = 500; + } + + configure_http_client(client, endpoint, stream, timeout_ms, printer_config); + int result = client.GET(); + return result >= 200 && result < 300; +} + +bool OctoPrinter::make_request(JsonDocument& doc, const char* endpoint, HttpRequestType requestType, int timeout_ms, bool stream) +{ + HTTPClient client; + + if (timeout_ms <= 0) + { + timeout_ms = 500; + } + + configure_http_client(client, endpoint, stream, timeout_ms, printer_config); + int result = client.GET(); + + if (result >= 200 && result < 300) + { + auto result = deserializeJson(doc, client.getStream()); + return result == DeserializationError::Ok; + } + + return false; +} + +bool OctoPrinter::move_printer(const char* axis, float amount, bool relative) +{ + return false; +} + +bool OctoPrinter::execute_feature(PrinterFeatures feature) +{ + return false; +} + +bool OctoPrinter::connect() +{ + return false; +} + +bool OctoPrinter::fetch() +{ + return false; +} + +PrinterDataMinimal OctoPrinter::fetch_min() +{ + return {}; +} + +void OctoPrinter::disconnect() +{ + +} + +Macros OctoPrinter::get_macros() +{ + return {}; +} + +int OctoPrinter::get_macros_count() +{ + return 0; +} + +bool OctoPrinter::execute_macro(const char* macro) +{ + return false; +} + +PowerDevices OctoPrinter::get_power_devices() +{ + return {}; +} + +int OctoPrinter::get_power_devices_count() +{ + return 0; +} + +bool OctoPrinter::set_power_device_state(const char* device_name, bool state) +{ + return false; +} + +Files OctoPrinter::get_files() +{ + return {}; +} + +bool OctoPrinter::start_file(const char* filename) +{ + return false; +} + +Thumbnail OctoPrinter::get_32_32_png_image_thumbnail(const char* gcode_filename) +{ + return {}; +} + +bool OctoPrinter::set_target_temperature(PrinterTemperatureDevice device, unsigned int temperature) +{ + return false; +} + +OctoConnectionStatus connection_test_octoprint(PrinterConfiguration* config) +{ + HTTPClient client; + configure_http_client(client, "/api/version", false, 1000, config); + + int http_code = client.GET(); + if (http_code == 200) + { + return OctoConnectionStatus::OctoConnectOk; + } + else if (http_code == 401 || http_code == 403) + { + return OctoConnectionStatus::OctoConnectKeyFail; + } + else + { + return OctoConnectionStatus::OctoConnectFail; + } +} \ No newline at end of file diff --git a/CYD-Klipper/src/core/octoprint/octoprint_printer_integration.hpp b/CYD-Klipper/src/core/octoprint/octoprint_printer_integration.hpp new file mode 100644 index 0000000..acea923 --- /dev/null +++ b/CYD-Klipper/src/core/octoprint/octoprint_printer_integration.hpp @@ -0,0 +1,58 @@ +#include "../printer_integration.hpp" +#include +#include + +class OctoPrinter : public BasePrinter +{ + protected: + bool make_request(const char* endpoint, HttpRequestType requestType = HttpRequestType::HttpGet, int timeout_ms = 1000, bool stream = true); + bool make_request(JsonDocument& doc, const char* endpoint, HttpRequestType requestType = HttpRequestType::HttpGet, int timeout_ms = 1000, bool stream = true); + + public: + OctoPrinter(int index) : BasePrinter(index) + { + supported_features = PrinterFeatureHome + | PrinterFeatureDisableSteppers + | PrinterFeaturePause + | PrinterFeatureResume + | PrinterFeatureStop + | PrinterFeatureExtrude + | PrinterFeatureRetract + | PrinterFeatureCooldown + | PrinterFeatureRetryError; + + supported_temperature_devices = PrinterTemperatureDeviceBed + | PrinterTemperatureDeviceNozzle1; + + printer_data.error_screen_features = PrinterFeatureRetryError; + } + + bool move_printer(const char* axis, float amount, bool relative); + bool execute_feature(PrinterFeatures feature); + bool connect(); + bool fetch(); + PrinterDataMinimal fetch_min(); + void disconnect(); + + Macros get_macros(); + int get_macros_count(); + bool execute_macro(const char* macro); + + PowerDevices get_power_devices(); + int get_power_devices_count(); + bool set_power_device_state(const char* device_name, bool state); + + Files get_files(); + bool start_file(const char* filename); + + Thumbnail get_32_32_png_image_thumbnail(const char* gcode_filename); + bool set_target_temperature(PrinterTemperatureDevice device, unsigned int temperature); +}; + +enum OctoConnectionStatus { + OctoConnectFail = 0, + OctoConnectOk = 1, + OctoConnectKeyFail = 2, +}; + +OctoConnectionStatus connection_test_octoprint(PrinterConfiguration* config); \ No newline at end of file diff --git a/CYD-Klipper/src/core/octoprint/octoprint_printer_parsers.cpp b/CYD-Klipper/src/core/octoprint/octoprint_printer_parsers.cpp new file mode 100644 index 0000000..c3b716e --- /dev/null +++ b/CYD-Klipper/src/core/octoprint/octoprint_printer_parsers.cpp @@ -0,0 +1,3 @@ +#include "../printer_integration.hpp" +#include "octoprint_printer_integration.hpp" +#include \ No newline at end of file diff --git a/CYD-Klipper/src/core/printer_integration.hpp b/CYD-Klipper/src/core/printer_integration.hpp index f90af31..058caf5 100644 --- a/CYD-Klipper/src/core/printer_integration.hpp +++ b/CYD-Klipper/src/core/printer_integration.hpp @@ -134,6 +134,12 @@ typedef struct { unsigned char* png; } Thumbnail; +enum HttpRequestType +{ + HttpPost, + HttpGet +}; + class BasePrinter { protected: diff --git a/CYD-Klipper/src/ui/ip_setup.cpp b/CYD-Klipper/src/ui/ip_setup.cpp index 738cd20..ad893ca 100644 --- a/CYD-Klipper/src/ui/ip_setup.cpp +++ b/CYD-Klipper/src/ui/ip_setup.cpp @@ -12,6 +12,7 @@ #include "../core/bambu/bambu_printer_integration.hpp" #include "../core/screen_driver.h" #include "../core/klipper-serial/serial_klipper_printer_integration.hpp" +#include "../core/octoprint/octoprint_printer_integration.hpp" void show_ip_entry(); void choose_printer_type(); @@ -217,10 +218,23 @@ static void keyboard_event_ip_entry(lv_event_t * e) { lv_label_set_text(main_label, "Incorrect IP/Access code"); } } - } - else - { - return; + else if (type == PrinterType::PrinterTypeOctoprint) + { + OctoConnectionStatus octo_status = connection_test_octoprint(&global_config.printer_config[global_config.printer_index]); + if (octo_status == OctoConnectionStatus::OctoConnectOk) + { + global_config.printer_config[global_config.printer_index].setup_complete = true; + write_global_config(); + } + else if (octo_status == OctoConnectionStatus::OctoConnectKeyFail) + { + lv_label_set_text(main_label, "Incorrect API key"); + } + else + { + lv_label_set_text(main_label, "Failed to connect"); + } + } } } @@ -249,7 +263,6 @@ void show_ip_entry() lv_obj_set_flex_grow(button_back, 1); lv_obj_add_event_cb(button_back, return_to_choose_printer_type, LV_EVENT_CLICKED, NULL); - lv_obj_t * label = lv_label_create(button_back); lv_label_set_text(label, LV_SYMBOL_LEFT); lv_obj_center(label); @@ -359,6 +372,13 @@ void show_ip_entry() lv_textarea_set_placeholder_text(port_entry, "Access code"); lv_textarea_set_placeholder_text(auth_entry, "Printer serial number"); break; + case PrinterType::PrinterTypeOctoprint: + lv_label_set_text(main_label, "Octoprint Setup"); + lv_textarea_set_max_length(port_entry, 5); + lv_textarea_set_placeholder_text(host_entry, "Octoprint Host"); + lv_textarea_set_placeholder_text(port_entry, "Port"); + lv_textarea_set_placeholder_text(auth_entry, "API key"); + break; case PrinterType::PrinterTypeKlipperSerial: lv_label_set_text(main_label, "Klipper (Serial) Setup"); lv_obj_del(ip_row); @@ -394,6 +414,12 @@ static void printer_type_serial_klipper(lv_event_t * e) show_ip_entry(); } +static void printer_type_octoprint(lv_event_t * e) +{ + global_config.printer_config[global_config.printer_index].printer_type = PrinterType::PrinterTypeOctoprint; + show_ip_entry(); +} + static void return_to_wifi_configuration(lv_event_t * e) { global_config.wifi_configuration_skipped = false; @@ -401,6 +427,22 @@ static void return_to_wifi_configuration(lv_event_t * e) ESP.restart(); } +static inline void create_printer_type_button(lv_obj_t * root, const char * label, lv_event_cb_t event, bool require_wifi = true) +{ + if (require_wifi && !global_config.wifi_configured) + { + return; + } + + lv_obj_t * btn = lv_btn_create(root); + lv_obj_set_size(btn, CYD_SCREEN_WIDTH_PX - CYD_SCREEN_GAP_PX * 2, CYD_SCREEN_MIN_BUTTON_HEIGHT_PX); + lv_obj_add_event_cb(btn, event, LV_EVENT_CLICKED, NULL); + + lv_obj_t * label_obj = lv_label_create(btn); + lv_label_set_text(label_obj, label); + lv_obj_center(label_obj); +} + void choose_printer_type() { lv_obj_t * btn; @@ -418,45 +460,14 @@ void choose_printer_type() lv_obj_t * label = lv_label_create(root); lv_label_set_text(label, "Choose printer type"); - if (global_config.wifi_configured) - { - btn = lv_btn_create(root); - lv_obj_set_size(btn, CYD_SCREEN_WIDTH_PX - CYD_SCREEN_GAP_PX * 2, CYD_SCREEN_MIN_BUTTON_HEIGHT_PX); - lv_obj_add_event_cb(btn, printer_type_klipper, LV_EVENT_CLICKED, NULL); - - label = lv_label_create(btn); - lv_label_set_text(label, "Klipper"); - lv_obj_center(label); - } - - btn = lv_btn_create(root); - lv_obj_set_size(btn, CYD_SCREEN_WIDTH_PX - CYD_SCREEN_GAP_PX * 2, CYD_SCREEN_MIN_BUTTON_HEIGHT_PX); - lv_obj_add_event_cb(btn, printer_type_serial_klipper, LV_EVENT_CLICKED, NULL); - - label = lv_label_create(btn); - lv_label_set_text(label, "Klipper (Serial)"); - lv_obj_center(label); - - if (global_config.wifi_configured) - { - btn = lv_btn_create(root); - lv_obj_set_size(btn, CYD_SCREEN_WIDTH_PX - CYD_SCREEN_GAP_PX * 2, CYD_SCREEN_MIN_BUTTON_HEIGHT_PX); - lv_obj_add_event_cb(btn, printer_type_bambu_local, LV_EVENT_CLICKED, NULL); - - label = lv_label_create(btn); - lv_label_set_text(label, "Bambu (Local)"); - lv_obj_center(label); - } - + create_printer_type_button(root, "Klipper", printer_type_klipper); + create_printer_type_button(root, "Klipper (Serial)", printer_type_serial_klipper, false); + create_printer_type_button(root, "Bambu (Local)", printer_type_bambu_local); + create_printer_type_button(root, "Octoprint", printer_type_octoprint); + if (global_config.wifi_configuration_skipped) { - btn = lv_btn_create(root); - lv_obj_set_size(btn, CYD_SCREEN_WIDTH_PX - CYD_SCREEN_GAP_PX * 2, CYD_SCREEN_MIN_BUTTON_HEIGHT_PX); - lv_obj_add_event_cb(btn, return_to_wifi_configuration, LV_EVENT_CLICKED, NULL); - - label = lv_label_create(btn); - lv_label_set_text(label, "Return to WiFi configuration"); - lv_obj_center(label); + create_printer_type_button(root, "Return to WiFi configuration", return_to_wifi_configuration, false); } } diff --git a/CYD-Klipper/src/ui/panels/settings_panel.cpp b/CYD-Klipper/src/ui/panels/settings_panel.cpp index d7865b3..204626b 100644 --- a/CYD-Klipper/src/ui/panels/settings_panel.cpp +++ b/CYD-Klipper/src/ui/panels/settings_panel.cpp @@ -17,7 +17,7 @@ static void invert_color_switch(lv_event_t * e){ auto state = lv_obj_get_state(lv_event_get_target(e)); bool checked = (state & LV_STATE_CHECKED == LV_STATE_CHECKED); - get_current_printer()->printer_config->invert_colors = checked; + global_config.printer_config[global_config.printer_index].invert_colors = checked; write_global_config(); set_invert_display(); } @@ -184,17 +184,6 @@ void settings_section_theming(lv_obj_t* panel) lv_label_set_text(label, "Theming"); lv_create_custom_menu_dropdown("Theme", panel, theme_dropdown, "Blue\nGreen\nLime\nGrey\nYellow\nOrange\nRed\nPurple", get_current_printer()->printer_config->color_scheme, NULL, PRINTER_SPECIFIC_SETTING); - -#ifndef CYD_SCREEN_DISABLE_INVERT_COLORS - lv_create_custom_menu_switch("Invert Colors", panel, invert_color_switch, get_current_printer()->printer_config->invert_colors, NULL, (global_config.multi_printer_mode) ? "Stored per printer" - #ifdef CYD_SCREEN_DRIVER_ESP32_2432S028R - "\nIntended for the 2.8\" dual USB model screen" : "Intended for the 2.8\" dual USB model screen" - #else - : NULL - #endif - ); -#endif // CYD_SCREEN_DISABLE_INVERT_COLORS - lv_create_custom_menu_switch("Light Mode", panel, light_mode_switch, get_current_printer()->printer_config->light_mode, NULL, PRINTER_SPECIFIC_SETTING); } @@ -251,6 +240,16 @@ void settings_section_device(lv_obj_t* panel) lv_create_custom_menu_dropdown("Brightness", panel, brightness_dropdown, brightness_options, brightness_settings_index); +#ifndef CYD_SCREEN_DISABLE_INVERT_COLORS + lv_create_custom_menu_switch("Invert Colors", panel, invert_color_switch, global_config.printer_config[global_config.printer_index].invert_colors, NULL, (global_config.multi_printer_mode) ? "Stored per printer" + #ifdef CYD_SCREEN_DRIVER_ESP32_2432S028R + "\nIntended for the 2.8\" dual USB model screen" : "Intended for the 2.8\" dual USB model screen" + #else + : NULL + #endif + ); +#endif // CYD_SCREEN_DISABLE_INVERT_COLORS + #ifdef CYD_SCREEN_DRIVER_ESP32_2432S028R lv_create_custom_menu_switch("Screen Color Fix", panel, dualusb_screen_fix_switch, global_config.display_mode, NULL, "ONLY for the 2.8\" dual USB model screen"); #endif diff --git a/CYD-Klipper/src/ui/panels/temp_panel.cpp b/CYD-Klipper/src/ui/panels/temp_panel.cpp index 0d1045d..bbdfc9a 100644 --- a/CYD-Klipper/src/ui/panels/temp_panel.cpp +++ b/CYD-Klipper/src/ui/panels/temp_panel.cpp @@ -154,7 +154,7 @@ static void set_temp_via_preset(lv_event_t * e){ return; } - current_printer_set_target_temperature(TARGET_HOTEND_CONFIG_3 + current_printer_set_target_temperature(target <= TARGET_HOTEND_CONFIG_3 ? PrinterTemperatureDevice::PrinterTemperatureDeviceNozzle1 : PrinterTemperatureDevice::PrinterTemperatureDeviceBed , value); From 8521664a697a7d127c116d3dc625622f3236f15e Mon Sep 17 00:00:00 2001 From: suchmememanyskill <38142618+suchmememanyskill@users.noreply.github.com> Date: Sat, 16 Nov 2024 22:51:17 +0100 Subject: [PATCH 42/63] Fetch data from octoprint --- .../src/core/bambu/bambu_printer_parsers.cpp | 2 +- .../octoprint_printer_integration.cpp | 119 ++++++++++++++++-- .../octoprint_printer_integration.hpp | 13 +- .../octoprint/octoprint_printer_parsers.cpp | 103 ++++++++++++++- CYD-Klipper/src/core/printer_integration.hpp | 2 + CYD-Klipper/src/ui/ip_setup.cpp | 2 +- CYD-Klipper/src/ui/panels/macros_panel.cpp | 11 +- 7 files changed, 236 insertions(+), 16 deletions(-) diff --git a/CYD-Klipper/src/core/bambu/bambu_printer_parsers.cpp b/CYD-Klipper/src/core/bambu/bambu_printer_parsers.cpp index 3add9df..60bed9e 100644 --- a/CYD-Klipper/src/core/bambu/bambu_printer_parsers.cpp +++ b/CYD-Klipper/src/core/bambu/bambu_printer_parsers.cpp @@ -63,7 +63,7 @@ void BambuPrinter::parse_state(JsonDocument& in) if (print.containsKey("nozzle_temper")) { printer_data.temperatures[PrinterTemperatureDeviceIndexNozzle1] = print["nozzle_temper"]; - printer_data.can_extrude = printer_data.temperatures[PrinterTemperatureDeviceIndexNozzle1] > 175; + printer_data.can_extrude = printer_data.temperatures[PrinterTemperatureDeviceIndexNozzle1] >= MIN_EXTRUDER_EXTRUDE_TEMP; } if (print.containsKey("nozzle_target_temper")) diff --git a/CYD-Klipper/src/core/octoprint/octoprint_printer_integration.cpp b/CYD-Klipper/src/core/octoprint/octoprint_printer_integration.cpp index 2a272e3..d8587d8 100644 --- a/CYD-Klipper/src/core/octoprint/octoprint_printer_integration.cpp +++ b/CYD-Klipper/src/core/octoprint/octoprint_printer_integration.cpp @@ -5,6 +5,9 @@ #include #include +const char* COMMAND_CONNECT = "{\"command\":\"connect\"}"; +const char* COMMAND_DISCONNECT = "{\"command\":\"disconnect\"}"; + void configure_http_client(HTTPClient &client, String url_part, bool stream, int timeout, PrinterConfiguration* printer_config) { client.useHTTP10(stream); @@ -21,7 +24,7 @@ void configure_http_client(HTTPClient &client, String url_part, bool stream, int } } -bool OctoPrinter::make_request(const char* endpoint, HttpRequestType requestType, int timeout_ms, bool stream) +bool OctoPrinter::get_request(const char* endpoint, int timeout_ms, bool stream) { HTTPClient client; @@ -35,7 +38,7 @@ bool OctoPrinter::make_request(const char* endpoint, HttpRequestType requestType return result >= 200 && result < 300; } -bool OctoPrinter::make_request(JsonDocument& doc, const char* endpoint, HttpRequestType requestType, int timeout_ms, bool stream) +bool OctoPrinter::post_request(const char* endpoint, const char* body, int timeout_ms, bool stream) { HTTPClient client; @@ -45,14 +48,18 @@ bool OctoPrinter::make_request(JsonDocument& doc, const char* endpoint, HttpRequ } configure_http_client(client, endpoint, stream, timeout_ms, printer_config); - int result = client.GET(); - if (result >= 200 && result < 300) + if (body[0] == '{' || body[0] == '[') { - auto result = deserializeJson(doc, client.getStream()); - return result == DeserializationError::Ok; + client.addHeader("Content-Type", "application/json"); } + int result = client.POST(body); + return result >= 200 && result < 300; +} + +bool OctoPrinter::send_gcode(const char* gcode, bool wait) +{ return false; } @@ -63,17 +70,77 @@ bool OctoPrinter::move_printer(const char* axis, float amount, bool relative) bool OctoPrinter::execute_feature(PrinterFeatures feature) { + switch (feature) + { + case PrinterFeatureRetryError: + if (no_printer) + { + bool a = post_request("/api/connection", COMMAND_CONNECT); + LOG_F(("Retry error: %d\n", a)); + return a; + } + default: + LOG_F(("Unsupported printer feature %d", feature)); + break; + } + return false; } bool OctoPrinter::connect() { - return false; + return connection_test_octoprint(printer_config) == OctoConnectionStatus::OctoConnectOk; } bool OctoPrinter::fetch() { - return false; + HTTPClient client; + HTTPClient client2; + configure_http_client(client, "/api/printer", true, 1000, printer_config); + + int http_code = client.GET(); + + if (http_code == 200) + { + no_printer = false; + request_consecutive_fail_count = 0; + JsonDocument doc; + deserializeJson(doc, client.getStream()); + parse_printer_state(doc); + + doc.clear(); + configure_http_client(client2, "/api/job", true, 1000, printer_config); + if (client2.GET() == 200) + { + deserializeJson(doc, client2.getStream()); + parse_job_state(doc); + } + else + { + printer_data.state = PrinterStateOffline; + return false; + } + } + else if (http_code == 409) + { + no_printer = true; + JsonDocument doc; + deserializeJson(doc, client.getStream()); + parse_error(doc); + } + else + { + request_consecutive_fail_count++; + LOG_LN("Failed to fetch printer data"); + + if (request_consecutive_fail_count >= 5) + { + printer_data.state = PrinterStateOffline; + return false; + } + } + + return true; } PrinterDataMinimal OctoPrinter::fetch_min() @@ -86,18 +153,50 @@ void OctoPrinter::disconnect() } +const char* MACRO_AUTOLEVEL = "Auto-Level (G28+G29)"; +const char* MACRO_DISCONNECT = "Disconnect printer"; + Macros OctoPrinter::get_macros() { - return {}; + if (printer_data.state == PrinterStatePrinting || printer_data.state == PrinterStateOffline) + { + Macros macros = {0}; + macros.success = false; + return macros; + } + + Macros macros = {0}; + macros.count = 2; + macros.macros = (char **)malloc(sizeof(char *) * macros.count); + macros.macros[0] = (char *)malloc(strlen(MACRO_AUTOLEVEL) + 1); + strcpy(macros.macros[0], MACRO_AUTOLEVEL); + macros.macros[1] = (char *)malloc(strlen(MACRO_DISCONNECT) + 1); + strcpy(macros.macros[1], MACRO_DISCONNECT); + macros.success = true; + return macros; } int OctoPrinter::get_macros_count() { - return 0; + return (printer_data.state == PrinterStatePrinting || printer_data.state == PrinterStateOffline) ? 0 : 2; } bool OctoPrinter::execute_macro(const char* macro) { + if (strcmp(macro, MACRO_AUTOLEVEL) == 0) + { + return send_gcode("G28\nG29"); + } + else if (strcmp(macro, MACRO_DISCONNECT) == 0) + { + if (printer_data.state == PrinterStatePrinting || printer_data.state == PrinterStateOffline) + { + return false; + } + + return post_request("/api/connection", COMMAND_DISCONNECT); + } + return false; } diff --git a/CYD-Klipper/src/core/octoprint/octoprint_printer_integration.hpp b/CYD-Klipper/src/core/octoprint/octoprint_printer_integration.hpp index acea923..43f0183 100644 --- a/CYD-Klipper/src/core/octoprint/octoprint_printer_integration.hpp +++ b/CYD-Klipper/src/core/octoprint/octoprint_printer_integration.hpp @@ -5,8 +5,15 @@ class OctoPrinter : public BasePrinter { protected: - bool make_request(const char* endpoint, HttpRequestType requestType = HttpRequestType::HttpGet, int timeout_ms = 1000, bool stream = true); - bool make_request(JsonDocument& doc, const char* endpoint, HttpRequestType requestType = HttpRequestType::HttpGet, int timeout_ms = 1000, bool stream = true); + bool no_printer = false; + unsigned char request_consecutive_fail_count{}; + + void parse_printer_state(JsonDocument& in); + void parse_job_state(JsonDocument& in); + void parse_error(JsonDocument& in); + + bool get_request(const char* endpoint, int timeout_ms = 1000, bool stream = true); + bool post_request(const char* endpoint, const char* body, int timeout_ms = 1000, bool stream = false); public: OctoPrinter(int index) : BasePrinter(index) @@ -47,6 +54,8 @@ class OctoPrinter : public BasePrinter Thumbnail get_32_32_png_image_thumbnail(const char* gcode_filename); bool set_target_temperature(PrinterTemperatureDevice device, unsigned int temperature); + + bool send_gcode(const char* gcode, bool wait = true); }; enum OctoConnectionStatus { diff --git a/CYD-Klipper/src/core/octoprint/octoprint_printer_parsers.cpp b/CYD-Klipper/src/core/octoprint/octoprint_printer_parsers.cpp index c3b716e..1a43415 100644 --- a/CYD-Klipper/src/core/octoprint/octoprint_printer_parsers.cpp +++ b/CYD-Klipper/src/core/octoprint/octoprint_printer_parsers.cpp @@ -1,3 +1,104 @@ #include "../printer_integration.hpp" #include "octoprint_printer_integration.hpp" -#include \ No newline at end of file +#include + +void OctoPrinter::parse_printer_state(JsonDocument& in) +{ + auto flags = in["state"]["flags"]; + auto text = in["state"]["text"]; + + bool cancelling = flags["cancelling"]; + bool closedOrError = flags["closedOrError"]; + bool error = flags["error"]; + bool finishing = flags["finishing"]; + bool operational = flags["operational"]; + bool paused = flags["paused"]; + bool pausing = flags["pausing"]; + bool printing = flags["printing"]; + bool ready = flags["ready"]; + bool resuming = flags["resuming"]; + bool sdReady = flags["sdReady"]; + + if (printing || resuming) + { + printer_data.state = PrinterState::PrinterStatePrinting; + } + else if (pausing || paused) + { + printer_data.state = PrinterState::PrinterStatePaused; + } + else if (cancelling || finishing || ready) + { + printer_data.state = PrinterState::PrinterStateIdle; + } + else + { + if (text != NULL && (printer_data.state_message == NULL || strcmp(printer_data.state_message, text))) + { + printer_data.state_message = (char *)malloc(strlen(text) + 1); + strcpy(printer_data.state_message, text); + } + + printer_data.state = PrinterState::PrinterStateError; + } + + auto temperature = in["temperature"]; + + if (temperature.containsKey("bed")) + { + printer_data.temperatures[PrinterTemperatureDeviceIndexBed] = temperature["bed"]["actual"]; + printer_data.target_temperatures[PrinterTemperatureDeviceIndexBed] = temperature["bed"]["target"]; + } + + if (temperature.containsKey("tool0")) + { + printer_data.temperatures[PrinterTemperatureDeviceIndexNozzle1] = temperature["tool0"]["actual"]; + printer_data.target_temperatures[PrinterTemperatureDeviceIndexNozzle1] = temperature["tool0"]["target"]; + } + + printer_data.can_extrude = printer_data.temperatures[PrinterTemperatureDeviceIndexNozzle1] >= MIN_EXTRUDER_EXTRUDE_TEMP; + printer_data.homed_axis = true; +} + +void OctoPrinter::parse_job_state(JsonDocument& in) +{ + auto job = in["job"]; + + if (job.containsKey("file")) + { + const char* name = job["file"]["name"]; + + if (name != NULL && (printer_data.print_filename == NULL || strcmp(printer_data.print_filename, name))) + { + printer_data.print_filename = (char *)malloc(strlen(name) + 1); + strcpy(printer_data.print_filename, name); + } + } + + if (job.containsKey("filament") && job["filament"] != NULL && job["filament"].containsKey("tool0")) + { + printer_data.filament_used_mm = job["filament"]["tool0"]["length"]; + } + + auto progress = in["progress"]; + float completion = progress["completion"]; + printer_data.print_progress = completion / 100; + printer_data.elapsed_time_s = progress["printTime"]; + printer_data.printed_time_s = progress["printTime"]; + printer_data.remaining_time_s = progress["printTimeLeft"]; +} + +void OctoPrinter::parse_error(JsonDocument& in) +{ + const char* error = in["error"]; + if (error != NULL) + { + printer_data.state = PrinterState::PrinterStateError; + + if (printer_data.state_message == NULL || strcmp(printer_data.state_message, error)) + { + printer_data.state_message = (char *)malloc(strlen(error) + 1); + strcpy(printer_data.state_message, error); + } + } +} \ No newline at end of file diff --git a/CYD-Klipper/src/core/printer_integration.hpp b/CYD-Klipper/src/core/printer_integration.hpp index 058caf5..acab184 100644 --- a/CYD-Klipper/src/core/printer_integration.hpp +++ b/CYD-Klipper/src/core/printer_integration.hpp @@ -2,6 +2,8 @@ #include "../conf/global_config.h" #include +#define MIN_EXTRUDER_EXTRUDE_TEMP 175 + enum PrinterFeatures { PrinterFeatureRestart = BIT(0), PrinterFeatureFirmwareRestart = BIT(1), diff --git a/CYD-Klipper/src/ui/ip_setup.cpp b/CYD-Klipper/src/ui/ip_setup.cpp index ad893ca..32c310d 100644 --- a/CYD-Klipper/src/ui/ip_setup.cpp +++ b/CYD-Klipper/src/ui/ip_setup.cpp @@ -461,7 +461,7 @@ void choose_printer_type() lv_label_set_text(label, "Choose printer type"); create_printer_type_button(root, "Klipper", printer_type_klipper); - create_printer_type_button(root, "Klipper (Serial)", printer_type_serial_klipper, false); + create_printer_type_button(root, "Klipper (Serial/USB)", printer_type_serial_klipper, false); create_printer_type_button(root, "Bambu (Local)", printer_type_bambu_local); create_printer_type_button(root, "Octoprint", printer_type_octoprint); diff --git a/CYD-Klipper/src/ui/panels/macros_panel.cpp b/CYD-Klipper/src/ui/panels/macros_panel.cpp index eaccf58..49f5ded 100644 --- a/CYD-Klipper/src/ui/panels/macros_panel.cpp +++ b/CYD-Klipper/src/ui/panels/macros_panel.cpp @@ -30,7 +30,16 @@ void macros_panel_init(lv_obj_t* panel) { if (macros_count <= 0){ label = lv_label_create(root_panel); - lv_label_set_text(label, "No macros found.\nMacros with the description\n\"CYD_SCREEN_MACRO\"\nwill show up here."); + if (get_current_printer()->printer_config->printer_type == PrinterType::PrinterTypeKlipper + || get_current_printer()->printer_config->printer_type == PrinterType::PrinterTypeKlipper) + { + lv_label_set_text(label, "No macros found.\nMacros with the description\n\"CYD_SCREEN_MACRO\"\nwill show up here."); + } + else + { + lv_label_set_text(label, "No macros found."); + } + if (power_count <= 0){ lv_layout_flex_column(root_panel, LV_FLEX_ALIGN_CENTER); From 0c364ec5971e5b541f65d07b9b3070db9970f8f0 Mon Sep 17 00:00:00 2001 From: suchmememanyskill <38142618+suchmememanyskill@users.noreply.github.com> Date: Wed, 27 Nov 2024 22:53:35 +0100 Subject: [PATCH 43/63] Lower cpu usage --- serial/serial_server.py | 93 ++++++++++++++++++++--------------------- 1 file changed, 46 insertions(+), 47 deletions(-) diff --git a/serial/serial_server.py b/serial/serial_server.py index fadf1f9..52f38f0 100644 --- a/serial/serial_server.py +++ b/serial/serial_server.py @@ -105,58 +105,57 @@ def write(text : str, write : bool): def main(): while True: # Read a line from the serial port - if ser.in_waiting > 0: - line = ser.readline().decode('utf-8').strip() - if line.startswith("HTTP_REQUEST") or line.startswith("HTTP_BINARY"): - print(f">>> {line}") - # Parse the parameters - try: - parts = line.split(' ', 3) - timeout_ms, request_type, url_path = int(parts[1]), parts[2], parts[3] + line = ser.readline().decode('utf-8').strip() + if line.startswith("HTTP_REQUEST") or line.startswith("HTTP_BINARY"): + print(f">>> {line}") + # Parse the parameters + try: + parts = line.split(' ', 3) + timeout_ms, request_type, url_path = int(parts[1]), parts[2], parts[3] - ignore_timeout = timeout_ms <= 0 - binary = line.startswith("HTTP_BINARY") + ignore_timeout = timeout_ms <= 0 + binary = line.startswith("HTTP_BINARY") - if ignore_timeout: - timeout_ms = 1000; + if ignore_timeout: + timeout_ms = 1000; - # Construct the full URL - full_url = f"{PROTOCOL}://{HOSTNAME}:{PORT}{url_path}" + # Construct the full URL + full_url = f"{PROTOCOL}://{HOSTNAME}:{PORT}{url_path}" - # Make the HTTP request based on the type - response = None - if request_type.upper() == "GET": - response = requests.get(full_url, timeout=timeout_ms / 1000) - elif request_type.upper() == "POST": - response = requests.post(full_url, timeout=timeout_ms / 1000) - else: - write("400 Unsupported request type", not ignore_timeout) - continue - - # Send response back over serial - if response != None: - if binary: - if response.status_code != 200: - write("00000000", not ignore_timeout) - else: - length = len(response.content) - ser.write(f"{length:>08}".encode('utf-8')) - ser.write(response.content) - print(f"<<< (Binary data of {length} bytes)") + # Make the HTTP request based on the type + response = None + if request_type.upper() == "GET": + response = requests.get(full_url, timeout=timeout_ms / 1000) + elif request_type.upper() == "POST": + response = requests.post(full_url, timeout=timeout_ms / 1000) + else: + write("400 Unsupported request type", not ignore_timeout) + continue + + # Send response back over serial + if response != None: + if binary: + if response.status_code != 200: + write("00000000", not ignore_timeout) else: - status_code = response.status_code - body = response.text.replace('\n', ' ') # Trim and sanitize body for serial - message = f"{status_code} {body}" - write(message, not ignore_timeout) - except (IndexError, ValueError) as e: - write(f"400 Malformed request {str(e)}", not ignore_timeout) - except requests.exceptions.ReadTimeout as e: - print("Request timed out.") - pass - except requests.exceptions.RequestException as e: - write("500 Request failed", not ignore_timeout) - else: - print(f"[LOG] {line}") + length = len(response.content) + ser.write(f"{length:>08}".encode('utf-8')) + ser.write(response.content) + print(f"<<< (Binary data of {length} bytes)") + else: + status_code = response.status_code + body = response.text.replace('\n', ' ') # Trim and sanitize body for serial + message = f"{status_code} {body}" + write(message, not ignore_timeout) + except (IndexError, ValueError) as e: + write(f"400 Malformed request {str(e)}", not ignore_timeout) + except requests.exceptions.ReadTimeout as e: + print("Request timed out.") + pass + except requests.exceptions.RequestException as e: + write("500 Request failed", not ignore_timeout) + else: + print(f"[LOG] {line}") if __name__ == "__main__": while True: From 15dedb7255d14964802f6a2af1e3f1c3a99ad27c Mon Sep 17 00:00:00 2001 From: Sims <38142618+suchmememanyskill@users.noreply.github.com> Date: Wed, 4 Dec 2024 08:27:41 +0100 Subject: [PATCH 44/63] Octoprint: Add more commands --- .../octoprint_printer_integration.cpp | 56 ++++++++++++++++++- 1 file changed, 54 insertions(+), 2 deletions(-) diff --git a/CYD-Klipper/src/core/octoprint/octoprint_printer_integration.cpp b/CYD-Klipper/src/core/octoprint/octoprint_printer_integration.cpp index d8587d8..99f8881 100644 --- a/CYD-Klipper/src/core/octoprint/octoprint_printer_integration.cpp +++ b/CYD-Klipper/src/core/octoprint/octoprint_printer_integration.cpp @@ -7,6 +7,7 @@ const char* COMMAND_CONNECT = "{\"command\":\"connect\"}"; const char* COMMAND_DISCONNECT = "{\"command\":\"disconnect\"}"; +const char* COMMAND_HOME = "{\"command\":\"home\",\"axes\":[\"x\",\"y\",\"z\"]}"; void configure_http_client(HTTPClient &client, String url_part, bool stream, int timeout, PrinterConfiguration* printer_config) { @@ -58,14 +59,61 @@ bool OctoPrinter::post_request(const char* endpoint, const char* body, int timeo return result >= 200 && result < 300; } +// TODO: Make array in the first place, don't split on \n bool OctoPrinter::send_gcode(const char* gcode, bool wait) { - return false; + JsonDocument doc; + JsonArray array = doc["commands"].to(); + const char* last_line_start = gcode; + char out_buff[512]; + + for (const char* iter = gcode;; iter++) + { + if (*iter == '\n' || *iter == '\0') + { + const char *prev_char = iter - 1; + + if (iter == last_line_start) + { + continue; + } + + char* buff = (char*)malloc(sizeof(char) * (prev_char - gcode) + 1); + buff[prev_char - gcode] = '\0'; + memcpy(buff, last_line_start, prev_char - gcode); + last_line_start = iter + 1; + array.add(last_line_start); + } + + if (*iter == '\0') + { + break; + } + } + + if (serializeJson(doc, out_buff, 512) != 512) + { + return false; + } + + return post_request("/api/printer/command/custom", out_buff); } bool OctoPrinter::move_printer(const char* axis, float amount, bool relative) { - return false; + JsonDocument doc; + char out_buff[512]; + + doc["command"] = "jog"; + doc[axis] = amount; + doc["absolute"] = !relative; + + if (serializeJson(doc, out_buff, 512) != 512) + { + return false; + } + + return post_request("/api/printer/printhead", out_buff); } bool OctoPrinter::execute_feature(PrinterFeatures feature) @@ -79,6 +127,10 @@ bool OctoPrinter::execute_feature(PrinterFeatures feature) LOG_F(("Retry error: %d\n", a)); return a; } + case PrinterFeatureHome: + return post_request("/api/printer/printhead", COMMAND_HOME); + case PrinterFeatureDisableSteppers: + return send_gcode("M18"); default: LOG_F(("Unsupported printer feature %d", feature)); break; From fcd133eb328785662dc2037a10650dd838792d60 Mon Sep 17 00:00:00 2001 From: Sims <38142618+suchmememanyskill@users.noreply.github.com> Date: Wed, 11 Dec 2024 08:00:45 +0100 Subject: [PATCH 45/63] Better split impl --- .../octoprint/octoprint_printer_integration.cpp | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/CYD-Klipper/src/core/octoprint/octoprint_printer_integration.cpp b/CYD-Klipper/src/core/octoprint/octoprint_printer_integration.cpp index 99f8881..72846bb 100644 --- a/CYD-Klipper/src/core/octoprint/octoprint_printer_integration.cpp +++ b/CYD-Klipper/src/core/octoprint/octoprint_printer_integration.cpp @@ -59,7 +59,6 @@ bool OctoPrinter::post_request(const char* endpoint, const char* body, int timeo return result >= 200 && result < 300; } -// TODO: Make array in the first place, don't split on \n bool OctoPrinter::send_gcode(const char* gcode, bool wait) { JsonDocument doc; @@ -73,16 +72,15 @@ bool OctoPrinter::send_gcode(const char* gcode, bool wait) { const char *prev_char = iter - 1; - if (iter == last_line_start) + if (iter != last_line_start) { - continue; + char* buff = (char*)malloc(sizeof(char) * ((prev_char - last_line_start) + 1)); + buff[prev_char - last_line_start] = '\0'; + memcpy(buff, last_line_start, prev_char - last_line_start); + array.add(buff); } - char* buff = (char*)malloc(sizeof(char) * (prev_char - gcode) + 1); - buff[prev_char - gcode] = '\0'; - memcpy(buff, last_line_start, prev_char - gcode); last_line_start = iter + 1; - array.add(last_line_start); } if (*iter == '\0') @@ -96,6 +94,11 @@ bool OctoPrinter::send_gcode(const char* gcode, bool wait) return false; } + for (char* alloc : array) + { + free(alloc); + } + return post_request("/api/printer/command/custom", out_buff); } From 1578b4129ddcd735b91615ac4456245ce8b9fc8f Mon Sep 17 00:00:00 2001 From: Sims <38142618+suchmememanyskill@users.noreply.github.com> Date: Wed, 11 Dec 2024 08:10:05 +0100 Subject: [PATCH 46/63] Better better split impl --- .../octoprint_printer_integration.cpp | 29 +++++++++---------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/CYD-Klipper/src/core/octoprint/octoprint_printer_integration.cpp b/CYD-Klipper/src/core/octoprint/octoprint_printer_integration.cpp index 72846bb..7a5adc0 100644 --- a/CYD-Klipper/src/core/octoprint/octoprint_printer_integration.cpp +++ b/CYD-Klipper/src/core/octoprint/octoprint_printer_integration.cpp @@ -61,23 +61,22 @@ bool OctoPrinter::post_request(const char* endpoint, const char* body, int timeo bool OctoPrinter::send_gcode(const char* gcode, bool wait) { + char* gcode_copy = (char*)malloc(sizeof(char) * (strlen(gcode) + 1)); + size_t out_buff_size = sizeof(char) * (strlen(gcode) * 2 + 51); + char* out_buff = (char*)malloc(out_buff_size); + strcpy(gcode_copy, gcode); JsonDocument doc; JsonArray array = doc["commands"].to(); - const char* last_line_start = gcode; - char out_buff[512]; + const char* last_line_start = gcode_copy; - for (const char* iter = gcode;; iter++) + for (char* iter = gcode_copy;; iter++) { if (*iter == '\n' || *iter == '\0') { - const char *prev_char = iter - 1; - if (iter != last_line_start) { - char* buff = (char*)malloc(sizeof(char) * ((prev_char - last_line_start) + 1)); - buff[prev_char - last_line_start] = '\0'; - memcpy(buff, last_line_start, prev_char - last_line_start); - array.add(buff); + *iter = '\0'; + array.add(last_line_start); } last_line_start = iter + 1; @@ -89,17 +88,15 @@ bool OctoPrinter::send_gcode(const char* gcode, bool wait) } } - if (serializeJson(doc, out_buff, 512) != 512) + if (serializeJson(doc, out_buff, out_buff_size) == out_buff_size) { return false; } - for (char* alloc : array) - { - free(alloc); - } - - return post_request("/api/printer/command/custom", out_buff); + free(gcode_copy); + bool result = post_request("/api/printer/command/custom", out_buff); + free(out_buff); + return result; } bool OctoPrinter::move_printer(const char* axis, float amount, bool relative) From 2fce5a9e304a4ad0e2732deb2e9d3217e51267a6 Mon Sep 17 00:00:00 2001 From: Sims <38142618+suchmememanyskill@users.noreply.github.com> Date: Wed, 11 Dec 2024 08:29:18 +0100 Subject: [PATCH 47/63] Start implementation on file list --- .../klipper/klipper_printer_integration.cpp | 2 +- .../klipper/klipper_printer_integration.hpp | 4 +- .../core/klipper/klipper_printer_parsers.cpp | 4 +- .../octoprint_printer_integration.cpp | 13 +++++ .../octoprint_printer_integration.hpp | 7 +++ .../octoprint/octoprint_printer_parsers.cpp | 48 +++++++++++++++++++ 6 files changed, 73 insertions(+), 5 deletions(-) diff --git a/CYD-Klipper/src/core/klipper/klipper_printer_integration.cpp b/CYD-Klipper/src/core/klipper/klipper_printer_integration.cpp index 7279453..ec675a1 100644 --- a/CYD-Klipper/src/core/klipper/klipper_printer_integration.cpp +++ b/CYD-Klipper/src/core/klipper/klipper_printer_integration.cpp @@ -330,7 +330,7 @@ Files KlipperPrinter::get_files() Files files_result = {0}; HTTPClient client; LOG_F(("Heap space pre-file-parse: %d bytes\n", esp_get_free_heap_size())); - std::list files; + std::list files; auto timer_request = millis(); configure_http_client(client, "/server/files/list", true, 5000); diff --git a/CYD-Klipper/src/core/klipper/klipper_printer_integration.hpp b/CYD-Klipper/src/core/klipper/klipper_printer_integration.hpp index 3487029..5aacd39 100644 --- a/CYD-Klipper/src/core/klipper/klipper_printer_integration.hpp +++ b/CYD-Klipper/src/core/klipper/klipper_printer_integration.hpp @@ -8,7 +8,7 @@ typedef struct { char* name; float modified; -} FileSystemFile; +} KlipperFileSystemFile; class KlipperPrinter : public BasePrinter { @@ -32,7 +32,7 @@ class KlipperPrinter : public BasePrinter int parse_macros_count(JsonDocument &in); PowerDevices parse_power_devices(JsonDocument &in); int parse_power_devices_count(JsonDocument &in); - void parse_file_list(JsonDocument &in, std::list &files, int fetch_limit); + void parse_file_list(JsonDocument &in, std::list &files, int fetch_limit); char *parse_thumbnails(JsonDocument &in); public: diff --git a/CYD-Klipper/src/core/klipper/klipper_printer_parsers.cpp b/CYD-Klipper/src/core/klipper/klipper_printer_parsers.cpp index 391cd9f..2c7490e 100644 --- a/CYD-Klipper/src/core/klipper/klipper_printer_parsers.cpp +++ b/CYD-Klipper/src/core/klipper/klipper_printer_parsers.cpp @@ -310,13 +310,13 @@ int KlipperPrinter::parse_power_devices_count(JsonDocument &in) return count; } -void KlipperPrinter::parse_file_list(JsonDocument &in, std::list &files, int fetch_limit) +void KlipperPrinter::parse_file_list(JsonDocument &in, std::list &files, int fetch_limit) { auto result = in["result"].as(); for (auto file : result) { - FileSystemFile f = {0}; + KlipperFileSystemFile f = {0}; const char *path = file["path"]; float modified = file["modified"]; auto file_iter = files.begin(); diff --git a/CYD-Klipper/src/core/octoprint/octoprint_printer_integration.cpp b/CYD-Klipper/src/core/octoprint/octoprint_printer_integration.cpp index 7a5adc0..b293941 100644 --- a/CYD-Klipper/src/core/octoprint/octoprint_printer_integration.cpp +++ b/CYD-Klipper/src/core/octoprint/octoprint_printer_integration.cpp @@ -269,6 +269,19 @@ bool OctoPrinter::set_power_device_state(const char* device_name, bool state) Files OctoPrinter::get_files() { + HTTPClient client; + JsonDocument filter; + JsonDocument doc; + configure_http_client(client, "/api/files?recursive=true", true, 5000, printer_config); + + filter["files"][0]["path"] = true; + filter["files"][0]["date"] = true; + + if (client.GET() == 200) + { + auto parseResult = deserializeJson(doc, client.getStream(), DeserializationOption::Filter(filter)); + } + return {}; } diff --git a/CYD-Klipper/src/core/octoprint/octoprint_printer_integration.hpp b/CYD-Klipper/src/core/octoprint/octoprint_printer_integration.hpp index 43f0183..5f12513 100644 --- a/CYD-Klipper/src/core/octoprint/octoprint_printer_integration.hpp +++ b/CYD-Klipper/src/core/octoprint/octoprint_printer_integration.hpp @@ -1,6 +1,12 @@ #include "../printer_integration.hpp" #include #include +#include + +typedef struct { + char* name; + float modified; +} OctoFileSystemFile; class OctoPrinter : public BasePrinter { @@ -11,6 +17,7 @@ class OctoPrinter : public BasePrinter void parse_printer_state(JsonDocument& in); void parse_job_state(JsonDocument& in); void parse_error(JsonDocument& in); + void OctoPrinter::parse_file_list(JsonDocument &in, std::list &files, int fetch_limit); bool get_request(const char* endpoint, int timeout_ms = 1000, bool stream = true); bool post_request(const char* endpoint, const char* body, int timeout_ms = 1000, bool stream = false); diff --git a/CYD-Klipper/src/core/octoprint/octoprint_printer_parsers.cpp b/CYD-Klipper/src/core/octoprint/octoprint_printer_parsers.cpp index 1a43415..6cbb511 100644 --- a/CYD-Klipper/src/core/octoprint/octoprint_printer_parsers.cpp +++ b/CYD-Klipper/src/core/octoprint/octoprint_printer_parsers.cpp @@ -101,4 +101,52 @@ void OctoPrinter::parse_error(JsonDocument& in) strcpy(printer_data.state_message, error); } } +} + +void OctoPrinter::parse_file_list(JsonDocument &in, std::list &files, int fetch_limit) +{ + auto result = in["files"].as(); + + for (auto file : result) + { + OctoFileSystemFile f = {0}; + const char *path = file["path"]; + float modified = file["date"]; + auto file_iter = files.begin(); + + while (file_iter != files.end()) + { + if ((*file_iter).modified < modified) + break; + + file_iter++; + } + + if (file_iter == files.end() && files.size() >= fetch_limit) + continue; + + f.name = (char *)malloc(strlen(path) + 1); + if (f.name == NULL) + { + LOG_LN("Failed to allocate memory"); + continue; + } + strcpy(f.name, path); + f.modified = modified; + + if (file_iter != files.end()) + files.insert(file_iter, f); + else + files.push_back(f); + + if (files.size() > fetch_limit) + { + auto last_entry = files.back(); + + if (last_entry.name != NULL) + free(last_entry.name); + + files.pop_back(); + } + } } \ No newline at end of file From 96f8695b0eb9d256d13dc36740a418c901d6aeaa Mon Sep 17 00:00:00 2001 From: Sims <38142618+suchmememanyskill@users.noreply.github.com> Date: Wed, 11 Dec 2024 17:48:22 +0100 Subject: [PATCH 48/63] Continued impl of octoprint --- .../klipper/klipper_printer_integration.cpp | 7 +- .../octoprint_printer_integration.cpp | 74 +++++++++++++++++-- .../octoprint/octoprint_printer_parsers.cpp | 5 ++ 3 files changed, 79 insertions(+), 7 deletions(-) diff --git a/CYD-Klipper/src/core/klipper/klipper_printer_integration.cpp b/CYD-Klipper/src/core/klipper/klipper_printer_integration.cpp index ec675a1..d2c862a 100644 --- a/CYD-Klipper/src/core/klipper/klipper_printer_integration.cpp +++ b/CYD-Klipper/src/core/klipper/klipper_printer_integration.cpp @@ -338,12 +338,17 @@ Files KlipperPrinter::get_files() int http_code = client.GET(); auto timer_parse = millis(); - if (http_code == 200){ + if (http_code == 200) + { JsonDocument doc; auto parseResult = deserializeJson(doc, client.getStream()); LOG_F(("Json parse: %s\n", parseResult.c_str())) parse_file_list(doc, files, KLIPPER_FILE_FETCH_LIMIT); } + else + { + return files_result; + } files_result.available_files = (char**)malloc(sizeof(char*) * files.size()); diff --git a/CYD-Klipper/src/core/octoprint/octoprint_printer_integration.cpp b/CYD-Klipper/src/core/octoprint/octoprint_printer_integration.cpp index b293941..acacc04 100644 --- a/CYD-Klipper/src/core/octoprint/octoprint_printer_integration.cpp +++ b/CYD-Klipper/src/core/octoprint/octoprint_printer_integration.cpp @@ -8,6 +8,7 @@ const char* COMMAND_CONNECT = "{\"command\":\"connect\"}"; const char* COMMAND_DISCONNECT = "{\"command\":\"disconnect\"}"; const char* COMMAND_HOME = "{\"command\":\"home\",\"axes\":[\"x\",\"y\",\"z\"]}"; +const char* COMMAND_PRINT = "{\"command\":\"select\",\"print\":true}"; void configure_http_client(HTTPClient &client, String url_part, bool stream, int timeout, PrinterConfiguration* printer_config) { @@ -108,7 +109,7 @@ bool OctoPrinter::move_printer(const char* axis, float amount, bool relative) doc[axis] = amount; doc["absolute"] = !relative; - if (serializeJson(doc, out_buff, 512) != 512) + if (serializeJson(doc, out_buff, 512) >= 512) { return false; } @@ -267,27 +268,69 @@ bool OctoPrinter::set_power_device_state(const char* device_name, bool state) return false; } +#define OCTO_FILE_FETCH_LIMIT 20 + Files OctoPrinter::get_files() { + LOG_F(("Heap space pre-file-parse: %d bytes\n", esp_get_free_heap_size())); + + Files files_result = {0}; HTTPClient client; JsonDocument filter; - JsonDocument doc; - configure_http_client(client, "/api/files?recursive=true", true, 5000, printer_config); + std::list files; filter["files"][0]["path"] = true; filter["files"][0]["date"] = true; + filter["files"][0]["origin"] = true; + + auto timer_request = millis(); + configure_http_client(client, "/api/files?recursive=true", true, 5000, printer_config); + + int http_code = client.GET(); + auto timer_parse = millis(); - if (client.GET() == 200) + if (http_code == 200) { + JsonDocument doc; auto parseResult = deserializeJson(doc, client.getStream(), DeserializationOption::Filter(filter)); + LOG_F(("Json parse: %s\n", parseResult.c_str())) + parse_file_list(doc, files, OCTO_FILE_FETCH_LIMIT); } + else + { + return files_result; + } + + files_result.available_files = (char**)malloc(sizeof(char*) * files.size()); + + if (files_result.available_files == NULL){ + LOG_LN("Failed to allocate memory"); + + for (auto file : files){ + free(file.name); + } + + return files_result; + } + + for (auto file : files){ + files_result.available_files[files_result.count++] = file.name; + } + + files_result.success = true; + + LOG_F(("Heap space post-file-parse: %d bytes\n", esp_get_free_heap_size())) + LOG_F(("Got %d files. Request took %dms, parsing took %dms\n", files.size(), timer_parse - timer_request, millis() - timer_parse)) + return files_result; return {}; } bool OctoPrinter::start_file(const char* filename) { - return false; + char buff[512]; + sprintf("/api/files/local/%s", filename); + return post_request(buff, COMMAND_PRINT); } Thumbnail OctoPrinter::get_32_32_png_image_thumbnail(const char* gcode_filename) @@ -297,7 +340,26 @@ Thumbnail OctoPrinter::get_32_32_png_image_thumbnail(const char* gcode_filename) bool OctoPrinter::set_target_temperature(PrinterTemperatureDevice device, unsigned int temperature) { - return false; + JsonDocument doc; + char out_buff[512]; + + doc["command"] = "target"; + + if (device == PrinterTemperatureDevice::PrinterTemperatureDeviceNozzle1) + { + doc["targets"]["tool0"] = temperature; + } + else + { + doc["target"] = temperature; + } + + if (serializeJson(doc, out_buff, 512) >= 512) + { + return false; + } + + return post_request(device == PrinterTemperatureDevice::PrinterTemperatureDeviceBed ? "/api/printer/bed" : "/api/printer/tool", out_buff); } OctoConnectionStatus connection_test_octoprint(PrinterConfiguration* config) diff --git a/CYD-Klipper/src/core/octoprint/octoprint_printer_parsers.cpp b/CYD-Klipper/src/core/octoprint/octoprint_printer_parsers.cpp index 6cbb511..fbc7243 100644 --- a/CYD-Klipper/src/core/octoprint/octoprint_printer_parsers.cpp +++ b/CYD-Klipper/src/core/octoprint/octoprint_printer_parsers.cpp @@ -109,6 +109,11 @@ void OctoPrinter::parse_file_list(JsonDocument &in, std::list Date: Sun, 15 Dec 2024 00:40:11 +0100 Subject: [PATCH 49/63] Add octoprint panels --- .../octoprint_printer_integration.cpp | 8 +- .../octoprint_printer_integration.hpp | 7 +- .../octoprint/octoprint_printer_panels.cpp | 111 ++++++++++++++++++ 3 files changed, 120 insertions(+), 6 deletions(-) create mode 100644 CYD-Klipper/src/core/octoprint/octoprint_printer_panels.cpp diff --git a/CYD-Klipper/src/core/octoprint/octoprint_printer_integration.cpp b/CYD-Klipper/src/core/octoprint/octoprint_printer_integration.cpp index acacc04..a3f3f4f 100644 --- a/CYD-Klipper/src/core/octoprint/octoprint_printer_integration.cpp +++ b/CYD-Klipper/src/core/octoprint/octoprint_printer_integration.cpp @@ -26,7 +26,7 @@ void configure_http_client(HTTPClient &client, String url_part, bool stream, int } } -bool OctoPrinter::get_request(const char* endpoint, int timeout_ms, bool stream) +bool OctoPrinter::get_request(const char* endpoint, int timeout_ms) { HTTPClient client; @@ -35,12 +35,12 @@ bool OctoPrinter::get_request(const char* endpoint, int timeout_ms, bool stream) timeout_ms = 500; } - configure_http_client(client, endpoint, stream, timeout_ms, printer_config); + configure_http_client(client, endpoint, false, timeout_ms, printer_config); int result = client.GET(); return result >= 200 && result < 300; } -bool OctoPrinter::post_request(const char* endpoint, const char* body, int timeout_ms, bool stream) +bool OctoPrinter::post_request(const char* endpoint, const char* body, int timeout_ms) { HTTPClient client; @@ -49,7 +49,7 @@ bool OctoPrinter::post_request(const char* endpoint, const char* body, int timeo timeout_ms = 500; } - configure_http_client(client, endpoint, stream, timeout_ms, printer_config); + configure_http_client(client, endpoint, false, timeout_ms, printer_config); if (body[0] == '{' || body[0] == '[') { diff --git a/CYD-Klipper/src/core/octoprint/octoprint_printer_integration.hpp b/CYD-Klipper/src/core/octoprint/octoprint_printer_integration.hpp index 5f12513..0c0901c 100644 --- a/CYD-Klipper/src/core/octoprint/octoprint_printer_integration.hpp +++ b/CYD-Klipper/src/core/octoprint/octoprint_printer_integration.hpp @@ -19,8 +19,8 @@ class OctoPrinter : public BasePrinter void parse_error(JsonDocument& in); void OctoPrinter::parse_file_list(JsonDocument &in, std::list &files, int fetch_limit); - bool get_request(const char* endpoint, int timeout_ms = 1000, bool stream = true); - bool post_request(const char* endpoint, const char* body, int timeout_ms = 1000, bool stream = false); + bool get_request(const char* endpoint, int timeout_ms = 1000); + void init_ui_panels(); public: OctoPrinter(int index) : BasePrinter(index) @@ -39,8 +39,11 @@ class OctoPrinter : public BasePrinter | PrinterTemperatureDeviceNozzle1; printer_data.error_screen_features = PrinterFeatureRetryError; + + init_ui_panels(); } + bool post_request(const char* endpoint, const char* body, int timeout_ms = 1000); bool move_printer(const char* axis, float amount, bool relative); bool execute_feature(PrinterFeatures feature); bool connect(); diff --git a/CYD-Klipper/src/core/octoprint/octoprint_printer_panels.cpp b/CYD-Klipper/src/core/octoprint/octoprint_printer_panels.cpp new file mode 100644 index 0000000..f778eb8 --- /dev/null +++ b/CYD-Klipper/src/core/octoprint/octoprint_printer_panels.cpp @@ -0,0 +1,111 @@ +#include "octoprint_printer_integration.hpp" +#include "lvgl.h" +#include "../../ui/ui_utils.h" +#include + +const char* COMMAND_EXTRUDE_MULT = "{\"command\":\"flowrate\",\"factor\":%d}"; + +#define OCTO_TIMEOUT_POPUP_MESSAGES 4000 + +static void set_fan_speed_text(lv_event_t * e) +{ + lv_obj_t * label = lv_event_get_target(e); + lv_label_set_text(label, "Fan"); +} + +static void set_speed_mult_text(lv_event_t * e) +{ + lv_obj_t * label = lv_event_get_target(e); + lv_label_set_text(label, "Speed"); +} + +static void set_extruder_mult_text(lv_event_t * e) +{ + lv_obj_t * label = lv_event_get_target(e); + lv_label_set_text(label, "Flowrate"); +} + +bool get_range(lv_event_t * e, int min, int max, int* out) +{ + char buff[64]; + lv_obj_t * ta = lv_event_get_target(e); + lv_obj_t * kb = (lv_obj_t *)lv_event_get_user_data(e); + const char * txt = lv_textarea_get_text(ta); + + if (txt == NULL || *txt == '\0') + { + return false; + } + + int parsed_input = atoi(txt); + if (parsed_input < min || parsed_input > max) + { + sprintf(buff, "Value out of range (%d -> %d)", min, max); + lv_create_popup_message(buff, OCTO_TIMEOUT_POPUP_MESSAGES); + return false; + } + + *out = parsed_input; + return true; +} + +static void set_fan_speed(lv_event_t * e) +{ + int fan_speed = 0; + if (get_range(e, 0, 100, &fan_speed)) + { + int actual_fan_speed = fan_speed * 255 / 100; + char buff[16]; + sprintf(buff, "M106 S%d", actual_fan_speed); + ((OctoPrinter*)get_current_printer())->send_gcode(buff); + } +} + +static void open_fan_speed_keypad(lv_event_t * e) +{ + lv_create_keyboard_text_entry(set_fan_speed, "New fan speed %", LV_KEYBOARD_MODE_NUMBER); +} + +static void set_speed_mult(lv_event_t * e) +{ + int speed_mult = 0; + if (get_range(e, 50, 300, &speed_mult)) + { + char buff[16]; + sprintf(buff, "M220 S%d", speed_mult); + ((OctoPrinter*)get_current_printer())->send_gcode(buff); + } +} + +static void open_speed_mult_keypad(lv_event_t * e) +{ + lv_create_keyboard_text_entry(set_speed_mult, "New speed multiplier %", LV_KEYBOARD_MODE_NUMBER); +} + +static void set_extrude_mult(lv_event_t * e) +{ + int extrude_mult = 0; + if (get_range(e, 75, 125, &extrude_mult)) + { + char buff[64]; + sprintf(buff, COMMAND_EXTRUDE_MULT, extrude_mult); + ((OctoPrinter*)get_current_printer())->post_request("/api/printer/tool", buff); + } +} + +static void open_extrude_mult_keypad(lv_event_t * e) +{ + lv_create_keyboard_text_entry(set_extrude_mult, "New extrude multiplier %", LV_KEYBOARD_MODE_NUMBER); +} + +static PrinterUiPanel klipper_ui_panels[4] { + { .set_label = (void*)set_fan_speed_text, .open_panel = (void*)open_fan_speed_keypad }, + { .set_label = (void*)set_speed_mult_text, .open_panel = (void*)open_speed_mult_keypad }, + { .set_label = (void*)set_extruder_mult_text, .open_panel = (void*)open_extrude_mult_keypad }, +}; + +void OctoPrinter::init_ui_panels() +{ + custom_menus_count = 4; + custom_menus = klipper_ui_panels; +} \ No newline at end of file From 2f1b0095b0f59183f9de9f78fd5edc24a36d6b0d Mon Sep 17 00:00:00 2001 From: Sims <38142618+suchmememanyskill@users.noreply.github.com> Date: Sun, 15 Dec 2024 00:59:06 +0100 Subject: [PATCH 50/63] Implement missing commands for octoprint --- .../octoprint_printer_integration.cpp | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/CYD-Klipper/src/core/octoprint/octoprint_printer_integration.cpp b/CYD-Klipper/src/core/octoprint/octoprint_printer_integration.cpp index a3f3f4f..5ff3c4f 100644 --- a/CYD-Klipper/src/core/octoprint/octoprint_printer_integration.cpp +++ b/CYD-Klipper/src/core/octoprint/octoprint_printer_integration.cpp @@ -9,6 +9,11 @@ const char* COMMAND_CONNECT = "{\"command\":\"connect\"}"; const char* COMMAND_DISCONNECT = "{\"command\":\"disconnect\"}"; const char* COMMAND_HOME = "{\"command\":\"home\",\"axes\":[\"x\",\"y\",\"z\"]}"; const char* COMMAND_PRINT = "{\"command\":\"select\",\"print\":true}"; +const char* COMMAND_CANCEL_PRINT = "{\"command\":\"cancel\"}"; +const char* COMMAND_PAUSE_PRINT = "{\"command\":\"pause\",\"action\":\"pause\"}"; +const char* COMMAND_RESUME_PRINT = "{\"command\":\"pause\",\"action\":\"resume\"}"; +const char* COMMAND_EXTRUDE = "{\"command\":\"extrude\",\"amount\":25}"; +const char* COMMAND_RETRACT = "{\"command\":\"extrude\",\"amount\":-25}"; void configure_http_client(HTTPClient &client, String url_part, bool stream, int timeout, PrinterConfiguration* printer_config) { @@ -132,6 +137,19 @@ bool OctoPrinter::execute_feature(PrinterFeatures feature) return post_request("/api/printer/printhead", COMMAND_HOME); case PrinterFeatureDisableSteppers: return send_gcode("M18"); + case PrinterFeaturePause: + return post_request("/api/job", COMMAND_PAUSE_PRINT); + case PrinterFeatureResume: + return post_request("/api/job", COMMAND_RESUME_PRINT); + case PrinterFeatureStop: + return post_request("/api/job", COMMAND_CANCEL_PRINT); + case PrinterFeatureCooldown: + return set_target_temperature(PrinterTemperatureDeviceNozzle1, 0) + && set_target_temperature(PrinterTemperatureDeviceBed, 0); + case PrinterFeatureExtrude: + return post_request("/api/printer/tool", COMMAND_EXTRUDE); + case PrinterFeatureRetract: + return post_request("/api/printer/tool", COMMAND_RETRACT); default: LOG_F(("Unsupported printer feature %d", feature)); break; From 6aa74633a8f2d968f7ec4a0674d26957bf621fde Mon Sep 17 00:00:00 2001 From: Sims <38142618+suchmememanyskill@users.noreply.github.com> Date: Sun, 15 Dec 2024 01:15:58 +0100 Subject: [PATCH 51/63] Add min fetcher for octoprint --- .../octoprint_printer_integration.cpp | 50 +++++++++++++++++-- .../octoprint_printer_integration.hpp | 6 ++- .../octoprint/octoprint_printer_parsers.cpp | 29 +++++++---- 3 files changed, 71 insertions(+), 14 deletions(-) diff --git a/CYD-Klipper/src/core/octoprint/octoprint_printer_integration.cpp b/CYD-Klipper/src/core/octoprint/octoprint_printer_integration.cpp index 5ff3c4f..bff131c 100644 --- a/CYD-Klipper/src/core/octoprint/octoprint_printer_integration.cpp +++ b/CYD-Klipper/src/core/octoprint/octoprint_printer_integration.cpp @@ -177,7 +177,7 @@ bool OctoPrinter::fetch() request_consecutive_fail_count = 0; JsonDocument doc; deserializeJson(doc, client.getStream()); - parse_printer_state(doc); + parse_printer_status(doc); doc.clear(); configure_http_client(client2, "/api/job", true, 1000, printer_config); @@ -216,12 +216,56 @@ bool OctoPrinter::fetch() PrinterDataMinimal OctoPrinter::fetch_min() { - return {}; + PrinterDataMinimal min = {}; + min.success = true; + min.print_progress = 0; + min.power_devices = 0; + min.state = PrinterState::PrinterStateOffline; + + { + HTTPClient client; + int http_code = 0; + configure_http_client(client, "/api/printer", true, 1000, printer_config); + int http_code = client.GET(); + + if (http_code == 200) + { + JsonDocument doc; + deserializeJson(doc, client.getStream()); + min.state = parse_printer_state(doc); + } + else if (http_code == 409) + { + min.state = PrinterState::PrinterStateError; + return min; + } + else + { + return min; + } + } + + { + HTTPClient client; + configure_http_client(client, "/api/job", true, 1000, printer_config); + + if (client.GET() == 200) + { + JsonDocument doc; + deserializeJson(doc, client.getStream()); + min.print_progress = parse_job_state_progress(doc); + } + else + { + min.state = PrinterState::PrinterStateError; + } + } + + return min; } void OctoPrinter::disconnect() { - } const char* MACRO_AUTOLEVEL = "Auto-Level (G28+G29)"; diff --git a/CYD-Klipper/src/core/octoprint/octoprint_printer_integration.hpp b/CYD-Klipper/src/core/octoprint/octoprint_printer_integration.hpp index 0c0901c..724ff07 100644 --- a/CYD-Klipper/src/core/octoprint/octoprint_printer_integration.hpp +++ b/CYD-Klipper/src/core/octoprint/octoprint_printer_integration.hpp @@ -14,10 +14,12 @@ class OctoPrinter : public BasePrinter bool no_printer = false; unsigned char request_consecutive_fail_count{}; - void parse_printer_state(JsonDocument& in); + void parse_printer_status(JsonDocument& in); + PrinterState parse_printer_state(JsonDocument& in); void parse_job_state(JsonDocument& in); + float parse_job_state_progress(JsonDocument& in); void parse_error(JsonDocument& in); - void OctoPrinter::parse_file_list(JsonDocument &in, std::list &files, int fetch_limit); + void parse_file_list(JsonDocument &in, std::list &files, int fetch_limit); bool get_request(const char* endpoint, int timeout_ms = 1000); void init_ui_panels(); diff --git a/CYD-Klipper/src/core/octoprint/octoprint_printer_parsers.cpp b/CYD-Klipper/src/core/octoprint/octoprint_printer_parsers.cpp index fbc7243..fd0563e 100644 --- a/CYD-Klipper/src/core/octoprint/octoprint_printer_parsers.cpp +++ b/CYD-Klipper/src/core/octoprint/octoprint_printer_parsers.cpp @@ -2,11 +2,9 @@ #include "octoprint_printer_integration.hpp" #include -void OctoPrinter::parse_printer_state(JsonDocument& in) +PrinterState OctoPrinter::parse_printer_state(JsonDocument& in) { auto flags = in["state"]["flags"]; - auto text = in["state"]["text"]; - bool cancelling = flags["cancelling"]; bool closedOrError = flags["closedOrError"]; bool error = flags["error"]; @@ -21,25 +19,32 @@ void OctoPrinter::parse_printer_state(JsonDocument& in) if (printing || resuming) { - printer_data.state = PrinterState::PrinterStatePrinting; + return PrinterState::PrinterStatePrinting; } else if (pausing || paused) { - printer_data.state = PrinterState::PrinterStatePaused; + return PrinterState::PrinterStatePaused; } else if (cancelling || finishing || ready) { - printer_data.state = PrinterState::PrinterStateIdle; + return PrinterState::PrinterStateIdle; } - else + + return PrinterState::PrinterStateError; +} + +void OctoPrinter::parse_printer_status(JsonDocument& in) +{ + auto text = in["state"]["text"]; + printer_data.state = parse_printer_state(in); + + if (printer_data.state == PrinterState::PrinterStateError) { if (text != NULL && (printer_data.state_message == NULL || strcmp(printer_data.state_message, text))) { printer_data.state_message = (char *)malloc(strlen(text) + 1); strcpy(printer_data.state_message, text); } - - printer_data.state = PrinterState::PrinterStateError; } auto temperature = in["temperature"]; @@ -88,6 +93,12 @@ void OctoPrinter::parse_job_state(JsonDocument& in) printer_data.remaining_time_s = progress["printTimeLeft"]; } +float OctoPrinter::parse_job_state_progress(JsonDocument& in) +{ + float completion = in["progress"]["completion"]; + return completion / 100; +} + void OctoPrinter::parse_error(JsonDocument& in) { const char* error = in["error"]; From abbb0b2f7eecb4e9bd464f3d70ade8b1c2df4c73 Mon Sep 17 00:00:00 2001 From: Sims <38142618+suchmememanyskill@users.noreply.github.com> Date: Sun, 15 Dec 2024 01:16:46 +0100 Subject: [PATCH 52/63] We have 3 --- CYD-Klipper/src/core/octoprint/octoprint_printer_panels.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CYD-Klipper/src/core/octoprint/octoprint_printer_panels.cpp b/CYD-Klipper/src/core/octoprint/octoprint_printer_panels.cpp index f778eb8..c40b409 100644 --- a/CYD-Klipper/src/core/octoprint/octoprint_printer_panels.cpp +++ b/CYD-Klipper/src/core/octoprint/octoprint_printer_panels.cpp @@ -106,6 +106,6 @@ static PrinterUiPanel klipper_ui_panels[4] { void OctoPrinter::init_ui_panels() { - custom_menus_count = 4; + custom_menus_count = 3; custom_menus = klipper_ui_panels; } \ No newline at end of file From 211fe15aee556c576b83b66c2dc6c13a3ddb40b1 Mon Sep 17 00:00:00 2001 From: suchmememanyskill <38142618+suchmememanyskill@users.noreply.github.com> Date: Sun, 15 Dec 2024 12:13:32 +0100 Subject: [PATCH 53/63] Fix compile errors --- .../core/klipper-serial/serial_klipper_printer_integration.cpp | 2 +- .../src/core/octoprint/octoprint_printer_integration.cpp | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/CYD-Klipper/src/core/klipper-serial/serial_klipper_printer_integration.cpp b/CYD-Klipper/src/core/klipper-serial/serial_klipper_printer_integration.cpp index 618c0be..01ad9ab 100644 --- a/CYD-Klipper/src/core/klipper-serial/serial_klipper_printer_integration.cpp +++ b/CYD-Klipper/src/core/klipper-serial/serial_klipper_printer_integration.cpp @@ -269,7 +269,7 @@ Files SerialKlipperPrinter::get_files() files_result.success = false; JsonDocument doc; LOG_F(("Heap space pre-file-parse: %d bytes\n", esp_get_free_heap_size())); - std::list files; + std::list files; auto timer_request = millis(); bool result = make_serial_request(doc, 5000, HttpGet, "/server/files/list"); diff --git a/CYD-Klipper/src/core/octoprint/octoprint_printer_integration.cpp b/CYD-Klipper/src/core/octoprint/octoprint_printer_integration.cpp index bff131c..e78ef62 100644 --- a/CYD-Klipper/src/core/octoprint/octoprint_printer_integration.cpp +++ b/CYD-Klipper/src/core/octoprint/octoprint_printer_integration.cpp @@ -224,7 +224,6 @@ PrinterDataMinimal OctoPrinter::fetch_min() { HTTPClient client; - int http_code = 0; configure_http_client(client, "/api/printer", true, 1000, printer_config); int http_code = client.GET(); From b342e58cfc04e21da31f92521557e9c31071bf7c Mon Sep 17 00:00:00 2001 From: suchmememanyskill <38142618+suchmememanyskill@users.noreply.github.com> Date: Sun, 15 Dec 2024 13:10:12 +0100 Subject: [PATCH 54/63] Install python packages in venv --- serial/install.sh | 6 +++++- serial/run.sh | 4 ++++ 2 files changed, 9 insertions(+), 1 deletion(-) create mode 100644 serial/run.sh diff --git a/serial/install.sh b/serial/install.sh index b4acb4c..7fe8471 100644 --- a/serial/install.sh +++ b/serial/install.sh @@ -7,7 +7,11 @@ fi set -e +chmod a+x ./run.sh + # Install dependencies +python3 -m venv ./env +source ./env/bin/activate pip3 install -r requirements.txt # Create systemd unit file @@ -17,7 +21,7 @@ echo "Description=CYD Klipper serial server" >> ~/.config/systemd/user/cyd-klipp echo "After=network.target" >> ~/.config/systemd/user/cyd-klipper-serial.service echo "" >> ~/.config/systemd/user/cyd-klipper-serial.service echo "[Service]" >> ~/.config/systemd/user/cyd-klipper-serial.service -echo "ExecStart=python3 $(pwd)/serial_server.py" >> ~/.config/systemd/user/cyd-klipper-serial.service +echo "ExecStart=$(pwd)/run.sh" >> ~/.config/systemd/user/cyd-klipper-serial.service echo "WorkingDirectory=$(pwd)" >> ~/.config/systemd/user/cyd-klipper-serial.service echo "Restart=always" >> ~/.config/systemd/user/cyd-klipper-serial.service echo "" >> ~/.config/systemd/user/cyd-klipper-serial.service diff --git a/serial/run.sh b/serial/run.sh new file mode 100644 index 0000000..6023f66 --- /dev/null +++ b/serial/run.sh @@ -0,0 +1,4 @@ +#!/bin/bash + +source ./env/bin/activate +python3 serial_server.py \ No newline at end of file From f4498e95cd14da01c793e9d1b6d9ff2285db5b49 Mon Sep 17 00:00:00 2001 From: suchmememanyskill <38142618+suchmememanyskill@users.noreply.github.com> Date: Sun, 15 Dec 2024 22:06:01 +0100 Subject: [PATCH 55/63] Make octoprint work after testing --- CYD-Klipper/src/conf/global_config.cpp | 8 +-- CYD-Klipper/src/conf/global_config.h | 6 +-- .../core/bambu/bambu_printer_integration.cpp | 10 ++-- .../src/core/bambu/bambu_printer_parsers.cpp | 4 +- .../klipper/klipper_printer_integration.cpp | 8 +-- .../octoprint_printer_integration.cpp | 24 +++++---- .../octoprint/octoprint_printer_parsers.cpp | 6 ++- CYD-Klipper/src/ui/ip_setup.cpp | 23 ++++++--- .../src/ui/panels/connecting_panel.cpp | 2 +- CYD-Klipper/src/ui/panels/macros_panel.cpp | 2 +- CYD-Klipper/src/ui/panels/printer_panel.cpp | 2 +- CYD-Klipper/src/ui/serial/serial_commands.cpp | 51 +++++++++---------- 12 files changed, 80 insertions(+), 66 deletions(-) diff --git a/CYD-Klipper/src/conf/global_config.cpp b/CYD-Klipper/src/conf/global_config.cpp index 2c7ef77..c336758 100644 --- a/CYD-Klipper/src/conf/global_config.cpp +++ b/CYD-Klipper/src/conf/global_config.cpp @@ -84,8 +84,8 @@ void global_config_add_new_printer() new_config->printer_type = PrinterType::PrinterTypeNone; new_config->printer_name[0] = 0; - new_config->klipper_host[0] = 0; - new_config->klipper_auth[0] = 0; + new_config->printer_host[0] = 0; + new_config->printer_auth[0] = 0; new_config->klipper_port = 0; new_config->color_scheme = old_config->color_scheme; @@ -144,8 +144,8 @@ void set_printer_config_index(int index) new_config->auth_configured = false; new_config->printer_name[0] = 0; - new_config->klipper_host[0] = 0; - new_config->klipper_auth[0] = 0; + new_config->printer_host[0] = 0; + new_config->printer_auth[0] = 0; new_config->klipper_port = 0; new_config->color_scheme = old_config->color_scheme; diff --git a/CYD-Klipper/src/conf/global_config.h b/CYD-Klipper/src/conf/global_config.h index f337225..c235fff 100644 --- a/CYD-Klipper/src/conf/global_config.h +++ b/CYD-Klipper/src/conf/global_config.h @@ -4,7 +4,7 @@ #include "lvgl.h" #define CONFIG_VERSION 7 -#define PRINTER_CONFIG_COUNT 8 +#define PRINTER_CONFIG_COUNT 6 #define DISPLAY_SECRETS 0 enum { @@ -49,8 +49,8 @@ typedef struct { }; char printer_name[25]; - char klipper_host[65]; - char klipper_auth[33]; + char printer_host[65]; + char printer_auth[65]; unsigned int klipper_port; unsigned char color_scheme; diff --git a/CYD-Klipper/src/core/bambu/bambu_printer_integration.cpp b/CYD-Klipper/src/core/bambu/bambu_printer_integration.cpp index 7b3ec3b..95ec995 100644 --- a/CYD-Klipper/src/core/bambu/bambu_printer_integration.cpp +++ b/CYD-Klipper/src/core/bambu/bambu_printer_integration.cpp @@ -40,7 +40,7 @@ bool BambuPrinter::publish_mqtt_command(const char* command) } char auth[48] = {0}; - sprintf(auth, "device/%s/request", printer_config->klipper_auth); + sprintf(auth, "device/%s/request", printer_config->printer_auth); return client.publish(auth, command); } @@ -117,7 +117,7 @@ bool BambuPrinter::connect() { wifi_client.setInsecure(); client.setBufferSize(4096); - client.setServer(printer_config->klipper_host, 8883); + client.setServer(printer_config->printer_host, 8883); current_printer = this; client.setCallback(NULL); char buff[10] = {0}; @@ -129,7 +129,7 @@ bool BambuPrinter::connect() } char auth[48] = {0}; - sprintf(auth, "device/%s/report", printer_config->klipper_auth); + sprintf(auth, "device/%s/report", printer_config->printer_auth); if (!client.subscribe(auth)) { @@ -341,7 +341,7 @@ BambuConnectionStatus connection_test_bambu(PrinterConfiguration* config) WiFiClientSecure connection_test_wifi_client; PubSubClient connection_test_client(connection_test_wifi_client); connection_test_wifi_client.setInsecure(); - connection_test_client.setServer(config->klipper_host, 8883); + connection_test_client.setServer(config->printer_host, 8883); char buff[10] = {0}; sprintf(buff, "%d", config->klipper_port); if (!connection_test_client.connect("id", "bblp", buff)) @@ -351,7 +351,7 @@ BambuConnectionStatus connection_test_bambu(PrinterConfiguration* config) } char auth[48] = {0}; - sprintf(auth, "device/%s/report", config->klipper_auth); + sprintf(auth, "device/%s/report", config->printer_auth); if (!connection_test_client.subscribe(auth)) { diff --git a/CYD-Klipper/src/core/bambu/bambu_printer_parsers.cpp b/CYD-Klipper/src/core/bambu/bambu_printer_parsers.cpp index 60bed9e..6d9bafb 100644 --- a/CYD-Klipper/src/core/bambu/bambu_printer_parsers.cpp +++ b/CYD-Klipper/src/core/bambu/bambu_printer_parsers.cpp @@ -309,7 +309,7 @@ Files BambuPrinter::parse_files(WiFiClientSecure& wifi_client, int max_files) unsigned long timer_request = millis(); Files result = {0}; - if (!wifi_client.connect(printer_config->klipper_host, 990)) + if (!wifi_client.connect(printer_config->printer_host, 990)) { LOG_LN("Failed to fetch files: connection failed"); } @@ -325,7 +325,7 @@ Files BambuPrinter::parse_files(WiFiClientSecure& wifi_client, int max_files) send_command_without_response(wifi_client, "NLST"); wifi_client.stop(); - if (wifi_client.connect(printer_config->klipper_host, 2024)) + if (wifi_client.connect(printer_config->printer_host, 2024)) { unsigned long timer_parse = millis(); std::list files; diff --git a/CYD-Klipper/src/core/klipper/klipper_printer_integration.cpp b/CYD-Klipper/src/core/klipper/klipper_printer_integration.cpp index d2c862a..562c91c 100644 --- a/CYD-Klipper/src/core/klipper/klipper_printer_integration.cpp +++ b/CYD-Klipper/src/core/klipper/klipper_printer_integration.cpp @@ -14,10 +14,10 @@ void KlipperPrinter::configure_http_client(HTTPClient &client, String url_part, client.setConnectTimeout(timeout); } - client.begin("http://" + String(printer_config->klipper_host) + ":" + String(printer_config->klipper_port) + url_part); + client.begin("http://" + String(printer_config->printer_host) + ":" + String(printer_config->klipper_port) + url_part); if (printer_config->auth_configured) { - client.addHeader("X-Api-Key", printer_config->klipper_auth); + client.addHeader("X-Api-Key", printer_config->printer_auth); } } @@ -495,10 +495,10 @@ KlipperConnectionStatus connection_test_klipper(PrinterConfiguration* config) client.setTimeout(1000); client.setConnectTimeout(1000); - client.begin("http://" + String(config->klipper_host) + ":" + String(config->klipper_port) + "/printer/info"); + client.begin("http://" + String(config->printer_host) + ":" + String(config->klipper_port) + "/printer/info"); if (config->auth_configured) { - client.addHeader("X-Api-Key", config->klipper_auth); + client.addHeader("X-Api-Key", config->printer_auth); } int http_code; diff --git a/CYD-Klipper/src/core/octoprint/octoprint_printer_integration.cpp b/CYD-Klipper/src/core/octoprint/octoprint_printer_integration.cpp index e78ef62..7773d8c 100644 --- a/CYD-Klipper/src/core/octoprint/octoprint_printer_integration.cpp +++ b/CYD-Klipper/src/core/octoprint/octoprint_printer_integration.cpp @@ -24,10 +24,10 @@ void configure_http_client(HTTPClient &client, String url_part, bool stream, int client.setConnectTimeout(timeout); } - client.begin("http://" + String(printer_config->klipper_host) + ":" + String(printer_config->klipper_port) + url_part); + client.begin("http://" + String(printer_config->printer_host) + ":" + String(printer_config->klipper_port) + url_part); if (printer_config->auth_configured) { - client.addHeader("X-Api-Key", printer_config->klipper_auth); + client.addHeader("X-Api-Key", printer_config->printer_auth); } } @@ -54,6 +54,7 @@ bool OctoPrinter::post_request(const char* endpoint, const char* body, int timeo timeout_ms = 500; } + LOG_F(("POST >>> %s %s\n", endpoint, body)); configure_http_client(client, endpoint, false, timeout_ms, printer_config); if (body[0] == '{' || body[0] == '[') @@ -61,8 +62,10 @@ bool OctoPrinter::post_request(const char* endpoint, const char* body, int timeo client.addHeader("Content-Type", "application/json"); } - int result = client.POST(body); - return result >= 200 && result < 300; + int http_code = client.POST(body); + bool result = http_code >= 200 && http_code < 300; + LOG_F(("<<< %d\n", http_code)); + return result; } bool OctoPrinter::send_gcode(const char* gcode, bool wait) @@ -77,7 +80,8 @@ bool OctoPrinter::send_gcode(const char* gcode, bool wait) for (char* iter = gcode_copy;; iter++) { - if (*iter == '\n' || *iter == '\0') + char cur_iter = *iter; + if (cur_iter == '\n' || cur_iter == '\0') { if (iter != last_line_start) { @@ -88,7 +92,7 @@ bool OctoPrinter::send_gcode(const char* gcode, bool wait) last_line_start = iter + 1; } - if (*iter == '\0') + if (cur_iter == '\0') { break; } @@ -100,7 +104,7 @@ bool OctoPrinter::send_gcode(const char* gcode, bool wait) } free(gcode_copy); - bool result = post_request("/api/printer/command/custom", out_buff); + bool result = post_request("/api/printer/command", out_buff); free(out_buff); return result; } @@ -109,9 +113,11 @@ bool OctoPrinter::move_printer(const char* axis, float amount, bool relative) { JsonDocument doc; char out_buff[512]; + out_buff[0] = tolower(axis[0]); + out_buff[1] = '\0'; doc["command"] = "jog"; - doc[axis] = amount; + doc[out_buff] = amount; doc["absolute"] = !relative; if (serializeJson(doc, out_buff, 512) >= 512) @@ -390,7 +396,7 @@ Files OctoPrinter::get_files() bool OctoPrinter::start_file(const char* filename) { char buff[512]; - sprintf("/api/files/local/%s", filename); + sprintf(buff, "/api/files/local/%s", filename); return post_request(buff, COMMAND_PRINT); } diff --git a/CYD-Klipper/src/core/octoprint/octoprint_printer_parsers.cpp b/CYD-Klipper/src/core/octoprint/octoprint_printer_parsers.cpp index fd0563e..786b690 100644 --- a/CYD-Klipper/src/core/octoprint/octoprint_printer_parsers.cpp +++ b/CYD-Klipper/src/core/octoprint/octoprint_printer_parsers.cpp @@ -120,13 +120,15 @@ void OctoPrinter::parse_file_list(JsonDocument &in, std::listprinter_name[0] == 0) ? config->klipper_host : config->printer_name; + const char* printer_name = (config->printer_name[0] == 0) ? config->printer_host : config->printer_name; if (i == global_config.printer_index && config->setup_complete) { @@ -122,7 +122,7 @@ static void host_update(lv_event_t * e) { lv_obj_t * ta = lv_event_get_target(e); const char* text = lv_textarea_get_text(ta); - strcpy(global_config.printer_config[global_config.printer_index].klipper_host, text); + strcpy(global_config.printer_config[global_config.printer_index].printer_host, text); global_config.printer_config[global_config.printer_index].ip_configured = text[0] != '\0'; } @@ -140,7 +140,7 @@ static void auth_update(lv_event_t * e) { lv_obj_t * ta = lv_event_get_target(e); const char* text = lv_textarea_get_text(ta); - strcpy(global_config.printer_config[global_config.printer_index].klipper_auth, text); + strcpy(global_config.printer_config[global_config.printer_index].printer_auth, text); global_config.printer_config[global_config.printer_index].auth_configured = text[0] != '\0'; } @@ -166,6 +166,10 @@ static void keyboard_event_ip_entry(lv_event_t * e) { { lv_keyboard_set_mode(kb, LV_KEYBOARD_MODE_USER_2); } + else if (lv_obj_has_flag(ta, LV_OBJ_FLAG_USER_3)) + { + lv_keyboard_set_mode(kb, LV_KEYBOARD_MODE_TEXT_LOWER); + } else { lv_keyboard_set_mode(kb, LV_KEYBOARD_MODE_NUMBER); @@ -309,7 +313,7 @@ void show_ip_entry() { char buff[10] = {0}; sprintf(buff, "%d", global_config.printer_config[global_config.printer_index].klipper_port); - lv_textarea_set_text(host_entry, global_config.printer_config[global_config.printer_index].klipper_host); + lv_textarea_set_text(host_entry, global_config.printer_config[global_config.printer_index].printer_host); lv_textarea_set_text(port_entry, buff); } else @@ -327,18 +331,18 @@ void show_ip_entry() global_config.printer_config[global_config.printer_index].klipper_port = 80; } - global_config.printer_config[global_config.printer_index].klipper_host[0] = '\0'; + global_config.printer_config[global_config.printer_index].printer_host[0] = '\0'; } if (global_config.printer_config[global_config.printer_index].auth_configured) { - lv_textarea_set_text(auth_entry, global_config.printer_config[global_config.printer_index].klipper_auth); + lv_textarea_set_text(auth_entry, global_config.printer_config[global_config.printer_index].printer_auth); } else { lv_textarea_set_text(auth_entry, ""); - global_config.printer_config[global_config.printer_index].klipper_auth[0] = '\0'; + global_config.printer_config[global_config.printer_index].printer_auth[0] = '\0'; } lv_obj_add_event_cb(host_entry, host_update, LV_EVENT_VALUE_CHANGED, NULL); @@ -373,6 +377,9 @@ void show_ip_entry() lv_textarea_set_placeholder_text(auth_entry, "Printer serial number"); break; case PrinterType::PrinterTypeOctoprint: + lv_obj_clear_flag(auth_entry, LV_OBJ_FLAG_USER_2); + lv_obj_add_flag(auth_entry, LV_OBJ_FLAG_USER_3); + lv_textarea_set_max_length(auth_entry, 48); lv_label_set_text(main_label, "Octoprint Setup"); lv_textarea_set_max_length(port_entry, 5); lv_textarea_set_placeholder_text(host_entry, "Octoprint Host"); diff --git a/CYD-Klipper/src/ui/panels/connecting_panel.cpp b/CYD-Klipper/src/ui/panels/connecting_panel.cpp index a182548..a653aa5 100644 --- a/CYD-Klipper/src/ui/panels/connecting_panel.cpp +++ b/CYD-Klipper/src/ui/panels/connecting_panel.cpp @@ -5,7 +5,7 @@ void connecting_panel_init(lv_obj_t* panel) { lv_obj_t* label = lv_label_create(panel); lv_label_set_text_fmt(label, "Connecting to %s...", (get_current_printer()->printer_config->printer_name[0] == 0) - ? get_current_printer()->printer_config->klipper_host + ? get_current_printer()->printer_config->printer_host : get_current_printer()->printer_config->printer_name); lv_obj_align(label, LV_ALIGN_CENTER, 0, 0); } \ No newline at end of file diff --git a/CYD-Klipper/src/ui/panels/macros_panel.cpp b/CYD-Klipper/src/ui/panels/macros_panel.cpp index 49f5ded..ef4c2fc 100644 --- a/CYD-Klipper/src/ui/panels/macros_panel.cpp +++ b/CYD-Klipper/src/ui/panels/macros_panel.cpp @@ -31,7 +31,7 @@ void macros_panel_init(lv_obj_t* panel) { if (macros_count <= 0){ label = lv_label_create(root_panel); if (get_current_printer()->printer_config->printer_type == PrinterType::PrinterTypeKlipper - || get_current_printer()->printer_config->printer_type == PrinterType::PrinterTypeKlipper) + || get_current_printer()->printer_config->printer_type == PrinterType::PrinterTypeKlipperSerial) { lv_label_set_text(label, "No macros found.\nMacros with the description\n\"CYD_SCREEN_MACRO\"\nwill show up here."); } diff --git a/CYD-Klipper/src/ui/panels/printer_panel.cpp b/CYD-Klipper/src/ui/panels/printer_panel.cpp index 5e22797..b11da02 100644 --- a/CYD-Klipper/src/ui/panels/printer_panel.cpp +++ b/CYD-Klipper/src/ui/panels/printer_panel.cpp @@ -22,7 +22,7 @@ static void update_printer_name_text(lv_event_t * e) lv_obj_t * label = lv_event_get_target(e); int config_index = (int)lv_event_get_user_data(e); BasePrinter* printer = get_printer(config_index); - lv_label_set_text(label, printer->printer_config->printer_name[0] == 0 ? printer->printer_config->klipper_host : printer->printer_config->printer_name); + lv_label_set_text(label, printer->printer_config->printer_name[0] == 0 ? printer->printer_config->printer_host : printer->printer_config->printer_name); } static void update_printer_status_text(lv_event_t * e) diff --git a/CYD-Klipper/src/ui/serial/serial_commands.cpp b/CYD-Klipper/src/ui/serial/serial_commands.cpp index 8dfe71c..b4b6e21 100644 --- a/CYD-Klipper/src/ui/serial/serial_commands.cpp +++ b/CYD-Klipper/src/ui/serial/serial_commands.cpp @@ -16,6 +16,11 @@ namespace serial_console { - optionally add handling the new preference to sets() and settings() if it modifies global_config */ +PrinterConfiguration* get_current_printer_config() +{ + return &global_config.printer_config[global_config.printer_index]; +} + HANDLER commandHandlers[] = { {"help", &help, 1}, {"reset", &reset, 1}, @@ -94,20 +99,20 @@ void sets(String argv[]) Serial.printf("erase ssid\n"); } - if(get_current_printer()->printer_config->ip_configured) + if(get_current_printer_config()->ip_configured) { - Serial.printf("ip %s %d\n",get_current_printer()->printer_config->klipper_host, get_current_printer()->printer_config->klipper_port); + Serial.printf("ip %s %d\n",get_current_printer_config()->printer_host, get_current_printer_config()->klipper_port); } else { Serial.printf("erase ip\n"); } - if(get_current_printer()->printer_config->auth_configured) + if(get_current_printer_config()->auth_configured) { Serial.printf("key %s\n", #if DISPLAY_SECRETS - get_current_printer()->printer_config->klipper_auth + get_current_printer_config()->printer_auth #else "[redacted]" #endif @@ -135,9 +140,9 @@ void sets(String argv[]) void settings(String argv[]) { - if(get_current_printer()->printer_config->printer_name[0] != 0) + if(get_current_printer_config()->printer_name[0] != 0) { - Serial.printf("Current printer# %d name: %s",global_config.printer_index, get_current_printer()->printer_config->printer_name); + Serial.printf("Current printer# %d name: %s",global_config.printer_index, get_current_printer_config()->printer_name); } else { @@ -162,20 +167,20 @@ void settings(String argv[]) Serial.printf("Wifi not configured\n"); } - if(get_current_printer()->printer_config->ip_configured) + if(get_current_printer_config()->ip_configured) { - Serial.printf("Moonraker address: %s:%d\n",get_current_printer()->printer_config->klipper_host, get_current_printer()->printer_config->klipper_port); + Serial.printf("Moonraker address: %s:%d\n",get_current_printer_config()->printer_host, get_current_printer_config()->klipper_port); } else { Serial.printf("Moonraker address not configured\n"); } - if(get_current_printer()->printer_config->auth_configured) + if(get_current_printer_config()->auth_configured) { Serial.printf("Moonraker API key: %s\n", #if DISPLAY_SECRETS - get_current_printer()->printer_config->klipper_auth + get_current_printer_config()->printer_auth #else "[redacted]" #endif @@ -205,15 +210,15 @@ void erase_one(const String arg) { if(arg == "key") { - get_current_printer()->printer_config->auth_configured = false; + get_current_printer_config()->auth_configured = false; // overwrite the key to make it unrecoverable for 3rd parties - memset(get_current_printer()->printer_config->klipper_auth,0,32); + memset(get_current_printer_config()->printer_auth,0,64); write_global_config(); } else if(arg == "ip") { - get_current_printer()->printer_config->setup_complete = false; - get_current_printer()->printer_config->ip_configured = false; + get_current_printer_config()->setup_complete = false; + get_current_printer_config()->ip_configured = false; write_global_config(); } else if(arg == "touch") @@ -252,14 +257,8 @@ void erase(String argv[]) void key(String argv[]) { - if (argv[1].length() != 32) - { - Serial.println("Key must be 32 characters"); - return; - } - - get_current_printer()->printer_config->auth_configured = true; - strncpy(get_current_printer()->printer_config->klipper_auth, argv[1].c_str(), sizeof(global_config.printer_config[0].klipper_auth)); + get_current_printer_config()->auth_configured = true; + strncpy(get_current_printer_config()->printer_auth, argv[1].c_str(), sizeof(global_config.printer_config[0].printer_auth)); write_global_config(); } @@ -283,10 +282,10 @@ void ssid(String argv[]) void ip(String argv[]) { - strncpy(get_current_printer()->printer_config->klipper_host, argv[1].c_str(), sizeof(global_config.printer_config[0].klipper_host)-1); - get_current_printer()->printer_config->klipper_port = argv[2].toInt(); - get_current_printer()->printer_config->ip_configured = true; - get_current_printer()->printer_config->setup_complete = true; + strncpy(get_current_printer_config()->printer_host, argv[1].c_str(), sizeof(global_config.printer_config[0].printer_host)-1); + get_current_printer_config()->klipper_port = argv[2].toInt(); + get_current_printer_config()->ip_configured = true; + get_current_printer_config()->setup_complete = true; write_global_config(); } From 4dd70aa3ea465a85102103c819957b80e6e03216 Mon Sep 17 00:00:00 2001 From: Sims <38142618+suchmememanyskill@users.noreply.github.com> Date: Thu, 19 Dec 2024 18:17:40 +0100 Subject: [PATCH 56/63] Add bambu panels --- .../core/bambu/bambu_printer_integration.hpp | 11 ++- .../src/core/bambu/bambu_printer_panels.cpp | 83 +++++++++++++++++++ .../src/core/bambu/bambu_printer_parsers.cpp | 12 +-- CYD-Klipper/src/core/common/constants.cpp | 15 ++++ CYD-Klipper/src/core/common/constants.h | 14 ++++ .../core/klipper/klipper_printer_panels.cpp | 15 +--- .../octoprint/octoprint_printer_panels.cpp | 22 ++--- 7 files changed, 144 insertions(+), 28 deletions(-) create mode 100644 CYD-Klipper/src/core/bambu/bambu_printer_panels.cpp create mode 100644 CYD-Klipper/src/core/common/constants.cpp create mode 100644 CYD-Klipper/src/core/common/constants.h diff --git a/CYD-Klipper/src/core/bambu/bambu_printer_integration.hpp b/CYD-Klipper/src/core/bambu/bambu_printer_integration.hpp index c878be7..0ecd156 100644 --- a/CYD-Klipper/src/core/bambu/bambu_printer_integration.hpp +++ b/CYD-Klipper/src/core/bambu/bambu_printer_integration.hpp @@ -4,13 +4,21 @@ #include #include +enum BambuSpeedProfile +{ + BambuSpeedProfileSilent = 1, + BambuSpeedProfileNormal = 2, + BambuSpeedProfileSport = 3, + BambuSpeedProfileLudicrous = 4, +} + class BambuPrinter : public BasePrinter { private: unsigned int last_error = 0; unsigned int ignore_error = 0; bool publish_mqtt_command(const char* command); - unsigned char speed_profile = 2; + BambuSpeedProfile speed_profile = 2; unsigned long print_start; union { @@ -25,6 +33,7 @@ class BambuPrinter : public BasePrinter protected: void parse_state(JsonDocument& in); + void init_ui_panels(); Files parse_files(WiFiClientSecure& client, int max_files); public: diff --git a/CYD-Klipper/src/core/bambu/bambu_printer_panels.cpp b/CYD-Klipper/src/core/bambu/bambu_printer_panels.cpp new file mode 100644 index 0000000..2d7cb1e --- /dev/null +++ b/CYD-Klipper/src/core/bambu/bambu_printer_panels.cpp @@ -0,0 +1,83 @@ +#include "bambu_printer_integration.hpp" +#include "lvgl.h" +#include "../../ui/ui_utils.h" +#include +#include "../common/constants.h" + +const char* speed_profiles[] = { "Silent (50%)", "Normal (100%)", "Sport (124%)", "Ludicrous (166%)" }; +const BambuSpeedProfile speed_profile_values[] = { BambuSpeedProfileSilent, BambuSpeedProfileNormal, BambuSpeedProfileSport, BambuSpeedProfileLudicrous }; + +// TODO: Move to common +static void set_fan_speed_text(lv_event_t * e) { + lv_obj_t * label = lv_event_get_target(e); + char data[16]; + sprintf(data, "Fan: %.0f%%", get_current_printer_data()->fan_speed * 100); + lv_label_set_text(label, data); +} + +static void set_fan_speed(lv_event_t * e){ + int speed = (int)lv_event_get_user_data(e); + BambuPrinter* printer = (BambuPrinter*)get_current_printer(); // TODO: pass by ref + // TODO: Implement +} + +FAN_SPEED_COLUMN(set_fan_speed, fan_speed_columns) + +static void set_aux_fan_speed_text(lv_event_t * e) { + // TODO: Implement + lv_obj_t * label = lv_event_get_target(e); + char data[16]; + sprintf(data, "Fan: %.0f%%", get_current_printer_data()->fan_speed * 100); + lv_label_set_text(label, data); +} + +static void set_aux_fan_speed(lv_event_t * e){ + int speed = (int)lv_event_get_user_data(e); + BambuPrinter* printer = (BambuPrinter*)get_current_printer(); // TODO: pass by ref + // TODO: Implement +} + +FAN_SPEED_COLUMN(set_aux_fan_speed, aux_fan_speed_columns) + +// TODO: move to common +static void set_speed_mult_text(lv_event_t * e){ + lv_obj_t * label = lv_event_get_target(e); + char data[16]; + sprintf(data, "Speed: %.0f%%", get_current_printer_data()->speed_mult * 100); + lv_label_set_text(label, data); +} + +static void set_speed_mult(lv_event_t * e) +{ + BambuSpeedProfile speed = (BambuSpeedProfile)lv_event_get_user_data(e); + BambuPrinter* printer = (BambuPrinter*)get_current_printer(); // TODO: pass by ref + // TODO: Implement +} + +lv_button_column_t speed_profile_columns[] = { + { set_speed_mult, speed_profiles, (const void**)speed_profile_values, 4}, +}; + +static void open_fan_speed_panel(lv_event_t * e){ + lv_create_fullscreen_button_matrix_popup(lv_scr_act(), set_fan_speed_text, fan_speed_columns, 3); +} + +static void open_aux_fan_speed_panel(lv_event_t * e){ + lv_create_fullscreen_button_matrix_popup(lv_scr_act(), set_aux_fan_speed_text, aux_fan_speed_columns, 3); +} + +static void open_speed_mult_panel(lv_event_t * e){ + lv_create_fullscreen_button_matrix_popup(lv_scr_act(), set_speed_mult_text, speed_profile_columns, 1); +} + +static PrinterUiPanel bambu_ui_panels[3] { + { .set_label = (void*)set_fan_speed_text, .open_panel = (void*)open_fan_speed_panel }, + { .set_label = (void*)set_aux_fan_speed_text, .open_panel = (void*)open_aux_fan_speed_panel }, + { .set_label = (void*)set_speed_mult_text, .open_panel = (void*)open_speed_mult_panel }, +}; + +void BambuPrinter::init_ui_panels() +{ + custom_menus_count = 3; + custom_menus = bambu_ui_panels; +} \ No newline at end of file diff --git a/CYD-Klipper/src/core/bambu/bambu_printer_parsers.cpp b/CYD-Klipper/src/core/bambu/bambu_printer_parsers.cpp index 6d9bafb..9fa2bb4 100644 --- a/CYD-Klipper/src/core/bambu/bambu_printer_parsers.cpp +++ b/CYD-Klipper/src/core/bambu/bambu_printer_parsers.cpp @@ -83,21 +83,23 @@ void BambuPrinter::parse_state(JsonDocument& in) if (print.containsKey("spd_lvl")) { - speed_profile = print["spd_lvl"]; + int speed_profile_int = print["spd_lvl"] + speed_profile = (BambuSpeedProfile)speed_profile_int; switch (speed_profile) { - case 1: + case BambuSpeedProfileSilent: printer_data.speed_mult = 0.5f; break; - case 2: + case BambuSpeedProfileNormal: printer_data.speed_mult = 1.0f; break; - case 3: + case BambuSpeedProfileSport: printer_data.speed_mult = 1.24f; break; - case 4: + case BambuSpeedProfileLudicrous: printer_data.speed_mult = 1.66f; + break; } } diff --git a/CYD-Klipper/src/core/common/constants.cpp b/CYD-Klipper/src/core/common/constants.cpp new file mode 100644 index 0000000..3613307 --- /dev/null +++ b/CYD-Klipper/src/core/common/constants.cpp @@ -0,0 +1,15 @@ +#include "constants.h" + +const char* fan_speeds_col_1[] = { "On", "Off" }; +const int fan_speeds_col_1_values[] = { 0, 100 }; + +const char* fan_speeds_col_2[] = { "10%", "20%", "30%", "40%"}; +const int fan_speeds_col_2_values[] = { 10, 20, 30, 40 }; + +const char* fan_speeds_col_3[] = { "50%", "60%", "70%", "80%"}; +const int fan_speeds_col_3_values[] = { 50, 60, 70, 80 }; + +char fan_percent_to_byte(int percent) +{ + return percent * 255 / 100; +} \ No newline at end of file diff --git a/CYD-Klipper/src/core/common/constants.h b/CYD-Klipper/src/core/common/constants.h new file mode 100644 index 0000000..2eadda7 --- /dev/null +++ b/CYD-Klipper/src/core/common/constants.h @@ -0,0 +1,14 @@ +#pragma once + +extern const char* fan_speeds_col_1[]; +extern const int fan_speeds_col_1_values[]; + +extern const char* fan_speeds_col_2[]; +extern const int fan_speeds_col_2_values[]; + +extern const char* fan_speeds_col_3[]; +extern const int fan_speeds_col_3_values[]; + +unsigned char fan_percent_to_byte(int percent); + +#define FAN_SPEED_COLUMN(set_fan_speed, column_name) lv_button_column_t column_name[] = {{ set_fan_speed, fan_speeds_col_2, (const void**)fan_speeds_col_2_values, 4},{ set_fan_speed, fan_speeds_col_3, (const void**)fan_speeds_col_3_values, 4}, { set_fan_speed, fan_speeds_col_1, (const void**)fan_speeds_col_1_values, 2}}; \ No newline at end of file diff --git a/CYD-Klipper/src/core/klipper/klipper_printer_panels.cpp b/CYD-Klipper/src/core/klipper/klipper_printer_panels.cpp index de9e394..4b7b51a 100644 --- a/CYD-Klipper/src/core/klipper/klipper_printer_panels.cpp +++ b/CYD-Klipper/src/core/klipper/klipper_printer_panels.cpp @@ -1,6 +1,7 @@ #include "klipper_printer_integration.hpp" #include "lvgl.h" #include "../../ui/ui_utils.h" +#include "../common/constants.h" #include static void set_fan_speed_text(lv_event_t * e) { @@ -12,22 +13,14 @@ static void set_fan_speed_text(lv_event_t * e) { static void set_fan_speed(lv_event_t * e){ int speed = (int)lv_event_get_user_data(e); + int actual_speed = fan_percent_to_byte(speed); KlipperPrinter* printer = (KlipperPrinter*)get_current_printer(); // TODO: pass by ref char gcode[16]; - sprintf(gcode, "M106 S%d", speed); + sprintf(gcode, "M106 S%d", actual_speed); printer->send_gcode(gcode); } -const char* fan_speeds[] = { "0%", "15%", "25%", "35%" }; -const int fan_speeds_values[] = { 0, 38, 64, 90 }; - -const char* fan_speeds_2[] = { "50%", "75%", "100%"}; -const int fan_speeds_values_2[] = { 128, 192, 255 }; - -lv_button_column_t fan_speed_columns[] = { - { set_fan_speed, fan_speeds, (const void**)fan_speeds_values, 4}, - { set_fan_speed, fan_speeds_2, (const void**)fan_speeds_values_2, 3} -}; +FAN_SPEED_COLUMN(set_fan_speed, fan_speed_columns) static void set_zoffset_text(lv_event_t * e) { lv_obj_t * label = lv_event_get_target(e); diff --git a/CYD-Klipper/src/core/octoprint/octoprint_printer_panels.cpp b/CYD-Klipper/src/core/octoprint/octoprint_printer_panels.cpp index c40b409..1926763 100644 --- a/CYD-Klipper/src/core/octoprint/octoprint_printer_panels.cpp +++ b/CYD-Klipper/src/core/octoprint/octoprint_printer_panels.cpp @@ -2,6 +2,7 @@ #include "lvgl.h" #include "../../ui/ui_utils.h" #include +#include "../common/constants.h" const char* COMMAND_EXTRUDE_MULT = "{\"command\":\"flowrate\",\"factor\":%d}"; @@ -51,19 +52,18 @@ bool get_range(lv_event_t * e, int min, int max, int* out) static void set_fan_speed(lv_event_t * e) { - int fan_speed = 0; - if (get_range(e, 0, 100, &fan_speed)) - { - int actual_fan_speed = fan_speed * 255 / 100; - char buff[16]; - sprintf(buff, "M106 S%d", actual_fan_speed); - ((OctoPrinter*)get_current_printer())->send_gcode(buff); - } + int speed = (int)lv_event_get_user_data(e); + int actual_fan_speed = fan_percent_to_byte(speed); + char buff[16]; + sprintf(buff, "M106 S%d", actual_fan_speed); + ((OctoPrinter*)get_current_printer())->send_gcode(buff); } -static void open_fan_speed_keypad(lv_event_t * e) +FAN_SPEED_COLUMN(set_fan_speed, fan_speed_columns) + +static void open_fan_speed_panel(lv_event_t * e) { - lv_create_keyboard_text_entry(set_fan_speed, "New fan speed %", LV_KEYBOARD_MODE_NUMBER); + lv_create_fullscreen_button_matrix_popup(lv_scr_act(), set_fan_speed_text, fan_speed_columns, 3); } static void set_speed_mult(lv_event_t * e) @@ -99,7 +99,7 @@ static void open_extrude_mult_keypad(lv_event_t * e) } static PrinterUiPanel klipper_ui_panels[4] { - { .set_label = (void*)set_fan_speed_text, .open_panel = (void*)open_fan_speed_keypad }, + { .set_label = (void*)set_fan_speed_text, .open_panel = (void*)open_fan_speed_panel }, { .set_label = (void*)set_speed_mult_text, .open_panel = (void*)open_speed_mult_keypad }, { .set_label = (void*)set_extruder_mult_text, .open_panel = (void*)open_extrude_mult_keypad }, }; From 093dd5efffa5893f346db9f293cd8e609de97a8f Mon Sep 17 00:00:00 2001 From: suchmememanyskill <38142618+suchmememanyskill@users.noreply.github.com> Date: Sat, 21 Dec 2024 22:04:51 +0100 Subject: [PATCH 57/63] Add fan/speed controls to bambu --- .../core/bambu/bambu_printer_integration.hpp | 11 +- .../src/core/bambu/bambu_printer_panels.cpp | 113 +++++++++++++----- .../src/core/bambu/bambu_printer_parsers.cpp | 29 ++++- CYD-Klipper/src/core/common/constants.cpp | 12 +- CYD-Klipper/src/core/common/constants.h | 2 +- .../core/klipper/klipper_printer_panels.cpp | 4 +- .../octoprint/octoprint_printer_panels.cpp | 4 +- CYD-Klipper/src/ui/ip_setup.cpp | 6 +- CYD-Klipper/src/ui/ui_utils.cpp | 3 +- CYD-Klipper/src/ui/wifi_setup.cpp | 1 + 10 files changed, 139 insertions(+), 46 deletions(-) diff --git a/CYD-Klipper/src/core/bambu/bambu_printer_integration.hpp b/CYD-Klipper/src/core/bambu/bambu_printer_integration.hpp index 0ecd156..5c266b2 100644 --- a/CYD-Klipper/src/core/bambu/bambu_printer_integration.hpp +++ b/CYD-Klipper/src/core/bambu/bambu_printer_integration.hpp @@ -10,15 +10,13 @@ enum BambuSpeedProfile BambuSpeedProfileNormal = 2, BambuSpeedProfileSport = 3, BambuSpeedProfileLudicrous = 4, -} +}; class BambuPrinter : public BasePrinter { private: unsigned int last_error = 0; unsigned int ignore_error = 0; - bool publish_mqtt_command(const char* command); - BambuSpeedProfile speed_profile = 2; unsigned long print_start; union { @@ -37,6 +35,10 @@ class BambuPrinter : public BasePrinter Files parse_files(WiFiClientSecure& client, int max_files); public: + float aux_fan_speed; + float chamber_fan_speed; + BambuSpeedProfile speed_profile = BambuSpeedProfileNormal; + BambuPrinter(int index) : BasePrinter(index) { supported_features = PrinterFeatureHome @@ -59,6 +61,8 @@ class BambuPrinter : public BasePrinter bambu_misc = 0; printer_data.error_screen_features = PrinterFeatureRetryError | PrinterFeatureIgnoreError | PrinterFeatureContinueError; print_start = millis(); + + init_ui_panels(); } bool move_printer(const char* axis, float amount, bool relative); @@ -79,6 +83,7 @@ class BambuPrinter : public BasePrinter bool set_target_temperature(PrinterTemperatureDevice device, unsigned int temperature); bool send_gcode(const char* gcode, bool wait = true); void receive_data(unsigned char* data, unsigned int length); + bool publish_mqtt_command(const char* command); }; enum BambuConnectionStatus { diff --git a/CYD-Klipper/src/core/bambu/bambu_printer_panels.cpp b/CYD-Klipper/src/core/bambu/bambu_printer_panels.cpp index 2d7cb1e..6362f3f 100644 --- a/CYD-Klipper/src/core/bambu/bambu_printer_panels.cpp +++ b/CYD-Klipper/src/core/bambu/bambu_printer_panels.cpp @@ -6,78 +6,137 @@ const char* speed_profiles[] = { "Silent (50%)", "Normal (100%)", "Sport (124%)", "Ludicrous (166%)" }; const BambuSpeedProfile speed_profile_values[] = { BambuSpeedProfileSilent, BambuSpeedProfileNormal, BambuSpeedProfileSport, BambuSpeedProfileLudicrous }; +const char* COMMAND_SET_PRINT_SPEED = "{\"print\":{\"command\":\"print_speed\",\"param\":\"%d\"}}"; -// TODO: Move to common -static void set_fan_speed_text(lv_event_t * e) { +enum FanIndex +{ + PartFan = 1, + AuxFan = 2, + ChamberFan = 3, +}; + +static void set_fan_speed_text(lv_event_t* e, FanIndex index) +{ lv_obj_t * label = lv_event_get_target(e); char data[16]; - sprintf(data, "Fan: %.0f%%", get_current_printer_data()->fan_speed * 100); + + float fan_speed = 0; + const char* fan_type = ""; + + switch (index) + { + case PartFan: + fan_speed = get_current_printer_data()->fan_speed; + fan_type = "P.Fan"; + break; + case AuxFan: + fan_speed = ((BambuPrinter*)get_current_printer)->aux_fan_speed; + fan_type = "A.Fan"; + break; + case ChamberFan: + fan_speed = ((BambuPrinter*)get_current_printer)->chamber_fan_speed; + fan_type = "C.Fan"; + break; + } + + sprintf(data, "%s: %.0f%%", fan_type, get_current_printer_data()->fan_speed * 100); lv_label_set_text(label, data); } -static void set_fan_speed(lv_event_t * e){ +static void set_fan_speed(lv_event_t* e, FanIndex index) +{ int speed = (int)lv_event_get_user_data(e); + int actual_speed = fan_percent_to_byte(speed); BambuPrinter* printer = (BambuPrinter*)get_current_printer(); // TODO: pass by ref - // TODO: Implement + char buff[20]; + sprintf(buff, "M106 P%d S%d", index, actual_speed); + printer->send_gcode(buff); } -FAN_SPEED_COLUMN(set_fan_speed, fan_speed_columns) +static void set_part_fan_speed_text(lv_event_t * e) +{ + set_fan_speed_text(e, FanIndex::PartFan); +} -static void set_aux_fan_speed_text(lv_event_t * e) { - // TODO: Implement - lv_obj_t * label = lv_event_get_target(e); - char data[16]; - sprintf(data, "Fan: %.0f%%", get_current_printer_data()->fan_speed * 100); - lv_label_set_text(label, data); +static void set_part_fan_speed(lv_event_t * e) +{ + set_fan_speed(e, FanIndex::PartFan); } -static void set_aux_fan_speed(lv_event_t * e){ - int speed = (int)lv_event_get_user_data(e); - BambuPrinter* printer = (BambuPrinter*)get_current_printer(); // TODO: pass by ref - // TODO: Implement +FAN_SPEED_COLUMN(set_part_fan_speed, part_fan_speed_columns) + +static void set_aux_fan_speed_text(lv_event_t * e) +{ + set_fan_speed_text(e, FanIndex::AuxFan); +} + +static void set_aux_fan_speed(lv_event_t * e) +{ + set_fan_speed(e, FanIndex::AuxFan); } FAN_SPEED_COLUMN(set_aux_fan_speed, aux_fan_speed_columns) +static void set_chamber_fan_speed_text(lv_event_t * e) +{ + set_fan_speed_text(e, FanIndex::ChamberFan); +} + +static void set_chamber_fan_speed(lv_event_t * e) +{ + set_fan_speed(e, FanIndex::ChamberFan); +} + +FAN_SPEED_COLUMN(set_chamber_fan_speed, chamber_fan_speed_columns) + // TODO: move to common static void set_speed_mult_text(lv_event_t * e){ lv_obj_t * label = lv_event_get_target(e); - char data[16]; - sprintf(data, "Speed: %.0f%%", get_current_printer_data()->speed_mult * 100); - lv_label_set_text(label, data); + char buff[16]; + sprintf(buff, "Speed: %.0f%%", get_current_printer_data()->speed_mult * 100); + lv_label_set_text(label, buff); } static void set_speed_mult(lv_event_t * e) { - BambuSpeedProfile speed = (BambuSpeedProfile)lv_event_get_user_data(e); + BambuSpeedProfile speed = (BambuSpeedProfile)((int)lv_event_get_user_data(e)); BambuPrinter* printer = (BambuPrinter*)get_current_printer(); // TODO: pass by ref - // TODO: Implement + char buff[128]; + + sprintf(buff, COMMAND_SET_PRINT_SPEED, speed); + printer->publish_mqtt_command(buff); } lv_button_column_t speed_profile_columns[] = { { set_speed_mult, speed_profiles, (const void**)speed_profile_values, 4}, }; -static void open_fan_speed_panel(lv_event_t * e){ - lv_create_fullscreen_button_matrix_popup(lv_scr_act(), set_fan_speed_text, fan_speed_columns, 3); +static void open_part_fan_speed_panel(lv_event_t * e){ + lv_create_fullscreen_button_matrix_popup(lv_scr_act(), set_part_fan_speed_text, part_fan_speed_columns, 3); } static void open_aux_fan_speed_panel(lv_event_t * e){ lv_create_fullscreen_button_matrix_popup(lv_scr_act(), set_aux_fan_speed_text, aux_fan_speed_columns, 3); } +static void open_chamber_fan_speed_panel(lv_event_t * e){ + lv_create_fullscreen_button_matrix_popup(lv_scr_act(), set_chamber_fan_speed_text, chamber_fan_speed_columns, 3); +} + + static void open_speed_mult_panel(lv_event_t * e){ lv_create_fullscreen_button_matrix_popup(lv_scr_act(), set_speed_mult_text, speed_profile_columns, 1); } -static PrinterUiPanel bambu_ui_panels[3] { - { .set_label = (void*)set_fan_speed_text, .open_panel = (void*)open_fan_speed_panel }, - { .set_label = (void*)set_aux_fan_speed_text, .open_panel = (void*)open_aux_fan_speed_panel }, +static PrinterUiPanel bambu_ui_panels[4] { { .set_label = (void*)set_speed_mult_text, .open_panel = (void*)open_speed_mult_panel }, + { .set_label = (void*)set_part_fan_speed_text, .open_panel = (void*)open_part_fan_speed_panel }, + { .set_label = (void*)set_chamber_fan_speed_text, .open_panel = (void*)open_chamber_fan_speed_panel }, + { .set_label = (void*)set_aux_fan_speed_text, .open_panel = (void*)open_aux_fan_speed_panel }, }; void BambuPrinter::init_ui_panels() { - custom_menus_count = 3; + custom_menus_count = 4; custom_menus = bambu_ui_panels; } \ No newline at end of file diff --git a/CYD-Klipper/src/core/bambu/bambu_printer_parsers.cpp b/CYD-Klipper/src/core/bambu/bambu_printer_parsers.cpp index 9fa2bb4..d2c2b8e 100644 --- a/CYD-Klipper/src/core/bambu/bambu_printer_parsers.cpp +++ b/CYD-Klipper/src/core/bambu/bambu_printer_parsers.cpp @@ -6,6 +6,18 @@ #define BIT_Y_AXIS_HOMED BIT(1) #define BIT_Z_AXIS_HOMED BIT(2) +float convert_fan_speed(const char* in) +{ + if (in == NULL || strlen(in) <= 0) + { + return 0; + } + + int part_value = atoi(in); + float percentage = (part_value / 15.0f) * 100; + return round(percentage / 10) / 10; +} + void BambuPrinter::parse_state(JsonDocument& in) { if (!in.containsKey("print")) @@ -83,7 +95,7 @@ void BambuPrinter::parse_state(JsonDocument& in) if (print.containsKey("spd_lvl")) { - int speed_profile_int = print["spd_lvl"] + int speed_profile_int = print["spd_lvl"]; speed_profile = (BambuSpeedProfile)speed_profile_int; switch (speed_profile) @@ -201,6 +213,21 @@ void BambuPrinter::parse_state(JsonDocument& in) } } + if (print.containsKey("cooling_fan_speed")) + { + printer_data.fan_speed = convert_fan_speed(print["cooling_fan_speed"]); + } + + if (print.containsKey("big_fan1_speed")) + { + aux_fan_speed = convert_fan_speed(print["big_fan1_speed"]); + } + + if (print.containsKey("big_fan2_speed")) + { + chamber_fan_speed = convert_fan_speed(print["big_fan2_speed"]); + } + printer_data.extrude_mult = 1; } diff --git a/CYD-Klipper/src/core/common/constants.cpp b/CYD-Klipper/src/core/common/constants.cpp index 3613307..90b56f8 100644 --- a/CYD-Klipper/src/core/common/constants.cpp +++ b/CYD-Klipper/src/core/common/constants.cpp @@ -1,15 +1,15 @@ #include "constants.h" const char* fan_speeds_col_1[] = { "On", "Off" }; -const int fan_speeds_col_1_values[] = { 0, 100 }; +const int fan_speeds_col_1_values[] = { 100, 0 }; -const char* fan_speeds_col_2[] = { "10%", "20%", "30%", "40%"}; -const int fan_speeds_col_2_values[] = { 10, 20, 30, 40 }; +const char* fan_speeds_col_2[] = { "10%", "20%", "30%", "40%", "50%"}; +const int fan_speeds_col_2_values[] = { 10, 20, 30, 40, 50 }; -const char* fan_speeds_col_3[] = { "50%", "60%", "70%", "80%"}; -const int fan_speeds_col_3_values[] = { 50, 60, 70, 80 }; +const char* fan_speeds_col_3[] = { "60%", "70%", "80%", "90%"}; +const int fan_speeds_col_3_values[] = { 60, 70, 80, 90 }; -char fan_percent_to_byte(int percent) +unsigned char fan_percent_to_byte(int percent) { return percent * 255 / 100; } \ No newline at end of file diff --git a/CYD-Klipper/src/core/common/constants.h b/CYD-Klipper/src/core/common/constants.h index 2eadda7..be7e92a 100644 --- a/CYD-Klipper/src/core/common/constants.h +++ b/CYD-Klipper/src/core/common/constants.h @@ -11,4 +11,4 @@ extern const int fan_speeds_col_3_values[]; unsigned char fan_percent_to_byte(int percent); -#define FAN_SPEED_COLUMN(set_fan_speed, column_name) lv_button_column_t column_name[] = {{ set_fan_speed, fan_speeds_col_2, (const void**)fan_speeds_col_2_values, 4},{ set_fan_speed, fan_speeds_col_3, (const void**)fan_speeds_col_3_values, 4}, { set_fan_speed, fan_speeds_col_1, (const void**)fan_speeds_col_1_values, 2}}; \ No newline at end of file +#define FAN_SPEED_COLUMN(set_fan_speed, column_name) lv_button_column_t column_name[] = {{ set_fan_speed, fan_speeds_col_2, (const void**)fan_speeds_col_2_values, 5},{ set_fan_speed, fan_speeds_col_3, (const void**)fan_speeds_col_3_values, 4}, { set_fan_speed, fan_speeds_col_1, (const void**)fan_speeds_col_1_values, 2}}; \ No newline at end of file diff --git a/CYD-Klipper/src/core/klipper/klipper_printer_panels.cpp b/CYD-Klipper/src/core/klipper/klipper_printer_panels.cpp index 4b7b51a..c00418b 100644 --- a/CYD-Klipper/src/core/klipper/klipper_printer_panels.cpp +++ b/CYD-Klipper/src/core/klipper/klipper_printer_panels.cpp @@ -20,7 +20,7 @@ static void set_fan_speed(lv_event_t * e){ printer->send_gcode(gcode); } -FAN_SPEED_COLUMN(set_fan_speed, fan_speed_columns) +FAN_SPEED_COLUMN(set_fan_speed, klipper_fan_speed_columns) static void set_zoffset_text(lv_event_t * e) { lv_obj_t * label = lv_event_get_target(e); @@ -145,7 +145,7 @@ lv_button_column_t extrude_mult_columns[] = { }; static void open_fan_speed_panel(lv_event_t * e){ - lv_create_fullscreen_button_matrix_popup(lv_scr_act(), set_fan_speed_text, fan_speed_columns, 2); + lv_create_fullscreen_button_matrix_popup(lv_scr_act(), set_fan_speed_text, klipper_fan_speed_columns, 2); } static void open_zoffset_panel(lv_event_t * e){ diff --git a/CYD-Klipper/src/core/octoprint/octoprint_printer_panels.cpp b/CYD-Klipper/src/core/octoprint/octoprint_printer_panels.cpp index 1926763..f513c51 100644 --- a/CYD-Klipper/src/core/octoprint/octoprint_printer_panels.cpp +++ b/CYD-Klipper/src/core/octoprint/octoprint_printer_panels.cpp @@ -59,11 +59,11 @@ static void set_fan_speed(lv_event_t * e) ((OctoPrinter*)get_current_printer())->send_gcode(buff); } -FAN_SPEED_COLUMN(set_fan_speed, fan_speed_columns) +FAN_SPEED_COLUMN(set_fan_speed, octo_fan_speed_columns) static void open_fan_speed_panel(lv_event_t * e) { - lv_create_fullscreen_button_matrix_popup(lv_scr_act(), set_fan_speed_text, fan_speed_columns, 3); + lv_create_fullscreen_button_matrix_popup(lv_scr_act(), set_fan_speed_text, octo_fan_speed_columns, 3); } static void set_speed_mult(lv_event_t * e) diff --git a/CYD-Klipper/src/ui/ip_setup.cpp b/CYD-Klipper/src/ui/ip_setup.cpp index 8d62e92..b5bab46 100644 --- a/CYD-Klipper/src/ui/ip_setup.cpp +++ b/CYD-Klipper/src/ui/ip_setup.cpp @@ -467,10 +467,10 @@ void choose_printer_type() lv_obj_t * label = lv_label_create(root); lv_label_set_text(label, "Choose printer type"); - create_printer_type_button(root, "Klipper", printer_type_klipper); + create_printer_type_button(root, "Klipper (Wifi)", printer_type_klipper); create_printer_type_button(root, "Klipper (Serial/USB)", printer_type_serial_klipper, false); - create_printer_type_button(root, "Bambu (Local)", printer_type_bambu_local); - create_printer_type_button(root, "Octoprint", printer_type_octoprint); + create_printer_type_button(root, "Bambu (Wifi, Local) [BETA]", printer_type_bambu_local); + create_printer_type_button(root, "Octoprint (Wifi) [BETA]", printer_type_octoprint); if (global_config.wifi_configuration_skipped) { diff --git a/CYD-Klipper/src/ui/ui_utils.cpp b/CYD-Klipper/src/ui/ui_utils.cpp index 0fcccf1..7faa561 100644 --- a/CYD-Klipper/src/ui/ui_utils.cpp +++ b/CYD-Klipper/src/ui/ui_utils.cpp @@ -90,7 +90,8 @@ void lv_create_fullscreen_button_matrix_popup(lv_obj_t * root, lv_event_cb_t tit for (int j = 0; j < columns[i].length; j++){ lv_obj_t * btn = lv_btn_create(column); - lv_obj_set_size(btn, column_width, CYD_SCREEN_MIN_BUTTON_HEIGHT_PX); + lv_obj_set_width(btn, column_width); + lv_obj_set_flex_grow(btn, 1); lv_obj_add_event_cb(btn, columns[i].event, LV_EVENT_CLICKED, (void*)columns[i].data[j]); label = lv_label_create(btn); diff --git a/CYD-Klipper/src/ui/wifi_setup.cpp b/CYD-Klipper/src/ui/wifi_setup.cpp index 9c25694..a91d0f6 100644 --- a/CYD-Klipper/src/ui/wifi_setup.cpp +++ b/CYD-Klipper/src/ui/wifi_setup.cpp @@ -120,6 +120,7 @@ static void wifi_btn_settings(lv_event_t * e){ lv_obj_t * btn = lv_btn_create(panel); lv_obj_add_event_cb(btn, reset_btn_event_handler, LV_EVENT_CLICKED, NULL); + lv_obj_set_style_radius(btn, 0, 0); lv_obj_set_size(btn, LV_PCT(100), CYD_SCREEN_MIN_BUTTON_HEIGHT_PX); lv_obj_t * label = lv_label_create(btn); From 161c10a43b5e54885a7263f518ed505e2f3e873a Mon Sep 17 00:00:00 2001 From: suchmememanyskill <38142618+suchmememanyskill@users.noreply.github.com> Date: Sun, 22 Dec 2024 00:14:49 +0100 Subject: [PATCH 58/63] Start print in bambu integration --- .../core/bambu/bambu_printer_integration.cpp | 6 +- .../core/bambu/bambu_printer_integration.hpp | 22 ++-- .../src/core/bambu/bambu_printer_panels.cpp | 115 ++++++++++++++++++ .../src/core/bambu/bambu_printer_parsers.cpp | 9 ++ CYD-Klipper/src/core/printer_integration.hpp | 1 + CYD-Klipper/src/ui/panels/files_panel.cpp | 19 ++- CYD-Klipper/src/ui/ui_utils.cpp | 4 +- 7 files changed, 156 insertions(+), 20 deletions(-) diff --git a/CYD-Klipper/src/core/bambu/bambu_printer_integration.cpp b/CYD-Klipper/src/core/bambu/bambu_printer_integration.cpp index 95ec995..a7571f6 100644 --- a/CYD-Klipper/src/core/bambu/bambu_printer_integration.cpp +++ b/CYD-Klipper/src/core/bambu/bambu_printer_integration.cpp @@ -42,6 +42,7 @@ bool BambuPrinter::publish_mqtt_command(const char* command) char auth[48] = {0}; sprintf(auth, "device/%s/request", printer_config->printer_auth); + LOG_F(("Publishing MQTT Command: %s", command)); return client.publish(auth, command); } @@ -298,11 +299,6 @@ Files BambuPrinter::get_files() return files; } -bool BambuPrinter::start_file(const char* filename) -{ - return false; -} - Thumbnail BambuPrinter::get_32_32_png_image_thumbnail(const char* gcode_filename) { Thumbnail thumbnail = {0}; diff --git a/CYD-Klipper/src/core/bambu/bambu_printer_integration.hpp b/CYD-Klipper/src/core/bambu/bambu_printer_integration.hpp index 5c266b2..c4643a9 100644 --- a/CYD-Klipper/src/core/bambu/bambu_printer_integration.hpp +++ b/CYD-Klipper/src/core/bambu/bambu_printer_integration.hpp @@ -19,16 +19,6 @@ class BambuPrinter : public BasePrinter unsigned int ignore_error = 0; unsigned long print_start; - union { - struct { - bool chamber_light_available : 1; - bool chamber_light_on : 1; - bool work_light_available : 1; - bool work_light_on : 1; - }; - unsigned char bambu_misc; - }; - protected: void parse_state(JsonDocument& in); void init_ui_panels(); @@ -39,6 +29,17 @@ class BambuPrinter : public BasePrinter float chamber_fan_speed; BambuSpeedProfile speed_profile = BambuSpeedProfileNormal; + union { + struct { + bool chamber_light_available : 1; + bool chamber_light_on : 1; + bool work_light_available : 1; + bool work_light_on : 1; + bool has_ams : 1; + }; + unsigned char bambu_misc; + }; + BambuPrinter(int index) : BasePrinter(index) { supported_features = PrinterFeatureHome @@ -63,6 +64,7 @@ class BambuPrinter : public BasePrinter print_start = millis(); init_ui_panels(); + no_confirm_print_file = true; } bool move_printer(const char* axis, float amount, bool relative); diff --git a/CYD-Klipper/src/core/bambu/bambu_printer_panels.cpp b/CYD-Klipper/src/core/bambu/bambu_printer_panels.cpp index 6362f3f..f6494be 100644 --- a/CYD-Klipper/src/core/bambu/bambu_printer_panels.cpp +++ b/CYD-Klipper/src/core/bambu/bambu_printer_panels.cpp @@ -7,6 +7,7 @@ const char* speed_profiles[] = { "Silent (50%)", "Normal (100%)", "Sport (124%)", "Ludicrous (166%)" }; const BambuSpeedProfile speed_profile_values[] = { BambuSpeedProfileSilent, BambuSpeedProfileNormal, BambuSpeedProfileSport, BambuSpeedProfileLudicrous }; const char* COMMAND_SET_PRINT_SPEED = "{\"print\":{\"command\":\"print_speed\",\"param\":\"%d\"}}"; +const char* COMMAND_START_PRINT_3MF = "{\"print\":{\"command\":\"project_file\",\"param\":\"Metadata/plate_1.gcode\",\"project_id\":\"0\",\"profile_id\":\"0\",\"task_id\":\"0\",\"subtask_id\":\"0\",\"subtask_name\":\"CYD-Klipper Print Job\",\"url\":\"file:///sdcard/%s\",\"timelapse\":%s,\"bed_type\":\"auto\",\"bed_leveling\":%s,\"flow_cali\":%s,\"vibration_cali\":%s,\"layer_inspect\":%s,\"ams_mapping\":[],\"use_ams\":%s}}"; enum FanIndex { @@ -139,4 +140,118 @@ void BambuPrinter::init_ui_panels() { custom_menus_count = 4; custom_menus = bambu_ui_panels; +} + +struct +{ + const char* bambu_current_file; + + union + { + struct + { + bool bambu_option_use_ams : 1; + bool bambu_option_timelapse : 1; + bool bambu_option_bed_leveling : 1; + bool bambu_option_flow_calibration : 1; + bool bambu_option_vibration_compensation : 1; + bool bambu_option_layer_inspect : 1; + }; + unsigned char bambu_options_raw; + }; +} __internal_bambu_file_state = {}; + +#define SET_BOOL_STATE(bool_name, func_name) static void func_name (lv_event_t * e) { auto state = lv_obj_get_state(lv_event_get_target(e)); bool_name = (state & LV_STATE_CHECKED == LV_STATE_CHECKED); } + +SET_BOOL_STATE(__internal_bambu_file_state.bambu_option_use_ams, set_bambu_option_use_ams) +SET_BOOL_STATE(__internal_bambu_file_state.bambu_option_timelapse, set_bambu_option_timelapse) +SET_BOOL_STATE(__internal_bambu_file_state.bambu_option_bed_leveling, set_bambu_option_bed_leveling) +SET_BOOL_STATE(__internal_bambu_file_state.bambu_option_flow_calibration, set_bambu_option_flow_calibration) +SET_BOOL_STATE(__internal_bambu_file_state.bambu_option_vibration_compensation, set_bambu_option_vibration_compensation) +SET_BOOL_STATE(__internal_bambu_file_state.bambu_option_layer_inspect, set_bambu_option_layer_inspect) + +#define BOOLEAN_TO_STRING(b) b ? "true" : "false" + +static void print_file_start(lv_event_t * e) +{ + BambuPrinter* printer = (BambuPrinter*)get_current_printer(); + char buff[713]; + + if (snprintf(buff, 713, COMMAND_START_PRINT_3MF, + __internal_bambu_file_state.bambu_current_file, + BOOLEAN_TO_STRING(__internal_bambu_file_state.bambu_option_timelapse), + BOOLEAN_TO_STRING(__internal_bambu_file_state.bambu_option_bed_leveling), + BOOLEAN_TO_STRING(__internal_bambu_file_state.bambu_option_flow_calibration), + BOOLEAN_TO_STRING(__internal_bambu_file_state.bambu_option_vibration_compensation), + BOOLEAN_TO_STRING(__internal_bambu_file_state.bambu_option_layer_inspect), + BOOLEAN_TO_STRING(__internal_bambu_file_state.bambu_option_use_ams)) >= 712) + { + LOG_LN("Failed to prepare message to start print"); + return; + } + + printer->publish_mqtt_command(buff); +} + +bool BambuPrinter::start_file(const char* filename){ + if (get_current_printer_data()->state != PrinterState::PrinterStateIdle) + { + return false; + } + + __internal_bambu_file_state.bambu_current_file = filename; + + lv_obj_t * panel = lv_obj_create(lv_scr_act()); + lv_obj_set_style_pad_all(panel, CYD_SCREEN_GAP_PX * 2, 0); + lv_layout_flex_column(panel); + lv_obj_set_size(panel, CYD_SCREEN_WIDTH_PX - CYD_SCREEN_GAP_PX * 3, CYD_SCREEN_HEIGHT_PX - CYD_SCREEN_GAP_PX * 2); + lv_obj_align(panel, LV_ALIGN_CENTER, 0, 0); + + lv_obj_t * label_print_file = lv_label_create(panel); + lv_obj_set_width(label_print_file, LV_PCT(100)); + lv_label_set_long_mode(label_print_file, LV_LABEL_LONG_SCROLL_CIRCULAR); + lv_label_set_text_fmt(label_print_file, "Settings for %s", __internal_bambu_file_state.bambu_current_file); + + __internal_bambu_file_state.bambu_option_use_ams = ((BambuPrinter*)get_current_printer())->has_ams; + __internal_bambu_file_state.bambu_option_timelapse = false; + __internal_bambu_file_state.bambu_option_bed_leveling = true; + __internal_bambu_file_state.bambu_option_flow_calibration = true; + __internal_bambu_file_state.bambu_option_vibration_compensation = true; + __internal_bambu_file_state.bambu_option_layer_inspect = true; + + if (__internal_bambu_file_state.bambu_option_use_ams) + { + lv_create_custom_menu_switch("Use AMS", panel, set_bambu_option_use_ams, __internal_bambu_file_state.bambu_option_use_ams); + } + + lv_create_custom_menu_switch("Timelapse", panel, set_bambu_option_timelapse, __internal_bambu_file_state.bambu_option_timelapse); + lv_create_custom_menu_switch("Bed Leveling", panel, set_bambu_option_bed_leveling, __internal_bambu_file_state.bambu_option_bed_leveling); + lv_create_custom_menu_switch("Flow Calibration", panel, set_bambu_option_flow_calibration, __internal_bambu_file_state.bambu_option_flow_calibration); + lv_create_custom_menu_switch("Vibration Compensation", panel, set_bambu_option_vibration_compensation, __internal_bambu_file_state.bambu_option_vibration_compensation); + lv_create_custom_menu_switch("Inspect First Layer", panel, set_bambu_option_layer_inspect, __internal_bambu_file_state.bambu_option_layer_inspect); + + lv_obj_t* buttons_panel = lv_create_empty_panel(panel); + lv_layout_flex_row(buttons_panel); + lv_obj_set_size(buttons_panel, LV_PCT(100), CYD_SCREEN_MIN_BUTTON_HEIGHT_PX); + + lv_obj_t* btn = lv_btn_create(buttons_panel); + lv_obj_set_flex_grow(btn, 1); + lv_obj_set_height(btn, CYD_SCREEN_MIN_BUTTON_HEIGHT_PX); + lv_obj_add_event_cb(btn, destroy_event_user_data, LV_EVENT_CLICKED, panel); + + lv_obj_t* label = lv_label_create(btn); + lv_label_set_text(label, LV_SYMBOL_CLOSE " Cancel"); + lv_obj_center(label); + + btn = lv_btn_create(buttons_panel); + lv_obj_set_flex_grow(btn, 1); + lv_obj_set_height(btn, CYD_SCREEN_MIN_BUTTON_HEIGHT_PX); + lv_obj_add_event_cb(btn, print_file_start, LV_EVENT_CLICKED, panel); + lv_obj_add_event_cb(btn, destroy_event_user_data, LV_EVENT_CLICKED, panel); + + label = lv_label_create(btn); + lv_label_set_text(label, LV_SYMBOL_OK " Print"); + lv_obj_center(label); + + return true; } \ No newline at end of file diff --git a/CYD-Klipper/src/core/bambu/bambu_printer_parsers.cpp b/CYD-Klipper/src/core/bambu/bambu_printer_parsers.cpp index d2c2b8e..b1a0e44 100644 --- a/CYD-Klipper/src/core/bambu/bambu_printer_parsers.cpp +++ b/CYD-Klipper/src/core/bambu/bambu_printer_parsers.cpp @@ -228,6 +228,15 @@ void BambuPrinter::parse_state(JsonDocument& in) chamber_fan_speed = convert_fan_speed(print["big_fan2_speed"]); } + if (print.containsKey("ams_exist_bits")) + { + const char* ams_exists = print["ams_exist_bits"]; + if (!strcmp(ams_exists, "0")) + { + has_ams = true; + } + } + printer_data.extrude_mult = 1; } diff --git a/CYD-Klipper/src/core/printer_integration.hpp b/CYD-Klipper/src/core/printer_integration.hpp index acab184..220aa5f 100644 --- a/CYD-Klipper/src/core/printer_integration.hpp +++ b/CYD-Klipper/src/core/printer_integration.hpp @@ -150,6 +150,7 @@ class BasePrinter public: short popup_message_timeout_s = 10; + bool no_confirm_print_file = false; PrinterConfiguration* printer_config{}; PrinterFeatures supported_features{}; diff --git a/CYD-Klipper/src/ui/panels/files_panel.cpp b/CYD-Klipper/src/ui/panels/files_panel.cpp index 87ec141..d4c74be 100644 --- a/CYD-Klipper/src/ui/panels/files_panel.cpp +++ b/CYD-Klipper/src/ui/panels/files_panel.cpp @@ -11,14 +11,23 @@ const char* selected_file = NULL; -static void btn_print_file(lv_event_t * e){ +static void btn_print_file(lv_event_t * e) +{ lv_obj_t * panel = (lv_obj_t*)lv_event_get_user_data(e); lv_obj_del(panel); current_printer_start_file(selected_file); } -static void btn_print_file_verify(lv_event_t * e){ +static void btn_print_file_verify_instant(lv_event_t * e) +{ + lv_obj_t * btn = lv_event_get_target(e); + selected_file = (char*)lv_event_get_user_data(e); + current_printer_start_file(selected_file); +} + +static void btn_print_file_verify(lv_event_t * e) +{ if (get_current_printer_data()->state != PrinterState::PrinterStateIdle){ return; } @@ -111,10 +120,12 @@ void files_panel_init(lv_obj_t* panel){ lv_obj_t * btn = lv_list_add_btn(list, LV_SYMBOL_FILE, files.available_files[i]); lv_obj_set_style_bg_opa(btn, LV_OPA_TRANSP, 0); - if (global_config.full_filenames){ + if (global_config.full_filenames) + { lv_label_set_long_mode(lv_obj_get_child(btn, 1), LV_LABEL_LONG_WRAP); } - lv_obj_add_event_cb(btn, btn_print_file_verify, LV_EVENT_CLICKED, (void*)(files.available_files[i])); + + lv_obj_add_event_cb(btn, (get_current_printer()->no_confirm_print_file) ? btn_print_file_verify_instant : btn_print_file_verify, LV_EVENT_CLICKED, (void*)(files.available_files[i])); lv_obj_on_destroy_free_data(btn, files.available_files[i]); } diff --git a/CYD-Klipper/src/ui/ui_utils.cpp b/CYD-Klipper/src/ui/ui_utils.cpp index 7faa561..31afb73 100644 --- a/CYD-Klipper/src/ui/ui_utils.cpp +++ b/CYD-Klipper/src/ui/ui_utils.cpp @@ -181,8 +181,10 @@ void lv_create_custom_menu_entry(const char* label_text, lv_obj_t* object, lv_ob lv_obj_set_parent(object, panel); - if (set_height) + if (set_height) + { lv_obj_set_height(object, CYD_SCREEN_MIN_BUTTON_HEIGHT_PX); + } if (comment != NULL) { From 4fc16ecc9200a8e9483a9c75078b862255311b53 Mon Sep 17 00:00:00 2001 From: suchmememanyskill <38142618+suchmememanyskill@users.noreply.github.com> Date: Sun, 22 Dec 2024 23:04:12 +0100 Subject: [PATCH 59/63] Fan profiles: On to 100% --- CYD-Klipper/src/core/common/constants.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CYD-Klipper/src/core/common/constants.cpp b/CYD-Klipper/src/core/common/constants.cpp index 90b56f8..82a9810 100644 --- a/CYD-Klipper/src/core/common/constants.cpp +++ b/CYD-Klipper/src/core/common/constants.cpp @@ -1,6 +1,6 @@ #include "constants.h" -const char* fan_speeds_col_1[] = { "On", "Off" }; +const char* fan_speeds_col_1[] = { "100%", "0%" }; const int fan_speeds_col_1_values[] = { 100, 0 }; const char* fan_speeds_col_2[] = { "10%", "20%", "30%", "40%", "50%"}; From 5ec2ba66e46c7297a2e8d485e530546e716f0829 Mon Sep 17 00:00:00 2001 From: suchmememanyskill <38142618+suchmememanyskill@users.noreply.github.com> Date: Sun, 22 Dec 2024 23:20:36 +0100 Subject: [PATCH 60/63] Change some spelling, set timeout on bambu loop --- CYD-Klipper/src/core/bambu/bambu_printer_integration.cpp | 3 ++- CYD-Klipper/src/core/common/constants.cpp | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CYD-Klipper/src/core/bambu/bambu_printer_integration.cpp b/CYD-Klipper/src/core/bambu/bambu_printer_integration.cpp index a7571f6..ff6968e 100644 --- a/CYD-Klipper/src/core/bambu/bambu_printer_integration.cpp +++ b/CYD-Klipper/src/core/bambu/bambu_printer_integration.cpp @@ -42,7 +42,7 @@ bool BambuPrinter::publish_mqtt_command(const char* command) char auth[48] = {0}; sprintf(auth, "device/%s/request", printer_config->printer_auth); - LOG_F(("Publishing MQTT Command: %s", command)); + LOG_F(("Publishing MQTT Command: %s\n", command)); return client.publish(auth, command); } @@ -117,6 +117,7 @@ bool BambuPrinter::execute_feature(PrinterFeatures feature) bool BambuPrinter::connect() { wifi_client.setInsecure(); + wifi_client.setTimeout(3); client.setBufferSize(4096); client.setServer(printer_config->printer_host, 8883); current_printer = this; diff --git a/CYD-Klipper/src/core/common/constants.cpp b/CYD-Klipper/src/core/common/constants.cpp index 82a9810..b52374a 100644 --- a/CYD-Klipper/src/core/common/constants.cpp +++ b/CYD-Klipper/src/core/common/constants.cpp @@ -1,6 +1,6 @@ #include "constants.h" -const char* fan_speeds_col_1[] = { "100%", "0%" }; +const char* fan_speeds_col_1[] = { "On\n100%", "Off\n0%" }; const int fan_speeds_col_1_values[] = { 100, 0 }; const char* fan_speeds_col_2[] = { "10%", "20%", "30%", "40%", "50%"}; From 660723d5965906e89930b3b6b9b2b0f28485baf6 Mon Sep 17 00:00:00 2001 From: suchmememanyskill <38142618+suchmememanyskill@users.noreply.github.com> Date: Thu, 9 Jan 2025 21:12:50 +0100 Subject: [PATCH 61/63] Fix arduinojson compile --- .../src/core/bambu/bambu_printer_parsers.cpp | 4 ++-- .../core/klipper/klipper_printer_parsers.cpp | 24 +++++++++---------- .../octoprint/octoprint_printer_parsers.cpp | 16 ++++++------- 3 files changed, 22 insertions(+), 22 deletions(-) diff --git a/CYD-Klipper/src/core/bambu/bambu_printer_parsers.cpp b/CYD-Klipper/src/core/bambu/bambu_printer_parsers.cpp index b1a0e44..d7a5b48 100644 --- a/CYD-Klipper/src/core/bambu/bambu_printer_parsers.cpp +++ b/CYD-Klipper/src/core/bambu/bambu_printer_parsers.cpp @@ -25,7 +25,7 @@ void BambuPrinter::parse_state(JsonDocument& in) return; } - auto print = in["print"]; + JsonObject print = in["print"]; if (print.containsKey("print_error")) { @@ -176,7 +176,7 @@ void BambuPrinter::parse_state(JsonDocument& in) if (print.containsKey("lights_report")) { - for (auto lights : print["lights_report"].as()) + for (JsonObject lights : print["lights_report"].as()) { if (lights.containsKey("node") && lights.containsKey("mode")) { diff --git a/CYD-Klipper/src/core/klipper/klipper_printer_parsers.cpp b/CYD-Klipper/src/core/klipper/klipper_printer_parsers.cpp index 2c7490e..96de5a3 100644 --- a/CYD-Klipper/src/core/klipper/klipper_printer_parsers.cpp +++ b/CYD-Klipper/src/core/klipper/klipper_printer_parsers.cpp @@ -11,7 +11,7 @@ int KlipperPrinter::parse_slicer_time_estimate(JsonDocument &in) void KlipperPrinter::parse_state(JsonDocument &in) { - auto status = in["result"]["status"]; + JsonObject status = in["result"]["status"]; if (status.containsKey("webhooks")) { @@ -185,7 +185,7 @@ void KlipperPrinter::parse_state(JsonDocument &in) void KlipperPrinter::parse_state_min(JsonDocument &in, PrinterDataMinimal* data) { - auto status = in["result"]["status"]; + JsonObject status = in["result"]["status"]; if (status.containsKey("webhooks")) { @@ -230,7 +230,7 @@ void KlipperPrinter::parse_state_min(JsonDocument &in, PrinterDataMinimal* data) Macros KlipperPrinter::parse_macros(JsonDocument &in) { - auto result = in["result"].as(); + JsonObject result = in["result"]; Macros macros = {0}; macros.macros = (char **)malloc(sizeof(char *) * 32); macros.count = 0; @@ -259,7 +259,7 @@ Macros KlipperPrinter::parse_macros(JsonDocument &in) int KlipperPrinter::parse_macros_count(JsonDocument &in) { - auto result = in["result"].as(); + JsonObject result = in["result"]; int count = 0; @@ -278,13 +278,13 @@ int KlipperPrinter::parse_macros_count(JsonDocument &in) PowerDevices KlipperPrinter::parse_power_devices(JsonDocument &in) { PowerDevices power_devices = {0}; - auto result = in["result"]["devices"].as(); + JsonArray result = in["result"]["devices"]; power_devices.power_devices = (char **)malloc(sizeof(char *) * 16); power_devices.power_states = (bool *)malloc(sizeof(bool) * 16); power_devices.count = 0; power_devices.success = true; - for (auto i : result) + for (JsonObject i : result) { const char *device_name = i["device"]; const char *device_state = i["status"]; @@ -299,10 +299,10 @@ PowerDevices KlipperPrinter::parse_power_devices(JsonDocument &in) int KlipperPrinter::parse_power_devices_count(JsonDocument &in) { - auto result = in["result"]["devices"].as(); + JsonArray result = in["result"]["devices"]; int count = 0; - for (auto i : result) + for (JsonObject i : result) { count++; } @@ -312,9 +312,9 @@ int KlipperPrinter::parse_power_devices_count(JsonDocument &in) void KlipperPrinter::parse_file_list(JsonDocument &in, std::list &files, int fetch_limit) { - auto result = in["result"].as(); + JsonArray result = in["result"]; - for (auto file : result) + for (JsonObject file : result) { KlipperFileSystemFile f = {0}; const char *path = file["path"]; @@ -360,9 +360,9 @@ void KlipperPrinter::parse_file_list(JsonDocument &in, std::list(); + JsonArray result = in["result"]; const char *chosen_thumb = NULL; - for (auto file : result) + for (JsonObject file : result) { int width = file["width"]; int height = file["height"]; diff --git a/CYD-Klipper/src/core/octoprint/octoprint_printer_parsers.cpp b/CYD-Klipper/src/core/octoprint/octoprint_printer_parsers.cpp index 786b690..383faa5 100644 --- a/CYD-Klipper/src/core/octoprint/octoprint_printer_parsers.cpp +++ b/CYD-Klipper/src/core/octoprint/octoprint_printer_parsers.cpp @@ -4,7 +4,7 @@ PrinterState OctoPrinter::parse_printer_state(JsonDocument& in) { - auto flags = in["state"]["flags"]; + JsonObject flags = in["state"]["flags"]; bool cancelling = flags["cancelling"]; bool closedOrError = flags["closedOrError"]; bool error = flags["error"]; @@ -35,7 +35,7 @@ PrinterState OctoPrinter::parse_printer_state(JsonDocument& in) void OctoPrinter::parse_printer_status(JsonDocument& in) { - auto text = in["state"]["text"]; + const char* text = in["state"]["text"]; printer_data.state = parse_printer_state(in); if (printer_data.state == PrinterState::PrinterStateError) @@ -47,7 +47,7 @@ void OctoPrinter::parse_printer_status(JsonDocument& in) } } - auto temperature = in["temperature"]; + JsonObject temperature = in["temperature"]; if (temperature.containsKey("bed")) { @@ -67,7 +67,7 @@ void OctoPrinter::parse_printer_status(JsonDocument& in) void OctoPrinter::parse_job_state(JsonDocument& in) { - auto job = in["job"]; + JsonObject job = in["job"]; if (job.containsKey("file")) { @@ -80,12 +80,12 @@ void OctoPrinter::parse_job_state(JsonDocument& in) } } - if (job.containsKey("filament") && job["filament"] != NULL && job["filament"].containsKey("tool0")) + if (job.containsKey("filament") && job["filament"].as() != NULL && job["filament"].containsKey("tool0")) { printer_data.filament_used_mm = job["filament"]["tool0"]["length"]; } - auto progress = in["progress"]; + JsonObject progress = in["progress"]; float completion = progress["completion"]; printer_data.print_progress = completion / 100; printer_data.elapsed_time_s = progress["printTime"]; @@ -116,9 +116,9 @@ void OctoPrinter::parse_error(JsonDocument& in) void OctoPrinter::parse_file_list(JsonDocument &in, std::list &files, int fetch_limit) { - auto result = in["files"].as(); + JsonArray result = in["files"]; - for (auto file : result) + for (JsonObject file : result) { const char *path = file["path"]; if (strcmp("local", file["origin"])) From 71119e164884fe5dac03478f742437f2162263fd Mon Sep 17 00:00:00 2001 From: suchmememanyskill <38142618+suchmememanyskill@users.noreply.github.com> Date: Thu, 9 Jan 2025 22:00:53 +0100 Subject: [PATCH 62/63] Make UI more specific per printer type, hide settings --- .../core/klipper/klipper_printer_parsers.cpp | 8 +---- CYD-Klipper/src/core/printer_integration.cpp | 5 +++ CYD-Klipper/src/core/printer_integration.hpp | 1 + CYD-Klipper/src/ui/macros.cpp | 6 ++++ CYD-Klipper/src/ui/panels/progress_panel.cpp | 2 +- CYD-Klipper/src/ui/panels/settings_panel.cpp | 35 ++++++++++++++----- test_printer/config.json | 6 ++++ test_printer/docker-compose.yml | 14 ++++++++ 8 files changed, 60 insertions(+), 17 deletions(-) create mode 100644 test_printer/config.json create mode 100644 test_printer/docker-compose.yml diff --git a/CYD-Klipper/src/core/klipper/klipper_printer_parsers.cpp b/CYD-Klipper/src/core/klipper/klipper_printer_parsers.cpp index 96de5a3..5e2ed95 100644 --- a/CYD-Klipper/src/core/klipper/klipper_printer_parsers.cpp +++ b/CYD-Klipper/src/core/klipper/klipper_printer_parsers.cpp @@ -134,7 +134,7 @@ void KlipperPrinter::parse_state(JsonDocument &in) printer_data.print_progress = status["display_status"]["progress"]; const char *message = status["display_status"]["message"]; - if (message != NULL && (printer_data.popup_message == NULL || strcmp(printer_data.popup_message, message))) + if (!global_config.disable_m117_messaging && message != NULL && (printer_data.popup_message == NULL || strcmp(printer_data.popup_message, message))) { printer_data.popup_message = (char *)malloc(strlen(message) + 1); strcpy(printer_data.popup_message, message); @@ -248,12 +248,6 @@ Macros KlipperPrinter::parse_macros(JsonDocument &in) } } - if (global_config.sort_macros) - { - std::sort(macros.macros, macros.macros + macros.count, [](const char *a, const char *b) - { return strcmp(a, b) < 0; }); - } - return macros; } diff --git a/CYD-Klipper/src/core/printer_integration.cpp b/CYD-Klipper/src/core/printer_integration.cpp index 05d1460..a76ae38 100644 --- a/CYD-Klipper/src/core/printer_integration.cpp +++ b/CYD-Klipper/src/core/printer_integration.cpp @@ -94,6 +94,11 @@ BasePrinter* get_printer(int idx) return registered_printers[idx]; } +bool BasePrinter::supports_feature(PrinterFeatures feature) +{ + return supported_features & feature == feature; +} + int get_current_printer_index() { return current_printer_index; diff --git a/CYD-Klipper/src/core/printer_integration.hpp b/CYD-Klipper/src/core/printer_integration.hpp index 220aa5f..a731e34 100644 --- a/CYD-Klipper/src/core/printer_integration.hpp +++ b/CYD-Klipper/src/core/printer_integration.hpp @@ -181,6 +181,7 @@ class BasePrinter BasePrinter(unsigned char index); PrinterData* AnnouncePrinterData(); + bool supports_feature(PrinterFeatures feature); }; #define DATA_PRINTER_STATE 1 diff --git a/CYD-Klipper/src/ui/macros.cpp b/CYD-Klipper/src/ui/macros.cpp index af176d3..9afa22e 100644 --- a/CYD-Klipper/src/ui/macros.cpp +++ b/CYD-Klipper/src/ui/macros.cpp @@ -27,6 +27,12 @@ int macros_add_macros_to_panel(lv_obj_t * root_panel, BasePrinter* printer) return 0; } + if (global_config.sort_macros) + { + std::sort(macros.macros, macros.macros + macros.count, [](const char *a, const char *b) + { return strcmp(a, b) < 0; }); + } + for (int i = 0; i < macros.count; i++) { const char* macro = macros.macros[i]; diff --git a/CYD-Klipper/src/ui/panels/progress_panel.cpp b/CYD-Klipper/src/ui/panels/progress_panel.cpp index 60442c0..e44a420 100644 --- a/CYD-Klipper/src/ui/panels/progress_panel.cpp +++ b/CYD-Klipper/src/ui/panels/progress_panel.cpp @@ -79,7 +79,7 @@ void progress_panel_init(lv_obj_t* panel){ const auto button_size_mult = 1.3f; // Emergency Stop - if (global_config.show_estop){ + if (global_config.show_estop && (get_current_printer()->supports_feature(PrinterFeatureEmergencyStop))){ lv_obj_t * btn = lv_btn_create(panel); lv_obj_add_event_cb(btn, btn_click_estop, LV_EVENT_CLICKED, NULL); diff --git a/CYD-Klipper/src/ui/panels/settings_panel.cpp b/CYD-Klipper/src/ui/panels/settings_panel.cpp index 204626b..88755ce 100644 --- a/CYD-Klipper/src/ui/panels/settings_panel.cpp +++ b/CYD-Klipper/src/ui/panels/settings_panel.cpp @@ -189,11 +189,23 @@ void settings_section_theming(lv_obj_t* panel) void settings_section_behaviour(lv_obj_t* panel) { + PrinterType printer_type = get_current_printer()->printer_config->printer_type; + bool is_klipper = printer_type == PrinterTypeKlipper || printer_type == PrinterTypeKlipperSerial; + bool is_octo = printer_type == PrinterTypeOctoprint; + bool is_bambu = printer_type == PrinterTypeBambuLocal; + lv_obj_t * label = lv_label_create(panel); lv_label_set_text(label, "\nBehaviour"); - lv_create_custom_menu_dropdown("Estimated Time", panel, estimated_time_dropdown, estimated_time_options, get_current_printer()->printer_config->remaining_time_calc_mode, NULL, PRINTER_SPECIFIC_SETTING); - lv_create_custom_menu_dropdown("Stats in Progress Screen", panel, show_stats_on_progress_panel_dropdown, "None\nLayers\nPartial\nAll", get_current_printer()->printer_config->show_stats_on_progress_panel, NULL, PRINTER_SPECIFIC_SETTING); + if (is_klipper) + { + lv_create_custom_menu_dropdown("Estimated Time", panel, estimated_time_dropdown, estimated_time_options, get_current_printer()->printer_config->remaining_time_calc_mode, NULL, PRINTER_SPECIFIC_SETTING); + lv_create_custom_menu_dropdown("Stats in Progress Screen", panel, show_stats_on_progress_panel_dropdown, "None\nLayers\nPartial\nAll", get_current_printer()->printer_config->show_stats_on_progress_panel, NULL, PRINTER_SPECIFIC_SETTING); + } + else if (is_bambu) + { + lv_create_custom_menu_dropdown("Stats in Progress Screen", panel, show_stats_on_progress_panel_dropdown, "None\nLayers", get_current_printer()->printer_config->show_stats_on_progress_panel, NULL, PRINTER_SPECIFIC_SETTING); + } #ifndef CYD_SCREEN_DISABLE_TIMEOUT int wake_timeout_settings_index = 0; @@ -212,17 +224,22 @@ void settings_section_behaviour(lv_obj_t* panel) #endif lv_create_custom_menu_switch("Multi Printer Mode", panel, multi_printer_switch, global_config.multi_printer_mode); - lv_create_custom_menu_switch("Disable M117 Messaging", panel, disable_m117_messaging_switch, global_config.disable_m117_messaging); - lv_create_custom_menu_button("Configure Printer IP", panel, reset_ip_click, "Restart"); + + if (is_klipper) + { + lv_create_custom_menu_switch("Disable M117 Messaging", panel, disable_m117_messaging_switch, global_config.disable_m117_messaging); + + lv_create_custom_menu_switch("Custom Filament Move Macros", panel, filament_move_mode_switch, get_current_printer()->printer_config->custom_filament_move_macros, NULL, + global_config.multi_printer_mode + ? "Calls FILAMENT_RETRACT and\nFILAMENT_EXTRUDE in temperature menu\nwhen enabled. Stored per printer." + : "Calls FILAMENT_RETRACT and\nFILAMENT_EXTRUDE in temperature menu\nwhen enabled"); - lv_create_custom_menu_switch("Custom Filament Move Macros", panel, filament_move_mode_switch, get_current_printer()->printer_config->custom_filament_move_macros, NULL, - global_config.multi_printer_mode - ? "Calls FILAMENT_RETRACT and\nFILAMENT_EXTRUDE in temperature menu\nwhen enabled. Stored per printer." - : "Calls FILAMENT_RETRACT and\nFILAMENT_EXTRUDE in temperature menu\nwhen enabled"); + lv_create_custom_menu_switch("Show Emergency Stop", panel, show_estop_switch, global_config.show_estop); + } lv_create_custom_menu_switch("Sort Macros A->Z", panel, sort_macros_switch, global_config.sort_macros); - lv_create_custom_menu_switch("Show Emergency Stop", panel, show_estop_switch, global_config.show_estop); lv_create_custom_menu_switch("Show Full Filenames", panel, full_filenames_switch, global_config.full_filenames); + lv_create_custom_menu_button("Configure Printer Host", panel, reset_ip_click, "Restart"); } void settings_section_device(lv_obj_t* panel) diff --git a/test_printer/config.json b/test_printer/config.json new file mode 100644 index 0000000..e59e526 --- /dev/null +++ b/test_printer/config.json @@ -0,0 +1,6 @@ +{ + "instancesDB": "json", + "instances": [ + { "hostname": "localhost", "port": 7125 } + ] + } \ No newline at end of file diff --git a/test_printer/docker-compose.yml b/test_printer/docker-compose.yml new file mode 100644 index 0000000..25b176b --- /dev/null +++ b/test_printer/docker-compose.yml @@ -0,0 +1,14 @@ +services: + printer: + container_name: printer + ports: + - "7125:7125" + - "8110:8110" + image: ghcr.io/mainsail-crew/virtual-klipper-printer:master + webui: + container_name: mainsail + volumes: + - ./config.json:/usr/share/nginx/html/config.json:ro + ports: + - 6969:80 + image: ghcr.io/mainsail-crew/mainsail \ No newline at end of file From 7b0497c75b09bb7a69bf953110c45bdb08744c01 Mon Sep 17 00:00:00 2001 From: suchmememanyskill <38142618+suchmememanyskill@users.noreply.github.com> Date: Thu, 9 Jan 2025 22:35:13 +0100 Subject: [PATCH 63/63] Fix crowpanel compile --- CYD-Klipper/src/core/device/ESP32-CROWPANEL_28R.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CYD-Klipper/src/core/device/ESP32-CROWPANEL_28R.cpp b/CYD-Klipper/src/core/device/ESP32-CROWPANEL_28R.cpp index a3674e7..580e2d7 100644 --- a/CYD-Klipper/src/core/device/ESP32-CROWPANEL_28R.cpp +++ b/CYD-Klipper/src/core/device/ESP32-CROWPANEL_28R.cpp @@ -58,7 +58,7 @@ void screen_lv_touchRead(lv_indev_drv_t *indev_driver, lv_indev_data_t *data) } void set_invert_display(){ - tft.invertDisplay(get_current_printer_config()->invert_colors); + tft.invertDisplay(global_config.printer_config[global_config.printer_index].invert_colors); } void screen_setup()