diff --git a/src/hasp/hasp.cpp b/src/hasp/hasp.cpp index bc7150dd..6e7bc1b8 100644 --- a/src/hasp/hasp.cpp +++ b/src/hasp/hasp.cpp @@ -566,7 +566,7 @@ void haspSetup(void) hasp_init(); hasp_load_json(); - haspPages.set(haspStartPage, LV_SCR_LOAD_ANIM_FADE_ON); + haspPages.set(haspStartPage, LV_SCR_LOAD_ANIM_FADE_ON, 500, 0); // lv_obj_t* obj = lv_datetime_create(haspPages.get_obj(haspPages.get()), NULL); // obj->user_data.objid = LV_HASP_DATETIME; diff --git a/src/hasp/hasp_anim.cpp b/src/hasp/hasp_anim.cpp new file mode 100644 index 00000000..8ad5ef35 --- /dev/null +++ b/src/hasp/hasp_anim.cpp @@ -0,0 +1,166 @@ +#ifdef LV_LVGL_H_INCLUDE_SIMPLE +#include "lvgl.h" +#include "hasp_anim.h" +#include "hasplib.h" +#else +#include "lvgl/lvgl.h" +#endif + +#if LV_USE_ANIMATION + +static void my_scr_load_anim_start(lv_anim_t* a) +{ + lv_disp_t* d = lv_obj_get_disp((lv_obj_t*)a->var); + d->prev_scr = lv_scr_act(); + + lv_obj_t* page = (lv_obj_t*)a->var; + uint8_t pageid; + uint8_t objid; + + lv_disp_load_scr(page); + if(hasp_find_id_from_obj(page, &pageid, &objid)) { + LOG_TRACE(TAG_HASP, F(D_HASP_CHANGE_PAGE), pageid); + dispatch_current_page(); +#if defined(HASP_DEBUG_OBJ_TREE) + hasp_object_tree(page, pageid, 0); +#endif + } else { + dispatch_current_page(); + } +} + +static void my_opa_scale_anim(lv_obj_t* obj, lv_anim_value_t v) +{ + lv_obj_set_style_local_opa_scale(obj, LV_OBJ_PART_MAIN, LV_STATE_DEFAULT, v); +} + +static void my_scr_anim_ready(lv_anim_t* a) +{ + lv_disp_t* d = lv_obj_get_disp((lv_obj_t*)a->var); + + if(d->prev_scr && d->del_prev) lv_obj_del(d->prev_scr); + d->prev_scr = NULL; + d->scr_to_load = NULL; + lv_style_remove_prop(lv_obj_get_local_style((lv_obj_t*)a->var, LV_OBJ_PART_MAIN), LV_STYLE_OPA_SCALE); +} + +/** + * Switch screen with animation + * @param scr pointer to the new screen to load + * @param anim_type type of the animation from `lv_scr_load_anim_t`. E.g. `LV_SCR_LOAD_ANIM_MOVE_LEFT` + * @param time time of the animation + * @param delay delay before the transition + * @param auto_del true: automatically delete the old screen + */ +void my_scr_load_anim(lv_obj_t* new_scr, lv_scr_load_anim_t anim_type, uint32_t time, uint32_t delay, bool auto_del) +{ + lv_disp_t* d = lv_obj_get_disp(new_scr); + lv_obj_t* act_scr = lv_scr_act(); + + if(d->scr_to_load && act_scr != d->scr_to_load) { + lv_disp_load_scr(d->scr_to_load); + lv_anim_del(d->scr_to_load, NULL); + lv_obj_set_pos(d->scr_to_load, 0, 0); + lv_style_remove_prop(lv_obj_get_local_style(d->scr_to_load, LV_OBJ_PART_MAIN), LV_STYLE_OPA_SCALE); + + if(d->del_prev) { + lv_obj_del(act_scr); + } + act_scr = d->scr_to_load; + } + + d->scr_to_load = new_scr; + + if(d->prev_scr && d->del_prev) { + lv_obj_del(d->prev_scr); + d->prev_scr = NULL; + } + + d->del_prev = auto_del; + + /*Be sure there is no other animation on the screens*/ + lv_anim_del(new_scr, NULL); + lv_anim_del(lv_scr_act(), NULL); + + /*Be sure both screens are in a normal position*/ + lv_obj_set_pos(new_scr, 0, 0); + lv_obj_set_pos(lv_scr_act(), 0, 0); + lv_style_remove_prop(lv_obj_get_local_style(new_scr, LV_OBJ_PART_MAIN), LV_STYLE_OPA_SCALE); + lv_style_remove_prop(lv_obj_get_local_style(lv_scr_act(), LV_OBJ_PART_MAIN), LV_STYLE_OPA_SCALE); + + lv_anim_t a_new; + lv_anim_init(&a_new); + lv_anim_set_var(&a_new, new_scr); + lv_anim_set_start_cb(&a_new, my_scr_load_anim_start); + lv_anim_set_ready_cb(&a_new, my_scr_anim_ready); + lv_anim_set_time(&a_new, time); + lv_anim_set_delay(&a_new, delay); + + lv_anim_t a_old; + lv_anim_init(&a_old); + lv_anim_set_var(&a_old, d->act_scr); + lv_anim_set_time(&a_old, time); + lv_anim_set_delay(&a_old, delay); + + switch(anim_type) { + case LV_SCR_LOAD_ANIM_NONE: + /* Create a dummy animation to apply the delay*/ + lv_anim_set_exec_cb(&a_new, (lv_anim_exec_xcb_t)lv_obj_set_x); + lv_anim_set_values(&a_new, 0, 0); + break; + case LV_SCR_LOAD_ANIM_OVER_LEFT: + lv_anim_set_exec_cb(&a_new, (lv_anim_exec_xcb_t)lv_obj_set_x); + lv_anim_set_values(&a_new, lv_disp_get_hor_res(d), 0); + break; + case LV_SCR_LOAD_ANIM_OVER_RIGHT: + lv_anim_set_exec_cb(&a_new, (lv_anim_exec_xcb_t)lv_obj_set_x); + lv_anim_set_values(&a_new, -lv_disp_get_hor_res(d), 0); + break; + case LV_SCR_LOAD_ANIM_OVER_TOP: + lv_anim_set_exec_cb(&a_new, (lv_anim_exec_xcb_t)lv_obj_set_y); + lv_anim_set_values(&a_new, lv_disp_get_ver_res(d), 0); + break; + case LV_SCR_LOAD_ANIM_OVER_BOTTOM: + lv_anim_set_exec_cb(&a_new, (lv_anim_exec_xcb_t)lv_obj_set_y); + lv_anim_set_values(&a_new, -lv_disp_get_ver_res(d), 0); + break; + case LV_SCR_LOAD_ANIM_MOVE_LEFT: + lv_anim_set_exec_cb(&a_new, (lv_anim_exec_xcb_t)lv_obj_set_x); + lv_anim_set_values(&a_new, lv_disp_get_hor_res(d), 0); + + lv_anim_set_exec_cb(&a_old, (lv_anim_exec_xcb_t)lv_obj_set_x); + lv_anim_set_values(&a_old, 0, -lv_disp_get_hor_res(d)); + break; + case LV_SCR_LOAD_ANIM_MOVE_RIGHT: + lv_anim_set_exec_cb(&a_new, (lv_anim_exec_xcb_t)lv_obj_set_x); + lv_anim_set_values(&a_new, -lv_disp_get_hor_res(d), 0); + + lv_anim_set_exec_cb(&a_old, (lv_anim_exec_xcb_t)lv_obj_set_x); + lv_anim_set_values(&a_old, 0, lv_disp_get_hor_res(d)); + break; + case LV_SCR_LOAD_ANIM_MOVE_TOP: + lv_anim_set_exec_cb(&a_new, (lv_anim_exec_xcb_t)lv_obj_set_y); + lv_anim_set_values(&a_new, lv_disp_get_ver_res(d), 0); + + lv_anim_set_exec_cb(&a_old, (lv_anim_exec_xcb_t)lv_obj_set_y); + lv_anim_set_values(&a_old, 0, -lv_disp_get_ver_res(d)); + break; + case LV_SCR_LOAD_ANIM_MOVE_BOTTOM: + lv_anim_set_exec_cb(&a_new, (lv_anim_exec_xcb_t)lv_obj_set_y); + lv_anim_set_values(&a_new, -lv_disp_get_ver_res(d), 0); + + lv_anim_set_exec_cb(&a_old, (lv_anim_exec_xcb_t)lv_obj_set_y); + lv_anim_set_values(&a_old, 0, lv_disp_get_ver_res(d)); + break; + + case LV_SCR_LOAD_ANIM_FADE_ON: + lv_anim_set_exec_cb(&a_new, (lv_anim_exec_xcb_t)my_opa_scale_anim); + lv_anim_set_values(&a_new, LV_OPA_TRANSP, LV_OPA_COVER); + break; + } + + lv_anim_start(&a_new); + lv_anim_start(&a_old); +} + +#endif \ No newline at end of file diff --git a/src/hasp/hasp_anim.h b/src/hasp/hasp_anim.h new file mode 100644 index 00000000..88a5dfcb --- /dev/null +++ b/src/hasp/hasp_anim.h @@ -0,0 +1,31 @@ +#ifndef HASP_ANIM_H +#define HASP_ANIM_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef LV_LVGL_H_INCLUDE_SIMPLE +#include "lvgl.h" +#else +#include "lvgl/lvgl.h" +#endif + +#if LV_USE_ANIMATION + +/** + * Switch screen with animation + * @param scr pointer to the new screen to load + * @param anim_type type of the animation from `lv_scr_load_anim_t`. E.g. `LV_SCR_LOAD_ANIM_MOVE_LEFT` + * @param time time of the animation + * @param delay delay before the transition + * @param auto_del true: automatically delete the old screen + */ +void my_scr_load_anim(lv_obj_t * new_scr, lv_scr_load_anim_t anim_type, uint32_t time, uint32_t delay, bool auto_del); +#endif + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif \ No newline at end of file diff --git a/src/hasp/hasp_attribute.cpp b/src/hasp/hasp_attribute.cpp index 9cbfd36c..bca9c107 100644 --- a/src/hasp/hasp_attribute.cpp +++ b/src/hasp/hasp_attribute.cpp @@ -2723,6 +2723,19 @@ void hasp_process_obj_attribute(lv_obj_t* obj, const char* attribute, const char val = strtol(payload, nullptr, DEC); ret = specific_page_attribute(obj, attr_hash, val, update); break; + case ATTR_NAME: { + uint8_t pageid = 99; + haspPages.get_id(obj, &pageid); + if(update) { + haspPages.set_name(pageid, payload); + LOG_VERBOSE(TAG_HASP, F("%s %d"), haspPages.get_name(pageid), pageid); + } else { + text = haspPages.get_name(pageid); + LOG_VERBOSE(TAG_HASP, F("%s %d"), haspPages.get_name(pageid), pageid); + } + ret = HASP_ATTR_TYPE_STR; + break; + } case ATTR_DIRECTION: val = strtol(payload, nullptr, DEC); diff --git a/src/hasp/hasp_attribute.h b/src/hasp/hasp_attribute.h index 2c5de754..b8fdb4b7 100644 --- a/src/hasp/hasp_attribute.h +++ b/src/hasp/hasp_attribute.h @@ -391,6 +391,7 @@ _HASP_ATTRIBUTE(SCALE_END_LINE_WIDTH, scale_end_line_width, lv_style_int_t) #define ATTR_NEXT 60915 #define ATTR_PREV 21587 #define ATTR_BACK 57799 +#define ATTR_NAME 44331 /* Object Attributes */ #define ATTR_X 120 diff --git a/src/hasp/hasp_dispatch.cpp b/src/hasp/hasp_dispatch.cpp index 777808d6..af4a1dfa 100644 --- a/src/hasp/hasp_dispatch.cpp +++ b/src/hasp/hasp_dispatch.cpp @@ -776,53 +776,71 @@ void dispatch_current_page() // Dispatch Page Get or Set void dispatch_page_next(lv_scr_load_anim_t animation) { - haspPages.next(animation); + haspPages.next(animation, 500, 0); dispatch_current_page(); } void dispatch_page_prev(lv_scr_load_anim_t animation) { - haspPages.prev(animation); + haspPages.prev(animation, 500, 0); dispatch_current_page(); } void dispatch_page_back(lv_scr_load_anim_t animation) { - haspPages.back(animation); + haspPages.back(animation, 500, 0); dispatch_current_page(); } void dispatch_set_page(uint8_t pageid) { - dispatch_set_page(pageid, LV_SCR_LOAD_ANIM_NONE); + dispatch_set_page(pageid, LV_SCR_LOAD_ANIM_NONE, 500, 0); } -void dispatch_set_page(uint8_t pageid, lv_scr_load_anim_t animation) +void dispatch_set_page(uint8_t pageid, lv_scr_load_anim_t animation, uint32_t time, uint32_t delay) { - haspPages.set(pageid, animation); - dispatch_current_page(); + haspPages.set(pageid, animation, time, delay); } -void dispatch_page(const char*, const char* page, uint8_t source) +void dispatch_page(const char*, const char* payload, uint8_t source) { - if(strlen(page) == 0) { + if(!payload || strlen(payload) == 0) { dispatch_current_page(); // No payload, send current page return; } lv_scr_load_anim_t animation = LV_SCR_LOAD_ANIM_NONE; - if(Parser::is_only_digits(page)) { - uint8_t pageid = atoi(page); - dispatch_set_page(pageid, animation); - } else if(!strcasecmp_P(page, PSTR("prev"))) { - dispatch_page_prev(animation); - } else if(!strcasecmp_P(page, PSTR("next"))) { - dispatch_page_next(animation); - } else if(!strcasecmp_P(page, PSTR("back"))) { - dispatch_page_back(animation); - } else { - LOG_WARNING(TAG_MSGR, PSTR(D_DISPATCH_INVALID_PAGE), page); + uint32_t time = 500; + uint32_t delay = 0; + uint8_t pageid = Parser::haspPayloadToPageid(payload); + + if(pageid == 0) { + size_t maxsize = (128u * ((strlen(payload) / 128) + 1)) + 128; + DynamicJsonDocument json(maxsize); + + // Note: Deserialization needs to be (const char *) so the objects WILL be copied + // this uses more memory but otherwise the mqtt receive buffer can get overwritten by the send buffer !! + DeserializationError jsonError = deserializeJson(json, payload); + json.shrinkToFit(); + + if(!jsonError && json.is()) { // Only JsonObject is valid + JsonVariant prop; + + prop = json[F("page")]; + if(!prop.isNull()) pageid = Parser::haspPayloadToPageid(prop.as()); + + prop = json[F("transition")]; + if(!prop.isNull()) animation = (lv_scr_load_anim_t)prop.as(); + + prop = json[F("time")]; + if(!prop.isNull()) time = prop.as(); + + prop = json[F("delay")]; + if(!prop.isNull()) delay = prop.as(); + } } + + dispatch_set_page(pageid, animation, time, delay); } // Clears all fonts @@ -1122,6 +1140,15 @@ void dispatch_send_sensordata(const char*, const char*, uint8_t source) #endif } +void dispatch_queue_discovery(const char*, const char*, uint8_t source) +{ + long seconds = random(10); + if(dispatchSecondsToNextTeleperiod == seconds) seconds++; + if(dispatchSecondsToNextSensordata == seconds) seconds++; + LOG_VERBOSE(TAG_MSGR, F("Discovery queued in %d seconds"), seconds); + dispatchSecondsToNextDiscovery = seconds; +} + // Periodically publish a JSON string facilitating plate discovery void dispatch_send_discovery(const char*, const char*, uint8_t source) { @@ -1169,7 +1196,7 @@ void dispatch_send_discovery(const char*, const char*, uint8_t source) default: LOG_ERROR(TAG_MQTT, F(D_ERROR_UNKNOWN)); } - dispatchSecondsToNextDiscovery = dispatch_setings.teleperiod; + dispatchSecondsToNextDiscovery = dispatch_setings.teleperiod * 2 + random(10); #endif } @@ -1418,7 +1445,7 @@ void dispatchSetup() dispatch_add_command(PSTR("reboot"), dispatch_reboot); dispatch_add_command(PSTR("restart"), dispatch_reboot); dispatch_add_command(PSTR("screenshot"), dispatch_screenshot); - dispatch_add_command(PSTR("discovery"), dispatch_send_discovery); + dispatch_add_command(PSTR("discovery"), dispatch_queue_discovery); dispatch_add_command(PSTR("factoryreset"), dispatch_factory_reset); /* obsolete commands */ @@ -1451,21 +1478,18 @@ void dispatchEverySecond() dispatchSecondsToNextTeleperiod--; } else if(dispatch_setings.teleperiod > 0 && mqttIsConnected()) { dispatch_statusupdate(NULL, NULL, TAG_MSGR); - dispatchSecondsToNextTeleperiod = dispatch_setings.teleperiod; } if(dispatchSecondsToNextSensordata > 1) { dispatchSecondsToNextSensordata--; } else if(dispatch_setings.teleperiod > 0 && mqttIsConnected()) { dispatch_send_sensordata(NULL, NULL, TAG_MSGR); - dispatchSecondsToNextSensordata = dispatch_setings.teleperiod; } if(dispatchSecondsToNextDiscovery > 1) { dispatchSecondsToNextDiscovery--; } else if(dispatch_setings.teleperiod > 0 && mqttIsConnected()) { dispatch_send_discovery(NULL, NULL, TAG_MSGR); - dispatchSecondsToNextDiscovery = dispatch_setings.teleperiod; } #endif } diff --git a/src/hasp/hasp_dispatch.h b/src/hasp/hasp_dispatch.h index 39961fc2..1ea8eefe 100644 --- a/src/hasp/hasp_dispatch.h +++ b/src/hasp/hasp_dispatch.h @@ -58,10 +58,11 @@ void dispatch_parse_jsonl(std::istream& stream, uint8_t& saved_page_id); void dispatch_clear_page(const char* page); void dispatch_json_error(uint8_t tag, DeserializationError& jsonError); -void dispatch_set_page(uint8_t pageid, lv_scr_load_anim_t effectid); +void dispatch_set_page(uint8_t pageid, lv_scr_load_anim_t animation, uint32_t time, uint32_t delay); void dispatch_page_next(lv_scr_load_anim_t effectid); void dispatch_page_prev(lv_scr_load_anim_t effectid); void dispatch_page_back(lv_scr_load_anim_t effectid); +void dispatch_page(const char*, const char* payload, uint8_t source); bool dispatch_factory_reset(); void dispatch_reboot(bool saveConfig); diff --git a/src/hasp/hasp_event.cpp b/src/hasp/hasp_event.cpp index 36b7d408..8725bb93 100644 --- a/src/hasp/hasp_event.cpp +++ b/src/hasp/hasp_event.cpp @@ -365,13 +365,13 @@ void swipe_event_handler(lv_obj_t* obj, lv_event_t event) lv_gesture_dir_t dir = lv_indev_get_gesture_dir(lv_indev_get_act()); switch(dir) { case LV_GESTURE_DIR_LEFT: - haspPages.next(LV_SCR_LOAD_ANIM_NONE); + haspPages.next(LV_SCR_LOAD_ANIM_NONE, 500, 0); break; case LV_GESTURE_DIR_RIGHT: - haspPages.prev(LV_SCR_LOAD_ANIM_NONE); + haspPages.prev(LV_SCR_LOAD_ANIM_NONE, 500, 0); break; case LV_GESTURE_DIR_BOTTOM: - haspPages.back(LV_SCR_LOAD_ANIM_NONE); + haspPages.back(LV_SCR_LOAD_ANIM_NONE, 500, 0); break; default: return; @@ -488,16 +488,16 @@ void generic_event_handler(lv_obj_t* obj, lv_event_t event) lv_scr_load_anim_t transitionid = (lv_scr_load_anim_t)obj->user_data.transitionid; switch(obj->user_data.actionid) { case HASP_NUM_PAGE_PREV: - haspPages.prev(transitionid); + haspPages.prev(transitionid, 500, 0); break; case HASP_NUM_PAGE_BACK: - haspPages.back(transitionid); + haspPages.back(transitionid, 500, 0); break; case HASP_NUM_PAGE_NEXT: - haspPages.next(transitionid); + haspPages.next(transitionid, 500, 0); break; default: - haspPages.set(obj->user_data.actionid, transitionid); + haspPages.set(obj->user_data.actionid, transitionid, 500, 0); } dispatch_current_page(); } diff --git a/src/hasp/hasp_object.cpp b/src/hasp/hasp_object.cpp index 2b262d77..0e5d2e9e 100644 --- a/src/hasp/hasp_object.cpp +++ b/src/hasp/hasp_object.cpp @@ -109,8 +109,12 @@ void hasp_object_tree(const lv_obj_t* parent, uint8_t pageid, uint16_t level) /* Sends the data out on the state/pxby topic */ void object_dispatch_state(uint8_t pageid, uint8_t btnid, const char* payload) { - char topic[16]; - snprintf_P(topic, sizeof(topic), PSTR(HASP_OBJECT_NOTATION), pageid, btnid); + char topic[64]; + char* pagename = haspPages.get_name(pageid); + if (pagename) + snprintf_P(topic, sizeof(topic), PSTR("%s.b%u"), pagename, btnid); + else + snprintf_P(topic, sizeof(topic), PSTR(HASP_OBJECT_NOTATION), pageid, btnid); dispatch_state_subtopic(topic, payload); } diff --git a/src/hasp/hasp_page.cpp b/src/hasp/hasp_page.cpp index d7a49ce8..e6e8a468 100644 --- a/src/hasp/hasp_page.cpp +++ b/src/hasp/hasp_page.cpp @@ -4,6 +4,7 @@ #include "hasplib.h" #include +#include "hasp_anim.h" #if defined(ARDUINO) #include "StreamUtils.h" // For EEPromStream @@ -53,7 +54,7 @@ void Page::swap(lv_obj_t* page, uint8_t id) // Delete previous page object if(prev_page_obj) { if(prev_page_obj == lv_scr_act()) { - lv_scr_load_anim(_pages[id], LV_SCR_LOAD_ANIM_NONE, 500, 0, false); // update page screen obj + my_scr_load_anim(_pages[id], LV_SCR_LOAD_ANIM_NONE, 500, 0, false); // update page screen obj lv_obj_del_async(prev_page_obj); } else lv_obj_del(prev_page_obj); @@ -73,6 +74,8 @@ void Page::init(uint8_t start_page) _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; + + set_name(i, NULL); } } @@ -92,7 +95,7 @@ void Page::clear(uint8_t pageid) // set(pageid, LV_SCR_LOAD_ANIM_NONE); // } -void Page::set(uint8_t pageid, lv_scr_load_anim_t animation) +void Page::set(uint8_t pageid, lv_scr_load_anim_t anim_type, uint32_t time, uint32_t delay) { lv_obj_t* page = get_obj(pageid); if(!is_valid(pageid)) { @@ -101,9 +104,17 @@ void Page::set(uint8_t pageid, lv_scr_load_anim_t animation) LOG_WARNING(TAG_HASP, F(D_HASP_INVALID_PAGE), pageid); } else { _current_page = pageid; - if(page != lv_scr_act()) { + if(page == lv_scr_act()) { + dispatch_current_page(); + return; + } + + if((anim_type != LV_SCR_LOAD_ANIM_NONE && time > 0) || delay > 0) { + my_scr_load_anim(page, anim_type, time, delay, false); + } else { LOG_TRACE(TAG_HASP, F(D_HASP_CHANGE_PAGE), pageid); - lv_scr_load_anim(page, animation, 500, 0, false); + lv_scr_load_anim(page, anim_type, time, delay, false); + dispatch_current_page(); #if defined(HASP_DEBUG_OBJ_TREE) hasp_object_tree(page, pageid, 0); #endif @@ -126,6 +137,11 @@ uint8_t Page::get_back(uint8_t pageid) return is_valid(pageid) ? _meta_data[pageid - PAGE_START_INDEX].back : 0; } +char* Page::get_name(uint8_t pageid) +{ + return pageid <= HASP_NUM_PAGES ? _pagenames[pageid] : NULL; +} + void Page::set_next(uint8_t pageid, uint8_t nextid) { if(is_valid(pageid) && is_valid(nextid)) _meta_data[pageid - PAGE_START_INDEX].next = nextid; @@ -141,19 +157,49 @@ void Page::set_back(uint8_t pageid, uint8_t backid) if(is_valid(pageid) && is_valid(backid)) _meta_data[pageid - PAGE_START_INDEX].back = backid; } -void Page::next(lv_scr_load_anim_t animation) +void Page::set_name(uint8_t pageid, const char* name) { - set(_meta_data[_current_page - PAGE_START_INDEX].next, animation); + if(pageid > HASP_NUM_PAGES) { + LOG_WARNING(TAG_HASP, F(D_HASP_INVALID_PAGE), pageid); + return; + } + + LOG_VERBOSE(TAG_HASP, F("%s - %d"), __FILE__, __LINE__); + + if(_pagenames[pageid]) { + hasp_free(_pagenames[pageid]); + _pagenames[pageid] = NULL; + } + + LOG_VERBOSE(TAG_HASP, F("%s - %d"), __FILE__, __LINE__); + if(!name) return; + size_t size = strlen(name) + 1; + + LOG_VERBOSE(TAG_HASP, F("%s - %d"), __FILE__, __LINE__); + if(size > 1) { + _pagenames[pageid] = (char*)hasp_calloc(sizeof(char), size); + LOG_VERBOSE(TAG_HASP, F("%s - %d"), __FILE__, __LINE__); + if(_pagenames[pageid] == NULL) return; + memset(_pagenames[pageid], 0, size); + strlcpy(_pagenames[pageid], name, size); + LOG_VERBOSE(TAG_HASP, F("%s"), _pagenames[pageid]); + } + LOG_VERBOSE(TAG_HASP, F("%s - %d"), __FILE__, __LINE__); } -void Page::prev(lv_scr_load_anim_t animation) +void Page::next(lv_scr_load_anim_t anim_type, uint32_t time, uint32_t delay) { - set(_meta_data[_current_page - PAGE_START_INDEX].prev, animation); + set(_meta_data[_current_page - PAGE_START_INDEX].next, anim_type, time, delay); } -void Page::back(lv_scr_load_anim_t animation) +void Page::prev(lv_scr_load_anim_t anim_type, uint32_t time, uint32_t delay) { - set(_meta_data[_current_page - PAGE_START_INDEX].back, animation); + set(_meta_data[_current_page - PAGE_START_INDEX].prev, anim_type, time, delay); +} + +void Page::back(lv_scr_load_anim_t anim_type, uint32_t time, uint32_t delay) +{ + set(_meta_data[_current_page - PAGE_START_INDEX].back, anim_type, time, delay); } uint8_t Page::get() diff --git a/src/hasp/hasp_page.h b/src/hasp/hasp_page.h index 9c0afae2..cfc9b27a 100644 --- a/src/hasp/hasp_page.h +++ b/src/hasp/hasp_page.h @@ -26,6 +26,7 @@ namespace hasp { class Page { private: + char* _pagenames[HASP_NUM_PAGES + 1]; // index 0 = Page 0 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; @@ -36,20 +37,22 @@ class Page { void init(uint8_t start_page); void clear(uint8_t pageid); // void set(uint8_t pageid); - void set(uint8_t pageid, lv_scr_load_anim_t animation); + void set(uint8_t pageid, lv_scr_load_anim_t anim_type, uint32_t time, uint32_t delay); void swap(lv_obj_t* page, uint8_t id); - void next(lv_scr_load_anim_t animation); - void prev(lv_scr_load_anim_t animation); - void back(lv_scr_load_anim_t animation); + void next(lv_scr_load_anim_t anim_type, uint32_t time, uint32_t delay); + void prev(lv_scr_load_anim_t anim_type, uint32_t time, uint32_t delay); + void back(lv_scr_load_anim_t anim_type, uint32_t time, uint32_t delay); uint8_t get_next(uint8_t pageid); uint8_t get_prev(uint8_t pageid); uint8_t get_back(uint8_t pageid); + char* get_name(uint8_t pageid); void set_next(uint8_t pageid, uint8_t nextid); void set_prev(uint8_t pageid, uint8_t previd); void set_back(uint8_t pageid, uint8_t backid); + void set_name(uint8_t pageid, const char* name); uint8_t get(); void load_jsonl(const char* pagesfile); diff --git a/src/hasp/hasp_parser.cpp b/src/hasp/hasp_parser.cpp index ac5f1b1a..0b85e415 100644 --- a/src/hasp/hasp_parser.cpp +++ b/src/hasp/hasp_parser.cpp @@ -93,6 +93,25 @@ bool Parser::haspPayloadToColor(const char* payload, lv_color32_t& color) return false; /* Color not found */ } +uint8_t Parser::haspPayloadToPageid(const char* payload) +{ + if(!payload || strlen(payload) == 0) return 0; + + uint8_t pageid = 0; + uint8_t current_page = haspPages.get(); + + if(!strcasecmp_P(payload, PSTR("prev"))) { + pageid = haspPages.get_prev(current_page); + } else if(!strcasecmp_P(payload, PSTR("next"))) { + pageid = haspPages.get_next(current_page); + } else if(!strcasecmp_P(payload, PSTR("back"))) { + pageid = haspPages.get_back(current_page); + } else if(is_only_digits(payload)) { + pageid = atoi(payload); + } + return pageid; +} + // Map events to either ON or OFF (UP or DOWN) bool Parser::get_event_state(uint8_t eventid) { diff --git a/src/hasp/hasp_parser.h b/src/hasp/hasp_parser.h index 50cf56f5..4b9a8748 100644 --- a/src/hasp/hasp_parser.h +++ b/src/hasp/hasp_parser.h @@ -9,6 +9,7 @@ class Parser { public: + static uint8_t haspPayloadToPageid(const char* payload); static void ColorToHaspPayload(lv_color_t color, char* payload, size_t len); static bool haspPayloadToColor(const char* payload, lv_color32_t& color); static bool get_event_state(uint8_t eventid); diff --git a/src/sys/svc/hasp_console.cpp b/src/sys/svc/hasp_console.cpp index 99829f92..95c43a90 100644 --- a/src/sys/svc/hasp_console.cpp +++ b/src/sys/svc/hasp_console.cpp @@ -158,7 +158,7 @@ IRAM_ATTR void consoleLoop() break; case(ConsoleInput::KEY_FN)...(ConsoleInput::KEY_FN + 12): - dispatch_set_page(keypress - ConsoleInput::KEY_FN, LV_SCR_LOAD_ANIM_NONE); + dispatch_set_page(keypress - ConsoleInput::KEY_FN, LV_SCR_LOAD_ANIM_NONE, 500, 0); break; } } diff --git a/src/sys/svc/hasp_http.cpp b/src/sys/svc/hasp_http.cpp index c27608b9..d91bf4d0 100644 --- a/src/sys/svc/hasp_http.cpp +++ b/src/sys/svc/hasp_http.cpp @@ -1074,8 +1074,9 @@ static void handleFileCreate() } if(webServer.hasArg(F("page"))) { dispatch_wakeup(); - uint8_t pageid = atoi(webServer.arg(F("page")).c_str()); - dispatch_set_page(pageid, LV_SCR_LOAD_ANIM_NONE); + dispatch_page(NULL, webServer.arg(F("page")).c_str(), TAG_HTTP); + // uint8_t pageid = atoi(webServer.arg(F("page")).c_str()); + // dispatch_set_page(pageid, LV_SCR_LOAD_ANIM_NONE); } webServer.send(200, PSTR("text/plain"), ""); } @@ -2353,7 +2354,8 @@ void httpSetup() webServer.on(F("/page/"), []() { String pageid = webServer.arg(F("page")); webServer.send(200, PSTR("text/plain"), "Page: '" + pageid + "'"); - dispatch_set_page(pageid.toInt(), LV_SCR_LOAD_ANIM_NONE); + dispatch_page(NULL, webServer.arg(F("page")).c_str(), TAG_HTTP); + // dispatch_set_page(pageid.toInt(), LV_SCR_LOAD_ANIM_NONE); }); #if HASP_USE_SPIFFS > 0 || HASP_USE_LITTLEFS > 0