Refactor event dispatching

This commit is contained in:
fvanroie 2020-12-15 21:08:56 +01:00
parent 7c9bfe573c
commit 262567c450
10 changed files with 218 additions and 204 deletions

View File

@ -511,21 +511,6 @@ void haspSetPage(uint8_t pageid)
}
}
// TODO make this a recursicee function
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_parent_id(get_page_obj(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 haspLoadPage(const char * pages)
{
#if HASP_USE_SPIFFS > 0 || HASP_USE_LITTLEFS > 0

View File

@ -49,8 +49,6 @@ void haspClearPage(uint16_t pageid);
void haspGetVersion(char* version,size_t len);
//void haspBackground(uint16_t pageid, uint16_t imageid);
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 haspProgressVal(uint8_t val);

View File

@ -21,6 +21,7 @@ uint8_t nCommands = 0;
haspCommand_t commands[16];
static void dispatch_config(const char * topic, const char * payload);
static void dispatch_group_state(uint8_t groupid, uint8_t eventid, lv_obj_t * obj);
bool is_true(const char * s)
{
@ -64,22 +65,6 @@ bool dispatch_factory_reset()
return formated && erased;
}
void dispatchGpioOutput(int groupid, bool state)
{
if(groupid >= 0) {
Log.notice(TAG_MSGR, F("GROUP %d OUTPUT STATE %d"), groupid, state);
gpio_set_group_outputs(groupid, state ? HASP_EVENT_ON : HASP_EVENT_OFF);
}
}
void dispatchGpioOutput(String strTopic, const char * payload)
{
String strTemp((char *)0);
strTemp.reserve(128);
strTemp = strTopic.substring(6, strTopic.length());
dispatchGpioOutput(strTemp.toInt(), is_true(payload));
}
// p[x].b[y].attr=value
inline void dispatch_process_button_attribute(String strTopic, const char * payload)
{
@ -125,7 +110,8 @@ void dispatch_command(const char * topic, const char * payload)
/* =============================== Not standard payload commands ===================================== */
if(strlen(topic) == 7 && topic == strstr_P(topic, PSTR("output"))) {
dispatchGpioOutput(topic, payload);
dispatch_group_state(atoi(topic + 6), is_true(payload) ? HASP_EVENT_ON : HASP_EVENT_OFF,
NULL); // + 6 => trim 'output' from the topic
// } else if(strcasecmp_P(topic, PSTR("screenshot")) == 0) {
// guiTakeScreenshot("/screenshot.bmp"); // Literal String
@ -259,96 +245,6 @@ void dispatch_output_idle_state(uint8_t state)
#endif
}
void dispatch_button(uint8_t id, const char * event)
{
#if !defined(HASP_USE_MQTT) && !defined(HASP_USE_TASMOTA_SLAVE)
Log.notice(TAG_MSGR, F("input%d = %s"), id, event);
#else
#if HASP_USE_MQTT > 0
mqtt_send_input(id, event);
#endif
#if HASP_USE_TASMOTA_SLAVE > 0
slave_send_input(id, event);
#endif
#endif
}
// 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;
default:
memcpy_P(buffer, PSTR("UNKNOWN"), size);
}
}
void dispatch_send_group_event(uint8_t groupid, uint8_t eventid, bool update_hasp)
{
// update outputs
gpio_set_group_outputs(groupid, eventid);
char payload[8];
dispatch_get_event_name(eventid, payload, sizeof(payload));
// send out value
#if !defined(HASP_USE_MQTT) && !defined(HASP_USE_TASMOTA_SLAVE)
Log.notice(TAG_MSGR, F("group%d = %s"), groupid, payload);
#else
#if HASP_USE_MQTT > 0
mqtt_send_input(groupid, payload);
#endif
#if HASP_USE_TASMOTA_SLAVE > 0
slave_send_input(groupid, payload);
#endif
#endif
// update objects, except src_obj
if(update_hasp) hasp_set_group_objects(groupid, eventid, NULL);
}
void IRAM_ATTR dispatch_send_obj_attribute_str(uint8_t pageid, uint8_t btnid, const char * attribute, const char * data)
{
#if !defined(HASP_USE_MQTT) && !defined(HASP_USE_TASMOTA_SLAVE)
@ -363,20 +259,6 @@ void IRAM_ATTR dispatch_send_obj_attribute_str(uint8_t pageid, uint8_t btnid, co
#endif
}
void dispatch_send_object_event(uint8_t pageid, uint8_t objid, uint8_t eventid)
{
if(objid < 100) {
char topic[8];
char payload[8];
snprintf_P(topic, sizeof(topic), PSTR("event"));
dispatch_get_event_name(eventid, payload, sizeof(payload));
dispatch_send_obj_attribute_str(pageid, objid, topic, payload);
} else {
uint8_t groupid = (objid - 100) / 10;
dispatch_send_group_event(groupid, eventid, true);
}
}
// send return output back to the client
void IRAM_ATTR dispatch_obj_attribute_str(uint8_t pageid, uint8_t btnid, const char * attribute, const char * data)
{
@ -490,6 +372,137 @@ static void dispatch_config(const char * topic, const char * payload)
}
}
/********************************************** 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
static 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;
default:
memcpy_P(buffer, PSTR("UNKNOWN"), size);
}
}
void dispatch_gpio_event(uint8_t pin, uint8_t group, uint8_t eventid)
{
dispatch_group_state(group, dispatch_get_event_state(eventid), NULL);
char payload[8];
dispatch_get_event_name(eventid, payload, sizeof(payload));
#if !defined(HASP_USE_MQTT) && !defined(HASP_USE_TASMOTA_SLAVE)
Log.notice(TAG_MSGR, F("gpio%d = %s"), id, event);
#else
#if HASP_USE_MQTT > 0
mqtt_send_gpio_event(pin, group, payload);
#endif
#if HASP_USE_TASMOTA_SLAVE > 0
slave_send_input(pin, event);
#endif
#endif
}
void dispatch_object_event(lv_obj_t * obj, uint8_t eventid)
{
char topic[8];
char payload[8];
uint8_t pageid, objid;
snprintf_P(topic, sizeof(topic), PSTR("event"));
dispatch_get_event_name(eventid, payload, sizeof(payload));
if(hasp_find_id_from_obj(obj, &pageid, &objid)) {
dispatch_send_obj_attribute_str(pageid, objid, topic, payload);
}
if(obj->user_data.groupid > 0) {
dispatch_group_state(obj->user_data.groupid, eventid, obj);
}
}
/********************************************** Output Events ******************************************/
// void dispatch_group_event(uint8_t groupid, uint8_t eventid)
// {
// // update outputs
// gpio_set_group_state(groupid, eventid);
// char payload[8];
// dispatch_get_event_name(eventid, payload, sizeof(payload));
// // send out value
// #if !defined(HASP_USE_MQTT) && !defined(HASP_USE_TASMOTA_SLAVE)
// Log.notice(TAG_MSGR, F("group%d = %s"), groupid, payload);
// #else
// #if HASP_USE_MQTT > 0
// mqtt_send_input(groupid, payload);
// #endif
// #if HASP_USE_TASMOTA_SLAVE > 0
// slave_send_input(groupid, payload);
// #endif
// #endif
// // update objects, except src_obj
// // if(update_hasp)
// }
void dispatch_group_state(uint8_t groupid, uint8_t eventid, lv_obj_t * obj)
{
char payload[8];
dispatch_get_event_name(eventid, payload, sizeof(payload));
Log.notice(TAG_MSGR, F("GROUP %d => OUTPUT EVENT: %s"), groupid, payload);
if(groupid >= 0) {
gpio_set_group_state(groupid, eventid);
object_set_group_state(groupid, eventid, obj);
}
}
// void dispatch_group_state(const char * group_str, const char * payload)
// {
// dispatch_group_state(atoi(group_str), is_true(payload));
// }
/********************************************** Native Commands ****************************************/
void dispatch_parse_json(const char *, const char * payload)

View File

@ -46,10 +46,8 @@ void dispatch_output_idle_state(uint8_t state);
void dispatch_output_statusupdate(void);
void dispatch_output_current_page();
void dispatch_button(uint8_t id, const char * event);
void dispatch_send_object_event(uint8_t pageid, uint8_t objid, uint8_t eventid);
void dispatch_send_group_event(uint8_t groupid, uint8_t eventid, bool update_hasp);
void dispatch_gpio_event(uint8_t pin, uint8_t group, uint8_t eventid);
void dispatch_object_event(lv_obj_t * obj, uint8_t eventid);
bool dispatch_get_event_state(uint8_t eventid);
bool is_true(const char * s);

View File

@ -46,40 +46,32 @@ TouchConfig touchConfig();
static void gpio_event_handler(AceButton * button, uint8_t eventType, uint8_t buttonState)
{
uint8_t btnid = button->getId();
uint8_t eventid;
char buffer[16];
switch(eventType) {
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 AceButton::kEventLongPressed:
eventid = HASP_EVENT_LONG;
memcpy_P(buffer, PSTR("LONG"), sizeof(buffer));
break;
case AceButton::kEventRepeatPressed:
// return; // Fix needed for switches
eventid = HASP_EVENT_HOLD;
memcpy_P(buffer, PSTR("HOLD"), sizeof(buffer));
break;
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(gpioConfig[button->getId()].group, buffer);
dispatch_send_group_event(gpioConfig[button->getId()].group, eventid, true);
dispatch_gpio_event(gpioConfig[btnid].pin, gpioConfig[btnid].group, eventid);
}
void aceButtonSetup(void)
@ -90,7 +82,7 @@ void aceButtonSetup(void)
// Features
buttonConfig->setFeature(ButtonConfig::kFeatureClick);
buttonConfig->setFeature(ButtonConfig::kFeatureLongPress);
buttonConfig->setFeature(ButtonConfig::kFeatureRepeatPress);
// buttonConfig->setFeature(ButtonConfig::kFeatureRepeatPress);
// buttonConfig->setFeature(ButtonConfig::kFeatureDoubleClick);
// buttonConfig->setFeature(ButtonConfig::kFeatureSuppressClickBeforeDoubleClick);
@ -123,14 +115,14 @@ void gpioAddButton(uint8_t pin, uint8_t input_mode, uint8_t default_state, uint8
// button[i]->init(pin, default_state, index);
if(button[i]) {
pinMode(pin, input_mode);
//pinMode(pin, input_mode);
ButtonConfig * buttonConfig = button[i]->getButtonConfig();
buttonConfig->setEventHandler(gpio_event_handler);
buttonConfig->setFeature(ButtonConfig::kFeatureClick);
buttonConfig->clearFeature(ButtonConfig::kFeatureDoubleClick);
buttonConfig->setFeature(ButtonConfig::kFeatureLongPress);
buttonConfig->clearFeature(ButtonConfig::kFeatureRepeatPress);
//buttonConfig->clearFeature(ButtonConfig::kFeatureRepeatPress);
buttonConfig->clearFeature(
ButtonConfig::kFeatureSuppressClickBeforeDoubleClick); // Causes annoying pauses
@ -202,6 +194,7 @@ void gpioSetup()
case HASP_GPIO_SWITCH:
case HASP_GPIO_BUTTON:
gpioAddButton(gpioConfig[i].pin, input_mode, HIGH, i);
pinMode(gpioConfig[i].pin, INPUT_PULLUP);
break;
case HASP_GPIO_SWITCH_INVERTED:
case HASP_GPIO_BUTTON_INVERTED:
@ -230,37 +223,53 @@ void gpioSetup()
}
}
void gpio_set_group_outputs(uint8_t groupid, uint8_t eventid)
void gpio_set_state(hasp_gpio_config_t gpio, bool state)
{
switch(gpio.type) {
case HASP_GPIO_RELAY:
case HASP_GPIO_LED:
digitalWrite(gpio.pin, state ? HIGH : LOW);
break;
case HASP_GPIO_RELAY_INVERTED:
case HASP_GPIO_LED_INVERTED:
digitalWrite(gpio.pin, state ? LOW : HIGH);
break;
#if defined(ARDUINO_ARCH_ESP32)
case HASP_GPIO_PWM:
ledcWrite(gpio.group, map(state, 0, 1, 0, 1023)); // ledChannel and value
break;
case HASP_GPIO_PWM_INVERTED:
ledcWrite(gpio.group, map(!state, 0, 1, 0, 1023)); // ledChannel and value
break;
#else
case HASP_GPIO_PWM:
analogWrite(gpio.pin, map(state, 0, 1, 0, 1023));
break;
case HASP_GPIO_PWM_INVERTED:
analogWrite(gpio.pin, map(!state, 0, 1, 0, 1023));
break;
#endif
default:;
}
}
void gpio_set_group_state(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:;
}
gpio_set_state(gpioConfig[i], state);
}
}
}
void gpio_set_gpio_state(uint8_t pin, uint8_t eventid)
{
bool state = dispatch_get_event_state(eventid);
for(uint8_t i = 0; i < HASP_NUM_GPIO_CONFIG; i++) {
if(gpioConfig[i].pin == pin) {
gpio_set_state(gpioConfig[i], state);
return;
}
}
}

