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* 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 diff --git a/include/hasp_conf.h b/include/hasp_conf.h index bcdad641..650b80eb 100644 --- a/include/hasp_conf.h +++ b/include/hasp_conf.h @@ -1,6 +1,10 @@ #ifndef HASP_CONF_H #define HASP_CONF_H +#define HASP_VERSION_MAJOR 0 +#define HASP_VERSION_MINOR 2 +#define HASP_VERSION_REVISION 1108 + #define HASP_USE_APP 1 /* Network Services */ @@ -31,7 +35,7 @@ #endif #ifndef HASP_USE_SYSLOG -#define HASP_USE_SYSLOG 0 +#define HASP_USE_SYSLOG 1 #endif #ifndef HASP_USE_TELNET @@ -107,6 +111,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 +140,7 @@ #endif #include "hasp_ethernet.h" #endif +#endif #if HASP_USE_MQTT > 0 #include "hasp_mqtt.h" @@ -144,6 +164,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 #endif #if HASP_USE_TASMOTA_SLAVE > 0 diff --git a/include/lv_conf.h b/include/lv_conf.h index e19d6a29..9cba6751 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/lib/lv_lib_zifont/lv_zifont.cpp b/lib/lv_lib_zifont/lv_zifont.cpp index 42303778..087b2198 100644 --- a/lib/lv_lib_zifont/lv_zifont.cpp +++ b/lib/lv_lib_zifont/lv_zifont.cpp @@ -79,8 +79,8 @@ 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; } @@ -117,7 +117,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; @@ -156,8 +156,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(); @@ -407,8 +407,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(); @@ -439,7 +441,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 3953e929..994c62bf 160000 --- a/lib/lvgl +++ b/lib/lvgl @@ -1 +1 @@ -Subproject commit 3953e9293adb8462265074d9769ef11fe218e29f +Subproject commit 994c62bf9a35d5e8e39ecfa496edc43c7e1ecbe9 diff --git a/platformio.ini b/platformio.ini index 6972e23f..1d2b0ca7 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 @@ -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 @@ -68,9 +68,6 @@ build_flags = -Og ; Code Debug Optimization ;-w ; Suppress warnings -D CORE_DEBUG_LEVEL=1 ; Errors - -D HASP_VERSION_MAJOR=0 - -D HASP_VERSION_MINOR=1 - -D HASP_VERSION_REVISION=2 -D LV_CONF_INCLUDE_SIMPLE -D LV_LVGL_H_INCLUDE_SIMPLE ; for lv_drivers -D SPIFFS_TEMPORAL_FD_CACHE ; speedup opening recent files @@ -156,36 +153,12 @@ 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 = esp32_partition_app1280k_spiffs1472k.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) - -lib_ignore = - GxTFT - XPT2046_Touchscreen - ;*************************************************** ; Lolin D32 Pro with Lolin TFT 2.4" ;*************************************************** ; !! 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 @@ -209,10 +182,10 @@ lib_ignore = ; 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 = 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 @@ -237,25 +210,25 @@ lib_ignore = ;*************************************************** ; 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/src/hasp.cpp b/src/hasp.cpp index b48cc804..fd052bbd 100644 --- a/src/hasp.cpp +++ b/src/hasp.cpp @@ -21,6 +21,7 @@ #include "hasp_attribute.h" #include "hasp.h" +#include "lv_theme_hasp.h" #include "EEPROM.h" @@ -55,7 +56,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) @@ -69,12 +70,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]; -#else -lv_font_t * haspFonts[8]; -#endif -uint8_t current_page = 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 @@ -85,6 +83,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 @@ -123,7 +134,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) { @@ -239,26 +251,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); @@ -344,6 +343,19 @@ void haspProgressMsg(const __FlashStringHelper * msg) haspProgressMsg(String(msg).c_str()); } +/*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 */ @@ -351,12 +363,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; @@ -383,21 +389,23 @@ 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 ********** */ - /* ********** Font Initializations ********** */ - defaultFont = LV_FONT_DEFAULT; // Use default font #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); + 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 { - defaultFont = haspFonts[0]; + // defaultFont = haspFonts[0]; } #endif #endif + /* ********** Font Initializations ********** */ /* ********** Theme Initializations ********** */ @@ -405,8 +413,8 @@ void haspSetup() switch(haspThemeId) { #if(LV_USE_THEME_EMPTY == 1) case 0: - th = lv_theme_empty_init(LV_COLOR_PURPLE, LV_COLOR_BLACK, LV_THEME_DEFAULT_FLAGS, defaultFont, defaultFont, - defaultFont, defaultFont); + th = lv_theme_empty_init(LV_COLOR_PURPLE, LV_COLOR_BLACK, LV_THEME_DEFAULT_FLAGS, haspFonts[0], haspFonts[1], + haspFonts[2], haspFonts[3]); break; #endif @@ -424,15 +432,21 @@ void haspSetup() #if(LV_USE_THEME_MONO == 1) case 3: - th = lv_theme_mono_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, 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_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, 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, haspFonts[0], + haspFonts[1], haspFonts[2], haspFonts[3]); break; #endif @@ -450,15 +464,15 @@ void haspSetup() #if LV_USE_THEME_TEMPLATE == 1 case 7: - 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, haspFonts[0], haspFonts[1], + haspFonts[2], haspFonts[3]); 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, defaultFont, - defaultFont, defaultFont, defaultFont); + 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 @@ -471,8 +485,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, haspFonts[0], + haspFonts[1], haspFonts[2], haspFonts[3]); Log.error(F("HASP: Unknown theme selected")); } @@ -484,20 +498,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 @@ -711,10 +724,10 @@ String haspGetVersion() void haspClearPage(uint16_t pageid) { lv_obj_t * page = get_page_obj(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 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]); @@ -787,7 +800,6 @@ void haspNewObject(const JsonObject & config, uint8_t & saved_page_id) } } - /* Input cache and validation */ uint8_t objid = config[F("objid")].as(); uint8_t id = config[F("id")].as(); @@ -802,9 +814,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; } @@ -931,8 +941,7 @@ void haspNewObject(const JsonObject & config, uint8_t & saved_page_id) break; } case LV_HASP_ROLLER: { - obj = lv_roller_create(parent_obj, NULL); - bool infinite = config[F("infinite")].as(); + 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); @@ -1004,7 +1013,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.h b/src/hasp.h index c1ade3f8..1b1f7d3a 100644 --- a/src/hasp.h +++ b/src/hasp.h @@ -106,6 +106,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 4a110d65..da68cedf 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,49 @@ static lv_color_t haspPayloadToColor(const char * payload) return LV_COLOR_BLACK; } +static lv_font_t * haspPayloadToFont(const char * 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; + +#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 +232,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 +388,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 +415,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"), payload); + } + } /* 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) { @@ -552,8 +603,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: @@ -562,16 +613,34 @@ 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)) { 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) { @@ -579,23 +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)); @@ -616,32 +696,53 @@ 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_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 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)); } } -// 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(); @@ -662,11 +763,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); @@ -714,12 +835,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)) { @@ -789,11 +910,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 +940,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_" @@ -842,6 +968,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: @@ -869,6 +997,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 2d6763eb..0d55b55c 100644 --- a/src/hasp_attribute.h +++ b/src/hasp_attribute.h @@ -29,8 +29,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; \ - temp = lv_obj_get_style_##func_name(obj, part); \ + 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); \ } \ } @@ -46,7 +46,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) @@ -55,31 +65,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) @@ -90,19 +97,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) @@ -123,92 +127,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 @@ -220,7 +248,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 diff --git a/src/hasp_debug.cpp b/src/hasp_debug.cpp index 38033453..739005ac 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 "" @@ -71,7 +73,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 +99,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" @@ -279,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: @@ -381,23 +387,23 @@ 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) { 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; } } @@ -442,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 94e5ae53..6a474ca7 100644 --- a/src/hasp_dispatch.cpp +++ b/src/hasp_dispatch.cpp @@ -8,27 +8,15 @@ #include "hasp_debug.h" #include "hasp_gpio.h" #include "hasp_gui.h" +#include "hasp_oobe.h" #include "hasp_hal.h" #include "hasp.h" #include "hasp_conf.h" -inline void dispatchPrintln(String header, String & data) +inline bool isON(const char * payload) { - Log.notice(F("%s: %s"), header.c_str(), data.c_str()); -} - -bool isON(const char * payload) -{ - return strcmp_P(payload, PSTR("ON")) == 0; -} - -String getOnOff(bool state) -{ - String result((char *)0); - result.reserve(128); - result = state ? F("ON") : F("OFF"); - return result; + return strcasecmp_P(payload, PSTR("ON")) == 0; } void dispatchSetup() @@ -37,14 +25,31 @@ void dispatchSetup() void dispatchLoop() {} -void dispatchStatusUpdate() +// Send status update message to the client +void dispatch_output_statusupdate() { #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; @@ -62,16 +67,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,201 +148,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("clearconfig")) { - configClear(); + } else if(!strcmp_P(topic, PSTR("setupap"))) { + oobeFakeSetup(); - } else if(strTopic == F("setupap")) { - // haspDisplayAP(String(F("HASP-ABC123")).c_str(), String(F("haspadmin")).c_str()); + } else if(strlen(topic) == 7 && topic == strstr_P(topic, PSTR("output"))) { + dispatchGpioOutput(topic, payload); - } else if(strTopic.length() == 7 && strTopic.startsWith(F("output"))) { - dispatchOutput(strTopic, payload); - } -} + } else if(strcasecmp_P(topic, PSTR("calibrate")) == 0) { + guiCalibrate(); -void dispatchPage(String strPageid) -{ - dispatchPrintln(F("PAGE"), strPageid); + } 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()); + mqtt_send_state(F("light"), guiGetBacklight() ? PSTR("ON") : PSTR("OFF")); #endif + #if HASP_USE_TASMOTA_SLAVE > 0 - slave_send_state(F("light"), strPayload.c_str()); + 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(); @@ -394,6 +491,20 @@ void dispatch_send_group_event(uint8_t groupid, uint8_t eventid, bool update_has if(update_hasp) hasp_set_group_objects(groupid, eventid, NULL); } +void IRAM_ATTR dispatch_send_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) + Log.notice(F("OUT: json = {\"p[%u].b[%u].%s\":\"%s\"}"), pageid, btnid, attribute, data); +#else +#if HASP_USE_MQTT > 0 + mqtt_send_obj_attribute_str(pageid, btnid, attribute, data); +#endif +#if HASP_USE_TASMOTA_SLAVE > 0 + slave_send_obj_attribute_str(pageid, btnid, attribute, data); +#endif +#endif +} + void dispatch_send_object_event(uint8_t pageid, uint8_t objid, uint8_t eventid) { if(objid < 100) { @@ -414,7 +525,8 @@ void dispatchWebUpdate(const char * espOtaUrl) #endif } -void IRAM_ATTR dispatch_send_obj_attribute_str(uint8_t pageid, uint8_t btnid, const char * attribute, const char * data) +// 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) Log.notice(F("OUT: json = {\"p[%u].b[%u].%s\":\"%s\"}"), pageid, btnid, attribute, data); @@ -428,6 +540,7 @@ void IRAM_ATTR dispatch_send_obj_attribute_str(uint8_t pageid, uint8_t btnid, co #endif } +// Get or Set a part of the config.json file void dispatchConfig(const char * topic, const char * payload) { DynamicJsonDocument doc(128 * 2); @@ -450,21 +563,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 @@ -472,14 +585,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 @@ -487,11 +600,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 @@ -499,7 +612,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_dispatch.h b/src/hasp_dispatch.h index 65abfeb3..e89e636f 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_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_gpio.cpp b/src/hasp_gpio.cpp index b59152bd..f46176e3 100644 --- a/src/hasp_gpio.cpp +++ b/src/hasp_gpio.cpp @@ -15,7 +15,13 @@ uint8_t gpioUsedInputCount = 0; using namespace ace_button; static AceButton * button[HASP_NUM_INPUTS]; -hasp_gpio_config_t gpioConfig[HASP_NUM_GPIO_CONFIG]; + + +// An array of button pins, led pins, and the led states. Cannot be const +// because ledState is mutable. +hasp_gpio_config_t gpioConfig[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 { @@ -176,19 +182,13 @@ void gpioSetup() // return; #if defined(ARDUINO_ARCH_ESP8266) - gpioConfig[0] = {D2, 7, HASP_GPIO_BUTTON, INPUT_PULLUP}; - gpioConfig[1] = {D1, 7, HASP_GPIO_LED, OUTPUT}; - -// gpioAddButton(D2, INPUT_PULLUP, HIGH, 1); -// pinMode(D1, OUTPUT); + gpioAddButton(D2, INPUT_PULLUP, HIGH, 1); + pinMode(D1, OUTPUT); #endif #if defined(ARDUINO_ARCH_ESP32) - gpioConfig[0] = {D2, 0, HASP_GPIO_SWITCH, INPUT}; - gpioConfig[1] = {D1, 1, HASP_GPIO_RELAY, OUTPUT}; - -// gpioAddButton(D2, INPUT, HIGH, 1); -// pinMode(D1, OUTPUT); + // gpioAddButton( D2, INPUT, HIGH, 1); + // pinMode(D1, OUTPUT); #endif /* diff --git a/src/hasp_gui.cpp b/src/hasp_gui.cpp index b854e42f..337d5357 100644 --- a/src/hasp_gui.cpp +++ b/src/hasp_gui.cpp @@ -85,19 +85,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; @@ -513,9 +513,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 */ diff --git a/src/hasp_hal.cpp b/src/hasp_hal.cpp index 686ef308..3fca8895 100644 --- a/src/hasp_hal.cpp +++ b/src/hasp_hal.cpp @@ -127,6 +127,10 @@ String halGetChipModel() String model((char *)0); model.reserve(128); +#if defined(STM32F4xx) + model = F("STM32"); +#endif + #if defined(STM32F4xx) model = F("STM32F4xx"); @@ -149,7 +153,7 @@ String halGetChipModel() break; #endif default: - model = F("Unknown ESP"); + model = F("Unknown ESP32"); } model += F(" rev"); model += chip_info.revision; diff --git a/src/hasp_http.cpp b/src/hasp_http.cpp index a4d4f050..d7681374 100644 --- a/src/hasp_http.cpp +++ b/src/hasp_http.cpp @@ -382,10 +382,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); @@ -1094,7 +1098,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()); } //////////////////////////////////////////////////////////////////////////////////////////////////// @@ -1390,6 +1394,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("

