diff --git a/src/hasp.cpp b/src/hasp.cpp index 718698d0..481e06af 100644 --- a/src/hasp.cpp +++ b/src/hasp.cpp @@ -173,7 +173,7 @@ void hasp_send_obj_attribute_str(lv_obj_t * obj, const char * attribute, const c uint8_t objid; if(FindIdFromObj(obj, &pageid, &objid)) { - dispatch_obj_attribute_str(pageid, objid, attribute, data); + dispatch_send_obj_attribute_str(pageid, objid, attribute, data); } } @@ -301,25 +301,47 @@ void haspReconnect() lv_obj_set_hidden(obj, true);*/ } -void haspProgress(uint8_t val, char * msg) +String progress_str((char *)0); + +void haspProgressVal(uint8_t val) { lv_obj_t * layer = lv_disp_get_layer_sys(NULL); lv_obj_t * bar = hasp_find_obj_from_id(255, 10); - - if(val == 255) { - lv_obj_set_style_local_bg_opa(layer, LV_OBJ_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_0); - if(bar) { - lv_obj_set_hidden(bar, true); - } - } else { - lv_obj_set_style_local_bg_opa(layer, LV_OBJ_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_100); - if(bar) { - lv_obj_set_hidden(bar, false); + if(layer && bar) { + if(val == 255) { + if(!lv_obj_get_hidden(bar)) { + lv_obj_set_hidden(bar, true); + lv_obj_set_style_local_bg_opa(layer, LV_OBJ_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_0); + lv_obj_set_style_local_value_str(bar, LV_OBJ_PART_MAIN, LV_STATE_DEFAULT, ""); +#if defined(ARCH_ARDUINO_ESP32) || defined(ARCH_ARDUINO_ESP8266) + progress_str.clear(); +#endif + } + } else { + if(lv_obj_get_hidden(bar)) { + lv_obj_set_hidden(bar, false); + lv_obj_set_style_local_bg_opa(layer, LV_OBJ_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_100); + } lv_bar_set_value(bar, val, LV_ANIM_OFF); - lv_obj_set_style_local_value_str(bar, LV_OBJ_PART_MAIN, LV_STATE_DEFAULT, msg); } + lv_task_handler(); /* let the GUI do its work */ } - lv_tick_inc(30); +} + +void haspProgressMsg(const char * msg) +{ + lv_obj_t * bar = hasp_find_obj_from_id(255, 10); + if(bar) { + progress_str.reserve(64); + progress_str = msg; + lv_obj_set_style_local_value_str(bar, LV_OBJ_PART_MAIN, LV_STATE_DEFAULT, progress_str.c_str()); + lv_task_handler(); /* let the GUI do its work */ + } +} + +void haspProgressMsg(const __FlashStringHelper * msg) +{ + haspProgressMsg(String(msg).c_str()); } /** @@ -546,27 +568,34 @@ void hasp_background(uint16_t pageid, uint16_t imageid) */ void IRAM_ATTR btn_event_handler(lv_obj_t * obj, lv_event_t event) { + uint8_t eventid; char buffer[64]; snprintf(buffer, sizeof(buffer), PSTR("HASP: ")); switch(event) { case LV_EVENT_PRESSED: + eventid = HASP_EVENT_DOWN; memcpy_P(buffer, PSTR("DOWN"), sizeof(buffer)); break; case LV_EVENT_CLICKED: // UP = the same object was release then was pressed and press was not lost! + eventid = HASP_EVENT_UP; memcpy_P(buffer, PSTR("UP"), sizeof(buffer)); break; case LV_EVENT_SHORT_CLICKED: + eventid = HASP_EVENT_SHORT; memcpy_P(buffer, PSTR("SHORT"), sizeof(buffer)); break; case LV_EVENT_LONG_PRESSED: + eventid = HASP_EVENT_LONG; memcpy_P(buffer, PSTR("LONG"), sizeof(buffer)); break; case LV_EVENT_LONG_PRESSED_REPEAT: + eventid = HASP_EVENT_HOLD; memcpy_P(buffer, PSTR("HOLD"), sizeof(buffer)); break; case LV_EVENT_PRESS_LOST: + eventid = HASP_EVENT_LOST; memcpy_P(buffer, PSTR("LOST"), sizeof(buffer)); break; case LV_EVENT_PRESSING: @@ -585,7 +614,7 @@ void IRAM_ATTR btn_event_handler(lv_obj_t * obj, lv_event_t event) Log.notice(buffer, event); return; default: - strcat_P(buffer, PSTR("HASP : Unknown Event % d occured")); + strcat_P(buffer, PSTR("HASP : Unknown Event occured")); Log.warning(buffer, event); return; } @@ -595,7 +624,8 @@ void IRAM_ATTR btn_event_handler(lv_obj_t * obj, lv_event_t event) mqtt_send_state(F("wakeuptouch"), buffer); #endif } else { - hasp_send_obj_attribute_event(obj, buffer); + // hasp_send_obj_attribute_event(obj, buffer); + dispatch_send_object_event(current_page, (uint8_t)obj->user_data, eventid); } } @@ -697,6 +727,20 @@ void haspSetPage(uint8_t pageid) } } +void hasp_set_group_objects(uint8_t groupid, uint8_t eventid, lv_obj_t * src_obj) +{ + bool state = dispatch_get_event_state(eventid); + for(uint8_t page = 0; page < HASP_NUM_PAGES; page++) { + uint8_t startid = 100 + groupid * 10; // groups start at id 100 + for(uint8_t objid = startid; objid < (startid + 10); objid++) { + lv_obj_t * obj = hasp_find_obj_from_id(page, objid); + if(obj && obj != src_obj) { // skip source object, if set + lv_obj_set_state(obj, state ? LV_STATE_PRESSED | LV_STATE_CHECKED : LV_STATE_DEFAULT); + } + } + } +} + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void haspNewObject(const JsonObject & config, uint8_t & saved_page_id) diff --git a/src/hasp.h b/src/hasp.h index 6d2eb8e8..c1ade3f8 100644 --- a/src/hasp.h +++ b/src/hasp.h @@ -19,7 +19,7 @@ extern "C" { * INCLUDES *********************/ -#if HASP_USE_APP>0 +#if HASP_USE_APP > 0 /********************* * DEFINES @@ -29,6 +29,19 @@ extern "C" { * TYPEDEFS **********************/ +enum hasp_event_t { // even = released, odd = pressed + HASP_EVENT_OFF = 0, + HASP_EVENT_ON = 1, + HASP_EVENT_UP = 2, + HASP_EVENT_DOWN = 3, + + HASP_EVENT_SHORT = 4, + HASP_EVENT_LONG = 5, + HASP_EVENT_LOST = 6, + HASP_EVENT_HOLD = 7, + HASP_EVENT_DOUBLE = 8 +}; + enum lv_hasp_obj_type_t { LV_HASP_BUTTON = 10, LV_HASP_CHECKBOX = 11, @@ -51,12 +64,12 @@ enum lv_hasp_obj_type_t { LV_HASP_IMAGE = 60, - LV_HASP_TABVIEW = 70, + LV_HASP_TABVIEW = 70, LV_HASP_TILEVIEW = 71, LV_HASP_CONTAINER = 90, - LV_HASP_OBJECT = 91, - LV_HASP_PAGE = 92, + LV_HASP_OBJECT = 91, + LV_HASP_PAGE = 92, }; /********************** @@ -80,13 +93,14 @@ void hasp_send_obj_attribute_str(lv_obj_t * obj, const char * attribute, const c void hasp_send_obj_attribute_int(lv_obj_t * obj, const char * attribute, int32_t val); void hasp_send_obj_attribute_color(lv_obj_t * obj, const char * attribute, lv_color_t color); void hasp_process_attribute(uint8_t pageid, uint8_t objid, const char * attr, const char * payload); +void hasp_set_group_objects(uint8_t groupid, uint8_t eventid, lv_obj_t * src_obj); void haspNewObject(const JsonObject & config, uint8_t & saved_page_id); void haspReconnect(void); void haspDisconnect(void); void haspWakeUp(void); -void haspProgress(uint8_t val, char * msg); +void haspProgressVal(uint8_t val); bool haspGetConfig(const JsonObject & settings); bool haspSetConfig(const JsonObject & settings); @@ -106,4 +120,7 @@ void IRAM_ATTR toggle_event_handler(lv_obj_t * obj, lv_event_t event); } /* extern "C" */ #endif +void haspProgressMsg(const char * msg); +void haspProgressMsg(const __FlashStringHelper * msg); + #endif /*HASP_H*/ diff --git a/src/hasp_gpio.cpp b/src/hasp_gpio.cpp index e9f01ae6..f6c8afd6 100644 --- a/src/hasp_gpio.cpp +++ b/src/hasp_gpio.cpp @@ -7,28 +7,22 @@ #include "hasp_conf.h" #include "hasp_gpio.h" #include "hasp_dispatch.h" - -#define HASP_NUM_GPIO_CONFIG 5 +#include "hasp.h" uint8_t gpioUsedInputCount = 0; -uint16_t gpioConfig[HASP_NUM_GPIO_CONFIG]; using namespace ace_button; static AceButton * button[HASP_NUM_INPUTS]; struct hasp_gpio_config_t { - const uint8_t pin; - const uint8_t group; - const uint8_t io_mode; - bool default_state; + uint8_t pin; // pin number + uint8_t group; // groupid + uint8_t type; // switch, button, ... + uint8_t gpio_function; // INPUT, OUTPUT, PULLUP, etc }; -// An array of button pins, led pins, and the led states. Cannot be const -// because ledState is mutable. -hasp_gpio_config_t gpioConfig2[HASP_NUM_GPIO_CONFIG] = { - {2, 8, INPUT, LOW}, {3, 9, OUTPUT, LOW}, {4, 10, INPUT, HIGH}, {5, 11, OUTPUT, LOW}, {6, 12, INPUT, LOW}, -}; +hasp_gpio_config_t gpioConfig[HASP_NUM_GPIO_CONFIG]; #if defined(ARDUINO_ARCH_ESP32) class TouchConfig : public ButtonConfig { @@ -53,39 +47,48 @@ class TouchConfig : public ButtonConfig { TouchConfig touchConfig(); #endif -static void gpio_event_cb(AceButton * button, uint8_t eventType, uint8_t buttonState) +static void gpio_event_handler(AceButton * button, uint8_t eventType, uint8_t buttonState) { + uint8_t eventid; char buffer[16]; switch(eventType) { - case 0: // AceButton::kEventPressed: + case AceButton::kEventPressed: + eventid = HASP_EVENT_DOWN; memcpy_P(buffer, PSTR("DOWN"), sizeof(buffer)); break; case 2: // AceButton::kEventClicked: + eventid = HASP_EVENT_SHORT; memcpy_P(buffer, PSTR("SHORT"), sizeof(buffer)); break; case AceButton::kEventDoubleClicked: + eventid = HASP_EVENT_DOUBLE; memcpy_P(buffer, PSTR("DOUBLE"), sizeof(buffer)); break; - case 4: // AceButton::kEventLongPressed: + case AceButton::kEventLongPressed: + eventid = HASP_EVENT_LONG; memcpy_P(buffer, PSTR("LONG"), sizeof(buffer)); break; - case 5: // AceButton::kEventRepeatPressed: + case AceButton::kEventRepeatPressed: // return; // Fix needed for switches + eventid = HASP_EVENT_HOLD; memcpy_P(buffer, PSTR("HOLD"), sizeof(buffer)); break; - case 1: // AceButton::kEventReleased: + case AceButton::kEventReleased: + eventid = HASP_EVENT_UP; memcpy_P(buffer, PSTR("UP"), sizeof(buffer)); break; default: + eventid = HASP_EVENT_LOST; memcpy_P(buffer, PSTR("UNKNOWN"), sizeof(buffer)); } dispatch_button(button->getId(), buffer); + dispatch_send_group_event(gpioConfig[button->getId()].group, eventid, true); } void aceButtonSetup(void) { ButtonConfig * buttonConfig = ButtonConfig::getSystemButtonConfig(); - buttonConfig->setEventHandler(gpio_event_cb); + buttonConfig->setEventHandler(gpio_event_handler); // Features buttonConfig->setFeature(ButtonConfig::kFeatureClick); @@ -110,21 +113,20 @@ void IRAM_ATTR gpioLoop(void) } } -void gpioAddButton(uint8_t pin, uint8_t input_mode, uint8_t default_state, uint8_t channel) +void gpioAddButton(uint8_t pin, uint8_t input_mode, uint8_t default_state, uint8_t index) { - uint8_t i; for(i = 0; i < HASP_NUM_INPUTS; i++) { if(!button[i]) { - button[i] = new AceButton(pin, default_state, channel); - // button[i]->init(pin, default_state, channel); + button[i] = new AceButton(pin, default_state, index); + // button[i]->init(pin, default_state, index); if(button[i]) { pinMode(pin, input_mode); ButtonConfig * buttonConfig = button[i]->getButtonConfig(); - buttonConfig->setEventHandler(gpio_event_cb); + buttonConfig->setEventHandler(gpio_event_handler); buttonConfig->setFeature(ButtonConfig::kFeatureClick); buttonConfig->clearFeature(ButtonConfig::kFeatureDoubleClick); buttonConfig->setFeature(ButtonConfig::kFeatureLongPress); @@ -132,30 +134,30 @@ void gpioAddButton(uint8_t pin, uint8_t input_mode, uint8_t default_state, uint8 buttonConfig->clearFeature( ButtonConfig::kFeatureSuppressClickBeforeDoubleClick); // Causes annoying pauses - Log.verbose(F("GPIO: Button%d created on pin %d (channel %d) mode %d default %d"), i, pin, channel, + Log.verbose(F("GPIO: Button%d created on pin %d (index %d) mode %d default %d"), i, pin, index, input_mode, default_state); gpioUsedInputCount = i + 1; return; } } } - Log.error(F("GPIO: Failed to create Button%d pin %d (channel %d). All %d slots available are in use!"), i, pin, - channel, HASP_NUM_INPUTS); + Log.error(F("GPIO: Failed to create Button%d pin %d (index %d). All %d slots available are in use!"), i, pin, index, + HASP_NUM_INPUTS); } -void gpioAddTouchButton(uint8_t pin, uint8_t input_mode, uint8_t default_state, uint8_t channel) +void gpioAddTouchButton(uint8_t pin, uint8_t input_mode, uint8_t default_state, uint8_t index) { uint8_t i; for(i = 0; i < HASP_NUM_INPUTS; i++) { if(!button[i]) { - button[i] = new AceButton(); + button[i] = new AceButton(pin, default_state, index); if(button[i]) { pinMode(pin, input_mode); ButtonConfig * buttonConfig = button[i]->getButtonConfig(); - buttonConfig->setEventHandler(gpio_event_cb); + buttonConfig->setEventHandler(gpio_event_handler); buttonConfig->setFeature(ButtonConfig::kFeatureClick); buttonConfig->clearFeature(ButtonConfig::kFeatureDoubleClick); buttonConfig->setFeature(ButtonConfig::kFeatureLongPress); @@ -163,83 +165,39 @@ void gpioAddTouchButton(uint8_t pin, uint8_t input_mode, uint8_t default_state, buttonConfig->clearFeature( ButtonConfig::kFeatureSuppressClickBeforeDoubleClick); // Causes annoying pauses - Log.verbose(F("GPIO: Button%d created on pin %d (channel %d) mode %d default %d"), i, pin, channel, + Log.verbose(F("GPIO: Button%d created on pin %d (index %d) mode %d default %d"), i, pin, index, input_mode, default_state); gpioUsedInputCount = i + 1; return; } } } - Log.error(F("GPIO: Failed to create Button%d pin %d (channel %d). All %d slots available are in use!"), i, pin, - channel, HASP_NUM_INPUTS); + Log.error(F("GPIO: Failed to create Button%d pin %d (index %d). All %d slots available are in use!"), i, pin, index, + HASP_NUM_INPUTS); } void gpioSetup() { aceButtonSetup(); - return; - - // gpioConfig[0] = PD15 * 256 + 5 + (INPUT << 3); + // return; + #if defined(ARDUINO_ARCH_ESP8266) - gpioAddButton(D2, INPUT_PULLUP, HIGH, 1); - //pinMode(D1, OUTPUT); + gpioConfig[0] = {D2, 7, HASP_GPIO_BUTTON, INPUT_PULLUP}; + gpioConfig[1] = {D1, 7, HASP_GPIO_LED, OUTPUT}; + +// gpioAddButton(D2, INPUT_PULLUP, HIGH, 1); +// pinMode(D1, OUTPUT); #endif #if defined(ARDUINO_ARCH_ESP32) - // gpioAddButton(D2, INPUT, HIGH, 1); - // pinMode(D1, OUTPUT); + // gpioConfig[0] = {D2, 0, HASP_GPIO_SWITCH, INPUT}; + // gpioConfig[1] = {D1, 1, HASP_GPIO_RELAY, OUTPUT}; + +// gpioAddButton(D2, INPUT, HIGH, 1); +// pinMode(D1, OUTPUT); #endif - for(uint8_t i = 0; i < HASP_NUM_GPIO_CONFIG; i++) { - uint8_t pin = (gpioConfig[i] >> 8) & 0xFF; - uint8_t channel = gpioConfig[i] & 0b111; // 3bit - uint8_t input_mode = (gpioConfig[i] >> 3) & 0b11; // 2bit gpio mode - // uint8_t input_mode = gpioConfig[i].io_mode - uint8_t gpiotype = (gpioConfig[i] >> 5) & 0b111; // 3bit - uint8_t default_state = gpioConfig[i] & 0b1; // 1bit: 0=LOW, 1=HIGH - - switch(input_mode) { - case 1: - input_mode = OUTPUT; - break; - case 2: - input_mode = INPUT_PULLUP; - break; -#ifndef ARDUINO_ARCH_ESP8266 - case 3: - input_mode = INPUT_PULLDOWN; - break; -#endif - default: - input_mode = INPUT; - } - - switch(gpiotype) { - case HASP_GPIO_SWITCH: - case HASP_GPIO_BUTTON: - // gpioAddButton(gpioConfig[i].io_mode.pin, input_mode, gpioConfig[i].default_state, - // gpioConfig[i].group); - break; - - case HASP_GPIO_RELAY: - pinMode(pin, OUTPUT); - break; - - // case HASP_GPIO_LED: - case HASP_GPIO_PWM: - case HASP_GPIO_BACKLIGHT: - pinMode(pin, OUTPUT); -#if defined(ARDUINO_ARCH_ESP32) - // configure LED PWM functionalitites - ledcSetup(channel, 20000, 10); - // attach the channel to the GPIO to be controlled - ledcAttachPin(pin, channel); -#endif - break; - } - } - /* #if defined(ARDUINO_ARCH_ESP8266) pinMode(D1, OUTPUT); @@ -250,4 +208,88 @@ void gpioSetup() pinMode(HASP_INPUT_PIN, INPUT); #endif */ -} \ No newline at end of file + + for(uint8_t i = 0; i < HASP_NUM_GPIO_CONFIG; i++) { + uint8_t input_mode; + switch(gpioConfig[i].gpio_function) { + case OUTPUT: + input_mode = OUTPUT; + break; + case INPUT_PULLUP: + input_mode = INPUT_PULLUP; + break; +#ifndef ARDUINO_ARCH_ESP8266 + case INPUT_PULLDOWN: + input_mode = INPUT_PULLDOWN; + break; +#endif + default: + input_mode = INPUT; + } + + switch(gpioConfig[i].type) { + case HASP_GPIO_SWITCH: + case HASP_GPIO_BUTTON: + gpioAddButton(gpioConfig[i].pin, input_mode, HIGH, i); + break; + case HASP_GPIO_SWITCH_INVERTED: + case HASP_GPIO_INPUT_BUTTON_INVERTED: + gpioAddButton(gpioConfig[i].pin, input_mode, LOW, i); + break; + + case HASP_GPIO_RELAY: + case HASP_GPIO_RELAY_INVERTED: + case HASP_GPIO_LED: + case HASP_GPIO_LED_INVERTED: + pinMode(gpioConfig[i].pin, OUTPUT); + break; + + case HASP_GPIO_PWM: + case HASP_GPIO_PWM_INVERTED: + // case HASP_GPIO_BACKLIGHT: + pinMode(gpioConfig[i].pin, OUTPUT); +#if defined(ARDUINO_ARCH_ESP32) + // configure LED PWM functionalitites + ledcSetup(gpioConfig[i].group, 20000, 10); + // attach the channel to the GPIO to be controlled + ledcAttachPin(gpioConfig[i].pin, gpioConfig[i].group); +#endif + break; + } + } +} + +void gpio_set_group_outputs(uint8_t groupid, uint8_t eventid) +{ + bool state = dispatch_get_event_state(eventid); + for(uint8_t i = 0; i < HASP_NUM_GPIO_CONFIG; i++) { + if(gpioConfig[i].group == groupid) { + switch(gpioConfig[i].type) { + case HASP_GPIO_RELAY: + case HASP_GPIO_LED: + digitalWrite(gpioConfig[i].pin, state ? HIGH : LOW); + break; + case HASP_GPIO_RELAY_INVERTED: + case HASP_GPIO_LED_INVERTED: + digitalWrite(gpioConfig[i].pin, state ? LOW : HIGH); + break; +#if defined(ARDUINO_ARCH_ESP32) + case HASP_GPIO_PWM: + ledcWrite(groupid, map(state, 0, 1, 0, 1023)); // ledChannel and value + break; + case HASP_GPIO_PWM_INVERTED: + ledcWrite(groupid, map(!state, 0, 1, 0, 1023)); // ledChannel and value + break; +#else + case HASP_GPIO_PWM: + analogWrite(gpioConfig[i].pin, map(state, 0, 1, 0, 1023)); + break; + case HASP_GPIO_PWM_INVERTED: + analogWrite(gpioConfig[i].pin, map(!state, 0, 1, 0, 1023)); + break; +#endif + default:; + } + } + } +} diff --git a/src/hasp_gpio.h b/src/hasp_gpio.h index 9a5c3b91..c9e5ed52 100644 --- a/src/hasp_gpio.h +++ b/src/hasp_gpio.h @@ -9,14 +9,27 @@ extern "C" { void gpioSetup(void); void IRAM_ATTR gpioLoop(void); +void gpio_set_group_outputs(uint8_t groupid, uint8_t eventid); -enum lv_hasp_gpio_type_t { - HASP_GPIO_SWITCH = 0, - HASP_GPIO_BUTTON = 1, - HASP_GPIO_RELAY = 2, - HASP_GPIO_PWM = 3, - HASP_GPIO_BACKLIGHT = 4, -}; +#define HASP_GPIO_FREE 0x00 +#define HASP_GPIO_USED 0x01 +#define HASP_GPIO_SWITCH 0x02 +#define HASP_GPIO_SWITCH_INVERTED 0x03 +#define HASP_GPIO_BUTTON 0x04 +#define HASP_GPIO_INPUT_BUTTON_INVERTED 0x05 +#define HASP_GPIO_COUNTER 0x06 +#define HASP_GPIO_COUNTER_INVERTED 0x07 +#define HASP_GPIO_ADC 0x08 +#define HASP_GPIO_ADC_INVERTED 0x09 +#define HASP_GPIO_RELAY 0x0A +#define HASP_GPIO_RELAY_INVERTED 0x0B +#define HASP_GPIO_LED 0x0C +#define HASP_GPIO_LED_INVERTED 0x0D +#define HASP_GPIO_PWM 0x0E +#define HASP_GPIO_PWM_INVERTED 0x0F +#define HASP_GPIO_DAC 0x10 +#define HASP_GPIO_DAC_INVERTED 0x11 +#define HASP_GPIO_USER 0xFF #ifdef __cplusplus } /* extern "C" */