31 Commits

Author SHA1 Message Date
Sims
9a96f9336f Merge pull request #125 from suchmememanyskill/dev
v1.8.0
2024-08-31 11:49:48 +02:00
Rory Hayes
0b1db1d834 Add emergency stop and full filename options (#124)
* init estop button

* style estop and add full filename option

* finalize estop style and adjust layout to accommodate extras

---------

Co-authored-by: Sims <38142618+suchmememanyskill@users.noreply.github.com>
2024-08-31 11:36:00 +02:00
suchmememanyskill
db019939a6 Allow escaped spaces in wifi ssid serial console 2024-08-14 23:06:46 +02:00
Sims
5c46764c7c Merge pull request #122 from suchmememanyskill/dev
v1.7.0
2024-08-02 21:39:42 +02:00
suchmememanyskill
6ebaf68cf1 Merge branch 'master' into dev 2024-08-02 21:19:47 +02:00
bwucke
41aa073ae0 Serial console (#117)
* Update readme

* Update README.md (#95)

* v1.6.4 (#113)

* Fix gcode previews with special chars not loading

* Add .gitignore file (#108)

* Bulletproof ci.py (#107)

* Implement file sorting (implement #89)

* Set chip family to ESP32-S3 for specific models (fix #67)

* Add files menu to params panel while printing (implement #80)

* Update ci.py (#110)

Typo fix for ESP32-S3 boards array name

---------

Co-authored-by: Sebastian Göls <6608231+Abrynos@users.noreply.github.com>
Co-authored-by: Miroslav Zuzelka <mzuzelka@gmail.com>

* Added serial console

* backspace, minor tweaks

* - added temporary_config alongside global_config, to hold non-persistent configuration
- added macros LOG, LOG_F, LOG_LN conditional on temporary_config.debug for Serial.print/printf/println
- put all debug to console behind these macros
- added 'debug' serial command to toggle temporary_config.debug, defaults to REPO_DEVELOPMENT
- added 'echo' serial command to toggle remote echo, temporary_config.remote_echo
- added #define DISPLAY_SECRETS to global_config.h, to censor wifi password and api key on serial console
- added entries about serial console to README.md and to _site/index.html

* restored -DREPO_DEVELOPMENT=1 (m)

* Build failed on esp32-3248S035C, reduced console input buffer size (static char cmdline) as it was failing to fit.

* typo

* A lot of what should be LOG_F was LOG_LN instead
Handling undefined REPO_DEVELOPMENT when initializing temporary_config.debug

---------

Co-authored-by: Sims <38142618+suchmememanyskill@users.noreply.github.com>
Co-authored-by: Beebles <102569435+beebls@users.noreply.github.com>
Co-authored-by: Sebastian Göls <6608231+Abrynos@users.noreply.github.com>
Co-authored-by: Miroslav Zuzelka <mzuzelka@gmail.com>
Co-authored-by: Bartosz Wucke <b.wucke@a-ster.pl>
2024-08-02 21:16:45 +02:00
suchmememanyskill
19cfaefd36 Don't forget to actually use the auth 2024-07-14 19:57:43 +02:00
suchmememanyskill
04d890227e Fix auth on minimal requests 2024-07-14 19:54:38 +02:00
Sims
e2c2a38b20 v1.6.4 (#113)
* Fix gcode previews with special chars not loading

* Add .gitignore file (#108)

* Bulletproof ci.py (#107)

* Implement file sorting (implement #89)

* Set chip family to ESP32-S3 for specific models (fix #67)

* Add files menu to params panel while printing (implement #80)

* Update ci.py (#110)

Typo fix for ESP32-S3 boards array name

---------

Co-authored-by: Sebastian Göls <6608231+Abrynos@users.noreply.github.com>
Co-authored-by: Miroslav Zuzelka <mzuzelka@gmail.com>
2024-06-28 19:11:20 +02:00
Miroslav Zuzelka
5d2571ef83 Update ci.py (#110)
Typo fix for ESP32-S3 boards array name
2024-06-12 11:27:08 +02:00
suchmememanyskill
d4645f4fa1 Add files menu to params panel while printing (implement #80) 2024-06-11 20:52:51 +02:00
suchmememanyskill
4ac87c8ffc Set chip family to ESP32-S3 for specific models (fix #67) 2024-06-11 20:49:50 +02:00
suchmememanyskill
d780c8d55e Implement file sorting (implement #89) 2024-06-11 20:49:13 +02:00
Sebastian Göls
d69446a11b Bulletproof ci.py (#107) 2024-06-10 23:06:44 +02:00
Sebastian Göls
90fd1b0ab2 Add .gitignore file (#108) 2024-06-10 22:42:44 +02:00
suchmememanyskill
4a96f7db0b Fix gcode previews with special chars not loading 2024-06-09 00:18:57 +02:00
Sims
c640d7fade Merge pull request #104 from suchmememanyskill/dev
Clear memory before doing OTA
2024-05-28 22:15:23 +02:00
suchmememanyskill
d22a9e1ee4 Clear memory before doing OTA 2024-05-28 22:03:51 +02:00
Sims
98c7364ce7 Merge pull request #103 from suchmememanyskill/dev
v1.6.2
2024-05-28 21:30:19 +02:00
suchmememanyskill
7815a0fbf4 Specify specific version for esp32 platform 2024-05-26 00:26:49 +02:00
suchmememanyskill
bd32fcb81e Allow accessing the parameters/stats panel from unlocked stepper move panel 2024-05-25 12:47:43 +02:00
suchmememanyskill
bc0502745d Allow custom extrude/retract macros 2024-05-25 12:40:07 +02:00
suchmememanyskill
d75cbb65dc Fix #99 2024-05-11 00:05:24 +02:00
Beebles
e004456ee9 Update README.md (#95) 2024-04-28 23:57:29 +02:00
Flaviu Tamas
ae34e91530 Custom API key keymap (#94)
Since the api key is just hex, we can use a keymap with larger buttons
that is easier to use.
2024-04-28 20:23:49 +02:00
Flaviu Tamas
cbd40414c8 Fix segfault on entering IP (#93)
On my esp32-3248S035C, after entering the IP address, I was seeing a
segfault at

lv_mem_free at .pio/libdeps/esp32-3248S035C/lvgl/src/misc/lv_mem.c:179
allocate_btn_areas_and_controls at .pio/libdeps/esp32-3248S035C/lvgl/src/widgets/lv_btnmatrix.c:877
lv_btnmatrix_set_map at .pio/libdeps/esp32-3248S035C/lvgl/src/widgets/lv_btnmatrix.c:94
lv_keyboard_update_map at .pio/libdeps/esp32-3248S035C/lvgl/src/extra/widgets/keyboard/lv_keyboard.c:397
lv_keyboard_set_mode at .pio/libdeps/esp32-3248S035C/lvgl/src/extra/widgets/keyboard/lv_keyboard.c:185
keyboard_event_ip_entry(_lv_event_t*) at src/ui/ip_setup.cpp:81
event_send_core at .pio/libdeps/esp32-3248S035C/lvgl/src/core/lv_event.c:467
lv_event_send at .pio/libdeps/esp32-3248S035C/lvgl/src/core/lv_event.c:63
lv_keyboard_def_event_cb at .pio/libdeps/esp32-3248S035C/lvgl/src/extra/widgets/keyboard/lv_keyboard.c:308
event_send_core at .pio/libdeps/esp32-3248S035C/lvgl/src/core/lv_event.c:467
lv_event_send at .pio/libdeps/esp32-3248S035C/lvgl/src/core/lv_event.c:63
lv_btnmatrix_event at .pio/libdeps/esp32-3248S035C/lvgl/src/widgets/lv_btnmatrix.c:520
lv_obj_event_base at .pio/libdeps/esp32-3248S035C/lvgl/src/core/lv_event.c:91 (discriminator 1)
event_send_core at .pio/libdeps/esp32-3248S035C/lvgl/src/core/lv_event.c:458
lv_event_send at .pio/libdeps/esp32-3248S035C/lvgl/src/core/lv_event.c:63
indev_proc_release at .pio/libdeps/esp32-3248S035C/lvgl/src/core/lv_indev.c:970
indev_button_proc at .pio/libdeps/esp32-3248S035C/lvgl/src/core/lv_indev.c:808
lv_timer_exec at .pio/libdeps/esp32-3248S035C/lvgl/src/misc/lv_timer.c:313
set_screen_brightness() at src/core/lv_setup.cpp:191
ip_init() at src/ui/ip_setup.cpp:239
setup() at src/main.cpp:28
loopTask(void*) at /home/user/etc/.platformio/packages/framework-arduinoespressif32/cores/esp32/main.cpp:41

This seems to be due to a free-after-free. The solution here is to
potentially change the keymap before running the rest of the logic,
because the later logic may tear down the context.

This change also only changes the keyboard mode on focus change, to
avoid running this code on the many un-related events that this handler
gets called for.
2024-04-28 20:22:06 +02:00
suchmememanyskill
06691df094 Remove esp32-4827S043R-SD from CI builds 2024-04-24 22:23:57 +02:00
suchmememanyskill
9b551915d7 Fix possible nullref in fetch_printer_data 2024-04-15 22:56:57 +02:00
suchmememanyskill
73be7c6c9f Forgot to add device to platformio cfg 2024-04-15 19:39:03 +02:00
suchmememanyskill
e06ea214c4 esp32-4827S043R 2024-04-15 18:02:05 +02:00
suchmememanyskill
9e739de731 Add more clear manual install instructions 2024-04-15 17:37:07 +02:00
41 changed files with 1164 additions and 169 deletions

10
.gitignore vendored Normal file
View File

@@ -0,0 +1,10 @@
_site/out/
_site/OTA.json
_site/esp32-*.json
pyvenv.cfg
bin/
out/
lib
lib64

View File

@@ -0,0 +1,146 @@
{
"build": {
"arduino": {
"ldscript": "esp32s3_out.ld",
"partitions": "default_16MB.csv",
"memory_type": "qio_opi"
},
"core": "esp32",
"extra_flags": [
"'-D ARDUINO_ESP32S3_DEV'",
"'-D BOARD_HAS_PSRAM'",
"'-D ARDUINO_USB_MODE=1'",
"'-D ARDUINO_RUNNING_CORE=1'",
"'-D ARDUINO_EVENT_RUNNING_CORE=1'",
"'-D ARDUINO_USB_CDC_ON_BOOT=0'",
"'-D ESP32_4827S043R'",
"'-D LCD_WIDTH=480'",
"'-D LCD_HEIGHT=272'",
"'-D LVGL_BUFFER_PIXELS=(LCD_WIDTH*LCD_HEIGHT)'",
"'-D LVGL_BUFFER_MALLOC_FLAGS=(MALLOC_CAP_SPIRAM|MALLOC_CAP_8BIT)'",
"'-D GPIO_BCKL=2'",
"'-D LCD_ST7262_PAR'",
"'-D ST7262_PANEL_CONFIG_CLK_SRC=LCD_CLK_SRC_PLL160M'",
"'-D ST7262_PANEL_CONFIG_TIMINGS_PCLK_HZ=(8*1000000)'",
"'-D ST7262_PANEL_CONFIG_TIMINGS_H_RES=LCD_WIDTH'",
"'-D ST7262_PANEL_CONFIG_TIMINGS_V_RES=LCD_HEIGHT'",
"'-D ST7262_PANEL_CONFIG_TIMINGS_HSYNC_PULSE_WIDTH=4'",
"'-D ST7262_PANEL_CONFIG_TIMINGS_HSYNC_BACK_PORCH=43'",
"'-D ST7262_PANEL_CONFIG_TIMINGS_HSYNC_FRONT_PORCH=8'",
"'-D ST7262_PANEL_CONFIG_TIMINGS_VSYNC_PULSE_WIDTH=4'",
"'-D ST7262_PANEL_CONFIG_TIMINGS_VSYNC_BACK_PORCH=12'",
"'-D ST7262_PANEL_CONFIG_TIMINGS_VSYNC_FRONT_PORCH=8'",
"'-D ST7262_PANEL_CONFIG_TIMINGS_FLAGS_HSYNC_IDLE_LOW=true'",
"'-D ST7262_PANEL_CONFIG_TIMINGS_FLAGS_VSYNC_IDLE_LOW=true'",
"'-D ST7262_PANEL_CONFIG_TIMINGS_FLAGS_DE_IDLE_HIGH=false'",
"'-D ST7262_PANEL_CONFIG_TIMINGS_FLAGS_PCLK_ACTIVE_NEG=true'",
"'-D ST7262_PANEL_CONFIG_TIMINGS_FLAGS_PCLK_IDLE_HIGH=false'",
"'-D ST7262_PANEL_CONFIG_DATA_WIDTH=16'",
"'-D ST7262_PANEL_CONFIG_SRAM_TRANS_ALIGN=4'",
"'-D ST7262_PANEL_CONFIG_PSRAM_TRANS_ALIGN=64'",
"'-D ST7262_PANEL_CONFIG_HSYNC_GPIO_NUM=39'",
"'-D ST7262_PANEL_CONFIG_VSYNC_GPIO_NUM=41'",
"'-D ST7262_PANEL_CONFIG_DE_GPIO_NUM=40'",
"'-D ST7262_PANEL_CONFIG_PCLK_GPIO_NUM=42'",
"'-D ST7262_PANEL_CONFIG_DATA_GPIO_R0=8'",
"'-D ST7262_PANEL_CONFIG_DATA_GPIO_R1=3'",
"'-D ST7262_PANEL_CONFIG_DATA_GPIO_R2=46'",
"'-D ST7262_PANEL_CONFIG_DATA_GPIO_R3=9'",
"'-D ST7262_PANEL_CONFIG_DATA_GPIO_R4=1'",
"'-D ST7262_PANEL_CONFIG_DATA_GPIO_G0=5'",
"'-D ST7262_PANEL_CONFIG_DATA_GPIO_G1=6'",
"'-D ST7262_PANEL_CONFIG_DATA_GPIO_G2=7'",
"'-D ST7262_PANEL_CONFIG_DATA_GPIO_G3=15'",
"'-D ST7262_PANEL_CONFIG_DATA_GPIO_G4=16'",
"'-D ST7262_PANEL_CONFIG_DATA_GPIO_G5=4'",
"'-D ST7262_PANEL_CONFIG_DATA_GPIO_B0=45'",
"'-D ST7262_PANEL_CONFIG_DATA_GPIO_B1=48'",
"'-D ST7262_PANEL_CONFIG_DATA_GPIO_B2=47'",
"'-D ST7262_PANEL_CONFIG_DATA_GPIO_B3=21'",
"'-D ST7262_PANEL_CONFIG_DATA_GPIO_B4=14'",
"'-D ST7262_PANEL_CONFIG_DISP_GPIO_NUM=GPIO_NUM_NC'",
"'-D ST7262_PANEL_CONFIG_FLAGS_DISP_ACTIVE_LOW=false'",
"'-D ST7262_PANEL_CONFIG_FLAGS_RELAX_ON_IDLE=false'",
"'-D ST7262_PANEL_CONFIG_FLAGS_FB_IN_PSRAM=true'",
"'-D BOARD_HAS_TOUCH'",
"'-D TOUCH_XPT2046_SPI'",
"'-D XPT2046_SPI_HOST=SPI2_HOST'",
"'-D XPT2046_SPI_DMA_CHANNEL=SPI_DMA_CH_AUTO'",
"'-D XPT2046_SPI_BUS_MOSI_IO_NUM=11'",
"'-D XPT2046_SPI_BUS_MISO_IO_NUM=13'",
"'-D XPT2046_SPI_BUS_SCLK_IO_NUM=12'",
"'-D XPT2046_SPI_BUS_QUADWP_IO_NUM=GPIO_NUM_NC'",
"'-D XPT2046_SPI_BUS_QUADHD_IO_NUM=GPIO_NUM_NC'",
"'-D XPT2046_SPI_CONFIG_CS_GPIO_NUM=38'",
"'-D XPT2046_SPI_CONFIG_DC_GPIO_NUM=GPIO_NUM_NC'",
"'-D XPT2046_SPI_CONFIG_SPI_MODE=SPI_MODE0'",
"'-D XPT2046_SPI_CONFIG_PCLK_HZ=2000000'",
"'-D XPT2046_SPI_CONFIG_TRANS_QUEUE_DEPTH=3'",
"'-D XPT2046_SPI_CONFIG_LCD_CMD_BITS=8'",
"'-D XPT2046_SPI_CONFIG_LCD_PARAM_BITS=8'",
"'-D XPT2046_SPI_CONFIG_FLAGS_DC_AS_CMD_PHASE=false'",
"'-D XPT2046_SPI_CONFIG_FLAGS_DC_LOW_ON_DATA=false'",
"'-D XPT2046_SPI_CONFIG_FLAGS_OCTAL_MODE=false'",
"'-D XPT2046_SPI_CONFIG_FLAGS_LSB_FIRST=false'",
"'-D XPT2046_TOUCH_CONFIG_X_MAX=LCD_WIDTH'",
"'-D XPT2046_TOUCH_CONFIG_Y_MAX=LCD_HEIGHT'",
"'-D XPT2046_TOUCH_CONFIG_RST_GPIO_NUM=GPIO_NUM_NC'",
"'-D XPT2046_TOUCH_CONFIG_INT_GPIO_NUM=18'",
"'-D XPT2046_TOUCH_CONFIG_LEVELS_RESET=0'",
"'-D XPT2046_TOUCH_CONFIG_LEVELS_INTERRUPT=0'",
"'-D TOUCH_SWAP_XY=false'",
"'-D TOUCH_SWAP_X=false'",
"'-D TOUCH_SWAP_Y=false'",
"'-D BOARD_HAS_TF'",
"'-D TF_CS=10'",
"'-D TF_SPI_MOSI=11'",
"'-D TF_SPI_SCLK=12'",
"'-D TF_SPI_MISO=13'",
"'-DCYD_SCREEN_HEIGHT_PX=272'",
"'-DCYD_SCREEN_WIDTH_PX=480'",
"-DROTATION_INVERTED=LV_DISP_ROT_180",
"-DROTATION_NORMAL=LV_DISP_ROT_NONE",
"'-DCYD_SCREEN_GAP_PX=10'",
"'-DCYD_SCREEN_MIN_BUTTON_HEIGHT_PX=35'",
"'-DCYD_SCREEN_MIN_BUTTON_WIDTH_PX=40'",
"'-DCYD_SCREEN_FONT=lv_font_montserrat_16'",
"'-DCYD_SCREEN_FONT_SMALL=lv_font_montserrat_12'",
"'-DCYD_SCREEN_SIDEBAR_SIZE_PX=50'",
"'-DCYD_SCREEN_DRIVER_ESP32_SMARTDISPLAY=1'"
],
"f_cpu": "240000000L",
"f_flash": "80000000L",
"flash_mode": "qio",
"hwids": [
[
"0x303A",
"0x1001"
]
],
"mcu": "esp32s3",
"variant": "esp32s3"
},
"connectivity": [
"wifi"
],
"debug": {
"openocd_target": "esp32s3.cfg"
},
"frameworks": [
"arduino",
"espidf"
],
"name": "esp32-4827S043R-SD",
"upload": {
"flash_size": "16MB",
"maximum_ram_size": 327680,
"maximum_size": 16777216,
"use_1200bps_touch": true,
"wait_for_upload_port": true,
"require_upload_port": true,
"speed": 460800
},
"url": "https://www.aliexpress.com/item/1005004788147691.html",
"vendor": "Sunton"
}

View File

@@ -9,7 +9,7 @@
; https://docs.platformio.org/page/projectconf.html
[env]
platform = espressif32
platform = https://github.com/platformio/platform-espressif32#v6.4.0
board = esp32dev
framework = arduino
monitor_speed = 115200
@@ -78,5 +78,9 @@ board = esp32-3248S035C-smartdisplay
[env:esp32-4827S043C-SD]
board = esp32-4827S043C-smartdisplay
[env:esp32-4827S043R-SD]
board = esp32-4827S043C-smartdisplay
[env:esp32-8048S043C-SD]
board = esp32-8048S043C-smartdisplay

View File

@@ -3,6 +3,7 @@
#include "lvgl.h"
GLOBAL_CONFIG global_config = {0};
TEMPORARY_CONFIG temporary_config = {0};
COLOR_DEF color_defs[] = {
{LV_PALETTE_BLUE, 0, LV_PALETTE_RED},
@@ -31,9 +32,9 @@ void verify_version()
GLOBAL_CONFIG config = {0};
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) {
Serial.println("Clearing Global Config");
LOG_LN("Clearing Global Config");
preferences.clear();
}
@@ -131,4 +132,11 @@ void load_global_config()
preferences.begin("global_config", true);
preferences.getBytes("global_config", &global_config, sizeof(global_config));
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 PRINTER_CONFIG_COUNT 8
#define DISPLAY_SECRETS 0
enum {
REMAINING_TIME_CALC_PERCENTAGE = 0,
@@ -32,6 +33,8 @@ typedef struct _PRINTER_CONFIG {
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;
};
};
@@ -66,6 +69,9 @@ typedef struct _GLOBAL_CONFIG {
bool on_during_print : 1;
bool display_mode : 1; // Driver specifc usage. Currently only used on ESP32-2432S028R to fix the screen on the usb-c model
bool disable_m117_messaging : 1;
bool sort_macros : 1;
bool show_estop : 1;
bool full_filenames : 1;
};
};
@@ -84,6 +90,13 @@ typedef struct _GLOBAL_CONFIG {
unsigned char printer_index;
} 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 {
lv_palette_t primary_color;
short primary_color_light;
@@ -91,8 +104,13 @@ typedef struct _COLOR_DEF {
} COLOR_DEF;
extern GLOBAL_CONFIG global_config;
extern TEMPORARY_CONFIG temporary_config;
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 verify_version();
void load_global_config();

View File

@@ -16,6 +16,7 @@ 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,7 +43,7 @@ void unfreeze_render_thread(){
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);
try
@@ -51,7 +52,22 @@ void send_gcode(bool wait, const char *gcode)
}
catch (...)
{
Serial.println("Failed to send gcode");
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");
}
}
@@ -72,7 +88,7 @@ int get_slicer_time_estimate_s()
JsonDocument doc;
deserializeJson(doc, client.getStream());
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;
}
@@ -82,25 +98,29 @@ void move_printer(const char* axis, float amount, bool relative) {
char gcode[64];
const char* extra = (amount > 0) ? "+" : "";
const char* start = "";
const char* end = "";
bool absolute_coords = printer.absolute_coords;
if (absolute_coords && relative) {
send_gcode(true, "G91");
start = "G91\n";
}
else if (!absolute_coords && !relative) {
send_gcode(true, "G90");
start = "G90\n";
}
sprintf(gcode, "G1 %s%s%.3f F6000", axis, extra, amount);
send_gcode(true, gcode);
if (absolute_coords && relative) {
send_gcode(true, "G90");
end = "\nG90";
}
else if (!absolute_coords && !relative) {
send_gcode(true, "G91");
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;
@@ -192,7 +212,16 @@ void fetch_printer_data()
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"];
@@ -212,7 +241,7 @@ void fetch_printer_data()
if (status.containsKey("print_stats"))
{
const char *filename = status["print_stats"]["filename"];
strcpy(filename_buff, 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"];
@@ -316,7 +345,7 @@ void fetch_printer_data()
unfreeze_render_thread();
}
Serial.printf("Failed to fetch printer data: %d\n", httpCode);
LOG_F(("Failed to fetch printer data: %d\n", httpCode))
}
}
@@ -335,7 +364,7 @@ void fetch_printer_data_minimal()
delay(10);
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();
int httpCode = client.GET();

View File

@@ -54,6 +54,7 @@ extern int klipper_request_consecutive_fail_count;
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);

View File

@@ -9,9 +9,8 @@
// Always has +1 entry with a null'd name
FILESYSTEM_FILE* last_query = NULL;
FILESYSTEM_FILE* get_files(int limit){
freeze_request_thread();
void clear_files()
{
if (last_query != NULL){
FILESYSTEM_FILE* current = last_query;
@@ -21,9 +20,16 @@ FILESYSTEM_FILE* get_files(int limit){
}
free(last_query);
last_query = NULL;
}
}
Serial.printf("Heap space pre-file-parse: %d bytes\n", esp_get_free_heap_size());
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<FILESYSTEM_FILE> files;
auto timer_request = millis();
@@ -35,7 +41,7 @@ FILESYSTEM_FILE* get_files(int limit){
if (httpCode == 200){
JsonDocument doc;
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>();
for (auto file : result){
@@ -56,7 +62,7 @@ FILESYSTEM_FILE* get_files(int limit){
f.name = (char*)malloc(strlen(path) + 1);
if (f.name == NULL){
Serial.println("Failed to allocate memory");
LOG_LN("Failed to allocate memory");
continue;
}
strcpy(f.name, path);
@@ -82,7 +88,7 @@ FILESYSTEM_FILE* get_files(int limit){
FILESYSTEM_FILE* result = (FILESYSTEM_FILE*)malloc(size);
if (result == NULL){
Serial.println("Failed to allocate memory");
LOG_LN("Failed to allocate memory");
for (auto file : files){
free(file.name);
@@ -100,8 +106,8 @@ FILESYSTEM_FILE* get_files(int limit){
result += 1;
}
Serial.printf("Heap space post-file-parse: %d bytes\n", esp_get_free_heap_size());
Serial.printf("Got %d files. Request took %dms, parsing took %dms\n", files.size(), timer_parse - timer_request, millis() - timer_parse);
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;
}

View File

@@ -20,3 +20,4 @@ typedef struct _FILESYSTEM_FILE {
} FILESYSTEM_FILE;
FILESYSTEM_FILE* get_files(int limit);
void clear_files();

View File

@@ -2,16 +2,19 @@
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;
}
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){
client.useHTTP10(true);
}
@@ -23,7 +26,7 @@ void configure_http_client(HTTPClient &client, String url, bool stream, int time
client.begin(url);
if (get_current_printer_config()->auth_configured) {
client.addHeader("X-Api-Key", get_current_printer_config()->klipper_auth);
if (config->auth_configured) {
client.addHeader("X-Api-Key", config->klipper_auth);
}
}

View File

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

View File

@@ -4,6 +4,7 @@
#include "lvgl.h"
#include "../ui/ui_utils.h"
#include <Esp.h>
#include "../ui/serial/serial_console.h"
#ifndef CPU_FREQ_HIGH
#define CPU_FREQ_HIGH 240
@@ -117,6 +118,7 @@ void lv_do_calibration(){
while (true){
lv_handler();
serial_console::run();
if (point[0] != 0 && point[1] != 0){
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);
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();
}
@@ -183,7 +185,7 @@ void lv_do_calibration(){
write_global_config();
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()
@@ -208,7 +210,7 @@ void screen_timer_wake()
// Reset cpu freq
setCpuFrequencyMhz(CPU_FREQ_HIGH);
Serial.printf("CPU Speed: %d MHz\n", ESP.getCpuFreqMHz());
LOG_F(("CPU Speed: %d MHz\n", ESP.getCpuFreqMHz()))
#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 ;)
setCpuFrequencyMhz(CPU_FREQ_LOW);
Serial.printf("CPU Speed: %d MHz\n", ESP.getCpuFreqMHz());
LOG_F(("CPU Speed: %d MHz\n", ESP.getCpuFreqMHz()))
#endif
}

View File

@@ -12,6 +12,15 @@ 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;
@@ -24,11 +33,7 @@ MACROSQUERY macros_query(PRINTER_CONFIG * config)
deserializeJson(doc, client.getStream());
auto result = doc["result"].as<JsonObject>();
for (int i = 0; i < macros_count; i++){
free(macros[i]);
}
macros_count = 0;
macros_clear();
for (JsonPair i : result){
const char *key = i.key().c_str();
@@ -40,6 +45,13 @@ MACROSQUERY macros_query(PRINTER_CONFIG * config)
}
}
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 {
@@ -85,6 +97,15 @@ 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;
@@ -97,11 +118,7 @@ POWERQUERY power_devices_query(PRINTER_CONFIG * config)
deserializeJson(doc, client.getStream());
auto result = doc["result"]["devices"].as<JsonArray>();
for (int i = 0; i < stored_power_devices_count; i++){
free(power_devices[i]);
}
stored_power_devices_count = 0;
power_devices_clear();
for (auto i : result){
const char * device_name = i["device"];
@@ -154,8 +171,6 @@ 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;

View File

@@ -23,3 +23,5 @@ 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();

View File

@@ -100,7 +100,7 @@ private:
size_t bytes_written = Update.write(buff, bytes_read);
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;
}
offset += bytes_written;
@@ -212,8 +212,8 @@ public:
String CDevice = config["Device"].isNull() ? "" : (const char *)config["Device"];
CVersion = config["Version"].isNull() ? "" : (const char *)config["Version"];
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());
//Serial.printf("Against %s %s %s %s\n", BoardName.c_str(), DeviceName.c_str(), CurrentVersion, ConfigName.c_str());
//LOG_F(("Checking %s %s %s %s\n", CBoard.c_str(), CDevice.c_str(), CVersion.c_str(), CConfig.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) &&
(CDevice.isEmpty() || CDevice == DeviceName) &&
(CConfig.isEmpty() || CConfig == ConfigName))

View File

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

View File

@@ -2,6 +2,7 @@
#include "lvgl.h"
#include "ui_utils.h"
#include <Esp.h>
#include <UrlEncode.h>
#include <ArduinoJson.h>
#include "../conf/global_config.h"
#include "../core/http_client.h"
@@ -10,29 +11,27 @@ static unsigned char * data_png = NULL;
static char img_filename_path[256] = {0};
static lv_img_dsc_t img_header = {0};
bool has_128_128_gcode(const char* filename)
bool has_32_32_gcode_img(const char* filename)
{
if (filename == NULL){
Serial.println("No gcode filename");
LOG_LN("No gcode filename");
return false;
}
SETUP_HTTP_CLIENT("/server/files/thumbnails?filename=" + String(filename));
SETUP_HTTP_CLIENT("/server/files/thumbnails?filename=" + urlEncode(filename));
int httpCode = 0;
try {
httpCode = client.GET();
}
catch (...){
Serial.println("Exception while fetching gcode img location");
return {0};
LOG_LN("Exception while fetching gcode img location");
return false;
}
if (httpCode == 200)
{
String payload = client.getString();
JsonDocument doc;
deserializeJson(doc, payload);
deserializeJson(doc, client.getStream());
auto result = doc["result"].as<JsonArray>();
const char* chosen_thumb = NULL;
@@ -53,11 +52,15 @@ bool has_128_128_gcode(const char* filename)
}
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);
return true;
}
}
else
{
LOG_F(("Failed to fetch gcode image data: %d\n", httpCode))
}
return false;
}
@@ -67,18 +70,18 @@ lv_obj_t* draw_gcode_img()
clear_img_mem();
if (img_filename_path[0] == 0){
Serial.println("No gcode img path");
LOG_LN("No gcode img path");
return NULL;
}
SETUP_HTTP_CLIENT_FULL("/server/files/gcodes/" + String(img_filename_path), false, 2000);
SETUP_HTTP_CLIENT_FULL("/server/files/gcodes/" + urlEncode(img_filename_path), false, 2000);
int httpCode = 0;
try {
httpCode = client.GET();
}
catch (...){
Serial.println("Exception while fetching gcode img");
LOG_LN("Exception while fetching gcode img");
return NULL;
}
@@ -87,13 +90,13 @@ lv_obj_t* draw_gcode_img()
size_t len = client.getSize();
if (len <= 0)
{
Serial.println("No gcode img data");
LOG_LN("No gcode img data");
return NULL;
}
data_png = (unsigned char*)malloc(len + 1);
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();
return NULL;
}
@@ -117,12 +120,12 @@ lv_obj_t* draw_gcode_img()
lv_obj_t* show_gcode_img(const char* filename)
{
if (filename == NULL){
Serial.println("No gcode filename");
LOG_LN("No gcode filename");
return NULL;
}
if (!has_128_128_gcode(filename)){
Serial.println("No 32x32 gcode img found");
if (!has_32_32_gcode_img(filename)){
LOG_LN("No 32x32 gcode img found");
return NULL;
}

View File

@@ -2,5 +2,5 @@
#include "lvgl.h"
lv_obj_t* show_gcode_img(const char* filename);
bool has_128_128_gcode(const char* filename);
bool has_32_32_gcode_img(const char* filename);
void clear_img_mem();

View File

@@ -10,6 +10,7 @@
#include "switch_printer.h"
#include "macros.h"
#include "../core/lv_setup.h"
#include "serial/serial_console.h"
lv_obj_t * hostEntry;
lv_obj_t * portEntry;
@@ -33,6 +34,20 @@ static const lv_btnmatrix_ctrl_t kb_ctrl[] = {
LV_KEYBOARD_CTRL_BTN_FLAGS | 6, 4, 4, 4, 4, 4, 4, 4, 4, 4, LV_KEYBOARD_CTRL_BTN_FLAGS | 6
};
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
};
static const lv_btnmatrix_ctrl_t hex_numpad_ctrl[] = {
1, 1, 1, 1, LV_KEYBOARD_CTRL_BTN_FLAGS | 1,
1, 1, 1, 1, LV_KEYBOARD_CTRL_BTN_FLAGS | 1,
1, 1, 1, 1, LV_KEYBOARD_CTRL_BTN_FLAGS | 1,
1, 1, 1, 1, LV_KEYBOARD_CTRL_BTN_FLAGS | 1,
};
enum connection_status_t {
CONNECT_FAIL = 0,
CONNECT_OK = 1,
@@ -52,7 +67,7 @@ connection_status_t verify_ip(){
return httpCode == 200 ? CONNECT_OK : CONNECT_FAIL;
}
catch (...) {
Serial.println("Failed to connect");
LOG_LN("Failed to connect");
return CONNECT_FAIL;
}
}
@@ -62,6 +77,20 @@ static void keyboard_event_ip_entry(lv_event_t * 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_FOCUSED || code == LV_EVENT_DEFOCUSED) && ta != NULL)
{
// make sure we alter the keymap before taking actions that might
// destroy the keyboard
if (lv_obj_has_flag(ta, LV_OBJ_FLAG_USER_1))
{
lv_keyboard_set_mode(kb, LV_KEYBOARD_MODE_USER_1);
}
else
{
lv_keyboard_set_mode(kb, LV_KEYBOARD_MODE_NUMBER);
}
}
if(code == LV_EVENT_FOCUSED) {
lv_keyboard_set_textarea(kb, ta);
lv_obj_clear_flag(kb, LV_OBJ_FLAG_HIDDEN);
@@ -94,15 +123,6 @@ static void keyboard_event_ip_entry(lv_event_t * e) {
{
return;
}
if (lv_obj_has_flag(ta, LV_OBJ_FLAG_USER_1))
{
lv_keyboard_set_mode(kb, LV_KEYBOARD_MODE_USER_1);
}
else
{
lv_keyboard_set_mode(kb, LV_KEYBOARD_MODE_NUMBER);
}
}
static void keyboard_event_auth_entry(lv_event_t * e) {
@@ -170,8 +190,8 @@ void show_auth_entry()
lv_obj_set_flex_grow(passEntry, 1);
lv_keyboard_set_textarea(keyboard, passEntry);
lv_keyboard_set_map(keyboard, LV_KEYBOARD_MODE_USER_1, kb_map, kb_ctrl);
lv_keyboard_set_mode(keyboard, LV_KEYBOARD_MODE_USER_1);
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);
}
void show_ip_entry()
@@ -234,5 +254,6 @@ void ip_init(){
while (!get_current_printer_config()->ip_configured)
{
lv_handler();
serial_console::run();
}
}

View File

@@ -8,7 +8,7 @@ PRINTER_CONFIG * curernt_config = NULL;
static void btn_press(lv_event_t * e){
lv_obj_t * btn = lv_event_get_target(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);
}
@@ -25,7 +25,7 @@ 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);
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)
set_power_state(power_device_name, checked, curernt_config);

View File

@@ -30,8 +30,11 @@ static void on_state_change(void * s, lv_msg_t * m){
else if (printer.state == PRINTER_STATE_ERROR){
nav_buttons_setup(PANEL_ERROR);
}
else if (printer.state == PRINTER_STATE_IDLE) {
nav_buttons_setup(PANEL_FILES);
}
else {
nav_buttons_setup(PANEL_PRINT);
nav_buttons_setup(PANEL_PROGRESS);
}
}

View File

@@ -58,7 +58,11 @@ static void update_printer_data_time(lv_event_t * e){
}
static void btn_click_files(lv_event_t * e){
nav_buttons_setup(PANEL_PRINT);
nav_buttons_setup(PANEL_FILES);
}
static void btn_click_progress(lv_event_t * e){
nav_buttons_setup(PANEL_PROGRESS);
}
static void btn_click_move(lv_event_t * e){
@@ -115,7 +119,7 @@ void create_button(const char* icon, const char* name, lv_event_cb_t button_clic
lv_obj_add_style(label, &nav_button_text_style, 0);
}
void nav_buttons_setup(unsigned char active_panel){
void nav_buttons_setup(PANEL_TYPE active_panel){
lv_obj_clean(lv_scr_act());
lv_obj_clear_flag(lv_scr_act(), LV_OBJ_FLAG_SCROLLABLE);
@@ -134,7 +138,14 @@ void nav_buttons_setup(unsigned char active_panel){
if (printer.state > PRINTER_STATE_ERROR){
// Files/Print
if (printer.state == PRINTER_STATE_IDLE)
{
create_button(LV_SYMBOL_COPY, "Idle", btn_click_files, update_printer_data_time, root_panel);
}
else
{
create_button(LV_SYMBOL_FILE, "Paused", btn_click_progress, update_printer_data_time, root_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);
@@ -165,8 +176,8 @@ void nav_buttons_setup(unsigned char active_panel){
lv_obj_align(panel, LV_ALIGN_TOP_RIGHT, 0, 0);
switch (active_panel){
case PANEL_PRINT:
print_panel_init(panel);
case PANEL_FILES:
files_panel_init(panel);
break;
case PANEL_MOVE:
move_panel_init(panel);
@@ -192,6 +203,9 @@ void nav_buttons_setup(unsigned char active_panel){
case PANEL_CONNECTING:
connecting_panel_init(panel);
break;
case PANEL_PROGRESS:
progress_panel_init(panel);
break;
}
lv_msg_send(DATA_PRINTER_DATA, &printer);

View File

@@ -1,14 +1,17 @@
#pragma once
#define PANEL_PRINT 0
#define PANEL_MOVE 1
#define PANEL_TEMP 2
#define PANEL_SETTINGS 3
#define PANEL_MACROS 4
#define PANEL_STATS 5
#define PANEL_PRINTER 6
#define PANEL_ERROR 7
#define PANEL_CONNECTING 8
enum PANEL_TYPE {
PANEL_FILES = 0,
PANEL_MOVE = 1,
PANEL_TEMP = 2,
PANEL_SETTINGS = 3,
PANEL_MACROS = 4,
PANEL_STATS = 5,
PANEL_PRINTER = 6,
PANEL_ERROR = 7,
PANEL_CONNECTING = 8,
PANEL_PROGRESS = 9,
};
void nav_buttons_setup(unsigned char active_panel);
void nav_buttons_setup(PANEL_TYPE active_panel);
void nav_style_setup();

View File

@@ -5,6 +5,9 @@
#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
@@ -46,7 +49,7 @@ void do_update_callback(int offset, int totallength)
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_t *panel = lv_create_empty_panel(lv_scr_act());
@@ -64,7 +67,7 @@ void ota_do_update(bool variant_automatic)
lv_label_set_text(update_label, "0/0");
if (!variant_automatic) {
Serial.println("Freezing Background Tasks");
LOG_LN("Freezing Background Tasks");
screen_timer_wake();
screen_timer_stop();
freeze_request_thread();
@@ -74,6 +77,11 @@ 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);
}
@@ -82,7 +90,7 @@ void ota_init()
{
//ota_pull.AllowDowngrades(true);
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;
if (global_config.auto_ota_update && update_available)

View File

@@ -19,10 +19,14 @@ static void btn_print_file(lv_event_t * e){
SETUP_HTTP_CLIENT("/printer/print/start?filename=" + urlEncode(selected_file->name));
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){
if (printer.state != PRINTER_STATE_IDLE){
return;
}
const auto button_size_mult = 1.3f;
lv_obj_t * btn = lv_event_get_target(e);
@@ -76,12 +80,7 @@ static void btn_print_file_verify(lv_event_t * e){
}
}
void print_panel_init(lv_obj_t* panel){
if (printer.state == PRINTER_STATE_PRINTING || printer.state == PRINTER_STATE_PAUSED){
progress_panel_init(panel);
return;
}
void files_panel_init(lv_obj_t* panel){
clear_img_mem();
lv_obj_t * list = lv_list_create(panel);
@@ -96,6 +95,10 @@ void print_panel_init(lv_obj_t* panel){
while (files != NULL && files->name != NULL && count <= 20){
lv_obj_t * btn = lv_list_add_btn(list, LV_SYMBOL_FILE, files->name);
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;

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};
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;
write_global_config();
nav_buttons_setup(PANEL_MOVE);
@@ -312,19 +312,30 @@ inline void root_panel_steppers_locked(lv_obj_t * root_panel){
inline void root_panel_steppers_unlocked(lv_obj_t * root_panel){
lv_obj_t * panel = lv_create_empty_panel(root_panel);
lv_obj_set_size(panel, CYD_SCREEN_PANEL_WIDTH_PX, CYD_SCREEN_PANEL_HEIGHT_PX);
lv_obj_set_style_pad_all(panel, CYD_SCREEN_GAP_PX, 0);
lv_layout_flex_column(panel, LV_FLEX_ALIGN_CENTER);
lv_obj_t * label = lv_label_create(panel);
lv_label_set_text(label, LV_SYMBOL_EYE_CLOSE " Steppers unlocked");
lv_obj_t * btn = lv_btn_create(panel);
lv_obj_t * btn_row = lv_create_empty_panel(panel);
lv_obj_set_size(btn_row, CYD_SCREEN_PANEL_WIDTH_PX, CYD_SCREEN_MIN_BUTTON_HEIGHT_PX);
lv_layout_flex_row(btn_row, LV_FLEX_ALIGN_CENTER);
lv_obj_t * btn = lv_btn_create(btn_row);
lv_obj_set_height(btn, CYD_SCREEN_MIN_BUTTON_HEIGHT_PX);
lv_obj_add_event_cb(btn, home_button_click, LV_EVENT_CLICKED, NULL);
label = lv_label_create(btn);
lv_label_set_text(label, LV_SYMBOL_HOME "Home Axis");
lv_obj_center(label);
btn = lv_btn_create(btn_row);
lv_obj_set_height(btn, CYD_SCREEN_MIN_BUTTON_HEIGHT_PX);
lv_obj_add_event_cb(btn, switch_to_stat_panel, LV_EVENT_CLICKED, NULL);
label = lv_label_create(btn);
lv_label_set_text(label, LV_SYMBOL_SETTINGS "Parameters");
lv_obj_center(label);
}
static void root_panel_state_update(lv_event_t * e){

View File

@@ -5,7 +5,7 @@
void settings_panel_init(lv_obj_t* panel);
void temp_panel_init(lv_obj_t* panel);
void print_panel_init(lv_obj_t* panel);
void files_panel_init(lv_obj_t* panel);
void move_panel_init(lv_obj_t* panel);
void progress_panel_init(lv_obj_t* panel);
void macros_panel_init(lv_obj_t* panel);

View File

@@ -69,37 +69,48 @@ static void btn_click_resume(lv_event_t * e){
send_gcode(true, "RESUME");
}
static void btn_click_estop(lv_event_t * e){
send_estop();
send_gcode(false, "M112");
}
void progress_panel_init(lv_obj_t* panel){
auto panel_width = CYD_SCREEN_PANEL_WIDTH_PX - CYD_SCREEN_GAP_PX * 3;
const auto button_size_mult = 1.3f;
// Emergency Stop
if (global_config.show_estop){
lv_obj_t * btn = lv_btn_create(panel);
lv_obj_add_event_cb(btn, btn_click_estop, LV_EVENT_CLICKED, NULL);
lv_obj_set_height(btn, CYD_SCREEN_MIN_BUTTON_HEIGHT_PX);
lv_obj_align(btn, LV_ALIGN_TOP_MID, 0, CYD_SCREEN_GAP_PX);
lv_obj_set_style_bg_color(btn, lv_color_hex(0xFF0000), LV_PART_MAIN);
lv_obj_t * label = lv_label_create(btn);
lv_label_set_text(label, LV_SYMBOL_POWER " EMERGENCY STOP");
lv_obj_center(label);
}
lv_obj_t * center_panel = lv_create_empty_panel(panel);
lv_obj_set_size(center_panel, panel_width, LV_SIZE_CONTENT);
lv_layout_flex_column(center_panel);
if (get_current_printer_config()->show_stats_on_progress_panel == SHOW_STATS_ON_PROGRESS_PANEL_ALL)
// 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)
{
lv_obj_align(center_panel, LV_ALIGN_TOP_MID, 0, CYD_SCREEN_GAP_PX);
lv_obj_align(center_panel, LV_ALIGN_TOP_MID, 0, CYD_SCREEN_MIN_BUTTON_HEIGHT_PX+(3 * CYD_SCREEN_GAP_PX));
}
else
{
lv_obj_align(center_panel, LV_ALIGN_CENTER, 0, 0);
}
if (get_current_printer_config()->show_stats_on_progress_panel == SHOW_STATS_ON_PROGRESS_PANEL_LAYER)
{
lv_obj_t * label = lv_label_create(panel);
lv_obj_align(label, LV_ALIGN_TOP_MID, 0, CYD_SCREEN_GAP_PX);
lv_obj_set_style_text_font(label, &CYD_SCREEN_FONT_SMALL, 0);
lv_obj_add_event_cb(label, update_printer_data_stats, LV_EVENT_MSG_RECEIVED, NULL);
lv_msg_subsribe_obj(DATA_PRINTER_DATA, label, NULL);
}
// Filename
lv_obj_t * label = lv_label_create(center_panel);
lv_label_set_text(label, printer.print_filename);
lv_label_set_long_mode(label, LV_LABEL_LONG_SCROLL_CIRCULAR);
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);
// Progress Bar
@@ -165,7 +176,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_PARTIAL)
if (get_current_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);

View File

@@ -52,6 +52,13 @@ static void light_mode_switch(lv_event_t * e){
set_color_scheme();
}
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;
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;
@@ -103,6 +110,27 @@ static void disable_m117_messaging_switch(lv_event_t* e){
write_global_config();
}
static void sort_macros_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);
global_config.sort_macros = checked;
write_global_config();
}
static void show_estop_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);
global_config.show_estop = checked;
write_global_config();
}
static void full_filenames_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);
global_config.full_filenames = checked;
write_global_config();
}
static void rotate_screen_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);
@@ -147,7 +175,7 @@ static void estimated_time_dropdown(lv_event_t * e){
write_global_config();
}
#define PRINTER_SPECIFIC_SETTING global_config.multi_printer_mode ? LV_SYMBOL_PLUS " Stored per printer" : NULL
#define PRINTER_SPECIFIC_SETTING global_config.multi_printer_mode ? "Stored per printer" : NULL
void settings_section_theming(lv_obj_t* panel)
{
@@ -157,7 +185,7 @@ void settings_section_theming(lv_obj_t* panel)
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);
#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) ? LV_SYMBOL_PLUS " Stored per printer"
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"
#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
@@ -196,6 +224,15 @@ void settings_section_behaviour(lv_obj_t* panel)
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");
lv_create_custom_menu_switch("Custom Filament Move Macros", panel, filament_move_mode_switch, get_current_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("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);
}
void settings_section_device(lv_obj_t* panel)
@@ -217,7 +254,12 @@ void settings_section_device(lv_obj_t* panel)
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
#if defined(CYD_SCREEN_DRIVER_ESP32_SMARTDISPLAY) && !defined(CYD_SCREEN_DISABLE_TOUCH_CALIBRATION)
// TODO: Rotating screen requires different calibration points.
#else
lv_create_custom_menu_switch("Rotate Screen", panel, rotate_screen_switch, global_config.rotate_screen);
#endif
lv_create_custom_menu_switch("Auto Update", panel, auto_ota_update_switch, global_config.auto_ota_update);
lv_create_custom_menu_label("Version", panel, REPO_VERSION " ");

View File

@@ -1,9 +1,14 @@
#include "panel.h"
#include "../ui_utils.h"
#include "../../core/data_setup.h"
#include "../nav_buttons.h"
#include <stdio.h>
#include <Esp.h>
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];
@@ -249,6 +254,16 @@ 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){
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);
lv_obj_t * label = lv_label_create(btn);
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);

View File

@@ -139,8 +139,15 @@ static void btn_extrude(lv_event_t * e){
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");
}
}
static void set_temp_via_preset(lv_event_t * e){
@@ -173,8 +180,15 @@ static void btn_retract(lv_event_t * e){
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");
}
}
static void set_chart_range(lv_event_t * e) {

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,157 @@
#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] == ' ' && (index <= 0 || input[index - 1] != '\\')) || 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
{
if (input[index] != '\\')
{
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 "../core/data_setup.h"
#include "../core/lv_setup.h"
#include "serial/serial_console.h"
void wifi_init_inner();
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){
delay(100);
char* ssid = (char*)e->user_data;
Serial.println(ssid);
LOG_LN(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);
char * text_copy = (char*)malloc(strlen(text) + 1);
strcpy(text_copy, text);
Serial.println(text_copy);
LOG_LN(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);
}
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_label_set_text(label, "Connecting to WiFi");
@@ -221,10 +222,12 @@ void wifi_init(){
while (!global_config.wifi_configured || WiFi.status() != WL_CONNECTED){
if (millis() - print_timer > print_freq){
print_timer = millis();
Serial.printf("WiFi Status: %s\n", errs[WiFi.status()]);
LOG_F(("WiFi Status: %s\n", errs[WiFi.status()]))
}
lv_handler();
serial_console::run();
}
}
@@ -232,7 +235,7 @@ ulong start_time_recovery = 0;
void wifi_ok(){
if (WiFi.status() != WL_CONNECTED){
Serial.println("WiFi Connection Lost. Reconnecting...");
LOG_LN("WiFi Connection Lost. Reconnecting...");
freeze_request_thread();
WiFi.disconnect();
delay(5000); // Wait for the WiFi to disconnect
@@ -250,9 +253,9 @@ void wifi_ok(){
while (WiFi.status() != WL_CONNECTED){
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){
Serial.println("WiFi Connection failed to reconnect. Restarting...");
LOG_LN("WiFi Connection failed to reconnect. Restarting...");
ESP.restart();
}
}

View File

@@ -1,29 +1,38 @@
# Building
# Manual install
## Running a developer build
## Flashing a build via the commandline
On every change made in this repository, [Github Actions](https://github.com/suchmememanyskill/CYD-Klipper/actions) automatically builds the firmware images for various screens. You can run one of these images as follows:
#### Release firmware image
1. Go to [the releases tab](https://github.com/suchmememanyskill/CYD-Klipper/releases), and download the latest `firmware.zip` release.
2. Open the firmware.zip archive you just downloaded, open the corresponding folder for your screen, then extract `merged_firmware.bin`
This merged_firmware.bin file is a ready to flash image. Note that flashing this image does wipe your current configuration.
#### Developer firmware image
On every change made in this repository, [Github Actions](https://github.com/suchmememanyskill/CYD-Klipper/actions) automatically builds the firmware images for various screens.
#### Getting a firmware image
0. Make sure you are logged into github
1. Go to a [Github Actions](https://github.com/suchmememanyskill/CYD-Klipper/actions) build summary, then download the `firmware` Artifact.
2. Open the firmware.zip archive you just downloaded, open the corresponding folder for your screen, then extract `merged_firmware.bin`
This merged_firmware.bin file is a ready to flash image. Note that flashing this image does wipe your current configuration.
#### Flashing merged_firmware.bin
### Flashing merged_firmware.bin
1. Download and extract [esptool](https://github.com/espressif/esptool/releases) to a new folder
- For windows, download `esptool-v4.7.0-win64.zip`
2. Open a terminal window and navigate to this new folder containing esptool
- In windows, you can type cmd and press enter in the address bar in explorer to jump to the folder in cmd ![cmd](readme/cmd.jpg)
3. Move `merged-firmware.bin` into this new folder
4. Connect the display to your computer
5. Execute the command `esptool write_flash 0x0 merged-firmware.bin`
5. Execute the command `esptool write_flash 0x0 merged_firmware.bin`
- Don't forget to hold down the boot button on the display
## Building via PlatformIO
## Building & Flashing via PlatformIO
0. Install [Visual Studio Code](https://code.visualstudio.com/) and install the PlatformIO IDE plugin.
0. Install the following tools:
- [Visual Studio Code](https://code.visualstudio.com/) and install the PlatformIO IDE plugin.
- [Git](https://git-scm.com/download/win)
1. Download the source code of CYD-Klipper
- This can be done via the `git clone https://github.com/suchmememanyskill/CYD-Klipper` command or via the green `<> Code` button on Github
2. Open the CYD-Klipper folder inside the CYD-Klipper folder in Visual Studio Code
@@ -35,3 +44,5 @@ This merged_firmware.bin file is a ready to flash image. Note that flashing this
6. Click 'Upload and Monitor'
- This will start compiling the code, and after upload it to the display
- Don't forget to hold the boot button while flashing. The screen will flash when the firmware is attempted to be flashed
![platformio](readme/platformio.png)

View File

@@ -23,10 +23,11 @@ A ESP32-2432S028R is required to run this project. You can find out where to buy
- Execute predefined gcode macros
- Toggle Moonraker power devices
- OTA updates
- Serial console over USB (115200 8n1, echo off, LF/LF)
### Install
[There is a web-based installer available. This is only supported on Chrome, Edge or Opera, and only on Desktop.](https://suchmememanyskill.github.io/CYD-Klipper/)
[There is a web-based installer available. This is only supported on Chrome, Edge, Arc or Opera, and only on Desktop.](https://suchmememanyskill.github.io/CYD-Klipper/)
On initial install, all data should be wiped. On updates, data should be able to be kept without issues.

View File

@@ -8,6 +8,11 @@
font-family: 'Roboto', sans-serif;
}
TT {
font-family: 'Terminal', monospace;
background-color: #080a0b;
}
body {
background-color: #181a1b;
color: white;
@@ -27,7 +32,7 @@
color: #F44;
}
.install {
.configure {
margin-bottom: 300px;
}
@@ -97,5 +102,13 @@
</select>
<span id="install-btn"></span>
</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>
</body>

17
ci.py
View File

@@ -7,17 +7,25 @@ CYD_PORTS = [
"esp32-8048S043C-SD",
"esp32-2432S024C-SD",
"esp32-4827S043C-SD",
"esp32-3248S035C-V"
"esp32-3248S035C-V",
#"esp32-4827S043R-SD",
]
ESP_S3_CHIPS = [
"esp32-8048S043C-SD",
"esp32-4827S043C-SD",
]
BASE_DIR = os.getcwd()
def get_manifest(base_path : str, device_name : str):
return {
"name": f"to {device_name}",
"funding_url": "https://ko-fi.com/suchmememanyskill",
"new_install_prompt_erase": True,
"builds": [
{
"chipFamily": "ESP32",
"chipFamily": "ESP32-S3" if device_name in ESP_S3_CHIPS else "ESP32",
"parts": [
{
"path": f"{base_path}/bootloader.bin",
@@ -79,7 +87,10 @@ for port in CYD_PORTS:
add_configuration(port)
os.chdir(BASE_DIR)
shutil.copytree("./out", "./_site/out")
out_dir = "./_site/out"
if os.path.exists(out_dir):
shutil.rmtree(out_dir)
shutil.copytree("./out", out_dir)
with open("./_site/OTA.json", "w") as f:
json.dump({"Configurations": configurations}, f)

BIN
readme/platformio.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB