Merge pull request #122 from suchmememanyskill/dev

v1.7.0
This commit is contained in:
Sims
2024-08-02 21:39:42 +02:00
committed by GitHub
22 changed files with 666 additions and 62 deletions

View File

@@ -3,6 +3,7 @@
#include "lvgl.h" #include "lvgl.h"
GLOBAL_CONFIG global_config = {0}; GLOBAL_CONFIG global_config = {0};
TEMPORARY_CONFIG temporary_config = {0};
COLOR_DEF color_defs[] = { COLOR_DEF color_defs[] = {
{LV_PALETTE_BLUE, 0, LV_PALETTE_RED}, {LV_PALETTE_BLUE, 0, LV_PALETTE_RED},
@@ -31,9 +32,9 @@ void verify_version()
GLOBAL_CONFIG config = {0}; GLOBAL_CONFIG config = {0};
preferences.getBytes("global_config", &config, sizeof(config)); preferences.getBytes("global_config", &config, sizeof(config));
Serial.printf("Config version: %d\n", config.version); LOG_F(("Config version: %d\n", config.version))
if (config.version != CONFIG_VERSION) { if (config.version != CONFIG_VERSION) {
Serial.println("Clearing Global Config"); LOG_LN("Clearing Global Config");
preferences.clear(); preferences.clear();
} }
@@ -131,4 +132,11 @@ void load_global_config()
preferences.begin("global_config", true); preferences.begin("global_config", true);
preferences.getBytes("global_config", &global_config, sizeof(global_config)); preferences.getBytes("global_config", &global_config, sizeof(global_config));
preferences.end(); preferences.end();
#if defined REPO_DEVELOPMENT && REPO_DEVELOPMENT == 1
temporary_config.debug = true;
#else
temporary_config.debug = false;
#endif
temporary_config.remote_echo = true;
} }

View File

@@ -5,6 +5,7 @@
#define CONFIG_VERSION 6 #define CONFIG_VERSION 6
#define PRINTER_CONFIG_COUNT 8 #define PRINTER_CONFIG_COUNT 8
#define DISPLAY_SECRETS 0
enum { enum {
REMAINING_TIME_CALC_PERCENTAGE = 0, REMAINING_TIME_CALC_PERCENTAGE = 0,
@@ -87,6 +88,13 @@ typedef struct _GLOBAL_CONFIG {
unsigned char printer_index; unsigned char printer_index;
} GLOBAL_CONFIG; } GLOBAL_CONFIG;
// Volatile/temporary config that doesn't survive a reset
typedef struct _TEMPORARY_CONFIG {
bool debug : 1;
bool remote_echo : 1;
} TEMPORARY_CONFIG;
typedef struct _COLOR_DEF { typedef struct _COLOR_DEF {
lv_palette_t primary_color; lv_palette_t primary_color;
short primary_color_light; short primary_color_light;
@@ -94,8 +102,13 @@ typedef struct _COLOR_DEF {
} COLOR_DEF; } COLOR_DEF;
extern GLOBAL_CONFIG global_config; extern GLOBAL_CONFIG global_config;
extern TEMPORARY_CONFIG temporary_config;
extern COLOR_DEF color_defs[]; extern COLOR_DEF color_defs[];
#define LOG(x) if(temporary_config.debug){ Serial.print(x);}
#define LOG_LN(x) if(temporary_config.debug){ Serial.println(x);}
#define LOG_F(x) if(temporary_config.debug){ Serial.printf x ;} // use with double braces, LOF_F(("x=%d\n",x));
void write_global_config(); void write_global_config();
void verify_version(); void verify_version();
void load_global_config(); void load_global_config();

View File

@@ -43,7 +43,7 @@ void unfreeze_render_thread(){
void send_gcode(bool wait, const char *gcode) void send_gcode(bool wait, const char *gcode)
{ {
Serial.printf("Sending gcode: %s\n", gcode); LOG_F(("Sending gcode: %s\n", gcode))
SETUP_HTTP_CLIENT_FULL("/printer/gcode/script?script=" + urlEncode(gcode), false, wait ? 5000 : 750); SETUP_HTTP_CLIENT_FULL("/printer/gcode/script?script=" + urlEncode(gcode), false, wait ? 5000 : 750);
try try
@@ -52,7 +52,7 @@ void send_gcode(bool wait, const char *gcode)
} }
catch (...) catch (...)
{ {
Serial.println("Failed to send gcode"); LOG_LN("Failed to send gcode");
} }
} }
@@ -73,7 +73,7 @@ int get_slicer_time_estimate_s()
JsonDocument doc; JsonDocument doc;
deserializeJson(doc, client.getStream()); deserializeJson(doc, client.getStream());
int time_estimate_s = doc["result"]["estimated_time"]; int time_estimate_s = doc["result"]["estimated_time"];
Serial.printf("Got slicer time estimate: %ds\n", time_estimate_s); LOG_F(("Got slicer time estimate: %ds\n", time_estimate_s))
return time_estimate_s; return time_estimate_s;
} }
@@ -330,7 +330,7 @@ void fetch_printer_data()
unfreeze_render_thread(); unfreeze_render_thread();
} }
Serial.printf("Failed to fetch printer data: %d\n", httpCode); LOG_F(("Failed to fetch printer data: %d\n", httpCode))
} }
} }
@@ -349,7 +349,7 @@ void fetch_printer_data_minimal()
delay(10); delay(10);
HTTPClient client; HTTPClient client;
configure_http_client(client, get_full_url("/printer/objects/query?webhooks&print_stats&virtual_sdcard", config), true, 1000); configure_http_client(client, get_full_url("/printer/objects/query?webhooks&print_stats&virtual_sdcard", config), true, 1000, config);
freeze_request_thread(); freeze_request_thread();
int httpCode = client.GET(); int httpCode = client.GET();

