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 @@
[](https://github.com/fvanroie/hasp-lvgl/blob/master/LICENSE)
[](#Contributing)
[](http://github.com/fvanroie/hasp-lvgl/issues)
+[][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