From 8152ba557af4b96da09630831a7654ec1ad4bbea Mon Sep 17 00:00:00 2001 From: fvanroie Date: Thu, 2 Apr 2020 16:44:41 +0200 Subject: [PATCH] Move attribute handler and sender --- src/hasp.h | 11 +- src/{hasp_attr_set.cpp => hasp_attribute.cpp} | 688 +++++++++++------- src/{hasp_attr_set.h => hasp_attribute.h} | 4 +- src/hasp_mqtt.cpp | 31 +- src/hasp_mqtt.h | 8 +- 5 files changed, 440 insertions(+), 302 deletions(-) rename src/{hasp_attr_set.cpp => hasp_attribute.cpp} (54%) rename src/{hasp_attr_set.h => hasp_attribute.h} (50%) diff --git a/src/hasp.h b/src/hasp.h index 39c091a1..302094c0 100644 --- a/src/hasp.h +++ b/src/hasp.h @@ -71,10 +71,13 @@ String haspGetNodename(); String haspGetVersion(); void haspBackground(uint16_t pageid, uint16_t imageid); -void hasp_process_attribute(uint8_t pageid, uint8_t objid, String strAttr, String strPayload); +void hasp_send_obj_attribute_str(lv_obj_t * obj, const char * attribute, const char * data); +void hasp_send_obj_attribute_int(lv_obj_t * obj, const char * attribute, int32_t val); +void hasp_process_attribute(uint8_t pageid, uint8_t objid, const char * attr, const char * payload); + void haspSendCmd(String nextionCmd); void haspParseJson(String & strPayload); -void haspNewObject(const JsonObject & settings); +void haspNewObject(const JsonObject & config, uint8_t & saved_page_id); void haspReconnect(void); void haspDisconnect(void); @@ -85,7 +88,9 @@ bool haspGetConfig(const JsonObject & settings); bool haspSetConfig(const JsonObject & settings); bool check_obj_type(const char * lvobjtype, lv_hasp_obj_type_t haspobjtype); -void haspSetToggle(lv_obj_t * obj, bool toggle); + +void IRAM_ATTR btn_event_handler(lv_obj_t * obj, lv_event_t event); +void IRAM_ATTR toggle_event_handler(lv_obj_t * obj, lv_event_t event); /********************** * MACROS diff --git a/src/hasp_attr_set.cpp b/src/hasp_attribute.cpp similarity index 54% rename from src/hasp_attr_set.cpp rename to src/hasp_attribute.cpp index ed6ad4a1..5cfb01eb 100644 --- a/src/hasp_attr_set.cpp +++ b/src/hasp_attribute.cpp @@ -1,21 +1,38 @@ #include "ArduinoLog.h" +#include "ArduinoJson.h" #include "lvgl.h" #include "lv_conf.h" -#include "hasp.h" -#include "hasp_attr_set.h" -#define LVGL7 1 +#include "hasp.h" +#include "hasp_dispatch.h" +#include "hasp_attribute.h" LV_FONT_DECLARE(unscii_8_icon); extern lv_font_t * haspFonts[8]; -static inline bool is_true(const char * s) +static inline bool is_true(const char * s); +static inline bool only_digits(const char * s); +static inline void hasp_out_int(lv_obj_t * obj, const char * attr, uint32_t val); +static inline void hasp_out_str(lv_obj_t * obj, const char * attr, const char * data); +static inline void hasp_out_color(lv_obj_t * obj, const char * attr, lv_color_t color); + +// this function is missing in lvgl +// OK +static uint8_t lv_roller_get_visible_row_count(lv_obj_t * roller) { - return (!strcmp_P(s, PSTR("true")) || !strcmp_P(s, PSTR("TRUE")) || !strcmp_P(s, PSTR("1"))); + const lv_font_t * font = lv_obj_get_style_text_font(roller, LV_ROLLER_PART_BG); + lv_style_int_t line_space = lv_obj_get_style_text_line_space(roller, LV_ROLLER_PART_BG); + lv_coord_t h = lv_obj_get_height(roller); + + if((lv_font_get_line_height(font) + line_space) != 0) + return (uint8_t)(h / (lv_font_get_line_height(font) + line_space)); + else + return 0; } -lv_color_t haspLogColor(lv_color_t color) +// OK +static lv_color_t haspLogColor(lv_color_t color) { uint8_t r = (LV_COLOR_GET_R(color) * 263 + 7) >> 5; uint8_t g = (LV_COLOR_GET_G(color) * 259 + 3) >> 6; @@ -24,7 +41,8 @@ lv_color_t haspLogColor(lv_color_t color) return color; } -lv_color_t haspPayloadToColor(const char * payload) +// OK +static lv_color_t haspPayloadToColor(const char * payload) { switch(strlen(payload)) { case 3: @@ -55,6 +73,7 @@ lv_color_t haspPayloadToColor(const char * payload) case 7: if(!strcmp_P(payload, PSTR("magenta"))) return haspLogColor(LV_COLOR_MAGENTA); + /* HEX format #rrggbb or #rrggbbaa */ int r, g, b, a; if(*payload == '#' && sscanf(payload + 1, "%2x%2x%2x%2x", &r, &g, &b, &a) == 4) { return haspLogColor(LV_COLOR_MAKE(r, g, b)); @@ -63,16 +82,13 @@ lv_color_t haspPayloadToColor(const char * payload) } default: // if(!strcmp_P(payload, PSTR("darkblue"))) return haspLogColor(LV_COLOR_MAKE(0, 51, 102)); - // if(!strcmp_P(payload, PSTR("lightblue"))) return haspLogColor(LV_COLOR_MAKE(46, 203, 203)); + // if(!strcmp_P(payload, PSTR("lightblue"))) return haspLogColor(LV_COLOR_MAKE(46, 203, + // 203)); break; } /* 16-bit RGB565 Color Scheme*/ - uint8_t digits = 0; - while((payload + digits) != '\0' && isdigit(*(payload + digits))) { - digits++; - } - if(strlen(payload) == digits) { + if(only_digits(payload)) { uint16_t c = atoi(payload); /* Initial colors */ uint8_t R5 = ((c >> 11) & 0b11111); @@ -90,34 +106,30 @@ lv_color_t haspPayloadToColor(const char * payload) return LV_COLOR_BLACK; } -static void haspAttributeNotFound(const char * attr) +static void hasp_process_label_long_mode(lv_obj_t * obj, const char * payload, bool update) { - Log.warning(F("HASP: Unknown property %s"), attr); -} - -void set_cpicker_value(lv_obj_t * obj, const char * payload) -{ - lv_color_t color = haspPayloadToColor(payload); - lv_cpicker_set_color(obj, color); -} - -void set_label_long_mode(lv_obj_t * obj, const char * payload) -{ - lv_label_long_mode_t mode; - if(!strcmp_P(payload, PSTR("expand"))) { - mode = LV_LABEL_LONG_EXPAND; - } else if(!strcmp_P(payload, PSTR("break"))) { - mode = LV_LABEL_LONG_BREAK; - } else if(!strcmp_P(payload, PSTR("dots"))) { - mode = LV_LABEL_LONG_DOT; - } else if(!strcmp_P(payload, PSTR("scroll"))) { - mode = LV_LABEL_LONG_SROLL; - } else if(!strcmp_P(payload, PSTR("loop"))) { - mode = LV_LABEL_LONG_SROLL_CIRC; + if(update) { + lv_label_long_mode_t mode = LV_LABEL_LONG_EXPAND; + if(!strcmp_P(payload, PSTR("expand"))) { + mode = LV_LABEL_LONG_EXPAND; + } else if(!strcmp_P(payload, PSTR("break"))) { + mode = LV_LABEL_LONG_BREAK; + } else if(!strcmp_P(payload, PSTR("dots"))) { + mode = LV_LABEL_LONG_DOT; + } else if(!strcmp_P(payload, PSTR("scroll"))) { + mode = LV_LABEL_LONG_SROLL; + } else if(!strcmp_P(payload, PSTR("loop"))) { + mode = LV_LABEL_LONG_SROLL_CIRC; + } else { + return Log.warning(F("Invalid long mode")); + } + lv_label_set_long_mode(obj, mode); + } else { + // Getter needed } - lv_label_set_long_mode(obj, mode); } +// OK lv_obj_t * FindButtonLabel(lv_obj_t * btn) { if(btn) { @@ -125,8 +137,9 @@ lv_obj_t * FindButtonLabel(lv_obj_t * btn) if(label) { lv_obj_type_t list; lv_obj_get_type(label, &list); + const char * objtype = list.type[0]; - if(check_obj_type(list.type[0], LV_HASP_LABEL)) { + if(check_obj_type(objtype, LV_HASP_LABEL)) { return label; } @@ -139,6 +152,7 @@ lv_obj_t * FindButtonLabel(lv_obj_t * btn) return NULL; } +// OK static inline void haspSetLabelText(lv_obj_t * obj, const char * value) { lv_obj_t * label = FindButtonLabel(obj); @@ -147,25 +161,39 @@ static inline void haspSetLabelText(lv_obj_t * obj, const char * value) } } -void haspSetOpacity(lv_obj_t * obj, uint8_t val) +// OK +static inline bool haspGetLabelText(lv_obj_t * obj, char * text) { -#if LVGL7 - // Needs LV_USE_OPA_SCALE - lv_obj_set_style_local_opa_scale(obj, LV_OBJ_PART_MAIN, LV_STATE_DEFAULT, val); -#else - lv_obj_set_opa_scale_enable(obj, val < 255); - lv_obj_set_opa_scale(obj, val < 255 ? val : 255); -#endif + if(!obj) { + Log.warning(F("HASP: Button not defined")); + return false; + } + + lv_obj_t * label = lv_obj_get_child_back(obj, NULL); + if(label) { + lv_obj_type_t list; + lv_obj_get_type(label, &list); + + if(check_obj_type(list.type[0], LV_HASP_LABEL)) { + text = lv_label_get_text(label); + return true; + } + + } else { + Log.warning(F("HASP: haspGetLabelText NULL Pointer encountered")); + } + + return false; } -void haspSetLocalStyle(lv_obj_t * obj, const char * attr_p, const char * payload) +static void hasp_local_style_attr(lv_obj_t * obj, const char * attr_p, const char * payload, bool update) { uint8_t part = LV_TABLE_PART_BG; uint8_t state = LV_STATE_DEFAULT; int16_t var = atoi(payload); int len = strlen(attr_p); - if(len > 0) { + if(len > 0 && len < 128) { // Check Trailing partnumber if(attr_p[len - 1] == '1') { part = LV_TABLE_PART_CELL1; @@ -188,37 +216,67 @@ void haspSetLocalStyle(lv_obj_t * obj, const char * attr_p, const char * payload attr[len] = 0; // debugPrintln(strAttr + "&" + part); + uint8_t t8 = 0; + + /* ***** WARNING **************************************************** + * when using hasp_out use attr_p for the original attribute name + * *************************************************************** */ if(!strcmp_P(attr, PSTR("radius"))) { - return lv_obj_set_style_local_radius(obj, part, state, (lv_style_int_t)var); + if(update) { + return lv_obj_set_style_local_radius(obj, part, state, (lv_style_int_t)var); + } else { + lv_obj_get_style_local_radius(obj, part, state, &var); + return hasp_out_int(obj, attr_p, var); + } + } else if(!strcmp_P(attr, PSTR("clip_corner"))) { - return lv_obj_set_style_local_clip_corner(obj, part, state, (bool)var); + if(update) { + return lv_obj_set_style_local_clip_corner(obj, part, state, (bool)var); + } else { + lv_obj_get_style_local_clip_corner(obj, part, state, &t8); + return hasp_out_int(obj, attr_p, t8); + } + } else if(!strcmp_P(attr, PSTR("size"))) { return lv_obj_set_style_local_size(obj, part, state, (lv_style_int_t)var); + } else if(!strcmp_P(attr, PSTR("transform_width"))) { return lv_obj_set_style_local_transform_width(obj, part, state, (lv_style_int_t)var); + } else if(!strcmp_P(attr, PSTR("transform_height"))) { return lv_obj_set_style_local_transform_height(obj, part, state, (lv_style_int_t)var); + } else if(!strcmp_P(attr, PSTR("opa_scale"))) { return lv_obj_set_style_local_opa_scale(obj, part, state, (lv_opa_t)var); + } else if(!strcmp_P(attr, PSTR("pad_top"))) { return lv_obj_set_style_local_pad_top(obj, part, state, (lv_style_int_t)var); + } else if(!strcmp_P(attr, PSTR("pad_bottom"))) { return lv_obj_set_style_local_pad_bottom(obj, part, state, (lv_style_int_t)var); + } else if(!strcmp_P(attr, PSTR("pad_left"))) { return lv_obj_set_style_local_pad_left(obj, part, state, (lv_style_int_t)var); + } else if(!strcmp_P(attr, PSTR("pad_right"))) { return lv_obj_set_style_local_pad_right(obj, part, state, (lv_style_int_t)var); + } else if(!strcmp_P(attr, PSTR("pad_inner"))) { return lv_obj_set_style_local_pad_inner(obj, part, state, (lv_style_int_t)var); + } else if(!strcmp_P(attr, PSTR("bg_blend_mode"))) { return lv_obj_set_style_local_bg_blend_mode(obj, part, state, (lv_blend_mode_t)var); + } else if(!strcmp_P(attr, PSTR("bg_main_stop"))) { return lv_obj_set_style_local_bg_main_stop(obj, part, state, (lv_style_int_t)var); + } else if(!strcmp_P(attr, PSTR("bg_grad_stop"))) { return lv_obj_set_style_local_bg_grad_stop(obj, part, state, (lv_style_int_t)var); + } else if(!strcmp_P(attr, PSTR("bg_grad_dir"))) { return lv_obj_set_style_local_bg_grad_dir(obj, part, state, (lv_grad_dir_t)var); + } else if(!strcmp_P(attr, PSTR("bg_color"))) { lv_color_t color = haspPayloadToColor(payload); if(part != 64) @@ -383,300 +441,376 @@ void haspSetLocalStyle(lv_obj_t * obj, const char * attr_p, const char * payload } } - /* Property not found */ - haspAttributeNotFound(attr_p); + Log.warning(F("HASP: Unknown property %s"), attr_p); } -void haspSetObjAttribute1(lv_obj_t * obj, const char * attr, const char * payload) +// OK +static void hasp_process_obj_attribute_txt(lv_obj_t * obj, const char * attr, const char * payload, bool update) +{ + /* Attributes depending on objecttype */ + lv_obj_type_t list; + lv_obj_get_type(obj, &list); + const char * objtype = list.type[0]; + + if(check_obj_type(objtype, LV_HASP_BUTTON)) { + if(update) { + haspSetLabelText(obj, payload); + } else { + char * text = NULL; + if(haspGetLabelText(obj, text)) hasp_out_str(obj, attr, text); + } + return; + } + if(check_obj_type(objtype, LV_HASP_LABEL)) { + return update ? lv_label_set_text(obj, payload) : hasp_out_str(obj, attr, lv_label_get_text(obj)); + } + if(check_obj_type(objtype, LV_HASP_CHECKBOX)) { + return update ? lv_checkbox_set_text(obj, payload) : hasp_out_str(obj, attr, lv_checkbox_get_text(obj)); + } + if(check_obj_type(objtype, LV_HASP_DDLIST)) { + char buffer[128]; + lv_dropdown_get_selected_str(obj, buffer, sizeof(buffer)); + return hasp_out_str(obj, attr, buffer); + } + if(check_obj_type(objtype, LV_HASP_ROLLER)) { + char buffer[128]; + lv_roller_get_selected_str(obj, buffer, sizeof(buffer)); + return hasp_out_str(obj, attr, buffer); + } +} + +static void hasp_process_obj_attribute_val(lv_obj_t * obj, const char * attr, const char * payload, bool update) +{ + int16_t intval = atoi(payload); + uint16_t val = atoi(payload); + + /* Attributes depending on objecttype */ + lv_obj_type_t list; + lv_obj_get_type(obj, &list); + const char * objtype = list.type[0]; + + if(check_obj_type(objtype, LV_HASP_BUTTON)) { + if(lv_btn_get_checkable(obj)) { + lv_btn_state_t state; + switch(val) { + case 0: + state = LV_BTN_STATE_RELEASED; + break; + case 1: + state = LV_BTN_STATE_CHECKED_RELEASED; + break; + default: + state = LV_BTN_STATE_DISABLED; + } + lv_btn_set_state(obj, state); + return; + } + } + if(check_obj_type(objtype, LV_HASP_CHECKBOX)) { + return update ? lv_checkbox_set_checked(obj, is_true(payload)) + : hasp_out_int(obj, attr, lv_checkbox_is_checked(obj)); + } + if(check_obj_type(objtype, LV_HASP_SWITCH)) { + if(update) { + return is_true(payload) ? lv_switch_off(obj, LV_ANIM_ON) : lv_switch_on(obj, LV_ANIM_ON); + } else { + return hasp_out_int(obj, attr, lv_switch_get_state(obj)); + } + } else if(check_obj_type(objtype, LV_HASP_DDLIST)) { + lv_dropdown_set_selected(obj, val); + return; + } else if(check_obj_type(objtype, LV_HASP_LMETER)) { + lv_linemeter_set_value(obj, intval); + return; + } else if(check_obj_type(objtype, LV_HASP_SLIDER)) { + lv_slider_set_value(obj, intval, LV_ANIM_ON); + return; + } else if(check_obj_type(objtype, LV_HASP_LED)) { + lv_led_set_bright(obj, (uint8_t)val); + return; + } else if(check_obj_type(objtype, LV_HASP_GAUGE)) { + lv_gauge_set_value(obj, 0, intval); + return; + } else if(check_obj_type(objtype, LV_HASP_ROLLER)) { + lv_roller_set_selected(obj, val, LV_ANIM_ON); + return; + } else if(check_obj_type(objtype, LV_HASP_BAR)) { + lv_bar_set_value(obj, intval, LV_ANIM_OFF); + return; + } else if(check_obj_type(objtype, LV_HASP_CPICKER)) { + return update ? (void)lv_cpicker_set_color(obj, haspPayloadToColor(payload)) + : hasp_out_color(obj, attr, lv_cpicker_get_color(obj)); + } +} + +// OK +static void hasp_process_obj_attribute_range(lv_obj_t * obj, const char * attr, const char * payload, bool update, + bool set_min, bool set_max) +{ + int16_t val = atoi(payload); + + /* Attributes depending on objecttype */ + lv_obj_type_t list; + lv_obj_get_type(obj, &list); + const char * objtype = list.type[0]; + + if(check_obj_type(objtype, LV_HASP_SLIDER)) { + int16_t min = lv_slider_get_min_value(obj); + int16_t max = lv_slider_get_max_value(obj); + return update ? lv_slider_set_range(obj, set_min ? val : min, set_max ? val : max) + : hasp_out_int(obj, attr, set_min ? lv_slider_get_min_value(obj) : lv_slider_get_max_value(obj)); + } + if(check_obj_type(objtype, LV_HASP_GAUGE)) { + int16_t min = lv_gauge_get_min_value(obj); + int16_t max = lv_gauge_get_max_value(obj); + return update ? lv_gauge_set_range(obj, set_min ? val : min, set_max ? val : max) + : hasp_out_int(obj, attr, set_min ? lv_gauge_get_min_value(obj) : lv_gauge_get_max_value(obj)); + } + if(check_obj_type(objtype, LV_HASP_BAR)) { + int16_t min = lv_bar_get_min_value(obj); + int16_t max = lv_bar_get_max_value(obj); + return update ? lv_bar_set_range(obj, set_min ? val : min, set_max ? val : max) + : hasp_out_int(obj, attr, set_min ? lv_bar_get_min_value(obj) : lv_bar_get_max_value(obj)); + } + if(check_obj_type(objtype, LV_HASP_LMETER)) { + int16_t min = lv_linemeter_get_min_value(obj); + int16_t max = lv_linemeter_get_max_value(obj); + return update ? lv_linemeter_set_range(obj, set_min ? val : min, set_max ? val : max) + : hasp_out_int(obj, attr, + set_min ? lv_linemeter_get_min_value(obj) : lv_linemeter_get_max_value(obj)); + } +} + +// OK +static void hasp_process_obj_attribute1(lv_obj_t * obj, const char * attr, const char * payload, bool update) { int16_t val = atoi(payload); if(!strcmp_P(attr, PSTR("x"))) { - lv_obj_set_x(obj, val); - return; - } else if(!strcmp_P(attr, PSTR("y"))) { - lv_obj_set_y(obj, val); - return; - } else if(!strcmp_P(attr, PSTR("w"))) { - lv_obj_set_width(obj, val); - return; - } else if(!strcmp_P(attr, PSTR("h"))) { - lv_obj_set_height(obj, val); - return; + return update ? lv_obj_set_x(obj, val) : hasp_out_int(obj, attr, lv_obj_get_x(obj)); } - haspSetLocalStyle(obj, attr, payload); + if(!strcmp_P(attr, PSTR("y"))) { + return update ? lv_obj_set_y(obj, val) : hasp_out_int(obj, attr, lv_obj_get_y(obj)); + } + if(!strcmp_P(attr, PSTR("w"))) { + return update ? lv_obj_set_width(obj, val) : hasp_out_int(obj, attr, lv_obj_get_width(obj)); + } + if(!strcmp_P(attr, PSTR("h"))) { + return update ? lv_obj_set_height(obj, val) : hasp_out_int(obj, attr, lv_obj_get_height(obj)); + } + + hasp_local_style_attr(obj, attr, payload, update); } -void haspSetObjAttribute3(lv_obj_t * obj, const char * attr, const char * payload) +// OK +static void hasp_process_obj_attribute3(lv_obj_t * obj, const char * attr, const char * payload, bool update) { int16_t val = atoi(payload); if(!strcmp_P(attr, PSTR("vis"))) { - lv_obj_set_hidden(obj, val == 0); - return; - } else { - /* .txt and .val depend on objecttype */ - lv_obj_type_t list; - lv_obj_get_type(obj, &list); - - if(!strcmp_P(attr, PSTR("txt"))) { // In order of likelihood to occur - if(check_obj_type(list.type[0], LV_HASP_BUTTON)) { - haspSetLabelText(obj, payload); - return; - } else if(check_obj_type(list.type[0], LV_HASP_LABEL)) { - lv_label_set_text(obj, payload); - return; - } else if(check_obj_type(list.type[0], LV_HASP_CHECKBOX)) { -#if LVGL7 - lv_checkbox_set_text(obj, payload); -#else - lv_cb_set_text(obj, payload); -#endif - return; - } - } - - if(!strcmp_P(attr, PSTR("val"))) { // In order of likelihood to occur - int16_t intval = atoi(payload); - -#if LVGL7 - if(check_obj_type(list.type[0], LV_HASP_BUTTON)) { - if(lv_btn_get_checkable(obj)) { - lv_btn_state_t state; - switch(val) { - case 0: - state = LV_BTN_STATE_RELEASED; - break; - case 1: - state = LV_BTN_STATE_CHECKED_RELEASED; - break; - default: - state = LV_BTN_STATE_DISABLED; - } - lv_btn_set_state(obj, state); - return; - } - } else if(check_obj_type(list.type[0], LV_HASP_CHECKBOX)) { - lv_checkbox_set_checked(obj, val != 0); - return; - } else if(check_obj_type(list.type[0], LV_HASP_SWITCH)) { - val == 0 ? lv_switch_off(obj, LV_ANIM_ON) : lv_switch_on(obj, LV_ANIM_ON); - return; - } else if(check_obj_type(list.type[0], LV_HASP_DDLIST)) { - lv_dropdown_set_selected(obj, val); - return; - } else if(check_obj_type(list.type[0], LV_HASP_LMETER)) { - lv_linemeter_set_value(obj, intval); - return; -#else - if(check_obj_type(list.type[0], LV_HASP_BUTTON)) { - if(lv_btn_get_toggle(obj)) { - lv_btn_set_state(obj, val == 0 ? LV_BTN_STATE_REL : LV_BTN_STATE_TGL_REL); - return; - } - } else if(check_obj_type(list.type[0], LV_HASP_CHECKBOX)) { - lv_cb_set_checked(obj, val != 0); - return; - } else if(check_obj_type(list.type[0], LV_HASP_SWITCH)) { - val == 0 ? lv_sw_off(obj, LV_ANIM_ON) : lv_sw_on(obj, LV_ANIM_ON); - return; - } else if(check_obj_type(list.type[0], LV_HASP_DDLIST)) { - lv_ddlist_set_selected(obj, val); - return; - } else if(check_obj_type(list.type[0], LV_HASP_LMETER)) { - lv_lmeter_set_value(obj, intval); - return; -#endif - - } else if(check_obj_type(list.type[0], LV_HASP_SLIDER)) { - lv_slider_set_value(obj, intval, LV_ANIM_ON); - return; - } else if(check_obj_type(list.type[0], LV_HASP_LED)) { - lv_led_set_bright(obj, (uint8_t)val); - return; - } else if(check_obj_type(list.type[0], LV_HASP_GAUGE)) { - lv_gauge_set_value(obj, 0, intval); - return; - } else if(check_obj_type(list.type[0], LV_HASP_ROLLER)) { - lv_roller_set_selected(obj, val, LV_ANIM_ON); - return; - } else if(check_obj_type(list.type[0], LV_HASP_BAR)) { - lv_bar_set_value(obj, intval, LV_ANIM_OFF); - return; - } else if(check_obj_type(list.type[0], LV_HASP_CPICKER)) { - set_cpicker_value(obj, payload); - return; - } - } - - if(!strcmp_P(attr, PSTR("min"))) { // In order of likelihood to occur - int16_t min = atoi(payload); - if(check_obj_type(list.type[0], LV_HASP_SLIDER)) { - int16_t max = lv_slider_get_max_value(obj); - lv_slider_set_range(obj, min, max); - return; - } else if(check_obj_type(list.type[0], LV_HASP_GAUGE)) { - int16_t max = lv_gauge_get_max_value(obj); - lv_gauge_set_range(obj, min, max); - return; - } else if(check_obj_type(list.type[0], LV_HASP_BAR)) { - int16_t max = lv_bar_get_max_value(obj); - lv_bar_set_range(obj, min, max); - return; - } else if(check_obj_type(list.type[0], LV_HASP_LMETER)) { - int16_t max = lv_linemeter_get_max_value(obj); - lv_linemeter_set_range(obj, min, max); - return; - } - } - - if(!strcmp_P(attr, PSTR("max"))) { // In order of likelihood to occur - int16_t max = atoi(payload); - if(check_obj_type(list.type[0], LV_HASP_SLIDER)) { - int16_t min = lv_slider_get_max_value(obj); - lv_slider_set_range(obj, min, max); - return; - } else if(check_obj_type(list.type[0], LV_HASP_GAUGE)) { - int16_t min = lv_gauge_get_max_value(obj); - lv_gauge_set_range(obj, min, max); - return; - } else if(check_obj_type(list.type[0], LV_HASP_BAR)) { - int16_t min = lv_bar_get_max_value(obj); - lv_bar_set_range(obj, min, max); - return; - } else if(check_obj_type(list.type[0], LV_HASP_LMETER)) { - int16_t min = lv_linemeter_get_max_value(obj); - lv_linemeter_set_range(obj, min, max); - return; - } - } + return update ? lv_obj_set_hidden(obj, !is_true(payload)) : hasp_out_int(obj, attr, !lv_obj_get_hidden(obj)); } - haspSetLocalStyle(obj, attr, payload); + if(!strcmp_P(attr, PSTR("txt"))) { // In order of likelihood to occur + return hasp_process_obj_attribute_txt(obj, attr, payload, update); + } + if(!strcmp_P(attr, PSTR("val"))) { // In order of likelihood to occur + return hasp_process_obj_attribute_val(obj, attr, payload, update); + } + if(!strcmp_P(attr, PSTR("min"))) { // In order of likelihood to occur + return hasp_process_obj_attribute_range(obj, attr, payload, update, true, false); + } + if(!strcmp_P(attr, PSTR("max"))) { // In order of likelihood to occur + return hasp_process_obj_attribute_range(obj, attr, payload, update, false, true); + } + + hasp_local_style_attr(obj, attr, payload, update); } -void haspSetObjAttribute4(lv_obj_t * obj, const char * attr, const char * payload) +static void hasp_process_obj_attribute4(lv_obj_t * obj, const char * attr, const char * payload, bool update) { int16_t val = atoi(payload); if(!strcmp_P(attr, PSTR("rows"))) { lv_obj_type_t list; lv_obj_get_type(obj, &list); + const char * objtype = list.type[0]; - if(check_obj_type(list.type[0], LV_HASP_ROLLER)) { - lv_roller_set_visible_row_count(obj, (uint8_t)val); - return; - } - } else { - lv_obj_type_t list; - lv_obj_get_type(obj, &list); - - if(!strcmp_P(attr, PSTR("rect"))) { - if(check_obj_type(list.type[0], LV_HASP_CPICKER)) { - lv_cpicker_set_type(obj, is_true(payload) ? LV_CPICKER_TYPE_RECT : LV_CPICKER_TYPE_DISC); - return; - } - } - - if(!strcmp_P(attr, PSTR("mode"))) { - if(check_obj_type(list.type[0], LV_HASP_BUTTON)) { - lv_obj_t * label = FindButtonLabel(obj); - if(label) { - set_label_long_mode(label, payload); - lv_obj_set_width(label, lv_obj_get_width(obj)); - } - return; - } - - if(check_obj_type(list.type[0], LV_HASP_LABEL)) { - set_label_long_mode(obj, payload); - return; - } + if(check_obj_type(objtype, LV_HASP_ROLLER)) { + return update ? lv_roller_set_visible_row_count(obj, (uint8_t)val) + : hasp_out_int(obj, attr, lv_roller_get_visible_row_count(obj)); } } - haspSetLocalStyle(obj, attr, payload); + /* Attributes depending on objecttype */ + lv_obj_type_t list; + lv_obj_get_type(obj, &list); + const char * objtype = list.type[0]; + + if(!strcmp_P(attr, PSTR("rect"))) { + if(check_obj_type(objtype, LV_HASP_CPICKER)) { + lv_cpicker_set_type(obj, is_true(payload) ? LV_CPICKER_TYPE_RECT : LV_CPICKER_TYPE_DISC); + return; + } + } + + if(!strcmp_P(attr, PSTR("mode"))) { + if(check_obj_type(objtype, LV_HASP_BUTTON)) { + lv_obj_t * label = FindButtonLabel(obj); + if(label) { + hasp_process_label_long_mode(label, payload, update); + lv_obj_set_width(label, lv_obj_get_width(obj)); + } + return; + } + + if(check_obj_type(objtype, LV_HASP_LABEL)) { + hasp_process_label_long_mode(obj, payload, update); + return; + } + } + + hasp_local_style_attr(obj, attr, payload, update); } -void haspSetObjAttribute6(lv_obj_t * obj, const char * attr, const char * payload) +// OK +static void hasp_process_obj_attribute6(lv_obj_t * obj, const char * attr, const char * payload, bool update) { int16_t val = atoi(payload); if(!strcmp_P(attr, PSTR("hidden"))) { - lv_obj_set_hidden(obj, is_true(payload)); - return; - } else { - lv_obj_type_t list; - lv_obj_get_type(obj, &list); + return update ? lv_obj_set_hidden(obj, is_true(payload)) : hasp_out_int(obj, attr, lv_obj_get_hidden(obj)); + } - if(!strcmp_P(attr, PSTR("toggle"))) { - if(check_obj_type(list.type[0], LV_HASP_BUTTON)) { - haspSetToggle(obj, is_true(payload)); - return; + /* Attributes depending on objecttype */ + lv_obj_type_t list; + lv_obj_get_type(obj, &list); + const char * objtype = list.type[0]; + + if(!strcmp_P(attr, PSTR("toggle"))) { + if(check_obj_type(objtype, LV_HASP_BUTTON)) { + if(update) { + bool toggle = is_true(payload); + lv_btn_set_checkable(obj, toggle); + lv_obj_set_event_cb(obj, toggle ? toggle_event_handler : btn_event_handler); + } else { + hasp_out_int(obj, attr, lv_btn_get_checkable(obj)); } } } - haspSetLocalStyle(obj, attr, payload); + + hasp_local_style_attr(obj, attr, payload, update); } -void haspSetObjAttribute7(lv_obj_t * obj, const char * attr, const char * payload) +// OK +static void hasp_process_obj_attribute7(lv_obj_t * obj, const char * attr, const char * payload, bool update) { int16_t val = atoi(payload); if(!strcmp_P(attr, PSTR("opacity"))) { - haspSetOpacity(obj, val); - return; + return update ? lv_obj_set_style_local_opa_scale(obj, LV_OBJ_PART_MAIN, LV_STATE_DEFAULT, val) + : hasp_out_int(obj, attr, lv_obj_get_style_opa_scale(obj, LV_OBJ_PART_MAIN)); + } else if(!strcmp_P(attr, PSTR("enabled"))) { - lv_obj_set_click(obj, is_true(payload)); - return; + return update ? lv_obj_set_click(obj, is_true(payload)) : hasp_out_int(obj, attr, lv_obj_get_click(obj)); + } else if(!strcmp_P(attr, PSTR("options"))) { - /* .options depend on objecttype */ + /* Attributes depending on objecttype */ lv_obj_type_t list; lv_obj_get_type(obj, &list); + const char * objtype = list.type[0]; - if(check_obj_type(list.type[0], LV_HASP_DDLIST)) { -#if LVGL7 - lv_dropdown_set_options(obj, payload); -#else - lv_ddlist_set_options(obj, payload); -#endif + if(check_obj_type(objtype, LV_HASP_DDLIST)) { + if(update) { + lv_dropdown_set_options(obj, payload); + } else { + hasp_out_str(obj, attr, lv_dropdown_get_options(obj)); + } return; - } else if(check_obj_type(list.type[0], LV_HASP_ROLLER)) { - lv_roller_ext_t * ext = (lv_roller_ext_t *)lv_obj_get_ext_attr(obj); - lv_roller_set_options(obj, payload, ext->mode); + + } else if(check_obj_type(objtype, LV_HASP_ROLLER)) { + if(update) { + lv_roller_ext_t * ext = (lv_roller_ext_t *)lv_obj_get_ext_attr(obj); + lv_roller_set_options(obj, payload, ext->mode); + } else { + hasp_out_str(obj, attr, lv_roller_get_options(obj)); + } return; } } - haspSetLocalStyle(obj, attr, payload); + + hasp_local_style_attr(obj, attr, payload, update); } -void hasp_set_obj_attribute(lv_obj_t * obj, const char * attr_p, const char * payload) +// OK +// @param update bool: change the value if true, dispatch value if false +void hasp_process_obj_attribute(lv_obj_t * obj, const char * attr_p, const char * payload, bool update) { - if(!obj) { - Log.warning(F("HASP: Unknown object")); - return; - } + if(!obj) return Log.warning(F("HASP: Unknown object")); - // strip starting '.' char * attr = (char *)attr_p; - if(*attr == '.') attr++; + if(*attr == '.') attr++; // strip leading '.' switch(strlen(attr)) { case 1: - haspSetObjAttribute1(obj, attr, payload); + hasp_process_obj_attribute1(obj, attr, payload, update); break; case 4: - haspSetObjAttribute4(obj, attr, payload); + hasp_process_obj_attribute4(obj, attr, payload, update); break; case 3: - haspSetObjAttribute3(obj, attr, payload); + hasp_process_obj_attribute3(obj, attr, payload, update); break; case 6: - haspSetObjAttribute6(obj, attr, payload); + hasp_process_obj_attribute6(obj, attr, payload, update); break; case 7: - haspSetObjAttribute7(obj, attr, payload); + hasp_process_obj_attribute7(obj, attr, payload, update); break; default: - haspSetLocalStyle(obj, attr, payload); + hasp_local_style_attr(obj, attr, payload, update); // all other lengths } -} \ No newline at end of file +} + +/* ************************** + * Static Inline functions + * **************************/ +static inline bool is_true(const char * s) +{ + return (!strcmp_P(s, PSTR("true")) || !strcmp_P(s, PSTR("TRUE")) || !strcmp_P(s, PSTR("1")) || + !strcmp_P(s, PSTR("on")) || !strcmp_P(s, PSTR("ON")) || !strcmp_P(s, PSTR("On")) || + !strcmp_P(s, PSTR("yes")) || !strcmp_P(s, PSTR("YES")) || !strcmp_P(s, PSTR("Yes"))); +} + +static inline bool only_digits(const char * s) +{ + size_t digits = 0; + while((s + digits) != '\0' && isdigit(*(s + digits))) { + digits++; + } + return strlen(s) == digits; +} + +static inline void hasp_out_int(lv_obj_t * obj, const char * attr, uint32_t val) +{ + return hasp_send_attribute(obj, attr, val); +} + +static inline void hasp_out_str(lv_obj_t * obj, const char * attr, const char * data) +{ + return hasp_send_attribute_str(obj, attr, data); +} + +static inline void hasp_out_color(lv_obj_t * obj, const char * attr, lv_color_t color) +{ + lv_color32_t c32; + c32.full = lv_color_to32(color); + + DynamicJsonDocument doc(128); + doc[F("r")] = c32.ch.red; + doc[F("g")] = c32.ch.green; + doc[F("b")] = c32.ch.blue; + + char buffer[128]; + serializeJson(doc, buffer, sizeof(buffer)); + hasp_send_attribute_str(obj, attr, buffer); +} diff --git a/src/hasp_attr_set.h b/src/hasp_attribute.h similarity index 50% rename from src/hasp_attr_set.h rename to src/hasp_attribute.h index 20ed2921..6af6e0e5 100644 --- a/src/hasp_attr_set.h +++ b/src/hasp_attribute.h @@ -1,15 +1,13 @@ #ifndef HASP_ATTR_SET_H #define HASP_ATTR_SET_H -#include "Arduino.h" #include "lvgl.h" #ifdef __cplusplus extern "C" { #endif -void hasp_set_obj_attribute(lv_obj_t * obj, const char * attr_p, const char * payload); -void haspSetOpacity(lv_obj_t * obj, uint8_t val); +void hasp_process_obj_attribute(lv_obj_t * obj, const char * attr_p, const char * payload, bool update); #ifdef __cplusplus } /* extern "C" */ diff --git a/src/hasp_mqtt.cpp b/src/hasp_mqtt.cpp index d33bfb5e..b03a6299 100644 --- a/src/hasp_mqtt.cpp +++ b/src/hasp_mqtt.cpp @@ -149,7 +149,7 @@ void IRAM_ATTR mqtt_send_input(uint8_t id, const char * payload) Log.notice(F("MQTT OUT: %sstate/input%u = %s"), mqttNodeTopic, id, payload); } -void IRAM_ATTR mqtt_send_attribute(uint8_t pageid, uint8_t btnid, const char * attribute, const char * data) +void IRAM_ATTR mqtt_send_obj_attribute_str(uint8_t pageid, uint8_t btnid, const char * attribute, const char * data) { if(mqttIsConnected()) { char topic[64]; @@ -169,30 +169,31 @@ void IRAM_ATTR mqtt_send_attribute(uint8_t pageid, uint8_t btnid, const char * a data); } -void mqtt_send_attribute(uint8_t pageid, uint8_t btnid, const __FlashStringHelper * attr, const char * data) +/*void IRAM_ATTR mqtt_send_attribute_P(uint8_t pageid, uint8_t btnid, const char * attr, const char * data) { - String strAttr((char *)0); - strAttr.reserve(64); - strAttr = attr; - mqtt_send_attribute(pageid, btnid, strAttr.c_str(), data); + char * buffer; + buffer = (char *)malloc(strlen_P(attr) + 1); + strcpy_P(buffer, attr); + mqtt_send_attribute_str(pageid, btnid, buffer, data); + free(buffer); } -void IRAM_ATTR mqtt_send_txt_attribute(uint8_t pageid, uint8_t btnid, const char * txt) +void IRAM_ATTR mqtt_send_attribute_txt(uint8_t pageid, uint8_t btnid, const char * txt) { - mqtt_send_attribute(pageid, btnid, F("txt"), txt); + mqtt_send_attribute_P(pageid, btnid, PSTR("txt"), txt); } -void IRAM_ATTR mqtt_send_val_attribute(uint8_t pageid, uint8_t btnid, int32_t val) +void IRAM_ATTR mqtt_send_attribute_val(uint8_t pageid, uint8_t btnid, int32_t val) { char data[64]; itoa(val, data, 10); - mqtt_send_attribute(pageid, btnid, F("val"), data); + mqtt_send_attribute_P(pageid, btnid, PSTR("val"), data); } -void IRAM_ATTR mqtt_send_event_attribute(uint8_t pageid, uint8_t btnid, const char * event) +void IRAM_ATTR mqtt_send_attribute_event(uint8_t pageid, uint8_t btnid, const char * event) { - mqtt_send_attribute(pageid, btnid, F("event"), event); -} + mqtt_send_attribute_P(pageid, btnid, PSTR("event"), event); +}*/ void mqtt_send_statusupdate() { // Periodically publish a JSON string indicating system status @@ -287,7 +288,7 @@ static void mqtt_message_cb(char * topic_p, byte * payload, unsigned int length) Log.error(F("MQTT: Message received with invalid topic")); return; } - Log.trace(F("MQTT IN: short topic: %s"), topic); + // Log.trace(F("MQTT IN: short topic: %s"), topic); if(!strcmp_P(topic, PSTR("command"))) { dispatchCommand((char *)payload); @@ -296,7 +297,7 @@ static void mqtt_message_cb(char * topic_p, byte * payload, unsigned int length) if(topic == strstr_P(topic, PSTR("command/"))) { // startsWith command/ topic += 8u; - Log.trace(F("MQTT IN: command subtopic: %s"), topic); + // Log.trace(F("MQTT IN: command subtopic: %s"), topic); if(!strcmp_P(topic, PSTR("json"))) { // '[...]/device/command/json' -m '["dim=5", "page 1"]' = // nextionSendCmd("dim=50"), nextionSendCmd("page 1") diff --git a/src/hasp_mqtt.h b/src/hasp_mqtt.h index c2bc2fa2..344dc75d 100644 --- a/src/hasp_mqtt.h +++ b/src/hasp_mqtt.h @@ -13,10 +13,10 @@ void IRAM_ATTR mqtt_send_state(const __FlashStringHelper * subtopic, const char void IRAM_ATTR mqtt_send_input(uint8_t id, const char * payload); // attributes -void IRAM_ATTR mqtt_send_attribute(uint8_t pageid, uint8_t btnid, const char * attribute, const char * data); -void IRAM_ATTR mqtt_send_event_attribute(uint8_t pageid, uint8_t btnid, const char * event); -void IRAM_ATTR mqtt_send_val_attribute(uint8_t pageid, uint8_t btnid, int32_t val); -void IRAM_ATTR mqtt_send_txt_attribute(uint8_t pageid, uint8_t btnid, const char * txt); +void IRAM_ATTR mqtt_send_obj_attribute_str(uint8_t pageid, uint8_t btnid, const char * attribute, const char * data); +/*void IRAM_ATTR mqtt_send_attribute_txt(uint8_t pageid, uint8_t btnid, const char * txt); +void IRAM_ATTR mqtt_send_attribute_val(uint8_t pageid, uint8_t btnid, int32_t val); +void IRAM_ATTR mqtt_send_attribute_event(uint8_t pageid, uint8_t btnid, const char * event);*/ void mqtt_send_statusupdate(void); bool IRAM_ATTR mqttIsConnected(void);