From 2bedc3326330b897b06c291d549bf90f6e25e4ea Mon Sep 17 00:00:00 2001 From: fvanroie Date: Sat, 23 May 2020 11:44:29 +0200 Subject: [PATCH 01/33] Update to lvgl master --- lib/lvgl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/lvgl b/lib/lvgl index 85f281bd..8b663bdc 160000 --- a/lib/lvgl +++ b/lib/lvgl @@ -1 +1 @@ -Subproject commit 85f281bd3b4a6cb60381ff3d8a73534748e7d079 +Subproject commit 8b663bdc39b8a745cee39334b2f6c065babd5fd9 From 9e2795600cd92f42ebbeb878b4370842b5e07cc4 Mon Sep 17 00:00:00 2001 From: fvanroie Date: Mon, 12 Oct 2020 11:26:47 +0200 Subject: [PATCH 02/33] Update to lvgl 7.6.1 --- esp32_partition_app1300k_spiffs1216k.csv | 6 + include/hasp_conf.h | 2 +- lib/lv_lib_zifont/lv_zifont.cpp | 24 +- lib/lvgl | 2 +- platformio.ini | 29 +- src/hasp.cpp | 40 +- src/hasp_attribute.cpp | 485 +++++++++++--------- src/hasp_attribute.h | 176 ++++--- src/hasp_debug.cpp | 7 +- src/hasp_dispatch.cpp | 18 +- src/hasp_http.cpp | 5 +- src/hasp_mqtt.cpp | 2 +- src/hasp_telnet.cpp | 2 +- user_setups/esp32/d1-mini-esp32_ili9341.ini | 6 +- 14 files changed, 451 insertions(+), 353 deletions(-) create mode 100644 esp32_partition_app1300k_spiffs1216k.csv diff --git a/esp32_partition_app1300k_spiffs1216k.csv b/esp32_partition_app1300k_spiffs1216k.csv new file mode 100644 index 00000000..d361047a --- /dev/null +++ b/esp32_partition_app1300k_spiffs1216k.csv @@ -0,0 +1,6 @@ +# Name, Type, SubType, Offset, Size, Flags +nvs, data, nvs, 0x9000, 0x5000, +otadata, data, ota, 0xe000, 0x2000, +app0, app, ota_0, 0x10000, 0x160000, +app1, app, ota_1, 0x170000, 0x160000, +spiffs, data, spiffs, 0x2D0000, 0x130000, diff --git a/include/hasp_conf.h b/include/hasp_conf.h index 28260cbd..32eba200 100644 --- a/include/hasp_conf.h +++ b/include/hasp_conf.h @@ -94,7 +94,7 @@ #include "hasp_spiffs.h" #if defined(ARDUINO_ARCH_ESP32) || defined(ARDUINO_ARCH_ESP8266) -//#include "lv_zifont.h" +#include "lv_zifont.h" #endif #endif // SPIFFS diff --git a/lib/lv_lib_zifont/lv_zifont.cpp b/lib/lv_lib_zifont/lv_zifont.cpp index 829ae752..fb1f08d0 100644 --- a/lib/lv_lib_zifont/lv_zifont.cpp +++ b/lib/lv_lib_zifont/lv_zifont.cpp @@ -78,15 +78,15 @@ static inline bool openFont(File & file, const char * filename) file = SPIFFS.open(filename, "r"); if(!file) { - // Log.error(F("FONT: %sOpening font: %s"), filename); - // return false; + Log.error(F("FONT: %sOpening font: %s"), filename); + return false; } return file; } static inline void initCharacterFrame(size_t size) { - if(size > lv_mem_get_size(charBitmap_p)) { + if(size > _lv_mem_get_size(charBitmap_p)) { if(charBitmap_p) lv_mem_free(charBitmap_p); charBitmap_p = (uint8_t *)lv_mem_alloc(size); } @@ -100,14 +100,14 @@ int lv_zifont_font_init(lv_font_t ** font, const char * font_path, uint16_t size if(!*font) { *font = (lv_font_t *)lv_mem_alloc(sizeof(lv_font_t)); LV_ASSERT_MEM(*font); - lv_memset(*font, 0x00, sizeof(lv_font_t)); // lv_mem_alloc might be dirty + memset(*font, 0x00, sizeof(lv_font_t)); // lv_mem_alloc might be dirty } lv_font_fmt_zifont_dsc_t * dsc; if(!(*font)->dsc) { dsc = (lv_font_fmt_zifont_dsc_t *)lv_mem_alloc(sizeof(lv_font_fmt_zifont_dsc_t)); LV_ASSERT_MEM(dsc); - lv_memset(dsc, 0x00, sizeof(lv_font_fmt_zifont_dsc_t)); // lv_mem_alloc might be dirty + memset(dsc, 0x00, sizeof(lv_font_fmt_zifont_dsc_t)); // lv_mem_alloc might be dirty } else { dsc = (lv_font_fmt_zifont_dsc_t *)(*font)->dsc; } @@ -116,7 +116,7 @@ int lv_zifont_font_init(lv_font_t ** font, const char * font_path, uint16_t size /* Initialize Last Glyph DSC */ dsc->last_glyph_dsc = (lv_zifont_char_t *)lv_mem_alloc(sizeof(lv_zifont_char_t)); - lv_memset(dsc->last_glyph_dsc, 0x00, sizeof(lv_zifont_char_t)); // lv_mem_alloc might be dirty + memset(dsc->last_glyph_dsc, 0x00, sizeof(lv_zifont_char_t)); // lv_mem_alloc might be dirty if(dsc->last_glyph_dsc == NULL) return ZIFONT_ERROR_OUT_OF_MEMORY; dsc->last_glyph_dsc->width = 0; @@ -155,8 +155,8 @@ int lv_zifont_font_init(lv_font_t ** font, const char * font_path, uint16_t size if(!dsc->ascii_glyph_dsc) { dsc->ascii_glyph_dsc = (lv_zifont_char_t *)lv_mem_alloc(sizeof(lv_zifont_char_t) * CHAR_CACHE_SIZE); LV_ASSERT_MEM(dsc->ascii_glyph_dsc); - lv_memset(dsc->ascii_glyph_dsc, 0x00, - sizeof(lv_zifont_char_t) * CHAR_CACHE_SIZE); // lv_mem_alloc might be dirty + memset(dsc->ascii_glyph_dsc, 0x00, + sizeof(lv_zifont_char_t) * CHAR_CACHE_SIZE); // lv_mem_alloc might be dirty } if(dsc->ascii_glyph_dsc == NULL) { file.close(); @@ -406,8 +406,10 @@ bool IRAM_ATTR lv_font_get_glyph_dsc_fmt_zifont(const lv_font_t * font, lv_font_ uint32_t unicode_letter, uint32_t unicode_letter_next) { /* Only ascii characteres supported for now */ - if(unicode_letter < 0x20) return false; - if(unicode_letter > 0xff && unicode_letter < 0xf000) return false; + // returning true with a box_h of 0 does not display an error + dsc_out->box_w = dsc_out->box_h = 0; // Prevents glyph not found error messages when true is returned + if(unicode_letter < 0x20) return true; + if(unicode_letter > 0xff && unicode_letter < 0xf000) return true; // if(unicode_letter > 0xff) Serial.printf("Char# %u\n", unicode_letter); // ulong startMillis = millis(); @@ -438,7 +440,7 @@ bool IRAM_ATTR lv_font_get_glyph_dsc_fmt_zifont(const lv_font_t * font, lv_font_ if(unicode_letter >= 0xF000) { char filename[32]; sprintf_P(filename, PSTR("/fontawesome%u.zi"), fdsc->CharHeight); - if(!openFont(file, filename)) return false; + if(!openFont(file, filename)) return true; // suppress glyph not found errors for icon font } else { if(!openFont(file, (char *)font->user_data)) return false; } diff --git a/lib/lvgl b/lib/lvgl index ecd0d4fb..d01d1357 160000 --- a/lib/lvgl +++ b/lib/lvgl @@ -1 +1 @@ -Subproject commit ecd0d4fb0907d73e07788283c16e5a4ab1e829b6 +Subproject commit d01d1357ad28e10c606b9e426f7fdf0c23b1e5ac diff --git a/platformio.ini b/platformio.ini index 8a971a18..51a553a0 100644 --- a/platformio.ini +++ b/platformio.ini @@ -48,11 +48,11 @@ lib_deps = https://github.com/netwizeBE/TFT_eSPI.git ;TFT_eSPI@^2.2.2 ; Tft SPI drivers ;TFT_eSPI@^1.4.20 ; Tft SPI drivers - PubSubClient@^2.7.0 ; MQTT client - ArduinoJson@^6.15.1,>6.15.0 ; needs at least 6.15.0 + PubSubClient@^2.8.0 ; MQTT client + ArduinoJson@^6.16.1 ; JSON Parser StreamUtils@^1.4.0 Syslog@^2.0.0 - AceButton@^1.4.0 + AceButton@^1.6.1 ;AsyncTCP ;https://github.com/me-no-dev/ESPAsyncWebServer/archive/master.zip ;https://github.com/me-no-dev/ESPAsyncTCP/archive/master.zip @@ -129,27 +129,6 @@ hspi32 = ; 7 - mirror content, and rotate 90 deg anti-clockwise -;*************************************************** -; D1 Mini ESP32 with Lolin TFT 2.4" -;*************************************************** -[env:d1mini32-lolintft24] -platform = espressif32@^1.12.0 -board = wemos_d1_mini32 -upload_port = COM5 ; To change the port, use platform_override.ini -monitor_port = COM5 ; To change the port, use platform_override.ini -board_build.partitions = default.csv -build_flags = - ${flags.esp32_flags} -; -- TFT_eSPI build options ------------------------ - ${lcd.lolin24} - ${pins.vspi32} - -D TFT_DC=5 - -D TFT_CS=26 - -D TFT_RST=-1 ; RST - -D TFT_BCKL=-1 ; None, configurable via web UI (e.g. 21) - -D TOUCH_CS=17 ; (can also be 22 or 16) - - ;*************************************************** ; Lolin D32 Pro with Lolin TFT 2.4" ;*************************************************** @@ -159,7 +138,7 @@ platform = espressif32 board = lolin_d32_pro upload_port = COM6 ; To change the port, use platform_override.ini monitor_port = COM6 ; To change the port, use platform_override.ini -board_build.partitions = default.csv +board_build.partitions = esp32_partition_app1300k_spiffs1216k.csv ; default.csv build_flags = ${flags.esp32_flags} ; -- TFT_eSPI build options ------------------------ diff --git a/src/hasp.cpp b/src/hasp.cpp index fc983b0c..8e8fef7e 100644 --- a/src/hasp.cpp +++ b/src/hasp.cpp @@ -362,12 +362,24 @@ void haspSetup() /* ********** Font Initializations ********** */ defaultFont = LV_FONT_DEFAULT; // Use default font +#if ESP32 + lv_font_t * font_small = defaultFont; + lv_font_t * font_normal = &lv_font_montserrat_12; + lv_font_t * font_subtitle = &lv_font_montserrat_16; + lv_font_t * font_title = &lv_font_montserrat_22; +#else + lv_font_t * font_small = defaultFont; + lv_font_t * font_normal = defaultFont; + lv_font_t * font_subtitle = defaultFont; + lv_font_t * font_title = defaultFont; +#endif + #if HASP_USE_SPIFFS > 0 #if defined(ARDUINO_ARCH_ESP32) || defined(ARDUINO_ARCH_ESP8266) lv_zifont_init(); if(lv_zifont_font_init(&haspFonts[0], haspZiFontPath, 24) != 0) { - Log.error(F("HASP: Failed to set the custom font to %s"), haspZiFontPath); + Log.error(F("HASP: Failed to set font to %s"), haspZiFontPath); } else { defaultFont = haspFonts[0]; } @@ -390,14 +402,20 @@ void haspSetup() #endif #if(LV_USE_THEME_MONO == 1) || (LV_USE_THEME_EMPTY == 1) case 3: - th = lv_theme_empty_init(LV_COLOR_PURPLE, LV_COLOR_BLACK, LV_THEME_DEFAULT_FLAGS, defaultFont, defaultFont, - defaultFont, defaultFont); + th = lv_theme_mono_init(LV_COLOR_PURPLE, LV_COLOR_BLACK, LV_THEME_DEFAULT_FLAGS, font_small, font_normal, + font_subtitle, font_title); break; #endif #if LV_USE_THEME_MATERIAL == 1 case 4: - th = lv_theme_material_init(LV_COLOR_PURPLE, LV_COLOR_ORANGE, LV_THEME_DEFAULT_FLAGS, defaultFont, - defaultFont, defaultFont, defaultFont); + th = lv_theme_material_init(LV_COLOR_PURPLE, LV_COLOR_ORANGE, + LV_THEME_MATERIAL_FLAG_LIGHT + LV_THEME_MATERIAL_FLAG_NO_FOCUS, font_small, + font_normal, font_subtitle, font_title); + break; + case 9: + th = lv_theme_material_init(LV_COLOR_PURPLE, LV_COLOR_ORANGE, + LV_THEME_MATERIAL_FLAG_DARK + LV_THEME_MATERIAL_FLAG_NO_FOCUS, font_small, + font_normal, font_subtitle, font_title); break; #endif @@ -418,8 +436,8 @@ void haspSetup() #endif #if(LV_USE_THEME_HASP == 1) || (LV_USE_THEME_TEMPLATE == 1) case 8: - th = lv_theme_template_init(LV_COLOR_PURPLE, LV_COLOR_ORANGE, LV_THEME_DEFAULT_FLAGS, defaultFont, - defaultFont, defaultFont, defaultFont); + th = lv_theme_template_init(LV_COLOR_PURPLE, LV_COLOR_ORANGE, LV_THEME_DEFAULT_FLAGS, font_small, + font_normal, font_subtitle, font_title); break; #endif /* case 0: @@ -431,8 +449,8 @@ void haspSetup() break; */ default: - th = lv_theme_material_init(LV_COLOR_PURPLE, LV_COLOR_ORANGE, LV_THEME_DEFAULT_FLAGS, defaultFont, - defaultFont, defaultFont, defaultFont); + th = lv_theme_template_init(LV_COLOR_PURPLE, LV_COLOR_ORANGE, LV_THEME_DEFAULT_FLAGS, font_small, + font_normal, font_subtitle, font_title); Log.error(F("HASP: Unknown theme selected")); } @@ -450,13 +468,13 @@ void haspSetup() lv_style_set_text_font(&pagefont, LV_STATE_DEFAULT, defaultFont); list = lv_obj_get_style_list(lv_disp_get_layer_top(NULL), LV_OBJ_PART_MAIN); - lv_style_list_add_style(list, &pagefont); + _lv_style_list_add_style(list, &pagefont); /* Create all screens using the theme */ for(uint8_t i = 0; i < (sizeof pages / sizeof *pages); i++) { pages[i] = lv_obj_create(NULL, NULL); list = lv_obj_get_style_list(pages[i], LV_OBJ_PART_MAIN); - lv_style_list_add_style(list, &pagefont); + _lv_style_list_add_style(list, &pagefont); // lv_obj_set_size(pages[0], hres, vres); } diff --git a/src/hasp_attribute.cpp b/src/hasp_attribute.cpp index 4a110d65..b52c8ae3 100644 --- a/src/hasp_attribute.cpp +++ b/src/hasp_attribute.cpp @@ -11,7 +11,7 @@ LV_FONT_DECLARE(unscii_8_icon); extern lv_font_t * haspFonts[8]; -static inline bool is_true(const char * s); +static bool is_true(const char * s); static inline bool only_digits(const char * s); /* 16-bit hashing function http://www.cse.yorku.ca/~oz/hash.html */ @@ -57,32 +57,32 @@ static lv_color_t haspPayloadToColor(const char * payload) { switch(strlen(payload)) { case 3: - if(!strcmp_P(payload, PSTR("red"))) return haspLogColor(LV_COLOR_RED); + if(!strcasecmp_P(payload, PSTR("red"))) return haspLogColor(LV_COLOR_RED); break; case 4: - if(!strcmp_P(payload, PSTR("blue"))) return haspLogColor(LV_COLOR_BLUE); - if(!strcmp_P(payload, PSTR("cyan"))) return haspLogColor(LV_COLOR_CYAN); - if(!strcmp_P(payload, PSTR("gray"))) return haspLogColor(LV_COLOR_GRAY); - /* if(!strcmp_P(payload, PSTR("aqua"))) return haspLogColor(LV_COLOR_AQUA); - if(!strcmp_P(payload, PSTR("lime"))) return haspLogColor(LV_COLOR_LIME); - if(!strcmp_P(payload, PSTR("teal"))) return haspLogColor(LV_COLOR_TEAL); - if(!strcmp_P(payload, PSTR("navy"))) return haspLogColor(LV_COLOR_NAVY);*/ + if(!strcasecmp_P(payload, PSTR("blue"))) return haspLogColor(LV_COLOR_BLUE); + if(!strcasecmp_P(payload, PSTR("cyan"))) return haspLogColor(LV_COLOR_CYAN); + if(!strcasecmp_P(payload, PSTR("gray"))) return haspLogColor(LV_COLOR_GRAY); + // if(!strcmp_P(payload, PSTR("aqua"))) return haspLogColor(LV_COLOR_AQUA); + // if(!strcmp_P(payload, PSTR("lime"))) return haspLogColor(LV_COLOR_LIME); + // if(!strcmp_P(payload, PSTR("teal"))) return haspLogColor(LV_COLOR_TEAL); + // if(!strcmp_P(payload, PSTR("navy"))) return haspLogColor(LV_COLOR_NAVY); break; case 5: - if(!strcmp_P(payload, PSTR("green"))) return haspLogColor(LV_COLOR_GREEN); - if(!strcmp_P(payload, PSTR("white"))) return haspLogColor(LV_COLOR_WHITE); - if(!strcmp_P(payload, PSTR("black"))) return haspLogColor(LV_COLOR_BLACK); + if(!strcasecmp_P(payload, PSTR("green"))) return haspLogColor(LV_COLOR_GREEN); + if(!strcasecmp_P(payload, PSTR("white"))) return haspLogColor(LV_COLOR_WHITE); + if(!strcasecmp_P(payload, PSTR("black"))) return haspLogColor(LV_COLOR_BLACK); // if(!strcmp_P(payload, PSTR("olive"))) return haspLogColor(LV_COLOR_OLIVE); break; case 6: - if(!strcmp_P(payload, PSTR("yellow"))) return haspLogColor(LV_COLOR_YELLOW); - if(!strcmp_P(payload, PSTR("orange"))) return haspLogColor(LV_COLOR_ORANGE); - if(!strcmp_P(payload, PSTR("purple"))) return haspLogColor(LV_COLOR_PURPLE); - if(!strcmp_P(payload, PSTR("silver"))) return haspLogColor(LV_COLOR_SILVER); + if(!strcasecmp_P(payload, PSTR("yellow"))) return haspLogColor(LV_COLOR_YELLOW); + if(!strcasecmp_P(payload, PSTR("orange"))) return haspLogColor(LV_COLOR_ORANGE); + if(!strcasecmp_P(payload, PSTR("purple"))) return haspLogColor(LV_COLOR_PURPLE); + if(!strcasecmp_P(payload, PSTR("silver"))) return haspLogColor(LV_COLOR_SILVER); // if(!strcmp_P(payload, PSTR("maroon"))) return haspLogColor(LV_COLOR_MAROON); break; case 7: - if(!strcmp_P(payload, PSTR("magenta"))) return haspLogColor(LV_COLOR_MAGENTA); + if(!strcasecmp_P(payload, PSTR("magenta"))) return haspLogColor(LV_COLOR_MAGENTA); default: // if(!strcmp_P(payload, PSTR("darkblue"))) return haspLogColor(LV_COLOR_MAKE(0, 51, 102)); @@ -118,19 +118,43 @@ static lv_color_t haspPayloadToColor(const char * payload) return LV_COLOR_BLACK; } +static lv_font_t * haspPayloadToFont(const char * payload) +{ + int16_t var = atoi(payload); + + switch(var) { + case 8: + return &unscii_8_icon; + +#if ESP32 + case 12: + return &lv_font_montserrat_12; + case 16: + return &lv_font_montserrat_16; + case 22: + return &lv_font_montserrat_22; + case 28: + return &lv_font_montserrat_28_compressed; +#endif + + default: + return nullptr; + } +} + static void hasp_process_label_long_mode(lv_obj_t * obj, const char * payload, bool update) { if(update) { lv_label_long_mode_t mode = LV_LABEL_LONG_EXPAND; - if(!strcmp_P(payload, PSTR("expand"))) { + if(!strcasecmp_P(payload, PSTR("expand"))) { mode = LV_LABEL_LONG_EXPAND; - } else if(!strcmp_P(payload, PSTR("break"))) { + } else if(!strcasecmp_P(payload, PSTR("break"))) { mode = LV_LABEL_LONG_BREAK; - } else if(!strcmp_P(payload, PSTR("dots"))) { + } else if(!strcasecmp_P(payload, PSTR("dots"))) { mode = LV_LABEL_LONG_DOT; - } else if(!strcmp_P(payload, PSTR("scroll"))) { + } else if(!strcasecmp_P(payload, PSTR("scroll"))) { mode = LV_LABEL_LONG_SROLL; - } else if(!strcmp_P(payload, PSTR("loop"))) { + } else if(!strcasecmp_P(payload, PSTR("loop"))) { mode = LV_LABEL_LONG_SROLL_CIRC; } else { return Log.warning(F("Invalid long mode")); @@ -202,60 +226,142 @@ static void hasp_attribute_get_part_state(lv_obj_t * obj, const char * attr_in, uint8_t & state) { int len = strlen(attr_in); - if(len > 0 && len < 32) { - // Check Trailing partnumber - if(attr_in[len - 1] == '1') { - part = LV_TABLE_PART_CELL1; - } else if(attr_in[len - 1] == '2') { - part = LV_TABLE_PART_CELL2; - } else if(attr_in[len - 1] == '3') { - part = LV_TABLE_PART_CELL3; - } else if(attr_in[len - 1] == '4') { - part = LV_TABLE_PART_CELL4; - } + if(len <= 0 || len >= 32) { + attr_out[0] = 0; // empty string + part = LV_OBJ_PART_MAIN; + state = LV_STATE_DEFAULT; + return; + } + int index = atoi(&attr_in[len - 1]); - // Remove Trailing part digit - if(part != LV_TABLE_PART_BG && len > 0) { - len--; + // Drop Trailing partnumber + if(attr_in[len - 1] == '0' || index > 0) { + part = LV_TABLE_PART_BG; + len--; + } + strncpy(attr_out, attr_in, len); + attr_out[len] = 0; + + /* Attributes depending on objecttype */ + lv_obj_type_t list; + lv_obj_get_type(obj, &list); + const char * objtype = list.type[0]; + + if(check_obj_type(objtype, LV_HASP_BUTTON)) { + switch(index) { + case 1: + state = LV_BTN_STATE_PRESSED; + break; + case 2: + state = LV_BTN_STATE_DISABLED; + break; + case 3: + state = LV_BTN_STATE_CHECKED_RELEASED; + break; + case 4: + state = LV_BTN_STATE_CHECKED_PRESSED; + break; + case 5: + state = LV_BTN_STATE_CHECKED_DISABLED; + break; + default: + state = LV_BTN_STATE_RELEASED; } - strncpy(attr_out, attr_in, len + 1); - attr_out[len] = 0; - } else { - attr_out[0] = 0; + part = LV_BTN_PART_MAIN; + return; + } + + if(check_obj_type(objtype, LV_HASP_BAR)) { + if(index == 1) { + part = LV_BAR_PART_INDIC; + } else { + part = LV_BAR_PART_BG; + } + state = LV_STATE_DEFAULT; + return; + } + + if(check_obj_type(objtype, LV_HASP_CHECKBOX)) { + if(index == 1) { + part = LV_CHECKBOX_PART_BULLET; + } else { + part = LV_CHECKBOX_PART_BG; + } + state = LV_STATE_DEFAULT; + return; + } + + if(check_obj_type(objtype, LV_HASP_CPICKER)) { + if(index == 1) { + part = LV_CPICKER_PART_KNOB; + } else { + part = LV_CPICKER_PART_MAIN; + } + state = LV_STATE_DEFAULT; + return; } } +/** + * Change or Retrieve the value of a local attribute of an object PART + * @param obj lv_obj_t*: the object to get/set the attribute + * @param attr_p char*: the attribute name (with or without leading ".") + * @param attr_hash uint16_t: the sbdm hash of the attribute name without leading "." + * @param payload char*: the new value of the attribute + * @param update bool: change/set the value if true, dispatch/get value if false + * @note setting a value won't return anything, getting will dispatch the value + */ static void hasp_local_style_attr(lv_obj_t * obj, const char * attr_p, uint16_t attr_hash, const char * payload, bool update) { char attr[32]; - uint8_t part = LV_TABLE_PART_BG; + uint8_t part = LV_OBJ_PART_MAIN; uint8_t state = LV_STATE_DEFAULT; int16_t var = atoi(payload); hasp_attribute_get_part_state(obj, attr_p, attr, part, state); + attr_hash = sdbm(attr); // attribute name without the index number /* ***** WARNING **************************************************** * when using hasp_out use attr_p for the original attribute name * *************************************************************** */ switch(attr_hash) { + +/* 1: Use other blend modes than normal (`LV_BLEND_MODE_...`)*/ +#if LV_USE_BLEND_MODES + case ATTR_BG_BLEND_MODE: + return attribute_bg_blend_mode(obj, part, state, update, attr_p, (lv_blend_mode_t)var); + case ATTR_TEXT_BLEND_MODE: + return lv_obj_set_style_local_text_blend_mode(obj, part, state, (lv_blend_mode_t)var); + case ATTR_BORDER_BLEND_MODE: + return lv_obj_set_style_local_border_blend_mode(obj, part, state, (lv_blend_mode_t)var); + case ATTR_OUTLINE_BLEND_MODE: + return lv_obj_set_style_local_outline_blend_mode(obj, part, state, (lv_blend_mode_t)var); + case ATTR_SHADOW_BLEND_MODE: + return lv_obj_set_style_local_shadow_blend_mode(obj, part, state, (lv_blend_mode_t)var); + case ATTR_LINE_BLEND_MODE: + return lv_obj_set_style_local_line_blend_mode(obj, part, state, (lv_blend_mode_t)var); + case ATTR_VALUE_BLEND_MODE: + return lv_obj_set_style_local_value_blend_mode(obj, part, state, (lv_blend_mode_t)var); + case ATTR_PATTERN_BLEND_MODE: + return lv_obj_set_style_local_pattern_blend_mode(obj, part, state, (lv_blend_mode_t)var); +#endif + + case ATTR_SIZE: + return attribute_size(obj, part, state, update, attr_p, var); case ATTR_RADIUS: return attribute_radius(obj, part, state, update, attr_p, var); case ATTR_CLIP_CORNER: return attribute_clip_corner(obj, part, state, update, attr_p, var); - case ATTR_SIZE: - return attribute_size(obj, part, state, update, attr_p, var); - case ATTR_TRANSFORM_WIDTH: - return lv_obj_set_style_local_transform_width(obj, part, state, (lv_style_int_t)var); - case ATTR_TRANSFORM_HEIGHT: - return lv_obj_set_style_local_transform_height(obj, part, state, (lv_style_int_t)var); case ATTR_OPA_SCALE: - return lv_obj_set_style_local_opa_scale(obj, part, state, (lv_opa_t)var); + return attribute_opa_scale(obj, part, state, update, attr_p, (lv_opa_t)var); + case ATTR_TRANSFORM_WIDTH: + return attribute_transform_width(obj, part, state, update, attr_p, (lv_style_int_t)var); + case ATTR_TRANSFORM_HEIGHT: + return attribute_transform_height(obj, part, state, update, attr_p, (lv_style_int_t)var); - /* Background attributes */ - case ATTR_BG_BLEND_MODE: - return attribute_bg_blend_mode(obj, part, state, update, attr_p, (lv_blend_mode_t)var); + /* Background attributes */ case ATTR_BG_MAIN_STOP: return attribute_bg_main_stop(obj, part, state, update, attr_p, (lv_style_int_t)var); case ATTR_BG_GRAD_STOP: @@ -276,25 +382,25 @@ static void hasp_local_style_attr(lv_obj_t * obj, const char * attr_p, uint16_t /* Padding attributes */ case ATTR_PAD_TOP: - return attribute_pad_top(obj, part, state, update, attr_p, (lv_blend_mode_t)var); + return attribute_pad_top(obj, part, state, update, attr_p, (lv_style_int_t)var); case ATTR_PAD_BOTTOM: return attribute_pad_bottom(obj, part, state, update, attr_p, (lv_style_int_t)var); case ATTR_PAD_LEFT: return attribute_pad_left(obj, part, state, update, attr_p, (lv_style_int_t)var); case ATTR_PAD_RIGHT: - return attribute_pad_right(obj, part, state, update, attr_p, (lv_grad_dir_t)var); + return attribute_pad_right(obj, part, state, update, attr_p, (lv_style_int_t)var); case ATTR_PAD_INNER: - return attribute_pad_inner(obj, part, state, update, attr_p, (lv_opa_t)var); + return attribute_pad_inner(obj, part, state, update, attr_p, (lv_style_int_t)var); /* Text attributes */ case ATTR_TEXT_LETTER_SPACE: - return lv_obj_set_style_local_text_letter_space(obj, part, state, (lv_style_int_t)var); + return attribute_text_letter_space(obj, part, state, update, attr_p, (lv_style_int_t)var); case ATTR_TEXT_LINE_SPACE: - return lv_obj_set_style_local_text_line_space(obj, part, state, (lv_style_int_t)var); + return attribute_text_line_space(obj, part, state, update, attr_p, (lv_style_int_t)var); case ATTR_TEXT_DECOR: - return lv_obj_set_style_local_text_decor(obj, part, state, (lv_text_decor_t)var); - case ATTR_TEXT_BLEND_MODE: - return lv_obj_set_style_local_text_blend_mode(obj, part, state, (lv_blend_mode_t)var); + return attribute_text_decor(obj, part, state, update, attr_p, (lv_text_decor_t)var); + case ATTR_TEXT_OPA: + return attribute_text_opa(obj, part, state, update, attr_p, (lv_opa_t)var); case ATTR_TEXT_COLOR: { lv_color_t color = haspPayloadToColor(payload); return lv_obj_set_style_local_text_color(obj, part, state, color); @@ -303,210 +409,149 @@ static void hasp_local_style_attr(lv_obj_t * obj, const char * attr_p, uint16_t lv_color_t color = haspPayloadToColor(payload); return lv_obj_set_style_local_text_sel_color(obj, part, state, color); } - case ATTR_TEXT_OPA: - return lv_obj_set_style_local_text_opa(obj, part, state, (lv_opa_t)var); + case ATTR_TEXT_FONT: { + lv_font_t * font = haspPayloadToFont(payload); + if(font) { + return lv_obj_set_style_local_text_font(obj, part, state, font); + } else { + return Log.warning(F("HASP: Unknown Font ID %s"), attr_p); + } + } /* Border attributes */ case ATTR_BORDER_WIDTH: - return lv_obj_set_style_local_border_width(obj, part, state, (lv_style_int_t)var); + return attribute_border_width(obj, part, state, update, attr_p, (lv_style_int_t)var); case ATTR_BORDER_SIDE: - return lv_obj_set_style_local_border_side(obj, part, state, (lv_border_side_t)var); - case ATTR_BORDER_BLEND_MODE: - return lv_obj_set_style_local_border_blend_mode(obj, part, state, (lv_blend_mode_t)var); + return attribute_border_side(obj, part, state, update, attr_p, (lv_border_side_t)var); case ATTR_BORDER_POST: - return lv_obj_set_style_local_border_post(obj, part, state, (bool)var); + return attribute_border_post(obj, part, state, update, attr_p, is_true(payload)); + case ATTR_BORDER_OPA: + return attribute_border_opa(obj, part, state, update, attr_p, (lv_opa_t)var); case ATTR_BORDER_COLOR: { lv_color_t color = haspPayloadToColor(payload); return lv_obj_set_style_local_border_color(obj, part, state, color); } - case ATTR_BORDER_OPA: - return lv_obj_set_style_local_border_opa(obj, part, state, (lv_opa_t)var); - - /* Outline attributes */ + /* Outline attributes */ case ATTR_OUTLINE_WIDTH: - return lv_obj_set_style_local_outline_width(obj, part, state, (lv_style_int_t)var); + return attribute_outline_width(obj, part, state, update, attr_p, (lv_style_int_t)var); case ATTR_OUTLINE_PAD: - return lv_obj_set_style_local_outline_pad(obj, part, state, (lv_style_int_t)var); - case ATTR_OUTLINE_BLEND_MODE: - return lv_obj_set_style_local_outline_blend_mode(obj, part, state, (lv_blend_mode_t)var); + return attribute_outline_pad(obj, part, state, update, attr_p, (lv_style_int_t)var); + case ATTR_OUTLINE_OPA: + return attribute_outline_opa(obj, part, state, update, attr_p, (lv_opa_t)var); case ATTR_OUTLINE_COLOR: { lv_color_t color = haspPayloadToColor(payload); return lv_obj_set_style_local_outline_color(obj, part, state, color); } - case ATTR_OUTLINE_OPA: - return lv_obj_set_style_local_outline_opa(obj, part, state, (lv_opa_t)var); /* Shadow attributes */ +#if LV_USE_SHADOW case ATTR_SHADOW_WIDTH: - return lv_obj_set_style_local_shadow_width(obj, part, state, (lv_style_int_t)var); + return attribute_shadow_width(obj, part, state, update, attr_p, (lv_style_int_t)var); case ATTR_SHADOW_OFS_X: - return lv_obj_set_style_local_shadow_ofs_x(obj, part, state, (lv_style_int_t)var); + return attribute_shadow_ofs_x(obj, part, state, update, attr_p, (lv_style_int_t)var); case ATTR_SHADOW_OFS_Y: - return lv_obj_set_style_local_shadow_ofs_y(obj, part, state, (lv_style_int_t)var); + return attribute_shadow_ofs_y(obj, part, state, update, attr_p, (lv_style_int_t)var); case ATTR_SHADOW_SPREAD: - return lv_obj_set_style_local_shadow_spread(obj, part, state, (lv_style_int_t)var); - case ATTR_SHADOW_BLEND_MODE: - return lv_obj_set_style_local_shadow_blend_mode(obj, part, state, (lv_blend_mode_t)var); + return attribute_shadow_spread(obj, part, state, update, attr_p, (lv_style_int_t)var); + case ATTR_SHADOW_OPA: + return attribute_shadow_opa(obj, part, state, update, attr_p, (lv_opa_t)var); case ATTR_SHADOW_COLOR: { lv_color_t color = haspPayloadToColor(payload); return lv_obj_set_style_local_shadow_color(obj, part, state, color); } - case ATTR_SHADOW_OPA: - return lv_obj_set_style_local_shadow_opa(obj, part, state, (lv_opa_t)var); +#endif /* Line attributes */ case ATTR_LINE_WIDTH: - return lv_obj_set_style_local_line_width(obj, part, state, (lv_style_int_t)var); - case ATTR_LINE_BLEND_MODE: - return lv_obj_set_style_local_line_blend_mode(obj, part, state, (lv_blend_mode_t)var); + return attribute_line_width(obj, part, state, update, attr_p, (lv_style_int_t)var); case ATTR_LINE_DASH_WIDTH: - return lv_obj_set_style_local_line_dash_width(obj, part, state, (lv_style_int_t)var); + return attribute_line_dash_width(obj, part, state, update, attr_p, (lv_style_int_t)var); case ATTR_LINE_DASH_GAP: - return lv_obj_set_style_local_line_dash_gap(obj, part, state, (lv_style_int_t)var); + return attribute_line_dash_gap(obj, part, state, update, attr_p, (lv_style_int_t)var); case ATTR_LINE_ROUNDED: - return lv_obj_set_style_local_line_rounded(obj, part, state, (bool)var); + return attribute_line_rounded(obj, part, state, update, attr_p, is_true(payload)); + case ATTR_LINE_OPA: + return attribute_line_opa(obj, part, state, update, attr_p, (lv_opa_t)var); case ATTR_LINE_COLOR: { lv_color_t color = haspPayloadToColor(payload); return lv_obj_set_style_local_line_color(obj, part, state, color); } - case ATTR_LINE_OPA: - return lv_obj_set_style_local_line_opa(obj, part, state, (lv_opa_t)var); /* Value attributes */ case ATTR_VALUE_LETTER_SPACE: - return lv_obj_set_style_local_value_letter_space(obj, part, state, (lv_style_int_t)var); - + return attribute_value_letter_space(obj, part, state, update, attr_p, (lv_style_int_t)var); case ATTR_VALUE_LINE_SPACE: - return lv_obj_set_style_local_value_line_space(obj, part, state, (lv_style_int_t)var); - case ATTR_VALUE_BLEND_MODE: - return lv_obj_set_style_local_value_blend_mode(obj, part, state, (lv_blend_mode_t)var); + return attribute_value_line_space(obj, part, state, update, attr_p, (lv_style_int_t)var); case ATTR_VALUE_OFS_X: - return lv_obj_set_style_local_value_ofs_x(obj, part, state, (lv_style_int_t)var); + return attribute_value_ofs_x(obj, part, state, update, attr_p, (lv_style_int_t)var); case ATTR_VALUE_OFS_Y: - return lv_obj_set_style_local_value_ofs_y(obj, part, state, (lv_style_int_t)var); + return attribute_value_ofs_y(obj, part, state, update, attr_p, (lv_style_int_t)var); case ATTR_VALUE_ALIGN: - return lv_obj_set_style_local_value_align(obj, part, state, (lv_align_t)var); + return attribute_value_align(obj, part, state, update, attr_p, (lv_align_t)var); + case ATTR_VALUE_OPA: + return attribute_value_opa(obj, part, state, update, attr_p, (lv_opa_t)var); + case ATTR_VALUE_STR: { + if(update) { + // Free previous string + const char * str = lv_obj_get_style_value_str(obj, part); + lv_obj_set_style_local_value_str(obj, part, state, NULL); + lv_mem_free(str); + + // Create new string + size_t len = strlen(payload); + if(len > 0) { + len++; + char * str_p = (char *)lv_mem_alloc(len); + memset(str_p, 0, len); + memccpy(str_p, payload, 0, len); + lv_obj_set_style_local_value_str(obj, part, state, str_p); + } + } else { + hasp_out_str(obj, attr, lv_obj_get_style_value_str(obj, part)); + } + return; + } case ATTR_VALUE_COLOR: { lv_color_t color = haspPayloadToColor(payload); return lv_obj_set_style_local_value_color(obj, part, state, color); } - case ATTR_VALUE_OPA: - return lv_obj_set_style_local_value_opa(obj, part, state, (lv_opa_t)var); - case ATTR_VALUE_STR: - return lv_obj_set_style_local_value_str(obj, part, state, (const char *)payload); + case ATTR_VALUE_FONT: { + lv_font_t * font = haspPayloadToFont(payload); + if(font) { + return lv_obj_set_style_local_value_font(obj, part, state, font); + } else { + return Log.warning(F("HASP: Unknown Font ID %s"), attr_p); + } + } /* Pattern attributes */ case ATTR_PATTERN_REPEAT: - return lv_obj_set_style_local_pattern_repeat(obj, part, state, (bool)var); - case ATTR_PATTERN_BLEND_MODE: - return lv_obj_set_style_local_pattern_blend_mode(obj, part, state, (lv_blend_mode_t)var); + return attribute_pattern_repeat(obj, part, state, update, attr_p, is_true(payload)); + case ATTR_PATTERN_OPA: + return attribute_pattern_opa(obj, part, state, update, attr_p, (lv_opa_t)var); + case ATTR_PATTERN_RECOLOR_OPA: + return attribute_pattern_recolor_opa(obj, part, state, update, attr_p, (lv_opa_t)var); + case ATTR_PATTERN_IMAGE: + // return lv_obj_set_style_local_pattern_image(obj, part, state, (constvoid *)var); + break; case ATTR_PATTERN_RECOLOR: { lv_color_t color = haspPayloadToColor(payload); return lv_obj_set_style_local_pattern_recolor(obj, part, state, color); } - case ATTR_PATTERN_OPA: - return lv_obj_set_style_local_pattern_opa(obj, part, state, (lv_opa_t)var); - case ATTR_PATTERN_RECOLOR_OPA: - return lv_obj_set_style_local_pattern_recolor_opa(obj, part, state, (lv_opa_t)var); - case ATTR_PATTERN_IMAGE: - // return lv_obj_set_style_local_pattern_image(obj, part, state, (constvoid *)var); - break; + + /* Image attributes */ + // Todo + + /* Scale attributes */ + // Todo + + /* Transition attributes */ + // Todo } Log.warning(F("HASP: Unknown property %s"), attr_p); } -static void hasp_local_style_attr_font(lv_obj_t * obj, const char * attr_p, uint16_t attr_hash, const char * payload, - bool update) -{ - uint8_t part = LV_TABLE_PART_BG; - uint8_t state = LV_STATE_DEFAULT; - int16_t var = atoi(payload); - - int len = strlen(attr_p); - if(len > 0 && len < 32) { - // Check Trailing partnumber - if(attr_p[len - 1] == '1') { - part = LV_TABLE_PART_CELL1; - } else if(attr_p[len - 1] == '2') { - part = LV_TABLE_PART_CELL2; - } else if(attr_p[len - 1] == '3') { - part = LV_TABLE_PART_CELL3; - } else if(attr_p[len - 1] == '4') { - part = LV_TABLE_PART_CELL4; - // } else if(attr[len - 1] == '9') { - // part = LV_PAGE_PART_SCROLLBAR; - } - - // Remove Trailing part digit - char attr[32]; - if(part != LV_TABLE_PART_BG && len > 0) { - len--; - } - strncpy(attr, attr_p, len + 1); - attr[len] = 0; - - // debugPrintln(strAttr + "&" + part); - - /* ***** WARNING **************************************************** - * when using hasp_out use attr_p for the original attribute name - * *************************************************************** */ - - if(!strcmp_P(attr, PSTR("value_font"))) { -#if ESP32 - switch(var) { - case 8: - lv_obj_set_style_local_value_font(obj, part, state, &unscii_8_icon); - break; - case 12: - lv_obj_set_style_local_value_font(obj, part, state, &lv_font_montserrat_12); - break; - case 16: - lv_obj_set_style_local_value_font(obj, part, state, &lv_font_montserrat_16); - break; - case 22: - lv_obj_set_style_local_value_font(obj, part, state, &lv_font_montserrat_22); - break; - case 28: - lv_obj_set_style_local_value_font(obj, part, state, &lv_font_montserrat_28_compressed); - break; - } - return; -#endif - // return lv_obj_set_style_local_value_font(obj, part, state, (constlv_font_t *)var); - - } else if(!strcmp_P(attr, PSTR("text_font"))) { -#if ESP32 - switch(var) { - case 0: - lv_obj_set_style_local_text_font(obj, part, state, haspFonts[0]); - Log.verbose(F("Changing font to : %s"), (char *)haspFonts[0]->user_data); - break; - case 8: - lv_obj_set_style_local_text_font(obj, part, state, &unscii_8_icon); - break; - case 12: - lv_obj_set_style_local_text_font(obj, part, state, &lv_font_montserrat_12); - break; - case 16: - lv_obj_set_style_local_text_font(obj, part, state, &lv_font_montserrat_16); - break; - case 22: - lv_obj_set_style_local_text_font(obj, part, state, &lv_font_montserrat_22); - break; - case 28: - lv_obj_set_style_local_text_font(obj, part, state, &lv_font_montserrat_28_compressed); - break; - } - return; -#endif - // return lv_obj_set_style_local_text_font(obj, part, state, (constlv_font_t *)var); - } - } - - Log.warning(F("HASP: Unknown property %s"), attr_p); -} - // OK static void hasp_process_obj_attribute_txt(lv_obj_t * obj, const char * attr, const char * payload, bool update) { @@ -640,8 +685,14 @@ static void hasp_process_obj_attribute_range(lv_obj_t * obj, const char * attr, } } -// OK -// @param update bool: change the value if true, dispatch value if false +/** + * Change or Retrieve the value of the attribute of an object + * @param obj lv_obj_t*: the object to get/set the attribute + * @param attr_p char*: the attribute name (with or without leading ".") + * @param payload char*: the new value of the attribute + * @param update bool: change/set the value if true, dispatch/get value if false + * @note setting a value won't return anything, getting will dispatch the value + */ void hasp_process_obj_attribute(lv_obj_t * obj, const char * attr_p, const char * payload, bool update) { unsigned long start = millis(); @@ -789,11 +840,9 @@ void hasp_process_obj_attribute(lv_obj_t * obj, const char * attr_p, const char /* ************************** * Static Inline functions * **************************/ -static inline bool is_true(const char * s) +static bool is_true(const char * s) { - return (!strcmp_P(s, PSTR("true")) || !strcmp_P(s, PSTR("TRUE")) || !strcmp_P(s, PSTR("True")) || - !strcmp_P(s, PSTR("on")) || !strcmp_P(s, PSTR("ON")) || !strcmp_P(s, PSTR("On")) || - !strcmp_P(s, PSTR("yes")) || !strcmp_P(s, PSTR("YES")) || !strcmp_P(s, PSTR("Yes")) || + return (!strcasecmp_P(s, PSTR("true")) || !strcasecmp_P(s, PSTR("on")) || !strcasecmp_P(s, PSTR("yes")) || !strcmp_P(s, PSTR("1"))); } @@ -821,6 +870,13 @@ void inline hasp_out_color(lv_obj_t * obj, const char * attr, lv_color_t color) hasp_send_obj_attribute_color(obj, attr, color); } +/** + * Check if an lvgl object typename corresponds to a given HASP object ID + * @param lvobjtype a char* to a string + * @param haspobjtype the HASP object ID to check against + * @return true or false wether the types match + * @note + */ bool check_obj_type(const char * lvobjtype, lv_hasp_obj_type_t haspobjtype) { lvobjtype += 3; // skip "lv_" @@ -869,6 +925,13 @@ bool check_obj_type(const char * lvobjtype, lv_hasp_obj_type_t haspobjtype) } } +/** + * Check if an lvgl objecttype name corresponds to a given HASP object ID + * @param obj an lv_obj_t* of the object to check its type + * @param haspobjtype the HASP object ID to check against + * @return true or false wether the types match + * @note + */ bool check_obj_type(lv_obj_t * obj, lv_hasp_obj_type_t haspobjtype) { lv_obj_type_t list; diff --git a/src/hasp_attribute.h b/src/hasp_attribute.h index 6171e1e3..911a6f94 100644 --- a/src/hasp_attribute.h +++ b/src/hasp_attribute.h @@ -28,8 +28,8 @@ bool check_obj_type(lv_obj_t * obj, lv_hasp_obj_type_t haspobjtype); if(update) { \ return lv_obj_set_style_local_##func_name(obj, part, state, (value_type)val); \ } else { \ - value_type temp; \ - lv_obj_get_style_local_##func_name(obj, part, state, &temp); \ + value_type temp = lv_obj_get_style_##func_name(obj, part); \ + /*lv_obj_get_style_##func_name(obj, part, state, &temp);*/ \ return hasp_out_int(obj, attr, temp); \ } \ } @@ -45,7 +45,17 @@ _HASP_ATTRIBUTE(PAD_BOTTOM, pad_bottom, lv_style_int_t) _HASP_ATTRIBUTE(PAD_LEFT, pad_left, lv_style_int_t) _HASP_ATTRIBUTE(PAD_RIGHT, pad_right, lv_style_int_t) _HASP_ATTRIBUTE(PAD_INNER, pad_inner, lv_style_int_t) +#if LV_USE_BLEND_MODES _HASP_ATTRIBUTE(BG_BLEND_MODE, bg_blend_mode, lv_blend_mode_t) +_HASP_ATTRIBUTE(BORDER_BLEND_MODE, border_blend_mode, lv_blend_mode_t) +_HASP_ATTRIBUTE(OUTLINE_BLEND_MODE, outline_blend_mode, lv_blend_mode_t) +_HASP_ATTRIBUTE(SHADOW_BLEND_MODE, shadow_blend_mode, lv_blend_mode_t) +_HASP_ATTRIBUTE(PATTERN_BLEND_MODE, pattern_blend_mode, lv_blend_mode_t) +_HASP_ATTRIBUTE(VALUE_BLEND_MODE, value_blend_mode, lv_blend_mode_t) +_HASP_ATTRIBUTE(TEXT_BLEND_MODE, text_blend_mode, lv_blend_mode_t) +_HASP_ATTRIBUTE(LINE_BLEND_MODE, line_blend_mode, lv_blend_mode_t) +_HASP_ATTRIBUTE(IMAGE_BLEND_MODE, image_blend_mode, lv_blend_mode_t) +#endif _HASP_ATTRIBUTE(BG_MAIN_STOP, bg_main_stop, lv_style_int_t) _HASP_ATTRIBUTE(BG_GRAD_STOP, bg_grad_stop, lv_style_int_t) _HASP_ATTRIBUTE(BG_GRAD_DIR, bg_grad_dir, lv_grad_dir_t) @@ -54,31 +64,28 @@ _HASP_ATTRIBUTE(BG_GRAD_DIR, bg_grad_dir, lv_grad_dir_t) _HASP_ATTRIBUTE(BG_OPA, bg_opa, lv_opa_t) _HASP_ATTRIBUTE(BORDER_WIDTH, border_width, lv_style_int_t) _HASP_ATTRIBUTE(BORDER_SIDE, border_side, lv_border_side_t) -_HASP_ATTRIBUTE(BORDER_BLEND_MODE, border_blend_mode, lv_blend_mode_t) _HASP_ATTRIBUTE(BORDER_POST, border_post, bool) //_HASP_ATTRIBUTE(BORDER_COLOR, border_color, lv_color_t, _color, nonscalar) _HASP_ATTRIBUTE(BORDER_OPA, border_opa, lv_opa_t) _HASP_ATTRIBUTE(OUTLINE_WIDTH, outline_width, lv_style_int_t) _HASP_ATTRIBUTE(OUTLINE_PAD, outline_pad, lv_style_int_t) -_HASP_ATTRIBUTE(OUTLINE_BLEND_MODE, outline_blend_mode, lv_blend_mode_t) //_HASP_ATTRIBUTE(OUTLINE_COLOR, outline_color, lv_color_t, _color, nonscalar) _HASP_ATTRIBUTE(OUTLINE_OPA, outline_opa, lv_opa_t) +#if LV_USE_SHADOW _HASP_ATTRIBUTE(SHADOW_WIDTH, shadow_width, lv_style_int_t) _HASP_ATTRIBUTE(SHADOW_OFS_X, shadow_ofs_x, lv_style_int_t) _HASP_ATTRIBUTE(SHADOW_OFS_Y, shadow_ofs_y, lv_style_int_t) _HASP_ATTRIBUTE(SHADOW_SPREAD, shadow_spread, lv_style_int_t) -_HASP_ATTRIBUTE(SHADOW_BLEND_MODE, shadow_blend_mode, lv_blend_mode_t) //_HASP_ATTRIBUTE(SHADOW_COLOR, shadow_color, lv_color_t, _color, nonscalar) _HASP_ATTRIBUTE(SHADOW_OPA, shadow_opa, lv_opa_t) +#endif _HASP_ATTRIBUTE(PATTERN_REPEAT, pattern_repeat, bool) -_HASP_ATTRIBUTE(PATTERN_BLEND_MODE, pattern_blend_mode, lv_blend_mode_t) //_HASP_ATTRIBUTE(PATTERN_RECOLOR, pattern_recolor, lv_color_t, _color, nonscalar) _HASP_ATTRIBUTE(PATTERN_OPA, pattern_opa, lv_opa_t) _HASP_ATTRIBUTE(PATTERN_RECOLOR_OPA, pattern_recolor_opa, lv_opa_t) //_HASP_ATTRIBUTE(PATTERN_IMAGE, pattern_image, const void *, _data_ptr, scalar) _HASP_ATTRIBUTE(VALUE_LETTER_SPACE, value_letter_space, lv_style_int_t) _HASP_ATTRIBUTE(VALUE_LINE_SPACE, value_line_space, lv_style_int_t) -_HASP_ATTRIBUTE(VALUE_BLEND_MODE, value_blend_mode, lv_blend_mode_t) _HASP_ATTRIBUTE(VALUE_OFS_X, value_ofs_x, lv_style_int_t) _HASP_ATTRIBUTE(VALUE_OFS_Y, value_ofs_y, lv_style_int_t) _HASP_ATTRIBUTE(VALUE_ALIGN, value_align, lv_align_t) @@ -89,19 +96,16 @@ _HASP_ATTRIBUTE(VALUE_OPA, value_opa, lv_opa_t) _HASP_ATTRIBUTE(TEXT_LETTER_SPACE, text_letter_space, lv_style_int_t) _HASP_ATTRIBUTE(TEXT_LINE_SPACE, text_line_space, lv_style_int_t) _HASP_ATTRIBUTE(TEXT_DECOR, text_decor, lv_text_decor_t) -_HASP_ATTRIBUTE(TEXT_BLEND_MODE, text_blend_mode, lv_blend_mode_t) //_HASP_ATTRIBUTE(TEXT_COLOR, text_color, lv_color_t, _color, nonscalar) //_HASP_ATTRIBUTE(TEXT_SEL_COLOR, text_sel_color, lv_color_t, _color, nonscalar) _HASP_ATTRIBUTE(TEXT_OPA, text_opa, lv_opa_t) //_HASP_ATTRIBUTE(TEXT_FONT, text_font, const lv_font_t *, _data_ptr, scalar) _HASP_ATTRIBUTE(LINE_WIDTH, line_width, lv_style_int_t) -_HASP_ATTRIBUTE(LINE_BLEND_MODE, line_blend_mode, lv_blend_mode_t) _HASP_ATTRIBUTE(LINE_DASH_WIDTH, line_dash_width, lv_style_int_t) _HASP_ATTRIBUTE(LINE_DASH_GAP, line_dash_gap, lv_style_int_t) _HASP_ATTRIBUTE(LINE_ROUNDED, line_rounded, bool) //_HASP_ATTRIBUTE(LINE_COLOR, line_color, lv_color_t, _color, nonscalar) _HASP_ATTRIBUTE(LINE_OPA, line_opa, lv_opa_t) -_HASP_ATTRIBUTE(IMAGE_BLEND_MODE, image_blend_mode, lv_blend_mode_t) //_HASP_ATTRIBUTE(IMAGE_RECOLOR, image_recolor, lv_color_t, _color, nonscalar) _HASP_ATTRIBUTE(IMAGE_OPA, image_opa, lv_opa_t) _HASP_ATTRIBUTE(IMAGE_RECOLOR_OPA, image_recolor_opa, lv_opa_t) @@ -122,92 +126,116 @@ _HASP_ATTRIBUTE(SCALE_END_LINE_WIDTH, scale_end_line_width, lv_style_int_t) //_HASP_ATTRIBUTE(SCALE_END_COLOR, scale_end_color, lv_color_t, _color, nonscalar) /* attribute hashes */ +/* Object Part Attributes */ #define ATTR_SIZE 16417 -#define ATTR_BG_OPA 48966 #define ATTR_RADIUS 20786 -#define ATTR_PAD_TOP 59081 -#define ATTR_LINE_OPA 24501 -#define ATTR_BG_COLOR 64969 -#define ATTR_PAD_LEFT 43123 -#define ATTR_TEXT_OPA 37166 -#define ATTR_IMAGE_OPA 58140 -#define ATTR_OPA_SCALE 64875 -#define ATTR_PAD_INNER 9930 -#define ATTR_PAD_RIGHT 65104 -#define ATTR_BORDER_OPA 2061 -#define ATTR_VALUE_OPA 50482 -#define ATTR_LINE_WIDTH 25467 -#define ATTR_LINE_COLOR 22200 -#define ATTR_PAD_BOTTOM 3767 -#define ATTR_TEXT_FONT 22465 -#define ATTR_VALUE_STR 1091 -#define ATTR_SHADOW_OPA 38401 -#define ATTR_TEXT_COLOR 23473 -#define ATTR_TEXT_DECOR 1971 -#define ATTR_BORDER_SIDE 53962 -#define ATTR_VALUE_FONT 9405 #define ATTR_CLIP_CORNER 9188 -#define ATTR_PATTERN_OPA 43633 -#define ATTR_OUTLINE_OPA 23011 -#define ATTR_BORDER_POST 49491 -#define ATTR_OUTLINE_PAD 26038 -#define ATTR_SCALE_WIDTH 36017 +#define ATTR_OPA_SCALE 64875 +#define ATTR_TRANSFORM_HEIGHT 55994 +#define ATTR_TRANSFORM_WIDTH 48627 + +/* Background Attributes */ +#define ATTR_BG_OPA 48966 +#define ATTR_BG_COLOR 64969 #define ATTR_BG_GRAD_DIR 41782 -#define ATTR_VALUE_ALIGN 27895 -#define ATTR_VALUE_COLOR 52661 #define ATTR_BG_GRAD_STOP 4025 -#define ATTR_VALUE_OFS_X 21415 -#define ATTR_VALUE_OFS_Y 21416 #define ATTR_BG_MAIN_STOP 63118 -#define ATTR_BORDER_WIDTH 24531 -#define ATTR_LINE_ROUNDED 15042 -#define ATTR_BORDER_COLOR 21264 #define ATTR_BG_BLEND_MODE 31147 #define ATTR_BG_GRAD_COLOR 44140 -#define ATTR_SHADOW_WIDTH 13255 -#define ATTR_IMAGE_RECOLOR 52204 -#define ATTR_SHADOW_COLOR 9988 -#define ATTR_LINE_DASH_GAP 49332 -#define ATTR_OUTLINE_WIDTH 9897 -#define ATTR_SHADOW_OFS_X 44278 -#define ATTR_SHADOW_OFS_Y 44279 -#define ATTR_PATTERN_IMAGE 61292 -#define ATTR_SHADOW_SPREAD 21138 -#define ATTR_OUTLINE_COLOR 6630 + +/* Padding Attributes */ +#define ATTR_PAD_TOP 59081 +#define ATTR_PAD_LEFT 43123 +#define ATTR_PAD_INNER 9930 +#define ATTR_PAD_RIGHT 65104 +#define ATTR_PAD_BOTTOM 3767 + +/* Text Attributes */ +#define ATTR_TEXT_OPA 37166 +#define ATTR_TEXT_FONT 22465 +#define ATTR_TEXT_COLOR 23473 +#define ATTR_TEXT_DECOR 1971 +#define ATTR_TEXT_LETTER_SPACE 62079 #define ATTR_TEXT_SEL_COLOR 32076 -#define ATTR_LINE_DASH_WIDTH 32676 -#define ATTR_PATTERN_REPEAT 31338 -#define ATTR_LINE_BLEND_MODE 60284 #define ATTR_TEXT_LINE_SPACE 54829 #define ATTR_TEXT_BLEND_MODE 32195 + +/* Border Attributes */ +#define ATTR_BORDER_OPA 2061 +#define ATTR_BORDER_SIDE 53962 +#define ATTR_BORDER_POST 49491 +#define ATTR_BORDER_BLEND_MODE 23844 +#define ATTR_BORDER_WIDTH 24531 +#define ATTR_BORDER_COLOR 21264 + +/* Outline Attributes */ +#define ATTR_OUTLINE_OPA 23011 +#define ATTR_OUTLINE_PAD 26038 +#define ATTR_OUTLINE_COLOR 6630 +#define ATTR_OUTLINE_BLEND_MODE 25038 +#define ATTR_OUTLINE_WIDTH 9897 + +/* Shadow Attributes */ +#define ATTR_SHADOW_OPA 38401 +#define ATTR_SHADOW_WIDTH 13255 +#define ATTR_SHADOW_OFS_X 44278 +#define ATTR_SHADOW_OFS_Y 44279 +#define ATTR_SHADOW_SPREAD 21138 +#define ATTR_SHADOW_BLEND_MODE 64048 +#define ATTR_SHADOW_COLOR 9988 + +/* Line Attributes */ +#define ATTR_LINE_OPA 24501 +#define ATTR_LINE_WIDTH 25467 +#define ATTR_LINE_COLOR 22200 +#define ATTR_LINE_DASH_WIDTH 32676 +#define ATTR_LINE_ROUNDED 15042 +#define ATTR_LINE_DASH_GAP 49332 +#define ATTR_LINE_BLEND_MODE 60284 + +/* Value Attributes */ +#define ATTR_VALUE_OPA 50482 +#define ATTR_VALUE_STR 1091 +#define ATTR_VALUE_FONT 9405 +#define ATTR_VALUE_ALIGN 27895 +#define ATTR_VALUE_COLOR 52661 +#define ATTR_VALUE_OFS_X 21415 +#define ATTR_VALUE_OFS_Y 21416 +#define ATTR_VALUE_LINE_SPACE 26921 +#define ATTR_VALUE_BLEND_MODE 4287 +#define ATTR_VALUE_LETTER_SPACE 51067 + +/* Pattern attributes */ +#define ATTR_PATTERN_BLEND_MODE 43456 +#define ATTR_PATTERN_RECOLOR_OPA 35074 +#define ATTR_PATTERN_RECOLOR 7745 +#define ATTR_PATTERN_REPEAT 31338 +#define ATTR_PATTERN_OPA 43633 +#define ATTR_PATTERN_IMAGE 61292 + #define ATTR_TRANSITION_PROP_1 49343 #define ATTR_TRANSITION_PROP_2 49344 -#define ATTR_SCALE_END_COLOR 44074 #define ATTR_TRANSITION_PROP_3 49345 -#define ATTR_TRANSFORM_WIDTH 48627 #define ATTR_TRANSITION_PROP_4 49346 #define ATTR_TRANSITION_PROP_5 49347 #define ATTR_TRANSITION_PROP_6 49348 #define ATTR_TRANSITION_TIME 26263 -#define ATTR_PATTERN_RECOLOR 7745 #define ATTR_TRANSITION_PATH 43343 -#define ATTR_IMAGE_BLEND_MODE 11349 -#define ATTR_VALUE_LINE_SPACE 26921 -#define ATTR_BORDER_BLEND_MODE 23844 -#define ATTR_VALUE_BLEND_MODE 4287 -#define ATTR_IMAGE_RECOLOR_OPA 43949 #define ATTR_TRANSITION_DELAY 64537 -#define ATTR_SCALE_GRAD_COLOR 47239 -#define ATTR_SHADOW_BLEND_MODE 64048 -#define ATTR_TRANSFORM_HEIGHT 55994 -#define ATTR_TEXT_LETTER_SPACE 62079 -#define ATTR_OUTLINE_BLEND_MODE 25038 -#define ATTR_PATTERN_BLEND_MODE 43456 -#define ATTR_SCALE_BORDER_WIDTH 2440 -#define ATTR_VALUE_LETTER_SPACE 51067 -#define ATTR_PATTERN_RECOLOR_OPA 35074 + +#define ATTR_IMAGE_OPA 58140 +#define ATTR_IMAGE_RECOLOR 52204 +#define ATTR_IMAGE_BLEND_MODE 11349 +#define ATTR_IMAGE_RECOLOR_OPA 43949 + #define ATTR_SCALE_END_LINE_WIDTH 30324 #define ATTR_SCALE_END_BORDER_WIDTH 34380 +#define ATTR_SCALE_BORDER_WIDTH 2440 +#define ATTR_SCALE_GRAD_COLOR 47239 +#define ATTR_SCALE_WIDTH 36017 +#define ATTR_SCALE_END_COLOR 44074 + +/* Object Attributes */ #define ATTR_X 120 #define ATTR_Y 121 #define ATTR_W 119 diff --git a/src/hasp_debug.cpp b/src/hasp_debug.cpp index 38033453..98ae27e7 100644 --- a/src/hasp_debug.cpp +++ b/src/hasp_debug.cpp @@ -71,7 +71,7 @@ Syslog * syslog; #endif // USE_SYSLOG // Serial Settings -uint8_t serialInputIndex = 0; // Empty buffer +uint8_t serialInputIndex = 0; // Empty buffer char serialInputBuffer[1024]; uint16_t debugSerialBaud = SERIAL_SPEED / 10; // Multiplied by 10 bool debugSerialStarted = false; @@ -97,7 +97,8 @@ String debugHaspHeader() String header((char *)0); header.reserve(256); if(debugAnsiCodes) header += TERM_COLOR_YELLOW; - header += F(" _____ _____ _____ _____\r\n" + header += F("\r\n" + " _____ _____ _____ _____\r\n" " | | | _ | __| _ |\r\n" " | | |__ | __|\r\n" " |__|__|__|__|_____|__|\r\n" @@ -381,7 +382,7 @@ void debugLvgl(lv_log_level_t level, const char * file, uint32_t line, const cha void debugLoop() { - while(Serial.available()) { + while(Serial.available()) { char ch = Serial.read(); Serial.print(ch); if(ch == 13 || ch == 10) { diff --git a/src/hasp_dispatch.cpp b/src/hasp_dispatch.cpp index ab227e64..17e1ab12 100644 --- a/src/hasp_dispatch.cpp +++ b/src/hasp_dispatch.cpp @@ -19,7 +19,7 @@ inline void dispatchPrintln(String header, String & data) bool isON(const char * payload) { - return strcmp_P(payload, PSTR("ON")) == 0; + return strcasecmp_P(payload, PSTR("ON")) == 0; } String getOnOff(bool state) @@ -362,21 +362,21 @@ void dispatchConfig(const char * topic, const char * payload) update = true; } - if(strcmp_P(topic, PSTR("debug")) == 0) { + if(strcasecmp_P(topic, PSTR("debug")) == 0) { if(update) debugSetConfig(settings); else debugGetConfig(settings); } - else if(strcmp_P(topic, PSTR("gui")) == 0) { + else if(strcasecmp_P(topic, PSTR("gui")) == 0) { if(update) guiSetConfig(settings); else guiGetConfig(settings); } - else if(strcmp_P(topic, PSTR("hasp")) == 0) { + else if(strcasecmp_P(topic, PSTR("hasp")) == 0) { if(update) haspSetConfig(settings); else @@ -384,14 +384,14 @@ void dispatchConfig(const char * topic, const char * payload) } #if HASP_USE_WIFI > 0 - else if(strcmp_P(topic, PSTR("wifi")) == 0) { + else if(strcasecmp_P(topic, PSTR("wifi")) == 0) { if(update) wifiSetConfig(settings); else wifiGetConfig(settings); } #if HASP_USE_MQTT > 0 - else if(strcmp_P(topic, PSTR("mqtt")) == 0) { + else if(strcasecmp_P(topic, PSTR("mqtt")) == 0) { if(update) mqttSetConfig(settings); else @@ -399,11 +399,11 @@ void dispatchConfig(const char * topic, const char * payload) } #endif #if HASP_USE_TELNET > 0 - // else if(strcmp_P(topic, PSTR("telnet")) == 0) + // else if(strcasecmp_P(topic, PSTR("telnet")) == 0) // telnetGetConfig(settings[F("telnet")]); #endif #if HASP_USE_MDNS > 0 - else if(strcmp_P(topic, PSTR("mdns")) == 0) { + else if(strcasecmp_P(topic, PSTR("mdns")) == 0) { if(update) mdnsSetConfig(settings); else @@ -411,7 +411,7 @@ void dispatchConfig(const char * topic, const char * payload) } #endif #if HASP_USE_HTTP > 0 - else if(strcmp_P(topic, PSTR("http")) == 0) { + else if(strcasecmp_P(topic, PSTR("http")) == 0) { if(update) httpSetConfig(settings); else diff --git a/src/hasp_http.cpp b/src/hasp_http.cpp index 3cb7e0fc..edb856f4 100644 --- a/src/hasp_http.cpp +++ b/src/hasp_http.cpp @@ -1286,10 +1286,11 @@ void webHandleHaspConfig() httpMessage += getOption(3, F("Mono"), themeid == 3); #endif #if LV_USE_THEME_MATERIAL == 1 - httpMessage += getOption(4, F("Material"), themeid == 4); + httpMessage += getOption(4, F("Material Light"), themeid == 4); + httpMessage += getOption(9, F("Material Dark"), themeid == 9); #endif #if LV_USE_THEME_ZEN == 1 - httpMessage += getOption(5, F("Zen"), themeid == 5); + // httpMessage += getOption(5, F("Zen"), themeid == 5); #endif #if LV_USE_THEME_NEMO == 1 httpMessage += getOption(6, F("Nemo"), themeid == 6); diff --git a/src/hasp_mqtt.cpp b/src/hasp_mqtt.cpp index 4bb7ef38..d05cc989 100644 --- a/src/hasp_mqtt.cpp +++ b/src/hasp_mqtt.cpp @@ -303,7 +303,7 @@ static void mqtt_message_cb(char * topic_p, byte * payload, unsigned int length) } // catch a dangling LWT from a previous connection if it appears - if(!strcmp_P(topic, PSTR("status")) && !strcmp_P((char *)payload, PSTR("OFF"))) { + if(!strcmp_P(topic, PSTR("status")) && !strcasecmp_P((char *)payload, PSTR("OFF"))) { char topicBuffer[128]; snprintf_P(topicBuffer, sizeof(topicBuffer), PSTR("%sstatus"), mqttNodeTopic); mqttClient.publish(topicBuffer, "ON", true); diff --git a/src/hasp_telnet.cpp b/src/hasp_telnet.cpp index e6595dba..365d8eeb 100644 --- a/src/hasp_telnet.cpp +++ b/src/hasp_telnet.cpp @@ -146,7 +146,7 @@ static void telnetProcessLine() } default: if(telnetInputIndex > 0) { - if(strcmp_P(telnetInputBuffer, PSTR("exit")) == 0) { + if(strcasecmp_P(telnetInputBuffer, PSTR("exit")) == 0) { telnetClientDisconnect(); } else { dispatchCommand(telnetInputBuffer); diff --git a/user_setups/esp32/d1-mini-esp32_ili9341.ini b/user_setups/esp32/d1-mini-esp32_ili9341.ini index bae61bc9..f05e45a8 100644 --- a/user_setups/esp32/d1-mini-esp32_ili9341.ini +++ b/user_setups/esp32/d1-mini-esp32_ili9341.ini @@ -8,9 +8,9 @@ [env:d1mini32-lolintft24] platform = espressif32@^1.12.0 board = wemos_d1_mini32 -upload_port = COM5 ; To change the port, use platform_override.ini -monitor_port = COM5 ; To change the port, use platform_override.ini -board_build.partitions = default.csv +upload_port = COM6 ; To change the port, use platform_override.ini +monitor_port = COM6 ; To change the port, use platform_override.ini +board_build.partitions = esp32_partition_app1300k_spiffs1216k.csv ; default.csv build_flags = ${flags.esp32_flags} ; -- TFT_eSPI build options ------------------------ From c1e497c3ad4949c284729abd3f2929a806998ffb Mon Sep 17 00:00:00 2001 From: fvanroie Date: Mon, 19 Oct 2020 22:10:35 +0200 Subject: [PATCH 03/33] Update to 0.2.0 --- include/hasp_conf.h | 6 +- platformio.ini | 4 +- src/hasp.cpp | 4 +- src/hasp_debug.cpp | 5 ++ src/hasp_dispatch.cpp | 3 +- src/hasp_http.cpp | 6 ++ src/hasp_oobe.cpp | 35 +++++++-- src/hasp_oobe.h | 3 +- src/main.cpp | 39 +++++----- test/connect.robot | 28 +++++++ test/hasp-lvgl.robot | 165 ++++++++++++++++++++++++++++++++++++++++++ test/keywords.robot | 91 +++++++++++++++++++++++ 12 files changed, 356 insertions(+), 33 deletions(-) create mode 100644 test/connect.robot create mode 100644 test/hasp-lvgl.robot create mode 100644 test/keywords.robot diff --git a/include/hasp_conf.h b/include/hasp_conf.h index 32eba200..1532c1f5 100644 --- a/include/hasp_conf.h +++ b/include/hasp_conf.h @@ -2,8 +2,8 @@ #define HASP_CONF_H #define HASP_VERSION_MAJOR 0 -#define HASP_VERSION_MINOR 1 -#define HASP_VERSION_REVISION 0 +#define HASP_VERSION_MINOR 2 +#define HASP_VERSION_REVISION 1014 #define HASP_USE_APP 1 @@ -35,7 +35,7 @@ #endif #ifndef HASP_USE_SYSLOG -#define HASP_USE_SYSLOG 0 +#define HASP_USE_SYSLOG 1 #endif #ifndef HASP_USE_TELNET diff --git a/platformio.ini b/platformio.ini index 51a553a0..45fe4f22 100644 --- a/platformio.ini +++ b/platformio.ini @@ -157,8 +157,8 @@ build_flags = [env:d1mini-lolintft24] platform = espressif8266@^2.4.0 ;@2.3.2 board = d1_mini -upload_port = COM7 ; To change the port, use platform_override.ini -monitor_port = COM7 ; To change the port, use platform_override.ini +;upload_port = To change the port, use platform_override.ini +;monitor_port = To change the port, use platform_override.ini board_build.f_flash = 40000000L board_build.flash_mode = dout board_build.ldscript = eagle.flash.4m2m.ld ; 2Mb Spiffs diff --git a/src/hasp.cpp b/src/hasp.cpp index 8e8fef7e..45d29b80 100644 --- a/src/hasp.cpp +++ b/src/hasp.cpp @@ -682,8 +682,8 @@ void haspClearPage(uint16_t pageid) lv_obj_t * page = get_page(pageid); if(!page) { Log.warning(F("HASP: Page ID %u not defined"), pageid); - } else if(page == lv_layer_sys() || page == lv_layer_top()) { - Log.warning(F("HASP: Cannot clear a layer")); + } else if(page == lv_layer_sys() /*|| page == lv_layer_top()*/) { + Log.warning(F("HASP: Cannot clear system layer")); } else { Log.notice(F("HASP: Clearing page %u"), pageid); lv_obj_clean(pages[pageid]); diff --git a/src/hasp_debug.cpp b/src/hasp_debug.cpp index 98ae27e7..ff5f291e 100644 --- a/src/hasp_debug.cpp +++ b/src/hasp_debug.cpp @@ -19,6 +19,7 @@ #include "hasp_mqtt.h" #endif +#include "hasp_conf.h" #include "hasp_debug.h" #include "hasp_config.h" #include "hasp_dispatch.h" @@ -37,6 +38,7 @@ #if HASP_USE_SYSLOG > 0 #include "Syslog.h" +#include #ifndef SYSLOG_SERVER #define SYSLOG_SERVER "" @@ -280,6 +282,9 @@ static void debugPrintLvglMemory(int level, Print * _logOutput) static void debugPrintPriority(int level, Print * _logOutput) { + if(_logOutput == &syslogClient) { + } + switch(level) { case LOG_LEVEL_FATAL: case LOG_LEVEL_ERROR: diff --git a/src/hasp_dispatch.cpp b/src/hasp_dispatch.cpp index 17e1ab12..9f5c0f69 100644 --- a/src/hasp_dispatch.cpp +++ b/src/hasp_dispatch.cpp @@ -7,6 +7,7 @@ #include "hasp_config.h" #include "hasp_debug.h" #include "hasp_gui.h" +#include "hasp_oobe.h" #include "hasp_hal.h" #include "hasp.h" @@ -119,7 +120,7 @@ void dispatchAttribute(String strTopic, const char * payload) dispatchWebUpdate(payload); } else if(strTopic == F("setupap")) { - // haspDisplayAP(String(F("HASP-ABC123")).c_str(), String(F("haspadmin")).c_str()); + oobeFakeSetup(); } else if(strTopic.length() == 7 && strTopic.startsWith(F("output"))) { dispatchOutput(strTopic, payload); diff --git a/src/hasp_http.cpp b/src/hasp_http.cpp index edb856f4..0a218e91 100644 --- a/src/hasp_http.cpp +++ b/src/hasp_http.cpp @@ -375,10 +375,14 @@ void webHandleAbout() F("