View File

@ -20,7 +20,9 @@ struct hasp_gpio_config_t
void gpioSetup(void);
void IRAM_ATTR gpioLoop(void);
void gpio_set_group_outputs(uint8_t groupid, uint8_t eventid);
void gpio_set_group_state(uint8_t groupid, uint8_t eventid);
void gpio_set_gpio_state(uint8_t pin, uint8_t eventid);
bool gpioSavePinConfig(uint8_t config_num, uint8_t pin, uint8_t type, uint8_t group, uint8_t pinfunc);
bool gpioIsSystemPin(uint8_t gpio);

View File

@ -165,21 +165,11 @@ void IRAM_ATTR mqtt_send_state(const __FlashStringHelper * subtopic, const char
// Log.notice(TAG_MQTT_PUB, F("%sstate/%S = %s"), mqttNodeTopic, subtopic, payload);
}
void mqtt_send_input(uint8_t id, const char * payload)
void mqtt_send_gpio_event(uint8_t pin, uint8_t group, const char * event)
{
// Log.verbose(TAG_MQTT,F("TST: %sstate/input%u = %s"), mqttNodeTopic, id, payload); // to be removed
// if(mqttIsConnected()) {
char tmp_topic[strlen(mqttNodeTopic) + 20];
snprintf_P(tmp_topic, sizeof(tmp_topic), PSTR("%sstate/input%u"), mqttNodeTopic, id);
bool res = mqttPublish(tmp_topic, payload);
mqttResult(res, tmp_topic, payload);
// } else {
// return mqtt_log_no_connection();
// }
// Log after char buffers are cleared
// Log.notice(TAG_MQTT_PUB, F("%sstate/input%u = %s"), mqttNodeTopic, id, payload);
char payload[64];
snprintf_P(payload, sizeof(payload), PSTR("{\"pin\":%d,\"group\":%d,\"event\":\"%s\"}"), pin, group, event);
mqtt_send_state(F("input"), payload);
}
void IRAM_ATTR mqtt_send_obj_attribute_str(uint8_t pageid, uint8_t btnid, const char * attribute, const char * data)

