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