"); @@ -1459,10 +1465,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); @@ -1636,7 +1643,7 @@ void httpHandleResetConfig() if(resetConfirmed) { // User has confirmed, so reset everything bool formatted = configClear(); 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; @@ -1684,7 +1691,11 @@ void webStart() #endif #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_mqtt.cpp b/src/hasp_mqtt.cpp index 5844c796..a03526d8 100644 --- a/src/hasp_mqtt.cpp +++ b/src/hasp_mqtt.cpp @@ -251,9 +251,12 @@ 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; // Check if payload fits the buffer - payload[length] = '\0'; // There's room in the buffer +{ // Handle incoming commands from MQTT + 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); // strTopic.reserve(MQTT_MAX_PACKET_SIZE); @@ -284,44 +287,16 @@ 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")) && !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); Log.notice(F("MQTT: binary_sensor state: [status] : ON")); - return; + // return; + } else { + dispatchTopicPayload(topic, (char *)payload); } /* @@ -471,7 +446,9 @@ void mqttReconnect() mqttReconnectCount = 0; haspReconnect(); - dispatchPage(String(haspGetPage())); + char page[4] = "999"; + itoa(haspGetPage(), page, DEC); + dispatchPage(page); mqtt_send_statusupdate(); } @@ -492,9 +469,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_oobe.cpp b/src/hasp_oobe.cpp index e63d27fe..479a7e9c 100644 --- a/src/hasp_oobe.cpp +++ b/src/hasp_oobe.cpp @@ -14,6 +14,10 @@ #include "hasp_config.h" #include "hasp_dispatch.h" +static bool oobeAutoCalibrate = true; + +#if HASP_USE_WIFI > 0 + #if HASP_USE_QRCODE > 0 #include "lv_qrcode.h" #endif @@ -21,18 +25,13 @@ 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]); + lv_obj_invalidate(lv_disp_get_layer_sys(NULL)); } void gotoPage1_cb(lv_obj_t * event_kb, lv_event_t event) @@ -292,28 +291,64 @@ static void oobe_calibrate_cb(lv_obj_t * ta, lv_event_t event) } } } +#endif // HASP_USE_WIFI -void oobeSetup() +void oobeSetAutoCalibrate(bool cal) { + oobeAutoCalibrate = cal; +} + +bool oobeSetup() +{ +#if HASP_USE_ETHERNET > 0 + if(eth_connected) return false; +#endif +#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 + 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_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/hasp_ota.cpp b/src/hasp_ota.cpp index 1bede7cf..1389ebcf 100644 --- a/src/hasp_ota.cpp +++ b/src/hasp_ota.cpp @@ -35,7 +35,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() { diff --git a/src/hasp_slave.cpp b/src/hasp_slave.cpp index 4148e1ca..e2f8b335 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_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/hasp_telnet.cpp b/src/hasp_telnet.cpp index e6595dba..c05c3192 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")); @@ -146,10 +146,10 @@ 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); + dispatchTextLine(telnetInputBuffer); } } } @@ -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); diff --git a/src/hasp_tft.cpp b/src/hasp_tft.cpp index 20b61278..d176b834 100644 --- a/src/hasp_tft.cpp +++ b/src/hasp_tft.cpp @@ -51,12 +51,11 @@ 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_ESP32) - // Log.verbose(F("TFT: Processor : ESP%x"), tftSetup.esp); - // #else - // Log.verbose(F("TFT: Processor : STM%x"), tftSetup.esp); - // #endif - Log.verbose(F("TFT: Processor : %s"), halGetChipModel().c_str()); +#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); +#endif Log.verbose(F("TFT: CPU freq. : %i MHz"), halGetCpuFreqMHz()); #if defined(ARDUINO_ARCH_ESP8266) diff --git a/src/hasp_wifi.cpp b/src/hasp_wifi.cpp index b173f8ba..56aae575 100644 --- a/src/hasp_wifi.cpp +++ b/src/hasp_wifi.cpp @@ -153,6 +153,18 @@ bool wifiShowAP(char * ssid, char * pass) return true; } +void wifiReconnect() +{ + WiFi.disconnect(true); +#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); +} + void wifiSetup() { #if defined(STM32F4xx) @@ -202,12 +214,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.begin(wifiSsid, wifiPassword); + + wifiReconnect(); Log.notice(F("WIFI: Connecting to : %s"), wifiSsid); } #endif @@ -232,7 +244,9 @@ 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) { + wifiReconnect(); + } return false; } } diff --git a/src/lv_theme_hasp.c b/src/lv_theme_hasp.c deleted file mode 100644 index 5fa2b79b..00000000 --- a/src/lv_theme_hasp.c +++ /dev/null @@ -1,519 +0,0 @@ -/** - * @file lv_theme_hasp.c - * - */ - -/********************* - * INCLUDES - *********************/ -#include "lv_themes/lv_theme.h" - -#if LV_USE_THEME_HASP - -/********************* - * DEFINES - *********************/ - -/********************** - * TYPEDEFS - **********************/ - -/********************** - * STATIC PROTOTYPES - **********************/ - -/********************** - * STATIC VARIABLES - **********************/ -static lv_theme_t theme; -static lv_style_t def; -static lv_style_t scr; - -/*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; - -/********************** - * MACROS - **********************/ - -/********************** - * STATIC FUNCTIONS - **********************/ - -static void basic_init(void) -{ - lv_style_plain.text.font = _font; - lv_style_pretty.text.font = _font; - lv_style_pretty_color.text.font = _font; - - 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; - - 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); - - 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; - - 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); - - 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); - - 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; -} - -static void btn_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 -} - -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 -} - -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) -{ -#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; - - 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) -{ -#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; - - 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) -{ -#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); - - 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 -} - -static void chart_init(void) -{ -#if LV_USE_CHART - - theme.style.chart = &lv_style_pretty; -#endif -} - -static void cb_init(void) -{ -#if LV_USE_CB != 0 - - 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) -{ -#if LV_USE_BTNM - - 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) -{ -#if LV_USE_KB - - 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) -{ -#if LV_USE_MBOX - - 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 -} - -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) -{ -#if LV_USE_TA - - 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 -} - -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 - - theme.style.ddlist.bg = &lv_style_pretty; - theme.style.ddlist.sel = &lv_style_plain_color; - theme.style.ddlist.sb = &sb; -#endif -} - -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 -} - -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 table_init(void) -{ -#if LV_USE_TABLE != 0 - theme.style.table.bg = &lv_style_transp_tight; - theme.style.table.cell = &lv_style_plain; -#endif -} - -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 - */ -lv_theme_t * lv_theme_hasp_init(uint16_t hue, lv_font_t * font) -{ - 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++; - } - - basic_init(); - btn_init(); - label_init(); - img_init(); - line_init(); - led_init(); - bar_init(); - slider_init(); - sw_init(); - lmeter_init(); - gauge_init(); - chart_init(); - cb_init(); - btnm_init(); - kb_init(); - mbox_init(); - page_init(); - ta_init(); - list_init(); - ddlist_init(); - roller_init(); - tabview_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 - - return &theme; -} - -/** - * Get a pointer to the theme - * @return pointer to the theme - */ -lv_theme_t * lv_theme_get_hasp(void) -{ - return &theme; -} - -/********************** - * STATIC FUNCTIONS - **********************/ - -#endif diff --git a/src/lv_theme_hasp.cpp b/src/lv_theme_hasp.cpp new file mode 100644 index 00000000..558c7db3 --- /dev/null +++ b/src/lv_theme_hasp.cpp @@ -0,0 +1,860 @@ +/** + * @file lv_theme_hasp.cpp + * + */ + +/********************* + * INCLUDES + *********************/ +#include "lvgl.h" /*To see all the widgets*/ + +#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 +#endif /* LV_ENABLE_GC */ + +/********************* + * DEFINES + *********************/ + +/********************** + * 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 theme_styles_t * styles; + +static bool inited; + +/********************** + * MACROS + **********************/ + +/********************** + * STATIC FUNCTIONS + **********************/ +static void style_init_reset(lv_style_t * style); + +static void basic_init(void) +{ + 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); + + 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); + + style_init_reset(&styles->round); + lv_style_set_radius(&styles->round, LV_STATE_DEFAULT, LV_RADIUS_CIRCLE); + + 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); + + 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); + + 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); + + 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 arc_init(void) +{ +#if LV_USE_ARC != 0 + +#endif +} + +static void bar_init(void) +{ +#if LV_USE_BAR + +#endif +} + +static void btn_init(void) +{ +#if LV_USE_BTN != 0 + +#endif +} + +static void btnmatrix_init(void) +{ +#if LV_USE_BTNMATRIX + +#endif +} + +static void calendar_init(void) +{ +#if LV_USE_CALENDAR + +#endif +} + +static void chart_init(void) +{ +#if LV_USE_CHART + +#endif +} + +static void cpicker_init(void) +{ +#if LV_USE_CPICKER + +#endif +} + +static void checkbox_init(void) +{ +#if LV_USE_CHECKBOX != 0 + +#endif +} + +static void cont_init(void) +{ +#if LV_USE_CONT != 0 + +#endif +} + +static void gauge_init(void) +{ +#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 + +#endif +} + +static void page_init(void) +{ +#if LV_USE_PAGE + +#endif +} + +static void slider_init(void) +{ +#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 + +#endif +} + +static void list_init(void) +{ +#if LV_USE_LIST != 0 + +#endif +} + +static void ddlist_init(void) +{ +#if LV_USE_DROPDOWN != 0 + +#endif +} + +static void roller_init(void) +{ +#if LV_USE_ROLLER != 0 + +#endif +} + +static void tabview_init(void) +{ +#if LV_USE_TABVIEW != 0 + +#endif +} + +static void tileview_init(void) +{ +#if LV_USE_TILEVIEW != 0 +#endif +} + +static void table_init(void) +{ +#if LV_USE_TABLE != 0 + +#endif +} + +static void win_init(void) +{ +#if LV_USE_WIN != 0 + +#endif +} + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +/** + * 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(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) +{ + + /* 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 = (theme_styles_t*)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(); + slider_init(); + switch_init(); + linemeter_init(); + gauge_init(); + arc_init(); + spinner_init(); + chart_init(); + calendar_init(); + cpicker_init(); + checkbox_init(); + btnmatrix_init(); + keyboard_init(); + msgbox_init(); + page_init(); + textarea_init(); + spinbox_init(); + list_init(); + ddlist_init(); + roller_init(); + tabview_init(); + tileview_init(); + table_init(); + win_init(); + + theme.apply_xcb = NULL; + theme.apply_cb = theme_apply; + + return &theme; +} + +void theme_apply(lv_theme_t * th, lv_obj_t * obj, lv_theme_style_t name) +{ + 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*/ diff --git a/src/main.cpp b/src/main.cpp index ea3ab485..743ce3f1 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -42,33 +42,34 @@ void setup() * Apply User Configuration ***************************/ debugSetup(); - guiSetup(); #if HASP_USE_GPIO > 0 gpioSetup(); #endif -#if HASP_USE_WIFI > 0 - wifiSetup(); -#endif - - oobeSetup(); - haspSetup(); - -#if HASP_USE_MDNS > 0 - mdnsSetup(); -#endif - -#if HASP_USE_OTA > 0 - otaSetup(); -#endif - #if HASP_USE_ETHERNET > 0 ethernetSetup(); #endif #if HASP_USE_MQTT > 0 - mqttSetup(); + mqttSetup(); // Load Hostname before starting WiFi +#endif + +#if HASP_USE_WIFI > 0 + wifiSetup(); +#endif + + guiSetup(); + if(!oobeSetup()) { + haspSetup(); + } + +#if HASP_USE_MDNS > 0 + mdnsSetup(); +#endif + +#if HASP_USE_OTA > 0 + otaSetup(); #endif #if HASP_USE_HTTP > 0 @@ -108,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(); @@ -145,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 */ 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..086766b5 --- /dev/null +++ b/test/hasp-lvgl.robot @@ -0,0 +1,185 @@ +| *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/platetelemetry/command +| | ${restopic} | Set Variable | hasp/platetelemetry/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/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} +| | 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} + +| 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/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} +| | 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 +| | 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 +| | 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 +| | 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[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 +| | 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[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 +| | 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 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 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..0c896838 --- /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@^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 +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 diff --git a/user_setups/esp32/d1-mini-esp32_ili9341.ini b/user_setups/esp32/d1-mini-esp32_ili9341.ini index 593ad419..6d8bfb93 100644 --- a/user_setups/esp32/d1-mini-esp32_ili9341.ini +++ b/user_setups/esp32/d1-mini-esp32_ili9341.ini @@ -6,11 +6,12 @@ ;***************************************************; [env:d1mini32-lolintft24] -platform = espressif32@^1.12.0 +platform = espressif32@^2.0.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 = esp32_partition_app1280k_spiffs1472k.csv +monitor_filters = esp32_exception_decoder +board_build.partitions = esp32_partition_app1300k_spiffs1216k.csv build_flags = ${flags.esp32_flags} @@ -25,4 +26,5 @@ build_flags = lib_ignore = GxTFT - XPT2046_Touchscreen \ No newline at end of file + XPT2046_Touchscreen + ESP32 BLE Arduino \ No newline at end of file diff --git a/user_setups/esp32/d132-unoshield_ili9486_parallel.ini b/user_setups/esp32/d132-unoshield_ili9486_parallel.ini index 9c3ebcb6..434b5f51 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 9ee7109d..f93b3e8c 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 28a82799..aa36d10b 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 c7278273..0646901d 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 b3ab8793..633f749f 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 759717ea..1adc999a 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 28c8d593..5efe54fa 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