View File

@@ -29,7 +29,7 @@ FILESYSTEM_FILE* get_files(int limit)
freeze_request_thread(); freeze_request_thread();
clear_files(); clear_files();
Serial.printf("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<FILESYSTEM_FILE> files; std::list<FILESYSTEM_FILE> files;
auto timer_request = millis(); auto timer_request = millis();
@@ -41,7 +41,7 @@ FILESYSTEM_FILE* get_files(int limit)
if (httpCode == 200){ if (httpCode == 200){
JsonDocument doc; JsonDocument doc;
auto parseResult = deserializeJson(doc, client.getStream()); auto parseResult = deserializeJson(doc, client.getStream());
Serial.printf("Json parse: %s\n", parseResult.c_str()); LOG_F(("Json parse: %s\n", parseResult.c_str()))
auto result = doc["result"].as<JsonArray>(); auto result = doc["result"].as<JsonArray>();
for (auto file : result){ for (auto file : result){
@@ -62,7 +62,7 @@ FILESYSTEM_FILE* get_files(int limit)
f.name = (char*)malloc(strlen(path) + 1); f.name = (char*)malloc(strlen(path) + 1);
if (f.name == NULL){ if (f.name == NULL){
Serial.println("Failed to allocate memory"); LOG_LN("Failed to allocate memory");
continue; continue;
} }
strcpy(f.name, path); strcpy(f.name, path);
@@ -88,7 +88,7 @@ FILESYSTEM_FILE* get_files(int limit)
FILESYSTEM_FILE* result = (FILESYSTEM_FILE*)malloc(size); FILESYSTEM_FILE* result = (FILESYSTEM_FILE*)malloc(size);
if (result == NULL){ if (result == NULL){
Serial.println("Failed to allocate memory"); LOG_LN("Failed to allocate memory");
for (auto file : files){ for (auto file : files){
free(file.name); free(file.name);
@@ -106,8 +106,8 @@ FILESYSTEM_FILE* get_files(int limit)
result += 1; result += 1;
} }
Serial.printf("Heap space post-file-parse: %d bytes\n", esp_get_free_heap_size()); LOG_F(("Heap space post-file-parse: %d bytes\n", esp_get_free_heap_size()))
Serial.printf("Got %d files. Request took %dms, parsing took %dms\n", files.size(), timer_parse - timer_request, millis() - timer_parse); LOG_F(("Got %d files. Request took %dms, parsing took %dms\n", files.size(), timer_parse - timer_request, millis() - timer_parse))
unfreeze_request_thread(); unfreeze_request_thread();
return last_query; return last_query;
} }

View File

@@ -2,16 +2,19 @@
String get_full_url(String url_part, PRINTER_CONFIG * config) 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; return "http://" + String(config->klipper_host) + ":" + String(config->klipper_port) + url_part;
} }
String get_full_url(String url_part) void configure_http_client(HTTPClient &client, String url, bool stream, int timeout, PRINTER_CONFIG * config)
{ {
return "http://" + String(get_current_printer_config()->klipper_host) + ":" + String(get_current_printer_config()->klipper_port) + url_part; if (config == NULL){
config = get_current_printer_config();
} }
void configure_http_client(HTTPClient &client, String url, bool stream, int timeout)
{
if (stream){ if (stream){
client.useHTTP10(true); client.useHTTP10(true);
} }
@@ -23,7 +26,7 @@ void configure_http_client(HTTPClient &client, String url, bool stream, int time
client.begin(url); client.begin(url);
if (get_current_printer_config()->auth_configured) { if (config->auth_configured) {
client.addHeader("X-Api-Key", get_current_printer_config()->klipper_auth); client.addHeader("X-Api-Key", config->klipper_auth);
} }
} }

View File

@@ -3,11 +3,8 @@
#include <HTTPClient.h> #include <HTTPClient.h>
#include "../conf/global_config.h" #include "../conf/global_config.h"
String get_full_url(String url_part); String get_full_url(String url_part, PRINTER_CONFIG * config = NULL);
String get_full_url(String url_part, PRINTER_CONFIG * config); void configure_http_client(HTTPClient &client, String url, bool stream = true, int timeout = 1000, PRINTER_CONFIG * config = NULL);
void configure_http_client(HTTPClient &client, String url, bool stream = true, int timeout = 1000);
#define SETUP_HTTP_CLIENT(url_part) HTTPClient client; configure_http_client(client, get_full_url(url_part)); #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); #define SETUP_HTTP_CLIENT_FULL(url_part, stream, timeout) HTTPClient client; configure_http_client(client, get_full_url(url_part), stream, timeout);

View File

@@ -4,6 +4,7 @@
#include "lvgl.h" #include "lvgl.h"
#include "../ui/ui_utils.h" #include "../ui/ui_utils.h"
#include <Esp.h> #include <Esp.h>
#include "../ui/serial/serial_console.h"
#ifndef CPU_FREQ_HIGH #ifndef CPU_FREQ_HIGH
#define CPU_FREQ_HIGH 240 #define CPU_FREQ_HIGH 240
@@ -117,6 +118,7 @@ void lv_do_calibration(){
while (true){ while (true){
lv_handler(); lv_handler();
serial_console::run();
if (point[0] != 0 && point[1] != 0){ if (point[0] != 0 && point[1] != 0){
break; break;
@@ -175,7 +177,7 @@ void lv_do_calibration(){
global_config.screen_cal_y_offset = 10.0 - ((float)y1 * global_config.screen_cal_y_mult); global_config.screen_cal_y_offset = 10.0 - ((float)y1 * global_config.screen_cal_y_mult);
if (global_config.screen_cal_x_mult == std::numeric_limits<float>::infinity() || global_config.screen_cal_y_mult == std::numeric_limits<float>::infinity()){ if (global_config.screen_cal_x_mult == std::numeric_limits<float>::infinity() || global_config.screen_cal_y_mult == std::numeric_limits<float>::infinity()){
Serial.println("Calibration failed, please try again"); LOG_LN("Calibration failed, please try again");
ESP.restart(); ESP.restart();
} }
@@ -183,7 +185,7 @@ void lv_do_calibration(){
write_global_config(); write_global_config();
lv_obj_clean(lv_scr_act()); lv_obj_clean(lv_scr_act());
Serial.printf("Calibration done: X*%.2f + %.2f, Y*%.2f + %.2f\n", global_config.screen_cal_x_mult, global_config.screen_cal_x_offset, global_config.screen_cal_y_mult, global_config.screen_cal_y_offset); LOG_F(("Calibration done: X*%.2f + %.2f, Y*%.2f + %.2f\n", global_config.screen_cal_x_mult, global_config.screen_cal_x_offset, global_config.screen_cal_y_mult, global_config.screen_cal_y_offset))
} }
void set_screen_brightness() void set_screen_brightness()
@@ -208,7 +210,7 @@ void screen_timer_wake()
// Reset cpu freq // Reset cpu freq
setCpuFrequencyMhz(CPU_FREQ_HIGH); setCpuFrequencyMhz(CPU_FREQ_HIGH);
Serial.printf("CPU Speed: %d MHz\n", ESP.getCpuFreqMHz()); LOG_F(("CPU Speed: %d MHz\n", ESP.getCpuFreqMHz()))
#endif #endif
} }
@@ -220,7 +222,7 @@ void screen_timer_sleep(lv_timer_t *timer)
// Screen is off, no need to make the cpu run fast, the user won't notice ;) // Screen is off, no need to make the cpu run fast, the user won't notice ;)
setCpuFrequencyMhz(CPU_FREQ_LOW); setCpuFrequencyMhz(CPU_FREQ_LOW);
Serial.printf("CPU Speed: %d MHz\n", ESP.getCpuFreqMHz()); LOG_F(("CPU Speed: %d MHz\n", ESP.getCpuFreqMHz()))
#endif #endif
} }

View File

@@ -100,7 +100,7 @@ private:
size_t bytes_written = Update.write(buff, bytes_read); size_t bytes_written = Update.write(buff, bytes_read);
if (bytes_read != bytes_written) if (bytes_read != bytes_written)
{ {
// Serial.printf("Unexpected error in OTA: %d %d %d\n", bytes_to_read, bytes_read, bytes_written); // LOG_F(("Unexpected error in OTA: %d %d %d\n", bytes_to_read, bytes_read, bytes_written))
break; break;
} }
offset += bytes_written; offset += bytes_written;
@@ -212,8 +212,8 @@ public:
String CDevice = config["Device"].isNull() ? "" : (const char *)config["Device"]; String CDevice = config["Device"].isNull() ? "" : (const char *)config["Device"];
CVersion = config["Version"].isNull() ? "" : (const char *)config["Version"]; CVersion = config["Version"].isNull() ? "" : (const char *)config["Version"];
String CConfig = config["Config"].isNull() ? "" : (const char *)config["Config"]; String CConfig = config["Config"].isNull() ? "" : (const char *)config["Config"];
//Serial.printf("Checking %s %s %s %s\n", CBoard.c_str(), CDevice.c_str(), CVersion.c_str(), CConfig.c_str()); //LOG_F(("Checking %s %s %s %s\n", CBoard.c_str(), CDevice.c_str(), CVersion.c_str(), CConfig.c_str()))
//Serial.printf("Against %s %s %s %s\n", BoardName.c_str(), DeviceName.c_str(), CurrentVersion, ConfigName.c_str()); //LOG_F(("Against %s %s %s %s\n", BoardName.c_str(), DeviceName.c_str(), CurrentVersion, ConfigName.c_str()))
if ((CBoard.isEmpty() || CBoard == BoardName) && if ((CBoard.isEmpty() || CBoard == BoardName) &&
(CDevice.isEmpty() || CDevice == DeviceName) && (CDevice.isEmpty() || CDevice == DeviceName) &&
(CConfig.isEmpty() || CConfig == ConfigName)) (CConfig.isEmpty() || CConfig == ConfigName))

View File

@@ -2,6 +2,7 @@
#include "core/screen_driver.h" #include "core/screen_driver.h"
#include "ui/wifi_setup.h" #include "ui/wifi_setup.h"
#include "ui/ip_setup.h" #include "ui/ip_setup.h"
#include "ui/serial/serial_console.h"
#include "lvgl.h" #include "lvgl.h"
#include "core/data_setup.h" #include "core/data_setup.h"
#include "ui/main_ui.h" #include "ui/main_ui.h"
@@ -12,11 +13,11 @@
void setup() { void setup() {
Serial.begin(115200); Serial.begin(115200);
Serial.println("Hello World"); serial_console::greet();
load_global_config(); load_global_config();
screen_setup(); screen_setup();
lv_setup(); lv_setup();
Serial.println("Screen init done"); LOG_LN("Screen init done");
wifi_init(); wifi_init();
ota_init(); ota_init();
@@ -31,6 +32,7 @@ void loop(){
wifi_ok(); wifi_ok();
data_loop(); data_loop();
lv_handler(); lv_handler();
serial_console::run();
if (is_ready_for_ota_update()) if (is_ready_for_ota_update())
{ {

View File

@@ -14,7 +14,7 @@ static lv_img_dsc_t img_header = {0};
bool has_32_32_gcode_img(const char* filename) bool has_32_32_gcode_img(const char* filename)
{ {
if (filename == NULL){ if (filename == NULL){
Serial.println("No gcode filename"); LOG_LN("No gcode filename");
return false; return false;
} }
@@ -24,7 +24,7 @@ bool has_32_32_gcode_img(const char* filename)
httpCode = client.GET(); httpCode = client.GET();
} }
catch (...){ catch (...){
Serial.println("Exception while fetching gcode img location"); LOG_LN("Exception while fetching gcode img location");
return false; return false;
} }
@@ -52,14 +52,14 @@ bool has_32_32_gcode_img(const char* filename)
} }
if (chosen_thumb != NULL){ if (chosen_thumb != NULL){
Serial.printf("Found 32x32 PNG gcode img at %s\n", filename); LOG_F(("Found 32x32 PNG gcode img at %s\n", filename))
strcpy(img_filename_path, chosen_thumb); strcpy(img_filename_path, chosen_thumb);
return true; return true;
} }
} }
else else
{ {
Serial.printf("Failed to fetch gcode image data: %d\n", httpCode); LOG_F(("Failed to fetch gcode image data: %d\n", httpCode))
} }
return false; return false;
@@ -70,7 +70,7 @@ lv_obj_t* draw_gcode_img()
clear_img_mem(); clear_img_mem();
if (img_filename_path[0] == 0){ if (img_filename_path[0] == 0){
Serial.println("No gcode img path"); LOG_LN("No gcode img path");
return NULL; return NULL;
} }
@@ -81,7 +81,7 @@ lv_obj_t* draw_gcode_img()
httpCode = client.GET(); httpCode = client.GET();
} }
catch (...){ catch (...){
Serial.println("Exception while fetching gcode img"); LOG_LN("Exception while fetching gcode img");
return NULL; return NULL;
} }
@@ -90,13 +90,13 @@ lv_obj_t* draw_gcode_img()
size_t len = client.getSize(); size_t len = client.getSize();
if (len <= 0) if (len <= 0)
{ {
Serial.println("No gcode img data"); LOG_LN("No gcode img data");
return NULL; return NULL;
} }
data_png = (unsigned char*)malloc(len + 1); data_png = (unsigned char*)malloc(len + 1);
if (len != client.getStream().readBytes(data_png, len)){ if (len != client.getStream().readBytes(data_png, len)){
Serial.println("Failed to read gcode img data"); LOG_LN("Failed to read gcode img data");
clear_img_mem(); clear_img_mem();
return NULL; return NULL;
} }
@@ -120,12 +120,12 @@ lv_obj_t* draw_gcode_img()
lv_obj_t* show_gcode_img(const char* filename) lv_obj_t* show_gcode_img(const char* filename)
{ {
if (filename == NULL){ if (filename == NULL){
Serial.println("No gcode filename"); LOG_LN("No gcode filename");
return NULL; return NULL;
} }
if (!has_32_32_gcode_img(filename)){ if (!has_32_32_gcode_img(filename)){
Serial.println("No 32x32 gcode img found"); LOG_LN("No 32x32 gcode img found");
return NULL; return NULL;
} }

View File

@@ -10,6 +10,7 @@
#include "switch_printer.h" #include "switch_printer.h"
#include "macros.h" #include "macros.h"
#include "../core/lv_setup.h" #include "../core/lv_setup.h"
#include "serial/serial_console.h"
lv_obj_t * hostEntry; lv_obj_t * hostEntry;
lv_obj_t * portEntry; lv_obj_t * portEntry;
@@ -66,7 +67,7 @@ connection_status_t verify_ip(){
return httpCode == 200 ? CONNECT_OK : CONNECT_FAIL; return httpCode == 200 ? CONNECT_OK : CONNECT_FAIL;
} }
catch (...) { catch (...) {
Serial.println("Failed to connect"); LOG_LN("Failed to connect");
return CONNECT_FAIL; return CONNECT_FAIL;
} }
} }
@@ -253,5 +254,6 @@ void ip_init(){
while (!get_current_printer_config()->ip_configured) while (!get_current_printer_config()->ip_configured)
{ {
lv_handler(); lv_handler();
serial_console::run();
} }
} }

View File

@@ -8,7 +8,7 @@ PRINTER_CONFIG * curernt_config = NULL;
static void btn_press(lv_event_t * e){ static void btn_press(lv_event_t * e){
lv_obj_t * btn = lv_event_get_target(e); lv_obj_t * btn = lv_event_get_target(e);
const char* macro = (const char*)lv_event_get_user_data(e); const char* macro = (const char*)lv_event_get_user_data(e);
Serial.printf("Macro: %s\n", macro); LOG_F(("Macro: %s\n", macro))
send_gcode(false, macro); send_gcode(false, macro);
} }
@@ -25,7 +25,7 @@ static void power_device_toggle(lv_event_t * e)
auto state = lv_obj_get_state(lv_event_get_target(e)); auto state = lv_obj_get_state(lv_event_get_target(e));
bool checked = (state & LV_STATE_CHECKED == LV_STATE_CHECKED); bool checked = (state & LV_STATE_CHECKED == LV_STATE_CHECKED);
const char* power_device_name = (const char*)lv_event_get_user_data(e); const char* power_device_name = (const char*)lv_event_get_user_data(e);
Serial.printf("Power Device: %s, State: %d -> %d\n", power_device_name, !checked, checked); LOG_F(("Power Device: %s, State: %d -> %d\n", power_device_name, !checked, checked))
if (curernt_config != NULL) if (curernt_config != NULL)
set_power_state(power_device_name, checked, curernt_config); set_power_state(power_device_name, checked, curernt_config);

View File

@@ -49,7 +49,7 @@ void do_update_callback(int offset, int totallength)
void ota_do_update(bool variant_automatic) void ota_do_update(bool variant_automatic)
{ {
Serial.println("Starting OTA Update"); LOG_LN("Starting OTA Update");
lv_obj_clean(lv_scr_act()); lv_obj_clean(lv_scr_act());
lv_obj_t *panel = lv_create_empty_panel(lv_scr_act()); lv_obj_t *panel = lv_create_empty_panel(lv_scr_act());
@@ -67,7 +67,7 @@ void ota_do_update(bool variant_automatic)
lv_label_set_text(update_label, "0/0"); lv_label_set_text(update_label, "0/0");
if (!variant_automatic) { if (!variant_automatic) {
Serial.println("Freezing Background Tasks"); LOG_LN("Freezing Background Tasks");
screen_timer_wake(); screen_timer_wake();
screen_timer_stop(); screen_timer_stop();
freeze_request_thread(); freeze_request_thread();
@@ -90,7 +90,7 @@ void ota_init()
{ {
//ota_pull.AllowDowngrades(true); //ota_pull.AllowDowngrades(true);
int result = ota_pull.CheckForOTAUpdate(ota_url, REPO_VERSION, ESP32OTAPull::ActionType::DONT_DO_UPDATE); int result = ota_pull.CheckForOTAUpdate(ota_url, REPO_VERSION, ESP32OTAPull::ActionType::DONT_DO_UPDATE);
Serial.printf("OTA Update Result: %d\n", result); LOG_F(("OTA Update Result: %d\n", result))
update_available = result == ESP32OTAPull::UPDATE_AVAILABLE; update_available = result == ESP32OTAPull::UPDATE_AVAILABLE;
if (global_config.auto_ota_update && update_available) if (global_config.auto_ota_update && update_available)

View File

@@ -19,7 +19,7 @@ static void btn_print_file(lv_event_t * e){
SETUP_HTTP_CLIENT("/printer/print/start?filename=" + urlEncode(selected_file->name)); SETUP_HTTP_CLIENT("/printer/print/start?filename=" + urlEncode(selected_file->name));
int httpCode = client.POST(""); int httpCode = client.POST("");
Serial.printf("Print start: HTTP %d\n", httpCode); LOG_F(("Print start: HTTP %d\n", httpCode))
} }
static void btn_print_file_verify(lv_event_t * e){ static void btn_print_file_verify(lv_event_t * e){

View File

@@ -75,7 +75,7 @@ static void keyboard_cb_edit_move_increment(lv_event_t * e)
} }
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_config()->printer_move_x_steps, get_current_printer_config()->printer_move_y_steps, get_current_printer_config()->printer_move_z_steps};
Serial.printf("Setting increment %d %d %f\n", selected_column, selected_row, increment); LOG_F(("Setting increment %d %d %f\n", selected_column, selected_row, increment))
items[selected_column][selected_row] = increment * 10; items[selected_column][selected_row] = increment * 10;
write_global_config(); write_global_config();
nav_buttons_setup(PANEL_MOVE); nav_buttons_setup(PANEL_MOVE);

View File

@@ -0,0 +1,370 @@
#include "serial_commands.h"
#include <HardwareSerial.h>
#include <Esp.h>
#include <cstring>
#include "../../conf/global_config.h"
#include "../switch_printer.h"
namespace serial_console {
/* How to add a new command:
- add the handler; function signature must be like: void handler(String argv[])
- add {"command_name", &handler_name, argc} to commandHandlers
(argc = num of args + 1; argv[0] is always the command name)
- add the handler signature to serial_command.h
- add description to help()
- optionally add handling the new preference to sets() and settings() if it modifies global_config
*/
HANDLER commandHandlers[] = {
{"help", &help, 1},
{"reset", &reset, 1},
{"settings", &settings, 1},
{"sets", &sets, 1},
{"erase", &erase, 2},
{"key", &key, 2},
{"touch", &touch, 5},
{"ssid", &ssid, 3},
{"ip", &ip, 3},
{"rotation", &rotation, 2},
{"brightness", &brightness, 2},
{"printer", &printer, 2},
{"debug", &debug, 2},
{"echo", &echo, 2}
};
void help(String argv[])
{
Serial.println("Serial console commands:");
Serial.println("");
Serial.println("settings - show current settings");
Serial.println("sets - show current settings as commands for copy-paste");
Serial.println("erase [item] - unconfigure parameter (key|touch|ssid|ip|all)");
Serial.println("reset - restart CYD-klipper");
Serial.println("touch [xm xo ym yo] - set touchscreen multipliers and offsets");
Serial.println("ssid [name pass] - set the network SSID and password to connect to");
Serial.println("ip [address port] - set Moonraker address");
Serial.println("key [key] - set the Moonraker API key");
Serial.println("rotation [on|off] - set rotate screen 180 degrees");
Serial.println("brightness [num] - set screen brightness");
Serial.println("printer [num|-1] - set active printer#; -1 for multi-printer mode off");
Serial.println("debug [on|off] - set printing of debug messages to serial console (not saved)");
Serial.println("echo [on|off] - set remote echo (eecchhoo ooffff) (not saved)");
Serial.println("help - this help");
Serial.println("");
Serial.println("Settings are saved immediately but come into effect after reset");
Serial.println("Unlike GUI, serial console does not validate if settings");
Serial.println("you enter work correctly. This is a double-edged sword.");
}
// this must be here, because serial_console doesn't have a clue about sizeof(commandHandlers) at compile time
int find_command(String cmd)
{
for(int i=0; i < sizeof(commandHandlers) / sizeof(HANDLER); ++i)
{
if(cmd == commandHandlers[i].name) return i;
}
Serial.println("Unknown command");
return -1;
}
void reset(String argv[])
{
ESP.restart();
}
void sets(String argv[])
{
Serial.printf("printer %d\n", global_config.multi_printer_mode?global_config.printer_index:-1);
if(global_config.wifi_configured)
{
Serial.printf("ssid %s %s\n",global_config.wifi_SSID,
#if DISPLAY_SECRETS
global_config.wifi_password
#else
"[redacted]"
#endif
);
}
else
{
Serial.printf("erase ssid\n");
}
if(get_current_printer_config()->ip_configured)
{
Serial.printf("ip %s %d\n",get_current_printer_config()->klipper_host, get_current_printer_config()->klipper_port);
}
else
{
Serial.printf("erase ip\n");
}
if(get_current_printer_config()->auth_configured)
{
Serial.printf("key %s\n",
#if DISPLAY_SECRETS
get_current_printer_config()->klipper_auth
#else
"[redacted]"
#endif
);
}
else
{
Serial.printf("erase key\n");
}
if(global_config.screen_calibrated)
{
Serial.printf("touch %f %f %f %f\n",
global_config.screen_cal_x_mult, global_config.screen_cal_x_offset, global_config.screen_cal_y_mult, global_config.screen_cal_y_offset);
}
else
{
Serial.printf("erase touch\n");
}
Serial.printf("rotation %s\n",global_config.rotate_screen?"on":"off");
Serial.printf("brightness %d\n",global_config.brightness);
}
void settings(String argv[])
{
if(get_current_printer_config()->printer_name[0] != 0)
{
Serial.printf("Current printer# %d name: %s",global_config.printer_index, get_current_printer_config()->printer_name);
}
else
{
Serial.printf("Current printer# %d",global_config.printer_index);
}
Serial.printf(" Multi-printer mode %s\n",global_config.multi_printer_mode?"enabled":"disabled");
if(global_config.wifi_configured)
{
Serial.printf("SSID: %s Password: %s\n",global_config.wifi_SSID,
#if DISPLAY_SECRETS
global_config.wifi_password
#else
"[redacted]"
#endif
);
}
else
{
Serial.printf("Wifi not configured\n");
}
if(get_current_printer_config()->ip_configured)
{
Serial.printf("Moonraker address: %s:%d\n",get_current_printer_config()->klipper_host, get_current_printer_config()->klipper_port);
}
else
{
Serial.printf("Moonraker address not configured\n");
}
if(get_current_printer_config()->auth_configured)
{
Serial.printf("Moonraker API key: %s\n",
#if DISPLAY_SECRETS
get_current_printer_config()->klipper_auth
#else
"[redacted]"
#endif
);
}
else
{
Serial.printf("Moonraker API key not configured\n");
}
if(global_config.screen_calibrated)
{
Serial.printf("Screen coefficients: x_screen = %f * x_touch + %f; y_screen = %f * y_touch + %f\n",
global_config.screen_cal_x_mult, global_config.screen_cal_x_offset, global_config.screen_cal_y_mult, global_config.screen_cal_y_offset);
}
else
{
Serial.printf("Screen not calibrated\n");
}
Serial.printf("Screen orientation: %s\n",global_config.rotate_screen?"rotated":"normal");
Serial.printf("Screen brightness: %d\n",global_config.brightness);
}
void erase_one(const String arg)
{
if(arg == "key")
{
get_current_printer_config()->auth_configured = false;
// overwrite the key to make it unrecoverable for 3rd parties
memset(get_current_printer_config()->klipper_auth,0,32);
write_global_config();
}
else if(arg == "ip")
{
get_current_printer_config()->ip_configured = false;
write_global_config();
}
else if(arg == "touch")
{
global_config.screen_calibrated = false;
write_global_config();
}
else if(arg == "ssid")
{
global_config.wifi_configured = false;
// overwrite the pass to make it unrecoverable for 3rd parties
memset(global_config.wifi_password,0,64);
write_global_config();
}
else
{
Serial.println("Unknown key");
}
}
void erase(String argv[])
{
const String& arg=argv[1];
if(arg != "all")
{
erase_one(arg);
}
else
{
erase_one("key");
erase_one("ip");
erase_one("touch");
erase_one("ssid");
}
}
void key(String argv[])
{
if (argv[1].length() != 32)
{
Serial.println("Key must be 32 characters");
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));
write_global_config();
}
void touch(String argv[])
{
global_config.screen_cal_x_mult = argv[1].toFloat();
global_config.screen_cal_x_offset = argv[2].toFloat();
global_config.screen_cal_y_mult = argv[3].toFloat();
global_config.screen_cal_y_offset = argv[4].toFloat();
global_config.screen_calibrated = true;
write_global_config();
}
void ssid(String argv[])
{
strncpy(global_config.wifi_SSID, argv[1].c_str(), sizeof(global_config.wifi_SSID)-1);
strncpy(global_config.wifi_password, argv[2].c_str(), sizeof(global_config.wifi_password)-1);
global_config.wifi_configured = true;
write_global_config();
}
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;
write_global_config();
}
void rotation(String argv[])
{
if(argv[1] == "on")
{
global_config.rotate_screen = true;
write_global_config();
}
else if (argv[1] == "off")
{
global_config.rotate_screen = false;
write_global_config();
}
else
{
Serial.println("Rotation can be on or off");
}
}
void brightness(String argv[])
{
global_config.brightness = argv[1].toInt();
write_global_config();
}
void printer(String argv[])
{
int ndx = argv[1].toInt();
if(ndx == -1)
{
global_config.multi_printer_mode = false;
switch_printer(0);
}
else if( ndx >=0 && ndx < PRINTER_CONFIG_COUNT)
{
global_config.multi_printer_mode = true;
switch_printer(ndx);
}
else
{
Serial.println("Printer index out of range");
}
}
void debug(String argv[])
{
if(argv[1] == "on")
{
temporary_config.debug = true;
}
else if (argv[1] == "off")
{
temporary_config.debug = false;
}
else
{
Serial.println("debug can be on or off");
}
}
void echo(String argv[])
{
if(argv[1] == "on")
{
temporary_config.remote_echo = true;
}
else if (argv[1] == "off")
{
temporary_config.remote_echo = false;
}
else
{
Serial.println("Echo can be on or off");
}
}
}

View File

@@ -0,0 +1,29 @@
#include <WString.h>
namespace serial_console {
typedef struct _HANDLER {
const char* name;
void (* function)(String argv[]);
int argc;
} HANDLER;
extern HANDLER commandHandlers[];
void help(String argv[]);
void reset(String argv[]);
void settings(String argv[]);
void sets(String argv[]);
void erase(String argv[]);
void key(String argv[]);
void touch(String argv[]);
void ssid(String argv[]);
void ip(String argv[]);
void rotation(String argv[]);
void brightness(String argv[]);
void printer(String argv[]);
void debug(String argv[]);
void echo(String argv[]);
int find_command(String cmd);
}

View File

@@ -0,0 +1,153 @@
#include "serial_commands.h"
#include "../../conf/global_config.h"
#include <HardwareSerial.h>
#include <WString.h>
#define MAX_COMDLINE_SIZE 80
#define MAX_WORDS 6
namespace serial_console
{
/*
* read_string_until: Non-blocking replacement for Serial.readStringUntil()..
* With delimeter '\n' acts as 'read line'.
* If input (line) size exceeds provided buffer's size, that entire input (until next delimeter) is silently discarded.
* Serial.available() can return true without \n being ever in the buffer, so we don't trust it here.
*/
bool read_string_until(char delimiter, char *result, int max_len)
{
static int index = 0;
int c; // read character, -1 if none
int cnt = 100; // limit on amount of iterations in one go; we're supposed to be non-blocking!
while ((c = Serial.read()) != -1 && cnt > 0)
{
--cnt;
// backspace
if (c == 8)
{
if (index > 0)
{
if(temporary_config.remote_echo) Serial.print("\x08 \x08"); // overwrite last character with space and move cursor 1 back.
index--;
}
continue;
}
if(temporary_config.remote_echo) Serial.print((char)c); // echo
// Buffer overflow handling:
// start treating current buffer as invalid:
// - stop collecting more data
// - return false on delimeter, flushing everything collected,
// - restart collection from scratch after delimeter,
// - return control as normal.
if (index >= max_len - 1)
{
if (c == delimiter) // got delimeter: flush buffer quietly, restart collection.
{
index = 0;
return false;
}
else
continue; // discard any data past the end of the buffer, keep reading
}
result[index++] = c;
// delimiter was found
if (c == delimiter)
{
result[index] = '\0'; // Null-terminate the string
index = 0;
return true; // Success: Delimiter found
}
}
return false; // still waiting for delimeter
}
// split input into words.
// assumes input ends with '\n', also ends parsing if found MAX_WORDS already.
int tokenize(String results[], char *input)
{
int index = 0;
int word_count = 0;
String word = "";
do
{
if (input[index] == '\t' || input[index] == ' ' || input[index] == '\n' || input[index] == '\r' || input[index] == '\0')
{
if (word.length() > 0)
{
results[word_count] = word;
++word_count;
if (word_count >= MAX_WORDS)
{
return word_count;
}
word = "";
}
if (input[index] == '\n' || input[index] == '\0')
{
return word_count;
}
index++;
}
else
{
word += input[index];
index++;
}
} while (1);
}
void greet()
{
Serial.println("CYD-Klipper " REPO_VERSION);
Serial.println("Type 'help' for serial console command list");
Serial.print("> ");
}
bool verify_arg_count(int got, int expected)
{
if (got != expected)
{
Serial.printf("Command expects %d argument%s, %d given.\n", expected - 1, expected == 2 ? "" : "s", got - 1);
return false;
}
return true;
}
// main "engine": non-blockingly read until newline found, parse, execute.
void run()
{
static char cmdline[MAX_COMDLINE_SIZE + 1] = {0};
if (!read_string_until('\n', cmdline, MAX_COMDLINE_SIZE))
return;
String argv[MAX_WORDS];
int argc = tokenize(argv, cmdline);
if (argc > 0)
{
do
{
int cmd_id = find_command(argv[0]);
if (cmd_id == -1)
break;
if (!verify_arg_count(argc, commandHandlers[cmd_id].argc))
break;
commandHandlers[cmd_id].function(argv);
} while (0);
}
Serial.print("> ");
}
}

View File

@@ -0,0 +1,8 @@
namespace serial_console {
void greet();
void run();
}

View File

@@ -5,6 +5,7 @@
#include "WiFi.h" #include "WiFi.h"
#include "../core/data_setup.h" #include "../core/data_setup.h"
#include "../core/lv_setup.h" #include "../core/lv_setup.h"
#include "serial/serial_console.h"
void wifi_init_inner(); void wifi_init_inner();
void wifi_pass_entry(const char* ssid); void wifi_pass_entry(const char* ssid);
@@ -87,7 +88,7 @@ void wifi_pass_entry(const char* ssid)
static void wifi_btn_event_handler(lv_event_t * e){ static void wifi_btn_event_handler(lv_event_t * e){
delay(100); delay(100);
char* ssid = (char*)e->user_data; char* ssid = (char*)e->user_data;
Serial.println(ssid); LOG_LN(ssid);
wifi_pass_entry(ssid); wifi_pass_entry(ssid);
} }
@@ -97,7 +98,7 @@ static void wifi_keyboard_cb_manual_ssid(lv_event_t * e){
const char * text = lv_textarea_get_text(ta); const char * text = lv_textarea_get_text(ta);
char * text_copy = (char*)malloc(strlen(text) + 1); char * text_copy = (char*)malloc(strlen(text) + 1);
strcpy(text_copy, text); strcpy(text_copy, text);
Serial.println(text_copy); LOG_LN(text_copy);
wifi_pass_entry(text_copy); wifi_pass_entry(text_copy);
} }
@@ -119,7 +120,7 @@ void wifi_init_inner(){
WiFi.begin(global_config.wifi_SSID, global_config.wifi_password); WiFi.begin(global_config.wifi_SSID, global_config.wifi_password);
} }
Serial.printf("Connecting to %s with a password length of %d\n", global_config.wifi_SSID, strlen(global_config.wifi_password)); LOG_F(("Connecting to %s with a password length of %d\n", global_config.wifi_SSID, strlen(global_config.wifi_password)))
lv_obj_t * label = lv_label_create(lv_scr_act()); lv_obj_t * label = lv_label_create(lv_scr_act());
lv_label_set_text(label, "Connecting to WiFi"); lv_label_set_text(label, "Connecting to WiFi");
@@ -221,10 +222,12 @@ void wifi_init(){
while (!global_config.wifi_configured || WiFi.status() != WL_CONNECTED){ while (!global_config.wifi_configured || WiFi.status() != WL_CONNECTED){
if (millis() - print_timer > print_freq){ if (millis() - print_timer > print_freq){
print_timer = millis(); print_timer = millis();
Serial.printf("WiFi Status: %s\n", errs[WiFi.status()]); LOG_F(("WiFi Status: %s\n", errs[WiFi.status()]))
} }
lv_handler(); lv_handler();
serial_console::run();
} }
} }
@@ -232,7 +235,7 @@ ulong start_time_recovery = 0;
void wifi_ok(){ void wifi_ok(){
if (WiFi.status() != WL_CONNECTED){ if (WiFi.status() != WL_CONNECTED){
Serial.println("WiFi Connection Lost. Reconnecting..."); LOG_LN("WiFi Connection Lost. Reconnecting...");
freeze_request_thread(); freeze_request_thread();
WiFi.disconnect(); WiFi.disconnect();
delay(5000); // Wait for the WiFi to disconnect delay(5000); // Wait for the WiFi to disconnect
@@ -250,9 +253,9 @@ void wifi_ok(){
while (WiFi.status() != WL_CONNECTED){ while (WiFi.status() != WL_CONNECTED){
delay(1000); delay(1000);
Serial.printf("WiFi Status: %s\n", errs[WiFi.status()]); LOG_F(("WiFi Status: %s\n", errs[WiFi.status()]))
if (millis() - start_time_recovery > 15000){ if (millis() - start_time_recovery > 15000){
Serial.println("WiFi Connection failed to reconnect. Restarting..."); LOG_LN("WiFi Connection failed to reconnect. Restarting...");
ESP.restart(); ESP.restart();
} }
} }

View File

@@ -23,6 +23,7 @@ A ESP32-2432S028R is required to run this project. You can find out where to buy
- Execute predefined gcode macros - Execute predefined gcode macros
- Toggle Moonraker power devices - Toggle Moonraker power devices
- OTA updates - OTA updates
- Serial console over USB (115200 8n1, echo off, LF/LF)
### Install ### Install

View File

@@ -8,6 +8,11 @@
font-family: 'Roboto', sans-serif; font-family: 'Roboto', sans-serif;
} }
TT {
font-family: 'Terminal', monospace;
background-color: #080a0b;
}
body { body {
background-color: #181a1b; background-color: #181a1b;
color: white; color: white;
@@ -27,7 +32,7 @@
color: #F44; color: #F44;
} }
.install { .configure {
margin-bottom: 300px; margin-bottom: 300px;
} }
@@ -97,5 +102,13 @@
</select> </select>
<span id="install-btn"></span> <span id="install-btn"></span>
</section> </section>
<section class="configure">
<h3><span class="iconify" data-icon="mdi-wrench" style="color: cyan; filter: drop-shadow(0 0 0.75rem blue);"></span> Config</h3>
<p> After installing CYD-Klipper, you can configure it using its touchscreen, or serial console. To use the serial console,
click 'Connect', select the serial port, select "LOGS &amp; CONSOLE" and reset the board without holding BOOT.<br>
Type <tt>help</tt> for list of available commands. You're interested in <tt>ssid</tt>, <tt>ip</tt> and <tt>key</tt>. (while you <i>can</i> set <tt>touch</tt>, it's really better done using the touchscreen.)
</section>
</section> </section>
</body> </body>