ArduinoLog

Copyright© 2017,2018 Thijs Elenbaas, MrRobot62, rahuldeo2047, NOX73, " "dhylands, Josha blemasle, mfalkvidd"); httpMessage += FPSTR(MIT_LICENSE); +#if HASP_USE_SYSLOG > 0 httpMessage += F("

Syslog

Copyright© 2016 Martin Sloup"); httpMessage += FPSTR(MIT_LICENSE); +#endif +#if HASP_USE_QRCODE > 0 httpMessage += F("

QR Code generator

Copyright© Project Nayuki"); httpMessage += FPSTR(MIT_LICENSE); +#endif httpMessage += F("

AceButton

Copyright© 2018 Brian T. Park"); httpMessage += FPSTR(MIT_LICENSE); @@ -1220,6 +1224,7 @@ void webHandleDebugConfig() httpMessage += settings[FPSTR(F_DEBUG_TELEPERIOD)].as(); httpMessage += F("'>

"); +#if HASP_USE_SYSLOG > 0 httpMessage += F("Syslog Hostame (optional)() == 1) httpMessage += F(" checked"); httpMessage += F(">BSD (RFC 3164)"); +#endif httpMessage += F("

"); diff --git a/src/hasp_oobe.cpp b/src/hasp_oobe.cpp index e63d27fe..6c633ffe 100644 --- a/src/hasp_oobe.cpp +++ b/src/hasp_oobe.cpp @@ -33,6 +33,7 @@ void oobeSetAutoCalibrate(bool cal) static inline void oobeSetPage(uint8_t pageid) { lv_scr_load(oobepage[pageid]); + lv_obj_invalidate(lv_disp_get_layer_sys(NULL)); } void gotoPage1_cb(lv_obj_t * event_kb, lv_event_t event) @@ -293,27 +294,51 @@ static void oobe_calibrate_cb(lv_obj_t * ta, lv_event_t event) } } -void oobeSetup() +bool oobeSetup() { +#if HASP_USE_WIFI > 0 char ssid[32]; char pass[32]; -#if HASP_USE_WIFI>0 if(wifiShowAP(ssid, pass)) { guiSetDim(100); oobeSetupQR(ssid, pass); oobeSetupSsid(); - oobeSetPage(0); - lv_obj_set_click(lv_disp_get_layer_sys(NULL), true); - lv_obj_set_event_cb(lv_disp_get_layer_sys(NULL), gotoPage1_cb); if(oobeAutoCalibrate) { lv_obj_set_click(lv_disp_get_layer_sys(NULL), true); lv_obj_set_event_cb(lv_disp_get_layer_sys(NULL), oobe_calibrate_cb); Log.verbose(F("OOBE: Enabled Auto Calibrate on touch")); } else { + lv_obj_set_click(lv_disp_get_layer_sys(NULL), false); + lv_obj_set_event_cb(lv_disp_get_layer_sys(NULL), gotoPage1_cb); Log.verbose(F("OOBE: Already calibrated")); } + oobeSetPage(0); + return true; + } else { + return false; } #endif +} + +void oobeFakeSetup() +{ + char ssid[32] = "HASP-ABCDEF"; + char pass[32] = "haspadmin"; + + guiSetDim(100); + oobeSetupQR(ssid, pass); + oobeSetupSsid(); + oobeSetPage(0); + lv_obj_set_click(lv_disp_get_layer_sys(NULL), true); + lv_obj_set_event_cb(lv_disp_get_layer_sys(NULL), gotoPage1_cb); + + if(oobeAutoCalibrate) { + lv_obj_set_click(lv_disp_get_layer_sys(NULL), true); + lv_obj_set_event_cb(lv_disp_get_layer_sys(NULL), oobe_calibrate_cb); + Log.verbose(F("OOBE: Enabled Auto Calibrate on touch")); + } else { + Log.verbose(F("OOBE: Already calibrated")); + } } \ No newline at end of file diff --git a/src/hasp_oobe.h b/src/hasp_oobe.h index a602358e..ed675a95 100644 --- a/src/hasp_oobe.h +++ b/src/hasp_oobe.h @@ -1,2 +1,3 @@ void oobeSetAutoCalibrate(bool cal); -void oobeSetup(); \ No newline at end of file +bool oobeSetup(); +void oobeFakeSetup(); \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index e03e3c21..7feb8331 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -21,15 +21,15 @@ void setup() ***************************/ /* Init Storage */ -#if HASP_USE_EEPROM>0 +#if HASP_USE_EEPROM > 0 eepromSetup(); // Don't start at boot, only at write #endif -#if HASP_USE_SPIFFS>0 +#if HASP_USE_SPIFFS > 0 spiffsSetup(); #endif -#if HASP_USE_SDCARD>0 +#if HASP_USE_SDCARD > 0 sdcardSetup(); #endif @@ -43,23 +43,24 @@ void setup() ***************************/ debugSetup(); -#if HASP_USE_GPIO>0 +#if HASP_USE_GPIO > 0 gpioSetup(); #endif -#if HASP_USE_WIFI>0 +#if HASP_USE_WIFI > 0 wifiSetup(); #endif guiSetup(); - oobeSetup(); - haspSetup(); + if(!oobeSetup()) { + haspSetup(); + } -#if HASP_USE_MDNS>0 +#if HASP_USE_MDNS > 0 mdnsSetup(); #endif -#if HASP_USE_OTA>0 +#if HASP_USE_OTA > 0 otaSetup(); #endif @@ -67,11 +68,11 @@ void setup() ethernetSetup(); #endif -#if HASP_USE_MQTT>0 +#if HASP_USE_MQTT > 0 mqttSetup(); #endif -#if HASP_USE_HTTP>0 +#if HASP_USE_HTTP > 0 httpSetup(); #endif @@ -79,7 +80,7 @@ void setup() telnetSetup(); #endif -#if HASP_USE_TASMOTA_SLAVE>0 +#if HASP_USE_TASMOTA_SLAVE > 0 slaveSetup(); #endif @@ -112,7 +113,7 @@ void loop() // haspLoop(); debugLoop(); -#if HASP_USE_GPIO>0 +#if HASP_USE_GPIO > 0 gpioLoop(); #endif @@ -121,19 +122,19 @@ void loop() ethernetLoop(); #endif -#if HASP_USE_MQTT>0 +#if HASP_USE_MQTT > 0 mqttLoop(); #endif // MQTT -#if HASP_USE_HTTP>0 +#if HASP_USE_HTTP > 0 httpLoop(); #endif // HTTP -#if HASP_USE_MDNS>0 +#if HASP_USE_MDNS > 0 mdnsLoop(); #endif // MDNS -#if HASP_USE_OTA>0 +#if HASP_USE_OTA > 0 otaLoop(); #endif // OTA @@ -141,7 +142,7 @@ void loop() telnetLoop(); #endif // TELNET -#if HASP_USE_TASMOTA_SLAVE>0 +#if HASP_USE_TASMOTA_SLAVE > 0 slaveLoop(); #endif // TASMOTASLAVE @@ -150,7 +151,7 @@ void loop() /* Timer Loop */ if(millis() - mainLastLoopTime >= 1000) { /* Run Every Second */ -#if HASP_USE_OTA>0 +#if HASP_USE_OTA > 0 otaEverySecond(); #endif debugEverySecond(); diff --git a/test/connect.robot b/test/connect.robot new file mode 100644 index 00000000..e1db3eac --- /dev/null +++ b/test/connect.robot @@ -0,0 +1,28 @@ +*** Settings *** +| Library | String +| Library | MQTTLibrary +| Test Timeout | 30 seconds + + +*** Variables *** +| ${broker.uri} | 10.4.0.5 +| ${broker.port} | 1883 +| ${client.id} | test.client + + +| *Test Cases* +| Connect to a broker with default port and client id +| | ${mqttc} | Connect | ${broker.uri} +| | ${client_id} = | Decode Bytes To String | ${mqttc._client_id} | UTF-8 +| | Should Be Empty | ${client_id} | +| | [Teardown] | Disconnect + +| Connect to a broker with default port and specified client id +| | ${mqttc} | Connect | ${broker.uri} | client_id=${client.id} +| | Should be equal as strings | ${mqttc._client_id} | ${client.id} +| | [Teardown] | Disconnect + +| Connect to a broker with specified port and client id +| | ${mqttc} | Connect | ${broker.uri} | ${broker.port} | ${client.id} +| | Should be equal as strings | ${mqttc._client_id} | ${client.id} +| | [Teardown] | Disconnect \ No newline at end of file diff --git a/test/hasp-lvgl.robot b/test/hasp-lvgl.robot new file mode 100644 index 00000000..143e7e59 --- /dev/null +++ b/test/hasp-lvgl.robot @@ -0,0 +1,165 @@ +| *Settings* | *Value* +| Resource | keywords.robot +| Test Timeout | 240 seconds + +| *Keywords* +| Test Property +| | [Arguments] | ${broker.uri}=${broker.uri} | ${port}=${broker.port} +| | ... | ${client.id}=${client.id} | ${clean_session}=${true} +| | ... | ${property}=${property} | ${data}=${data} +| | ${time} | Get Time | epoch +| | ${client} | Catenate | SEPARATOR=. | robot.mqtt | ${time} +| | ${topic} | Set Variable | hasp/plate35/command +| | ${restopic} | Set Variable | hasp/plate35/state/json +| | ${qos} | Set Variable | 1 +| | ${message} | Set Variable | ${property}=${data} +| | ${result} | Set Variable | {"${property}":"${data}"} +| | Sleep | .01s +| | Subscribe Async | client.id=${client} | topic=${restopic} +| | Connect | ${broker.uri} | ${port} | ${client.id} | ${clean_session} +| | Publish | ${topic} | ${message} | 1 +| | Publish | ${topic} | ${property} | 1 +| | log to console | ${result} +| | @{messages} | Listen and Get Messages | topic=${restopic} | limit=1 | timeout=1.5 +| | LOG | ${messages} +| | Length Should Be | ${messages} | 1 +| | Should Be Equal As Strings | ${messages}[0] | ${result} + +| Test Page +| | [Arguments] | ${broker.uri}=${broker.uri} | ${port}=${broker.port} +| | ... | ${client.id}=${client.id} | ${clean_session}=${true} +| | ... | ${property}=${property} | ${data}=${data} +| | ${time} | Get Time | epoch +| | ${client} | Catenate | SEPARATOR=. | robot.mqtt | ${time} +| | ${topic} | Set Variable | hasp/plate35/command +| | ${restopic} | Set Variable | hasp/plate35/state/page +| | ${qos} | Set Variable | 1 +| | ${message} | Set Variable | ${property}=${data} +| | Subscribe Async | client.id=${client} | topic=${restopic} +| | Connect | ${broker.uri} | ${port} | ${client.id} | ${clean_session} +| | Publish | ${topic} | ${message} | 1 +| | Publish | ${topic} | ${property} | 1 +| | @{messages} | Listen and Get Messages | topic=${restopic} | limit=1 | timeout=1 +| | LOG | ${messages} +| | Length Should Be | ${messages} | 1 +| | Should Be Equal As Strings | ${messages}[0] | ${data} + + +| *Test Cases* + +| Test Color Picker\n +| | ${obj} | Set Variable | p[1].b[4] +| | Test Page | property=page | data=1 +#| | Test Property | property=${obj}.txt | data=ABC +#| | Test Property | property=${obj}.txt | data=1234 +| | Test Property | property=${obj}.x | data=50 +| | Test Property | property=${obj}.x | data=60 +| | Test Property | property=${obj}.y | data=70 +| | Test Property | property=${obj}.y | data=80 +| | Test Property | property=${obj}.w | data=80 +| | Test Property | property=${obj}.w | data=100 +| | Test Property | property=${obj}.h | data=80 +| | Test Property | property=${obj}.h | data=100 +| | Test Property | property=${obj}.hidden | data=1 +| | Test Property | property=${obj}.hidden | data=0 +| | Test Property | property=${obj}.vis | data=0 +| | Test Property | property=${obj}.vis | data=1 +| | Test Property | property=${obj}.enabled | data=0 +| | Test Property | property=${obj}.enabled | data=1 +| | Test Property | property=${obj}.opacity | data=0 +| | Test Property | property=${obj}.opacity | data=64 +| | Test Property | property=${obj}.opacity | data=192 +| | Test Property | property=${obj}.opacity | data=255 +#| | Test Property | property=${obj}.rect | data=1 +#| | Test Property | property=${obj}.rect | data=0 +| | Test Property | property=${obj}.val | data=50 +| | Test Property | property=${obj}.val | data=60 +| | Test Property | property=${obj}.val | data=70 +| | Test Property | property=${obj}.val | data=80 + +| Test Text Field\n +| | ${obj} | Set Variable | p[1].b[1] +| | Test Page | property=page | data=1 +| | Test Property | property=${obj}.txt | data=ABC +| | Test Property | property=${obj}.txt | data=123 +| | Test Property | property=${obj}.x | data=20 +| | Test Property | property=${obj}.x | data=10 +| | Test Property | property=${obj}.y | data=20 +| | Test Property | property=${obj}.y | data=10 +#| | Test Property | property=${obj}.w | data=80 +#| | Test Property | property=${obj}.w | data=75 +#| | Test Property | property=${obj}.h | data=36 +#| | Test Property | property=${obj}.h | data=18 +| | Test Property | property=${obj}.hidden | data=1 +| | Test Property | property=${obj}.hidden | data=0 +| | Test Property | property=${obj}.vis | data=0 +| | Test Property | property=${obj}.vis | data=1 +| | Test Property | property=${obj}.enabled | data=0 +| | Test Property | property=${obj}.enabled | data=1 +| | Test Property | property=${obj}.opacity | data=0 +| | Test Property | property=${obj}.opacity | data=64 +| | Test Property | property=${obj}.opacity | data=192 +| | Test Property | property=${obj}.opacity | data=255 + + +| Test Button\n +| | ${obj} | Set Variable | p[0].b[1] +| | Test Page | property=page | data=0 +#| | Test Property | property=${obj}.txt | data=ABC +#| | Test Property | property=${obj}.txt | data=1234 +| | Test Property | property=${obj}.x | data=20 +| | Test Property | property=${obj}.x | data=10 +| | Test Property | property=${obj}.y | data=20 +| | Test Property | property=${obj}.y | data=10 +| | Test Property | property=${obj}.w | data=80 +| | Test Property | property=${obj}.w | data=75 +| | Test Property | property=${obj}.h | data=36 +| | Test Property | property=${obj}.h | data=18 +| | Test Property | property=${obj}.hidden | data=1 +| | Test Property | property=${obj}.hidden | data=0 +| | Test Property | property=${obj}.vis | data=0 +| | Test Property | property=${obj}.vis | data=1 +| | Test Property | property=${obj}.enabled | data=0 +| | Test Property | property=${obj}.enabled | data=1 +| | Test Property | property=${obj}.opacity | data=0 +| | Test Property | property=${obj}.opacity | data=64 +| | Test Property | property=${obj}.opacity | data=192 +| | Test Property | property=${obj}.opacity | data=255 +| | Test Property | property=${obj}.toggle | data=0 +| | Test Property | property=${obj}.toggle | data=1 +| | Test Property | property=${obj}.val | data=0 +| | Test Property | property=${obj}.val | data=1 +| | Test Property | property=${obj}.val | data=2 +| | Test Property | property=${obj}.val | data=3 + +| Test Slider\n +| | ${obj} | Set Variable | p[1].b[3] +| | Test Page | property=page | data=1 +#| | Test Property | property=${obj}.txt | data=ABC +#| | Test Property | property=${obj}.txt | data=1234 +| | Test Property | property=${obj}.x | data=20 +| | Test Property | property=${obj}.x | data=10 +| | Test Property | property=${obj}.y | data=20 +| | Test Property | property=${obj}.y | data=10 +| | Test Property | property=${obj}.w | data=80 +| | Test Property | property=${obj}.w | data=75 +| | Test Property | property=${obj}.h | data=36 +| | Test Property | property=${obj}.h | data=18 +| | Test Property | property=${obj}.hidden | data=1 +| | Test Property | property=${obj}.hidden | data=0 +| | Test Property | property=${obj}.vis | data=0 +| | Test Property | property=${obj}.vis | data=1 +| | Test Property | property=${obj}.enabled | data=0 +| | Test Property | property=${obj}.enabled | data=1 +| | Test Property | property=${obj}.opacity | data=0 +| | Test Property | property=${obj}.opacity | data=64 +| | Test Property | property=${obj}.opacity | data=192 +| | Test Property | property=${obj}.opacity | data=255 +| | Test Property | property=${obj}.max | data=200 +| | Test Property | property=${obj}.min | data=100 +| | Test Property | property=${obj}.min | data=50 +| | Test Property | property=${obj}.max | data=150 +| | Test Property | property=${obj}.val | data=50 +| | Test Property | property=${obj}.val | data=60 +| | Test Property | property=${obj}.val | data=70 +| | Test Property | property=${obj}.val | data=80 diff --git a/test/keywords.robot b/test/keywords.robot new file mode 100644 index 00000000..c29c54c9 --- /dev/null +++ b/test/keywords.robot @@ -0,0 +1,91 @@ +| *Settings* | *Value* +| Library | MQTTLibrary +| Library | BuiltIn + +| *Variables* | *Value* +#| ${broker.uri} | mqtt.eclipse.org +| ${broker.uri} | 10.4.0.5 +| ${broker.port} | 1883 +| ${client.id} | mqtt.test.client +| ${topic} | test/mqtt_test +| ${sub.topic} | test/mqtt_test_sub + +| *Keywords* | +| Easy Connect +| | [Arguments] | ${broker.uri}=${broker.uri} | ${port}=${broker.port} +| | ... | ${client.id}=${client.id} | ${clean_session}=${true} +| | Connect | ${broker.uri} | ${port} | ${client.id} | ${clean_session} + +| Publish to MQTT Broker +| | [Arguments] | ${broker.uri}=${broker.uri} | ${port}=${broker.port} +| | ... | ${client.id}=${client.id} | ${clean_session}=${true} +| | ... | ${topic}=${topic} | ${message}=${EMPTY} +| | ... | ${qos}=0 | ${retention}=${false} +| | Connect | ${broker.uri} | ${port} | ${client.id} | ${clean_session} +| | Publish | ${topic} | ${message} | ${qos} | ${retention} + +| Publish to MQTT Broker and Disconnect +| | [Arguments] | ${broker.uri}=${broker.uri} | ${port}=${broker.port} +| | ... | ${client.id}=${client.id} | ${clean_session}=${true} +| | ... | ${topic}=${topic} | ${message}=${EMPTY} +| | ... | ${qos}=0 | ${retention}=${false} +| | Connect | ${broker.uri} | ${port} | ${client.id} | ${clean_session} +| | Publish | ${topic} | ${message} | ${qos} | ${retention} +| | [Teardown] | Disconnect + +| Subscribe to MQTT Broker and Validate +| | [Arguments] | ${broker.uri}=${broker.uri} | ${port}=${broker.port} +| | ... | ${client.id}=${client.id} | ${topic}=${topic} +| | ... | ${message}=${EMPTY} | ${qos}=1 +| | ... | ${timeout}=1s +| | Connect | ${broker.uri} | ${port} | ${client.id} | ${false} +| | Subscribe and Validate +| | ... | ${topic} | ${qos} | ${message} | ${timeout} +| | [Teardown] | Disconnect + +| Subscribe and Get Messages +| | [Arguments] | ${broker.uri}=${broker.uri} | ${port}=${broker.port} +| | ... | ${client.id}=${client.id} | ${topic}=${topic} +| | ... | ${qos}=1 | ${timeout}=1s +| | ... | ${limit}=1 +| | Connect | ${broker.uri} | ${port} | ${client.id} | ${false} +| | @{messages} | Subscribe | ${topic} | ${qos} | ${timeout} | ${limit} +| | [Teardown] | Disconnect +| | [Return] | @{messages} + +| Subscribe Async +| | [Arguments] | ${broker.uri}=${broker.uri} | ${port}=${broker.port} +| | ... | ${client.id}=${client.id} | ${topic}=${topic} +| | ... | ${qos}=1 | ${timeout}=0s +| | ... | ${limit}=1 +| | Connect | ${broker.uri} | ${port} | ${client.id} | ${false} +| | Subscribe | ${topic} | ${qos} | ${timeout} | ${limit} + +| Unsubscribe and Disconnect +| | [Arguments] | ${topic}=${topic} +| | Unsubscribe | ${topic} +| | [Teardown] | Disconnect + +| Unsubscribe Multiple and Disconnect +| | [Arguments] | @{topics} +| | FOR | ${topic} | IN | @{topics} +| | | Unsubscribe | ${topic} +| | END +| | [Teardown] | Disconnect + +| Subscribe and Unsubscribe +| | [Arguments] | ${broker.uri}=${broker.uri} | ${port}=${broker.port} +| | ... | ${client.id}=${client.id} | ${topic}=${topic} +| | ... | ${qos}=1 | ${timeout}=1s +| | ... | ${limit}=1 +| | Connect | ${broker.uri} | ${port} | ${client.id} | ${false} +| | @{messages} | Subscribe | ${topic} | ${qos} | ${timeout} | ${limit} +| | Unsubscribe | ${topic} +| | [Teardown] | Disconnect +| | [Return] | @{messages} + +| Listen and Get Messages +| | [Arguments] | ${topic}=${topic} | ${timeout}=1s +| | ... | ${limit}=1 +| | @{messages} | Listen | ${topic} | ${timeout} | ${limit} +| | [Return] | @{messages} \ No newline at end of file From 4e6f6a82685d3f54a83193f00b58b6b5a1d31cd9 Mon Sep 17 00:00:00 2001 From: fvanroie Date: Mon, 19 Oct 2020 22:11:09 +0200 Subject: [PATCH 04/33] Fix attribute bugs --- src/hasp_attribute.cpp | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/src/hasp_attribute.cpp b/src/hasp_attribute.cpp index b52c8ae3..b23f9aed 100644 --- a/src/hasp_attribute.cpp +++ b/src/hasp_attribute.cpp @@ -597,8 +597,8 @@ static void hasp_process_obj_attribute_val(lv_obj_t * obj, const char * attr, co lv_obj_get_type(obj, &list); const char * objtype = list.type[0]; - if(check_obj_type(objtype, LV_HASP_BUTTON)) { - if(lv_btn_get_checkable(obj)) { + if(check_obj_type(objtype, LV_HASP_BUTTON) && lv_btn_get_checkable(obj)) { + if(update) { lv_btn_state_t state; switch(val) { case 0: @@ -607,11 +607,27 @@ static void hasp_process_obj_attribute_val(lv_obj_t * obj, const char * attr, co case 1: state = LV_BTN_STATE_CHECKED_RELEASED; break; + case 3: + state = LV_BTN_STATE_CHECKED_DISABLED; + break; default: state = LV_BTN_STATE_DISABLED; + }; + return lv_btn_set_state(obj, state); + } else { + lv_btn_state_t state = lv_btn_get_state(obj); + switch(state) { + case LV_BTN_STATE_RELEASED: + case LV_BTN_STATE_PRESSED: + return hasp_out_int(obj, attr, 0); + case LV_BTN_STATE_CHECKED_RELEASED: + case LV_BTN_STATE_CHECKED_PRESSED: + return hasp_out_int(obj, attr, 1); + case LV_BTN_STATE_DISABLED: + return hasp_out_int(obj, attr, 2); + case LV_BTN_STATE_CHECKED_DISABLED: + return hasp_out_int(obj, attr, 3); } - lv_btn_set_state(obj, state); - return; } } if(check_obj_type(objtype, LV_HASP_CHECKBOX)) { @@ -661,24 +677,28 @@ static void hasp_process_obj_attribute_range(lv_obj_t * obj, const char * attr, if(check_obj_type(objtype, LV_HASP_SLIDER)) { int16_t min = lv_slider_get_min_value(obj); int16_t max = lv_slider_get_max_value(obj); + if(update && (set_min ? val : min) <= (set_max ? val : max)) return; // prevent setting min<=max return update ? lv_slider_set_range(obj, set_min ? val : min, set_max ? val : max) : hasp_out_int(obj, attr, set_min ? lv_slider_get_min_value(obj) : lv_slider_get_max_value(obj)); } if(check_obj_type(objtype, LV_HASP_GAUGE)) { int16_t min = lv_gauge_get_min_value(obj); int16_t max = lv_gauge_get_max_value(obj); + if(update && (set_min ? val : min) <= (set_max ? val : max)) return; // prevent setting min<=max return update ? lv_gauge_set_range(obj, set_min ? val : min, set_max ? val : max) : hasp_out_int(obj, attr, set_min ? lv_gauge_get_min_value(obj) : lv_gauge_get_max_value(obj)); } if(check_obj_type(objtype, LV_HASP_BAR)) { int16_t min = lv_bar_get_min_value(obj); int16_t max = lv_bar_get_max_value(obj); + if(update && (set_min ? val : min) <= (set_max ? val : max)) return; // prevent setting min<=max return update ? lv_bar_set_range(obj, set_min ? val : min, set_max ? val : max) : hasp_out_int(obj, attr, set_min ? lv_bar_get_min_value(obj) : lv_bar_get_max_value(obj)); } if(check_obj_type(objtype, LV_HASP_LMETER)) { int16_t min = lv_linemeter_get_min_value(obj); int16_t max = lv_linemeter_get_max_value(obj); + if(update && (set_min ? val : min) <= (set_max ? val : max)) return; // prevent setting min<=max return update ? lv_linemeter_set_range(obj, set_min ? val : min, set_max ? val : max) : hasp_out_int(obj, attr, set_min ? lv_linemeter_get_min_value(obj) : lv_linemeter_get_max_value(obj)); From 218e81d29c4f7d773b57fbf1a2b4ae4495ddb047 Mon Sep 17 00:00:00 2001 From: fvanroie Date: Tue, 27 Oct 2020 22:39:06 +0100 Subject: [PATCH 05/33] Fix CPU info in log --- src/hasp_tft.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hasp_tft.cpp b/src/hasp_tft.cpp index 031b5f23..2ec5e51e 100644 --- a/src/hasp_tft.cpp +++ b/src/hasp_tft.cpp @@ -83,7 +83,7 @@ void tftShowConfig(TFT_eSPI & tft) tft.getSetup(tftSetup); Log.verbose(F("TFT: TFT_eSPI : v%s"), tftSetup.version.c_str()); -#if defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_32) +#if defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_ESP32) Log.verbose(F("TFT: Processor : ESP%x"), tftSetup.esp); #else Log.verbose(F("TFT: Processor : STM%x"), tftSetup.esp); From f5c45272e5b9a13eb209c4fc1beadf9e24b52af6 Mon Sep 17 00:00:00 2001 From: fvanroie Date: Tue, 27 Oct 2020 22:39:35 +0100 Subject: [PATCH 06/33] Fix setHostname for DHCP requests --- src/hasp_wifi.cpp | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/hasp_wifi.cpp b/src/hasp_wifi.cpp index 2921b027..6ee9a419 100644 --- a/src/hasp_wifi.cpp +++ b/src/hasp_wifi.cpp @@ -4,7 +4,7 @@ #include "hasp_conf.h" -#if HASP_USE_WIFI>0 +#if HASP_USE_WIFI > 0 #include "hasp_debug.h" #include "hasp_config.h" @@ -153,7 +153,12 @@ void wifiSetup() WiFi.onEvent(wifi_callback); WiFi.setSleep(false); #endif + + WiFi.disconnect(true); + WiFi.config(INADDR_NONE, INADDR_NONE, INADDR_NONE); + WiFi.setHostname(mqttGetNodename().c_str()); WiFi.begin(wifiSsid, wifiPassword); + Log.notice(F("WIFI: Connecting to : %s"), wifiSsid); } } @@ -171,7 +176,12 @@ bool wifiEvery5Seconds() dispatchReboot(false); } Log.warning(F("WIFI: No Connection... retry %u"), wifiReconnectCounter); - if(wifiReconnectCounter % 6 == 0) WiFi.begin(wifiSsid, wifiPassword); + if(wifiReconnectCounter % 6 == 0) { + WiFi.disconnect(true); + WiFi.config(INADDR_NONE, INADDR_NONE, INADDR_NONE); + WiFi.setHostname(mqttGetNodename().c_str()); + WiFi.begin(wifiSsid, wifiPassword); + } return false; } } From d7b3f663277b75c12f953d02b70905eaac06376b Mon Sep 17 00:00:00 2001 From: fvanroie Date: Tue, 27 Oct 2020 22:39:57 +0100 Subject: [PATCH 07/33] Fix hostname for DHCP request --- src/main.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 7feb8331..c7c4f5b8 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -47,6 +47,14 @@ void setup() gpioSetup(); #endif +#if HASP_USE_ETHERNET > 0 + ethernetSetup(); +#endif + +#if HASP_USE_MQTT > 0 + mqttSetup(); // Load Hostname before starting WiFi +#endif + #if HASP_USE_WIFI > 0 wifiSetup(); #endif @@ -64,14 +72,6 @@ void setup() otaSetup(); #endif -#if HASP_USE_ETHERNET > 0 - ethernetSetup(); -#endif - -#if HASP_USE_MQTT > 0 - mqttSetup(); -#endif - #if HASP_USE_HTTP > 0 httpSetup(); #endif From a6afdc9105011f5ce1c4c0db180894fe474a33d6 Mon Sep 17 00:00:00 2001 From: fvanroie Date: Tue, 27 Oct 2020 22:43:10 +0100 Subject: [PATCH 08/33] Fix Typo --- src/hasp_gui.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/hasp_gui.cpp b/src/hasp_gui.cpp index 7c33af36..20193f62 100644 --- a/src/hasp_gui.cpp +++ b/src/hasp_gui.cpp @@ -677,9 +677,9 @@ void guiSetup() /* Dump TFT Configuration */ tftSetup(tft); #ifdef USE_DMA_TO_TFT - Log.verbose(F("TFT: DMA : ENABELD")); + Log.verbose(F("TFT: DMA : ENABLED")); #else - Log.verbose(F("TFT: DMA : DISABELD")); + Log.verbose(F("TFT: DMA : DISABLED")); #endif /* Load User Settings */ From 2ee14c21dae199d2c28d7b93fd9fde2280c44dcd Mon Sep 17 00:00:00 2001 From: fvanroie Date: Tue, 27 Oct 2020 22:44:03 +0100 Subject: [PATCH 09/33] Version bump --- include/hasp_conf.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/hasp_conf.h b/include/hasp_conf.h index 1532c1f5..134dd1ca 100644 --- a/include/hasp_conf.h +++ b/include/hasp_conf.h @@ -3,7 +3,7 @@ #define HASP_VERSION_MAJOR 0 #define HASP_VERSION_MINOR 2 -#define HASP_VERSION_REVISION 1014 +#define HASP_VERSION_REVISION 1027 #define HASP_USE_APP 1 From a7807a9e8e0b8afa9ddd418facf092702312af31 Mon Sep 17 00:00:00 2001 From: fvanroie Date: Tue, 27 Oct 2020 22:47:53 +0100 Subject: [PATCH 10/33] Update lvgl --- lib/lvgl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/lvgl b/lib/lvgl index d01d1357..712c2e6c 160000 --- a/lib/lvgl +++ b/lib/lvgl @@ -1 +1 @@ -Subproject commit d01d1357ad28e10c606b9e426f7fdf0c23b1e5ac +Subproject commit 712c2e6ce91747e68dd127ea7ba294894cfc0ca7 From c63df51d1ade8040a8c420809f95c85e78d608bd Mon Sep 17 00:00:00 2001 From: fvanroie Date: Tue, 27 Oct 2020 23:02:07 +0100 Subject: [PATCH 11/33] Update lvgl --- lib/lvgl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/lvgl b/lib/lvgl index 712c2e6c..2af7abdb 160000 --- a/lib/lvgl +++ b/lib/lvgl @@ -1 +1 @@ -Subproject commit 712c2e6ce91747e68dd127ea7ba294894cfc0ca7 +Subproject commit 2af7abdbd1a6f066a966551cd1f32a2dfbbd086a From 8957bbd778aa49e4270950803f359a7be2b41d92 Mon Sep 17 00:00:00 2001 From: fvanroie Date: Tue, 27 Oct 2020 23:31:02 +0100 Subject: [PATCH 12/33] Update lvgl --- lib/lvgl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/lvgl b/lib/lvgl index 2af7abdb..e9fdc1d6 160000 --- a/lib/lvgl +++ b/lib/lvgl @@ -1 +1 @@ -Subproject commit 2af7abdbd1a6f066a966551cd1f32a2dfbbd086a +Subproject commit e9fdc1d68b3c81ea45d0a1d89ec17cc9a3899037 From 7131a4684730d2754d05ecfec5f02d6a2e870fa4 Mon Sep 17 00:00:00 2001 From: fvanroie Date: Wed, 28 Oct 2020 00:05:06 +0100 Subject: [PATCH 13/33] Update lvgl --- lib/lvgl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/lvgl b/lib/lvgl index e9fdc1d6..3543cc05 160000 --- a/lib/lvgl +++ b/lib/lvgl @@ -1 +1 @@ -Subproject commit e9fdc1d68b3c81ea45d0a1d89ec17cc9a3899037 +Subproject commit 3543cc051bdb7b8233ddcc71b3694efcbe562c52 From d036dd77c4c4aab40a1106c54474e99d2344cd2e Mon Sep 17 00:00:00 2001 From: fvanroie Date: Wed, 28 Oct 2020 00:55:01 +0100 Subject: [PATCH 14/33] Add missing test --- test/pubsub.robot | 209 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 209 insertions(+) create mode 100644 test/pubsub.robot diff --git a/test/pubsub.robot b/test/pubsub.robot new file mode 100644 index 00000000..a099a11e --- /dev/null +++ b/test/pubsub.robot @@ -0,0 +1,209 @@ +| *Settings* | *Value* +| Resource | keywords.robot +| Test Timeout | 30 seconds + +| *Test Cases* +| Publish a non-empty message +| | ${time} | Get Time | epoch +| | ${message} | Catenate | test message | ${time} +| | Publish to MQTT Broker and Disconnect | message=${message} + +| Publish an empty message +| | Publish to MQTT Broker and Disconnect + +| Publish a message with QOS 1 and validate that the message is received +| | ${time} | Get Time | epoch +| | ${client} | Catenate | SEPARATOR=. | robot.mqtt | ${time} +| | ${topic} | Set Variable | test/mqtt_test_sub +| | ${message} | Set Variable | subscription test message +| | Run Keyword And Expect Error | The expected payload didn't arrive in the topic +| | ... | Subscribe to MQTT Broker and Validate | client.id=${client} | topic=${topic} | message=${message} +| | Publish to MQTT Broker and Disconnect | topic=${topic} | message=${message} | qos=1 +| | Subscribe to MQTT Broker and Validate | client.id=${client} | topic=${topic} | message=${message} + +| Publish multiple messages and confirm that validation succeeds only after correct message is published +| | ${time} | Get Time | epoch +| | ${client} | Catenate | SEPARATOR=. | robot.mqtt | ${time} +| | ${topic} | Set Variable | test/mqtt_test_sub +| | ${message} | Set Variable | subscription test message +| | Run Keyword And Expect Error | The expected payload didn't arrive in the topic +| | ... | Subscribe to MQTT Broker and Validate | client.id=${client} | topic=${topic} | message=${message} +| | Publish to MQTT Broker and Disconnect | topic=${topic} | message=message1 | qos=1 +| | Publish to MQTT Broker and Disconnect | topic=${topic} | message=message2 | qos=1 +| | Run Keyword And Expect Error | The expected payload didn't arrive in the topic +| | ... | Subscribe to MQTT Broker and Validate | client.id=${client} | topic=${topic} | message=${message} +| | Publish to MQTT Broker and Disconnect | topic=${topic} | message=${message} | qos=1 +| | Publish to MQTT Broker and Disconnect | topic=${topic} | message=message3 | qos=1 +| | Publish to MQTT Broker and Disconnect | topic=${topic} | message=message4 | qos=1 +| | Subscribe to MQTT Broker and Validate | client.id=${client} | topic=${topic} | message=${message} + +| Publish an empty message with QOS 1 and validate +| | ${time} | Get Time | epoch +| | ${client} | Catenate | SEPARATOR=. | robot.mqtt | ${time} +| | ${topic} | Set Variable | test/mqtt_test_sub +| | Run Keyword And Expect Error | The expected payload didn't arrive in the topic +| | ... | Subscribe to MQTT Broker and Validate | client.id=${client} | topic=${topic} +| | Publish to MQTT Broker and Disconnect | topic=${topic} | qos=1 +| | Subscribe to MQTT Broker and Validate | client.id=${client} | topic=${topic} + +| Publish and validate with regular expression +| | ${time} | Get Time | epoch +| | ${client} | Catenate | SEPARATOR=. | robot.mqtt | ${time} +| | ${topic} | Set Variable | test/mqtt_test_sub +| | ${message} | Set Variable | subscription test message +| | ${regex} | Set Variable | ^subscription [test]{4} message$ +| | Run Keyword And Expect Error | The expected payload didn't arrive in the topic +| | ... | Subscribe to MQTT Broker and Validate | client.id=${client} | topic=${topic} | message=whatever +| | Publish to MQTT Broker and Disconnect | topic=${topic} | message=${message} | qos=1 +| | Subscribe to MQTT Broker and Validate | client.id=${client} | topic=${topic} | message=${regex} + +| Subscribe for the first time and validate that no messages are received +| | ${time} | Get Time | epoch +| | ${client} | Catenate | SEPARATOR=. | robot.mqtt | ${time} +| | ${topic} | Set Variable | test/mqtt_test_sub +| | @{messages} | Subscribe and Get Messages | client.id=${client} | topic=${topic} | timeout=5s +| | LOG | ${messages} +| | Length Should Be | ${messages} | 0 + +| Subscribe, publish 1 message and validate it is received +| | ${time} | Get Time | epoch +| | ${client} | Catenate | SEPARATOR=. | robot.mqtt | ${time} +| | ${topic} | Set Variable | test/mqtt_test_sub +| | Subscribe and Get Messages | client.id=${client} | topic=${topic} +| | Publish to MQTT Broker and Disconnect | topic=${topic} | message=test message | qos=1 +| | @{messages} | Subscribe and Get Messages | client.id=${client} | topic=${topic} +| | LOG | ${messages} +| | Length Should Be | ${messages} | 1 +| | Should Be Equal As Strings | ${messages}[0] | test message + +| Subscribe with no limit, publish multiple messages and validate they are received +| | ${time} | Get Time | epoch +| | ${client} | Catenate | SEPARATOR=. | robot.mqtt | ${time} +| | ${topic} | Set Variable | test/mqtt_test_sub +| | Subscribe and Get Messages | client.id=${client} | topic=${topic} +| | Publish to MQTT Broker and Disconnect | topic=${topic} | message=test message1 | qos=1 +| | Publish to MQTT Broker and Disconnect | topic=${topic} | message=test message2 | qos=1 +| | Publish to MQTT Broker and Disconnect | topic=${topic} | message=test message3 | qos=1 +| | @{messages} | Subscribe and Get Messages | client.id=${client} | topic=${topic} | limit=0 +| | LOG | ${messages} +| | Length Should Be | ${messages} | 3 +| | Should Be Equal As Strings | ${messages}[0] | test message1 +| | Should Be Equal As Strings | ${messages}[1] | test message2 +| | Should Be Equal As Strings | ${messages}[2] | test message3 + +| Subscribe with limit +| | ${time} | Get Time | epoch +| | ${client} | Catenate | SEPARATOR=. | robot.mqtt | ${time} +| | ${topic} | Set Variable | test/mqtt_test_sub +| | Subscribe and Get Messages | client.id=${client} | topic=${topic} +| | Publish to MQTT Broker and Disconnect | topic=${topic} | message=test message1 | qos=1 +| | Publish to MQTT Broker and Disconnect | topic=${topic} | message=test message2 | qos=1 +| | Publish to MQTT Broker and Disconnect | topic=${topic} | message=test message3 | qos=1 +| | @{messages} | Subscribe and Get Messages | client.id=${client} | topic=${topic} | limit=1 +| | LOG | ${messages} +| | Length Should Be | ${messages} | 1 +| | Should Be Equal As Strings | ${messages}[0] | test message1 +| | @{messages} | Subscribe and Get Messages | client.id=${client} | topic=${topic} | limit=2 +| | LOG | ${messages} +| | Length Should Be | ${messages} | 2 +| | Should Be Equal As Strings | ${messages}[0] | test message2 +| | Should Be Equal As Strings | ${messages}[1] | test message3 + +| Unsubscribe and validate no messages are received +| | ${time} | Get Time | epoch +| | ${client} | Catenate | SEPARATOR=. | robot.mqtt | ${time} +| | ${topic} | Set Variable | test/mqtt_test_sub +| | Subscribe and Get Messages | client.id=${client} | topic=${topic} +| | Publish to MQTT Broker and Disconnect | topic=${topic} | message=test message1 | qos=1 +| | @{messages} | Subscribe and Unsubscribe | client.id=${client} | topic=${topic} +| | Publish to MQTT Broker and Disconnect | topic=${topic} | message=test message2 | qos=1 +| | @{messages} | Subscribe and Get Messages | client.id=${client} | topic=${topic} +| | LOG | ${messages} +| | Length Should Be | ${messages} | 0 + +| Publish and Subscribe to a broker that requires username, password authentication +| | [Tags] | auth +| | ${time} | Get Time | epoch +| | ${client} | Catenate | SEPARATOR=. | robot.mqtt | ${time} +| | ${topic} | Set Variable | test +| | ${message} | Set Variable | subscription test message +| | Set username and password | authuser1 | password1 +| | Run Keyword And Expect Error | The expected payload didn't arrive in the topic +| | ... | Subscribe to MQTT Broker and Validate | broker.uri=127.0.0.1 | port=11883 | client.id=${client} +| | ... | topic=${topic} | message=${message} +| | Connect | 127.0.0.1 | 11883 +| | Publish | ${topic} | test message with username and password | qos=1 +| | Subscribe to MQTT Broker and Validate +| | ... | broker.uri=127.0.0.1 | port=11883 | client.id=${client} | topic=${topic} | message=test message with username and password +| | [Teardown] | Disconnect + +| Publish to a broker that requires authentication with invalid password +| | [Tags] | auth +| | ${time} | Get Time | epoch +| | ${client} | Catenate | SEPARATOR=. | robot.mqtt | ${time} +| | ${topic} | Set Variable | test +| | Set username and password | authuser1 | invalidpwd +| | Run Keyword and expect error | The client disconnected unexpectedly +| | ... | Connect | 127.0.0.1 | 11883 | ${client} +| | [Teardown] | Disconnect + +| Subscribe async, publish 1 message, listen for and validate it is received +| | ${time} | Get Time | epoch +| | ${client} | Catenate | SEPARATOR=. | robot.mqtt | ${time} +| | ${topic} | Set Variable | test/mqtt_test_sub +| | Subscribe Async | client.id=${client} | topic=${topic} +| | Publish to MQTT Broker | topic=${topic} | message=test message | qos=1 +| | @{messages} | Listen and Get Messages | topic=${topic} +| | LOG | ${messages} +| | Length Should Be | ${messages} | 1 +| | Should Be Equal As Strings | ${messages}[0] | test message +| | [Teardown] | Unsubscribe and Disconnect | ${topic} + +| Subscribe async, publish several messages, listen for and validate they are received +| | ${time} | Get Time | epoch +| | ${client} | Catenate | SEPARATOR=. | robot.mqtt | ${time} +| | ${topic} | Set Variable | test/mqtt_test_sub +| | Subscribe Async | client.id=${client} | topic=${topic} +| | Publish to MQTT Broker | topic=${topic} | message=test message1 | qos=1 +| | Publish to MQTT Broker | topic=${topic} | message=test message2 | qos=1 +| | Publish to MQTT Broker | topic=${topic} | message=test message3 | qos=1 +| | @{messages} | Listen and Get Messages | topic=${topic} | limit=0 +| | LOG | ${messages} +| | Length Should Be | ${messages} | 3 +| | Should Be Equal As Strings | ${messages}[0] | test message1 +| | Should Be Equal As Strings | ${messages}[1] | test message2 +| | Should Be Equal As Strings | ${messages}[2] | test message3 +| | [Teardown] | Unsubscribe and Disconnect | ${topic} + +| Subscribe async to multiple topics, publish several messages, listen for them and validate they are received +| | ${time} | Get Time | epoch +| | ${client1} | Catenate | SEPARATOR=. | robot.mqtt | ${time} +| | ${client2} | Catenate | SEPARATOR=. | robot.mqtt | ${time+1} +| | ${topic1} | Set Variable | test/mqtt_test_sub1 +| | ${topic2} | Set Variable | test/mqtt_test_sub2 +| | Subscribe Async | client.id=${client1} | topic=${topic1} +| | Subscribe Async | client.id=${client2} | topic=${topic2} +| | Publish to MQTT Broker | topic=${topic2} | message=test message1 | qos=1 +| | Publish to MQTT Broker | topic=${topic1} | message=test message2 | qos=1 +| | Publish to MQTT Broker | topic=${topic2} | message=test message3 | qos=1 +| | @{messages1} | Listen and Get Messages | topic=${topic1} | limit=0 +| | @{messages2} | Listen and Get Messages | topic=${topic2} | limit=0 +| | LOG | ${messages1} +| | LOG | ${messages2} +| | Length Should Be | ${messages1} | 1 +| | Should Be Equal As Strings | ${messages1}[0] | test message2 +| | Length Should Be | ${messages2} | 2 +| | Should Be Equal As Strings | ${messages2}[0] | test message1 +| | Should Be Equal As Strings | ${messages2}[1] | test message3 +| | [Teardown] | Unsubscribe Multiple and Disconnect | ${topic1} | ${topic2} + +| Listen immediately after Subscribe and validate message is received +| | ${time} | Get Time | epoch +| | ${client} | Catenate | SEPARATOR=. | robot.mqtt | ${time} +| | ${topic} | Set Variable | test/mqtt_test_sub +| | Subscribe and Get Messages | client.id=${client} | topic=${topic} +| | Publish to MQTT Broker and Disconnect | topic=${topic} | message=test message | qos=1 +| | Subscribe Async | client.id=${client} | topic=${topic} +| | @{messages}= | Listen | topic=${topic} | limit=10 | timeout=5 +| | Should Be Equal As Strings | ${messages}[0] | test message +| | [Teardown] | Unsubscribe and Disconnect | ${topic} \ No newline at end of file From 3a6b8d5605ed089debaf79d95583cf8021ba4d97 Mon Sep 17 00:00:00 2001 From: fvanroie Date: Wed, 28 Oct 2020 14:54:37 +0100 Subject: [PATCH 15/33] Improve font handling --- src/hasp.cpp | 117 +++++++++++++++-------------------------- src/hasp.h | 1 + src/hasp_attr_get.cpp | 50 ------------------ src/hasp_attribute.cpp | 10 +++- 4 files changed, 50 insertions(+), 128 deletions(-) delete mode 100644 src/hasp_attr_get.cpp diff --git a/src/hasp.cpp b/src/hasp.cpp index 45d29b80..e8b08a7b 100644 --- a/src/hasp.cpp +++ b/src/hasp.cpp @@ -57,7 +57,7 @@ char haspZiFontPath[32]; **********************/ lv_style_t style_mbox_bg; /*Black bg. style with opacity*/ lv_obj_t * kb; -lv_font_t * defaultFont; +// lv_font_t * defaultFont; #if LV_DEMO_WALLPAPER LV_IMG_DECLARE(img_bubble_pattern) @@ -84,17 +84,9 @@ static const char * btnm_map2[] = {"0", "1", "\n", "2", "3", "\n", "4", "5", */ lv_obj_t * pages[HASP_NUM_PAGES]; -#if defined(ARDUINO_ARCH_ESP8266) -static lv_font_t * haspFonts[4]; -// static lv_style_t labelStyles[4]; -// static lv_style_t rollerStyles[4]; -#else -lv_font_t * haspFonts[8]; -// static lv_style_t labelStyles[8]; -// static lv_style_t rollerStyles[8]; -#endif -uint8_t current_page = 0; -// uint16_t current_style = 0; +static lv_font_t * haspFonts[4] = {nullptr, LV_THEME_DEFAULT_FONT_NORMAL, LV_THEME_DEFAULT_FONT_SUBTITLE, + LV_THEME_DEFAULT_FONT_TITLE}; +uint8_t current_page = 0; /********************** * MACROS @@ -105,6 +97,19 @@ uint8_t current_page = 0; **********************/ void haspLoadPage(const char * pages); +//////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Get Font ID + */ +lv_font_t * hasp_get_font(uint8_t fontid) +{ + if(fontid >= 4) { + return nullptr; + } else { + return haspFonts[fontid]; + } +} + //////////////////////////////////////////////////////////////////////////////////////////////////// /** * Get Page Object by PageID @@ -257,26 +262,13 @@ static inline void hasp_send_obj_attribute_txt(lv_obj_t * obj, const char * txt) void hasp_process_attribute(uint8_t pageid, uint8_t objid, const char * attr, const char * payload) { hasp_process_obj_attribute(hasp_find_obj_from_id(pageid, objid), attr, payload, strlen(payload) > 0); - - /* else { - // publish the change - std::string strValue = ""; - if(haspGetObjAttribute(obj, strAttr, strValue)) { - #if HASP_USE_MQTT > 0 - mqtt_send_attribute(pageid, objid, strAttr.c_str(), strValue.c_str()); - #endif - } else { - Log.warning(F("HASP: Unknown property: %s"), strAttr.c_str()); - } - } // payload */ } //////////////////////////////////////////////////////////////////////////////////////////////////// /** - * Connection lost GUI + * WakeUp the display using a command instead of touch */ - void haspWakeUp() { lv_disp_trig_activity(NULL); @@ -358,21 +350,9 @@ void haspSetup() Log.error(F("Closing pages.json OK")); else Log.verbose(F("Closing pages.json on FS failed %d"), res); - /******* File System Test ********************************************************************/ + /******* File System Test ********************************************************************/ - /* ********** Font Initializations ********** */ - defaultFont = LV_FONT_DEFAULT; // Use default font -#if ESP32 - lv_font_t * font_small = defaultFont; - lv_font_t * font_normal = &lv_font_montserrat_12; - lv_font_t * font_subtitle = &lv_font_montserrat_16; - lv_font_t * font_title = &lv_font_montserrat_22; -#else - lv_font_t * font_small = defaultFont; - lv_font_t * font_normal = defaultFont; - lv_font_t * font_subtitle = defaultFont; - lv_font_t * font_title = defaultFont; -#endif + /* ********** Font Initializations ********** */ #if HASP_USE_SPIFFS > 0 #if defined(ARDUINO_ARCH_ESP32) || defined(ARDUINO_ARCH_ESP8266) @@ -380,11 +360,13 @@ void haspSetup() if(lv_zifont_font_init(&haspFonts[0], haspZiFontPath, 24) != 0) { Log.error(F("HASP: Failed to set font to %s"), haspZiFontPath); + haspFonts[0] = LV_FONT_DEFAULT; } else { - defaultFont = haspFonts[0]; + // defaultFont = haspFonts[0]; } #endif #endif + /* ********** Font Initializations ********** */ /* ********** Theme Initializations ********** */ @@ -402,20 +384,20 @@ void haspSetup() #endif #if(LV_USE_THEME_MONO == 1) || (LV_USE_THEME_EMPTY == 1) case 3: - th = lv_theme_mono_init(LV_COLOR_PURPLE, LV_COLOR_BLACK, LV_THEME_DEFAULT_FLAGS, font_small, font_normal, - font_subtitle, font_title); + th = lv_theme_mono_init(LV_COLOR_PURPLE, LV_COLOR_BLACK, LV_THEME_DEFAULT_FLAGS, haspFonts[0], haspFonts[1], + haspFonts[2], haspFonts[3]); break; #endif #if LV_USE_THEME_MATERIAL == 1 case 4: th = lv_theme_material_init(LV_COLOR_PURPLE, LV_COLOR_ORANGE, - LV_THEME_MATERIAL_FLAG_LIGHT + LV_THEME_MATERIAL_FLAG_NO_FOCUS, font_small, - font_normal, font_subtitle, font_title); + LV_THEME_MATERIAL_FLAG_LIGHT + LV_THEME_MATERIAL_FLAG_NO_FOCUS, haspFonts[0], + haspFonts[1], haspFonts[2], haspFonts[3]); break; case 9: th = lv_theme_material_init(LV_COLOR_PURPLE, LV_COLOR_ORANGE, - LV_THEME_MATERIAL_FLAG_DARK + LV_THEME_MATERIAL_FLAG_NO_FOCUS, font_small, - font_normal, font_subtitle, font_title); + LV_THEME_MATERIAL_FLAG_DARK + LV_THEME_MATERIAL_FLAG_NO_FOCUS, haspFonts[0], + haspFonts[1], haspFonts[2], haspFonts[3]); break; #endif @@ -436,8 +418,8 @@ void haspSetup() #endif #if(LV_USE_THEME_HASP == 1) || (LV_USE_THEME_TEMPLATE == 1) case 8: - th = lv_theme_template_init(LV_COLOR_PURPLE, LV_COLOR_ORANGE, LV_THEME_DEFAULT_FLAGS, font_small, - font_normal, font_subtitle, font_title); + th = lv_theme_template_init(LV_COLOR_PURPLE, LV_COLOR_ORANGE, LV_THEME_DEFAULT_FLAGS, haspFonts[0], + haspFonts[1], haspFonts[2], haspFonts[3]); break; #endif /* case 0: @@ -449,8 +431,8 @@ void haspSetup() break; */ default: - th = lv_theme_template_init(LV_COLOR_PURPLE, LV_COLOR_ORANGE, LV_THEME_DEFAULT_FLAGS, font_small, - font_normal, font_subtitle, font_title); + th = lv_theme_template_init(LV_COLOR_PURPLE, LV_COLOR_ORANGE, LV_THEME_DEFAULT_FLAGS, haspFonts[0], + haspFonts[1], haspFonts[2], haspFonts[3]); Log.error(F("HASP: Unknown theme selected")); } @@ -462,20 +444,19 @@ void haspSetup() // lv_theme_set_current(th); /* ********** Theme Initializations ********** */ - lv_style_list_t * list; - static lv_style_t pagefont; - lv_style_init(&pagefont); - lv_style_set_text_font(&pagefont, LV_STATE_DEFAULT, defaultFont); + // lv_style_list_t * list; + // static lv_style_t pagefont; + // lv_style_init(&pagefont); + // lv_style_set_text_font(&pagefont, LV_STATE_DEFAULT, defaultFont); - list = lv_obj_get_style_list(lv_disp_get_layer_top(NULL), LV_OBJ_PART_MAIN); - _lv_style_list_add_style(list, &pagefont); + // list = lv_obj_get_style_list(lv_disp_get_layer_top(NULL), LV_OBJ_PART_MAIN); + // _lv_style_list_add_style(list, &pagefont); /* Create all screens using the theme */ for(uint8_t i = 0; i < (sizeof pages / sizeof *pages); i++) { pages[i] = lv_obj_create(NULL, NULL); - list = lv_obj_get_style_list(pages[i], LV_OBJ_PART_MAIN); - _lv_style_list_add_style(list, &pagefont); - // lv_obj_set_size(pages[0], hres, vres); + // list = lv_obj_get_style_list(pages[i], LV_OBJ_PART_MAIN); + // _lv_style_list_add_style(list, &pagefont); } #if HASP_USE_WIFI > 0 @@ -742,22 +723,8 @@ void haspNewObject(const JsonObject & config, uint8_t & saved_page_id) } } - /* Input cache and validation */ - // int16_t min = config[F("min")].as(); - // int16_t max = config[F("max")].as(); - // int16_t val = config[F("val")].as(); - // if(min >= max) { - // min = 0; - // max = 100; - //} - // bool enabled = config[F("enable")].as() | true; - // lv_coord_t width = config[F("w")].as(); - // lv_coord_t height = config[F("h")].as(); - // if(width == 0) width = 32; - // if(height == 0) height = 32; uint8_t objid = config[F("objid")].as(); uint8_t id = config[F("id")].as(); - // uint8_t styleid = config[F("styleid")].as(); /* Define Objects*/ lv_obj_t * obj = hasp_find_obj_from_id(parent_obj, id); @@ -770,9 +737,7 @@ void haspNewObject(const JsonObject & config, uint8_t & saved_page_id) /* ----- Basic Objects ------ */ case LV_HASP_BUTTON: { obj = lv_btn_create(parent_obj, NULL); - /* lv_obj_t * label ; */ lv_label_create(obj, NULL); - // haspSetOpacity(obj, LV_OPA_COVER); lv_obj_set_event_cb(obj, btn_event_handler); break; } diff --git a/src/hasp.h b/src/hasp.h index 74d7a40d..395dbe61 100644 --- a/src/hasp.h +++ b/src/hasp.h @@ -91,6 +91,7 @@ bool haspGetConfig(const JsonObject & settings); bool haspSetConfig(const JsonObject & settings); lv_obj_t * hasp_find_obj_from_id(lv_obj_t * parent, uint8_t objid); +lv_font_t * hasp_get_font(uint8_t fontid); void IRAM_ATTR btn_event_handler(lv_obj_t * obj, lv_event_t event); void IRAM_ATTR toggle_event_handler(lv_obj_t * obj, lv_event_t event); diff --git a/src/hasp_attr_get.cpp b/src/hasp_attr_get.cpp deleted file mode 100644 index 50514811..00000000 --- a/src/hasp_attr_get.cpp +++ /dev/null @@ -1,50 +0,0 @@ -#include "lvgl.h" -#include "hasp.h" -#include "hasp_attribute.h" -//#include "hasp_attr_get.h" - -#define LVGL7 1 - -bool haspGetObjAttribute(lv_obj_t * obj, String strAttr, std::string & strPayload) -{ - if(!obj) return false; - - switch(strAttr.length()) { - case 4: - - /* .txt and .val depend on objecttype */ - lv_obj_type_t list; - lv_obj_get_type(obj, &list); - - if(strAttr == F(".val")) { - if(check_obj_type(list.type[0], LV_HASP_PRELOADER)) return false; - - if(check_obj_type(list.type[0], LV_HASP_BUTTON)) { - - if(lv_btn_get_state(obj) == LV_BTN_STATE_CHECKED_PRESSED || - lv_btn_get_state(obj) == LV_BTN_STATE_CHECKED_RELEASED) - strPayload = "1"; // It's toggled - else - strPayload = "0"; // Normal btn has no toggle state - } - - if(check_obj_type(list.type[0], LV_HASP_SLIDER)) strPayload = String(lv_slider_get_value(obj)).c_str(); - if(check_obj_type(list.type[0], LV_HASP_GAUGE)) strPayload = String(lv_gauge_get_value(obj, 0)).c_str(); - if(check_obj_type(list.type[0], LV_HASP_BAR)) strPayload = String(lv_bar_get_value(obj)).c_str(); - if(check_obj_type(list.type[0], LV_HASP_LMETER)) - strPayload = String(lv_linemeter_get_value(obj)).c_str(); - // if(check_obj_type(list.type[0], LV_HASP_CPICKER)) strPayload = - // String(lv_cpicker_get_color(obj)).c_str(); - if(check_obj_type(list.type[0], LV_HASP_CHECKBOX)) - strPayload = String(!lv_checkbox_is_checked(obj) ? 0 : 1).c_str(); - if(check_obj_type(list.type[0], LV_HASP_DDLIST)) - strPayload = String(lv_dropdown_get_selected(obj)).c_str(); - if(check_obj_type(list.type[0], LV_HASP_ROLLER)) - strPayload = String(lv_roller_get_selected(obj)).c_str(); - - if(check_obj_type(list.type[0], LV_HASP_LED)) strPayload = String(lv_led_get_bright(obj)).c_str(); - if(check_obj_type(list.type[0], LV_HASP_SWITCH)) strPayload = String(lv_switch_get_state(obj)).c_str(); - } - } - return false; -} \ No newline at end of file diff --git a/src/hasp_attribute.cpp b/src/hasp_attribute.cpp index b23f9aed..fc27298e 100644 --- a/src/hasp_attribute.cpp +++ b/src/hasp_attribute.cpp @@ -120,9 +120,15 @@ static lv_color_t haspPayloadToColor(const char * payload) static lv_font_t * haspPayloadToFont(const char * payload) { - int16_t var = atoi(payload); + uint8_t var = atoi(payload); switch(var) { + case 0: + case 1: + case 2: + case 3: + return hasp_get_font(var); + case 8: return &unscii_8_icon; @@ -414,7 +420,7 @@ static void hasp_local_style_attr(lv_obj_t * obj, const char * attr_p, uint16_t if(font) { return lv_obj_set_style_local_text_font(obj, part, state, font); } else { - return Log.warning(F("HASP: Unknown Font ID %s"), attr_p); + return Log.warning(F("HASP: Unknown Font ID %s"), payload); } } From 7c966e7a2df6f6fbe1f14850d68a2bcb6834a4c0 Mon Sep 17 00:00:00 2001 From: fvanroie Date: Wed, 28 Oct 2020 14:54:59 +0100 Subject: [PATCH 16/33] Improve model reporting --- src/hasp_hal.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/hasp_hal.cpp b/src/hasp_hal.cpp index 0348fec9..121f9f2a 100644 --- a/src/hasp_hal.cpp +++ b/src/hasp_hal.cpp @@ -126,7 +126,10 @@ String halGetChipModel() { String model((char *)0); model.reserve(128); + +#if defined(STM32F4xx) model = F("STM32"); +#endif #if ESP8266 model = F("ESP8266"); @@ -148,7 +151,7 @@ String halGetChipModel() break; #endif default: - model = F("Unknown ESP"); + model = F("Unknown ESP32"); } model += F(" rev"); model += chip_info.revision; From ae6cad97c4a571d0193902c07554443dafe078ce Mon Sep 17 00:00:00 2001 From: fvanroie Date: Wed, 28 Oct 2020 18:00:49 +0100 Subject: [PATCH 17/33] Theme update --- include/lv_conf.h | 1 + src/hasp.cpp | 10 +- src/hasp_spiffs.cpp | 35 +- src/lv_theme_hasp.c | 994 +++++++++++++++++++++++++++++--------------- src/lv_theme_hasp.h | 31 +- 5 files changed, 712 insertions(+), 359 deletions(-) diff --git a/include/lv_conf.h b/include/lv_conf.h index 85829f49..575cf008 100644 --- a/include/lv_conf.h +++ b/include/lv_conf.h @@ -402,6 +402,7 @@ typedef void* lv_font_user_data_t; #define LV_USE_THEME_EMPTY 1 #define LV_USE_THEME_TEMPLATE 1 +#define LV_USE_THEME_HASP 1 /*================= * Text settings diff --git a/src/hasp.cpp b/src/hasp.cpp index e8b08a7b..1745986c 100644 --- a/src/hasp.cpp +++ b/src/hasp.cpp @@ -24,6 +24,7 @@ //#include "hasp_attr_get.h" #include "hasp_attribute.h" #include "hasp.h" +#include "lv_theme_hasp.h" #include "EEPROM.h" @@ -358,7 +359,7 @@ void haspSetup() #if defined(ARDUINO_ARCH_ESP32) || defined(ARDUINO_ARCH_ESP8266) lv_zifont_init(); - if(lv_zifont_font_init(&haspFonts[0], haspZiFontPath, 24) != 0) { + if(lv_zifont_font_init(&haspFonts[0], haspZiFontPath, 32) != 0) { Log.error(F("HASP: Failed to set font to %s"), haspZiFontPath); haspFonts[0] = LV_FONT_DEFAULT; } else { @@ -416,10 +417,11 @@ void haspSetup() th = lv_theme_templ_init(haspThemeHue, defaultFont); // lightweight, not for production... break; #endif -#if(LV_USE_THEME_HASP == 1) || (LV_USE_THEME_TEMPLATE == 1) +#if(LV_USE_THEME_HASP == 1) case 8: - th = lv_theme_template_init(LV_COLOR_PURPLE, LV_COLOR_ORANGE, LV_THEME_DEFAULT_FLAGS, haspFonts[0], - haspFonts[1], haspFonts[2], haspFonts[3]); + th = lv_theme_hasp_init(lv_color_hsv_to_rgb(haspThemeHue, 100, 100), + lv_color_hsv_to_rgb(haspThemeHue, 100, 100), LV_THEME_DEFAULT_FLAGS, haspFonts[0], + haspFonts[1], haspFonts[2], haspFonts[3]); break; #endif /* case 0: diff --git a/src/hasp_spiffs.cpp b/src/hasp_spiffs.cpp index b916b07a..30c58a56 100644 --- a/src/hasp_spiffs.cpp +++ b/src/hasp_spiffs.cpp @@ -5,7 +5,7 @@ #include "hasp_conf.h" #include "hasp_spiffs.h" -#if HASP_USE_SPIFFS>0 +#if HASP_USE_SPIFFS > 0 #if defined(ARDUINO_ARCH_ESP32) #include "SPIFFS.h" #endif @@ -69,20 +69,31 @@ void spiffsInfo() void spiffsList() { - Log.verbose(F("FILE: Listing files on the internal flash:")); +#if HASP_USE_SPIFFS > 0 +#if defined(ARDUINO_ARCH_ESP8266) + if(!SPIFFS.begin()) { +#else + if(!SPIFFS.begin(true)) { +#endif + Log.error(F("FILE: Flash file system not mouted.")); + } else { + + Log.verbose(F("FILE: Listing files on the internal flash:")); #if defined(ARDUINO_ARCH_ESP32) - File root = SPIFFS.open("/"); - File file = root.openNextFile(); - while(file) { - Log.verbose(F("FILE: * %s (%u bytes)"), file.name(), (uint32_t)file.size()); - file = root.openNextFile(); - } + File root = SPIFFS.open("/"); + File file = root.openNextFile(); + while(file) { + Log.verbose(F("FILE: * %s (%u bytes)"), file.name(), (uint32_t)file.size()); + file = root.openNextFile(); + } #endif #if defined(ARDUINO_ARCH_ESP8266) - Dir dir = SPIFFS.openDir("/"); - while(dir.next()) { - Log.notice(F("FILE: * %s (%u bytes)"), dir.fileName().c_str(), (uint32_t)dir.fileSize()); + Dir dir = SPIFFS.openDir("/"); + while(dir.next()) { + Log.notice(F("FILE: * %s (%u bytes)"), dir.fileName().c_str(), (uint32_t)dir.fileSize()); + } +#endif } #endif } @@ -91,7 +102,7 @@ void spiffsSetup() { // no SPIFFS settings, as settings depend on SPIFFS -#if HASP_USE_SPIFFS>0 +#if HASP_USE_SPIFFS > 0 #if defined(ARDUINO_ARCH_ESP8266) if(!SPIFFS.begin()) { #else diff --git a/src/lv_theme_hasp.c b/src/lv_theme_hasp.c index 5fa2b79b..6f755dd7 100644 --- a/src/lv_theme_hasp.c +++ b/src/lv_theme_hasp.c @@ -6,10 +6,16 @@ /********************* * INCLUDES *********************/ -#include "lv_themes/lv_theme.h" +#include "lvgl.h" /*To see all the widgets*/ #if LV_USE_THEME_HASP +#include "lv_misc/lv_gc.h" + +#if defined(LV_GC_INCLUDE) +#include LV_GC_INCLUDE +#endif /* LV_ENABLE_GC */ + /********************* * DEFINES *********************/ @@ -18,29 +24,30 @@ * TYPEDEFS **********************/ +typedef struct +{ + lv_style_t bg; + lv_style_t btn; + lv_style_t round; + lv_style_t color; + lv_style_t gray; + lv_style_t tick_line; + lv_style_t tight; +} theme_styles_t; + /********************** * STATIC PROTOTYPES **********************/ +static void theme_apply(lv_theme_t * th, lv_obj_t * obj, lv_theme_style_t name); /********************** * STATIC VARIABLES **********************/ + static lv_theme_t theme; -static lv_style_t def; -static lv_style_t scr; +static theme_styles_t * styles; -/*Static style definitions*/ -static lv_style_t sb; -static lv_style_t plain_bordered; -static lv_style_t label_prim; -static lv_style_t label_sec; -static lv_style_t label_hint; - -// static lv_style_t btn_rel, btn_pr, btn_trel, btn_tpr, btn_ina; - -/*Saved input parameters*/ -static uint16_t _hue; -static lv_font_t * _font; +static bool inited; /********************** * MACROS @@ -49,121 +56,66 @@ static lv_font_t * _font; /********************** * STATIC FUNCTIONS **********************/ +static void style_init_reset(lv_style_t * style); static void basic_init(void) { - lv_style_plain.text.font = _font; - lv_style_pretty.text.font = _font; - lv_style_pretty_color.text.font = _font; + style_init_reset(&styles->bg); + lv_style_set_bg_opa(&styles->bg, LV_STATE_DEFAULT, LV_OPA_COVER); + lv_style_set_border_width(&styles->bg, LV_STATE_DEFAULT, 1); + lv_style_set_border_width(&styles->bg, LV_STATE_FOCUSED, 2); + lv_style_set_border_color(&styles->bg, LV_STATE_FOCUSED, theme.color_secondary); + lv_style_set_border_color(&styles->bg, LV_STATE_EDITED, lv_color_darken(theme.color_secondary, LV_OPA_30)); + lv_style_set_line_width(&styles->bg, LV_STATE_DEFAULT, 1); + lv_style_set_scale_end_line_width(&styles->bg, LV_STATE_DEFAULT, 1); + lv_style_set_scale_end_color(&styles->bg, LV_STATE_DEFAULT, theme.color_primary); + lv_style_set_text_color(&styles->bg, LV_STATE_DEFAULT, LV_COLOR_BLACK); + lv_style_set_text_font(&styles->bg, LV_STATE_DEFAULT, theme.font_normal); + lv_style_set_pad_left(&styles->bg, LV_STATE_DEFAULT, LV_DPI / 10); + lv_style_set_pad_right(&styles->bg, LV_STATE_DEFAULT, LV_DPI / 10); + lv_style_set_pad_top(&styles->bg, LV_STATE_DEFAULT, LV_DPI / 10); + lv_style_set_pad_bottom(&styles->bg, LV_STATE_DEFAULT, LV_DPI / 10); + lv_style_set_pad_inner(&styles->bg, LV_STATE_DEFAULT, LV_DPI / 10); + lv_style_set_value_font(&styles->bg, LV_STATE_DEFAULT, theme.font_normal); - lv_style_btn_rel.text.font = _font; - lv_style_btn_pr.text.font = _font; - lv_style_btn_tgl_rel.text.font = _font; - lv_style_btn_tgl_pr.text.font = _font; - lv_style_btn_ina.text.font = _font; + style_init_reset(&styles->btn); + lv_style_set_bg_color(&styles->btn, LV_STATE_PRESSED, lv_color_hex3(0xccc)); + lv_style_set_bg_color(&styles->btn, LV_STATE_CHECKED, theme.color_primary); + lv_style_set_bg_color(&styles->btn, LV_STATE_CHECKED | LV_STATE_PRESSED, + lv_color_darken(theme.color_primary, LV_OPA_30)); + lv_style_set_bg_color(&styles->btn, LV_STATE_DISABLED, LV_COLOR_SILVER); + lv_style_set_text_color(&styles->btn, LV_STATE_DISABLED, LV_COLOR_GRAY); + lv_style_set_image_recolor(&styles->btn, LV_STATE_DISABLED, LV_COLOR_GRAY); - if(_hue <= 360) { - lv_style_pretty_color.body.main_color = lv_color_hsv_to_rgb(_hue, 10, 70); - lv_style_pretty_color.body.grad_color = lv_color_hsv_to_rgb(_hue, 80, 80); + style_init_reset(&styles->round); + lv_style_set_radius(&styles->round, LV_STATE_DEFAULT, LV_RADIUS_CIRCLE); - lv_style_plain_color.body.main_color = lv_color_hsv_to_rgb(_hue, 50, 75); - lv_style_plain_color.body.grad_color = lv_style_plain_color.body.main_color; + style_init_reset(&styles->color); + lv_style_set_bg_color(&styles->color, LV_STATE_DEFAULT, theme.color_primary); + lv_style_set_line_color(&styles->color, LV_STATE_DEFAULT, theme.color_primary); - lv_style_btn_rel.body.main_color = lv_color_hsv_to_rgb(_hue, 10, 70); - lv_style_btn_rel.body.grad_color = lv_color_hsv_to_rgb(_hue, 80, 80); + style_init_reset(&styles->gray); + lv_style_set_bg_color(&styles->gray, LV_STATE_DEFAULT, LV_COLOR_SILVER); + lv_style_set_line_color(&styles->gray, LV_STATE_DEFAULT, LV_COLOR_SILVER); + lv_style_set_text_color(&styles->gray, LV_STATE_DEFAULT, LV_COLOR_GRAY); - lv_style_btn_pr.body.main_color = lv_color_hsv_to_rgb(_hue, 80, 70); - lv_style_btn_pr.body.grad_color = lv_color_hsv_to_rgb(_hue, 10, 80); + style_init_reset(&styles->tick_line); + lv_style_set_line_width(&styles->tick_line, LV_STATE_DEFAULT, 5); + lv_style_set_scale_end_line_width(&styles->tick_line, LV_STATE_DEFAULT, 5); + lv_style_set_scale_end_color(&styles->tick_line, LV_STATE_DEFAULT, theme.color_primary); - lv_style_btn_tgl_rel.body.main_color = lv_color_hsv_to_rgb(_hue, 80, 70); - lv_style_btn_tgl_rel.body.grad_color = lv_color_hsv_to_rgb(_hue, 10, 80); - - lv_style_btn_tgl_pr.body.main_color = lv_color_hsv_to_rgb(_hue, 10, 70); - lv_style_btn_tgl_pr.body.grad_color = lv_color_hsv_to_rgb(_hue, 80, 80); - } - - lv_style_copy(&def, &lv_style_pretty); /*Initialize the default style*/ - def.text.font = _font; - - lv_style_copy(&scr, &def); - scr.body.padding.bottom = 0; - scr.body.padding.top = 0; - scr.body.padding.left = 0; - scr.body.padding.right = 0; - - lv_style_copy(&sb, &lv_style_pretty_color); - sb.body.grad_color = sb.body.main_color; - sb.body.padding.right = sb.body.padding.right / 2; /*Make closer to the edges*/ - sb.body.padding.bottom = sb.body.padding.bottom / 2; - - lv_style_copy(&plain_bordered, &lv_style_plain); - plain_bordered.body.border.width = 2; - plain_bordered.body.border.color = lv_color_hex3(0xbbb); - - theme.style.bg = &lv_style_plain; - theme.style.scr = &scr; - theme.style.panel = &lv_style_pretty; + style_init_reset(&styles->tight); + lv_style_set_pad_left(&styles->tight, LV_STATE_DEFAULT, 0); + lv_style_set_pad_right(&styles->tight, LV_STATE_DEFAULT, 0); + lv_style_set_pad_top(&styles->tight, LV_STATE_DEFAULT, 0); + lv_style_set_pad_bottom(&styles->tight, LV_STATE_DEFAULT, 0); + lv_style_set_pad_inner(&styles->tight, LV_STATE_DEFAULT, 0); } -static void btn_init(void) +static void arc_init(void) { -#if LV_USE_BTN != 0 - theme.style.btn.rel = &lv_style_btn_rel; - theme.style.btn.pr = &lv_style_btn_pr; - theme.style.btn.tgl_rel = &lv_style_btn_tgl_rel; - theme.style.btn.tgl_pr = &lv_style_btn_tgl_pr; - theme.style.btn.ina = &lv_style_btn_ina; -#endif -} +#if LV_USE_ARC != 0 -static void label_init(void) -{ -#if LV_USE_LABEL != 0 - - lv_style_copy(&label_prim, &lv_style_plain); - lv_style_copy(&label_sec, &lv_style_plain); - lv_style_copy(&label_hint, &lv_style_plain); - - label_prim.text.color = lv_color_hex3(0x111); - label_sec.text.color = lv_color_hex3(0x888); - label_hint.text.color = lv_color_hex3(0xaaa); - - theme.style.label.prim = &label_prim; - theme.style.label.sec = &label_sec; - theme.style.label.hint = &label_hint; -#endif -} - -static void img_init(void) -{ -#if LV_USE_IMG != 0 - - theme.style.img.light = &def; - theme.style.img.dark = &def; -#endif -} - -static void line_init(void) -{ -#if LV_USE_LINE != 0 - - theme.style.line.decor = &def; -#endif -} - -static void led_init(void) -{ -#if LV_USE_LED != 0 - static lv_style_t led; - - lv_style_copy(&led, &lv_style_pretty_color); - led.body.shadow.width = LV_DPI / 10; - led.body.radius = LV_RADIUS_CIRCLE; - led.body.border.width = LV_DPI / 30; - led.body.border.opa = LV_OPA_30; - led.body.shadow.color = led.body.main_color; - - theme.style.led = &led; #endif } @@ -171,79 +123,27 @@ static void bar_init(void) { #if LV_USE_BAR - theme.style.bar.bg = &lv_style_pretty; - theme.style.bar.indic = &lv_style_pretty_color; #endif } -static void slider_init(void) +static void btn_init(void) { -#if LV_USE_SLIDER != 0 - static lv_style_t slider_bg; - lv_style_copy(&slider_bg, &lv_style_pretty); - slider_bg.body.padding.left = LV_DPI / 20; - slider_bg.body.padding.right = LV_DPI / 20; - slider_bg.body.padding.top = LV_DPI / 20; - slider_bg.body.padding.bottom = LV_DPI / 20; +#if LV_USE_BTN != 0 - theme.style.slider.bg = &slider_bg; - theme.style.slider.indic = &lv_style_pretty_color; - theme.style.slider.knob = &lv_style_pretty; #endif } -static void sw_init(void) +static void btnmatrix_init(void) { -#if LV_USE_SW != 0 - static lv_style_t sw_indic, sw_bg; - lv_style_copy(&sw_indic, &lv_style_pretty_color); - sw_indic.body.padding.left = -0; - sw_indic.body.padding.right = -0; - sw_indic.body.padding.top = -0; - sw_indic.body.padding.bottom = -0; - sw_indic.body.padding.inner = -0; +#if LV_USE_BTNMATRIX - lv_style_copy(&sw_bg, &lv_style_pretty); - sw_bg.body.padding.left = -0; - sw_bg.body.padding.right = -0; - sw_bg.body.padding.top = -0; - sw_bg.body.padding.bottom = -0; - sw_bg.body.padding.inner = -0; - - theme.style.sw.bg = &sw_bg; - theme.style.sw.indic = &sw_indic; - theme.style.sw.knob_off = &lv_style_pretty; - theme.style.sw.knob_on = &lv_style_pretty; #endif } -static void lmeter_init(void) +static void calendar_init(void) { -#if LV_USE_LMETER != 0 - static lv_style_t lmeter; - lv_style_copy(&lmeter, &lv_style_pretty_color); - lmeter.line.color = lv_color_hex3(0xddd); - lmeter.line.width = 2; - lmeter.body.main_color = lv_color_mix(lmeter.body.main_color, LV_COLOR_WHITE, LV_OPA_50); - lmeter.body.grad_color = lv_color_mix(lmeter.body.grad_color, LV_COLOR_BLACK, LV_OPA_50); +#if LV_USE_CALENDAR - theme.style.lmeter = &lmeter; -#endif -} - -static void gauge_init(void) -{ -#if LV_USE_GAUGE != 0 - static lv_style_t gauge; - lv_style_copy(&gauge, theme.style.lmeter); - gauge.line.color = theme.style.lmeter->body.grad_color; - gauge.line.width = 2; - gauge.body.main_color = lv_color_hex3(0x888); - gauge.body.grad_color = theme.style.lmeter->body.main_color; - gauge.text.color = lv_color_hex3(0x888); - gauge.text.font = _font; - - theme.style.gauge = &gauge; #endif } @@ -251,57 +151,69 @@ static void chart_init(void) { #if LV_USE_CHART - theme.style.chart = &lv_style_pretty; #endif } -static void cb_init(void) +static void cpicker_init(void) { -#if LV_USE_CB != 0 +#if LV_USE_CPICKER - theme.style.cb.bg = &lv_style_transp; - theme.style.cb.box.rel = &lv_style_pretty; - theme.style.cb.box.pr = &lv_style_btn_pr; - theme.style.cb.box.tgl_rel = &lv_style_btn_tgl_rel; - theme.style.cb.box.tgl_pr = &lv_style_btn_tgl_pr; - theme.style.cb.box.ina = &lv_style_btn_ina; #endif } -static void btnm_init(void) +static void checkbox_init(void) { -#if LV_USE_BTNM +#if LV_USE_CHECKBOX != 0 - theme.style.btnm.bg = &lv_style_pretty; - theme.style.btnm.btn.rel = &lv_style_btn_rel; - theme.style.btnm.btn.pr = &lv_style_btn_pr; - theme.style.btnm.btn.tgl_rel = &lv_style_btn_tgl_rel; - theme.style.btnm.btn.tgl_pr = &lv_style_btn_tgl_pr; - theme.style.btnm.btn.ina = &lv_style_btn_ina; #endif } -static void kb_init(void) +static void cont_init(void) { -#if LV_USE_KB +#if LV_USE_CONT != 0 - theme.style.kb.bg = &lv_style_pretty; - theme.style.kb.btn.rel = &lv_style_btn_rel; - theme.style.kb.btn.pr = &lv_style_btn_pr; - theme.style.kb.btn.tgl_rel = &lv_style_btn_tgl_rel; - theme.style.kb.btn.tgl_pr = &lv_style_btn_tgl_pr; - theme.style.kb.btn.ina = &lv_style_btn_ina; #endif } -static void mbox_init(void) +static void gauge_init(void) { -#if LV_USE_MBOX +#if LV_USE_GAUGE != 0 + +#endif +} + +static void img_init(void) +{ +#if LV_USE_IMG != 0 + +#endif +} + +static void label_init(void) +{ +#if LV_USE_LABEL != 0 + +#endif +} + +static void linemeter_init(void) +{ +#if LV_USE_LINEMETER != 0 + +#endif +} + +static void line_init(void) +{ +#if LV_USE_LINE != 0 + +#endif +} + +static void led_init(void) +{ +#if LV_USE_LED != 0 - theme.style.mbox.bg = &lv_style_pretty; - theme.style.mbox.btn.bg = &lv_style_transp; - theme.style.mbox.btn.rel = &lv_style_btn_rel; - theme.style.mbox.btn.pr = &lv_style_btn_tgl_pr; #endif } @@ -309,20 +221,55 @@ static void page_init(void) { #if LV_USE_PAGE - theme.style.page.bg = &lv_style_pretty; - theme.style.page.scrl = &lv_style_transp_tight; - theme.style.page.sb = &sb; #endif } -static void ta_init(void) +static void slider_init(void) { -#if LV_USE_TA +#if LV_USE_SLIDER != 0 + +#endif +} + +static void switch_init(void) +{ +#if LV_USE_SWITCH != 0 + +#endif +} + +static void spinbox_init(void) +{ +#if LV_USE_SPINBOX + +#endif +} + +static void spinner_init(void) +{ +#if LV_USE_SPINNER != 0 + +#endif +} + +static void keyboard_init(void) +{ +#if LV_USE_KEYBOARD + +#endif +} + +static void msgbox_init(void) +{ +#if LV_USE_MSGBOX + +#endif +} + +static void textarea_init(void) +{ +#if LV_USE_TEXTAREA - theme.style.ta.area = &lv_style_pretty; - theme.style.ta.oneline = &lv_style_pretty; - theme.style.ta.cursor = NULL; - theme.style.ta.sb = &sb; #endif } @@ -330,24 +277,13 @@ static void list_init(void) { #if LV_USE_LIST != 0 - theme.style.list.bg = &lv_style_pretty; - theme.style.list.scrl = &lv_style_transp_fit; - theme.style.list.sb = &sb; - theme.style.list.btn.rel = &lv_style_btn_rel; - theme.style.list.btn.pr = &lv_style_btn_pr; - theme.style.list.btn.tgl_rel = &lv_style_btn_tgl_rel; - theme.style.list.btn.tgl_pr = &lv_style_btn_tgl_pr; - theme.style.list.btn.ina = &lv_style_btn_ina; #endif } static void ddlist_init(void) { -#if LV_USE_DDLIST != 0 +#if LV_USE_DROPDOWN != 0 - theme.style.ddlist.bg = &lv_style_pretty; - theme.style.ddlist.sel = &lv_style_plain_color; - theme.style.ddlist.sb = &sb; #endif } @@ -355,8 +291,6 @@ static void roller_init(void) { #if LV_USE_ROLLER != 0 - theme.style.roller.bg = &lv_style_pretty; - theme.style.roller.sel = &lv_style_plain_color; #endif } @@ -364,21 +298,19 @@ static void tabview_init(void) { #if LV_USE_TABVIEW != 0 - theme.style.tabview.bg = &plain_bordered; - theme.style.tabview.indic = &lv_style_plain_color; - theme.style.tabview.btn.bg = &lv_style_transp; - theme.style.tabview.btn.rel = &lv_style_btn_rel; - theme.style.tabview.btn.pr = &lv_style_btn_pr; - theme.style.tabview.btn.tgl_rel = &lv_style_btn_tgl_rel; - theme.style.tabview.btn.tgl_pr = &lv_style_btn_tgl_pr; +#endif +} + +static void tileview_init(void) +{ +#if LV_USE_TILEVIEW != 0 #endif } static void table_init(void) { #if LV_USE_TABLE != 0 - theme.style.table.bg = &lv_style_transp_tight; - theme.style.table.cell = &lv_style_plain; + #endif } @@ -386,134 +318,542 @@ static void win_init(void) { #if LV_USE_WIN != 0 - theme.style.win.bg = &plain_bordered; - theme.style.win.sb = &sb; - theme.style.win.header = &lv_style_plain_color; - theme.style.win.content = &lv_style_transp; - theme.style.win.btn.rel = &lv_style_btn_rel; - theme.style.win.btn.pr = &lv_style_btn_pr; #endif } -#if LV_USE_GROUP - -static void style_mod(lv_group_t * group, lv_style_t * style) -{ - (void)group; /*Unused*/ -#if LV_COLOR_DEPTH != 1 - /*Make the style to be a little bit orange*/ - style->body.border.opa = LV_OPA_COVER; - style->body.border.color = LV_COLOR_ORANGE; - - /*If not empty or has border then emphasis the border*/ - if(style->body.opa != LV_OPA_TRANSP || style->body.border.width != 0) style->body.border.width = LV_DPI / 20; - - style->body.main_color = lv_color_mix(style->body.main_color, LV_COLOR_ORANGE, LV_OPA_70); - style->body.grad_color = lv_color_mix(style->body.grad_color, LV_COLOR_ORANGE, LV_OPA_70); - style->body.shadow.color = lv_color_mix(style->body.shadow.color, LV_COLOR_ORANGE, LV_OPA_60); - - style->text.color = lv_color_mix(style->text.color, LV_COLOR_ORANGE, LV_OPA_70); -#else - style->body.border.opa = LV_OPA_COVER; - style->body.border.color = LV_COLOR_BLACK; - style->body.border.width = 2; -#endif -} - -static void style_mod_edit(lv_group_t * group, lv_style_t * style) -{ - (void)group; /*Unused*/ -#if LV_COLOR_DEPTH != 1 - /*Make the style to be a little bit orange*/ - style->body.border.opa = LV_OPA_COVER; - style->body.border.color = LV_COLOR_GREEN; - - /*If not empty or has border then emphasis the border*/ - if(style->body.opa != LV_OPA_TRANSP || style->body.border.width != 0) style->body.border.width = LV_DPI / 20; - - style->body.main_color = lv_color_mix(style->body.main_color, LV_COLOR_GREEN, LV_OPA_70); - style->body.grad_color = lv_color_mix(style->body.grad_color, LV_COLOR_GREEN, LV_OPA_70); - style->body.shadow.color = lv_color_mix(style->body.shadow.color, LV_COLOR_GREEN, LV_OPA_60); - - style->text.color = lv_color_mix(style->text.color, LV_COLOR_GREEN, LV_OPA_70); -#else - style->body.border.opa = LV_OPA_COVER; - style->body.border.color = LV_COLOR_BLACK; - style->body.border.width = 3; -#endif -} - -#endif /*LV_USE_GROUP*/ - /********************** * GLOBAL FUNCTIONS **********************/ /** - * Initialize the default theme - * @param hue [0..360] hue value from HSV color space to define the theme's base color - * @param font pointer to a font (NULL to use the default) - * @return pointer to the initialized theme + * Initialize the default + * @param color_primary the primary color of the theme + * @param color_secondary the secondary color for the theme + * @param flags ORed flags starting with `LV_THEME_DEF_FLAG_...` + * @param font_small pointer to a small font + * @param font_normal pointer to a normal font + * @param font_subtitle pointer to a large font + * @param font_title pointer to a extra large font + * @return a pointer to reference this theme later */ -lv_theme_t * lv_theme_hasp_init(uint16_t hue, lv_font_t * font) +lv_theme_t * lv_theme_hasp_init(lv_color_t color_primary, lv_color_t color_secondary, uint32_t flags, + const lv_font_t * font_small, const lv_font_t * font_normal, + const lv_font_t * font_subtitle, const lv_font_t * font_title) { - if(font == NULL) font = LV_FONT_DEFAULT; - _hue = hue; - _font = font; - - /*For backward compatibility initialize all theme elements with a default style */ - uint16_t i; - lv_style_t ** style_p = (lv_style_t **)&theme.style; - for(i = 0; i < LV_THEME_STYLE_COUNT; i++) { - *style_p = &def; - style_p++; + /* This trick is required only to avoid the garbage collection of + * styles' data if LVGL is used in a binding (e.g. Micropython) + * In a general case styles could be simple `static lv_style_t my style` variables or allocated directly into + * `styles`*/ + if(!inited) { +#if defined(LV_GC_INCLUDE) + LV_GC_ROOT(_lv_theme_template_styles) = lv_mem_alloc(sizeof(theme_styles_t)); + styles = (theme_styles_t *)LV_GC_ROOT(_lv_theme_template_styles); +#else + styles = lv_mem_alloc(sizeof(theme_styles_t)); +#endif } + theme.color_primary = color_primary; + theme.color_secondary = color_secondary; + theme.font_small = font_small; + theme.font_normal = font_normal; + theme.font_subtitle = font_subtitle; + theme.font_title = font_title; + theme.flags = flags; + basic_init(); + cont_init(); btn_init(); label_init(); + bar_init(); img_init(); line_init(); led_init(); - bar_init(); slider_init(); - sw_init(); - lmeter_init(); + switch_init(); + linemeter_init(); gauge_init(); + arc_init(); + spinner_init(); chart_init(); - cb_init(); - btnm_init(); - kb_init(); - mbox_init(); + calendar_init(); + cpicker_init(); + checkbox_init(); + btnmatrix_init(); + keyboard_init(); + msgbox_init(); page_init(); - ta_init(); + textarea_init(); + spinbox_init(); list_init(); ddlist_init(); roller_init(); tabview_init(); + tileview_init(); table_init(); win_init(); -#if LV_USE_GROUP - theme.group.style_mod_xcb = style_mod; - theme.group.style_mod_edit_xcb = style_mod_edit; -#endif + theme.apply_xcb = NULL; + theme.apply_cb = theme_apply; return &theme; } -/** - * Get a pointer to the theme - * @return pointer to the theme - */ -lv_theme_t * lv_theme_get_hasp(void) +void theme_apply(lv_theme_t * th, lv_obj_t * obj, lv_theme_style_t name) { - return &theme; + LV_UNUSED(th); + + lv_style_list_t * list; + + switch(name) { + case LV_THEME_NONE: + break; + + case LV_THEME_SCR: + list = lv_obj_get_style_list(obj, LV_OBJ_PART_MAIN); + _lv_style_list_add_style(list, &styles->bg); + _lv_style_list_add_style(list, &styles->tight); + break; + case LV_THEME_OBJ: + list = lv_obj_get_style_list(obj, LV_OBJ_PART_MAIN); + _lv_style_list_add_style(list, &styles->bg); + break; +#if LV_USE_CONT + case LV_THEME_CONT: + list = lv_obj_get_style_list(obj, LV_CONT_PART_MAIN); + _lv_style_list_add_style(list, &styles->bg); + break; +#endif + +#if LV_USE_BTN + case LV_THEME_BTN: + list = lv_obj_get_style_list(obj, LV_BTN_PART_MAIN); + _lv_style_list_add_style(list, &styles->bg); + _lv_style_list_add_style(list, &styles->btn); + break; +#endif + +#if LV_USE_BTNMATRIX + case LV_THEME_BTNMATRIX: + list = lv_obj_get_style_list(obj, LV_BTNMATRIX_PART_BG); + _lv_style_list_add_style(list, &styles->bg); + + list = lv_obj_get_style_list(obj, LV_BTNMATRIX_PART_BTN); + _lv_style_list_add_style(list, &styles->bg); + _lv_style_list_add_style(list, &styles->btn); + break; +#endif + +#if LV_USE_KEYBOARD + case LV_THEME_KEYBOARD: + list = lv_obj_get_style_list(obj, LV_KEYBOARD_PART_BG); + _lv_style_list_add_style(list, &styles->bg); + + list = lv_obj_get_style_list(obj, LV_KEYBOARD_PART_BTN); + _lv_style_list_add_style(list, &styles->bg); + _lv_style_list_add_style(list, &styles->btn); + break; +#endif + +#if LV_USE_BAR + case LV_THEME_BAR: + list = lv_obj_get_style_list(obj, LV_BAR_PART_BG); + _lv_style_list_add_style(list, &styles->bg); + _lv_style_list_add_style(list, &styles->tight); + + list = lv_obj_get_style_list(obj, LV_BAR_PART_INDIC); + _lv_style_list_add_style(list, &styles->bg); + _lv_style_list_add_style(list, &styles->color); + break; +#endif + +#if LV_USE_SWITCH + case LV_THEME_SWITCH: + list = lv_obj_get_style_list(obj, LV_SWITCH_PART_BG); + _lv_style_list_add_style(list, &styles->bg); + _lv_style_list_add_style(list, &styles->tight); + _lv_style_list_add_style(list, &styles->round); + + list = lv_obj_get_style_list(obj, LV_SWITCH_PART_INDIC); + _lv_style_list_add_style(list, &styles->bg); + _lv_style_list_add_style(list, &styles->color); + + list = lv_obj_get_style_list(obj, LV_SWITCH_PART_KNOB); + _lv_style_list_add_style(list, &styles->bg); + _lv_style_list_add_style(list, &styles->tight); + _lv_style_list_add_style(list, &styles->round); + break; +#endif + +#if LV_USE_CANVAS + case LV_THEME_CANVAS: + list = lv_obj_get_style_list(obj, LV_CANVAS_PART_MAIN); + break; +#endif + +#if LV_USE_IMG + case LV_THEME_IMAGE: + list = lv_obj_get_style_list(obj, LV_IMG_PART_MAIN); + break; +#endif + +#if LV_USE_IMGBTN + case LV_THEME_IMGBTN: + list = lv_obj_get_style_list(obj, LV_IMG_PART_MAIN); + break; +#endif + +#if LV_USE_LABEL + case LV_THEME_LABEL: + list = lv_obj_get_style_list(obj, LV_LABEL_PART_MAIN); + break; +#endif + +#if LV_USE_LINE + case LV_THEME_LINE: + list = lv_obj_get_style_list(obj, LV_LABEL_PART_MAIN); + break; +#endif + +#if LV_USE_ARC + case LV_THEME_ARC: + list = lv_obj_get_style_list(obj, LV_ARC_PART_BG); + _lv_style_list_add_style(list, &styles->bg); + _lv_style_list_add_style(list, &styles->tick_line); + _lv_style_list_add_style(list, &styles->round); + + list = lv_obj_get_style_list(obj, LV_ARC_PART_INDIC); + _lv_style_list_add_style(list, &styles->bg); + _lv_style_list_add_style(list, &styles->color); + _lv_style_list_add_style(list, &styles->tick_line); + break; +#endif + +#if LV_USE_SPINNER + case LV_THEME_SPINNER: + list = lv_obj_get_style_list(obj, LV_SPINNER_PART_BG); + _lv_style_list_add_style(list, &styles->bg); + _lv_style_list_add_style(list, &styles->tick_line); + + list = lv_obj_get_style_list(obj, LV_SPINNER_PART_INDIC); + _lv_style_list_add_style(list, &styles->bg); + _lv_style_list_add_style(list, &styles->color); + _lv_style_list_add_style(list, &styles->tick_line); + break; +#endif + +#if LV_USE_SLIDER + case LV_THEME_SLIDER: + list = lv_obj_get_style_list(obj, LV_SLIDER_PART_BG); + _lv_style_list_add_style(list, &styles->bg); + + list = lv_obj_get_style_list(obj, LV_SLIDER_PART_INDIC); + _lv_style_list_add_style(list, &styles->bg); + _lv_style_list_add_style(list, &styles->color); + + list = lv_obj_get_style_list(obj, LV_SLIDER_PART_KNOB); + _lv_style_list_add_style(list, &styles->bg); + _lv_style_list_add_style(list, &styles->round); + break; +#endif + +#if LV_USE_CHECKBOX + case LV_THEME_CHECKBOX: + list = lv_obj_get_style_list(obj, LV_CHECKBOX_PART_BG); + + list = lv_obj_get_style_list(obj, LV_CHECKBOX_PART_BULLET); + _lv_style_list_add_style(list, &styles->bg); + _lv_style_list_add_style(list, &styles->btn); + break; +#endif + +#if LV_USE_MSGBOX + case LV_THEME_MSGBOX: + list = lv_obj_get_style_list(obj, LV_MSGBOX_PART_BG); + _lv_style_list_add_style(list, &styles->bg); + break; + + case LV_THEME_MSGBOX_BTNS: + list = lv_obj_get_style_list(obj, LV_MSGBOX_PART_BTN_BG); + _lv_style_list_add_style(list, &styles->bg); + + list = lv_obj_get_style_list(obj, LV_MSGBOX_PART_BTN); + _lv_style_list_add_style(list, &styles->bg); + _lv_style_list_add_style(list, &styles->btn); + break; + +#endif +#if LV_USE_LED + case LV_THEME_LED: + list = lv_obj_get_style_list(obj, LV_LED_PART_MAIN); + _lv_style_list_add_style(list, &styles->bg); + _lv_style_list_add_style(list, &styles->color); + _lv_style_list_add_style(list, &styles->round); + break; +#endif +#if LV_USE_PAGE + case LV_THEME_PAGE: + list = lv_obj_get_style_list(obj, LV_PAGE_PART_BG); + _lv_style_list_add_style(list, &styles->bg); + _lv_style_list_add_style(list, &styles->gray); + + list = lv_obj_get_style_list(obj, LV_PAGE_PART_SCROLLABLE); + _lv_style_list_add_style(list, &styles->bg); + + list = lv_obj_get_style_list(obj, LV_PAGE_PART_SCROLLBAR); + _lv_style_list_add_style(list, &styles->bg); + break; +#endif +#if LV_USE_TABVIEW + case LV_THEME_TABVIEW: + list = lv_obj_get_style_list(obj, LV_TABVIEW_PART_BG); + _lv_style_list_add_style(list, &styles->bg); + + list = lv_obj_get_style_list(obj, LV_TABVIEW_PART_BG_SCRLLABLE); + _lv_style_list_add_style(list, &styles->bg); + _lv_style_list_add_style(list, &styles->color); + + list = lv_obj_get_style_list(obj, LV_TABVIEW_PART_TAB_BG); + _lv_style_list_add_style(list, &styles->bg); + + list = lv_obj_get_style_list(obj, LV_TABVIEW_PART_INDIC); + _lv_style_list_add_style(list, &styles->bg); + _lv_style_list_add_style(list, &styles->color); + + list = lv_obj_get_style_list(obj, LV_TABVIEW_PART_TAB_BTN); + _lv_style_list_add_style(list, &styles->bg); + _lv_style_list_add_style(list, &styles->btn); + break; + + case LV_THEME_TABVIEW_PAGE: + list = lv_obj_get_style_list(obj, LV_PAGE_PART_BG); + _lv_style_list_add_style(list, &styles->bg); + _lv_style_list_add_style(list, &styles->gray); + + list = lv_obj_get_style_list(obj, LV_PAGE_PART_SCROLLABLE); + _lv_style_list_add_style(list, &styles->bg); + + break; +#endif + +#if LV_USE_TILEVIEW + case LV_THEME_TILEVIEW: + list = lv_obj_get_style_list(obj, LV_TILEVIEW_PART_BG); + _lv_style_list_add_style(list, &styles->bg); + + list = lv_obj_get_style_list(obj, LV_TILEVIEW_PART_SCROLLBAR); + _lv_style_list_add_style(list, &styles->bg); + + list = lv_obj_get_style_list(obj, LV_TILEVIEW_PART_EDGE_FLASH); + _lv_style_list_add_style(list, &styles->bg); + break; +#endif + +#if LV_USE_ROLLER + case LV_THEME_ROLLER: + list = lv_obj_get_style_list(obj, LV_ROLLER_PART_BG); + _lv_style_list_add_style(list, &styles->bg); + + list = lv_obj_get_style_list(obj, LV_ROLLER_PART_SELECTED); + _lv_style_list_add_style(list, &styles->bg); + _lv_style_list_add_style(list, &styles->color); + break; +#endif + +#if LV_USE_OBJMASK + case LV_THEME_OBJMASK: + list = lv_obj_get_style_list(obj, LV_OBJMASK_PART_MAIN); + break; +#endif + +#if LV_USE_LIST + case LV_THEME_LIST: + list = lv_obj_get_style_list(obj, LV_LIST_PART_BG); + _lv_style_list_add_style(list, &styles->bg); + + list = lv_obj_get_style_list(obj, LV_LIST_PART_SCROLLABLE); + + list = lv_obj_get_style_list(obj, LV_LIST_PART_SCROLLBAR); + _lv_style_list_add_style(list, &styles->bg); + break; + + case LV_THEME_LIST_BTN: + list = lv_obj_get_style_list(obj, LV_BTN_PART_MAIN); + _lv_style_list_add_style(list, &styles->bg); + _lv_style_list_add_style(list, &styles->btn); + break; +#endif + +#if LV_USE_DROPDOWN + case LV_THEME_DROPDOWN: + list = lv_obj_get_style_list(obj, LV_DROPDOWN_PART_MAIN); + _lv_style_list_add_style(list, &styles->bg); + _lv_style_list_add_style(list, &styles->btn); + + list = lv_obj_get_style_list(obj, LV_DROPDOWN_PART_LIST); + _lv_style_list_add_style(list, &styles->bg); + + list = lv_obj_get_style_list(obj, LV_DROPDOWN_PART_SCROLLBAR); + _lv_style_list_add_style(list, &styles->bg); + + list = lv_obj_get_style_list(obj, LV_DROPDOWN_PART_SELECTED); + _lv_style_list_add_style(list, &styles->bg); + _lv_style_list_add_style(list, &styles->color); + break; +#endif + +#if LV_USE_CHART + case LV_THEME_CHART: + list = lv_obj_get_style_list(obj, LV_CHART_PART_BG); + _lv_style_list_add_style(list, &styles->bg); + + list = lv_obj_get_style_list(obj, LV_CHART_PART_SERIES_BG); + _lv_style_list_add_style(list, &styles->bg); + + list = lv_obj_get_style_list(obj, LV_CHART_PART_SERIES); + _lv_style_list_add_style(list, &styles->bg); + _lv_style_list_add_style(list, &styles->tight); + break; +#endif +#if LV_USE_TABLE + case LV_THEME_TABLE: { + list = lv_obj_get_style_list(obj, LV_TABLE_PART_BG); + _lv_style_list_add_style(list, &styles->bg); + + int idx = 1; /* start value should be 1, not zero, since cell styles + start at 1 due to presence of LV_TABLE_PART_BG=0 + in the enum (lv_table.h) */ + /* declaring idx outside loop to work with older compilers */ + for(; idx <= LV_TABLE_CELL_STYLE_CNT; idx++) { + list = lv_obj_get_style_list(obj, idx); + _lv_style_list_add_style(list, &styles->bg); + } + break; + } +#endif + +#if LV_USE_WIN + case LV_THEME_WIN: + list = lv_obj_get_style_list(obj, LV_WIN_PART_BG); + _lv_style_list_add_style(list, &styles->bg); + + list = lv_obj_get_style_list(obj, LV_WIN_PART_SCROLLBAR); + _lv_style_list_add_style(list, &styles->bg); + + list = lv_obj_get_style_list(obj, LV_WIN_PART_CONTENT_SCROLLABLE); + _lv_style_list_add_style(list, &styles->bg); + + list = lv_obj_get_style_list(obj, LV_WIN_PART_HEADER); + _lv_style_list_add_style(list, &styles->bg); + break; + + case LV_THEME_WIN_BTN: + list = lv_obj_get_style_list(obj, LV_BTN_PART_MAIN); + _lv_style_list_add_style(list, &styles->bg); + _lv_style_list_add_style(list, &styles->btn); + break; +#endif + +#if LV_USE_TEXTAREA + case LV_THEME_TEXTAREA: + list = lv_obj_get_style_list(obj, LV_TEXTAREA_PART_BG); + _lv_style_list_add_style(list, &styles->bg); + + list = lv_obj_get_style_list(obj, LV_TEXTAREA_PART_PLACEHOLDER); + _lv_style_list_add_style(list, &styles->gray); + + list = lv_obj_get_style_list(obj, LV_TEXTAREA_PART_CURSOR); + _lv_style_list_add_style(list, &styles->bg); + _lv_style_list_add_style(list, &styles->tight); + + list = lv_obj_get_style_list(obj, LV_TEXTAREA_PART_SCROLLBAR); + _lv_style_list_add_style(list, &styles->bg); + break; +#endif + +#if LV_USE_SPINBOX + case LV_THEME_SPINBOX: + list = lv_obj_get_style_list(obj, LV_SPINBOX_PART_BG); + _lv_style_list_add_style(list, &styles->bg); + + list = lv_obj_get_style_list(obj, LV_SPINBOX_PART_CURSOR); + _lv_style_list_add_style(list, &styles->bg); + break; + + case LV_THEME_SPINBOX_BTN: + list = lv_obj_get_style_list(obj, LV_BTN_PART_MAIN); + _lv_style_list_add_style(list, &styles->bg); + _lv_style_list_add_style(list, &styles->btn); + break; +#endif + +#if LV_USE_CALENDAR + case LV_THEME_CALENDAR: + list = lv_obj_get_style_list(obj, LV_CALENDAR_PART_BG); + _lv_style_list_add_style(list, &styles->bg); + + list = lv_obj_get_style_list(obj, LV_CALENDAR_PART_DATE); + _lv_style_list_add_style(list, &styles->bg); + _lv_style_list_add_style(list, &styles->btn); + _lv_style_list_add_style(list, &styles->tight); + + list = lv_obj_get_style_list(obj, LV_CALENDAR_PART_HEADER); + _lv_style_list_add_style(list, &styles->bg); + + list = lv_obj_get_style_list(obj, LV_CALENDAR_PART_DAY_NAMES); + _lv_style_list_add_style(list, &styles->bg); + _lv_style_list_add_style(list, &styles->tight); + break; +#endif +#if LV_USE_CPICKER + case LV_THEME_CPICKER: + list = lv_obj_get_style_list(obj, LV_CPICKER_PART_MAIN); + _lv_style_list_add_style(list, &styles->bg); + + list = lv_obj_get_style_list(obj, LV_CPICKER_PART_KNOB); + _lv_style_list_add_style(list, &styles->bg); + _lv_style_list_add_style(list, &styles->round); + break; +#endif + +#if LV_USE_LINEMETER + case LV_THEME_LINEMETER: + list = lv_obj_get_style_list(obj, LV_LINEMETER_PART_MAIN); + _lv_style_list_add_style(list, &styles->bg); + _lv_style_list_add_style(list, &styles->round); + break; +#endif +#if LV_USE_GAUGE + case LV_THEME_GAUGE: + list = lv_obj_get_style_list(obj, LV_GAUGE_PART_MAIN); + _lv_style_list_add_style(list, &styles->bg); + _lv_style_list_add_style(list, &styles->round); + + list = lv_obj_get_style_list(obj, LV_GAUGE_PART_MAJOR); + _lv_style_list_add_style(list, &styles->tick_line); + + list = lv_obj_get_style_list(obj, LV_GAUGE_PART_NEEDLE); + _lv_style_list_add_style(list, &styles->bg); + break; +#endif + default: + break; + } + + lv_obj_refresh_style(obj, LV_OBJ_PART_ALL, LV_STYLE_PROP_ALL); } /********************** * STATIC FUNCTIONS **********************/ +static void style_init_reset(lv_style_t * style) +{ + if(inited) + lv_style_reset(style); + else + lv_style_init(style); +} + #endif diff --git a/src/lv_theme_hasp.h b/src/lv_theme_hasp.h index 8788304c..bd468d34 100644 --- a/src/lv_theme_hasp.h +++ b/src/lv_theme_hasp.h @@ -1,5 +1,5 @@ /** - * @file lv_theme_default.h + * @file lv_theme_hasp.h * */ @@ -13,8 +13,7 @@ extern "C" { /********************* * INCLUDES *********************/ -#include "lvgl.h" -//#include "../lib/lvgl/src/lv_conf_internal.h" +#include "lv_conf.h" #if LV_USE_THEME_HASP @@ -31,19 +30,19 @@ extern "C" { **********************/ /** - * Initialize the default theme - * @param hue [0..360] hue value from HSV color space to define the theme's base color - * @param font pointer to a font (NULL to use the default) - * @return pointer to the initialized theme + * Initialize the default + * @param color_primary the primary color of the theme + * @param color_secondary the secondary color for the theme + * @param flags ORed flags starting with `LV_THEME_DEF_FLAG_...` + * @param font_small pointer to a small font + * @param font_normal pointer to a normal font + * @param font_subtitle pointer to a large font + * @param font_title pointer to a extra large font + * @return a pointer to reference this theme later */ -lv_theme_t * lv_theme_hasp_init(uint16_t hue, lv_font_t * font); - -/** - * Get a pointer to the theme - * @return pointer to the theme - */ -lv_theme_t * lv_theme_get_hasp(void); - +lv_theme_t * lv_theme_hasp_init(lv_color_t color_primary, lv_color_t color_secondary, uint32_t flags, + const lv_font_t * font_small, const lv_font_t * font_normal, + const lv_font_t * font_subtitle, const lv_font_t * font_title); /********************** * MACROS **********************/ @@ -54,4 +53,4 @@ lv_theme_t * lv_theme_get_hasp(void); } /* extern "C" */ #endif -#endif /*LV_THEME_TEMPL_H*/ +#endif /*LV_THEME_HASP_H*/ From a6af4f385458ee26807089329e05c7be836013b3 Mon Sep 17 00:00:00 2001 From: fvanroie Date: Wed, 28 Oct 2020 22:01:20 +0100 Subject: [PATCH 18/33] Update arc and colorpicker --- src/hasp_attribute.cpp | 59 ++++++++++++++++++++++++++++++++---------- src/hasp_attribute.h | 2 +- 2 files changed, 46 insertions(+), 15 deletions(-) diff --git a/src/hasp_attribute.cpp b/src/hasp_attribute.cpp index fc27298e..a02d7ba7 100644 --- a/src/hasp_attribute.cpp +++ b/src/hasp_attribute.cpp @@ -656,6 +656,8 @@ static void hasp_process_obj_attribute_val(lv_obj_t * obj, const char * attr, co : hasp_out_int(obj, attr, lv_slider_get_value(obj)); } else if(check_obj_type(objtype, LV_HASP_LED)) { return update ? lv_led_set_bright(obj, (uint8_t)val) : hasp_out_int(obj, attr, lv_led_get_bright(obj)); + } else if(check_obj_type(objtype, LV_HASP_ARC)) { + return update ? lv_arc_set_value(obj, intval) : hasp_out_int(obj, attr, lv_arc_get_value(obj)); } else if(check_obj_type(objtype, LV_HASP_GAUGE)) { return update ? lv_gauge_set_value(obj, 0, intval) : hasp_out_int(obj, attr, lv_gauge_get_value(obj, 0)); } else if(check_obj_type(objtype, LV_HASP_ROLLER)) { @@ -683,28 +685,35 @@ static void hasp_process_obj_attribute_range(lv_obj_t * obj, const char * attr, if(check_obj_type(objtype, LV_HASP_SLIDER)) { int16_t min = lv_slider_get_min_value(obj); int16_t max = lv_slider_get_max_value(obj); - if(update && (set_min ? val : min) <= (set_max ? val : max)) return; // prevent setting min<=max + if(update && (set_min ? val : min) >= (set_max ? val : max)) return; // prevent setting min>=max return update ? lv_slider_set_range(obj, set_min ? val : min, set_max ? val : max) : hasp_out_int(obj, attr, set_min ? lv_slider_get_min_value(obj) : lv_slider_get_max_value(obj)); } if(check_obj_type(objtype, LV_HASP_GAUGE)) { int16_t min = lv_gauge_get_min_value(obj); int16_t max = lv_gauge_get_max_value(obj); - if(update && (set_min ? val : min) <= (set_max ? val : max)) return; // prevent setting min<=max + if(update && (set_min ? val : min) >= (set_max ? val : max)) return; // prevent setting min>=max return update ? lv_gauge_set_range(obj, set_min ? val : min, set_max ? val : max) : hasp_out_int(obj, attr, set_min ? lv_gauge_get_min_value(obj) : lv_gauge_get_max_value(obj)); } + if(check_obj_type(objtype, LV_HASP_ARC)) { + int16_t min = lv_arc_get_min_value(obj); + int16_t max = lv_arc_get_max_value(obj); + if(update && (set_min ? val : min) >= (set_max ? val : max)) return; // prevent setting min>=max + return update ? lv_arc_set_range(obj, set_min ? val : min, set_max ? val : max) + : hasp_out_int(obj, attr, set_min ? lv_arc_get_min_value(obj) : lv_arc_get_max_value(obj)); + } if(check_obj_type(objtype, LV_HASP_BAR)) { int16_t min = lv_bar_get_min_value(obj); int16_t max = lv_bar_get_max_value(obj); - if(update && (set_min ? val : min) <= (set_max ? val : max)) return; // prevent setting min<=max + if(update && (set_min ? val : min) >= (set_max ? val : max)) return; // prevent setting min>=max return update ? lv_bar_set_range(obj, set_min ? val : min, set_max ? val : max) : hasp_out_int(obj, attr, set_min ? lv_bar_get_min_value(obj) : lv_bar_get_max_value(obj)); } if(check_obj_type(objtype, LV_HASP_LMETER)) { int16_t min = lv_linemeter_get_min_value(obj); int16_t max = lv_linemeter_get_max_value(obj); - if(update && (set_min ? val : min) <= (set_max ? val : max)) return; // prevent setting min<=max + if(update && (set_min ? val : min) >= (set_max ? val : max)) return; // prevent setting min>=max return update ? lv_linemeter_set_range(obj, set_min ? val : min, set_max ? val : max) : hasp_out_int(obj, attr, set_min ? lv_linemeter_get_min_value(obj) : lv_linemeter_get_max_value(obj)); @@ -739,11 +748,31 @@ void hasp_process_obj_attribute(lv_obj_t * obj, const char * attr_p, const char case ATTR_Y: return update ? lv_obj_set_y(obj, val) : hasp_out_int(obj, attr, lv_obj_get_y(obj)); - case ATTR_W: - return update ? lv_obj_set_width(obj, val) : hasp_out_int(obj, attr, lv_obj_get_width(obj)); + case ATTR_W: { + if(update) { + lv_obj_set_width(obj, val); + if(check_obj_type(obj, LV_HASP_CPICKER)) { + lv_cpicker_set_type(obj, lv_obj_get_width(obj) == lv_obj_get_height(obj) ? LV_CPICKER_TYPE_DISC + : LV_CPICKER_TYPE_RECT); + } + } else { + hasp_out_int(obj, attr, lv_obj_get_width(obj)); + } + return; + } - case ATTR_H: - return update ? lv_obj_set_height(obj, val) : hasp_out_int(obj, attr, lv_obj_get_height(obj)); + case ATTR_H: { + if(update) { + lv_obj_set_height(obj, val); + if(check_obj_type(obj, LV_HASP_CPICKER)) { + lv_cpicker_set_type(obj, lv_obj_get_width(obj) == lv_obj_get_height(obj) ? LV_CPICKER_TYPE_DISC + : LV_CPICKER_TYPE_RECT); + } + } else { + hasp_out_int(obj, attr, lv_obj_get_height(obj)); + } + return; + } case ATTR_ID: return update ? (void)(obj->user_data = (uint8_t)val) : hasp_out_int(obj, attr, obj->user_data); @@ -791,12 +820,12 @@ void hasp_process_obj_attribute(lv_obj_t * obj, const char * attr_p, const char } break; - case ATTR_RECT: - if(check_obj_type(obj, LV_HASP_CPICKER)) { - lv_cpicker_set_type(obj, is_true(payload) ? LV_CPICKER_TYPE_RECT : LV_CPICKER_TYPE_DISC); - return; - } - break; + // case ATTR_RECT: + // if(check_obj_type(obj, LV_HASP_CPICKER)) { + // lv_cpicker_set_type(obj, is_true(payload) ? LV_CPICKER_TYPE_RECT : LV_CPICKER_TYPE_DISC); + // return; + // } + // break; case ATTR_MODE: if(check_obj_type(obj, LV_HASP_BUTTON)) { @@ -924,6 +953,8 @@ bool check_obj_type(const char * lvobjtype, lv_hasp_obj_type_t haspobjtype) return (strcmp_P(lvobjtype, PSTR("slider")) == 0); case LV_HASP_GAUGE: return (strcmp_P(lvobjtype, PSTR("gauge")) == 0); + case LV_HASP_ARC: + return (strcmp_P(lvobjtype, PSTR("arc")) == 0); case LV_HASP_BAR: return (strcmp_P(lvobjtype, PSTR("bar")) == 0); case LV_HASP_LMETER: diff --git a/src/hasp_attribute.h b/src/hasp_attribute.h index 911a6f94..2eaf06ee 100644 --- a/src/hasp_attribute.h +++ b/src/hasp_attribute.h @@ -247,7 +247,7 @@ _HASP_ATTRIBUTE(SCALE_END_LINE_WIDTH, scale_end_line_width, lv_style_int_t) #define ATTR_HIDDEN 11082 #define ATTR_VIS 16320 #define ATTR_MODE 45891 -#define ATTR_RECT 11204 +// #define ATTR_RECT 11204 #define ATTR_ROWS 52153 #define ATTR_MIN 46130 #define ATTR_MAX 45636 From 8d5e29822c4b439f4790e78a23c5a55645eef540 Mon Sep 17 00:00:00 2001 From: fvanroie Date: Wed, 28 Oct 2020 23:54:01 +0100 Subject: [PATCH 19/33] Exclude test reports --- .gitignore | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.gitignore b/.gitignore index d656f83e..a124c10c 100644 --- a/.gitignore +++ b/.gitignore @@ -10,6 +10,10 @@ src/user_config_override.h platformio_override.ini user_setups/active/* +## Test result files +*.html +*.xml + ## Visual Studio Code specific ###### .vscode .vscode/.browse.c_cpp.db* From 35a0c7792e170615de16aea0c89a844b11ff6814 Mon Sep 17 00:00:00 2001 From: fvanroie <15969459+fvanroie@users.noreply.github.com> Date: Thu, 29 Oct 2020 00:29:17 +0100 Subject: [PATCH 20/33] Update README.md --- README.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/README.md b/README.md index 763e189d..b754d38d 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,7 @@ [![GitHub](https://img.shields.io/github/license/mashape/apistatus.svg)](https://github.com/fvanroie/hasp-lvgl/blob/master/LICENSE) [![contributions welcome](https://img.shields.io/badge/contributions-welcome-brightgreen.svg?style=flat)](#Contributing) [![GitHub issues](https://img.shields.io/github/issues/fvanroie/hasp-lvgl.svg)](http://github.com/fvanroie/hasp-lvgl/issues) +[![Discord](https://img.shields.io/discord/538814618106331137?color=%237289DA&label=support&logo=discord&logoColor=white)][6] This project is a re-implementation of the popular HASwitchPlate sketch created by aderusha. The [original HASwitchPlate][1] project uses a Wemos D1 mini and requires a Nextion/TJC HMI display. @@ -61,8 +62,15 @@ git submodule update --init --recursive Check out the [wiki](https://github.com/fvanroie/hasp-lvgl/wiki) for how-to's, information and frequently asked questions. +Support +--------------------------- +For support using hasp-lvgl, please join the [#hasp-lvgl channel][6] on Discord. + + + [1]: https://github.com/aderusha/HASwitchPlate [2]: https://github.com/littlevgl/lvgl [3]: https://littlevgl.com/themes [4]: https://github.com/fvanroie/HMI-Font-Pack/releases [5]: https://fontawesome.com/cheatsheet/ +[6]: https://discord.gg/VCWyuhF From 07293d0d47f099d5801b3b32ecd80603fa248495 Mon Sep 17 00:00:00 2001 From: fvanroie Date: Thu, 29 Oct 2020 18:15:12 +0100 Subject: [PATCH 21/33] Update hasp-lvgl.robot --- lib/lvgl | 2 +- src/{lv_theme_hasp.c => lv_theme_hasp.cpp} | 5 ++-- test/hasp-lvgl.robot | 34 +++++++++++++++++----- 3 files changed, 31 insertions(+), 10 deletions(-) rename src/{lv_theme_hasp.c => lv_theme_hasp.cpp} (99%) diff --git a/lib/lvgl b/lib/lvgl index 3543cc05..00d32b12 160000 --- a/lib/lvgl +++ b/lib/lvgl @@ -1 +1 @@ -Subproject commit 3543cc051bdb7b8233ddcc71b3694efcbe562c52 +Subproject commit 00d32b127f5745bf477e9b3c8ae89f11b0247a5b diff --git a/src/lv_theme_hasp.c b/src/lv_theme_hasp.cpp similarity index 99% rename from src/lv_theme_hasp.c rename to src/lv_theme_hasp.cpp index 6f755dd7..558c7db3 100644 --- a/src/lv_theme_hasp.c +++ b/src/lv_theme_hasp.cpp @@ -1,5 +1,5 @@ /** - * @file lv_theme_hasp.c + * @file lv_theme_hasp.cpp * */ @@ -11,6 +11,7 @@ #if LV_USE_THEME_HASP #include "lv_misc/lv_gc.h" +#include "lv_theme_hasp.h" #if defined(LV_GC_INCLUDE) #include LV_GC_INCLUDE @@ -350,7 +351,7 @@ lv_theme_t * lv_theme_hasp_init(lv_color_t color_primary, lv_color_t color_secon LV_GC_ROOT(_lv_theme_template_styles) = lv_mem_alloc(sizeof(theme_styles_t)); styles = (theme_styles_t *)LV_GC_ROOT(_lv_theme_template_styles); #else - styles = lv_mem_alloc(sizeof(theme_styles_t)); + styles = (theme_styles_t*)lv_mem_alloc(sizeof(theme_styles_t)); #endif } diff --git a/test/hasp-lvgl.robot b/test/hasp-lvgl.robot index 143e7e59..9b3f708f 100644 --- a/test/hasp-lvgl.robot +++ b/test/hasp-lvgl.robot @@ -9,8 +9,8 @@ | | ... | ${property}=${property} | ${data}=${data} | | ${time} | Get Time | epoch | | ${client} | Catenate | SEPARATOR=. | robot.mqtt | ${time} -| | ${topic} | Set Variable | hasp/plate35/command -| | ${restopic} | Set Variable | hasp/plate35/state/json +| | ${topic} | Set Variable | hasp/plate37/command +| | ${restopic} | Set Variable | hasp/plate37/state/json | | ${qos} | Set Variable | 1 | | ${message} | Set Variable | ${property}=${data} | | ${result} | Set Variable | {"${property}":"${data}"} @@ -31,8 +31,8 @@ | | ... | ${property}=${property} | ${data}=${data} | | ${time} | Get Time | epoch | | ${client} | Catenate | SEPARATOR=. | robot.mqtt | ${time} -| | ${topic} | Set Variable | hasp/plate35/command -| | ${restopic} | Set Variable | hasp/plate35/state/page +| | ${topic} | Set Variable | hasp/plate37/command +| | ${restopic} | Set Variable | hasp/plate37/state/page | | ${qos} | Set Variable | 1 | | ${message} | Set Variable | ${property}=${data} | | Subscribe Async | client.id=${client} | topic=${restopic} @@ -44,12 +44,26 @@ | | Length Should Be | ${messages} | 1 | | Should Be Equal As Strings | ${messages}[0] | ${data} +| Hasp Command +| | [Arguments] | ${broker.uri}=${broker.uri} | ${port}=${broker.port} +| | ... | ${client.id}=${client.id} | ${clean_session}=${true} +| | ... | ${property}=${property} | ${data}=${data} +| | ${time} | Get Time | epoch +| | ${client} | Catenate | SEPARATOR=. | robot.mqtt | ${time} +| | ${topic} | Set Variable | hasp/plate37/command/${property} +| | ${restopic} | Set Variable | hasp/plate37/state/page +| | ${qos} | Set Variable | 1 +| | ${message} | Set Variable | ${data} +| | Connect | ${broker.uri} | ${port} | ${client.id} | ${clean_session} +| | Publish | ${topic} | ${message} | 1 | *Test Cases* | Test Color Picker\n | | ${obj} | Set Variable | p[1].b[4] | | Test Page | property=page | data=1 +| | Hasp Command | property=clearpage | data=1 +| | Hasp Command | property=jsonl | data={"page":1,"id":4,"objid":20} #| | Test Property | property=${obj}.txt | data=ABC #| | Test Property | property=${obj}.txt | data=1234 | | Test Property | property=${obj}.x | data=50 @@ -80,6 +94,8 @@ | Test Text Field\n | | ${obj} | Set Variable | p[1].b[1] | | Test Page | property=page | data=1 +| | Hasp Command | property=clearpage | data=1 +| | Hasp Command | property=jsonl | data={"page":1,"id":1,"objid":12} | | Test Property | property=${obj}.txt | data=ABC | | Test Property | property=${obj}.txt | data=123 | | Test Property | property=${obj}.x | data=20 @@ -103,8 +119,10 @@ | Test Button\n -| | ${obj} | Set Variable | p[0].b[1] -| | Test Page | property=page | data=0 +| | ${obj} | Set Variable | p[1].b[1] +| | Test Page | property=page | data=1 +| | Hasp Command | property=clearpage | data=1 +| | Hasp Command | property=jsonl | data={"page":1,"id":1,"objid":10} #| | Test Property | property=${obj}.txt | data=ABC #| | Test Property | property=${obj}.txt | data=1234 | | Test Property | property=${obj}.x | data=20 @@ -133,8 +151,10 @@ | | Test Property | property=${obj}.val | data=3 | Test Slider\n -| | ${obj} | Set Variable | p[1].b[3] +| | ${obj} | Set Variable | p[1].b[4] | | Test Page | property=page | data=1 +| | Hasp Command | property=clearpage | data=1 +| | Hasp Command | property=jsonl | data={"page":1,"id":4,"objid":30} #| | Test Property | property=${obj}.txt | data=ABC #| | Test Property | property=${obj}.txt | data=1234 | | Test Property | property=${obj}.x | data=20 From ba8f5b1fa0b1165e484ab7fdb878a4fd52e0e2a1 Mon Sep 17 00:00:00 2001 From: arovak Date: Tue, 3 Nov 2020 22:52:41 +0100 Subject: [PATCH 22/33] Inital ESP32 Ethernet support --- include/hasp_conf.h | 16 ++++++++++ src/hasp_ethernet.cpp | 2 +- src/hasp_ethernet_esp32.cpp | 64 +++++++++++++++++++++++++++++++++++++ src/hasp_ethernet_esp32.h | 13 ++++++++ src/hasp_http.cpp | 4 +++ src/hasp_oobe.cpp | 6 +++- test/hasp-lvgl.robot | 12 +++---- 7 files changed, 109 insertions(+), 8 deletions(-) create mode 100644 src/hasp_ethernet_esp32.cpp create mode 100644 src/hasp_ethernet_esp32.h diff --git a/include/hasp_conf.h b/include/hasp_conf.h index 134dd1ca..91375a11 100644 --- a/include/hasp_conf.h +++ b/include/hasp_conf.h @@ -107,6 +107,21 @@ #endif #if HASP_USE_ETHERNET > 0 +#if defined(ARDUINO_ARCH_ESP32) +#include + +#define ETH_ADDR 0 +#define ETH_POWER_PIN -1 +#define ETH_MDC_PIN 23 +#define ETH_MDIO_PIN 18 +#define NRST 5 +#define ETH_TYPE ETH_PHY_LAN8720 +#define ETH_CLKMODE ETH_CLOCK_GPIO17_OUT + +#include "hasp_ethernet_esp32.h" +#warning Using ESP32 Ethernet LAN8720 + +#else #if USE_BUILTIN_ETHERNET > 0 #include #include @@ -121,6 +136,7 @@ #endif #include "hasp_ethernet.h" #endif +#endif #if HASP_USE_MQTT > 0 #include "hasp_mqtt.h" diff --git a/src/hasp_ethernet.cpp b/src/hasp_ethernet.cpp index d6f82bff..073de7b1 100644 --- a/src/hasp_ethernet.cpp +++ b/src/hasp_ethernet.cpp @@ -4,7 +4,7 @@ #include "hasp_conf.h" #include "hasp_hal.h" -#if HASP_USE_ETHERNET > 0 +#if HASP_USE_ETHERNET > 0 && !defined(ARDUINO_ARCH_ESP32) EthernetClient EthClient; IPAddress ip; diff --git a/src/hasp_ethernet_esp32.cpp b/src/hasp_ethernet_esp32.cpp new file mode 100644 index 00000000..ede1a636 --- /dev/null +++ b/src/hasp_ethernet_esp32.cpp @@ -0,0 +1,64 @@ +#include +#include "ArduinoJson.h" +#include "ArduinoLog.h" +#include "hasp_conf.h" +#include "hasp_hal.h" + +#if HASP_USE_ETHERNET > 0 + +IPAddress ip; + +void EthernetEvent(WiFiEvent_t event) +{ + switch (event) { + case SYSTEM_EVENT_ETH_START: + Log.notice(F(LOG_ETH_CTR "Started")); + //set eth hostname here + ETH.setHostname("esp32-ethernet"); + break; + case SYSTEM_EVENT_ETH_CONNECTED: + Log.notice(F(LOG_ETH_CTR "Connected")); + break; + case SYSTEM_EVENT_ETH_GOT_IP: + Log.notice(F(LOG_ETH_CTR "MAC Address %s"), ETH.macAddress().c_str()); + ip = ETH.localIP(); + Log.notice(F(LOG_ETH_CTR "IPv4: %d.%d.%d.%d"), ip[0], ip[1], ip[2], ip[3]); + if (ETH.fullDuplex()) { + Log.notice(F(LOG_ETH_CTR "FULL_DUPLEX")); + } + Log.notice(F(LOG_ETH_CTR "LINK_SPEED %d Mbps"), ETH.linkSpeed()); + eth_connected = true; + break; + case SYSTEM_EVENT_ETH_DISCONNECTED: + Log.notice(F(LOG_ETH_CTR "Disconnected")); + eth_connected = false; + break; + case SYSTEM_EVENT_ETH_STOP: + Log.notice(F(LOG_ETH_CTR "Stopped")); + eth_connected = false; + break; + default: + break; + } +} + +void ethernetSetup() +{ + WiFi.onEvent(EthernetEvent); + ETH.begin(ETH_ADDR, ETH_POWER_PIN, ETH_MDC_PIN, ETH_MDIO_PIN, ETH_TYPE, ETH_CLKMODE); +} + + +void ethernetLoop(void) +{ +// +} + +bool ethernetEvery5Seconds() +{ + Log.warning(F(LOG_ETH_CTR "%s"), eth_connected ? F("ONLINE") : F("OFFLINE")); + return eth_connected; +} + + +#endif \ No newline at end of file diff --git a/src/hasp_ethernet_esp32.h b/src/hasp_ethernet_esp32.h new file mode 100644 index 00000000..ed45e9ea --- /dev/null +++ b/src/hasp_ethernet_esp32.h @@ -0,0 +1,13 @@ +#ifndef HASP_ETHERNET_ESP32_H +#define HASP_ETHERNET_ESP32_H + +#define LOG_ETH_CTR "ETH: " + +static bool eth_connected = false; + +void ethernetSetup(); +void ethernetLoop(void); + +bool ethernetEvery5Seconds(); + +#endif \ No newline at end of file diff --git a/src/hasp_http.cpp b/src/hasp_http.cpp index 0a218e91..42cb0616 100644 --- a/src/hasp_http.cpp +++ b/src/hasp_http.cpp @@ -1514,7 +1514,11 @@ void webStart() (WiFi.getMode() != WIFI_STA ? WiFi.softAPIP().toString().c_str() : WiFi.localIP().toString().c_str())); #else IPAddress ip; +#if defined(ARDUINO_ARCH_ESP32) + ip = ETH.localIP(); +#else ip = Ethernet.localIP(); +#endif Log.notice(F("HTTP: Server started @ http://%d.%d.%d.%d"), ip[0], ip[1], ip[2], ip[3]); #endif } diff --git a/src/hasp_oobe.cpp b/src/hasp_oobe.cpp index 6c633ffe..842dff03 100644 --- a/src/hasp_oobe.cpp +++ b/src/hasp_oobe.cpp @@ -73,13 +73,14 @@ static void kb_event_cb(lv_obj_t * event_kb, lv_event_t event) strncpy(pass, lv_textarea_get_text(obj), sizeof(pass)); settings[FPSTR(F_CONFIG_PASS)] = pass; } - + #if HASP_USE_WIFI > 0 if(strlen(ssid) > 0) { wifiSetConfig(settings.as()); if(wifiTestConnection()) { dispatchReboot(true); } } + #endif } else if(event == LV_EVENT_CANCEL) { oobeSetPage(0); @@ -296,6 +297,9 @@ static void oobe_calibrate_cb(lv_obj_t * ta, lv_event_t event) bool oobeSetup() { +#if HASP_USE_ETHERNET > 0 +if (eth_connected) return false; +#endif #if HASP_USE_WIFI > 0 char ssid[32]; char pass[32]; diff --git a/test/hasp-lvgl.robot b/test/hasp-lvgl.robot index 9b3f708f..086766b5 100644 --- a/test/hasp-lvgl.robot +++ b/test/hasp-lvgl.robot @@ -9,8 +9,8 @@ | | ... | ${property}=${property} | ${data}=${data} | | ${time} | Get Time | epoch | | ${client} | Catenate | SEPARATOR=. | robot.mqtt | ${time} -| | ${topic} | Set Variable | hasp/plate37/command -| | ${restopic} | Set Variable | hasp/plate37/state/json +| | ${topic} | Set Variable | hasp/platetelemetry/command +| | ${restopic} | Set Variable | hasp/platetelemetry/state/json | | ${qos} | Set Variable | 1 | | ${message} | Set Variable | ${property}=${data} | | ${result} | Set Variable | {"${property}":"${data}"} @@ -31,8 +31,8 @@ | | ... | ${property}=${property} | ${data}=${data} | | ${time} | Get Time | epoch | | ${client} | Catenate | SEPARATOR=. | robot.mqtt | ${time} -| | ${topic} | Set Variable | hasp/plate37/command -| | ${restopic} | Set Variable | hasp/plate37/state/page +| | ${topic} | Set Variable | hasp/platetelemetry/command +| | ${restopic} | Set Variable | hasp/platetelemetry/state/page | | ${qos} | Set Variable | 1 | | ${message} | Set Variable | ${property}=${data} | | Subscribe Async | client.id=${client} | topic=${restopic} @@ -50,8 +50,8 @@ | | ... | ${property}=${property} | ${data}=${data} | | ${time} | Get Time | epoch | | ${client} | Catenate | SEPARATOR=. | robot.mqtt | ${time} -| | ${topic} | Set Variable | hasp/plate37/command/${property} -| | ${restopic} | Set Variable | hasp/plate37/state/page +| | ${topic} | Set Variable | hasp/platetelemetry/command/${property} +| | ${restopic} | Set Variable | hasp/platetelemetry/state/page | | ${qos} | Set Variable | 1 | | ${message} | Set Variable | ${data} | | Connect | ${broker.uri} | ${port} | ${client.id} | ${clean_session} From e5ee2328a8c8d6c096982bf056df421fb92ee086 Mon Sep 17 00:00:00 2001 From: arovak Date: Tue, 3 Nov 2020 22:53:23 +0100 Subject: [PATCH 23/33] TTGO ESP32 POE user config --- user_setups/esp32/TTGO-esp32-POE_ili9341.ini | 35 ++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 user_setups/esp32/TTGO-esp32-POE_ili9341.ini diff --git a/user_setups/esp32/TTGO-esp32-POE_ili9341.ini b/user_setups/esp32/TTGO-esp32-POE_ili9341.ini new file mode 100644 index 00000000..47724a49 --- /dev/null +++ b/user_setups/esp32/TTGO-esp32-POE_ili9341.ini @@ -0,0 +1,35 @@ +;***************************************************; +; Lilygo®Ttgo ESP32 with Lolin TFT 2.4" ; +; - T-Internet-Poe ESP32-WROOM ; +; - LAN8720A with POE ; +; - ili9341 TFT ; +; - xpt2606 touch controller ; +;***************************************************; + +[env:ttgo_esp32-lolintft24] +platform = espressif32@^1.12.0 +board = esp32dev +upload_protocol = espota ; Use ArduinoOTA after flashing over serial +upload_port = 10.4.70.37 ; 10.4.0.198 ; IP of the ESP +upload_flags = + --port=3232 + +;upload_port = COM9 ; To change the port, use platform_override.ini +monitor_port = COM9 ; To change the port, use platform_override.ini +board_build.partitions = esp32_partition_app1300k_spiffs1216k.csv ; default.csv +build_flags = + ${flags.esp32_flags} +; -- TFT_eSPI build options ------------------------ + ${lcd.lolin24} + -D TFT_MISO=2 + -D TFT_MOSI=15 + -D TFT_SCLK=14 + -D TFT_DC=4 + -D TFT_CS=33 + -D TFT_RST=12 ; RST + -D TFT_BCKL=16 ; None, configurable via web UI (e.g. 21) + -D TOUCH_CS=32 ; (can also be 22 or 16) +; -- Options ---------------------------------------- + -D HASP_USE_TELNET=1 + -D HASP_USE_ETHERNET=1 + -D HASP_USE_WIFI=0 From a3bda0ec082f8b6de72721bd68655e65275034e3 Mon Sep 17 00:00:00 2001 From: fvanroie Date: Tue, 3 Nov 2020 23:00:11 +0100 Subject: [PATCH 24/33] Add HASP_OTA_PORT --- include/hasp_conf.h | 7 +++++++ src/hasp_ota.cpp | 3 ++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/include/hasp_conf.h b/include/hasp_conf.h index 134dd1ca..7327b4a8 100644 --- a/include/hasp_conf.h +++ b/include/hasp_conf.h @@ -144,6 +144,13 @@ #if HASP_USE_OTA > 0 #include "hasp_ota.h" + +#ifndef HASP_OTA_PORT +#if defined(ARDUINO_ARCH_ESP32) +#define HASP_OTA_PORT 3232 +#elif defined(ARDUINO_ARCH_ESP8266) +#define HASP_OTA_PORT 8266 +#endif #endif #if HASP_USE_TASMOTA_SLAVE > 0 diff --git a/src/hasp_ota.cpp b/src/hasp_ota.cpp index cc7a3fca..64acf333 100644 --- a/src/hasp_ota.cpp +++ b/src/hasp_ota.cpp @@ -34,7 +34,8 @@ static WiFiClient otaClient; std::string otaUrl = "http://10.1.0.3"; int8_t otaPrecentageComplete = -1; -int16_t otaPort = 3232; + +int16_t otaPort = HASP_OTA_PORT; void otaProgress() { From 5a54de84ac09fcf99117e3cfebbb74982beb2cfe Mon Sep 17 00:00:00 2001 From: fvanroie Date: Tue, 3 Nov 2020 23:00:27 +0100 Subject: [PATCH 25/33] Code clean-up --- src/hasp_attribute.cpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/hasp_attribute.cpp b/src/hasp_attribute.cpp index a02d7ba7..da68cedf 100644 --- a/src/hasp_attribute.cpp +++ b/src/hasp_attribute.cpp @@ -636,9 +636,11 @@ static void hasp_process_obj_attribute_val(lv_obj_t * obj, const char * attr, co } } } + if(check_obj_type(objtype, LV_HASP_CHECKBOX)) { return update ? lv_checkbox_set_checked(obj, is_true(payload)) : hasp_out_int(obj, attr, lv_checkbox_is_checked(obj)); + } if(check_obj_type(objtype, LV_HASP_SWITCH)) { if(update) { @@ -646,25 +648,34 @@ static void hasp_process_obj_attribute_val(lv_obj_t * obj, const char * attr, co } else { return hasp_out_int(obj, attr, lv_switch_get_state(obj)); } + } else if(check_obj_type(objtype, LV_HASP_DDLIST)) { lv_dropdown_set_selected(obj, val); return; + } else if(check_obj_type(objtype, LV_HASP_LMETER)) { return update ? lv_linemeter_set_value(obj, intval) : hasp_out_int(obj, attr, lv_linemeter_get_value(obj)); + } else if(check_obj_type(objtype, LV_HASP_SLIDER)) { return update ? lv_slider_set_value(obj, intval, LV_ANIM_ON) : hasp_out_int(obj, attr, lv_slider_get_value(obj)); + } else if(check_obj_type(objtype, LV_HASP_LED)) { return update ? lv_led_set_bright(obj, (uint8_t)val) : hasp_out_int(obj, attr, lv_led_get_bright(obj)); + } else if(check_obj_type(objtype, LV_HASP_ARC)) { return update ? lv_arc_set_value(obj, intval) : hasp_out_int(obj, attr, lv_arc_get_value(obj)); + } else if(check_obj_type(objtype, LV_HASP_GAUGE)) { return update ? lv_gauge_set_value(obj, 0, intval) : hasp_out_int(obj, attr, lv_gauge_get_value(obj, 0)); + } else if(check_obj_type(objtype, LV_HASP_ROLLER)) { lv_roller_set_selected(obj, val, LV_ANIM_ON); return; + } else if(check_obj_type(objtype, LV_HASP_BAR)) { return update ? lv_bar_set_value(obj, intval, LV_ANIM_ON) : hasp_out_int(obj, attr, lv_bar_get_value(obj)); + } else if(check_obj_type(objtype, LV_HASP_CPICKER)) { return update ? (void)lv_cpicker_set_color(obj, haspPayloadToColor(payload)) : hasp_out_color(obj, attr, lv_cpicker_get_color(obj)); @@ -689,6 +700,7 @@ static void hasp_process_obj_attribute_range(lv_obj_t * obj, const char * attr, return update ? lv_slider_set_range(obj, set_min ? val : min, set_max ? val : max) : hasp_out_int(obj, attr, set_min ? lv_slider_get_min_value(obj) : lv_slider_get_max_value(obj)); } + if(check_obj_type(objtype, LV_HASP_GAUGE)) { int16_t min = lv_gauge_get_min_value(obj); int16_t max = lv_gauge_get_max_value(obj); @@ -696,6 +708,7 @@ static void hasp_process_obj_attribute_range(lv_obj_t * obj, const char * attr, return update ? lv_gauge_set_range(obj, set_min ? val : min, set_max ? val : max) : hasp_out_int(obj, attr, set_min ? lv_gauge_get_min_value(obj) : lv_gauge_get_max_value(obj)); } + if(check_obj_type(objtype, LV_HASP_ARC)) { int16_t min = lv_arc_get_min_value(obj); int16_t max = lv_arc_get_max_value(obj); @@ -703,6 +716,7 @@ static void hasp_process_obj_attribute_range(lv_obj_t * obj, const char * attr, return update ? lv_arc_set_range(obj, set_min ? val : min, set_max ? val : max) : hasp_out_int(obj, attr, set_min ? lv_arc_get_min_value(obj) : lv_arc_get_max_value(obj)); } + if(check_obj_type(objtype, LV_HASP_BAR)) { int16_t min = lv_bar_get_min_value(obj); int16_t max = lv_bar_get_max_value(obj); @@ -710,6 +724,7 @@ static void hasp_process_obj_attribute_range(lv_obj_t * obj, const char * attr, return update ? lv_bar_set_range(obj, set_min ? val : min, set_max ? val : max) : hasp_out_int(obj, attr, set_min ? lv_bar_get_min_value(obj) : lv_bar_get_max_value(obj)); } + if(check_obj_type(objtype, LV_HASP_LMETER)) { int16_t min = lv_linemeter_get_min_value(obj); int16_t max = lv_linemeter_get_max_value(obj); From 9b6652ffce43f02f939ef16185861985d6fdf0f1 Mon Sep 17 00:00:00 2001 From: fvanroie Date: Tue, 3 Nov 2020 23:03:09 +0100 Subject: [PATCH 26/33] Add missing #endif --- include/hasp_conf.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/hasp_conf.h b/include/hasp_conf.h index c0de2df6..7b00cac0 100644 --- a/include/hasp_conf.h +++ b/include/hasp_conf.h @@ -160,7 +160,6 @@ #if HASP_USE_OTA > 0 #include "hasp_ota.h" - #ifndef HASP_OTA_PORT #if defined(ARDUINO_ARCH_ESP32) #define HASP_OTA_PORT 3232 @@ -168,6 +167,7 @@ #define HASP_OTA_PORT 8266 #endif #endif +#endif #if HASP_USE_TASMOTA_SLAVE > 0 #include "hasp_slave.h" From d2b82ba716c86d3841a01e2758b26a9fd8dfb228 Mon Sep 17 00:00:00 2001 From: fvanroie Date: Tue, 3 Nov 2020 23:55:43 +0100 Subject: [PATCH 27/33] Fix esp8266 wifi connection --- src/hasp_gpio.cpp | 43 ++++++++++++++++++++----------------------- src/hasp_mqtt.cpp | 10 +++++----- src/hasp_wifi.cpp | 26 +++++++++++++++----------- 3 files changed, 40 insertions(+), 39 deletions(-) diff --git a/src/hasp_gpio.cpp b/src/hasp_gpio.cpp index 885278db..8d31794b 100644 --- a/src/hasp_gpio.cpp +++ b/src/hasp_gpio.cpp @@ -16,26 +16,23 @@ uint16_t gpioConfig[HASP_NUM_GPIO_CONFIG]; using namespace ace_button; static AceButton * button[HASP_NUM_INPUTS]; -struct hasp_gpio_config_t { - const uint8_t pin; - const uint8_t group; - const uint8_t io_mode; - bool default_state; +struct hasp_gpio_config_t +{ + const uint8_t pin; + const uint8_t group; + const uint8_t io_mode; + bool default_state; }; // An array of button pins, led pins, and the led states. Cannot be const // because ledState is mutable. - hasp_gpio_config_t gpioConfig2[HASP_NUM_GPIO_CONFIG] = { - {2, 8, INPUT, LOW}, - {3, 9, OUTPUT, LOW}, - {4, 10, INPUT, HIGH}, - {5, 11, OUTPUT, LOW}, - {6, 12, INPUT, LOW}, +hasp_gpio_config_t gpioConfig2[HASP_NUM_GPIO_CONFIG] = { + {2, 8, INPUT, LOW}, {3, 9, OUTPUT, LOW}, {4, 10, INPUT, HIGH}, {5, 11, OUTPUT, LOW}, {6, 12, INPUT, LOW}, }; #if defined(ARDUINO_ARCH_ESP32) class TouchConfig : public ButtonConfig { - public: + public: TouchConfig(); protected: @@ -113,10 +110,9 @@ void IRAM_ATTR gpioLoop(void) } } -void gpioAddButton( uint8_t pin, uint8_t input_mode, uint8_t default_state, uint8_t channel) +void gpioAddButton(uint8_t pin, uint8_t input_mode, uint8_t default_state, uint8_t channel) { - uint8_t i; for(i = 0; i < HASP_NUM_INPUTS; i++) { @@ -147,7 +143,7 @@ void gpioAddButton( uint8_t pin, uint8_t input_mode, uint8_t default_state, uint channel, HASP_NUM_INPUTS); } -void gpioAddTouchButton( uint8_t pin, uint8_t input_mode, uint8_t default_state, uint8_t channel) +void gpioAddTouchButton(uint8_t pin, uint8_t input_mode, uint8_t default_state, uint8_t channel) { uint8_t i; for(i = 0; i < HASP_NUM_INPUTS; i++) { @@ -184,20 +180,20 @@ void gpioSetup() // gpioConfig[0] = PD15 * 256 + 5 + (INPUT << 3); #if defined(ARDUINO_ARCH_ESP8266) - gpioAddButton( D2, INPUT_PULLUP, HIGH, 1); + gpioAddButton(D2, INPUT_PULLUP, HIGH, 1); pinMode(D1, OUTPUT); #endif #if defined(ARDUINO_ARCH_ESP32) - gpioAddButton( D2, INPUT, HIGH, 1); - pinMode(D1, OUTPUT); + // gpioAddButton( D2, INPUT, HIGH, 1); + // pinMode(D1, OUTPUT); #endif for(uint8_t i = 0; i < HASP_NUM_GPIO_CONFIG; i++) { - uint8_t pin = (gpioConfig[i] >> 8) & 0xFF; - uint8_t channel = gpioConfig[i] & 0b111; // 3bit - uint8_t input_mode = (gpioConfig[i] >> 3) & 0b11; // 2bit gpio mode - //uint8_t input_mode = gpioConfig[i].io_mode + uint8_t pin = (gpioConfig[i] >> 8) & 0xFF; + uint8_t channel = gpioConfig[i] & 0b111; // 3bit + uint8_t input_mode = (gpioConfig[i] >> 3) & 0b11; // 2bit gpio mode + // uint8_t input_mode = gpioConfig[i].io_mode uint8_t gpiotype = (gpioConfig[i] >> 5) & 0b111; // 3bit uint8_t default_state = gpioConfig[i] & 0b1; // 1bit: 0=LOW, 1=HIGH @@ -220,7 +216,8 @@ void gpioSetup() switch(gpiotype) { case HASP_GPIO_SWITCH: case HASP_GPIO_BUTTON: - // gpioAddButton(gpioConfig[i].io_mode.pin, input_mode, gpioConfig[i].default_state, gpioConfig[i].group); + // gpioAddButton(gpioConfig[i].io_mode.pin, input_mode, gpioConfig[i].default_state, + // gpioConfig[i].group); break; case HASP_GPIO_RELAY: diff --git a/src/hasp_mqtt.cpp b/src/hasp_mqtt.cpp index d05cc989..690b867c 100644 --- a/src/hasp_mqtt.cpp +++ b/src/hasp_mqtt.cpp @@ -1,5 +1,5 @@ #include "hasp_conf.h" -#if HASP_USE_MQTT>0 +#if HASP_USE_MQTT > 0 #include #include "ArduinoJson.h" @@ -190,7 +190,7 @@ void mqtt_send_statusupdate() snprintf_P(data, sizeof(data), PSTR("{\"status\":\"available\",\"version\":\"%s\",\"uptime\":%lu,"), haspGetVersion().c_str(), long(millis() / 1000)); strcat(buffer, data); -#if HASP_USE_WIFI>0 +#if HASP_USE_WIFI > 0 snprintf_P(buffer, sizeof(buffer), PSTR("\"ssid\":\"%s\",\"rssi\":%i,\"ip\":\"%s\","), WiFi.SSID().c_str(), WiFi.RSSI(), WiFi.localIP().toString().c_str()); strcat(data, buffer); @@ -354,7 +354,7 @@ void mqttReconnect() { String mac = halGetMacAddress(3, ""); mac.toLowerCase(); - memset(mqttClientId, 0 ,sizeof(mqttClientId)); + memset(mqttClientId, 0, sizeof(mqttClientId)); snprintf_P(mqttClientId, sizeof(mqttClientId), PSTR("plate_%s"), mac.c_str()); Log.verbose(mqttClientId); } @@ -479,9 +479,9 @@ void mqttLoop() if(mqttEnabled) mqttClient.loop(); } -void mqttEvery5Seconds(bool wifiIsConnected) +void mqttEvery5Seconds(bool networkIsConnected) { - if(mqttEnabled && wifiIsConnected && !mqttClient.connected()) mqttReconnect(); + if(mqttEnabled && networkIsConnected && !mqttClient.connected()) mqttReconnect(); } String mqttGetNodename() diff --git a/src/hasp_wifi.cpp b/src/hasp_wifi.cpp index 6ee9a419..c03dc2b5 100644 --- a/src/hasp_wifi.cpp +++ b/src/hasp_wifi.cpp @@ -136,6 +136,18 @@ bool wifiShowAP(char * ssid, char * pass) return true; } +void wifiReconnect() +{ + WiFi.disconnect(true); + WiFi.config(INADDR_NONE, INADDR_NONE, INADDR_NONE); +#if defined(ARDUINO_ARCH_ESP8266) + WiFi.hostname(mqttGetNodename().c_str()); +#elif defined(ARDUINO_ARCH_ESP32) + WiFi.setHostname(mqttGetNodename().c_str()); +#endif + WiFi.begin(wifiSsid, wifiPassword); +} + void wifiSetup() { if(wifiShowAP()) { @@ -148,17 +160,12 @@ void wifiSetup() gotIpEventHandler = WiFi.onStationModeGotIP(wifiSTAGotIP); // As soon WiFi is connected, start NTP Client disconnectedEventHandler = WiFi.onStationModeDisconnected(wifiSTADisconnected); WiFi.setSleepMode(WIFI_NONE_SLEEP); -#endif -#if defined(ARDUINO_ARCH_ESP32) +#elif defined(ARDUINO_ARCH_ESP32) WiFi.onEvent(wifi_callback); WiFi.setSleep(false); #endif - WiFi.disconnect(true); - WiFi.config(INADDR_NONE, INADDR_NONE, INADDR_NONE); - WiFi.setHostname(mqttGetNodename().c_str()); - WiFi.begin(wifiSsid, wifiPassword); - + wifiReconnect(); Log.notice(F("WIFI: Connecting to : %s"), wifiSsid); } } @@ -177,10 +184,7 @@ bool wifiEvery5Seconds() } Log.warning(F("WIFI: No Connection... retry %u"), wifiReconnectCounter); if(wifiReconnectCounter % 6 == 0) { - WiFi.disconnect(true); - WiFi.config(INADDR_NONE, INADDR_NONE, INADDR_NONE); - WiFi.setHostname(mqttGetNodename().c_str()); - WiFi.begin(wifiSsid, wifiPassword); + wifiReconnect(); } return false; } From 75819f9e96a8a18966500281cf8f31c1bea3876a Mon Sep 17 00:00:00 2001 From: fvanroie Date: Tue, 3 Nov 2020 23:57:06 +0100 Subject: [PATCH 28/33] Small changes --- src/hasp.cpp | 20 ++++++++++++------- src/hasp_oobe.cpp | 51 +++++++++++++++++++++++++---------------------- src/main.cpp | 7 +++---- 3 files changed, 43 insertions(+), 35 deletions(-) diff --git a/src/hasp.cpp b/src/hasp.cpp index 1745986c..70effb32 100644 --- a/src/hasp.cpp +++ b/src/hasp.cpp @@ -312,6 +312,19 @@ void haspReconnect() lv_obj_set_hidden(obj, true);*/ } +/*Add a custom apply callback*/ +static void custom_font_apply_cb(lv_theme_t * th, lv_obj_t * obj, lv_theme_style_t name) +{ + lv_style_list_t * list; + + switch(name) { + case LV_THEME_BTN: + list = lv_obj_get_style_list(obj, LV_BTN_PART_MAIN); + // _lv_style_list_add_style(list, &my_style); + break; + } +} + /** * Create a demo application */ @@ -319,12 +332,6 @@ void haspSetup() { guiSetDim(haspStartDim); - // lv_coord_t hres = lv_disp_get_hor_res(NULL); - // lv_coord_t vres = lv_disp_get_ver_res(NULL); - - // static lv_font_t * - // my_font = (lv_font_t *)lv_mem_alloc(sizeof(lv_font_t)); - /******* File System Test ********************************************************************/ lv_fs_file_t f; lv_fs_res_t res; @@ -867,7 +874,6 @@ void haspNewObject(const JsonObject & config, uint8_t & saved_page_id) } case LV_HASP_ROLLER: { obj = lv_roller_create(parent_obj, NULL); - bool infinite = config[F("infinite")].as(); // lv_roller_set_fix_width(obj, width); // lv_obj_align(obj, NULL, LV_ALIGN_IN_TOP_MID, 0, 20); lv_obj_set_event_cb(obj, roller_event_handler); diff --git a/src/hasp_oobe.cpp b/src/hasp_oobe.cpp index 842dff03..ec513ead 100644 --- a/src/hasp_oobe.cpp +++ b/src/hasp_oobe.cpp @@ -14,6 +14,8 @@ #include "hasp_config.h" #include "hasp_dispatch.h" +#if HASP_USE_WIFI > 0 + #if HASP_USE_QRCODE > 0 #include "lv_qrcode.h" #endif @@ -73,14 +75,13 @@ static void kb_event_cb(lv_obj_t * event_kb, lv_event_t event) strncpy(pass, lv_textarea_get_text(obj), sizeof(pass)); settings[FPSTR(F_CONFIG_PASS)] = pass; } - #if HASP_USE_WIFI > 0 + if(strlen(ssid) > 0) { wifiSetConfig(settings.as()); if(wifiTestConnection()) { dispatchReboot(true); } } - #endif } else if(event == LV_EVENT_CANCEL) { oobeSetPage(0); @@ -295,10 +296,33 @@ static void oobe_calibrate_cb(lv_obj_t * ta, lv_event_t event) } } + +void oobeFakeSetup() +{ + char ssid[32] = "HASP-ABCDEF"; + char pass[32] = "haspadmin"; + + guiSetDim(100); + oobeSetupQR(ssid, pass); + oobeSetupSsid(); + oobeSetPage(0); + lv_obj_set_click(lv_disp_get_layer_sys(NULL), true); + lv_obj_set_event_cb(lv_disp_get_layer_sys(NULL), gotoPage1_cb); + + if(oobeAutoCalibrate) { + lv_obj_set_click(lv_disp_get_layer_sys(NULL), true); + lv_obj_set_event_cb(lv_disp_get_layer_sys(NULL), oobe_calibrate_cb); + Log.verbose(F("OOBE: Enabled Auto Calibrate on touch")); + } else { + Log.verbose(F("OOBE: Already calibrated")); + } +} +#endif // HASP_USE_WIFI + bool oobeSetup() { #if HASP_USE_ETHERNET > 0 -if (eth_connected) return false; + if(eth_connected) return false; #endif #if HASP_USE_WIFI > 0 char ssid[32]; @@ -325,24 +349,3 @@ if (eth_connected) return false; } #endif } - -void oobeFakeSetup() -{ - char ssid[32] = "HASP-ABCDEF"; - char pass[32] = "haspadmin"; - - guiSetDim(100); - oobeSetupQR(ssid, pass); - oobeSetupSsid(); - oobeSetPage(0); - lv_obj_set_click(lv_disp_get_layer_sys(NULL), true); - lv_obj_set_event_cb(lv_disp_get_layer_sys(NULL), gotoPage1_cb); - - if(oobeAutoCalibrate) { - lv_obj_set_click(lv_disp_get_layer_sys(NULL), true); - lv_obj_set_event_cb(lv_disp_get_layer_sys(NULL), oobe_calibrate_cb); - Log.verbose(F("OOBE: Enabled Auto Calibrate on touch")); - } else { - Log.verbose(F("OOBE: Already calibrated")); - } -} \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index c7c4f5b8..97fdd538 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -109,18 +109,19 @@ void loop() /* Graphics Loops */ // tftLoop(); guiLoop(); + /* Application Loops */ // haspLoop(); debugLoop(); #if HASP_USE_GPIO > 0 gpioLoop(); -#endif +#endif // GPIO /* Network Services Loops */ #if HASP_USE_ETHERNET > 0 ethernetLoop(); -#endif +#endif // ETHERNET #if HASP_USE_MQTT > 0 mqttLoop(); @@ -146,8 +147,6 @@ void loop() slaveLoop(); #endif // TASMOTASLAVE - // digitalWrite(HASP_OUTPUT_PIN, digitalRead(HASP_INPUT_PIN)); // sets the LED to the button's value - /* Timer Loop */ if(millis() - mainLastLoopTime >= 1000) { /* Run Every Second */ From 4d74a4037ac0804370fba58f68e33dc3b2f4372a Mon Sep 17 00:00:00 2001 From: fvanroie Date: Wed, 4 Nov 2020 00:15:39 +0100 Subject: [PATCH 29/33] Fix build errors --- src/hasp.cpp | 5 ++-- src/hasp_oobe.cpp | 59 ++++++++++++++++++++++++--------------------- src/hasp_telnet.cpp | 6 ++--- 3 files changed, 37 insertions(+), 33 deletions(-) diff --git a/src/hasp.cpp b/src/hasp.cpp index 70effb32..fee6dff3 100644 --- a/src/hasp.cpp +++ b/src/hasp.cpp @@ -148,7 +148,8 @@ bool get_page_id(lv_obj_t * obj, uint8_t * pageid) lv_obj_t * hasp_find_obj_from_id(lv_obj_t * parent, uint8_t objid) { - if(objid == 0) return parent; + if(objid == 0 || parent == nullptr) return parent; + lv_obj_t * child; child = lv_obj_get_child(parent, NULL); while(child) { @@ -873,7 +874,7 @@ void haspNewObject(const JsonObject & config, uint8_t & saved_page_id) break; } case LV_HASP_ROLLER: { - obj = lv_roller_create(parent_obj, NULL); + obj = lv_roller_create(parent_obj, NULL); // lv_roller_set_fix_width(obj, width); // lv_obj_align(obj, NULL, LV_ALIGN_IN_TOP_MID, 0, 20); lv_obj_set_event_cb(obj, roller_event_handler); diff --git a/src/hasp_oobe.cpp b/src/hasp_oobe.cpp index ec513ead..479a7e9c 100644 --- a/src/hasp_oobe.cpp +++ b/src/hasp_oobe.cpp @@ -14,6 +14,8 @@ #include "hasp_config.h" #include "hasp_dispatch.h" +static bool oobeAutoCalibrate = true; + #if HASP_USE_WIFI > 0 #if HASP_USE_QRCODE > 0 @@ -23,15 +25,9 @@ static lv_obj_t * oobepage[2]; static lv_obj_t * oobekb; extern lv_font_t * defaultFont; -static bool oobeAutoCalibrate = true; lv_obj_t * pwd_ta; -void oobeSetAutoCalibrate(bool cal) -{ - oobeAutoCalibrate = cal; -} - static inline void oobeSetPage(uint8_t pageid) { lv_scr_load(oobepage[pageid]); @@ -295,30 +291,13 @@ static void oobe_calibrate_cb(lv_obj_t * ta, lv_event_t event) } } } - - -void oobeFakeSetup() -{ - char ssid[32] = "HASP-ABCDEF"; - char pass[32] = "haspadmin"; - - guiSetDim(100); - oobeSetupQR(ssid, pass); - oobeSetupSsid(); - oobeSetPage(0); - lv_obj_set_click(lv_disp_get_layer_sys(NULL), true); - lv_obj_set_event_cb(lv_disp_get_layer_sys(NULL), gotoPage1_cb); - - if(oobeAutoCalibrate) { - lv_obj_set_click(lv_disp_get_layer_sys(NULL), true); - lv_obj_set_event_cb(lv_disp_get_layer_sys(NULL), oobe_calibrate_cb); - Log.verbose(F("OOBE: Enabled Auto Calibrate on touch")); - } else { - Log.verbose(F("OOBE: Already calibrated")); - } -} #endif // HASP_USE_WIFI +void oobeSetAutoCalibrate(bool cal) +{ + oobeAutoCalibrate = cal; +} + bool oobeSetup() { #if HASP_USE_ETHERNET > 0 @@ -348,4 +327,28 @@ bool oobeSetup() return false; } #endif + return false; } + +void oobeFakeSetup() +{ +#if HASP_USE_WIFI > 0 + char ssid[32] = "HASP-ABCDEF"; + char pass[32] = "haspadmin"; + + guiSetDim(100); + oobeSetupQR(ssid, pass); + oobeSetupSsid(); + oobeSetPage(0); + lv_obj_set_click(lv_disp_get_layer_sys(NULL), true); + lv_obj_set_event_cb(lv_disp_get_layer_sys(NULL), gotoPage1_cb); + + if(oobeAutoCalibrate) { + lv_obj_set_click(lv_disp_get_layer_sys(NULL), true); + lv_obj_set_event_cb(lv_disp_get_layer_sys(NULL), oobe_calibrate_cb); + Log.verbose(F("OOBE: Enabled Auto Calibrate on touch")); + } else { + Log.verbose(F("OOBE: Already calibrated")); + } +#endif +} \ No newline at end of file diff --git a/src/hasp_telnet.cpp b/src/hasp_telnet.cpp index 365d8eeb..8c109e2b 100644 --- a/src/hasp_telnet.cpp +++ b/src/hasp_telnet.cpp @@ -77,7 +77,7 @@ void telnetAcceptClient() telnetClient.stop(); // client disconnected Log.unregisterOutput(1); // telnetClient } - telnetClient = telnetServer.available(); // ready for new client + telnetClient = telnetServer->available(); // ready for new client // Log.notice(F("Client connected from %s"), telnetClient.remoteIP().toString().c_str()); if(!telnetClient) { Log.notice(F("Client NOT connected")); @@ -199,7 +199,7 @@ void telnetSetup() #if defined(STM32F4xx) // if(!telnetServer) telnetServer = new EthernetServer(telnetPort); // if(telnetServer) { - telnetServer.begin(); + telnetServer->begin(); Log.notice(F("Debug telnet console started")); // } else { // Log.error(F("Failed to start telnet server")); @@ -232,7 +232,7 @@ void IRAM_ATTR telnetLoop() Ethernet.schedule(); // if(telnetServer) { // client is connected - EthernetClient client = telnetServer.available(); + EthernetClient client = telnetServer->available(); if(client) { if(!telnetClient || !telnetClient.connected()) { //telnetAcceptClient(client); From 88880a94193fe528feb2efb264a00bc7270adb78 Mon Sep 17 00:00:00 2001 From: fvanroie Date: Sun, 8 Nov 2020 13:36:47 +0100 Subject: [PATCH 30/33] Update platform version --- platformio.ini | 48 +++++++++---------- user_setups/esp32/TTGO-esp32-POE_ili9341.ini | 2 +- user_setups/esp32/d1-mini-esp32_ili9341.ini | 10 ++-- .../esp32/d132-unoshield_ili9486_parallel.ini | 2 +- user_setups/esp32/esp32-dev_ili9488.ini | 2 +- .../esp32/esp32-dev_ili9488_parallel.ini | 2 +- user_setups/esp32/esp32cam_st7796.ini | 2 +- user_setups/esp32/nodemcu-32s_st7796.ini | 2 +- user_setups/esp8266/D1-mini_ili9341.ini | 2 +- user_setups/esp8266/esp8266_st7735.ini | 2 +- 10 files changed, 39 insertions(+), 35 deletions(-) diff --git a/platformio.ini b/platformio.ini index 45fe4f22..9af32822 100644 --- a/platformio.ini +++ b/platformio.ini @@ -134,7 +134,7 @@ hspi32 = ;*************************************************** ; !! This board already defines TFT_CS, TFT_DC and TFT_RST !! [env:lolind32pro-lolintft24] -platform = espressif32 +platform = espressif32@^2.0.0 board = lolin_d32_pro upload_port = COM6 ; To change the port, use platform_override.ini monitor_port = COM6 ; To change the port, use platform_override.ini @@ -155,7 +155,7 @@ build_flags = ; D1 Mini ESP8266 with Lolin TFT 2.4" ;*************************************************** [env:d1mini-lolintft24] -platform = espressif8266@^2.4.0 ;@2.3.2 +platform = espressif8266@^2.6.2 board = d1_mini ;upload_port = To change the port, use platform_override.ini ;monitor_port = To change the port, use platform_override.ini @@ -180,25 +180,25 @@ build_flags = ;*************************************************** ; Native build ;*************************************************** -[env:native] -platform = native -build_flags = - -D LV_CONF_INCLUDE_SIMPLE - ; -I src Required to find lv_conf.h - -I src - -I drivers/sdl2 - -lSDL2 - ; SDL drivers options - -D LV_LVGL_H_INCLUDE_SIMPLE - -D LV_DRV_NO_CONF - -D USE_MONITOR - -D MONITOR_ZOOM=2 - -D USE_MOUSE - -D USE_MOUSEWHEEL - -D USE_KEYBOARD -lib_deps = - ;lvgl=https://github.com/littlevgl/lvgl/archive/master.zip - ;lvgl@^6.1.0 - ;lv_drivers=https://github.com/littlevgl/lv_drivers/archive/master.zip - lv_drivers@^6.0.2 -src_filter = +<*> +<../drivers/sdl2> +;[env:native] +;platform = native +;build_flags = +; -D LV_CONF_INCLUDE_SIMPLE +; ; -I src Required to find lv_conf.h +; -I src +; -I drivers/sdl2 +; -lSDL2 +; ; SDL drivers options +; -D LV_LVGL_H_INCLUDE_SIMPLE +; -D LV_DRV_NO_CONF +; -D USE_MONITOR +; -D MONITOR_ZOOM=2 +; -D USE_MOUSE +; -D USE_MOUSEWHEEL +; -D USE_KEYBOARD +;lib_deps = +; ;lvgl=https://github.com/littlevgl/lvgl/archive/master.zip +; ;lvgl@^6.1.0 +; ;lv_drivers=https://github.com/littlevgl/lv_drivers/archive/master.zip +; lv_drivers@^6.0.2 +;src_filter = +<*> +<../drivers/sdl2> diff --git a/user_setups/esp32/TTGO-esp32-POE_ili9341.ini b/user_setups/esp32/TTGO-esp32-POE_ili9341.ini index 47724a49..0c896838 100644 --- a/user_setups/esp32/TTGO-esp32-POE_ili9341.ini +++ b/user_setups/esp32/TTGO-esp32-POE_ili9341.ini @@ -7,7 +7,7 @@ ;***************************************************; [env:ttgo_esp32-lolintft24] -platform = espressif32@^1.12.0 +platform = espressif32@^2.0.0 board = esp32dev upload_protocol = espota ; Use ArduinoOTA after flashing over serial upload_port = 10.4.70.37 ; 10.4.0.198 ; IP of the ESP diff --git a/user_setups/esp32/d1-mini-esp32_ili9341.ini b/user_setups/esp32/d1-mini-esp32_ili9341.ini index f05e45a8..7d8758cf 100644 --- a/user_setups/esp32/d1-mini-esp32_ili9341.ini +++ b/user_setups/esp32/d1-mini-esp32_ili9341.ini @@ -6,10 +6,14 @@ ;***************************************************; [env:d1mini32-lolintft24] -platform = espressif32@^1.12.0 +platform = espressif32@^2.0.0 board = wemos_d1_mini32 -upload_port = COM6 ; To change the port, use platform_override.ini -monitor_port = COM6 ; To change the port, use platform_override.ini +monitor_port = COM6 ; To change the port, use platform_override.ini +upload_port = COM6 ; To change the port, use platform_override.ini +;upload_protocol = espota ; You can switch to ArduinoOTA after flashing over serial once +;upload_port = 10.1.0.113 ; IP of the ESP +;upload_flags = +; --port=3232 board_build.partitions = esp32_partition_app1300k_spiffs1216k.csv ; default.csv build_flags = ${flags.esp32_flags} diff --git a/user_setups/esp32/d132-unoshield_ili9486_parallel.ini b/user_setups/esp32/d132-unoshield_ili9486_parallel.ini index e3c45355..8a1b8255 100644 --- a/user_setups/esp32/d132-unoshield_ili9486_parallel.ini +++ b/user_setups/esp32/d132-unoshield_ili9486_parallel.ini @@ -5,7 +5,7 @@ ;***************************************************; [env:d132-unoshield] -platform = espressif32 +platform = espressif32@^2.0.0 board = esp32dev upload_port = COM4 ; To change the port, use platform_override.ini monitor_port = COM4 ; To change the port, use platform_override.ini diff --git a/user_setups/esp32/esp32-dev_ili9488.ini b/user_setups/esp32/esp32-dev_ili9488.ini index b3fac875..9666cc53 100644 --- a/user_setups/esp32/esp32-dev_ili9488.ini +++ b/user_setups/esp32/esp32-dev_ili9488.ini @@ -5,7 +5,7 @@ ;***************************************************; [env:esp32dev-ili9488] -platform = espressif32 +platform = espressif32@^2.0.0 board = esp32dev upload_port = COM2 ; To change the port, use platform_override.ini monitor_port = COM2 ; To change the port, use platform_override.ini diff --git a/user_setups/esp32/esp32-dev_ili9488_parallel.ini b/user_setups/esp32/esp32-dev_ili9488_parallel.ini index 52e79ade..698a6db1 100644 --- a/user_setups/esp32/esp32-dev_ili9488_parallel.ini +++ b/user_setups/esp32/esp32-dev_ili9488_parallel.ini @@ -6,7 +6,7 @@ ;***************************************************; [env:esp32dev-mrb3511] -platform = espressif32 +platform = espressif32@^2.0.0 board = esp32dev upload_port = COM1 ; To change the port, use platform_override.ini monitor_port = COM1 ; To change the port, use platform_override.ini diff --git a/user_setups/esp32/esp32cam_st7796.ini b/user_setups/esp32/esp32cam_st7796.ini index cc111771..288c8205 100644 --- a/user_setups/esp32/esp32cam_st7796.ini +++ b/user_setups/esp32/esp32cam_st7796.ini @@ -6,7 +6,7 @@ ;***************************************************; [env:esp32cam-st7796] -platform = espressif32 +platform = espressif32@^2.0.0 board = esp32cam ; upload_port = COM18 ; To change the port, use platform_override.ini ; monitor_port = COM18 ; To change the port, use platform_override.ini diff --git a/user_setups/esp32/nodemcu-32s_st7796.ini b/user_setups/esp32/nodemcu-32s_st7796.ini index 9ccd8f96..275f2ef9 100644 --- a/user_setups/esp32/nodemcu-32s_st7796.ini +++ b/user_setups/esp32/nodemcu-32s_st7796.ini @@ -6,7 +6,7 @@ ;***************************************************; [env:nodemcu32s-raspi] -platform = espressif32 +platform = espressif32@^2.0.0 board = nodemcu-32s upload_port = COM3 ; To change the port, use platform_override.ini monitor_port = COM3 ; To change the port, use platform_override.ini diff --git a/user_setups/esp8266/D1-mini_ili9341.ini b/user_setups/esp8266/D1-mini_ili9341.ini index bd669242..16f694a7 100644 --- a/user_setups/esp8266/D1-mini_ili9341.ini +++ b/user_setups/esp8266/D1-mini_ili9341.ini @@ -6,7 +6,7 @@ ;***************************************************; [env:d1mini-lolintft24] -platform = espressif8266@^2.4.0 ;@2.3.2 +platform = espressif8266@^2.6.2 board = d1_mini upload_port = COM7 ; To change the port, use platform_override.ini monitor_port = COM7 ; To change the port, use platform_override.ini diff --git a/user_setups/esp8266/esp8266_st7735.ini b/user_setups/esp8266/esp8266_st7735.ini index 077eec02..8e6bf583 100644 --- a/user_setups/esp8266/esp8266_st7735.ini +++ b/user_setups/esp8266/esp8266_st7735.ini @@ -5,7 +5,7 @@ ;***************************************************; [env:esp12e-st7735] -platform = espressif8266@^2.4.0 ;@2.3.2 +platform = espressif8266@^2.6.2 board = esp12e upload_port = COM8 ; To change the port, use platform_override.ini monitor_port = COM8 ; To change the port, use platform_override.ini From 8d27895a4f62d3b817c53abcc0cc04bb16d04770 Mon Sep 17 00:00:00 2001 From: fvanroie Date: Sun, 8 Nov 2020 17:31:28 +0100 Subject: [PATCH 31/33] Wfi fix ESP8266 --- src/hasp_wifi.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hasp_wifi.cpp b/src/hasp_wifi.cpp index c03dc2b5..04b07048 100644 --- a/src/hasp_wifi.cpp +++ b/src/hasp_wifi.cpp @@ -139,10 +139,10 @@ bool wifiShowAP(char * ssid, char * pass) void wifiReconnect() { WiFi.disconnect(true); - WiFi.config(INADDR_NONE, INADDR_NONE, INADDR_NONE); #if defined(ARDUINO_ARCH_ESP8266) WiFi.hostname(mqttGetNodename().c_str()); #elif defined(ARDUINO_ARCH_ESP32) + WiFi.config(INADDR_NONE, INADDR_NONE, INADDR_NONE); WiFi.setHostname(mqttGetNodename().c_str()); #endif WiFi.begin(wifiSsid, wifiPassword); From 3d5d77928a606e7de0c6b6ad5448de7b253c7a92 Mon Sep 17 00:00:00 2001 From: fvanroie Date: Sun, 8 Nov 2020 17:35:24 +0100 Subject: [PATCH 32/33] Fix priority order of the extra_configs --- platformio.ini | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/platformio.ini b/platformio.ini index 9af32822..4214dcc4 100644 --- a/platformio.ini +++ b/platformio.ini @@ -16,11 +16,11 @@ extra_configs = lcd_config.ini pin_config.ini + ; -- Put active [env] files in this dir to be included in the build menu + user_setups/*/*.ini + user_setups/active/*.ini ; -- Add customizations to this file only: platformio_override.ini - ; -- Put active [env] files in this dir to be included in the build menu - user_setups/active/*.ini - user_setups/*/*.ini default_envs = ; Uncomment the needed environments in platformio_override.ini From 86629356768ed5c091fdd6d50cf9b5afd699cbee Mon Sep 17 00:00:00 2001 From: fvanroie Date: Sun, 8 Nov 2020 22:42:27 +0100 Subject: [PATCH 33/33] Dispatcher rewrite --- include/hasp_conf.h | 2 +- src/hasp.cpp | 5 +- src/hasp_debug.cpp | 14 +- src/hasp_dispatch.cpp | 370 +++++++++++++------- src/hasp_dispatch.h | 25 +- src/hasp_gui.cpp | 6 +- src/hasp_http.cpp | 4 +- src/hasp_mqtt.cpp | 43 +-- src/hasp_slave.cpp | 4 +- src/hasp_telnet.cpp | 2 +- user_setups/esp32/d1-mini-esp32_ili9341.ini | 1 + 11 files changed, 279 insertions(+), 197 deletions(-) diff --git a/include/hasp_conf.h b/include/hasp_conf.h index 7b00cac0..5793cb7a 100644 --- a/include/hasp_conf.h +++ b/include/hasp_conf.h @@ -3,7 +3,7 @@ #define HASP_VERSION_MAJOR 0 #define HASP_VERSION_MINOR 2 -#define HASP_VERSION_REVISION 1027 +#define HASP_VERSION_REVISION 1108 #define HASP_USE_APP 1 diff --git a/src/hasp.cpp b/src/hasp.cpp index fee6dff3..f4042c37 100644 --- a/src/hasp.cpp +++ b/src/hasp.cpp @@ -122,6 +122,7 @@ lv_obj_t * get_page(uint8_t pageid) if(pageid >= sizeof pages / sizeof *pages) return NULL; return pages[pageid]; } + bool get_page_id(lv_obj_t * obj, uint8_t * pageid) { lv_obj_t * page = lv_obj_get_screen(obj); @@ -671,7 +672,7 @@ String haspGetVersion() void haspClearPage(uint16_t pageid) { lv_obj_t * page = get_page(pageid); - if(!page) { + if(!page || pageid > 255) { Log.warning(F("HASP: Page ID %u not defined"), pageid); } else if(page == lv_layer_sys() /*|| page == lv_layer_top()*/) { Log.warning(F("HASP: Cannot clear system layer")); @@ -946,7 +947,7 @@ void haspLoadPage(const char * pages) Log.notice(F("HASP: Loading file %s"), pages); File file = SPIFFS.open(pages, "r"); - dispatchJsonl(file); + dispatchParseJsonl(file); file.close(); Log.notice(F("HASP: File %s loaded"), pages); diff --git a/src/hasp_debug.cpp b/src/hasp_debug.cpp index ff5f291e..739005ac 100644 --- a/src/hasp_debug.cpp +++ b/src/hasp_debug.cpp @@ -392,18 +392,18 @@ void debugLoop() Serial.print(ch); if(ch == 13 || ch == 10) { serialInputBuffer[serialInputIndex] = 0; - if(serialInputIndex > 0) dispatchCommand(serialInputBuffer); + if(serialInputIndex > 0) dispatchTextLine(serialInputBuffer); serialInputIndex = 0; } else { if(serialInputIndex < sizeof(serialInputBuffer) - 1) { serialInputBuffer[serialInputIndex++] = ch; } - serialInputBuffer[serialInputIndex] = 0; - if(strcmp(serialInputBuffer, "jsonl=") == 0) { - dispatchJsonl(Serial); - serialInputIndex = 0; - } + // if(strcmp(serialInputBuffer, "jsonl=") == 0) { + // dispatchJsonl(Serial); + // serialInputIndex = 0; + // } } + serialInputBuffer[serialInputIndex] = 0; } } @@ -448,7 +448,7 @@ void debugLoop() void debugEverySecond() { if(debugTelePeriod > 0 && (millis() - debugLastMillis) >= debugTelePeriod * 1000) { - dispatchStatusUpdate(); + dispatch_output_statusupdate(); debugLastMillis = millis(); } // printLocalTime(); diff --git a/src/hasp_dispatch.cpp b/src/hasp_dispatch.cpp index 9f5c0f69..58ae1cf5 100644 --- a/src/hasp_dispatch.cpp +++ b/src/hasp_dispatch.cpp @@ -13,43 +13,47 @@ #include "hasp_conf.h" -inline void dispatchPrintln(String header, String & data) -{ - Log.notice(F("%s: %s"), header.c_str(), data.c_str()); -} - -bool isON(const char * payload) +inline bool isON(const char * payload) { return strcasecmp_P(payload, PSTR("ON")) == 0; } -String getOnOff(bool state) -{ - String result((char *)0); - result.reserve(128); - result = state ? F("ON") : F("OFF"); - return result; -} - void dispatchSetup() {} void dispatchLoop() {} -void dispatchStatusUpdate() +// Send status update message to the client +void dispatch_output_statusupdate() { -#if HASP_USE_MQTT>0 +#if HASP_USE_MQTT > 0 mqtt_send_statusupdate(); #endif } -void dispatchOutput(int output, bool state) +// Format filesystem and erase EEPROM +bool dispatch_factory_reset() +{ + bool formated, erased = true; + +#if HASP_USE_SPIFFS > 0 + formated = SPIFFS.format(); +#endif + +#if HASP_USE_EEPROM > 0 + erased = false; +#endif + + return formated && erased; +} + +void dispatchGpioOutput(int output, bool state) { int pin = 0; if(pin >= 0) { - Log.notice(F("PIN OUTPUT STATE %d"),state); + Log.notice(F("PIN OUTPUT STATE %d"), state); #if defined(ARDUINO_ARCH_ESP32) ledcWrite(99, state ? 1023 : 0); // ledChannel and value @@ -62,16 +66,63 @@ void dispatchOutput(int output, bool state) } } -void dispatchOutput(String strTopic, const char * payload) +void dispatchGpioOutput(String strTopic, const char * payload) { String strTemp((char *)0); strTemp.reserve(128); strTemp = strTopic.substring(7, strTopic.length()); - dispatchOutput(strTemp.toInt(), isON(payload)); + dispatchGpioOutput(strTemp.toInt(), isON(payload)); } -void dispatchButtonAttribute(String & strTopic, const char * payload) +void dispatchParseJson(char * payload) +{ // Parse an incoming JSON array into individual commands + /* if(strPayload.endsWith(",]")) { + // Trailing null array elements are an artifact of older Home Assistant automations + // and need to be removed before parsing by ArduinoJSON 6+ + strPayload.remove(strPayload.length() - 2, 2); + strPayload.concat("]"); + }*/ + size_t maxsize = (128u * ((strlen(payload) / 128) + 1)) + 256; + DynamicJsonDocument haspCommands(maxsize); + DeserializationError jsonError = deserializeJson(haspCommands, payload); + // haspCommands.shrinkToFit(); + + if(jsonError) { // Couldn't parse incoming JSON command + Log.warning(F("JSON: Failed to parse incoming JSON command with error: %s"), jsonError.c_str()); + } else { + + JsonArray arr = haspCommands.as(); + for(JsonVariant command : arr) { + dispatchTextLine(command.as().c_str()); + } + } +} + +void dispatchParseJsonl(Stream & stream) { + DynamicJsonDocument jsonl(3 * 128u); + uint8_t savedPage = haspGetPage(); + + // Log.notice(F("DISPATCH: jsonl")); + + while(deserializeJson(jsonl, stream) == DeserializationError::Ok) { + // serializeJson(jsonl, Serial); + // Serial.println(); + haspNewObject(jsonl.as(), savedPage); + } +} + +void dispatchParseJsonl(char * payload) +{ + CharStream stream(payload); + dispatchParseJsonl(stream); +} + +// p[x].b[y]=value +inline void dispatch_process_button_attribute(String strTopic, const char * payload) +{ + // Log.trace(F("BTN ATTR: %s = %s"), strTopic.c_str(), payload); + String strPageId((char *)0); String strTemp((char *)0); @@ -96,199 +147,246 @@ void dispatchButtonAttribute(String & strTopic, const char * payload) } // objectattribute=value -void dispatchAttribute(String strTopic, const char * payload) +void dispatchCommand(const char * topic, const char * payload) { - if(strTopic.startsWith("p[")) { - dispatchButtonAttribute(strTopic, payload); + if(!strcmp_P(topic, PSTR("json"))) { // '[...]/device/command/json' -m '["dim=5", "page 1"]' = + // nextionSendCmd("dim=50"), nextionSendCmd("page 1") + dispatchParseJson((char *)payload); - } else if(strTopic == F("page")) { + } else if(!strcmp_P(topic, PSTR("jsonl"))) { + dispatchParseJsonl((char *)payload); + + } else if(!strcmp_P(topic, PSTR("page"))) { dispatchPage(payload); - } else if(strTopic == F("dim") || strTopic == F("brightness")) { + } else if(!strcmp_P(topic, PSTR("dim")) || !strcmp_P(topic, PSTR("brightness"))) { dispatchDim(payload); - } else if(strTopic == F("light")) { + } else if(!strcmp_P(topic, PSTR("light"))) { dispatchBacklight(payload); - } else if(strTopic == F("reboot") || strTopic == F("restart")) { + } else if(!strcmp_P(topic, PSTR("reboot")) || !strcmp_P(topic, PSTR("restart"))) { dispatchReboot(true); - } else if(strTopic == F("clearpage")) { + } else if(!strcmp_P(topic, PSTR("factoryreset"))) { + dispatch_factory_reset(); + delay(250); + dispatchReboot(false); // don't save config + + } else if(!strcmp_P(topic, PSTR("clearpage"))) { dispatchClearPage(payload); - } else if(strTopic == F("update")) { + } else if(!strcmp_P(topic, PSTR("update"))) { dispatchWebUpdate(payload); - } else if(strTopic == F("setupap")) { + } else if(!strcmp_P(topic, PSTR("setupap"))) { oobeFakeSetup(); - } else if(strTopic.length() == 7 && strTopic.startsWith(F("output"))) { - dispatchOutput(strTopic, payload); - } -} + } else if(strlen(topic) == 7 && topic == strstr_P(topic, PSTR("output"))) { + dispatchGpioOutput(topic, payload); -void dispatchPage(String strPageid) -{ - dispatchPrintln(F("PAGE"), strPageid); + } else if(strcasecmp_P(topic, PSTR("calibrate")) == 0) { + guiCalibrate(); + + } else if(strcasecmp_P(topic, PSTR("wakeup")) == 0) { + haspWakeUp(); + + } else if(strcasecmp_P(topic, PSTR("screenshot")) == 0) { + guiTakeScreenshot("/screenhot.bmp"); + + } else if(strcasecmp_P(topic, PSTR("")) == 0 || strcasecmp_P(topic, PSTR("statusupdate")) == 0) { + dispatch_output_statusupdate(); + + } else if(topic == strstr_P(topic, PSTR("p["))) { + dispatch_process_button_attribute(topic, payload); + + } else if(!strcmp_P(topic, F_CONFIG_SSID) || !strcmp_P(topic, F_CONFIG_PASS)) { + DynamicJsonDocument settings(45); + settings[topic] = payload; + wifiSetConfig(settings.as()); + + } else if(!strcmp_P(topic, PSTR("mqtthost")) || !strcmp_P(topic, PSTR("mqttport")) || + !strcmp_P(topic, PSTR("mqttuser")) || !strcmp_P(topic, PSTR("mqttpass"))) { + char item[5]; + memset(item, 0, sizeof(item)); + strncpy(item, topic + 4, 4); + DynamicJsonDocument settings(45); + settings[item] = payload; + mqttSetConfig(settings.as()); - if(strPageid.length() == 0) { } else { - if(strPageid.toInt() <= 250) haspSetPage(strPageid.toInt()); + if(strlen(payload) == 0) { + // dispatchTextLine(topic); // Could cause an infinite loop! + } + Log.warning(F(LOG_CMND_CTR "Command not found %s => %s"), topic, payload); } - String strPage((char *)0); - strPage.reserve(128); - strPage = haspGetPage(); +} + +// Get or Set a page +void dispatchPage(const char * page) +{ + // dispatchPrintln(F("PAGE"), strPageid); + + if(strlen(page) > 0 && atoi(page) <= 250) { + haspSetPage(atoi(page)); + } + + // Log result + char buffer[4]; + itoa(haspGetPage(), buffer, DEC); + #if HASP_USE_MQTT > 0 - mqtt_send_state(F("page"), strPage.c_str()); + mqtt_send_state(F("page"), buffer); #endif + #if HASP_USE_TASMOTA_SLAVE > 0 - slave_send_state(F("page"), strPage.c_str()); + slave_send_state(F("page"), buffer); #endif } -void dispatchClearPage(String strPageid) +// Clears a page id or the current page if empty +void dispatchClearPage(const char * page) { - dispatchPrintln(F("CLEAR"), strPageid); - - if(strPageid.length() == 0) { + if(strlen(page) == 0) { haspClearPage(haspGetPage()); } else { - haspClearPage(strPageid.toInt()); + haspClearPage(atoi(page)); } } -void dispatchDim(String strDimLevel) +void dispatchDim(const char * level) { // Set the current state - if(strDimLevel.length() != 0) guiSetDim(strDimLevel.toInt()); - dispatchPrintln(F("DIM"), strDimLevel); - char buffer[8]; + if(strlen(level) != 0) guiSetDim(atoi(level)); + // dispatchPrintln(F("DIM"), strDimLevel); + char buffer[4]; + #if defined(HASP_USE_MQTT) || defined(HASP_USE_TASMOTA_SLAVE) itoa(guiGetDim(), buffer, DEC); + #if HASP_USE_MQTT > 0 mqtt_send_state(F("dim"), buffer); #endif + #if HASP_USE_TASMOTA_SLAVE > 0 slave_send_state(F("dim"), buffer); #endif + #endif } -void dispatchBacklight(String strPayload) +void dispatchBacklight(const char * payload) { - strPayload.toUpperCase(); - dispatchPrintln(F("LIGHT"), strPayload); + // strPayload.toUpperCase(); + // dispatchPrintln(F("LIGHT"), strPayload); // Set the current state - if(strPayload.length() != 0) guiSetBacklight(isON(strPayload.c_str())); + if(strlen(payload) != 0) guiSetBacklight(isON(payload)); - // Return the current state - strPayload = getOnOff(guiGetBacklight()); + // Return the current state #if HASP_USE_MQTT > 0 - mqtt_send_state(F("light"), strPayload.c_str()); -#endif -#if HASP_USE_TASMOTA_SLAVE > 0 - slave_send_state(F("light"), strPayload.c_str()); + mqtt_send_state(F("light"), guiGetBacklight() ? PSTR("ON") : PSTR("OFF")); #endif +#if HASP_USE_TASMOTA_SLAVE > 0 + slave_send_state(F("light"), guiGetBacklight() ? PSTR("ON") : PSTR("OFF")); +#endif } -void dispatchCommand(String cmnd) +// Strip command/config prefix from the topic and process the payload +void dispatchTopicPayload(const char * topic, const char * payload) { - dispatchPrintln(F("CMND"), cmnd); + // Log.trace(F("TOPIC: short topic: %s"), topic); + + if(!strcmp_P(topic, PSTR("command"))) { + dispatchTextLine((char *)payload); + return; + } + + if(topic == strstr_P(topic, PSTR("command/"))) { // startsWith command/ + topic += 8u; + // Log.trace(F("MQTT IN: command subtopic: %s"), topic); + + // '[...]/device/command/p[1].b[4].txt' -m '"Lights On"' == + // nextionSetAttr("p[1].b[4].txt", "\"Lights On\"") + dispatchCommand(topic, (char *)payload); + + return; + } + + if(topic == strstr_P(topic, PSTR("config/"))) { // startsWith command/ + topic += 7u; + dispatchConfig(topic, (char *)payload); + return; + } + + dispatchCommand(topic, (char *)payload); // dispatch as is +} + +// Parse one line of text and execute the command(s) +void dispatchTextLine(const char * cmnd) +{ + // dispatchPrintln(F("CMND"), cmnd); + + if(cmnd == strstr_P(cmnd, PSTR("page "))) { // startsWith command/ + dispatchPage(cmnd + 5); - if(cmnd.startsWith(F("page "))) { - cmnd = cmnd.substring(5, cmnd.length()); - String strTopic((char *)0); - strTopic.reserve(128); - strTopic = F("page"); - dispatchAttribute(strTopic, cmnd.c_str()); - } else if(cmnd == F("calibrate")) { - guiCalibrate(); - } else if(cmnd == F("wakeup")) { - haspWakeUp(); - } else if(cmnd == F("screenshot")) { - // guiTakeScreenshot("/screenhot.bmp"); - } else if(cmnd == F("") || cmnd == F("statusupdate")) { - dispatchStatusUpdate(); } else { + size_t pos1 = std::string(cmnd).find("="); + size_t pos2 = std::string(cmnd).find(" "); + int pos = 0; + + if(pos1 != std::string::npos) { + if(pos2 != std::string::npos) { + pos = (pos1 < pos2 ? pos1 : pos2); + } else { + pos = pos1; + } + + } else if(pos2 != std::string::npos) { + pos = pos2; + } else { + pos = 0; + } - int pos = cmnd.indexOf("="); if(pos > 0) { String strTopic((char *)0); - String strPayload((char *)0); + // String strPayload((char *)0); - strTopic.reserve(128); - strPayload.reserve(128); + strTopic.reserve(pos + 1); + // strPayload.reserve(128); - strTopic = cmnd.substring(0, pos); - strPayload = cmnd.substring(pos + 1, cmnd.length()); + strTopic = String(cmnd).substring(0, pos); + // strPayload = cmnd.substring(pos + 1, cmnd.length()); + // cmnd[pos] = 0; // change '=' character into '\0' - dispatchAttribute(strTopic, strPayload.c_str()); + dispatchTopicPayload(strTopic.c_str(), + cmnd + pos + 1); // topic is before '=', payload is after '=' position } else { - dispatchAttribute(cmnd, ""); + dispatchTopicPayload(cmnd, ""); } } } -void dispatchJson(char * payload) -{ // Parse an incoming JSON array into individual commands - /* if(strPayload.endsWith(",]")) { - // Trailing null array elements are an artifact of older Home Assistant automations - // and need to be removed before parsing by ArduinoJSON 6+ - strPayload.remove(strPayload.length() - 2, 2); - strPayload.concat("]"); - }*/ - size_t maxsize = (128u * ((strlen(payload) / 128) + 1)) + 256; - DynamicJsonDocument haspCommands(maxsize); - DeserializationError jsonError = deserializeJson(haspCommands, payload); - // haspCommands.shrinkToFit(); - - if(jsonError) { // Couldn't parse incoming JSON command - Log.warning(F("JSON: Failed to parse incoming JSON command with error: %s"), jsonError.c_str()); - } else { - - JsonArray arr = haspCommands.as(); - for(JsonVariant command : arr) { - dispatchCommand(command.as()); - } - } -} - -void dispatchJsonl(Stream & stream) -{ - DynamicJsonDocument jsonl(3 * 128u); - uint8_t savedPage = haspGetPage(); - - Log.notice(F("DISPATCH: jsonl")); - - while(deserializeJson(jsonl, stream) == DeserializationError::Ok) { - // serializeJson(jsonl, Serial); - // Serial.println(); - haspNewObject(jsonl.as(), savedPage); - } -} - -void dispatchJsonl(char * payload) -{ - CharStream stream(payload); - dispatchJsonl(stream); -} - -void dispatchIdle(const char * state) +// send idle state to the client +void dispatch_output_idle_state(const char * state) { #if !defined(HASP_USE_MQTT) && !defined(HASP_USE_TASMOTA_SLAVE) Log.notice(F("OUT: idle = %s"), state); #else + #if HASP_USE_MQTT > 0 mqtt_send_state(F("idle"), state); #endif + #if HASP_USE_TASMOTA_SLAVE > 0 slave_send_state(F("idle"), state); #endif + #endif } +// restart the device void dispatchReboot(bool saveConfig) { if(saveConfig) configWriteConfig(); @@ -313,7 +411,7 @@ void dispatch_button(uint8_t id, const char * event) #if HASP_USE_MQTT > 0 mqtt_send_input(id, event); #endif -#if HASP_USE_TASMOTA_SLAVE>0 +#if HASP_USE_TASMOTA_SLAVE > 0 slave_send_input(id, event); #endif #endif @@ -327,6 +425,7 @@ void dispatchWebUpdate(const char * espOtaUrl) #endif } +// send return output back to the client void IRAM_ATTR dispatch_obj_attribute_str(uint8_t pageid, uint8_t btnid, const char * attribute, const char * data) { #if !defined(HASP_USE_MQTT) && !defined(HASP_USE_TASMOTA_SLAVE) @@ -341,6 +440,7 @@ void IRAM_ATTR dispatch_obj_attribute_str(uint8_t pageid, uint8_t btnid, const c #endif } +// Get or Set a part of the config.json file void dispatchConfig(const char * topic, const char * payload) { DynamicJsonDocument doc(128 * 2); @@ -426,7 +526,7 @@ void dispatchConfig(const char * topic, const char * payload) settings.remove(F("pass")); // hide password in output size_t size = serializeJson(doc, buffer, sizeof(buffer)); #if !defined(HASP_USE_MQTT) && !defined(HASP_USE_TASMOTA_SLAVE) - Log.notice(F("OUT: config %s = %s"),topic,buffer); + Log.notice(F("OUT: config %s = %s"), topic, buffer); #else #if HASP_USE_MQTT > 0 mqtt_send_state(F("config"), buffer); diff --git a/src/hasp_dispatch.h b/src/hasp_dispatch.h index fabb3d9d..e0b5cab2 100644 --- a/src/hasp_dispatch.h +++ b/src/hasp_dispatch.h @@ -3,26 +3,29 @@ #include "ArduinoJson.h" +#define LOG_CMND_CTR "CMND: " + void dispatchSetup(void); void dispatchLoop(void); -void dispatchAttribute(String strTopic, const char * strPayload); -void dispatchCommand(String cmnd); +// void dispatchCommand(const char * topic, const char * payload); // intenal void dispatchConfig(const char * topic, const char * payload); +void dispatchTopicPayload(const char * topic, const char * payload); +void dispatchTextLine(const char * cmnd); -void dispatchJson(char * strPayload); -void dispatchJsonl(char * strPayload); -void dispatchJsonl(Stream & stream); +// void dispatchParseJson(char * strPayload); +// void dispatchParseJsonl(char * strPayload); +void dispatchParseJsonl(Stream & stream); -void dispatchPage(String strPageid); -void dispatchClearPage(String strPageid); -void dispatchDim(String strDimLevel); -void dispatchBacklight(String strPayload); +void dispatchPage(const char * page); +void dispatchClearPage(const char * page); +void dispatchDim(const char * level); +void dispatchBacklight(const char * payload); void dispatchWebUpdate(const char * espOtaUrl); -void dispatchIdle(const char * state); +void dispatch_output_idle_state(const char * state); void dispatchReboot(bool saveConfig); -void dispatchStatusUpdate(void); +void dispatch_output_statusupdate(void); void dispatch_button(uint8_t id, const char * event); diff --git a/src/hasp_gui.cpp b/src/hasp_gui.cpp index 20193f62..b28f796f 100644 --- a/src/hasp_gui.cpp +++ b/src/hasp_gui.cpp @@ -90,19 +90,19 @@ static bool guiCheckSleep() uint32_t idle = lv_disp_get_inactive_time(NULL); if(idle >= (guiSleepTime1 + guiSleepTime2) * 1000U) { if(guiSleeping != 2) { - dispatchIdle(("LONG")); // Literal string + dispatch_output_idle_state(("LONG")); // Literal string guiSleeping = 2; } return true; } else if(idle >= guiSleepTime1 * 1000U) { if(guiSleeping != 1) { - dispatchIdle(("SHORT")); // Literal string + dispatch_output_idle_state(("SHORT")); // Literal string guiSleeping = 1; } return true; } if(guiSleeping != 0) { - dispatchIdle(("OFF")); // Literal string + dispatch_output_idle_state(("OFF")); // Literal string guiSleeping = 0; } return false; diff --git a/src/hasp_http.cpp b/src/hasp_http.cpp index 42cb0616..504d541d 100644 --- a/src/hasp_http.cpp +++ b/src/hasp_http.cpp @@ -1071,7 +1071,7 @@ void webHandleGuiConfig() } webSendFooter(); - if(webServer.hasArg(F("action"))) dispatchCommand(webServer.arg(F("action"))); + if(webServer.hasArg(F("action"))) dispatchTextLine(webServer.arg(F("action")).c_str()); } //////////////////////////////////////////////////////////////////////////////////////////////////// @@ -1471,7 +1471,7 @@ void httpHandleResetConfig() #if HASP_USE_SPIFFS > 0 bool formatted = SPIFFS.format(); if(formatted) { - httpMessage += F("Resetting all saved settings and restarting device into WiFi AP mode"); + httpMessage += F("Resetting all saved settings and restarting device"); } else { httpMessage += F("Failed to format the internal flash partition"); resetConfirmed = false; diff --git a/src/hasp_mqtt.cpp b/src/hasp_mqtt.cpp index 690b867c..8c8cdaa9 100644 --- a/src/hasp_mqtt.cpp +++ b/src/hasp_mqtt.cpp @@ -239,7 +239,10 @@ void mqtt_send_statusupdate() // Receive incoming messages static void mqtt_message_cb(char * topic_p, byte * payload, unsigned int length) { // Handle incoming commands from MQTT - if(length >= MQTT_MAX_PACKET_SIZE) return; + if(length >= MQTT_MAX_PACKET_SIZE) { + Log.error(F("MQTT RCV: Payload too long (%d bytes)"), length); + return; + } payload[length] = '\0'; // String strTopic((char *)0); @@ -271,36 +274,6 @@ static void mqtt_message_cb(char * topic_p, byte * payload, unsigned int length) Log.error(F("MQTT: Message received with invalid topic")); return; } - // Log.trace(F("MQTT IN: short topic: %s"), topic); - - if(!strcmp_P(topic, PSTR("command"))) { - dispatchCommand((char *)payload); - return; - } - - if(topic == strstr_P(topic, PSTR("command/"))) { // startsWith command/ - topic += 8u; - // Log.trace(F("MQTT IN: command subtopic: %s"), topic); - - if(!strcmp_P(topic, PSTR("json"))) { // '[...]/device/command/json' -m '["dim=5", "page 1"]' = - // nextionSendCmd("dim=50"), nextionSendCmd("page 1") - dispatchJson((char *)payload); // Send to nextionParseJson() - } else if(!strcmp_P(topic, PSTR("jsonl"))) { - dispatchJsonl((char *)payload); - } else if(length == 0) { - dispatchCommand(topic); - } else { // '[...]/device/command/p[1].b[4].txt' -m '"Lights On"' == - // nextionSetAttr("p[1].b[4].txt", "\"Lights On\"") - dispatchAttribute(topic, (char *)payload); - } - return; - } - - if(topic == strstr_P(topic, PSTR("config/"))) { // startsWith command/ - topic += 7u; - dispatchConfig(topic, (char *)payload); - return; - } // catch a dangling LWT from a previous connection if it appears if(!strcmp_P(topic, PSTR("status")) && !strcasecmp_P((char *)payload, PSTR("OFF"))) { @@ -308,7 +281,9 @@ static void mqtt_message_cb(char * topic_p, byte * payload, unsigned int length) snprintf_P(topicBuffer, sizeof(topicBuffer), PSTR("%sstatus"), mqttNodeTopic); mqttClient.publish(topicBuffer, "ON", true); Log.notice(F("MQTT: binary_sensor state: [status] : ON")); - return; + // return; + } else { + dispatchTopicPayload(topic, (char *)payload); } /* @@ -458,7 +433,9 @@ void mqttReconnect() mqttReconnectCount = 0; haspReconnect(); - dispatchPage(String(haspGetPage())); + char page[4] = "999"; + itoa(haspGetPage(), page, DEC); + dispatchPage(page); mqtt_send_statusupdate(); } diff --git a/src/hasp_slave.cpp b/src/hasp_slave.cpp index 7ae71a3c..c358cd50 100644 --- a/src/hasp_slave.cpp +++ b/src/hasp_slave.cpp @@ -98,7 +98,7 @@ void TASMO_DATA_RECEIVE(char *data) Log.verbose(F("TAS: dataType [%s]"), dataType); if (!strcmp(dataType, "p[")){ // - dispatchCommand(data); + dispatchTextLine(data); } else if (!strcmp(dataType, "[\"")) { dispatchJson(data); } else { @@ -123,7 +123,7 @@ void TASMO_DATA_RECEIVE(char *data) } else if (!strcmp(slvCmd, "clearpage")) { dispatchClearPage(slvVal); } else { - dispatchCommand(data); + dispatchTextLine(data); } } } diff --git a/src/hasp_telnet.cpp b/src/hasp_telnet.cpp index 8c109e2b..c05c3192 100644 --- a/src/hasp_telnet.cpp +++ b/src/hasp_telnet.cpp @@ -149,7 +149,7 @@ static void telnetProcessLine() if(strcasecmp_P(telnetInputBuffer, PSTR("exit")) == 0) { telnetClientDisconnect(); } else { - dispatchCommand(telnetInputBuffer); + dispatchTextLine(telnetInputBuffer); } } } diff --git a/user_setups/esp32/d1-mini-esp32_ili9341.ini b/user_setups/esp32/d1-mini-esp32_ili9341.ini index 7d8758cf..4a8856e9 100644 --- a/user_setups/esp32/d1-mini-esp32_ili9341.ini +++ b/user_setups/esp32/d1-mini-esp32_ili9341.ini @@ -8,6 +8,7 @@ [env:d1mini32-lolintft24] platform = espressif32@^2.0.0 board = wemos_d1_mini32 +monitor_filters = esp32_exception_decoder monitor_port = COM6 ; To change the port, use platform_override.ini upload_port = COM6 ; To change the port, use platform_override.ini ;upload_protocol = espota ; You can switch to ArduinoOTA after flashing over serial once