diff --git a/src/hasp/hasp_dispatch.cpp b/src/hasp/hasp_dispatch.cpp index 6ed4cacf..6e071ed3 100644 --- a/src/hasp/hasp_dispatch.cpp +++ b/src/hasp/hasp_dispatch.cpp @@ -96,24 +96,6 @@ void dispatch_state_object(uint8_t pageid, uint8_t btnid, const char* payload) dispatch_state_subtopic(topic, payload); } -/* Takes and lv_obj and finds the pageid and objid - Then sends the data out on the state/pxby topic -*/ -void dispatch_obj_data(lv_obj_t* obj, const char* data) -{ - uint8_t pageid; - uint8_t objid; - - if(hasp_find_id_from_obj(obj, &pageid, &objid)) { - if(!data) return; -#if HASP_USE_MQTT > 0 - dispatch_state_object(pageid, objid, data); -#endif - } else { - LOG_ERROR(TAG_MSGR, F(D_OBJECT_UNKNOWN)); - } -} - // Format filesystem and erase EEPROM bool dispatch_factory_reset() { @@ -233,6 +215,59 @@ static inline bool dispatch_parse_button_attribute(const char* topic_p, const ch // } } +static void dispatch_gpio(const char* topic, const char* payload) +{ + int16_t val; + uint8_t pin; + + if(topic == strstr_P(topic, PSTR("relay"))) { + if(strlen(payload) == 0) { + // val = gpio_get_relay_value(pin); + } else { + topic += 5; + if(Utilities::is_only_digits(topic)) { + pin = atoi(topic); + val = Utilities::is_true(payload); + // gpio_set_relay_value(pin, val); + return; + } + // invalid pin + } + + } else if(topic == strstr_P(topic, PSTR("led"))) { + if(strlen(payload) == 0) { + } else { + topic += 3; + if(Utilities::is_only_digits(topic)) { + pin = atoi(topic); + val = Utilities::is_true(payload); + // gpio_set_led_value(pin, val); + return; + } + // invalid pin + } + + } else if(topic == strstr_P(topic, PSTR("pwm"))) { + if(strlen(payload) == 0) { + + } else { + topic += 3; + if(Utilities::is_only_digits(topic)) { + pin = atoi(topic); + val = Utilities::is_true(payload); + // gpio_set_pwm_value(pin, val); + return; + } + // invalid pin + } + + } else { + LOG_WARNING(TAG_MSGR, F("Invalid gpio type %s"), topic); + return; + } + LOG_WARNING(TAG_MSGR, F("Invalid pin number %s"), topic); +} + // objectattribute=value void dispatch_command(const char* topic, const char* payload) { @@ -249,14 +284,9 @@ void dispatch_command(const char* topic, const char* payload) /* =============================== Not standard payload commands ===================================== */ - if(strlen(topic) == 7 && topic == strstr_P(topic, PSTR("output"))) { + if(topic == strstr_P(topic, PSTR("gpio/"))) { - if(strlen(payload) == 0) { - // reply state - } else { - int16_t state = atoi(payload); - dispatch_normalized_group_value(atoi(topic + 6), NULL, state, 0, 1); // + 6 => trim 'output' from the topic - } + dispatch_gpio(topic + 5, payload); // } else if(strcasecmp_P(topic, PSTR("screenshot")) == 0) { // guiTakeScreenshot("/screenshot.bmp"); // Literal String @@ -385,49 +415,17 @@ void dispatch_output_idle_state(uint8_t state) dispatch_state_subtopic(topic, payload); } -void dispatch_output_group_state(uint8_t groupid, uint16_t state) -{ - char payload[64]; - char number[16]; // Return the current state - char topic[8]; - itoa(state, number, DEC); - snprintf_P(payload, sizeof(payload), PSTR("{\"group\":%d,\"state\":\"%s\"}"), groupid, number); +// void dispatch_output_group_state(uint8_t groupid, uint16_t state) +// { +// char payload[64]; +// char number[16]; // Return the current state +// char topic[8]; +// itoa(state, number, DEC); +// snprintf_P(payload, sizeof(payload), PSTR("{\"group\":%d,\"state\":\"%s\"}"), groupid, number); - memcpy_P(topic, PSTR("output"), 7); - dispatch_state_subtopic(topic, payload); -} - -void dispatch_send_obj_attribute_str(uint8_t pageid, uint8_t btnid, const char* attribute, const char* data) -{ - if(!attribute || !data) return; - - char payload[32 + strlen(data) + strlen(attribute)]; - snprintf_P(payload, sizeof(payload), PSTR("{\"%s\":\"%s\"}"), attribute, data); - - dispatch_state_object(pageid, btnid, payload); -} - -void dispatch_send_obj_attribute_int(uint8_t pageid, uint8_t btnid, const char* attribute, int32_t val) -{ - if(!attribute) return; - - char payload[64 + strlen(attribute)]; - snprintf_P(payload, sizeof(payload), PSTR("{\"%s\":%d}"), attribute, val); - - dispatch_state_object(pageid, btnid, payload); -} - -void dispatch_send_obj_attribute_color(uint8_t pageid, uint8_t btnid, const char* attribute, uint8_t r, uint8_t g, - uint8_t b) -{ - if(!attribute) return; - - char payload[64 + strlen(attribute)]; - snprintf_P(payload, sizeof(payload), PSTR("{\"%s\":\"#%02x%02x%02x\",\"r\":%d,\"g\":%d,\"b\":%d}"), attribute, r, g, - b, r, g, b); - - dispatch_state_object(pageid, btnid, payload); -} +// memcpy_P(topic, PSTR("output"), 7); +// dispatch_state_subtopic(topic, payload); +// } #if HASP_USE_CONFIG > 0 // Get or Set a part of the config.json file @@ -533,126 +531,18 @@ static void dispatch_config(const char* topic, const char* payload) #endif // HASP_USE_CONFIG /********************************************** Input Events *******************************************/ -// Map events to either ON or OFF (UP or DOWN) -bool dispatch_get_event_state(uint8_t eventid) -{ - switch(eventid) { - case HASP_EVENT_ON: - case HASP_EVENT_DOWN: - case HASP_EVENT_LONG: - case HASP_EVENT_HOLD: - return true; - // case HASP_EVENT_OFF: - // case HASP_EVENT_UP: - // case HASP_EVENT_SHORT: - // case HASP_EVENT_DOUBLE: - // case HASP_EVENT_LOST: - default: - return false; - } -} - -// Map events to their description string -void dispatch_get_event_name(uint8_t eventid, char* buffer, size_t size) -{ - switch(eventid) { - case HASP_EVENT_ON: - memcpy_P(buffer, PSTR("on"), size); - break; - case HASP_EVENT_OFF: - memcpy_P(buffer, PSTR("off"), size); - break; - case HASP_EVENT_UP: - memcpy_P(buffer, PSTR("up"), size); - break; - case HASP_EVENT_DOWN: - memcpy_P(buffer, PSTR("down"), size); - break; - case HASP_EVENT_SHORT: - memcpy_P(buffer, PSTR("short"), size); - break; - case HASP_EVENT_LONG: - memcpy_P(buffer, PSTR("long"), size); - break; - case HASP_EVENT_HOLD: - memcpy_P(buffer, PSTR("hold"), size); - break; - case HASP_EVENT_LOST: - memcpy_P(buffer, PSTR("lost"), size); - break; - case HASP_EVENT_CHANGED: - memcpy_P(buffer, PSTR("changed"), size); - break; - default: - memcpy_P(buffer, PSTR("unknown"), size); - } -} - #if HASP_USE_GPIO > 0 -void dispatch_gpio_input_event(uint8_t pin, uint8_t group, uint8_t eventid) +void dispatch_gpio_output_value(const char* gpiotype, uint8_t pin, int16_t val) { - char payload[64]; - char topic[8]; - char event[8]; - dispatch_get_event_name(eventid, event, sizeof(event)); - snprintf_P(payload, sizeof(payload), PSTR("{\"pin\":%d,\"group\":%d,\"event\":\"%s\"}"), pin, group, event); + char payload[16]; + char topic[16]; + snprintf_P(topic, sizeof(topic), PSTR("%s%d"), gpiotype, pin); + snprintf_P(payload, sizeof(payload), PSTR("%d"), val); -#if HASP_USE_MQTT > 0 - memcpy_P(topic, PSTR("input"), 6); dispatch_state_subtopic(topic, payload); -#endif - - // update outputstates - // dispatch_group_onoff(group, dispatch_get_event_state(eventid), NULL); } #endif -/* ============================== Event Senders ============================ */ - -// Send out the event that occured -void dispatch_object_generic_event(lv_obj_t* obj, uint8_t eventid) -{ - char data[40]; - char eventname[8]; - - dispatch_get_event_name(eventid, eventname, sizeof(eventname)); - snprintf_P(data, sizeof(data), PSTR("{\"event\":\"%s\"}"), eventname); - dispatch_obj_data(obj, data); -} - -// Send out the on/off event, with the val -void dispatch_object_val_event(lv_obj_t* obj, uint8_t eventid, int16_t val) -{ - char data[40]; - char eventname[8]; - - dispatch_get_event_name(eventid, eventname, sizeof(eventname)); - snprintf_P(data, sizeof(data), PSTR("{\"event\":\"%s\",\"val\":%d}"), eventname, val); - dispatch_obj_data(obj, data); -} - -// Send out the changed event, with the val and text -void dispatch_object_selection_changed(lv_obj_t* obj, int16_t val, const char* text) -{ - char data[200]; - - snprintf_P(data, sizeof(data), PSTR("{\"event\":\"changed\",\"val\":%d,\"text\":\"%s\"}"), val, text); - dispatch_obj_data(obj, data); -} - -// Send out the changed event, with the color -void dispatch_object_color_changed(lv_obj_t* obj, lv_color_t color) -{ - char data[80]; - lv_color32_t c32; - c32.full = lv_color_to32(color); - - snprintf_P(data, sizeof(data), - PSTR("{\"event\":\"changed\",\"color\":\"#%02x%02x%02x\",\"r\":%d,\"g\":%d,\"b\":%d}"), c32.ch.red, - c32.ch.green, c32.ch.blue, c32.ch.red, c32.ch.green, c32.ch.blue); - dispatch_obj_data(obj, data); -} - /********************************************** Output States ******************************************/ /* static inline void dispatch_state_msg(const __FlashStringHelper* subtopic, const char* payload) @@ -665,13 +555,13 @@ static inline void dispatch_state_msg(const __FlashStringHelper* subtopic, const // if((eventid == HASP_EVENT_LONG) || (eventid == HASP_EVENT_HOLD)) return; // don't send repeat events // if(groupid >= 0) { -// bool state = dispatch_get_event_state(eventid); +// bool state = Parser::get_event_state(eventid); // gpio_set_group_onoff(groupid, state); // object_set_normalized_group_value(groupid, eventid, obj); // } // char payload[8]; -// dispatch_get_event_name(eventid, payload, sizeof(payload)); +// Parser::get_event_name(eventid, payload, sizeof(payload)); // // dispatch_output_group_state(groupid, payload); // } diff --git a/src/hasp/hasp_dispatch.h b/src/hasp/hasp_dispatch.h index ccf982b0..c5ce21ff 100644 --- a/src/hasp/hasp_dispatch.h +++ b/src/hasp/hasp_dispatch.h @@ -65,21 +65,14 @@ void dispatch_current_state(); void dispatch_output_current_page(); void dispatch_gpio_input_event(uint8_t pin, uint8_t group, uint8_t eventid); -bool dispatch_get_event_state(uint8_t eventid); -void dispatch_get_event_name(uint8_t eventid, char* buffer, size_t size); +void dispatch_gpio_output_value(const char* gpiotype, uint8_t pin, int16_t val); + void dispatch_object_value_changed(lv_obj_t* obj, int16_t state); void dispatch_normalized_group_value(uint8_t groupid, lv_obj_t* obj, int16_t val, int16_t min, int16_t max); -void dispatch_send_obj_attribute_str(uint8_t pageid, uint8_t btnid, const char* attribute, const char* data); -void dispatch_send_obj_attribute_int(uint8_t pageid, uint8_t btnid, const char* attribute, int32_t val); -void dispatch_send_obj_attribute_color(uint8_t pageid, uint8_t btnid, const char* attribute, uint8_t r, uint8_t g, - uint8_t b); - -void dispatch_object_generic_event(lv_obj_t* obj, uint8_t eventid); -void dispatch_object_val_event(lv_obj_t* obj, uint8_t eventid, int16_t val); -void dispatch_object_selection_changed(lv_obj_t* obj, int16_t val, const char* text); -void dispatch_object_color_changed(lv_obj_t* obj, lv_color_t color); +void dispatch_state_object(uint8_t pageid, uint8_t btnid, const char* payload); +void dispatch_state_subtopic(const char* subtopic, const char* payload); /* ===== Getter and Setter Functions ===== */ diff --git a/src/hasp/hasp_event.cpp b/src/hasp/hasp_event.cpp new file mode 100644 index 00000000..b543448e --- /dev/null +++ b/src/hasp/hasp_event.cpp @@ -0,0 +1,496 @@ +/* MIT License - Copyright (c) 2019-2021 Francis Van Roie + For full license information read the LICENSE file in the project folder */ + +/* ******************************************************************************************** + * + * HASP Event Handlers + * - Value Senders : Convert values and events into topic/payload before forwarding + * - Event Handlers : Callbacks for object event processing + * + ******************************************************************************************** */ + +#include "hasp_conf.h" +#include "hasplib.h" + +// static unsigned long last_change_event = 0; +static bool last_press_was_short = false; // Avoid SHORT + UP double events +static lv_style_int_t last_value_sent; + +/* ============================== Event Senders ============================ */ + +/* Takes and lv_obj and finds the pageid and objid + Then sends the data out on the state/pxby topic +*/ + +// ##################### Value Senders ######################################################## + +void event_obj_data(lv_obj_t* obj, const char* data) +{ + uint8_t pageid; + uint8_t objid; + + if(hasp_find_id_from_obj(obj, &pageid, &objid)) { + if(!data) return; +#if HASP_USE_MQTT > 0 + dispatch_state_object(pageid, objid, data); +#endif + } else { + LOG_ERROR(TAG_MSGR, F(D_OBJECT_UNKNOWN)); + } +} + +void event_dispatch(lv_obj_t* obj, uint8_t eventid, const char* data) +{} + +// Send out the event that occured +void event_object_generic_event(lv_obj_t* obj, uint8_t eventid) +{ + char data[40]; + char eventname[8]; + + Parser::get_event_name(eventid, eventname, sizeof(eventname)); + snprintf_P(data, sizeof(data), PSTR("{\"event\":\"%s\"}"), eventname); + event_obj_data(obj, data); +} + +// Send out the on/off event, with the val +void event_object_val_event(lv_obj_t* obj, uint8_t eventid, int16_t val) +{ + char data[40]; + char eventname[8]; + + Parser::get_event_name(eventid, eventname, sizeof(eventname)); + snprintf_P(data, sizeof(data), PSTR("{\"event\":\"%s\",\"val\":%d}"), eventname, val); + event_obj_data(obj, data); +} + +// Send out the changed event, with the val and text +void event_object_selection_changed(lv_obj_t* obj, int16_t val, const char* text) +{ + char data[200]; + + snprintf_P(data, sizeof(data), PSTR("{\"event\":\"changed\",\"val\":%d,\"text\":\"%s\"}"), val, text); + event_obj_data(obj, data); +} + +// Send out the changed event, with the color +void event_object_color_changed(lv_obj_t* obj, lv_color_t color) +{ + char data[80]; + lv_color32_t c32; + c32.full = lv_color_to32(color); + + snprintf_P(data, sizeof(data), + PSTR("{\"event\":\"changed\",\"color\":\"#%02x%02x%02x\",\"r\":%d,\"g\":%d,\"b\":%d}"), c32.ch.red, + c32.ch.green, c32.ch.blue, c32.ch.red, c32.ch.green, c32.ch.blue); + event_obj_data(obj, data); +} + +// ##################### Event Handlers ######################################################## + +#if HASP_USE_GPIO > 0 +void event_gpio_input(uint8_t pin, uint8_t group, uint8_t eventid) +{ + char payload[64]; + char topic[8]; + char event[8]; + Parser::get_event_name(eventid, event, sizeof(event)); + snprintf_P(payload, sizeof(payload), PSTR("{\"pin\":%d,\"group\":%d,\"event\":\"%s\"}"), pin, group, event); + + memcpy_P(topic, PSTR("input"), 6); + dispatch_state_subtopic(topic, payload); + + // update outputstates + // dispatch_group_onoff(group, Parser::get_event_state(eventid), NULL); +} +#endif + +void event_delete_object(lv_obj_t* obj) +{ + switch(obj->user_data.objid) { + case LV_HASP_LINE: + line_clear_points(obj); + break; + + case LV_HASP_BTNMATRIX: + my_btnmatrix_map_clear(obj); + _LV_WIN_PART_REAL_LAST; + _LV_WIN_PART_VIRTUAL_LAST; + break; + + case LV_HASP_GAUGE: + break; + } + + // TODO: delete value_str data for ALL parts + my_obj_set_value_str_txt(obj, LV_OBJ_PART_MAIN, LV_STATE_DEFAULT, NULL); +} + +void log_event(const char* name, lv_event_t event) +{ + return; + + switch(event) { + case LV_EVENT_PRESSED: + LOG_TRACE(TAG_EVENT, "%s Pressed", name); + break; + + case LV_EVENT_PRESS_LOST: + LOG_TRACE(TAG_EVENT, "%s Press lost", name); + break; + + case LV_EVENT_SHORT_CLICKED: + LOG_TRACE(TAG_EVENT, "%s Short clicked", name); + break; + + case LV_EVENT_CLICKED: + LOG_TRACE(TAG_EVENT, "%s Clicked", name); + break; + + case LV_EVENT_LONG_PRESSED: + LOG_TRACE(TAG_EVENT, "%S Long press", name); + break; + + case LV_EVENT_LONG_PRESSED_REPEAT: + LOG_TRACE(TAG_EVENT, "%s Long press repeat", name); + break; + + case LV_EVENT_RELEASED: + LOG_TRACE(TAG_EVENT, "%s Released", name); + break; + + case LV_EVENT_VALUE_CHANGED: + LOG_TRACE(TAG_EVENT, "%s Changed", name); + break; + + case LV_EVENT_PRESSING: + break; + + default: + LOG_TRACE(TAG_EVENT, "%s Other %d", name, event); + } +} + +/** + * Called when a press on the system layer is detected + * @param obj pointer to a button matrix + * @param event type of event that occured + */ +void wakeup_event_handler(lv_obj_t* obj, lv_event_t event) +{ + log_event("wakeup", event); + + if(event == LV_EVENT_RELEASED && obj == lv_disp_get_layer_sys(NULL)) { + hasp_update_sleep_state(); // wakeup? + if(!haspDevice.get_backlight_power()) + dispatch_backlight(NULL, "1"); // backlight on and also disable wakeup touch + else { + hasp_disable_wakeup_touch(); // only disable wakeup touch + } + } +} + +void page_event_handler(lv_obj_t* obj, lv_event_t event) +{ + log_event("page", event); + + if(event == LV_EVENT_GESTURE) { + 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); + break; + case LV_GESTURE_DIR_RIGHT: + haspPages.prev(LV_SCR_LOAD_ANIM_NONE); + break; + case LV_GESTURE_DIR_BOTTOM: + haspPages.back(LV_SCR_LOAD_ANIM_NONE); + break; + } + } +} + +/** + * Called when a button-style object is clicked + * @param obj pointer to a button object + * @param event type of event that occured + */ +void generic_event_handler(lv_obj_t* obj, lv_event_t event) +{ + uint8_t eventid; + log_event("generic", event); + + switch(event) { + case LV_EVENT_PRESSED: + eventid = HASP_EVENT_DOWN; + last_press_was_short = false; + break; + + case LV_EVENT_CLICKED: + // UP = the same object was release then was pressed and press was not lost! + eventid = last_press_was_short ? HASP_EVENT_SHORT : HASP_EVENT_UP; + break; + + case LV_EVENT_SHORT_CLICKED: + last_press_was_short = true; // Avoid SHORT + UP double events + return; + + // eventid = HASP_EVENT_SHORT; + // break; + case LV_EVENT_LONG_PRESSED: + eventid = HASP_EVENT_LONG; + last_press_was_short = false; + break; + + case LV_EVENT_LONG_PRESSED_REPEAT: + // last_press_was_short = false; + return; // we don't care about hold + // eventid = HASP_EVENT_HOLD; + // break; + case LV_EVENT_PRESS_LOST: + eventid = HASP_EVENT_LOST; + last_press_was_short = false; + break; + + case LV_EVENT_PRESSING: + case LV_EVENT_FOCUSED: + case LV_EVENT_DEFOCUSED: + case LV_EVENT_RELEASED: + return; + + case LV_EVENT_VALUE_CHANGED: + LOG_WARNING(TAG_EVENT, F("Value changed Event %d occured"), + event); // Shouldn't happen in this event handler + last_press_was_short = false; + return; + + case LV_EVENT_DELETE: + LOG_VERBOSE(TAG_EVENT, F(D_OBJECT_DELETED)); + event_delete_object(obj); // free and destroy persistent memory allocated for certain objects + last_press_was_short = false; + return; + + default: + LOG_WARNING(TAG_EVENT, F(D_OBJECT_EVENT_UNKNOWN), event); + last_press_was_short = false; + return; + } + + hasp_update_sleep_state(); // wakeup? + + /* If an actionid is attached, perform that action on UP event only */ + if(obj->user_data.actionid) { + if(eventid == HASP_EVENT_UP || eventid == HASP_EVENT_SHORT) { + 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); + break; + case HASP_NUM_PAGE_BACK: + haspPages.back(transitionid); + break; + case HASP_NUM_PAGE_NEXT: + haspPages.next(transitionid); + break; + default: + haspPages.set(obj->user_data.actionid, transitionid); + } + dispatch_output_current_page(); + } + } else { + event_object_generic_event(obj, eventid); // send normal object event + } + dispatch_normalized_group_value(obj->user_data.groupid, obj, Parser::get_event_state(eventid), HASP_EVENT_OFF, + HASP_EVENT_ON); +} + +/** + * Called when a object state is toggled on/off + * @param obj pointer to a switch object + * @param event type of event that occured + */ +void toggle_event_handler(lv_obj_t* obj, lv_event_t event) +{ + log_event("toggle", event); + + if(event == LV_EVENT_VALUE_CHANGED) { + bool val = 0; + hasp_update_sleep_state(); // wakeup? + + switch(obj->user_data.objid) { + case LV_HASP_SWITCH: + val = lv_switch_get_state(obj); + break; + + case LV_HASP_CHECKBOX: + val = lv_checkbox_is_checked(obj); + break; + + case LV_HASP_BUTTON: { + val = lv_obj_get_state(obj, LV_BTN_PART_MAIN) & LV_STATE_CHECKED; + break; + } + + default: + return; + } + + // snprintf_P(property, sizeof(property), PSTR("val")); + // hasp_send_obj_attribute_int(obj, property, val); + + hasp_update_sleep_state(); // wakeup? + event_object_val_event(obj, val, val); + dispatch_normalized_group_value(obj->user_data.groupid, obj, val, HASP_EVENT_OFF, HASP_EVENT_ON); + + } else if(event == LV_EVENT_DELETE) { + LOG_VERBOSE(TAG_EVENT, F(D_OBJECT_DELETED)); + event_delete_object(obj); + } +} + +/** + * Called when a range value has changed + * @param obj pointer to a dropdown list or roller + * @param event type of event that occured + */ +void selector_event_handler(lv_obj_t* obj, lv_event_t event) +{ + log_event("selector", event); + + if(event == LV_EVENT_VALUE_CHANGED) { + char buffer[128]; + char property[36]; + uint16_t val = 0; + uint16_t max = 0; + hasp_update_sleep_state(); // wakeup? + + switch(obj->user_data.objid) { + case LV_HASP_DROPDOWN: + val = lv_dropdown_get_selected(obj); + max = lv_dropdown_get_option_cnt(obj) - 1; + lv_dropdown_get_selected_str(obj, buffer, sizeof(buffer)); + break; + + case LV_HASP_ROLLER: + val = lv_roller_get_selected(obj); + max = lv_roller_get_option_cnt(obj) - 1; + lv_roller_get_selected_str(obj, buffer, sizeof(buffer)); + break; + + case LV_HASP_BTNMATRIX: { + val = lv_btnmatrix_get_active_btn(obj); + const char* txt = lv_btnmatrix_get_btn_text(obj, val); + strncpy(buffer, txt, sizeof(buffer)); + break; + } + + case LV_HASP_TABLE: { + uint16_t row; + uint16_t col; + if(lv_table_get_pressed_cell(obj, &row, &col) != LV_RES_OK) return; // outside any cell + + const char* txt = lv_table_get_cell_value(obj, row, col); + strncpy(buffer, txt, sizeof(buffer)); + + snprintf_P(property, sizeof(property), PSTR("row\":%d,\"col\":%d,\"text"), row, col); + hasp_send_obj_attribute_str(obj, property, buffer); + return; + } + + default: + return; + } + + // set the property + // snprintf_P(property, sizeof(property), PSTR("val\":%d,\"text"), val); + // hasp_send_obj_attribute_str(obj, property, buffer); + + event_object_selection_changed(obj, val, buffer); + if(max > 0) dispatch_normalized_group_value(obj->user_data.groupid, obj, val, 0, max); + + } else if(event == LV_EVENT_DELETE) { + LOG_VERBOSE(TAG_EVENT, F(D_OBJECT_DELETED)); + event_delete_object(obj); + } +} + +/** + * Called when a slider or adjustable arc is clicked + * @param obj pointer to a slider + * @param event type of event that occured + */ +void slider_event_handler(lv_obj_t* obj, lv_event_t event) +{ + log_event("slider", event); + + uint16_t evt; + switch(event) { + case LV_EVENT_VALUE_CHANGED: + break; + + case LV_EVENT_DELETE: + LOG_VERBOSE(TAG_EVENT, F(D_OBJECT_DELETED)); + event_delete_object(obj); + break; + + case LV_EVENT_PRESSED: + hasp_update_sleep_state(); // wakeup on press down? + evt = HASP_EVENT_DOWN; + case LV_EVENT_LONG_PRESSED_REPEAT: + if(event == LV_EVENT_LONG_PRESSED_REPEAT) evt = HASP_EVENT_CHANGED; + case LV_EVENT_RELEASED: { + if(event == LV_EVENT_RELEASED) evt = HASP_EVENT_UP; + + // case LV_EVENT_PRESSED || LV_EVENT_LONG_PRESSED_REPEAT || LV_EVENT_RELEASED + int16_t val; + int16_t min; + int16_t max; + + if(obj->user_data.objid == LV_HASP_SLIDER) { + val = lv_slider_get_value(obj); + min = lv_slider_get_min_value(obj); + max = lv_slider_get_max_value(obj); + } else if(obj->user_data.objid == LV_HASP_ARC) { + val = lv_arc_get_value(obj); + min = lv_arc_get_min_value(obj); + max = lv_arc_get_max_value(obj); + } else { + return; + } + + if((event == LV_EVENT_LONG_PRESSED_REPEAT && last_value_sent != val) || + event != LV_EVENT_LONG_PRESSED_REPEAT) { + last_value_sent = val; + event_object_val_event(obj, evt, val); + dispatch_normalized_group_value(obj->user_data.groupid, obj, val, min, max); + } + break; + } + + default: + // LOG_VERBOSE(TAG_EVENT, F("Event ID: %d"), event); + ; + } +} + +/** + * Called when a color picker is clicked + * @param obj pointer to a color picker + * @param event type of event that occured + */ +void cpicker_event_handler(lv_obj_t* obj, lv_event_t event) +{ + char color[6]; + snprintf_P(color, sizeof(color), PSTR("color")); + log_event("cpicker", event); + + if(event == LV_EVENT_VALUE_CHANGED) { + hasp_update_sleep_state(); // wakeup? + // hasp_send_obj_attribute_color(obj, color, lv_cpicker_get_color(obj)); + event_object_color_changed(obj, lv_cpicker_get_color(obj)); + + } else if(event == LV_EVENT_DELETE) { + LOG_VERBOSE(TAG_EVENT, F(D_OBJECT_DELETED)); + event_delete_object(obj); + } +} diff --git a/src/hasp/hasp_event.h b/src/hasp/hasp_event.h new file mode 100644 index 00000000..d1770bbd --- /dev/null +++ b/src/hasp/hasp_event.h @@ -0,0 +1,26 @@ +/* MIT License - Copyright (c) 2019-2021 Francis Van Roie + For full license information read the LICENSE file in the project folder */ + +#ifndef HASP_EVENT_H +#define HASP_EVENT_H + +#include "lvgl.h" +#include "hasp_conf.h" + +#define HASP_NUM_PAGE_PREV (HASP_NUM_PAGES + 1) +#define HASP_NUM_PAGE_BACK (HASP_NUM_PAGES + 2) +#define HASP_NUM_PAGE_NEXT (HASP_NUM_PAGES + 3) + +void wakeup_event_handler(lv_obj_t* obj, lv_event_t event); +void page_event_handler(lv_obj_t* obj, lv_event_t event); +void generic_event_handler(lv_obj_t* obj, lv_event_t event); +void toggle_event_handler(lv_obj_t* obj, lv_event_t event); +void slider_event_handler(lv_obj_t* obj, lv_event_t event); +void selector_event_handler(lv_obj_t* obj, lv_event_t event); +void cpicker_event_handler(lv_obj_t* obj, lv_event_t event); + +#if HASP_USE_GPIO > 0 +void event_gpio_input(uint8_t pin, uint8_t group, uint8_t eventid); +#endif + +#endif // HASP_EVENT_H \ No newline at end of file diff --git a/src/hasp/hasp_object.cpp b/src/hasp/hasp_object.cpp index ab35eca4..da232e1b 100644 --- a/src/hasp/hasp_object.cpp +++ b/src/hasp/hasp_object.cpp @@ -6,8 +6,6 @@ * HASP Object Handlers * - Object Finders : Convert from object pointers to and from p[x].b[y] IDs * - Value Dispatchers : Forward output data to the dispatcher - * - Value Senders : Convert values and events into topic/payload before forwarding - * - Event Handlers : Callbacks for object event processing * - Attribute processor : Decide if an attribute needs updating or querying and forward * - Object creator : Creates an object from a line of jsonl * @@ -24,14 +22,7 @@ #include "hasplib.h" -#define HASP_NUM_PAGE_PREV (HASP_NUM_PAGES + 1) -#define HASP_NUM_PAGE_BACK (HASP_NUM_PAGES + 2) -#define HASP_NUM_PAGE_NEXT (HASP_NUM_PAGES + 3) - const char** btnmatrix_default_map; // memory pointer to lvgl default btnmatrix map -// static unsigned long last_change_event = 0; -static bool last_press_was_short = false; // Avoid SHORT + UP double events -static lv_style_int_t last_value_sent; // ##################### Object Finders ######################################################## @@ -231,7 +222,12 @@ void hasp_send_obj_attribute_str(lv_obj_t* obj, const char* attribute, const cha uint8_t objid; if(hasp_find_id_from_obj(obj, &pageid, &objid)) { - dispatch_send_obj_attribute_str(pageid, objid, attribute, data); + if(!attribute || !data) return; + + char payload[32 + strlen(data) + strlen(attribute)]; + snprintf_P(payload, sizeof(payload), PSTR("{\"%s\":\"%s\"}"), attribute, data); + + dispatch_state_object(pageid, objid, payload); } } @@ -241,7 +237,12 @@ void hasp_send_obj_attribute_int(lv_obj_t* obj, const char* attribute, int32_t v uint8_t objid; if(hasp_find_id_from_obj(obj, &pageid, &objid)) { - dispatch_send_obj_attribute_int(pageid, objid, attribute, val); + if(!attribute) return; + + char payload[64 + strlen(attribute)]; + snprintf_P(payload, sizeof(payload), PSTR("{\"%s\":%d}"), attribute, val); + + dispatch_state_object(pageid, objid, payload); } } @@ -251,408 +252,15 @@ void hasp_send_obj_attribute_color(lv_obj_t* obj, const char* attribute, lv_colo uint8_t objid; if(hasp_find_id_from_obj(obj, &pageid, &objid)) { + if(!attribute) return; + + char payload[64 + strlen(attribute)]; lv_color32_t c32; c32.full = lv_color_to32(color); - dispatch_send_obj_attribute_color(pageid, objid, attribute, c32.ch.red, c32.ch.green, c32.ch.blue); - } -} -// ##################### Value Senders ######################################################## - -// static void hasp_send_obj_attribute_P(lv_obj_t * obj, const char * attr, const char * data) -// { -// char * buffer; -// buffer = (char *)malloc(strlen_P(attr) + 1); -// strcpy_P(buffer, attr); -// hasp_send_obj_attribute_str(obj, buffer, data); -// free(buffer); -// } - -// static inline void hasp_obj_value_changed(lv_obj_t * obj, int32_t val) -// { -// dispatch_object_value_changed(obj, val); -// char data[32]; -// itoa(val, data, DEC); -// hasp_send_obj_attribute_P(obj, PSTR("val"), data); -//} - -// static inline void hasp_send_obj_attribute_event(lv_obj_t * obj, const char * event) -// { -// hasp_send_obj_attribute_P(obj, PSTR("event"), event); -// } - -// static inline void hasp_send_obj_attribute_txt(lv_obj_t * obj, const char * txt) -// { -// hasp_send_obj_attribute_P(obj, PSTR("txt"), txt); -// } - -// ##################### Event Handlers ######################################################## - -void log_event(const char* name, lv_event_t event) -{ - return; - - switch(event) { - case LV_EVENT_PRESSED: - LOG_TRACE(TAG_HASP, "%s Pressed", name); - break; - - case LV_EVENT_PRESS_LOST: - LOG_TRACE(TAG_HASP, "%s Press lost", name); - break; - - case LV_EVENT_SHORT_CLICKED: - LOG_TRACE(TAG_HASP, "%s Short clicked", name); - break; - - case LV_EVENT_CLICKED: - LOG_TRACE(TAG_HASP, "%s Clicked", name); - break; - - case LV_EVENT_LONG_PRESSED: - LOG_TRACE(TAG_HASP, "%S Long press", name); - break; - - case LV_EVENT_LONG_PRESSED_REPEAT: - LOG_TRACE(TAG_HASP, "%s Long press repeat", name); - break; - - case LV_EVENT_RELEASED: - LOG_TRACE(TAG_HASP, "%s Released", name); - break; - - case LV_EVENT_VALUE_CHANGED: - LOG_TRACE(TAG_HASP, "%s Changed", name); - break; - - case LV_EVENT_PRESSING: - break; - - default: - LOG_TRACE(TAG_HASP, "%s Other %d", name, event); - } -} - -/** - * Called when a press on the system layer is detected - * @param obj pointer to a button matrix - * @param event type of event that occured - */ -void wakeup_event_handler(lv_obj_t* obj, lv_event_t event) -{ - log_event("wakeup", event); - - if(event == LV_EVENT_RELEASED && obj == lv_disp_get_layer_sys(NULL)) { - hasp_update_sleep_state(); // wakeup? - if(!haspDevice.get_backlight_power()) - dispatch_backlight(NULL, "1"); // backlight on and also disable wakeup touch - else { - hasp_disable_wakeup_touch(); // only disable wakeup touch - } - } -} - -void page_event_handler(lv_obj_t* obj, lv_event_t event) -{ - log_event("page", event); - - if(event == LV_EVENT_GESTURE) { - 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); - break; - case LV_GESTURE_DIR_RIGHT: - haspPages.prev(LV_SCR_LOAD_ANIM_NONE); - break; - case LV_GESTURE_DIR_BOTTOM: - haspPages.back(LV_SCR_LOAD_ANIM_NONE); - break; - } - } -} - -/** - * Called when a button-style object is clicked - * @param obj pointer to a button object - * @param event type of event that occured - */ -void generic_event_handler(lv_obj_t* obj, lv_event_t event) -{ - uint8_t eventid; - log_event("generic", event); - - switch(event) { - case LV_EVENT_PRESSED: - eventid = HASP_EVENT_DOWN; - last_press_was_short = false; - break; - - case LV_EVENT_CLICKED: - // UP = the same object was release then was pressed and press was not lost! - eventid = last_press_was_short ? HASP_EVENT_SHORT : HASP_EVENT_UP; - break; - - case LV_EVENT_SHORT_CLICKED: - last_press_was_short = true; // Avoid SHORT + UP double events - return; - - // eventid = HASP_EVENT_SHORT; - // break; - case LV_EVENT_LONG_PRESSED: - eventid = HASP_EVENT_LONG; - last_press_was_short = false; - break; - - case LV_EVENT_LONG_PRESSED_REPEAT: - // last_press_was_short = false; - return; // we don't care about hold - // eventid = HASP_EVENT_HOLD; - // break; - case LV_EVENT_PRESS_LOST: - eventid = HASP_EVENT_LOST; - last_press_was_short = false; - break; - - case LV_EVENT_PRESSING: - case LV_EVENT_FOCUSED: - case LV_EVENT_DEFOCUSED: - case LV_EVENT_RELEASED: - return; - - case LV_EVENT_VALUE_CHANGED: - LOG_WARNING(TAG_HASP, F("Value changed Event %d occured"), event); // Shouldn't happen in this event handler - last_press_was_short = false; - return; - - case LV_EVENT_DELETE: - LOG_VERBOSE(TAG_HASP, F(D_OBJECT_DELETED)); - hasp_object_delete(obj); // free and destroy persistent memory allocated for certain objects - last_press_was_short = false; - return; - - default: - LOG_WARNING(TAG_HASP, F(D_OBJECT_EVENT_UNKNOWN), event); - last_press_was_short = false; - return; - } - - hasp_update_sleep_state(); // wakeup? - - /* If an actionid is attached, perform that action on UP event only */ - if(obj->user_data.actionid) { - if(eventid == HASP_EVENT_UP || eventid == HASP_EVENT_SHORT) { - 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); - break; - case HASP_NUM_PAGE_BACK: - haspPages.back(transitionid); - break; - case HASP_NUM_PAGE_NEXT: - haspPages.next(transitionid); - break; - default: - haspPages.set(obj->user_data.actionid, transitionid); - } - dispatch_output_current_page(); - } - } else { - dispatch_object_generic_event(obj, eventid); // send normal object event - } - dispatch_normalized_group_value(obj->user_data.groupid, obj, dispatch_get_event_state(eventid), HASP_EVENT_OFF, - HASP_EVENT_ON); -} - -/** - * Called when a object state is toggled on/off - * @param obj pointer to a switch object - * @param event type of event that occured - */ -void toggle_event_handler(lv_obj_t* obj, lv_event_t event) -{ - log_event("toggle", event); - - if(event == LV_EVENT_VALUE_CHANGED) { - bool val = 0; - hasp_update_sleep_state(); // wakeup? - - switch(obj->user_data.objid) { - case LV_HASP_SWITCH: - val = lv_switch_get_state(obj); - break; - - case LV_HASP_CHECKBOX: - val = lv_checkbox_is_checked(obj); - break; - - case LV_HASP_BUTTON: { - val = lv_obj_get_state(obj, LV_BTN_PART_MAIN) & LV_STATE_CHECKED; - break; - } - - default: - return; - } - - // snprintf_P(property, sizeof(property), PSTR("val")); - // hasp_send_obj_attribute_int(obj, property, val); - - hasp_update_sleep_state(); // wakeup? - dispatch_object_val_event(obj, val, val); - dispatch_normalized_group_value(obj->user_data.groupid, obj, val, HASP_EVENT_OFF, HASP_EVENT_ON); - - } else if(event == LV_EVENT_DELETE) { - LOG_VERBOSE(TAG_HASP, F(D_OBJECT_DELETED)); - hasp_object_delete(obj); - } -} - -/** - * Called when a range value has changed - * @param obj pointer to a dropdown list or roller - * @param event type of event that occured - */ -static void selector_event_handler(lv_obj_t* obj, lv_event_t event) -{ - log_event("selector", event); - - if(event == LV_EVENT_VALUE_CHANGED) { - char buffer[128]; - char property[36]; - uint16_t val = 0; - uint16_t max = 0; - hasp_update_sleep_state(); // wakeup? - - switch(obj->user_data.objid) { - case LV_HASP_DROPDOWN: - val = lv_dropdown_get_selected(obj); - max = lv_dropdown_get_option_cnt(obj) - 1; - lv_dropdown_get_selected_str(obj, buffer, sizeof(buffer)); - break; - - case LV_HASP_ROLLER: - val = lv_roller_get_selected(obj); - max = lv_roller_get_option_cnt(obj) - 1; - lv_roller_get_selected_str(obj, buffer, sizeof(buffer)); - break; - - case LV_HASP_BTNMATRIX: { - val = lv_btnmatrix_get_active_btn(obj); - const char* txt = lv_btnmatrix_get_btn_text(obj, val); - strncpy(buffer, txt, sizeof(buffer)); - break; - } - - case LV_HASP_TABLE: { - uint16_t row; - uint16_t col; - if(lv_table_get_pressed_cell(obj, &row, &col) != LV_RES_OK) return; // outside any cell - - const char* txt = lv_table_get_cell_value(obj, row, col); - strncpy(buffer, txt, sizeof(buffer)); - - snprintf_P(property, sizeof(property), PSTR("row\":%d,\"col\":%d,\"text"), row, col); - hasp_send_obj_attribute_str(obj, property, buffer); - return; - } - - default: - return; - } - - // set the property - // snprintf_P(property, sizeof(property), PSTR("val\":%d,\"text"), val); - // hasp_send_obj_attribute_str(obj, property, buffer); - - dispatch_object_selection_changed(obj, val, buffer); - if(max > 0) dispatch_normalized_group_value(obj->user_data.groupid, obj, val, 0, max); - - } else if(event == LV_EVENT_DELETE) { - LOG_VERBOSE(TAG_HASP, F(D_OBJECT_DELETED)); - hasp_object_delete(obj); - } -} - -/** - * Called when a slider or adjustable arc is clicked - * @param obj pointer to a slider - * @param event type of event that occured - */ -void slider_event_handler(lv_obj_t* obj, lv_event_t event) -{ - log_event("slider", event); - - uint16_t evt; - switch(event) { - case LV_EVENT_VALUE_CHANGED: - break; - - case LV_EVENT_DELETE: - LOG_VERBOSE(TAG_HASP, F(D_OBJECT_DELETED)); - hasp_object_delete(obj); - break; - - case LV_EVENT_PRESSED: - hasp_update_sleep_state(); // wakeup on press down? - evt = HASP_EVENT_DOWN; - case LV_EVENT_LONG_PRESSED_REPEAT: - if(event == LV_EVENT_LONG_PRESSED_REPEAT) evt = HASP_EVENT_CHANGED; - case LV_EVENT_RELEASED: { - if(event == LV_EVENT_RELEASED) evt = HASP_EVENT_UP; - - // case LV_EVENT_PRESSED || LV_EVENT_LONG_PRESSED_REPEAT || LV_EVENT_RELEASED - int16_t val; - int16_t min; - int16_t max; - - if(obj->user_data.objid == LV_HASP_SLIDER) { - val = lv_slider_get_value(obj); - min = lv_slider_get_min_value(obj); - max = lv_slider_get_max_value(obj); - } else if(obj->user_data.objid == LV_HASP_ARC) { - val = lv_arc_get_value(obj); - min = lv_arc_get_min_value(obj); - max = lv_arc_get_max_value(obj); - } else { - return; - } - - if((event == LV_EVENT_LONG_PRESSED_REPEAT && last_value_sent != val) || - event != LV_EVENT_LONG_PRESSED_REPEAT) { - last_value_sent = val; - dispatch_object_val_event(obj, evt, val); - dispatch_normalized_group_value(obj->user_data.groupid, obj, val, min, max); - } - break; - } - - default: - // LOG_VERBOSE(TAG_HASP, F("Event ID: %d"), event); - ; - } -} - -/** - * Called when a color picker is clicked - * @param obj pointer to a color picker - * @param event type of event that occured - */ -static void cpicker_event_handler(lv_obj_t* obj, lv_event_t event) -{ - char color[6]; - snprintf_P(color, sizeof(color), PSTR("color")); - log_event("cpicker", event); - - if(event == LV_EVENT_VALUE_CHANGED) { - hasp_update_sleep_state(); // wakeup? - // hasp_send_obj_attribute_color(obj, color, lv_cpicker_get_color(obj)); - dispatch_object_color_changed(obj, lv_cpicker_get_color(obj)); - - } else if(event == LV_EVENT_DELETE) { - LOG_VERBOSE(TAG_HASP, F(D_OBJECT_DELETED)); - hasp_object_delete(obj); + snprintf_P(payload, sizeof(payload), PSTR("{\"%s\":\"#%02x%02x%02x\",\"r\":%d,\"g\":%d,\"b\":%d}"), attribute, + c32.ch.red, c32.ch.green, c32.ch.blue, c32.ch.red, c32.ch.green, c32.ch.blue); + dispatch_state_object(pageid, objid, payload); } } @@ -1181,24 +789,3 @@ void hasp_new_object(const JsonObject& config, uint8_t& saved_page_id) hasp_parse_json_attributes(obj, config); } - -void hasp_object_delete(lv_obj_t* obj) -{ - switch(obj->user_data.objid) { - case LV_HASP_LINE: - line_clear_points(obj); - break; - - case LV_HASP_BTNMATRIX: - my_btnmatrix_map_clear(obj); - _LV_WIN_PART_REAL_LAST; - _LV_WIN_PART_VIRTUAL_LAST; - break; - - case LV_HASP_GAUGE: - break; - } - - // TODO: delete value_str data for ALL parts - my_obj_set_value_str_txt(obj, LV_OBJ_PART_MAIN, LV_STATE_DEFAULT, NULL); -} diff --git a/src/hasp/hasp_object.h b/src/hasp/hasp_object.h index 3a3c5c86..cbff7266 100644 --- a/src/hasp/hasp_object.h +++ b/src/hasp/hasp_object.h @@ -69,7 +69,6 @@ bool hasp_find_id_from_obj(lv_obj_t* obj, uint8_t* pageid, uint8_t* objid); const char* get_obj_type_name(lv_obj_t* obj); bool check_obj_type(lv_obj_t* obj, lv_hasp_obj_type_t haspobjtype); void hasp_object_tree(lv_obj_t* parent, uint8_t pageid, uint16_t level); -void hasp_object_delete(lv_obj_t* obj); 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); @@ -78,12 +77,6 @@ void hasp_process_attribute(uint8_t pageid, uint8_t objid, const char* attr, con void object_set_normalized_group_value(uint8_t groupid, lv_obj_t* src_obj, int16_t val, int16_t min, int16_t max); -void wakeup_event_handler(lv_obj_t* obj, lv_event_t event); -void page_event_handler(lv_obj_t* obj, lv_event_t event); -void generic_event_handler(lv_obj_t* obj, lv_event_t event); -void toggle_event_handler(lv_obj_t* obj, lv_event_t event); -void slider_event_handler(lv_obj_t* obj, lv_event_t event); - #define HASP_OBJ_BAR 1971 #define HASP_OBJ_BTN 3164 #define HASP_OBJ_CPICKER 3313 diff --git a/src/hasp/hasp_parser.cpp b/src/hasp/hasp_parser.cpp index 10336a42..658b2e6b 100644 --- a/src/hasp/hasp_parser.cpp +++ b/src/hasp/hasp_parser.cpp @@ -85,4 +85,59 @@ bool Parser::haspPayloadToColor(const char* payload, lv_color32_t& color) #endif return false; /* Color not found */ +} + +// Map events to either ON or OFF (UP or DOWN) +bool Parser::get_event_state(uint8_t eventid) +{ + switch(eventid) { + case HASP_EVENT_ON: + case HASP_EVENT_DOWN: + case HASP_EVENT_LONG: + case HASP_EVENT_HOLD: + return true; + // case HASP_EVENT_OFF: + // case HASP_EVENT_UP: + // case HASP_EVENT_SHORT: + // case HASP_EVENT_DOUBLE: + // case HASP_EVENT_LOST: + default: + return false; + } +} + +// Map events to their description string +void Parser::get_event_name(uint8_t eventid, char* buffer, size_t size) +{ + switch(eventid) { + case HASP_EVENT_ON: + memcpy_P(buffer, PSTR("on"), size); + break; + case HASP_EVENT_OFF: + memcpy_P(buffer, PSTR("off"), size); + break; + case HASP_EVENT_UP: + memcpy_P(buffer, PSTR("up"), size); + break; + case HASP_EVENT_DOWN: + memcpy_P(buffer, PSTR("down"), size); + break; + case HASP_EVENT_SHORT: + memcpy_P(buffer, PSTR("short"), size); + break; + case HASP_EVENT_LONG: + memcpy_P(buffer, PSTR("long"), size); + break; + case HASP_EVENT_HOLD: + memcpy_P(buffer, PSTR("hold"), size); + break; + case HASP_EVENT_LOST: + memcpy_P(buffer, PSTR("lost"), size); + break; + case HASP_EVENT_CHANGED: + memcpy_P(buffer, PSTR("changed"), size); + break; + default: + memcpy_P(buffer, PSTR("unknown"), size); + } } \ No newline at end of file diff --git a/src/hasp/hasp_parser.h b/src/hasp/hasp_parser.h index d0697a17..2550d74b 100644 --- a/src/hasp/hasp_parser.h +++ b/src/hasp/hasp_parser.h @@ -11,6 +11,8 @@ class Parser { public: static bool haspPayloadToColor(const char* payload, lv_color32_t& color); + static bool get_event_state(uint8_t eventid); + static void get_event_name(uint8_t eventid, char* buffer, size_t size); }; /* Named COLOR attributes */ diff --git a/src/hasp_debug.cpp b/src/hasp_debug.cpp index f0a260c1..272fa569 100644 --- a/src/hasp_debug.cpp +++ b/src/hasp_debug.cpp @@ -223,6 +223,10 @@ void debug_get_tag(uint8_t tag, char* buffer) memcpy_P(buffer, PSTR("MSGR"), 5); break; + case TAG_EVENT: + memcpy_P(buffer, PSTR("EVNT"), 5); + break; + case TAG_OOBE: memcpy_P(buffer, PSTR("OOBE"), 5); break; diff --git a/src/hasp_debug.h b/src/hasp_debug.h index 006acb6c..dc1e92c2 100644 --- a/src/hasp_debug.h +++ b/src/hasp_debug.h @@ -152,14 +152,15 @@ bool debugSetConfig(const JsonObject& settings); #endif enum { - TAG_MAIN = 0, - TAG_HASP = 1, - TAG_ATTR = 2, - TAG_MSGR = 3, - TAG_OOBE = 4, - TAG_HAL = 5, - TAG_DRVR = 6, - TAG_DEV = 7, + TAG_MAIN = 0, + TAG_HASP = 1, + TAG_ATTR = 2, + TAG_MSGR = 3, + TAG_OOBE = 4, + TAG_HAL = 5, + TAG_DRVR = 6, + TAG_DEV = 7, + TAG_EVENT = 8, TAG_DEBG = 10, TAG_TELN = 11, diff --git a/src/hasplib.h b/src/hasplib.h index ada7b224..989b53c0 100644 --- a/src/hasplib.h +++ b/src/hasplib.h @@ -3,6 +3,7 @@ #include "hasp/hasp.h" #include "hasp/hasp_attribute.h" #include "hasp/hasp_dispatch.h" +#include "hasp/hasp_event.h" #include "hasp/hasp_object.h" #include "hasp/hasp_page.h" #include "hasp/hasp_parser.h" diff --git a/src/mqtt/hasp_mqtt_ha.cpp b/src/mqtt/hasp_mqtt_ha.cpp index 7257a0bd..59ad7c77 100644 --- a/src/mqtt/hasp_mqtt_ha.cpp +++ b/src/mqtt/hasp_mqtt_ha.cpp @@ -8,6 +8,7 @@ #include "hasp/hasp.h" #include "hasp/hasp_dispatch.h" +#include "hasp/hasp_parser.h" #include "dev/device.h" #include "hasp_mqtt.h" @@ -110,28 +111,28 @@ void mqtt_ha_register_button(uint8_t page, uint8_t id) doc[F("atype")] = "trigger"; // automation_type - dispatch_get_event_name(HASP_EVENT_DOWN, buffer, sizeof(buffer)); + Parser::get_event_name(HASP_EVENT_DOWN, buffer, sizeof(buffer)); doc[F("pl")] = buffer; doc[F("type")] = "button_short_press"; snprintf_P(buffer, sizeof(buffer), PSTR("%s/device_automation/%s/" HASP_OBJECT_NOTATION "_%s/config"), discovery_prefix, haspDevice.get_hostname(), page, id, "short_press"); mqtt_ha_send_json(buffer, doc); - dispatch_get_event_name(HASP_EVENT_SHORT, buffer, sizeof(buffer)); + Parser::get_event_name(HASP_EVENT_SHORT, buffer, sizeof(buffer)); doc[F("pl")] = buffer; doc[F("type")] = "button_short_release"; snprintf_P(buffer, sizeof(buffer), PSTR("%s/device_automation/%s/" HASP_OBJECT_NOTATION "_%s/config"), discovery_prefix, haspDevice.get_hostname(), page, id, "short_release"); mqtt_ha_send_json(buffer, doc); - dispatch_get_event_name(HASP_EVENT_LONG, buffer, sizeof(buffer)); + Parser::get_event_name(HASP_EVENT_LONG, buffer, sizeof(buffer)); doc[F("pl")] = buffer; doc[F("type")] = "button_long_press"; snprintf_P(buffer, sizeof(buffer), PSTR("%s/device_automation/%s/" HASP_OBJECT_NOTATION "_%s/config"), discovery_prefix, haspDevice.get_hostname(), page, id, "long_press"); mqtt_ha_send_json(buffer, doc); - dispatch_get_event_name(HASP_EVENT_UP, buffer, sizeof(buffer)); + Parser::get_event_name(HASP_EVENT_UP, buffer, sizeof(buffer)); doc[F("pl")] = buffer; doc[F("type")] = "button_long_release"; snprintf_P(buffer, sizeof(buffer), PSTR("%s/device_automation/%s/" HASP_OBJECT_NOTATION "_%s/config"), diff --git a/src/sys/gpio/hasp_gpio.cpp b/src/sys/gpio/hasp_gpio.cpp index 31762e7c..88342306 100644 --- a/src/sys/gpio/hasp_gpio.cpp +++ b/src/sys/gpio/hasp_gpio.cpp @@ -4,13 +4,10 @@ #include "AceButton.h" #include "lv_conf.h" // For timing defines -#include "hasp_conf.h" +#include "hasplib.h" #include "hasp_gpio.h" #include "hasp_config.h" -#include "hasp/hasp_dispatch.h" -#include "hasp/hasp.h" - #ifdef ARDUINO_ARCH_ESP8266 #define INPUT_PULLDOWN INPUT #endif @@ -88,7 +85,7 @@ static void gpio_event_handler(AceButton* button, uint8_t eventType, uint8_t but eventid = HASP_EVENT_LOST; } - dispatch_gpio_input_event(gpioConfig[btnid].pin, gpioConfig[btnid].group, eventid); + event_gpio_input(gpioConfig[btnid].pin, gpioConfig[btnid].group, eventid); if(eventid != HASP_EVENT_LONG) // do not repeat DOWN + LONG dispatch_normalized_group_value(gpioConfig[btnid].group, NULL, state, HASP_EVENT_OFF, HASP_EVENT_ON); } @@ -290,11 +287,15 @@ void gpio_set_normalized_value(hasp_gpio_config_t gpio, int16_t val, int16_t min case HASP_GPIO_RELAY: gpio.val = val > min ? HIGH : LOW; digitalWrite(gpio.pin, gpio.val); + dispatch_gpio_output_value("relay", gpio.pin, gpio.val); break; + case HASP_GPIO_RELAY_INVERTED: gpio.val = val > min ? LOW : HIGH; digitalWrite(gpio.pin, gpio.val); + dispatch_gpio_output_value("relay", gpio.pin, gpio.val); break; + case HASP_GPIO_LED: case HASP_GPIO_LED_R: case HASP_GPIO_LED_G: @@ -306,16 +307,9 @@ void gpio_set_normalized_value(hasp_gpio_config_t gpio, int16_t val, int16_t min gpio.val = map(val, min, max, 0, 1023); analogWrite(gpio.pin, gpio.val); #endif + dispatch_gpio_output_value("led", gpio.pin, gpio.val); break; - case HASP_GPIO_PWM: -#if defined(ARDUINO_ARCH_ESP32) - gpio.val = map(val, min, max, 0, 4095); - ledcWrite(gpio.group, gpio.val); // ledChannel and value -#else - gpio.val = map(val, min, max, 0, 1023); - analogWrite(gpio.pin, gpio.val); -#endif - break; + case HASP_GPIO_LED_INVERTED: case HASP_GPIO_LED_R_INVERTED: case HASP_GPIO_LED_G_INVERTED: @@ -328,6 +322,18 @@ void gpio_set_normalized_value(hasp_gpio_config_t gpio, int16_t val, int16_t min gpio.val = map(val, min, max, 0, 1023); analogWrite(gpio.pin, gpio.val); #endif + dispatch_gpio_output_value("led", gpio.pin, gpio.val); + break; + + case HASP_GPIO_PWM: +#if defined(ARDUINO_ARCH_ESP32) + gpio.val = map(val, min, max, 0, 4095); + ledcWrite(gpio.group, gpio.val); // ledChannel and value +#else + gpio.val = map(val, min, max, 0, 1023); + analogWrite(gpio.pin, gpio.val); +#endif + dispatch_gpio_output_value("pwm", gpio.pin, gpio.val); break; default: @@ -352,7 +358,7 @@ void gpio_set_normalized_group_value(uint8_t groupid, int16_t val, int16_t min, return; } - // bool state = dispatch_get_event_state(eventid); + // bool state = Parser::get_event_state(eventid); for(uint8_t i = 0; i < HASP_NUM_GPIO_CONFIG; i++) { if(gpioConfig[i].group == groupid) { gpio_set_normalized_value(gpioConfig[i], val, min, max); @@ -386,7 +392,7 @@ void gpio_set_moodlight(uint8_t r, uint8_t g, uint8_t b) // not used // void gpio_set_gpio_value(uint8_t pin, uint16_t state) // { -// // bool state = dispatch_get_event_state(eventid); +// // bool state = Parser::get_event_state(eventid); // for(uint8_t i = 0; i < HASP_NUM_GPIO_CONFIG; i++) { // if(gpioConfig[i].pin == pin) { // gpio_set_value(gpioConfig[i], state);