diff --git a/include/bootscreen.h b/include/bootscreen.h new file mode 100644 index 00000000..16ce2cf0 --- /dev/null +++ b/include/bootscreen.h @@ -0,0 +1,45 @@ +// Images can be converted to XBM format by using the online converter here: +// https://www.online-utility.org/image/convert/to/XBM + +// The output must be pasted in a header file, renamed and adjusted to appear +// as as a const unsigned char array in PROGMEM (FLASH program memory). + +// The xbm format adds padding to pixel rows so they are a whole number of bytes +// In this example 50 pixel width means 56 bits = 7 bytes +// the 50 height then means array uses 50 x 7 = 350 bytes of FLASH +// The library ignores the padding bits when drawing the image on the display. + +// The NetWize logo uses the MaterialDesign icons font, released under the OFL license + +#include // PROGMEM support header + +#define logoWidth 148 +#define logoHeight 24 + +// Image is stored in this array +PROGMEM const unsigned char bootscreen[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0F, 0x0F, 0xC0, 0xFF, 0x03, 0xF8, 0x7F, 0x00, 0x0F, 0x00, 0x0F, 0x80, 0x7F, 0x00, 0xFE, 0x1F, 0x00, 0xFF, 0x0F, + 0x1F, 0x0F, 0xC0, 0xFF, 0x03, 0xF8, 0x7F, 0x00, 0x0F, 0x00, 0x0F, 0x80, 0x7F, 0x00, 0xFE, 0x1F, 0x00, 0xFF, 0x0F, + 0x1F, 0x0F, 0xC0, 0xFF, 0x03, 0xF8, 0x7F, 0x00, 0x0F, 0x0F, 0x0F, 0x80, 0x7F, 0x00, 0xFE, 0x1F, 0x00, 0xFF, 0x0F, + 0x1F, 0x0F, 0xC0, 0xFF, 0x03, 0xF8, 0x7F, 0x00, 0x0F, 0x0F, 0x0F, 0x80, 0x7F, 0x00, 0xFE, 0x1F, 0x00, 0xFF, 0x0F, + 0x3F, 0x0F, 0xC0, 0x03, 0x00, 0x80, 0x07, 0x00, 0x0F, 0x0F, 0x0F, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x0F, 0x00, + 0x3F, 0x0F, 0xC0, 0x03, 0x00, 0x80, 0x07, 0x00, 0x0F, 0x0F, 0x0F, 0x00, 0x1E, 0x00, 0x00, 0x0F, 0x00, 0x0F, 0x00, + 0x7F, 0x0F, 0xC0, 0x03, 0x00, 0x80, 0x07, 0x00, 0x0F, 0x0F, 0x0F, 0x00, 0x1E, 0x00, 0x80, 0x07, 0x00, 0x0F, 0x00, + 0x7F, 0x0F, 0xC0, 0x03, 0x00, 0x80, 0x07, 0x00, 0x0F, 0x0F, 0x0F, 0x00, 0x1E, 0x00, 0x80, 0x07, 0x00, 0x0F, 0x00, + 0xFF, 0x0F, 0xC0, 0xFF, 0x03, 0x80, 0x07, 0x00, 0x0F, 0x0F, 0x0F, 0x00, 0x1E, 0x00, 0xC0, 0x03, 0x00, 0xFF, 0x0F, + 0xFF, 0x0F, 0xC0, 0xFF, 0x03, 0x80, 0x07, 0x00, 0x0F, 0x0F, 0x0F, 0x00, 0x1E, 0x00, 0xE0, 0x01, 0x00, 0xFF, 0x0F, + 0xFF, 0x0F, 0xC0, 0xFF, 0x03, 0x80, 0x07, 0x00, 0x0F, 0x0F, 0x0F, 0x00, 0x1E, 0x00, 0xE0, 0x01, 0x00, 0xFF, 0x0F, + 0xFF, 0x0F, 0xC0, 0xFF, 0x03, 0x80, 0x07, 0x00, 0x0F, 0x0F, 0x0F, 0x00, 0x1E, 0x00, 0xF0, 0x00, 0x00, 0xFF, 0x0F, + 0xEF, 0x0F, 0xC0, 0x03, 0x00, 0x80, 0x07, 0x00, 0x0F, 0x0F, 0x0F, 0x00, 0x1E, 0x00, 0x78, 0x00, 0x00, 0x0F, 0x00, + 0xEF, 0x0F, 0xC0, 0x03, 0x00, 0x80, 0x07, 0x00, 0x0F, 0x0F, 0x0F, 0x00, 0x1E, 0x00, 0x78, 0x00, 0x00, 0x0F, 0x00, + 0xCF, 0x0F, 0xC0, 0x03, 0x00, 0x80, 0x07, 0x00, 0x0F, 0x0F, 0x0F, 0x00, 0x1E, 0x00, 0x3C, 0x00, 0x00, 0x0F, 0x00, + 0xCF, 0x0F, 0xC0, 0x03, 0x00, 0x80, 0x07, 0x00, 0x0F, 0x0F, 0x0F, 0x00, 0x1E, 0x00, 0x1E, 0x00, 0x00, 0x0F, 0x00, + 0x8F, 0x0F, 0xC0, 0xFF, 0x03, 0x80, 0x07, 0x00, 0xFF, 0xFF, 0x0F, 0x80, 0x7F, 0x00, 0xFE, 0x1F, 0x00, 0xFF, 0x0F, + 0x8F, 0x0F, 0xC0, 0xFF, 0x03, 0x80, 0x07, 0x00, 0xFF, 0xFF, 0x0F, 0x80, 0x7F, 0x00, 0xFE, 0x1F, 0x00, 0xFF, 0x0F, + 0x8F, 0x0F, 0xC0, 0xFF, 0x03, 0x80, 0x07, 0x00, 0xFE, 0xFF, 0x07, 0x80, 0x7F, 0x00, 0xFE, 0x1F, 0x00, 0xFF, 0x0F, + 0x0F, 0x0F, 0xC0, 0xFF, 0x03, 0x80, 0x07, 0x00, 0xFC, 0xFF, 0x03, 0x80, 0x7F, 0x00, 0xFE, 0x1F, 0x00, 0xFF, 0x0F, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; diff --git a/include/hasp_conf.h b/include/hasp_conf.h index c6446a23..afaf3102 100644 --- a/include/hasp_conf.h +++ b/include/hasp_conf.h @@ -69,6 +69,10 @@ #define HASP_USE_PNGDECODE 0 #endif +#ifndef HASP_NUM_GPIO_CONFIG +#define HASP_NUM_GPIO_CONFIG 5 +#endif + #ifndef HASP_NUM_INPUTS #define HASP_NUM_INPUTS 3 // Buttons #endif diff --git a/include/lv_conf.h b/include/lv_conf.h index 85829f49..e19d6a29 100644 --- a/include/lv_conf.h +++ b/include/lv_conf.h @@ -77,7 +77,7 @@ typedef int16_t lv_coord_t; #if LV_MEM_CUSTOM == 0 /* Size of the memory used by `lv_mem_alloc` in bytes (>= 2kB)*/ #ifdef ESP8266 -# define LV_MEM_SIZE (12 * 1024U) // 12KB +# define LV_MEM_SIZE (10 * 1024U) // 12KB #endif #ifndef LV_MEM_SIZE # define LV_MEM_SIZE (20 * 1024U) // 48KB diff --git a/lib/lv_drv_fsmc_ili9341/fsmc_ili9341.cpp b/lib/lv_drv_fsmc_ili9341/fsmc_ili9341.cpp index 9448fcbe..b18eca48 100644 --- a/lib/lv_drv_fsmc_ili9341/fsmc_ili9341.cpp +++ b/lib/lv_drv_fsmc_ili9341/fsmc_ili9341.cpp @@ -48,6 +48,8 @@ TFT_Class tft(io, controller, TFT_WIDTH, TFT_HEIGHT); #include // 240x320 #include "GxReadRegisters.h" +#include "bootscreen.h" // Sketch tab header for xbm images + /********************* * DEFINES *********************/ @@ -76,18 +78,35 @@ TFT_Class tft(io, controller, TFT_WIDTH, TFT_HEIGHT); **********************/ /** - * Initialize the R61581 display controller - * @return HW_RES_OK or any error from hw_res_t enum + * Initialize the ILI9341 display controller */ void fsmc_ili9341_init(uint8_t rotation) { tft.init(); tft.setRotation(rotation); - // tft.fillScreen(BLUE); + tft.setRotation(rotation); + tft.fillScreen(TFT_DARKCYAN); + int x = (tft.width() - logoWidth) / 2; + int y = (tft.height() - logoHeight) / 2; + // tft.drawBitmap(x, y, bootscreen, logoWidth, logoHeight, TFT_WHITE); + + io.startTransaction(); + int32_t i, j, byteWidth = (logoWidth + 7) / 8; + + for(j = 0; j < logoHeight; j++) { + for(i = 0; i < logoWidth; i++) { + if(pgm_read_byte(bootscreen + j * byteWidth + i / 8) & (1 << (i & 7))) { + tft.drawPixel(x + i, y + j, TFT_WHITE); + } + } + } + + io.endTransaction(); + delay(800); } /* GxTFT::pushColors only supports writing up to 255 at a time */ -/* This local function circumvents this artificial limit */ +/* This *local* function circumvents this artificial limititaion */ static inline void pushColors(uint16_t * data, uint32_t len) { io.startTransaction(); @@ -103,21 +122,9 @@ void fsmc_ili9341_flush(int32_t x1, int32_t y1, int32_t x2, int32_t y2, lv_color tft.setWindow(x1, y1, x2, y2); size_t len = (x2 - x1 + 1) * (y2 - y1 + 1); /* Number of pixels */ -#if 1 +#if 1 // use local version instead pushColors((uint16_t *)color_p, len); #else - // tft.init(); - // Serial.print("flush "); - // Serial.print(x1); - // Serial.print(" "); - // Serial.print(y1); - // Serial.print(" "); - // Serial.print(x2); - // Serial.print(" "); - // Serial.print(y2); - // Serial.print(" "); - // Serial.println(len); - /* Update TFT */ while(len > 255) { tft.pushColors((uint16_t *)color_p, 255); diff --git a/lib/lv_drv_tft_espi/tft_espi_drv.cpp b/lib/lv_drv_tft_espi/tft_espi_drv.cpp index e87aed5c..cb435cba 100644 --- a/lib/lv_drv_tft_espi/tft_espi_drv.cpp +++ b/lib/lv_drv_tft_espi/tft_espi_drv.cpp @@ -16,6 +16,7 @@ #include LV_DRV_DISP_INCLUDE #include LV_DRV_DELAY_INCLUDE #include "../../../src/hasp_tft.h" +#include "bootscreen.h" // Sketch tab header for xbm images /********************* * DEFINES @@ -53,6 +54,9 @@ void tft_espi_init(uint8_t rotation) tft.setSwapBytes(true); /* set endianess */ tft.setRotation(rotation); tft.fillScreen(TFT_DARKCYAN); + int x = (tft.width() - logoWidth) / 2; + int y = (tft.height() - logoHeight) / 2; + tft.drawXBitmap(x, y, bootscreen, logoWidth, logoHeight, TFT_WHITE); #ifdef USE_DMA_TO_TFT // DMA - should work with STM32F2xx/F4xx/F7xx processors diff --git a/platformio.ini b/platformio.ini index 3bfc497e..3451f5fa 100644 --- a/platformio.ini +++ b/platformio.ini @@ -20,7 +20,7 @@ extra_configs = platformio_override.ini ; -- Put active [env] files in this dir to be included in the build menu user_setups/active/*.ini - user_setups/*/*.ini + ; user_setups/*/*.ini default_envs = ; Uncomment the needed environments in platformio_override.ini @@ -115,6 +115,7 @@ esp32_flags= stm32_flags= ${env.build_flags} -D IRAM_ATTR= ; No IRAM_ATTR available on STM32 + -D ICACHE_RAM_ATTR= -D STM32 -D STREAMUTILS_USE_EEPROM_UPDATE=1 ; update cell only when changed -D MQTT_MAX_PACKET_SIZE=2048 ; longer PubSubClient messages diff --git a/src/hasp.cpp b/src/hasp.cpp index 718698d0..481e06af 100644 --- a/src/hasp.cpp +++ b/src/hasp.cpp @@ -173,7 +173,7 @@ void hasp_send_obj_attribute_str(lv_obj_t * obj, const char * attribute, const c uint8_t objid; if(FindIdFromObj(obj, &pageid, &objid)) { - dispatch_obj_attribute_str(pageid, objid, attribute, data); + dispatch_send_obj_attribute_str(pageid, objid, attribute, data); } } @@ -301,25 +301,47 @@ void haspReconnect() lv_obj_set_hidden(obj, true);*/ } -void haspProgress(uint8_t val, char * msg) +String progress_str((char *)0); + +void haspProgressVal(uint8_t val) { lv_obj_t * layer = lv_disp_get_layer_sys(NULL); lv_obj_t * bar = hasp_find_obj_from_id(255, 10); - - if(val == 255) { - lv_obj_set_style_local_bg_opa(layer, LV_OBJ_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_0); - if(bar) { - lv_obj_set_hidden(bar, true); - } - } else { - lv_obj_set_style_local_bg_opa(layer, LV_OBJ_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_100); - if(bar) { - lv_obj_set_hidden(bar, false); + if(layer && bar) { + if(val == 255) { + if(!lv_obj_get_hidden(bar)) { + lv_obj_set_hidden(bar, true); + lv_obj_set_style_local_bg_opa(layer, LV_OBJ_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_0); + lv_obj_set_style_local_value_str(bar, LV_OBJ_PART_MAIN, LV_STATE_DEFAULT, ""); +#if defined(ARCH_ARDUINO_ESP32) || defined(ARCH_ARDUINO_ESP8266) + progress_str.clear(); +#endif + } + } else { + if(lv_obj_get_hidden(bar)) { + lv_obj_set_hidden(bar, false); + lv_obj_set_style_local_bg_opa(layer, LV_OBJ_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_100); + } lv_bar_set_value(bar, val, LV_ANIM_OFF); - lv_obj_set_style_local_value_str(bar, LV_OBJ_PART_MAIN, LV_STATE_DEFAULT, msg); } + lv_task_handler(); /* let the GUI do its work */ } - lv_tick_inc(30); +} + +void haspProgressMsg(const char * msg) +{ + lv_obj_t * bar = hasp_find_obj_from_id(255, 10); + if(bar) { + progress_str.reserve(64); + progress_str = msg; + lv_obj_set_style_local_value_str(bar, LV_OBJ_PART_MAIN, LV_STATE_DEFAULT, progress_str.c_str()); + lv_task_handler(); /* let the GUI do its work */ + } +} + +void haspProgressMsg(const __FlashStringHelper * msg) +{ + haspProgressMsg(String(msg).c_str()); } /** @@ -546,27 +568,34 @@ void hasp_background(uint16_t pageid, uint16_t imageid) */ void IRAM_ATTR btn_event_handler(lv_obj_t * obj, lv_event_t event) { + uint8_t eventid; char buffer[64]; snprintf(buffer, sizeof(buffer), PSTR("HASP: ")); switch(event) { case LV_EVENT_PRESSED: + eventid = HASP_EVENT_DOWN; memcpy_P(buffer, PSTR("DOWN"), sizeof(buffer)); break; case LV_EVENT_CLICKED: // UP = the same object was release then was pressed and press was not lost! + eventid = HASP_EVENT_UP; memcpy_P(buffer, PSTR("UP"), sizeof(buffer)); break; case LV_EVENT_SHORT_CLICKED: + eventid = HASP_EVENT_SHORT; memcpy_P(buffer, PSTR("SHORT"), sizeof(buffer)); break; case LV_EVENT_LONG_PRESSED: + eventid = HASP_EVENT_LONG; memcpy_P(buffer, PSTR("LONG"), sizeof(buffer)); break; case LV_EVENT_LONG_PRESSED_REPEAT: + eventid = HASP_EVENT_HOLD; memcpy_P(buffer, PSTR("HOLD"), sizeof(buffer)); break; case LV_EVENT_PRESS_LOST: + eventid = HASP_EVENT_LOST; memcpy_P(buffer, PSTR("LOST"), sizeof(buffer)); break; case LV_EVENT_PRESSING: @@ -585,7 +614,7 @@ void IRAM_ATTR btn_event_handler(lv_obj_t * obj, lv_event_t event) Log.notice(buffer, event); return; default: - strcat_P(buffer, PSTR("HASP : Unknown Event % d occured")); + strcat_P(buffer, PSTR("HASP : Unknown Event occured")); Log.warning(buffer, event); return; } @@ -595,7 +624,8 @@ void IRAM_ATTR btn_event_handler(lv_obj_t * obj, lv_event_t event) mqtt_send_state(F("wakeuptouch"), buffer); #endif } else { - hasp_send_obj_attribute_event(obj, buffer); + // hasp_send_obj_attribute_event(obj, buffer); + dispatch_send_object_event(current_page, (uint8_t)obj->user_data, eventid); } } @@ -697,6 +727,20 @@ void haspSetPage(uint8_t pageid) } } +void hasp_set_group_objects(uint8_t groupid, uint8_t eventid, lv_obj_t * src_obj) +{ + bool state = dispatch_get_event_state(eventid); + for(uint8_t page = 0; page < HASP_NUM_PAGES; page++) { + uint8_t startid = 100 + groupid * 10; // groups start at id 100 + for(uint8_t objid = startid; objid < (startid + 10); objid++) { + lv_obj_t * obj = hasp_find_obj_from_id(page, objid); + if(obj && obj != src_obj) { // skip source object, if set + lv_obj_set_state(obj, state ? LV_STATE_PRESSED | LV_STATE_CHECKED : LV_STATE_DEFAULT); + } + } + } +} + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void haspNewObject(const JsonObject & config, uint8_t & saved_page_id) diff --git a/src/hasp.h b/src/hasp.h index 6d2eb8e8..c1ade3f8 100644 --- a/src/hasp.h +++ b/src/hasp.h @@ -19,7 +19,7 @@ extern "C" { * INCLUDES *********************/ -#if HASP_USE_APP>0 +#if HASP_USE_APP > 0 /********************* * DEFINES @@ -29,6 +29,19 @@ extern "C" { * TYPEDEFS **********************/ +enum hasp_event_t { // even = released, odd = pressed + HASP_EVENT_OFF = 0, + HASP_EVENT_ON = 1, + HASP_EVENT_UP = 2, + HASP_EVENT_DOWN = 3, + + HASP_EVENT_SHORT = 4, + HASP_EVENT_LONG = 5, + HASP_EVENT_LOST = 6, + HASP_EVENT_HOLD = 7, + HASP_EVENT_DOUBLE = 8 +}; + enum lv_hasp_obj_type_t { LV_HASP_BUTTON = 10, LV_HASP_CHECKBOX = 11, @@ -51,12 +64,12 @@ enum lv_hasp_obj_type_t { LV_HASP_IMAGE = 60, - LV_HASP_TABVIEW = 70, + LV_HASP_TABVIEW = 70, LV_HASP_TILEVIEW = 71, LV_HASP_CONTAINER = 90, - LV_HASP_OBJECT = 91, - LV_HASP_PAGE = 92, + LV_HASP_OBJECT = 91, + LV_HASP_PAGE = 92, }; /********************** @@ -80,13 +93,14 @@ void hasp_send_obj_attribute_str(lv_obj_t * obj, const char * attribute, const c void hasp_send_obj_attribute_int(lv_obj_t * obj, const char * attribute, int32_t val); void hasp_send_obj_attribute_color(lv_obj_t * obj, const char * attribute, lv_color_t color); void hasp_process_attribute(uint8_t pageid, uint8_t objid, const char * attr, const char * payload); +void hasp_set_group_objects(uint8_t groupid, uint8_t eventid, lv_obj_t * src_obj); void haspNewObject(const JsonObject & config, uint8_t & saved_page_id); void haspReconnect(void); void haspDisconnect(void); void haspWakeUp(void); -void haspProgress(uint8_t val, char * msg); +void haspProgressVal(uint8_t val); bool haspGetConfig(const JsonObject & settings); bool haspSetConfig(const JsonObject & settings); @@ -106,4 +120,7 @@ void IRAM_ATTR toggle_event_handler(lv_obj_t * obj, lv_event_t event); } /* extern "C" */ #endif +void haspProgressMsg(const char * msg); +void haspProgressMsg(const __FlashStringHelper * msg); + #endif /*HASP_H*/ diff --git a/src/hasp_config.cpp b/src/hasp_config.cpp index c2da806a..2def1d73 100644 --- a/src/hasp_config.cpp +++ b/src/hasp_config.cpp @@ -199,7 +199,7 @@ void configWriteConfig() bool writefile = false; bool changed = false; -#if HASP_USE_WIFI>0 +#if HASP_USE_WIFI > 0 if(settings[F("wifi")].as().isNull()) settings.createNestedObject(F("wifi")); changed = wifiGetConfig(settings[F("wifi")]); if(changed) { @@ -207,7 +207,7 @@ void configWriteConfig() writefile = true; } #endif -#if HASP_USE_MQTT>0 +#if HASP_USE_MQTT > 0 if(settings[F("mqtt")].as().isNull()) settings.createNestedObject(F("mqtt")); changed = mqttGetConfig(settings[F("mqtt")]); if(changed) { @@ -216,7 +216,7 @@ void configWriteConfig() writefile = true; } #endif -#if HASP_USE_TELNET>0 +#if HASP_USE_TELNET > 0 if(settings[F("telnet")].as().isNull()) settings.createNestedObject(F("telnet")); changed = telnetGetConfig(settings[F("telnet")]); if(changed) { @@ -225,7 +225,7 @@ void configWriteConfig() writefile = true; } #endif -#if HASP_USE_MDNS>0 +#if HASP_USE_MDNS > 0 if(settings[F("mdns")].as().isNull()) settings.createNestedObject(F("mdns")); changed = mdnsGetConfig(settings[F("mdns")]); if(changed) { @@ -233,7 +233,7 @@ void configWriteConfig() writefile = true; } #endif -#if HASP_USE_HTTP>0 +#if HASP_USE_HTTP > 0 if(settings[F("http")].as().isNull()) settings.createNestedObject(F("http")); changed = httpGetConfig(settings[F("http")]); if(changed) { @@ -325,7 +325,7 @@ void configSetup() if(i == 0) { #if HASP_USE_SPIFFS > 0 EepromStream eepromStream(0, 2048); - DeserializationError error = deserializeJson(settings, eepromStream); + DeserializationError err = deserializeJson(settings, eepromStream); #else continue; #endif @@ -348,23 +348,23 @@ void configSetup() haspSetConfig(settings[F("hasp")]); // otaGetConfig(settings[F("ota")]); -#if HASP_USE_WIFI>0 +#if HASP_USE_WIFI > 0 Log.verbose(F("Loading WiFi settings")); wifiSetConfig(settings[F("wifi")]); #endif -#if HASP_USE_MQTT>0 +#if HASP_USE_MQTT > 0 Log.verbose(F("Loading MQTT settings")); mqttSetConfig(settings[F("mqtt")]); #endif -#if HASP_USE_TELNET>0 +#if HASP_USE_TELNET > 0 Log.verbose(F("Loading Telnet settings")); telnetSetConfig(settings[F("telnet")]); #endif -#if HASP_USE_MDNS>0 +#if HASP_USE_MDNS > 0 Log.verbose(F("Loading MDNS settings")); mdnsSetConfig(settings[F("mdns")]); #endif -#if HASP_USE_HTTP>0 +#if HASP_USE_HTTP > 0 Log.verbose(F("Loading HTTP settings")); httpSetConfig(settings[F("http")]); #endif diff --git a/src/hasp_dispatch.cpp b/src/hasp_dispatch.cpp index ab227e64..cec24e28 100644 --- a/src/hasp_dispatch.cpp +++ b/src/hasp_dispatch.cpp @@ -6,6 +6,7 @@ #include "hasp_dispatch.h" #include "hasp_config.h" #include "hasp_debug.h" +#include "hasp_gpio.h" #include "hasp_gui.h" #include "hasp_hal.h" #include "hasp.h" @@ -38,7 +39,7 @@ void dispatchLoop() void dispatchStatusUpdate() { -#if HASP_USE_MQTT>0 +#if HASP_USE_MQTT > 0 mqtt_send_statusupdate(); #endif } @@ -48,7 +49,7 @@ void dispatchOutput(int output, bool state) int pin = 0; if(pin >= 0) { - Log.notice(F("PIN OUTPUT STATE %d"),state); + Log.notice(F("PIN OUTPUT STATE %d"), state); #if defined(ARDUINO_ARCH_ESP32) ledcWrite(99, state ? 1023 : 0); // ledChannel and value @@ -189,7 +190,6 @@ void dispatchBacklight(String strPayload) #if HASP_USE_TASMOTA_SLAVE > 0 slave_send_state(F("light"), strPayload.c_str()); #endif - } void dispatchCommand(String cmnd) @@ -312,12 +312,97 @@ void dispatch_button(uint8_t id, const char * event) #if HASP_USE_MQTT > 0 mqtt_send_input(id, event); #endif -#if HASP_USE_TASMOTA_SLAVE>0 +#if HASP_USE_TASMOTA_SLAVE > 0 slave_send_input(id, event); #endif #endif } +// Map events to either ON or OFF (UP or DOWN) +bool dispatch_get_event_state(uint8_t eventid) +{ + switch(eventid) { + case HASP_EVENT_ON: + case HASP_EVENT_DOWN: + case HASP_EVENT_LONG: + case HASP_EVENT_HOLD: + return true; + case HASP_EVENT_OFF: + case HASP_EVENT_UP: + case HASP_EVENT_SHORT: + case HASP_EVENT_DOUBLE: + case HASP_EVENT_LOST: + default: + return false; + } +} + +// Map events to their description string +void dispatch_get_event_name(uint8_t eventid, char * buffer, size_t size) +{ + switch(eventid) { + case HASP_EVENT_ON: + memcpy_P(buffer, PSTR("ON"), size); + break; + case HASP_EVENT_OFF: + memcpy_P(buffer, PSTR("OFF"), size); + break; + case HASP_EVENT_UP: + memcpy_P(buffer, PSTR("UP"), size); + break; + case HASP_EVENT_DOWN: + memcpy_P(buffer, PSTR("DOWN"), size); + break; + case HASP_EVENT_SHORT: + memcpy_P(buffer, PSTR("SHORT"), size); + break; + case HASP_EVENT_LONG: + memcpy_P(buffer, PSTR("LONG"), size); + break; + case HASP_EVENT_HOLD: + memcpy_P(buffer, PSTR("HOLD"), size); + break; + case HASP_EVENT_LOST: + memcpy_P(buffer, PSTR("LOST"), size); + break; + default: + memcpy_P(buffer, PSTR("UNKNOWN"), size); + } +} + +void dispatch_send_group_event(uint8_t groupid, uint8_t eventid, bool update_hasp) +{ + // update outputs + gpio_set_group_outputs(groupid, eventid); + + // send out value +#if !defined(HASP_USE_MQTT) && !defined(HASP_USE_TASMOTA_SLAVE) + Log.notice(F("OUT: group%d = %s"), groupid, eventid); +#else +#if HASP_USE_MQTT > 0 + // mqtt_send_input(id, event); +#endif +#if HASP_USE_TASMOTA_SLAVE > 0 + // slave_send_input(id, event); +#endif +#endif + + // update objects, except src_obj + if(update_hasp) hasp_set_group_objects(groupid, eventid, NULL); +} + +void dispatch_send_object_event(uint8_t pageid, uint8_t objid, uint8_t eventid) +{ + if(objid < 100) { + char eventname[16]; + dispatch_get_event_name(eventid, eventname, sizeof(eventname)); + dispatch_send_obj_attribute_str(pageid, objid, "event", eventname); /* Literal String */ + } else { + uint8_t groupid = (objid - 100) / 10; + dispatch_send_group_event(groupid, eventid, true); + } +} + void dispatchWebUpdate(const char * espOtaUrl) { #if HASP_USE_OTA > 0 @@ -326,7 +411,7 @@ void dispatchWebUpdate(const char * espOtaUrl) #endif } -void IRAM_ATTR dispatch_obj_attribute_str(uint8_t pageid, uint8_t btnid, const char * attribute, const char * data) +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); @@ -425,7 +510,7 @@ void dispatchConfig(const char * topic, const char * payload) settings.remove(F("pass")); // hide password in output size_t size = serializeJson(doc, buffer, sizeof(buffer)); #if !defined(HASP_USE_MQTT) && !defined(HASP_USE_TASMOTA_SLAVE) - Log.notice(F("OUT: config %s = %s"),topic,buffer); + Log.notice(F("OUT: config %s = %s"), topic, buffer); #else #if HASP_USE_MQTT > 0 mqtt_send_state(F("config"), buffer); diff --git a/src/hasp_dispatch.h b/src/hasp_dispatch.h index fabb3d9d..65abfeb3 100644 --- a/src/hasp_dispatch.h +++ b/src/hasp_dispatch.h @@ -26,6 +26,11 @@ void dispatchStatusUpdate(void); void dispatch_button(uint8_t id, const char * event); -void IRAM_ATTR dispatch_obj_attribute_str(uint8_t pageid, uint8_t btnid, const char * attribute, const char * data); +void dispatch_send_object_event(uint8_t pageid, uint8_t objid, uint8_t eventid); +void dispatch_send_group_event(uint8_t groupid, uint8_t eventid, bool update_hasp); +bool dispatch_get_event_state(uint8_t eventid); + +void IRAM_ATTR dispatch_send_obj_attribute_str(uint8_t pageid, uint8_t btnid, const char * attribute, + const char * data); #endif \ No newline at end of file diff --git a/src/hasp_gpio.cpp b/src/hasp_gpio.cpp index e9f01ae6..f6c8afd6 100644 --- a/src/hasp_gpio.cpp +++ b/src/hasp_gpio.cpp @@ -7,28 +7,22 @@ #include "hasp_conf.h" #include "hasp_gpio.h" #include "hasp_dispatch.h" - -#define HASP_NUM_GPIO_CONFIG 5 +#include "hasp.h" uint8_t gpioUsedInputCount = 0; -uint16_t gpioConfig[HASP_NUM_GPIO_CONFIG]; using namespace ace_button; static AceButton * button[HASP_NUM_INPUTS]; struct hasp_gpio_config_t { - const uint8_t pin; - const uint8_t group; - const uint8_t io_mode; - bool default_state; + uint8_t pin; // pin number + uint8_t group; // groupid + uint8_t type; // switch, button, ... + uint8_t gpio_function; // INPUT, OUTPUT, PULLUP, etc }; -// An array of button pins, led pins, and the led states. Cannot be const -// because ledState is mutable. -hasp_gpio_config_t gpioConfig2[HASP_NUM_GPIO_CONFIG] = { - {2, 8, INPUT, LOW}, {3, 9, OUTPUT, LOW}, {4, 10, INPUT, HIGH}, {5, 11, OUTPUT, LOW}, {6, 12, INPUT, LOW}, -}; +hasp_gpio_config_t gpioConfig[HASP_NUM_GPIO_CONFIG]; #if defined(ARDUINO_ARCH_ESP32) class TouchConfig : public ButtonConfig { @@ -53,39 +47,48 @@ class TouchConfig : public ButtonConfig { TouchConfig touchConfig(); #endif -static void gpio_event_cb(AceButton * button, uint8_t eventType, uint8_t buttonState) +static void gpio_event_handler(AceButton * button, uint8_t eventType, uint8_t buttonState) { + uint8_t eventid; char buffer[16]; switch(eventType) { - case 0: // AceButton::kEventPressed: + case AceButton::kEventPressed: + eventid = HASP_EVENT_DOWN; memcpy_P(buffer, PSTR("DOWN"), sizeof(buffer)); break; case 2: // AceButton::kEventClicked: + eventid = HASP_EVENT_SHORT; memcpy_P(buffer, PSTR("SHORT"), sizeof(buffer)); break; case AceButton::kEventDoubleClicked: + eventid = HASP_EVENT_DOUBLE; memcpy_P(buffer, PSTR("DOUBLE"), sizeof(buffer)); break; - case 4: // AceButton::kEventLongPressed: + case AceButton::kEventLongPressed: + eventid = HASP_EVENT_LONG; memcpy_P(buffer, PSTR("LONG"), sizeof(buffer)); break; - case 5: // AceButton::kEventRepeatPressed: + case AceButton::kEventRepeatPressed: // return; // Fix needed for switches + eventid = HASP_EVENT_HOLD; memcpy_P(buffer, PSTR("HOLD"), sizeof(buffer)); break; - case 1: // AceButton::kEventReleased: + case AceButton::kEventReleased: + eventid = HASP_EVENT_UP; memcpy_P(buffer, PSTR("UP"), sizeof(buffer)); break; default: + eventid = HASP_EVENT_LOST; memcpy_P(buffer, PSTR("UNKNOWN"), sizeof(buffer)); } dispatch_button(button->getId(), buffer); + dispatch_send_group_event(gpioConfig[button->getId()].group, eventid, true); } void aceButtonSetup(void) { ButtonConfig * buttonConfig = ButtonConfig::getSystemButtonConfig(); - buttonConfig->setEventHandler(gpio_event_cb); + buttonConfig->setEventHandler(gpio_event_handler); // Features buttonConfig->setFeature(ButtonConfig::kFeatureClick); @@ -110,21 +113,20 @@ void IRAM_ATTR gpioLoop(void) } } -void gpioAddButton(uint8_t pin, uint8_t input_mode, uint8_t default_state, uint8_t channel) +void gpioAddButton(uint8_t pin, uint8_t input_mode, uint8_t default_state, uint8_t index) { - uint8_t i; for(i = 0; i < HASP_NUM_INPUTS; i++) { if(!button[i]) { - button[i] = new AceButton(pin, default_state, channel); - // button[i]->init(pin, default_state, channel); + button[i] = new AceButton(pin, default_state, index); + // button[i]->init(pin, default_state, index); if(button[i]) { pinMode(pin, input_mode); ButtonConfig * buttonConfig = button[i]->getButtonConfig(); - buttonConfig->setEventHandler(gpio_event_cb); + buttonConfig->setEventHandler(gpio_event_handler); buttonConfig->setFeature(ButtonConfig::kFeatureClick); buttonConfig->clearFeature(ButtonConfig::kFeatureDoubleClick); buttonConfig->setFeature(ButtonConfig::kFeatureLongPress); @@ -132,30 +134,30 @@ void gpioAddButton(uint8_t pin, uint8_t input_mode, uint8_t default_state, uint8 buttonConfig->clearFeature( ButtonConfig::kFeatureSuppressClickBeforeDoubleClick); // Causes annoying pauses - Log.verbose(F("GPIO: Button%d created on pin %d (channel %d) mode %d default %d"), i, pin, channel, + Log.verbose(F("GPIO: Button%d created on pin %d (index %d) mode %d default %d"), i, pin, index, input_mode, default_state); gpioUsedInputCount = i + 1; return; } } } - Log.error(F("GPIO: Failed to create Button%d pin %d (channel %d). All %d slots available are in use!"), i, pin, - channel, HASP_NUM_INPUTS); + Log.error(F("GPIO: Failed to create Button%d pin %d (index %d). All %d slots available are in use!"), i, pin, index, + HASP_NUM_INPUTS); } -void gpioAddTouchButton(uint8_t pin, uint8_t input_mode, uint8_t default_state, uint8_t channel) +void gpioAddTouchButton(uint8_t pin, uint8_t input_mode, uint8_t default_state, uint8_t index) { uint8_t i; for(i = 0; i < HASP_NUM_INPUTS; i++) { if(!button[i]) { - button[i] = new AceButton(); + button[i] = new AceButton(pin, default_state, index); if(button[i]) { pinMode(pin, input_mode); ButtonConfig * buttonConfig = button[i]->getButtonConfig(); - buttonConfig->setEventHandler(gpio_event_cb); + buttonConfig->setEventHandler(gpio_event_handler); buttonConfig->setFeature(ButtonConfig::kFeatureClick); buttonConfig->clearFeature(ButtonConfig::kFeatureDoubleClick); buttonConfig->setFeature(ButtonConfig::kFeatureLongPress); @@ -163,83 +165,39 @@ void gpioAddTouchButton(uint8_t pin, uint8_t input_mode, uint8_t default_state, buttonConfig->clearFeature( ButtonConfig::kFeatureSuppressClickBeforeDoubleClick); // Causes annoying pauses - Log.verbose(F("GPIO: Button%d created on pin %d (channel %d) mode %d default %d"), i, pin, channel, + Log.verbose(F("GPIO: Button%d created on pin %d (index %d) mode %d default %d"), i, pin, index, input_mode, default_state); gpioUsedInputCount = i + 1; return; } } } - Log.error(F("GPIO: Failed to create Button%d pin %d (channel %d). All %d slots available are in use!"), i, pin, - channel, HASP_NUM_INPUTS); + Log.error(F("GPIO: Failed to create Button%d pin %d (index %d). All %d slots available are in use!"), i, pin, index, + HASP_NUM_INPUTS); } void gpioSetup() { aceButtonSetup(); - return; - - // gpioConfig[0] = PD15 * 256 + 5 + (INPUT << 3); + // return; + #if defined(ARDUINO_ARCH_ESP8266) - gpioAddButton(D2, INPUT_PULLUP, HIGH, 1); - //pinMode(D1, OUTPUT); + 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); #endif #if defined(ARDUINO_ARCH_ESP32) - // gpioAddButton(D2, INPUT, HIGH, 1); - // pinMode(D1, OUTPUT); + // gpioConfig[0] = {D2, 0, HASP_GPIO_SWITCH, INPUT}; + // gpioConfig[1] = {D1, 1, HASP_GPIO_RELAY, OUTPUT}; + +// gpioAddButton(D2, INPUT, HIGH, 1); +// pinMode(D1, OUTPUT); #endif - for(uint8_t i = 0; i < HASP_NUM_GPIO_CONFIG; i++) { - uint8_t pin = (gpioConfig[i] >> 8) & 0xFF; - uint8_t channel = gpioConfig[i] & 0b111; // 3bit - uint8_t input_mode = (gpioConfig[i] >> 3) & 0b11; // 2bit gpio mode - // uint8_t input_mode = gpioConfig[i].io_mode - uint8_t gpiotype = (gpioConfig[i] >> 5) & 0b111; // 3bit - uint8_t default_state = gpioConfig[i] & 0b1; // 1bit: 0=LOW, 1=HIGH - - switch(input_mode) { - case 1: - input_mode = OUTPUT; - break; - case 2: - input_mode = INPUT_PULLUP; - break; -#ifndef ARDUINO_ARCH_ESP8266 - case 3: - input_mode = INPUT_PULLDOWN; - break; -#endif - default: - input_mode = INPUT; - } - - switch(gpiotype) { - case HASP_GPIO_SWITCH: - case HASP_GPIO_BUTTON: - // gpioAddButton(gpioConfig[i].io_mode.pin, input_mode, gpioConfig[i].default_state, - // gpioConfig[i].group); - break; - - case HASP_GPIO_RELAY: - pinMode(pin, OUTPUT); - break; - - // case HASP_GPIO_LED: - case HASP_GPIO_PWM: - case HASP_GPIO_BACKLIGHT: - pinMode(pin, OUTPUT); -#if defined(ARDUINO_ARCH_ESP32) - // configure LED PWM functionalitites - ledcSetup(channel, 20000, 10); - // attach the channel to the GPIO to be controlled - ledcAttachPin(pin, channel); -#endif - break; - } - } - /* #if defined(ARDUINO_ARCH_ESP8266) pinMode(D1, OUTPUT); @@ -250,4 +208,88 @@ void gpioSetup() pinMode(HASP_INPUT_PIN, INPUT); #endif */ -} \ No newline at end of file + + for(uint8_t i = 0; i < HASP_NUM_GPIO_CONFIG; i++) { + uint8_t input_mode; + switch(gpioConfig[i].gpio_function) { + case OUTPUT: + input_mode = OUTPUT; + break; + case INPUT_PULLUP: + input_mode = INPUT_PULLUP; + break; +#ifndef ARDUINO_ARCH_ESP8266 + case INPUT_PULLDOWN: + input_mode = INPUT_PULLDOWN; + break; +#endif + default: + input_mode = INPUT; + } + + switch(gpioConfig[i].type) { + case HASP_GPIO_SWITCH: + case HASP_GPIO_BUTTON: + gpioAddButton(gpioConfig[i].pin, input_mode, HIGH, i); + break; + case HASP_GPIO_SWITCH_INVERTED: + case HASP_GPIO_INPUT_BUTTON_INVERTED: + gpioAddButton(gpioConfig[i].pin, input_mode, LOW, i); + break; + + case HASP_GPIO_RELAY: + case HASP_GPIO_RELAY_INVERTED: + case HASP_GPIO_LED: + case HASP_GPIO_LED_INVERTED: + pinMode(gpioConfig[i].pin, OUTPUT); + break; + + case HASP_GPIO_PWM: + case HASP_GPIO_PWM_INVERTED: + // case HASP_GPIO_BACKLIGHT: + pinMode(gpioConfig[i].pin, OUTPUT); +#if defined(ARDUINO_ARCH_ESP32) + // configure LED PWM functionalitites + ledcSetup(gpioConfig[i].group, 20000, 10); + // attach the channel to the GPIO to be controlled + ledcAttachPin(gpioConfig[i].pin, gpioConfig[i].group); +#endif + break; + } + } +} + +void gpio_set_group_outputs(uint8_t groupid, uint8_t eventid) +{ + bool state = dispatch_get_event_state(eventid); + for(uint8_t i = 0; i < HASP_NUM_GPIO_CONFIG; i++) { + if(gpioConfig[i].group == groupid) { + switch(gpioConfig[i].type) { + case HASP_GPIO_RELAY: + case HASP_GPIO_LED: + digitalWrite(gpioConfig[i].pin, state ? HIGH : LOW); + break; + case HASP_GPIO_RELAY_INVERTED: + case HASP_GPIO_LED_INVERTED: + digitalWrite(gpioConfig[i].pin, state ? LOW : HIGH); + break; +#if defined(ARDUINO_ARCH_ESP32) + case HASP_GPIO_PWM: + ledcWrite(groupid, map(state, 0, 1, 0, 1023)); // ledChannel and value + break; + case HASP_GPIO_PWM_INVERTED: + ledcWrite(groupid, map(!state, 0, 1, 0, 1023)); // ledChannel and value + break; +#else + case HASP_GPIO_PWM: + analogWrite(gpioConfig[i].pin, map(state, 0, 1, 0, 1023)); + break; + case HASP_GPIO_PWM_INVERTED: + analogWrite(gpioConfig[i].pin, map(!state, 0, 1, 0, 1023)); + break; +#endif + default:; + } + } + } +} diff --git a/src/hasp_gpio.h b/src/hasp_gpio.h index 9a5c3b91..c9e5ed52 100644 --- a/src/hasp_gpio.h +++ b/src/hasp_gpio.h @@ -9,14 +9,27 @@ extern "C" { void gpioSetup(void); void IRAM_ATTR gpioLoop(void); +void gpio_set_group_outputs(uint8_t groupid, uint8_t eventid); -enum lv_hasp_gpio_type_t { - HASP_GPIO_SWITCH = 0, - HASP_GPIO_BUTTON = 1, - HASP_GPIO_RELAY = 2, - HASP_GPIO_PWM = 3, - HASP_GPIO_BACKLIGHT = 4, -}; +#define HASP_GPIO_FREE 0x00 +#define HASP_GPIO_USED 0x01 +#define HASP_GPIO_SWITCH 0x02 +#define HASP_GPIO_SWITCH_INVERTED 0x03 +#define HASP_GPIO_BUTTON 0x04 +#define HASP_GPIO_INPUT_BUTTON_INVERTED 0x05 +#define HASP_GPIO_COUNTER 0x06 +#define HASP_GPIO_COUNTER_INVERTED 0x07 +#define HASP_GPIO_ADC 0x08 +#define HASP_GPIO_ADC_INVERTED 0x09 +#define HASP_GPIO_RELAY 0x0A +#define HASP_GPIO_RELAY_INVERTED 0x0B +#define HASP_GPIO_LED 0x0C +#define HASP_GPIO_LED_INVERTED 0x0D +#define HASP_GPIO_PWM 0x0E +#define HASP_GPIO_PWM_INVERTED 0x0F +#define HASP_GPIO_DAC 0x10 +#define HASP_GPIO_DAC_INVERTED 0x11 +#define HASP_GPIO_USER 0xFF #ifdef __cplusplus } /* extern "C" */ diff --git a/src/hasp_gui.cpp b/src/hasp_gui.cpp index b021afe0..3935e463 100644 --- a/src/hasp_gui.cpp +++ b/src/hasp_gui.cpp @@ -52,7 +52,7 @@ File pFileOut; #endif -// #define LVGL_TICK_PERIOD 30 +#define LVGL_TICK_PERIOD 20 #ifndef TFT_BCKL #define TFT_BCKL -1 // No Backlight Control @@ -75,7 +75,7 @@ static uint8_t guiRotation = TFT_ROTATION; #if ESP32 > 0 || ESP8266 > 0 static Ticker tick; /* timer for interrupt handler */ #else -static Ticker tick(lv_tick_handler, guiTickPeriod); +static Ticker tick(lv_tick_handler, LVGL_TICK_PERIOD); // guiTickPeriod); #endif // static TFT_eSPI tft; // = TFT_eSPI(); /* TFT instance */ static uint16_t calData[5] = {0, 65535, 0, 65535, 0}; @@ -132,10 +132,10 @@ static void IRAM_ATTR my_flush_cb(lv_disp_drv_t * disp, const lv_area_t * area, } /* Interrupt driven periodic handler */ -static void IRAM_ATTR lv_tick_handler(void) +static void ICACHE_RAM_ATTR lv_tick_handler(void) { // Serial.print("."); - lv_tick_inc(guiTickPeriod); + lv_tick_inc(LVGL_TICK_PERIOD); } /* Reading input device (simulated encoder here) */ @@ -388,7 +388,7 @@ bool IRAM_ATTR my_touchpad_read(lv_indev_drv_t * indev_driver, lv_indev_data_t * uint16_t touchX, touchY; bool touched; #if TOUCH_DRIVER == 0 - touched = tft_espi_get_touch(&touchX, &touchY, 600); + touched = tft_espi_get_touch(&touchX, &touchY, 300); #elif TOUCH_DRIVER == 1 // return false; touched = GT911_getXY(&touchX, &touchY, true); @@ -486,7 +486,7 @@ void guiSetup() #elif defined(ARDUINO_ARCH_ESP8266) /* allocate on heap */ static lv_disp_buf_t disp_buf; - static lv_color_t guiVdbBuffer1[5 * 512u]; // 5 KBytes + static lv_color_t guiVdbBuffer1[4 * 512u]; // 4 KBytes // static lv_color_t guiVdbBuffer2[3 * 1024u]; // 6 KBytes guiVDBsize = sizeof(guiVdbBuffer1) / sizeof(guiVdbBuffer1[0]); lv_disp_buf_init(&disp_buf, guiVdbBuffer1, NULL, guiVDBsize); @@ -564,6 +564,7 @@ void guiSetup() disp_drv.ver_res = TFT_WIDTH; } lv_disp_drv_register(&disp_drv); + guiStart(); /* Initialize Global progress bar*/ lv_obj_t * bar = lv_bar_create(lv_layer_sys(), NULL); @@ -580,14 +581,6 @@ void guiSetup() lv_obj_set_style_local_bg_color(lv_layer_sys(), LV_OBJ_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_BLACK); lv_obj_set_style_local_bg_opa(lv_layer_sys(), LV_OBJ_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_0); - /*Initialize the graphics library's tick*/ -#if defined(ARDUINO_ARCH_ESP32) || defined(ARDUINO_ARCH_ESP8266) - tick.attach_ms(guiTickPeriod, lv_tick_handler); -#else - tick.start(); -#endif - lv_tick_handler(); - /*Initialize the touch pad*/ lv_indev_drv_t indev_drv; lv_indev_drv_init(&indev_drv); @@ -639,34 +632,6 @@ void guiSetup() lv_obj_set_click(cursor, false); // don't click on the cursor lv_indev_set_cursor(mouse_indev, cursor); // }*/ - - /*Initialize the graphics library's tick*/ -#if defined(ARDUINO_ARCH_ESP32) || defined(ARDUINO_ARCH_ESP8266) -#else - - /* - #if defined(TIM1) - TIM_TypeDef * Instance = TIM1; - #else - TIM_TypeDef * Instance = TIM2; - #endif - */ - // Instantiate HardwareTimer object. Thanks to 'new' instanciation, HardwareTimer is not destructed when setup() - // function is finished. - /* static HardwareTimer * MyTim = new HardwareTimer(Instance); - MyTim->pause(); - MyTim->setPrescaleFactor(1); - MyTim->setMode(0, TIMER_OUTPUT_COMPARE, NC); - MyTim->setOverflow(1000 * guiTickPeriod, MICROSEC_FORMAT); // MicroSec - MyTim->setCount(0,MICROSEC_FORMAT); - MyTim->refresh(); - MyTim->detachInterrupt(); - MyTim->attachInterrupt((void (*)(HardwareTimer *))lv_tick_handler); - MyTim->detachInterrupt(0); - MyTim->attachInterrupt(0,(void (*)(HardwareTimer *))lv_tick_handler); - MyTim->resume();*/ - tick.start(); -#endif } void IRAM_ATTR guiLoop() @@ -675,8 +640,8 @@ void IRAM_ATTR guiLoop() tick.update(); #endif - // lv_tick_handler(); - lv_task_handler(); /* let the GUI do its work */ + lv_task_handler(); + guiCheckSleep(); #if TOUCH_DRIVER == 1 @@ -684,8 +649,25 @@ void IRAM_ATTR guiLoop() #endif } +void guiStart() +{ + /*Initialize the graphics library's tick*/ +#if defined(ARDUINO_ARCH_ESP32) || defined(ARDUINO_ARCH_ESP8266) + tick.attach_ms(LVGL_TICK_PERIOD, lv_tick_handler); +#else + tick.start(); +#endif +} + void guiStop() -{} +{ + /*Deinitialize the graphics library's tick*/ +#if defined(ARDUINO_ARCH_ESP32) || defined(ARDUINO_ARCH_ESP8266) + tick.detach(); +#else + tick.stop(); +#endif +} bool guiGetBacklight() { diff --git a/src/hasp_gui.h b/src/hasp_gui.h index 76166eae..4e5891dc 100644 --- a/src/hasp_gui.h +++ b/src/hasp_gui.h @@ -19,6 +19,7 @@ void guiTakeScreenshot(); void guiSetup(); +void guiStart(void); void guiLoop(void); void guiStop(void); diff --git a/src/hasp_http.cpp b/src/hasp_http.cpp index d64d177e..13528a79 100644 --- a/src/hasp_http.cpp +++ b/src/hasp_http.cpp @@ -45,7 +45,7 @@ char httpUser[32] = ""; char httpPassword[32] = ""; #define HTTP_PAGE_SIZE (6 * 256) -#if defined(STM32F4xx) && HASP_USE_ETHERNET>0 +#if defined(STM32F4xx) && HASP_USE_ETHERNET > 0 #include EthernetWebServer webServer(80); #endif @@ -621,10 +621,13 @@ String getContentType(String filename) static unsigned long htppLastLoopTime = 0; void webUploadProgress() { + long t = webServer.header("Content-Length").toInt(); if(millis() - htppLastLoopTime >= 1250) { - Log.verbose(F(" * Uploaded %u bytes"), upload->totalSize + upload->currentSize); + Log.verbose(F(" * Uploaded %u bytes / %d"), upload->totalSize + upload->currentSize, t); htppLastLoopTime = millis(); } + if(t > 0) t = (upload->totalSize + upload->currentSize) * 100 / t; + haspProgressVal(t); } #if defined(ARDUINO_ARCH_ESP32) || defined(ARDUINO_ARCH_ESP8266) @@ -635,6 +638,7 @@ void webUpdatePrintError() StringStream stream((String &)output); Update.printError(stream); Log.error(F("HTTP: %s"), output.c_str()); + haspProgressMsg(output.c_str()); } void webUpdateReboot() @@ -666,6 +670,7 @@ void webHandleFirmwareUpdate() if(upload->status == UPLOAD_FILE_START) { if(!httpIsAuthenticated(F("update"))) return; Log.notice(F("Update: %s"), upload->filename.c_str()); + haspProgressMsg(upload->filename.c_str()); // WiFiUDP::stopAll(); uint32_t maxSketchSpace = (ESP.getFreeSketchSpace() - 0x1000) & 0xFFFFF000; // if(!Update.begin(UPDATE_SIZE_UNKNOWN)) { // start with max available size @@ -722,6 +727,7 @@ void handleFileUpload() upload = &webServer.upload(); if(upload->status == UPLOAD_FILE_START) { if(!httpIsAuthenticated(F("fileupload"))) return; + Log.verbose(F("Total size: %s"), webServer.headerName(0).c_str()); String filename((char *)0); filename.reserve(128); filename = upload->filename; @@ -732,6 +738,7 @@ void handleFileUpload() if(filename.length() < 32) { fsUploadFile = filesystem->open(filename, "w"); Log.notice(F("handleFileUpload Name: %s"), filename.c_str()); + haspProgressMsg(fsUploadFile.name()); } else { Log.error(F("Filename %s is too long"), filename.c_str()); } @@ -749,6 +756,7 @@ void handleFileUpload() Log.verbose(F("Uploaded %s (%u bytes)"), fsUploadFile.name(), upload->totalSize); fsUploadFile.close(); } + haspProgressVal(255); // Redirect to /config/hasp page. This flushes the web buffer and frees the memory webServer.sendHeader(String(F("Location")), String(F("/config/hasp")), true); @@ -1638,7 +1646,12 @@ void httpSetup() // first callback is called after the request has ended with all parsed arguments // second callback handles file uploads at that location webServer.on( - F("/edit"), HTTP_POST, []() { webServer.send(200, "text/plain", ""); }, handleFileUpload); + F("/edit"), HTTP_POST, + []() { + webServer.send(200, "text/plain", ""); + Log.verbose(F("Headers: %d"), webServer.headers()); + }, + handleFileUpload); #endif // get heap status, analog input value and all GPIO statuses in one json call @@ -1680,7 +1693,12 @@ void httpSetup() webServer.on(F("/firmware"), webHandleFirmware); #if defined(ARDUINO_ARCH_ESP32) || defined(ARDUINO_ARCH_ESP8266) webServer.on( - F("/update"), HTTP_POST, []() { webServer.send(200, "text/plain", ""); }, webHandleFirmwareUpdate); + F("/update"), HTTP_POST, + []() { + webServer.send(200, "text/plain", ""); + Log.verbose(F("Total size: %s"), webServer.hostHeader().c_str()); + }, + webHandleFirmwareUpdate); webServer.on(F("/espfirmware"), httpHandleEspFirmware); #endif webServer.on(F("/reboot"), httpHandleReboot); @@ -1696,6 +1714,11 @@ void httpSetup() webServer.on(F("/config"), webHandleConfig); webServer.onNotFound(httpHandleNotFound); + // ask server to track these headers + const char * headerkeys[] = {"Content-Length"}; // "Authentication" + size_t headerkeyssize = sizeof(headerkeys) / sizeof(char *); + webServer.collectHeaders(headerkeys, headerkeyssize); + Log.verbose(F("HTTP: Setup Complete")); webStart(); } diff --git a/src/hasp_ota.cpp b/src/hasp_ota.cpp index cc7a3fca..1bede7cf 100644 --- a/src/hasp_ota.cpp +++ b/src/hasp_ota.cpp @@ -7,14 +7,15 @@ #include "hasp_debug.h" #include "hasp_dispatch.h" #include "hasp_ota.h" +#include "hasp.h" #include "hasp_conf.h" -#if HASP_USE_MQTT>0 +#if HASP_USE_MQTT > 0 #include "hasp_mqtt.h" #endif -#if HASP_USE_MDNS>0 +#if HASP_USE_MDNS > 0 #include "hasp_mdns.h" #endif @@ -56,20 +57,28 @@ void otaSetup() } Log.notice(F("OTA: Start update")); + haspProgressVal(0); + haspProgressMsg(F("OTA: Firmware Update")); // dispatchPage("0"); otaPrecentageComplete = 0; // haspSetAttr("p[0].b[1].txt", "\"ESP OTA Update\""); }); ArduinoOTA.onEnd([]() { otaPrecentageComplete = 100; + haspProgressMsg(F("Applying Firmware & Reboot")); + haspProgressVal(100); otaProgress(); otaPrecentageComplete = -1; // dispatchPage("0"); // haspSetAttr("p[0].b[1].txt", "\"ESP OTA Update\\rComplete!\""); - dispatchReboot(true); + setup(); + //dispatchReboot(true); }); ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) { - if(total != 0) otaPrecentageComplete = progress * 100 / total; + if(total != 0) { + otaPrecentageComplete = progress * 100 / total; + haspProgressVal(otaPrecentageComplete); + } // haspSetAttr("p[0].b[1].txt", "\"ESP OTA Update\\rProgress: " + String(progress / (total / 100)) + "%\""); }); @@ -87,7 +96,7 @@ void otaSetup() else if(error == OTA_END_ERROR) Log.error(F("OTA: ERROR - End Failed")); // haspSetAttr("p[0].b[1].txt", "\"ESP OTA FAILED\""); - delay(5000); + // delay(5000); // haspSendCmd("page " + String(nextionActivePage)); }); @@ -107,7 +116,7 @@ void otaSetup() #endif // ArduinoOTA.setTimeout(1000); #endif - ArduinoOTA.setRebootOnSuccess(true); + ArduinoOTA.setRebootOnSuccess(false); // We do that ArduinoOTA.begin(); Log.notice(F("OTA: Over the Air firmware update ready")); diff --git a/src/hasp_wifi.cpp b/src/hasp_wifi.cpp index 6c39f819..00df9802 100644 --- a/src/hasp_wifi.cpp +++ b/src/hasp_wifi.cpp @@ -4,7 +4,7 @@ #include "hasp_conf.h" -#if HASP_USE_WIFI>0 +#if HASP_USE_WIFI > 0 #include "hasp_debug.h" #include "hasp_config.h" @@ -57,6 +57,7 @@ void wifiConnected(IPAddress ipaddress) Log.notice(F("WIFI: Received IP address %s"), ipaddress.toString().c_str()); #endif Log.verbose(F("WIFI: Connected = %s"), WiFi.status() == WL_CONNECTED ? PSTR("yes") : PSTR("no")); + haspProgressVal(255); // if(isConnected) { // mqttReconnect(); @@ -69,7 +70,9 @@ void wifiConnected(IPAddress ipaddress) void wifiDisconnected(const char * ssid, uint8_t reason) { wifiReconnectCounter++; - if(wifiReconnectCounter > 45) { + haspProgressVal(wifiReconnectCounter * 3); + haspProgressMsg(F("Wifi Disconnected")); + if(wifiReconnectCounter > 33) { Log.error(F("WIFI: Retries exceed %u: Rebooting..."), wifiReconnectCounter); dispatchReboot(false); } diff --git a/src/main.cpp b/src/main.cpp index 78d36ce6..ea3ab485 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -183,5 +183,5 @@ void loop() mainLastLoopTime += 1000; } - delay(3); + delay(1); } \ No newline at end of file diff --git a/user_setups/esp32/d1-mini-esp32_ili9341.ini b/user_setups/esp32/d1-mini-esp32_ili9341.ini index 26835497..593ad419 100644 --- a/user_setups/esp32/d1-mini-esp32_ili9341.ini +++ b/user_setups/esp32/d1-mini-esp32_ili9341.ini @@ -8,8 +8,8 @@ [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 +;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 = diff --git a/user_setups/esp8266/D1-mini_ili9341.ini b/user_setups/esp8266/D1-mini_ili9341.ini index 2c334eb1..759717ea 100644 --- a/user_setups/esp8266/D1-mini_ili9341.ini +++ b/user_setups/esp8266/D1-mini_ili9341.ini @@ -8,8 +8,8 @@ [env:d1mini-lolintft24] platform = espressif8266@^2.4.0 ;@2.3.2 board = d1_mini -upload_port = COM7 ; To change the port, use platform_override.ini -monitor_port = COM7 ; To change the port, use platform_override.ini +;upload_port = COM7 ; To change the port, use platform_override.ini +;monitor_port = COM7 ; 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