From cc6ce5c4f872b404b5092dbedd4d75c7677be643 Mon Sep 17 00:00:00 2001 From: fvanroie Date: Mon, 8 Mar 2021 03:37:21 +0100 Subject: [PATCH] Add local page navigation action --- include/lv_conf_v7.h | 3 +- src/hasp/hasp.cpp | 117 ++------------------------- src/hasp/hasp.h | 7 -- src/hasp/hasp_attribute.cpp | 5 ++ src/hasp/hasp_attribute.h | 1 + src/hasp/hasp_dispatch.cpp | 92 +++++++++++----------- src/hasp/hasp_dispatch.h | 3 +- src/hasp/hasp_object.cpp | 60 +++++++++----- src/hasp/hasp_page.cpp | 152 ++++++++++++++++++++++++++++++++++++ src/hasp/hasp_page.h | 55 +++++++++++++ src/hasplib.h | 1 + src/log/hasp_debug.cpp | 2 +- src/sys/svc/hasp_http.cpp | 10 ++- 13 files changed, 319 insertions(+), 189 deletions(-) create mode 100644 src/hasp/hasp_page.cpp create mode 100644 src/hasp/hasp_page.h diff --git a/include/lv_conf_v7.h b/include/lv_conf_v7.h index 99166358..c6b4a3ed 100644 --- a/include/lv_conf_v7.h +++ b/include/lv_conf_v7.h @@ -518,8 +518,9 @@ typedef void* lv_font_user_data_t; /*Declare the type of the user data of object (can be e.g. `void *`, `int`, `struct`)*/ typedef struct { uint8_t objid:8; + uint8_t pageaction:8; uint8_t groupid:8; - uint8_t id; + uint8_t id:8; } lv_obj_user_data_t; /*1: enable `lv_obj_realaign()` based on `lv_obj_align()` parameters*/ diff --git a/src/hasp/hasp.cpp b/src/hasp/hasp.cpp index 0cc018be..ada116c0 100644 --- a/src/hasp/hasp.cpp +++ b/src/hasp/hasp.cpp @@ -26,6 +26,7 @@ #endif #include "hasplib.h" +#include "hasp.h" #include "lv_theme_hasp.h" #include "dev/device.h" @@ -68,7 +69,6 @@ LV_IMG_DECLARE(img_bubble_pattern) /********************** * GLOBAL FUNCTIONS **********************/ -void haspLoadPage(const char* pages); //////////////////////////////////////////////////////////////////////////////////////////////////// uint8_t hasp_sleep_state = HASP_SLEEP_OFF; // Used in hasp_drv_touch.cpp @@ -86,10 +86,8 @@ lv_style_t style_mbox_bg; /*Black bg. style with opacity*/ lv_obj_t* kb; // lv_font_t * defaultFont; -lv_obj_t* pages[HASP_NUM_PAGES]; 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 = 1; /** * Get Font ID @@ -164,42 +162,6 @@ void haspEverySecond() dispatchEverySecond(); } -//////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Get Page Object by PageID - */ -lv_obj_t* get_page_obj(uint8_t pageid) -{ - if(pageid == 0) return lv_layer_top(); // 254 - if(pageid == 255) return lv_layer_sys(); - if(pageid > sizeof pages / sizeof *pages) return NULL; // >=0 - return pages[pageid - PAGE_START_INDEX]; -} - -bool get_page_id(lv_obj_t* obj, uint8_t* pageid) -{ - lv_obj_t* page = lv_obj_get_screen(obj); - - if(!page) return false; - - if(page == lv_layer_top()) { - *pageid = 0; // 254 - return true; - } - if(page == lv_layer_sys()) { - *pageid = 255; - return true; - } - - for(uint8_t i = 0; i < sizeof pages / sizeof *pages; i++) { - if(page == pages[i]) { - *pageid = i + PAGE_START_INDEX; - return true; - } - } - return false; -} - //////////////////////////////////////////////////////////////////////////////////////////////////// void haspDisconnect() @@ -245,7 +207,7 @@ void haspReconnect() void haspProgressVal(uint8_t val) { lv_obj_t* layer = lv_disp_get_layer_sys(NULL); - lv_obj_t* bar = hasp_find_obj_from_parent_id(get_page_obj(255), (uint8_t)10); + lv_obj_t* bar = hasp_find_obj_from_parent_id(haspPages.get_obj(255), (uint8_t)10); if(layer && bar) { if(val == 255) { if(!lv_obj_get_hidden(bar)) { @@ -274,7 +236,7 @@ void haspProgressVal(uint8_t val) // Sets the value string of the global progress bar void haspProgressMsg(const char* msg) { - lv_obj_t* bar = hasp_find_obj_from_parent_id(get_page_obj(255), (uint8_t)10); + lv_obj_t* bar = hasp_find_obj_from_parent_id(haspPages.get_obj(255), (uint8_t)10); if(bar) { char value_str[10]; @@ -454,9 +416,6 @@ void haspSetup(void) } /* Create all screens using the theme */ - for(int i = 0; i < (sizeof pages / sizeof *pages); i++) { - pages[i] = lv_obj_create(NULL, NULL); - } #if HASP_USE_WIFI > 0 if(!wifiShowAP()) { @@ -464,8 +423,9 @@ void haspSetup(void) } #endif - haspLoadPage(haspPagesPath); - haspSetPage(haspStartPage); + haspPages.init(haspStartPage); + haspPages.load_jsonl(haspPagesPath); + haspPages.set(haspStartPage); } /********************** @@ -533,71 +493,6 @@ void haspGetVersion(char* version, size_t len) snprintf_P(version, len, PSTR("%u.%u.%u"), HASP_VER_MAJ, HASP_VER_MIN, HASP_VER_REV); } -void haspClearPage(uint16_t pageid) -{ - lv_obj_t* page = get_page_obj(pageid); - if(!page || (pageid > HASP_NUM_PAGES)) { - LOG_WARNING(TAG_HASP, F(D_HASP_INVALID_PAGE), pageid); - } else if(page == lv_layer_sys() /*|| page == lv_layer_top()*/) { - LOG_WARNING(TAG_HASP, F(D_HASP_INVALID_LAYER)); - } else { - LOG_TRACE(TAG_HASP, F(D_HASP_CLEAR_PAGE), pageid); - lv_obj_clean(page); - } -} - -uint8_t haspGetPage() -{ - return current_page; -} - -void haspSetPage(uint8_t pageid) -{ - lv_obj_t* page = get_page_obj(pageid); - if(!page || pageid == 0 || pageid > HASP_NUM_PAGES) { - LOG_WARNING(TAG_HASP, F(D_HASP_INVALID_PAGE), pageid); - } else { - LOG_TRACE(TAG_HASP, F(D_HASP_CHANGE_PAGE), pageid); - current_page = pageid; - lv_scr_load(page); - hasp_object_tree(page, pageid, 0); - } -} - -void haspLoadPage(const char* pagesfile) -{ -#if HASP_USE_SPIFFS > 0 || HASP_USE_LITTLEFS > 0 - if(pagesfile[0] == '\0') return; - - if(!filesystemSetup()) { - LOG_ERROR(TAG_HASP, F("FS not mounted. Failed to load %s"), pagesfile); - return; - } - - if(!HASP_FS.exists(pagesfile)) { - LOG_ERROR(TAG_HASP, F("Non existing file %s"), pagesfile); - return; - } - - LOG_TRACE(TAG_HASP, F("Loading file %s"), pagesfile); - - File file = HASP_FS.open(pagesfile, "r"); - dispatch_parse_jsonl(file); - file.close(); - - LOG_INFO(TAG_HASP, F("File %s loaded"), pagesfile); -#else - -#if HASP_USE_EEPROM > 0 - LOG_TRACE(TAG_HASP, F("Loading jsonl from EEPROM...")); - EepromStream eepromStream(4096, 1024); - dispatch_parse_jsonl(eepromStream); - LOG_INFO(TAG_HASP, F("Loaded jsonl from EEPROM")); -#endif - -#endif -} - //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// #if HASP_USE_CONFIG > 0 bool haspGetConfig(const JsonObject& settings) diff --git a/src/hasp/hasp.h b/src/hasp/hasp.h index 986eefc8..d43b68fd 100644 --- a/src/hasp/hasp.h +++ b/src/hasp/hasp.h @@ -56,13 +56,6 @@ void haspEverySecond(void); void haspReconnect(void); void haspDisconnect(void); -lv_obj_t* get_page_obj(uint8_t pageid); -bool get_page_id(lv_obj_t* obj, uint8_t* pageid); - -void haspSetPage(uint8_t id); -uint8_t haspGetPage(); -void haspClearPage(uint16_t pageid); - void haspGetVersion(char* version, size_t len); // void haspBackground(uint16_t pageid, uint16_t imageid); diff --git a/src/hasp/hasp_attribute.cpp b/src/hasp/hasp_attribute.cpp index a9444c5c..6cbfe8d3 100644 --- a/src/hasp/hasp_attribute.cpp +++ b/src/hasp/hasp_attribute.cpp @@ -1406,6 +1406,11 @@ void hasp_process_obj_attribute(lv_obj_t* obj, const char* attr_p, const char* p update ? (void)(obj->user_data.groupid = (uint8_t)val) : hasp_out_int(obj, attr, obj->user_data.groupid); break; // attribute_found + case ATTR_ACTION: + update ? (void)(obj->user_data.pageaction = (uint8_t)val) + : hasp_out_int(obj, attr, obj->user_data.pageaction); + break; // attribute_found + case ATTR_OBJID: if(update) { LOG_WARNING(TAG_ATTR, F(D_ATTRIBUTE_READ_ONLY), attr_p); diff --git a/src/hasp/hasp_attribute.h b/src/hasp/hasp_attribute.h index ff8ccf50..8eac5816 100644 --- a/src/hasp/hasp_attribute.h +++ b/src/hasp/hasp_attribute.h @@ -312,6 +312,7 @@ _HASP_ATTRIBUTE(SCALE_END_LINE_WIDTH, scale_end_line_width, lv_style_int_t) #define ATTR_MAP 45628 /* hasp user data */ +#define ATTR_ACTION 42102 #define ATTR_GROUPID 48986 #define ATTR_OBJID 41010 diff --git a/src/hasp/hasp_dispatch.cpp b/src/hasp/hasp_dispatch.cpp index 58d17e0a..1c7d2efa 100644 --- a/src/hasp/hasp_dispatch.cpp +++ b/src/hasp/hasp_dispatch.cpp @@ -742,7 +742,7 @@ void dispatch_parse_json(const char*, const char* payload) } // guiStart(); } else if(json.is()) { // handle json as a jsonl - uint8_t savedPage = haspGetPage(); + uint8_t savedPage = haspPages.get(); hasp_new_object(json.as(), savedPage); // #ifdef ARDUINO @@ -770,7 +770,7 @@ void dispatch_parse_jsonl(Stream& stream) void dispatch_parse_jsonl(std::istringstream& stream) #endif { - uint8_t savedPage = haspGetPage(); + uint8_t savedPage = haspPages.get(); size_t line = 1; DynamicJsonDocument jsonl(MQTT_MAX_PACKET_SIZE / 2 + 128); // max ~256 characters per line DeserializationError jsonError = deserializeJson(jsonl, stream); @@ -814,63 +814,65 @@ void dispatch_output_current_page() char payload[8]; memcpy_P(topic, PSTR("page"), 5); - snprintf_P(payload, sizeof(payload), PSTR("%d"), haspGetPage()); + snprintf_P(payload, sizeof(payload), PSTR("%d"), haspPages.get()); dispatch_state_subtopic(topic, payload); } -// Get or Set a page -void dispatch_page(const char*, const char* page) -{ - if(strlen(page) > 0) { - if(Utilities::is_only_digits(page)) { - uint8_t pageid = atoi(page); - haspSetPage(pageid); - } else { - - if(!strcasecmp_P(page, PSTR("prev"))) { - dispatch_page_prev(); - } else if(!strcasecmp_P(page, PSTR("next"))) { - dispatch_page_next(); - } else { - LOG_WARNING(TAG_MSGR, PSTR(D_DISPATCH_INVALID_PAGE), page); - } - return; - } - } - - dispatch_output_current_page(); -} - +// Dispatch Page Get or Set void dispatch_page_next() { - uint8_t page = haspGetPage(); - if(page >= HASP_NUM_PAGES) { - page = 1; - } else { - page++; - } - haspSetPage(page); + haspPages.next(); dispatch_output_current_page(); } void dispatch_page_prev() { - uint8_t page = haspGetPage(); - if(page == 1) { - page = HASP_NUM_PAGES; - } else { - page--; - } - haspSetPage(page); + haspPages.prev(); dispatch_output_current_page(); } +void dispatch_page_back() +{ + haspPages.back(); + dispatch_output_current_page(); +} + +void dispatch_set_page(uint8_t pageid) +{ + haspPages.set(pageid); + dispatch_output_current_page(); +} + +void dispatch_page(const char*, const char* page) +{ + if(strlen(page) == 0) { + dispatch_output_current_page(); // No payload, send current page + return; + } + + if(Utilities::is_only_digits(page)) { + uint8_t pageid = atoi(page); + dispatch_set_page(pageid); + } else if(!strcasecmp_P(page, PSTR("prev"))) { + dispatch_page_prev(); + } else if(!strcasecmp_P(page, PSTR("next"))) { + dispatch_page_next(); + } else if(!strcasecmp_P(page, PSTR("back"))) { + dispatch_page_back(); + } else { + LOG_WARNING(TAG_MSGR, PSTR(D_DISPATCH_INVALID_PAGE), page); + } +} + // Clears a page id or the current page if empty void dispatch_clear_page(const char*, const char* page) { - uint8_t pageid = haspGetPage(); - if(strlen(page) > 0) pageid = atoi(page); - haspClearPage(pageid); + uint8_t pageid; + if(strlen(page) > 0) + pageid = atoi(page); + else + pageid = haspPages.get(); + haspPages.clear(pageid); } void dispatch_dim(const char*, const char* level) @@ -1030,8 +1032,8 @@ void dispatch_output_statusupdate(const char*, const char*) haspDevice.get_free_heap(), haspDevice.get_heap_fragmentation(), haspDevice.get_core_version()); strcat(data, buffer); - snprintf_P(buffer, sizeof(buffer), PSTR("\"canUpdate\":\"false\",\"page\":%u,\"numPages\":%u,"), haspGetPage(), - (HASP_NUM_PAGES)); + snprintf_P(buffer, sizeof(buffer), PSTR("\"canUpdate\":\"false\",\"page\":%u,\"numPages\":%u,"), + haspPages.get(), haspPages.count()); strcat(data, buffer); #if defined(ARDUINO_ARCH_ESP8266) diff --git a/src/hasp/hasp_dispatch.h b/src/hasp/hasp_dispatch.h index ac0e591b..a12f492c 100644 --- a/src/hasp/hasp_dispatch.h +++ b/src/hasp/hasp_dispatch.h @@ -47,9 +47,10 @@ void dispatch_parse_jsonl(std::istringstream& stream); void dispatch_clear_page(const char* page); void dispatch_json_error(uint8_t tag, DeserializationError& jsonError); -// void dispatchPage(uint8_t page); +void dispatch_set_page(uint8_t pageid); void dispatch_page_next(); void dispatch_page_prev(); +void dispatch_page_back(); void dispatch_dim(const char* level); void dispatch_backlight(const char* payload); diff --git a/src/hasp/hasp_object.cpp b/src/hasp/hasp_object.cpp index 20350691..ac0b853b 100644 --- a/src/hasp/hasp_object.cpp +++ b/src/hasp/hasp_object.cpp @@ -71,7 +71,7 @@ lv_obj_t* hasp_find_obj_from_parent_id(lv_obj_t* parent, uint8_t objid) bool hasp_find_id_from_obj(lv_obj_t* obj, uint8_t* pageid, uint8_t* objid) { - if(!get_page_id(obj, pageid)) return false; + if(!haspPages.get_id(obj, pageid)) return false; if(!(obj->user_data.id > 0)) return false; // memcpy(objid, &obj->user_data.id, sizeof(lv_obj_user_data_t)); *objid = obj->user_data.id; @@ -350,8 +350,20 @@ void generic_event_handler(lv_obj_t* obj, lv_event_t event) return; } - hasp_update_sleep_state(); // wakeup? - dispatch_object_generic_event(obj, eventid); // send object event + hasp_update_sleep_state(); // wakeup? + + /* If a pageaction is attached, perform that action on UP event only */ + if(obj->user_data.pageaction) { + if(eventid == HASP_EVENT_UP) { + lv_scr_load_anim_t effectid = LV_SCR_LOAD_ANIM_NONE; + if(obj->user_data.pageaction >> 4 <= LV_SCR_LOAD_ANIM_FADE_ON) + effectid = (lv_scr_load_anim_t)(obj->user_data.pageaction >> 4); + uint8_t pageid = obj->user_data.pageaction & 0x0F; + haspPages.set(pageid, effectid); + } + } else { + dispatch_object_generic_event(obj, eventid); // send object event + } dispatch_normalized_group_value(obj->user_data.groupid, NORMALIZE(dispatch_get_event_state(eventid), 0, 1), obj); } @@ -540,7 +552,7 @@ void object_set_group_state(uint8_t groupid, uint8_t eventid, lv_obj_t* src_obj) for(uint8_t page = 0; page < HASP_NUM_PAGES; page++) { uint8_t startid = 1; for(uint8_t objid = startid; objid < 20; objid++) { - lv_obj_t* obj = hasp_find_obj_from_parent_id(get_page_obj(page), objid); + lv_obj_t* obj = hasp_find_obj_from_parent_id(haspPages.get_obj(page), objid); if(obj && obj != src_obj && obj->user_data.groupid == groupid) { // skip source object, if set lv_obj_set_state(obj, state ? LV_STATE_PRESSED | LV_STATE_CHECKED : LV_STATE_DEFAULT); } @@ -593,7 +605,7 @@ void object_set_group_value(uint8_t groupid, int16_t state) // Used in the dispatcher & hasp_new_object void hasp_process_attribute(uint8_t pageid, uint8_t objid, const char* attr, const char* payload) { - if(lv_obj_t* obj = hasp_find_obj_from_parent_id(get_page_obj(pageid), objid)) { + if(lv_obj_t* obj = hasp_find_obj_from_parent_id(haspPages.get_obj(pageid), objid)) { hasp_process_obj_attribute(obj, attr, payload, strlen(payload) > 0); } else { LOG_WARNING(TAG_HASP, F(D_OBJECT_UNKNOWN " " HASP_OBJECT_NOTATION), pageid, objid); @@ -639,17 +651,23 @@ int hasp_parse_json_attributes(lv_obj_t* obj, const JsonObject& doc) */ void hasp_new_object(const JsonObject& config, uint8_t& saved_page_id) { - /* Page selection: page is the default parent_obj */ - uint8_t pageid = config[FPSTR(FP_PAGE)].isNull() ? saved_page_id : config[FPSTR(FP_PAGE)].as(); - lv_obj_t* parent_obj = get_page_obj(pageid); + /* Page selection */ + uint8_t pageid = saved_page_id; + if(!config[FPSTR(FP_PAGE)].isNull()) { + config[FPSTR(FP_PAGE)].as(); + config.remove(FPSTR(FP_PAGE)); + } + + /* Page with pageid is the default parent_obj */ + lv_obj_t* parent_obj = haspPages.get_obj(pageid); if(!parent_obj) { LOG_WARNING(TAG_HASP, F(D_OBJECT_PAGE_UNKNOWN), pageid); return; } else { - saved_page_id = pageid; /* save the current pageid */ + saved_page_id = pageid; /* save the current pageid for next objects */ } - // lv_obj_t * parent_obj = page; + /* A custom parentid was set */ if(!config[FPSTR(FP_PARENTID)].isNull()) { uint8_t parentid = config[FPSTR(FP_PARENTID)].as(); parent_obj = hasp_find_obj_from_parent_id(parent_obj, parentid); @@ -659,13 +677,15 @@ void hasp_new_object(const JsonObject& config, uint8_t& saved_page_id) } else { LOG_VERBOSE(TAG_HASP, F("Parent ID " HASP_OBJECT_NOTATION " found"), pageid, parentid); } + config.remove(FPSTR(FP_PARENTID)); } uint16_t sdbm = 0; - uint8_t id = config[FPSTR(FP_ID)].as(); uint8_t groupid = config[FPSTR(FP_GROUPID)].as(); + uint8_t id = config[FPSTR(FP_ID)].as(); + config.remove(FPSTR(FP_ID)); - /* Define Objects*/ + /* Create the object if it does not exist */ lv_obj_t* obj = hasp_find_obj_from_parent_id(parent_obj, id); if(!obj) { @@ -677,9 +697,11 @@ void hasp_new_object(const JsonObject& config, uint8_t& saved_page_id) return; // comments } else { sdbm = Utilities::get_sdbm(config[FPSTR(FP_OBJ)].as()); + config.remove(FPSTR(FP_OBJ)); } } else { sdbm = config[FPSTR(FP_OBJID)].as(); + config.remove(FPSTR(FP_OBJID)); } switch(sdbm) { @@ -1015,19 +1037,17 @@ void hasp_new_object(const JsonObject& config, uint8_t& saved_page_id) LOG_VERBOSE(TAG_HASP, F(D_BULLET HASP_OBJECT_NOTATION " = %s"), pageid, temp, list.type[0]); /* test double-check */ - lv_obj_t* test = hasp_find_obj_from_parent_id(get_page_obj(pageid), (uint8_t)temp); + lv_obj_t* test = hasp_find_obj_from_parent_id(haspPages.get_obj(pageid), (uint8_t)temp); if(test != obj) { LOG_ERROR(TAG_HASP, F(D_OBJECT_MISMATCH)); return; + } else { + // object created successfully } - } - /* do not process these attributes */ - config.remove(FPSTR(FP_PAGE)); - config.remove(FPSTR(FP_ID)); - config.remove(FPSTR(FP_OBJ)); - config.remove(FPSTR(FP_OBJID)); // TODO: obsolete objid - config.remove(FPSTR(FP_PARENTID)); + } else { + // object already exists + } hasp_parse_json_attributes(obj, config); } diff --git a/src/hasp/hasp_page.cpp b/src/hasp/hasp_page.cpp new file mode 100644 index 00000000..41285997 --- /dev/null +++ b/src/hasp/hasp_page.cpp @@ -0,0 +1,152 @@ +/* MIT License - Copyright (c) 2019-2021 Francis Van Roie + For full license information read the LICENSE file in the project folder */ + +#include "hasp_conf.h" +#include "hasplib.h" + +#include "hasp_page.h" + +namespace hasp { + +Page::Page() +{ + // LVGL is not yet initialized at construction time +} + +size_t Page::count() +{ + return sizeof(_pages) / sizeof(*_pages); +} + +void Page::init(uint8_t start_page) +{ + for(int i = 0; i < count(); i++) { + _pages[i] = lv_obj_create(NULL, NULL); + + uint16_t thispage = i + PAGE_START_INDEX; + _meta_data[i].prev = thispage == PAGE_START_INDEX ? HASP_NUM_PAGES : thispage - PAGE_START_INDEX; + _meta_data[i].next = thispage == HASP_NUM_PAGES ? PAGE_START_INDEX : thispage + PAGE_START_INDEX; + _meta_data[i].back = start_page; + } +} + +void Page::clear(uint16_t pageid) +{ + lv_obj_t* page = get_obj(pageid); + if(!page || (pageid > HASP_NUM_PAGES)) { + LOG_WARNING(TAG_HASP, F(D_HASP_INVALID_PAGE), pageid); + } else if(page == lv_layer_sys() /*|| page == lv_layer_top()*/) { + LOG_WARNING(TAG_HASP, F(D_HASP_INVALID_LAYER)); + } else { + LOG_TRACE(TAG_HASP, F(D_HASP_CLEAR_PAGE), pageid); + lv_obj_clean(page); + } +} + +void Page::set(uint8_t pageid) +{ + set(pageid, LV_SCR_LOAD_ANIM_NONE); +} + +void Page::set(uint8_t pageid, lv_scr_load_anim_t effectid) +{ + lv_obj_t* page = get_obj(pageid); + if(!page || pageid == 0 || pageid > HASP_NUM_PAGES) { + LOG_WARNING(TAG_HASP, F(D_HASP_INVALID_PAGE), pageid); + } else { + LOG_TRACE(TAG_HASP, F(D_HASP_CHANGE_PAGE), pageid); + _current_page = pageid; + lv_scr_load_anim(page, effectid, 1000, 0, false); + hasp_object_tree(page, pageid, 0); + } +} + +void Page::next() +{ + set(_meta_data[_current_page - PAGE_START_INDEX].next); +} + +void Page::prev() +{ + set(_meta_data[_current_page - PAGE_START_INDEX].prev); +} + +void Page::back() +{ + set(_meta_data[_current_page - PAGE_START_INDEX].back); +} + +uint8_t Page::get() +{ + return _current_page; +} + +void Page::load_jsonl(const char* pagesfile) +{ +#if HASP_USE_SPIFFS > 0 || HASP_USE_LITTLEFS > 0 + if(pagesfile[0] == '\0') return; + + if(!filesystemSetup()) { + LOG_ERROR(TAG_HASP, F("FS not mounted. Failed to load %s"), pagesfile); + return; + } + + if(!HASP_FS.exists(pagesfile)) { + LOG_ERROR(TAG_HASP, F("Non existing file %s"), pagesfile); + return; + } + + LOG_TRACE(TAG_HASP, F("Loading file %s"), pagesfile); + + File file = HASP_FS.open(pagesfile, "r"); + dispatch_parse_jsonl(file); + file.close(); + + LOG_INFO(TAG_HASP, F("File %s loaded"), pagesfile); +#else + +#if HASP_USE_EEPROM > 0 + LOG_TRACE(TAG_HASP, F("Loading jsonl from EEPROM...")); + EepromStream eepromStream(4096, 1024); + dispatch_parse_jsonl(eepromStream); + LOG_INFO(TAG_HASP, F("Loaded jsonl from EEPROM")); +#endif + +#endif +} + +lv_obj_t* Page::get_obj(uint8_t pageid) +{ + if(pageid == 0) return lv_layer_top(); // 254 + if(pageid == 255) return lv_layer_sys(); + if(pageid > count()) return NULL; // >=0 + return _pages[pageid - PAGE_START_INDEX]; +} + +bool Page::get_id(lv_obj_t* obj, uint8_t* pageid) +{ + lv_obj_t* page = lv_obj_get_screen(obj); + + if(!page) return false; + + if(page == lv_layer_top()) { + *pageid = 0; + return true; + } + if(page == lv_layer_sys()) { + *pageid = 255; + return true; + } + + for(uint8_t i = 0; i < count(); i++) { + if(page == _pages[i]) { + *pageid = i + PAGE_START_INDEX; + return true; + } + } + return false; +} + +} // namespace hasp + +hasp::Page haspPages; diff --git a/src/hasp/hasp_page.h b/src/hasp/hasp_page.h new file mode 100644 index 00000000..60f3c382 --- /dev/null +++ b/src/hasp/hasp_page.h @@ -0,0 +1,55 @@ +/* MIT License - Copyright (c) 2019-2021 Francis Van Roie + For full license information read the LICENSE file in the project folder */ + +#ifndef HASP_PAGES_H +#define HASP_PAGES_H + +#include "hasp_conf.h" +#include "hasplib.h" + +/********************* + * DEFINES + *********************/ +#define PAGE_START_INDEX 1 // Page number of array index 0 + +/********************** + * TYPEDEFS + **********************/ + +typedef struct hasp_page_meta_data_t +{ + uint8_t prev : 4; + uint8_t next : 4; + uint8_t back : 4; +}; + +namespace hasp { + +class Page { + private: + hasp_page_meta_data_t _meta_data[HASP_NUM_PAGES]; // index 0 = Page 1 etc. + lv_obj_t* _pages[HASP_NUM_PAGES]; // index 0 = Page 1 etc. + uint8_t _current_page; + + public: + Page(); + size_t count(); + void init(uint8_t start_page); + void clear(uint16_t pageid); + void set(uint8_t pageid); + void set(uint8_t pageid, lv_scr_load_anim_t effectid); + void next(); + void prev(); + void back(); + uint8_t get(); + void load_jsonl(const char* pagesfile); + lv_obj_t* get_obj(uint8_t pageid); + bool get_id(lv_obj_t* obj, uint8_t* pageid); +}; + +} // namespace hasp + +using hasp::Page; +extern hasp::Page haspPages; + +#endif // HASP_PAGES_H diff --git a/src/hasplib.h b/src/hasplib.h index 158a6e56..ada7b224 100644 --- a/src/hasplib.h +++ b/src/hasplib.h @@ -4,6 +4,7 @@ #include "hasp/hasp_attribute.h" #include "hasp/hasp_dispatch.h" #include "hasp/hasp_object.h" +#include "hasp/hasp_page.h" #include "hasp/hasp_parser.h" #include "hasp/hasp_utilities.h" #include "hasp/hasp_lvfs.h" diff --git a/src/log/hasp_debug.cpp b/src/log/hasp_debug.cpp index 4f6d36b0..514b24d0 100644 --- a/src/log/hasp_debug.cpp +++ b/src/log/hasp_debug.cpp @@ -706,7 +706,7 @@ void debugLoop(void) break; case(ConsoleInput::KEY_FN)...(ConsoleInput::KEY_FN + 12): - haspSetPage(keypress - ConsoleInput::KEY_FN - 1); + dispatch_set_page(keypress - ConsoleInput::KEY_FN); break; } } while(keypress != 0); diff --git a/src/sys/svc/hasp_http.cpp b/src/sys/svc/hasp_http.cpp index b8c51533..04492f3a 100644 --- a/src/sys/svc/hasp_http.cpp +++ b/src/sys/svc/hasp_http.cpp @@ -14,12 +14,14 @@ #include "dev/device.h" #include "hasp_gui.h" -#include "hal/hasp_hal.h" +#include "hasp/hasp_dispatch.h" #include "hasp_debug.h" #include "hasp_config.h" +#include "hal/hasp_hal.h" #include "hasp/hasp_utilities.h" #include "hasp/hasp_dispatch.h" +#include "hasp/hasp_page.h" #include "hasp/hasp.h" #if HASP_USE_HTTP > 0 @@ -377,6 +379,8 @@ void webHandleScreenshot() dispatch_page_next(); } else if(webServer.arg(F("a")) == F("prev")) { dispatch_page_prev(); + } else if(webServer.arg(F("a")) == F("back")) { + dispatch_page_back(); } } @@ -559,7 +563,7 @@ void webHandleInfo() // String(LV_HASP_VER_RES_MAX); httpMessage += F("
LCD Version: ")) + // String(lcdVersion); httpMessage += F("

LCD Active Page: "); - httpMessage += String(haspGetPage()); + httpMessage += String(haspPages.get()); /* Wifi Stats */ #if HASP_USE_WIFI > 0 @@ -1958,7 +1962,7 @@ void httpSetup() webServer.on(F("/page/"), []() { String pageid = webServer.arg(F("page")); webServer.send(200, PSTR("text/plain"), "Page: '" + pageid + "'"); - haspSetPage(pageid.toInt()); + dispatch_set_page(pageid.toInt()); }); #if HASP_USE_SPIFFS > 0 || HASP_USE_LITTLEFS > 0