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);