View File

@ -13,7 +13,7 @@ void mqttStart();
void mqttStop();
void IRAM_ATTR mqtt_send_state(const __FlashStringHelper * subtopic, const char * payload);
void mqtt_send_input(uint8_t id, const char * payload);
void mqtt_send_gpio_event(uint8_t pin,uint8_t group, const char * event);
void IRAM_ATTR mqtt_send_obj_attribute_str(uint8_t pageid, uint8_t btnid, const char * attribute, const char * data);
void mqtt_send_statusupdate(void);

View File

@ -311,8 +311,8 @@ void IRAM_ATTR btn_event_handler(lv_obj_t * obj, lv_event_t event)
return;
}
guiCheckSleep(); // wakeup?
dispatch_send_object_event(haspGetPage(), (uint8_t)obj->user_data.id, eventid);
guiCheckSleep(); // wakeup?
dispatch_object_event(obj, eventid); // send object event
}
/**
@ -446,6 +446,23 @@ static void roller_event_handler(lv_obj_t * obj, lv_event_t event)
}
}
// ##################### State Changers ########################################################
// TODO make this a recursive function that goes over all objects only ONCE
void object_set_group_state(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_parent_id(get_page_obj(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);
}
}
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////
// Used in the dispatcher & hasp_new_object
@ -458,7 +475,7 @@ void hasp_process_attribute(uint8_t pageid, uint8_t objid, const char * attr, co
}
}
// ##################### Obhject Creator ########################################################
// ##################### Object Creator ########################################################
/**
* Create a new object according to the json config
@ -623,11 +640,11 @@ void hasp_new_object(const JsonObject & config, uint8_t & saved_page_id)
if(obj) {
lv_obj_t * tab;
tab = lv_tabview_add_tab(obj, "tab 1");
//lv_obj_set_user_data(tab, id + 1);
// lv_obj_set_user_data(tab, id + 1);
tab = lv_tabview_add_tab(obj, "tab 2");
//lv_obj_set_user_data(tab, id + 2);
// lv_obj_set_user_data(tab, id + 2);
tab = lv_tabview_add_tab(obj, "tab 3");
//lv_obj_set_user_data(tab, id + 3);
// lv_obj_set_user_data(tab, id + 3);
}
break;
}

View File

@ -62,6 +62,8 @@ void hasp_send_obj_attribute_int(lv_obj_t * obj, const char * attribute, int32_t
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 object_set_group_state(uint8_t groupid, uint8_t eventid, lv_obj_t * src_obj);
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);
void wakeup_event_handler(lv_obj_t * obj, lv_event_t event);