Allow gpio PWM

This commit is contained in:
fvanroie 2021-01-23 01:32:52 +01:00
parent 6a29167c50
commit 7ca86b59bb
10 changed files with 555 additions and 384 deletions

View File

@ -4,6 +4,8 @@
#ifndef HASP_H
#define HASP_H
#define NORMALIZE(a, b, c) map(a, b, c, 0, 0xFFFFU)
#include <Arduino.h>
#include "lvgl.h"
#include "hasp_conf.h"

View File

@ -260,16 +260,16 @@ lv_chart_series_t * my_chart_get_series(lv_obj_t * chart, uint8_t ser_num)
*/
void my_obj_set_value_str_txt(lv_obj_t * obj, uint8_t part, lv_state_t state, const char * text)
{
// Log.verbose(TAG_ATTR, "%s %d", __FILE__, __LINE__);
// Log.verbose(TAG_ATTR, F("%s %d"), __FILE__, __LINE__);
const void * value_str_p = lv_obj_get_style_value_str(obj, part);
lv_obj_invalidate(obj);
if(text == NULL || text[0] == 0) {
Log.verbose(TAG_ATTR, "%s %d", __FILE__, __LINE__);
// Log.verbose(TAG_ATTR, F("%s %d"), __FILE__, __LINE__);
lv_obj_set_style_local_value_str(obj, part, state, NULL);
lv_mem_free(value_str_p);
Log.verbose(TAG_ATTR, "%s %d", __FILE__, __LINE__);
// Log.verbose(TAG_ATTR, F("%s %d"), __FILE__, __LINE__);
return;
}
@ -280,15 +280,15 @@ void my_obj_set_value_str_txt(lv_obj_t * obj, uint8_t part, lv_state_t state, co
size_t len = strlen(text) + 1;
/*Allocate space for the new text*/
// Log.verbose(TAG_ATTR, "%s %d", __FILE__, __LINE__);
// Log.verbose(TAG_ATTR, F("%s %d"), __FILE__, __LINE__);
value_str_p = (char *)lv_mem_alloc(len);
LV_ASSERT_MEM(value_str_p);
if(value_str_p == NULL) return;
// Log.verbose(TAG_ATTR, "%s %d", __FILE__, __LINE__);
// Log.verbose(TAG_ATTR, F("%s %d"), __FILE__, __LINE__);
strncpy((char *)value_str_p, text, len);
lv_obj_set_style_local_value_str(obj, part, state, (char *)value_str_p);
Log.verbose(TAG_ATTR, "%s %d", __FILE__, __LINE__);
// Log.verbose(TAG_ATTR, F("%s %d"), __FILE__, __LINE__);
return;
}
@ -306,10 +306,10 @@ void my_obj_set_value_str_txt(lv_obj_t * obj, uint8_t part, lv_state_t state, co
} else {
/*Free the old text*/
if(value_str_p != NULL) {
// Log.verbose(TAG_ATTR, "%s %d", __FILE__, __LINE__);
// Log.verbose(TAG_ATTR, F("%s %d"), __FILE__, __LINE__);
lv_mem_free(value_str_p);
value_str_p = NULL;
// Log.verbose(TAG_ATTR, "%s %d", __FILE__, __LINE__);
// Log.verbose(TAG_ATTR, F("%s %d"), __FILE__, __LINE__);
}
/*Get the size of the text*/
@ -322,7 +322,7 @@ void my_obj_set_value_str_txt(lv_obj_t * obj, uint8_t part, lv_state_t state, co
lv_obj_set_style_local_value_str(obj, part, state, (char *)value_str_p);
}
// Log.verbose(TAG_ATTR, "%s %d", __FILE__, __LINE__);
// Log.verbose(TAG_ATTR, F("%s %d"), __FILE__, __LINE__);
}
void my_btnmatrix_map_clear(lv_obj_t * obj)
@ -342,11 +342,11 @@ void my_btnmatrix_map_clear(lv_obj_t * obj)
Log.verbose(TAG_ATTR, "%s %d %x", __FILE__, __LINE__, map_p_tmp); // label pointer array block
lv_btnmatrix_set_map(obj, btnmatrix_default_map); // reset to default btnmap pointer
Log.verbose(TAG_ATTR, "%s %d", __FILE__, __LINE__);
Log.verbose(TAG_ATTR, F("%s %d"), __FILE__, __LINE__);
lv_mem_free(*map_p_tmp); // free label buffer reserved as a contiguous block
Log.verbose(TAG_ATTR, "%s %d", __FILE__, __LINE__);
Log.verbose(TAG_ATTR, F("%s %d"), __FILE__, __LINE__);
lv_mem_free(map_p_tmp); // free label pointer array block
Log.verbose(TAG_ATTR, "%s %d", __FILE__, __LINE__);
Log.verbose(TAG_ATTR, F("%s %d"), __FILE__, __LINE__);
}
}
@ -389,13 +389,13 @@ static void my_btnmatrix_map_create(lv_obj_t * obj, const char * payload)
memset(buffer_addr, 0, tot_len); // Important, last index needs to be 0 => empty string ""
/* Point of no return, destroy & free the previous map */
Log.verbose(TAG_ATTR, "%s %d map addr: %x", __FILE__, __LINE__, map_data_str);
Log.verbose(TAG_ATTR, F("%s %d map addr: %x"), __FILE__, __LINE__, map_data_str);
my_btnmatrix_map_clear(obj); // Free previous map
// Fill buffer
size_t index = 0;
size_t pos = 0;
Log.verbose(TAG_ATTR, "%s %d lbl addr: %x", __FILE__, __LINE__, buffer_addr);
Log.verbose(TAG_ATTR, F("%s %d lbl addr: %x"), __FILE__, __LINE__, buffer_addr);
for(JsonVariant btn : arr) {
size_t len = btn.as<String>().length() + 1;
Log.verbose(TAG_ATTR, F(" * Adding button: %s (%d bytes) %x"), btn.as<String>().c_str(), len,
@ -406,9 +406,9 @@ static void my_btnmatrix_map_create(lv_obj_t * obj, const char * payload)
}
map_data_str[index] = buffer_addr + pos; // save pointer to the last \0 byte
Log.verbose(TAG_ATTR, "%s %d", __FILE__, __LINE__);
Log.verbose(TAG_ATTR, F("%s %d"), __FILE__, __LINE__);
lv_btnmatrix_set_map(obj, map_data_str);
Log.verbose(TAG_ATTR, "%s %d", __FILE__, __LINE__);
Log.verbose(TAG_ATTR, F("%s %d"), __FILE__, __LINE__);
}
void line_clear_points(lv_obj_t * obj)
@ -497,140 +497,155 @@ static bool haspPayloadToColor(const char * payload, lv_color_t & color)
uint8_t G8 = (G6 * 259 + 33) >> 6;
uint8_t B8 = (B5 * 527 + 23) >> 6;
color = lv_color_make(R8, G8, B8);
} else {
/* Named Color Scheme*/
switch(hasp_util_get_sdbm(payload)) {
case ATTR_RED:
color = lv_color_make(0xFF, 0x00, 0x00);
break;
case ATTR_TAN:
color = lv_color_make(0xD2, 0xB4, 0x8C);
break;
case ATTR_BLUE:
color = lv_color_make(0x00, 0x00, 0xFF);
break;
case ATTR_AQUA:
case ATTR_CYAN:
color = lv_color_make(0x00, 0xFF, 0xFF);
break;
case ATTR_GOLD:
color = lv_color_make(0xFF, 0xD7, 0x00);
break;
case ATTR_GRAY:
case ATTR_GREY:
color = lv_color_make(0x80, 0x80, 0x80);
break;
case ATTR_LIME:
color = lv_color_make(0x00, 0xFF, 0x00);
break;
case ATTR_NAVY:
color = lv_color_make(0x00, 0x00, 0x80);
break;
case ATTR_PERU:
color = lv_color_make(0xCD, 0x85, 0x3F);
break;
case ATTR_PINK:
color = lv_color_make(0xFF, 0xC0, 0xCB);
break;
case ATTR_PLUM:
color = lv_color_make(0xDD, 0xA0, 0xDD);
break;
case ATTR_SNOW:
color = lv_color_make(0xFF, 0xFA, 0xFA);
break;
case ATTR_TEAL:
color = lv_color_make(0x00, 0x80, 0x80);
break;
case ATTR_AZURE:
color = lv_color_make(0xF0, 0xFF, 0xFF);
break;
case ATTR_BEIGE:
color = lv_color_make(0xF5, 0xF5, 0xDC);
break;
case ATTR_BLACK:
color = lv_color_make(0x00, 0x00, 0x00);
break;
case ATTR_BLUSH:
color = lv_color_make(0xB0, 0x00, 0x00);
break;
case ATTR_BROWN:
color = lv_color_make(0xA5, 0x2A, 0x2A);
break;
case ATTR_CORAL:
color = lv_color_make(0xFF, 0x7F, 0x50);
break;
case ATTR_GREEN:
color = lv_color_make(0x00, 0x80, 0x00);
break;
case ATTR_IVORY:
color = lv_color_make(0xFF, 0xFF, 0xF0);
break;
case ATTR_KHAKI:
color = lv_color_make(0xF0, 0xE6, 0x8C);
break;
case ATTR_LINEN:
color = lv_color_make(0xFA, 0xF0, 0xE6);
break;
case ATTR_OLIVE:
color = lv_color_make(0x80, 0x80, 0x00);
break;
case ATTR_WHEAT:
color = lv_color_make(0xF5, 0xDE, 0xB3);
break;
case ATTR_WHITE:
color = lv_color_make(0xFF, 0xFF, 0xFF);
break;
case ATTR_BISQUE:
color = lv_color_make(0xFF, 0xE4, 0xC4);
break;
case ATTR_INDIGO:
color = lv_color_make(0x4B, 0x00, 0x82);
break;
case ATTR_MAROON:
color = lv_color_make(0x80, 0x00, 0x00);
break;
case ATTR_ORANGE:
color = lv_color_make(0xFF, 0xA5, 0x00);
break;
case ATTR_ORCHID:
color = lv_color_make(0xDA, 0x70, 0xD6);
break;
case ATTR_PURPLE:
color = lv_color_make(0x80, 0x00, 0x80);
break;
case ATTR_SALMON:
color = lv_color_make(0xFA, 0x80, 0x72);
break;
case ATTR_SIENNA:
color = lv_color_make(0xA0, 0x52, 0x2D);
break;
case ATTR_SILVER:
color = lv_color_make(0xC0, 0xC0, 0xC0);
break;
case ATTR_TOMATO:
color = lv_color_make(0xFF, 0x63, 0x47);
break;
case ATTR_VIOLET:
color = lv_color_make(0xEE, 0x82, 0xEE);
break;
case ATTR_YELLOW:
color = lv_color_make(0xFF, 0xFF, 0x00);
break;
case ATTR_FUCHSIA:
case ATTR_MAGENTA:
color = lv_color_make(0xFF, 0x00, 0xFF);
break;
// switch(hasp_util_get_sdbm(payload)) {
// case ATTR_RED:
// color = lv_color_make(0xFF, 0x00, 0x00);
// break;
// case ATTR_TAN:
// color = lv_color_make(0xD2, 0xB4, 0x8C);
// break;
// case ATTR_BLUE:
// color = lv_color_make(0x00, 0x00, 0xFF);
// break;
// case ATTR_AQUA:
// case ATTR_CYAN:
// color = lv_color_make(0x00, 0xFF, 0xFF);
// break;
// case ATTR_GOLD:
// color = lv_color_make(0xFF, 0xD7, 0x00);
// break;
// case ATTR_GRAY:
// case ATTR_GREY:
// color = lv_color_make(0x80, 0x80, 0x80);
// break;
// case ATTR_LIME:
// color = lv_color_make(0x00, 0xFF, 0x00);
// break;
// case ATTR_NAVY:
// color = lv_color_make(0x00, 0x00, 0x80);
// break;
// case ATTR_PERU:
// color = lv_color_make(0xCD, 0x85, 0x3F);
// break;
// case ATTR_PINK:
// color = lv_color_make(0xFF, 0xC0, 0xCB);
// break;
// case ATTR_PLUM:
// color = lv_color_make(0xDD, 0xA0, 0xDD);
// break;
// case ATTR_SNOW:
// color = lv_color_make(0xFF, 0xFA, 0xFA);
// break;
// case ATTR_TEAL:
// color = lv_color_make(0x00, 0x80, 0x80);
// break;
// case ATTR_AZURE:
// color = lv_color_make(0xF0, 0xFF, 0xFF);
// break;
// case ATTR_BEIGE:
// color = lv_color_make(0xF5, 0xF5, 0xDC);
// break;
// case ATTR_BLACK:
// color = lv_color_make(0x00, 0x00, 0x00);
// break;
// case ATTR_BLUSH:
// color = lv_color_make(0xB0, 0x00, 0x00);
// break;
// case ATTR_BROWN:
// color = lv_color_make(0xA5, 0x2A, 0x2A);
// break;
// case ATTR_CORAL:
// color = lv_color_make(0xFF, 0x7F, 0x50);
// break;
// case ATTR_GREEN:
// color = lv_color_make(0x00, 0x80, 0x00);
// break;
// case ATTR_IVORY:
// color = lv_color_make(0xFF, 0xFF, 0xF0);
// break;
// case ATTR_KHAKI:
// color = lv_color_make(0xF0, 0xE6, 0x8C);
// break;
// case ATTR_LINEN:
// color = lv_color_make(0xFA, 0xF0, 0xE6);
// break;
// case ATTR_OLIVE:
// color = lv_color_make(0x80, 0x80, 0x00);
// break;
// case ATTR_WHEAT:
// color = lv_color_make(0xF5, 0xDE, 0xB3);
// break;
// case ATTR_WHITE:
// color = lv_color_make(0xFF, 0xFF, 0xFF);
// break;
// case ATTR_BISQUE:
// color = lv_color_make(0xFF, 0xE4, 0xC4);
// break;
// case ATTR_INDIGO:
// color = lv_color_make(0x4B, 0x00, 0x82);
// break;
// case ATTR_MAROON:
// color = lv_color_make(0x80, 0x00, 0x00);
// break;
// case ATTR_ORANGE:
// color = lv_color_make(0xFF, 0xA5, 0x00);
// break;
// case ATTR_ORCHID:
// color = lv_color_make(0xDA, 0x70, 0xD6);
// break;
// case ATTR_PURPLE:
// color = lv_color_make(0x80, 0x00, 0x80);
// break;
// case ATTR_SALMON:
// color = lv_color_make(0xFA, 0x80, 0x72);
// break;
// case ATTR_SIENNA:
// color = lv_color_make(0xA0, 0x52, 0x2D);
// break;
// case ATTR_SILVER:
// color = lv_color_make(0xC0, 0xC0, 0xC0);
// break;
// case ATTR_TOMATO:
// color = lv_color_make(0xFF, 0x63, 0x47);
// break;
// case ATTR_VIOLET:
// color = lv_color_make(0xEE, 0x82, 0xEE);
// break;
// case ATTR_YELLOW:
// color = lv_color_make(0xFF, 0xFF, 0x00);
// break;
// case ATTR_FUCHSIA:
// case ATTR_MAGENTA:
// color = lv_color_make(0xFF, 0x00, 0xFF);
// break;
default:
/* Unknown color name */
Log.warning(TAG_ATTR, F("Invalid color %s"), payload);
return false;
// default:
// /* Unknown color name */
// Log.warning(TAG_ATTR, F("Invalid color %s"), payload);
// return false;
// }
// }
size_t numColors = sizeof(haspNamedColors) / sizeof(haspNamedColors[0]);
uint16_t sdbm = hasp_util_get_sdbm(payload);
for(size_t i = 0; i < numColors; i++) {
if(sdbm == (uint16_t)pgm_read_word_near(&(haspNamedColors[i].hash))) {
uint8_t r = (uint16_t)pgm_read_byte_near(&(haspNamedColors[i].r));
uint8_t g = (uint16_t)pgm_read_byte_near(&(haspNamedColors[i].g));
uint8_t b = (uint16_t)pgm_read_byte_near(&(haspNamedColors[i].b));
color = lv_color_make(r, g, b);
return true; /* Color found */
}
}
return false; /* Color not found */
}
/* Unknown color scheme */
return true;
return true; /* Color found */
}
static lv_font_t * haspPayloadToFont(const char * payload)
@ -1034,7 +1049,7 @@ static void hasp_local_style_attr(lv_obj_t * obj, const char * attr_p, uint16_t
case ATTR_TEXT_FONT: {
lv_font_t * font = haspPayloadToFont(payload);
if(font) {
uint8_t count;
uint8_t count = 3;
if(check_obj_type(obj, LV_HASP_ROLLER)) count = my_roller_get_visible_row_count(obj);
lv_obj_set_style_local_text_font(obj, part, state, font);
if(check_obj_type(obj, LV_HASP_ROLLER)) lv_roller_set_visible_row_count(obj, count);
@ -1390,100 +1405,59 @@ static void hasp_process_obj_attribute_txt(lv_obj_t * obj, const char * attr, co
Log.warning(TAG_ATTR, F("Unknown property %s"), attr);
}
static void hasp_process_obj_attribute_val(lv_obj_t * obj, const char * attr, const char * payload, bool update)
bool 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(obj, LV_HASP_BUTTON) && lv_btn_get_checkable(obj)) {
if(check_obj_type(obj, LV_HASP_BUTTON)) {
if(lv_btn_get_checkable(obj)) {
if(update) {
lv_btn_state_t state;
switch(val) {
case 0:
state = LV_BTN_STATE_RELEASED;
break;
case 1:
state = LV_BTN_STATE_CHECKED_RELEASED;
break;
case 3:
state = LV_BTN_STATE_CHECKED_DISABLED;
break;
default:
state = LV_BTN_STATE_DISABLED;
};
return lv_btn_set_state(obj, state);
if(intval)
lv_obj_add_state(obj, LV_STATE_CHECKED);
else
lv_obj_clear_state(obj, LV_STATE_CHECKED);
} else {
lv_btn_state_t state = lv_btn_get_state(obj);
switch(state) {
case LV_BTN_STATE_RELEASED:
case LV_BTN_STATE_PRESSED:
return hasp_out_int(obj, attr, 0);
case LV_BTN_STATE_CHECKED_RELEASED:
case LV_BTN_STATE_CHECKED_PRESSED:
return hasp_out_int(obj, attr, 1);
case LV_BTN_STATE_DISABLED:
return hasp_out_int(obj, attr, 2);
case LV_BTN_STATE_CHECKED_DISABLED:
return hasp_out_int(obj, attr, 3);
hasp_out_int(obj, attr, lv_obj_get_state(obj, LV_BTN_PART_MAIN) & LV_STATE_CHECKED);
}
} else {
return false; // not checkable
}
}
if(check_obj_type(obj, LV_HASP_CHECKBOX)) {
return update ? lv_checkbox_set_checked(obj, hasp_util_is_true(payload))
} else if(check_obj_type(obj, LV_HASP_CHECKBOX)) {
update ? lv_checkbox_set_checked(obj, hasp_util_is_true(payload))
: hasp_out_int(obj, attr, lv_checkbox_is_checked(obj));
}
if(check_obj_type(obj, LV_HASP_SWITCH)) {
if(update) {
return hasp_util_is_true(payload) ? lv_switch_on(obj, LV_ANIM_ON) : lv_switch_off(obj, LV_ANIM_ON);
} else {
return hasp_out_int(obj, attr, lv_switch_get_state(obj));
}
} else if(check_obj_type(obj, LV_HASP_SWITCH)) {
if(update)
hasp_util_is_true(payload) ? lv_switch_on(obj, LV_ANIM_ON) : lv_switch_off(obj, LV_ANIM_ON);
else
hasp_out_int(obj, attr, lv_switch_get_state(obj));
} else if(check_obj_type(obj, LV_HASP_DDLIST)) {
lv_dropdown_set_selected(obj, val);
return;
lv_dropdown_set_selected(obj, (uint16_t)intval);
} else if(check_obj_type(obj, LV_HASP_LMETER)) {
return update ? lv_linemeter_set_value(obj, intval) : hasp_out_int(obj, attr, lv_linemeter_get_value(obj));
update ? lv_linemeter_set_value(obj, intval) : hasp_out_int(obj, attr, lv_linemeter_get_value(obj));
} else if(check_obj_type(obj, LV_HASP_SLIDER)) {
return update ? lv_slider_set_value(obj, intval, LV_ANIM_ON)
: hasp_out_int(obj, attr, lv_slider_get_value(obj));
update ? lv_slider_set_value(obj, intval, LV_ANIM_ON) : hasp_out_int(obj, attr, lv_slider_get_value(obj));
} else if(check_obj_type(obj, LV_HASP_LED)) {
return update ? lv_led_set_bright(obj, (uint8_t)val) : hasp_out_int(obj, attr, lv_led_get_bright(obj));
update ? lv_led_set_bright(obj, (uint8_t)intval) : hasp_out_int(obj, attr, lv_led_get_bright(obj));
} else if(check_obj_type(obj, LV_HASP_ARC)) {
return update ? lv_arc_set_value(obj, intval) : hasp_out_int(obj, attr, lv_arc_get_value(obj));
update ? lv_arc_set_value(obj, intval) : hasp_out_int(obj, attr, lv_arc_get_value(obj));
} else if(check_obj_type(obj, LV_HASP_GAUGE)) {
return update ? lv_gauge_set_value(obj, 0, intval) : hasp_out_int(obj, attr, lv_gauge_get_value(obj, 0));
update ? lv_gauge_set_value(obj, 0, intval) : hasp_out_int(obj, attr, lv_gauge_get_value(obj, 0));
} else if(check_obj_type(obj, LV_HASP_ROLLER)) {
lv_roller_set_selected(obj, val, LV_ANIM_ON);
return;
lv_roller_set_selected(obj, (uint16_t)intval, LV_ANIM_ON);
} else if(check_obj_type(obj, LV_HASP_BAR)) {
return update ? lv_bar_set_value(obj, intval, LV_ANIM_ON) : hasp_out_int(obj, attr, lv_bar_get_value(obj));
update ? lv_bar_set_value(obj, intval, LV_ANIM_ON) : hasp_out_int(obj, attr, lv_bar_get_value(obj));
} else if(check_obj_type(obj, LV_HASP_CPICKER)) {
if(update) {
lv_color_t color;
if(!haspPayloadToColor(payload, color)) return;
lv_cpicker_set_color(obj, color);
if(haspPayloadToColor(payload, color)) lv_cpicker_set_color(obj, color);
} else {
hasp_out_color(obj, attr, lv_cpicker_get_color(obj));
}
return;
} else {
return false;
}
Log.warning(TAG_ATTR, F("Unknown property %s"), attr);
return true;
}
static void hasp_process_obj_attribute_range(lv_obj_t * obj, const char * attr, const char * payload, bool update,
@ -1639,7 +1613,7 @@ void hasp_process_obj_attribute(lv_obj_t * obj, const char * attr_p, const char
break; // attribute_found
case ATTR_VAL:
hasp_process_obj_attribute_val(obj, attr, payload, update);
if(!hasp_process_obj_attribute_val(obj, attr, payload, update)) goto attribute_not_found;
break; // attribute_found
case ATTR_MIN:
@ -1832,5 +1806,5 @@ attribute_found:
return;
attribute_not_found:
Log.verbose(TAG_ATTR, F("%s (%d)"), attr_p, attr_hash);
Log.warning(TAG_ATTR, F("Unknown property %s (%d)"), attr_p, attr_hash);
}

View File

@ -25,6 +25,7 @@ void my_btnmatrix_map_clear(lv_obj_t * obj);
void line_clear_points(lv_obj_t * obj);
void hasp_process_obj_attribute(lv_obj_t * obj, const char * attr_p, const char * payload, bool update);
bool hasp_process_obj_attribute_val(lv_obj_t * obj, const char * attr, const char * payload, bool update);
#ifdef __cplusplus
} /* extern "C" */
@ -342,4 +343,28 @@ _HASP_ATTRIBUTE(SCALE_END_LINE_WIDTH, scale_end_line_width, lv_style_int_t)
#define ATTR_FUCHSIA 5463
#define ATTR_MAGENTA 49385
struct hasp_color_t
{
uint16_t hash;
uint8_t r, g, b;
};
/* Named COLOR lookup table */
const hasp_color_t haspNamedColors[] PROGMEM = {
{ATTR_RED, 0xFF, 0x00, 0x00}, {ATTR_TAN, 0xD2, 0xB4, 0x8C}, {ATTR_AQUA, 0x00, 0xFF, 0xFF},
{ATTR_BLUE, 0x00, 0x00, 0xFF}, {ATTR_CYAN, 0x00, 0xFF, 0xFF}, {ATTR_GOLD, 0xFF, 0xD7, 0x00},
{ATTR_GRAY, 0x80, 0x80, 0x80}, {ATTR_GREY, 0x80, 0x80, 0x80}, {ATTR_LIME, 0x00, 0xFF, 0x00},
{ATTR_NAVY, 0x00, 0x00, 0x80}, {ATTR_PERU, 0xCD, 0x85, 0x3F}, {ATTR_PINK, 0xFF, 0xC0, 0xCB},
{ATTR_PLUM, 0xDD, 0xA0, 0xDD}, {ATTR_SNOW, 0xFF, 0xFA, 0xFA}, {ATTR_TEAL, 0x00, 0x80, 0x80},
{ATTR_AZURE, 0xF0, 0xFF, 0xFF}, {ATTR_BEIGE, 0xF5, 0xF5, 0xDC}, {ATTR_BLACK, 0x00, 0x00, 0x00},
{ATTR_BLUSH, 0xB0, 0x00, 0x00}, {ATTR_BROWN, 0xA5, 0x2A, 0x2A}, {ATTR_CORAL, 0xFF, 0x7F, 0x50},
{ATTR_GREEN, 0x00, 0x80, 0x00}, {ATTR_IVORY, 0xFF, 0xFF, 0xF0}, {ATTR_KHAKI, 0xF0, 0xE6, 0x8C},
{ATTR_LINEN, 0xFA, 0xF0, 0xE6}, {ATTR_OLIVE, 0x80, 0x80, 0x00}, {ATTR_WHEAT, 0xF5, 0xDE, 0xB3},
{ATTR_WHITE, 0xFF, 0xFF, 0xFF}, {ATTR_BISQUE, 0xFF, 0xE4, 0xC4}, {ATTR_INDIGO, 0x4B, 0x00, 0x82},
{ATTR_MAROON, 0x80, 0x00, 0x00}, {ATTR_ORANGE, 0xFF, 0xA5, 0x00}, {ATTR_ORCHID, 0xDA, 0x70, 0xD6},
{ATTR_PURPLE, 0x80, 0x00, 0x80}, {ATTR_SALMON, 0xFA, 0x80, 0x72}, {ATTR_SIENNA, 0xA0, 0x52, 0x2D},
{ATTR_SILVER, 0xC0, 0xC0, 0xC0}, {ATTR_TOMATO, 0xFF, 0x63, 0x47}, {ATTR_VIOLET, 0xEE, 0x82, 0xEE},
{ATTR_YELLOW, 0xFF, 0xFF, 0x00}, {ATTR_FUCHSIA, 0xFF, 0x00, 0xFF}, {ATTR_MAGENTA, 0xFF, 0x00, 0xFF},
};
#endif

View File

@ -37,7 +37,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);
// void dispatch_group_value(uint8_t groupid, int16_t state, lv_obj_t * obj);
static inline void dispatch_state_msg(const __FlashStringHelper * subtopic, const char * payload);
void dispatch_screenshot(const char *, const char * filename)
@ -101,6 +101,18 @@ inline void dispatch_process_button_attribute(String strTopic, const char * payl
if(pageid >= 0 && pageid <= 255 && objid >= 0 && objid <= 255) {
hasp_process_attribute((uint8_t)pageid, (uint8_t)objid, strAttr.c_str(), payload);
} // valid page
} else {
unsigned int pageid, objid;
const char * topic_p = strTopic.c_str();
if(sscanf(topic_p, "p%ub%u.", &pageid, &objid) == 2) { // Literal String
size_t offset = 0;
while(topic_p[offset++] != '.') {
}
hasp_process_attribute((uint8_t)pageid, (uint8_t)objid, topic_p + offset, payload);
}
}
}
@ -121,8 +133,8 @@ void dispatch_command(const char * topic, const char * payload)
/* =============================== Not standard payload commands ===================================== */
if(strlen(topic) == 7 && topic == strstr_P(topic, PSTR("output"))) {
dispatch_group_state(atoi(topic + 6), hasp_util_is_true(payload) ? HASP_EVENT_ON : HASP_EVENT_OFF,
NULL); // + 6 => trim 'output' from the topic
int16_t state = atoi(payload);
dispatch_normalized_group_value(atoi(topic + 6), state, NULL); // + 6 => trim 'output' from the topic
// } else if(strcasecmp_P(topic, PSTR("screenshot")) == 0) {
// guiTakeScreenshot("/screenshot.bmp"); // Literal String
@ -243,8 +255,20 @@ void dispatch_output_idle_state(uint8_t state)
dispatch_state_msg(F("idle"), payload);
}
void dispatch_output_group_state(uint8_t groupid, uint16_t state)
{
char payload[64];
char number[16]; // Return the current state
itoa(state, number, DEC);
snprintf_P(payload, sizeof(payload), PSTR("{\"group\":%d,\"state\":\"%s\"}"), groupid, number);
dispatch_state_msg(F("output"), payload);
}
void IRAM_ATTR dispatch_send_obj_attribute_str(uint8_t pageid, uint8_t btnid, const char * attribute, const char * data)
{
if(!attribute || !data) return;
char topic[12];
char payload[32 + strlen(data) + strlen(attribute)];
// snprintf_P(payload, sizeof(payload), PSTR("{\"page\":%u,\"id\":%u,\"%s\":\"%s\"}"), pageid, btnid, attribute,
@ -399,7 +423,7 @@ static void dispatch_get_event_name(uint8_t eventid, char * buffer, size_t size)
}
#if HASP_USE_GPIO > 0
void dispatch_gpio_event(uint8_t pin, uint8_t group, uint8_t eventid)
void dispatch_gpio_input_event(uint8_t pin, uint8_t group, uint8_t eventid)
{
char payload[64];
char event[8];
@ -411,7 +435,7 @@ void dispatch_gpio_event(uint8_t pin, uint8_t group, uint8_t eventid)
#endif
// update outputstates
dispatch_group_state(group, dispatch_get_event_state(eventid), NULL);
// dispatch_group_onoff(group, dispatch_get_event_state(eventid), NULL);
}
#endif
@ -428,9 +452,16 @@ void dispatch_object_event(lv_obj_t * obj, uint8_t eventid)
dispatch_send_obj_attribute_str(pageid, objid, topic, payload);
}
if(obj->user_data.groupid > 0) {
dispatch_group_state(obj->user_data.groupid, eventid, obj);
}
// dispatch_group_onoff(obj->user_data.groupid, dispatch_get_event_state(eventid), obj);
}
void dispatch_object_value_changed(lv_obj_t * obj, int16_t state)
{
char topic[4];
hasp_update_sleep_state(); // wakeup?
snprintf_P(topic, sizeof(topic), PSTR("val"));
hasp_send_obj_attribute_int(obj, topic, state);
}
/********************************************** Output States ******************************************/
@ -448,21 +479,39 @@ static inline void dispatch_state_msg(const __FlashStringHelper * subtopic, cons
#endif
}
void dispatch_group_state(uint8_t groupid, uint8_t eventid, lv_obj_t * obj)
// void dispatch_group_onoff(uint8_t groupid, uint16_t eventid, lv_obj_t * obj)
// {
// 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);
// gpio_set_group_onoff(groupid, state);
// object_set_group_state(groupid, eventid, obj);
// }
// char payload[8];
// dispatch_get_event_name(eventid, payload, sizeof(payload));
// // dispatch_output_group_state(groupid, payload);
// }
// void dispatch_group_value(uint8_t groupid, int16_t state, lv_obj_t * obj)
// {
// if(groupid >= 0) {
// gpio_set_group_value(groupid, state);
// object_set_group_state(groupid, state, obj);
// }
// char payload[8];
// // dispatch_output_group_state(groupid, payload);
// }
void dispatch_normalized_group_value(uint8_t groupid, uint16_t value, lv_obj_t * obj)
{
if((eventid == HASP_EVENT_LONG) || (eventid == HASP_EVENT_HOLD)) return; // don't send repeat events
if(groupid >= 0) {
gpio_set_group_state(groupid, eventid);
object_set_group_state(groupid, eventid, obj);
if(groupid > 0) {
Log.verbose(TAG_MSGR, F("GROUP %d value %d"), groupid, value);
gpio_set_normalized_group_value(groupid, value);
// object_set_group_state(groupid, value, obj);
}
char payload[64];
char state[4]; // Return the current state
memcpy_P(state, dispatch_get_event_state(eventid) ? PSTR("ON") : PSTR("OFF"), sizeof(state));
snprintf_P(payload, sizeof(payload), PSTR("{\"group\":%d,\"state\":\"%s\"}"), groupid, state);
dispatch_state_msg(F("output"), payload);
}
/********************************************** Native Commands ****************************************/

View File

@ -47,9 +47,12 @@ void dispatch_output_idle_state(uint8_t state);
void dispatch_output_statusupdate(const char *, const char *);
void dispatch_output_current_page();
void dispatch_gpio_event(uint8_t pin, uint8_t group, uint8_t eventid);
void dispatch_gpio_input_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);
void dispatch_object_value_changed(lv_obj_t * obj, int16_t state);
void dispatch_normalized_group_value(uint8_t groupid, uint16_t value, lv_obj_t * obj);
void IRAM_ATTR dispatch_send_obj_attribute_str(uint8_t pageid, uint8_t btnid, const char * attribute,
const char * data);

View File

@ -48,7 +48,6 @@ lv_obj_t * hasp_find_obj_from_parent_id(lv_obj_t * parent, uint8_t objid)
/* check tabs */
if(check_obj_type(child, LV_HASP_TABVIEW)) {
//#if LVGL_VERSION_MAJOR == 7
uint16_t tabcount = lv_tabview_get_tab_count(child);
for(uint16_t i = 0; i < tabcount; i++) {
lv_obj_t * tab = lv_tabview_get_tab(child, i);
@ -59,7 +58,6 @@ lv_obj_t * hasp_find_obj_from_parent_id(lv_obj_t * parent, uint8_t objid)
grandchild = hasp_find_obj_from_parent_id(tab, objid);
if(grandchild) return grandchild; /* grandchild found, return it */
}
//#endif
}
/* try next sibling */
@ -231,6 +229,7 @@ void hasp_send_obj_attribute_color(lv_obj_t * obj, const char * attribute, lv_co
{
char buffer[40]; // "#ffffff","r":"255","g":"255","b":"255"
lv_color32_t c32;
c32.full = lv_color_to32(color);
snprintf_P(buffer, sizeof(buffer), PSTR("#%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);
@ -239,31 +238,32 @@ void hasp_send_obj_attribute_color(lv_obj_t * obj, const char * attribute, lv_co
// ##################### 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 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_send_obj_attribute_val(lv_obj_t * obj, int32_t val)
{
char data[32];
itoa(val, data, DEC);
hasp_send_obj_attribute_P(obj, PSTR("val"), data);
}
// 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_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);
}
// 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 ########################################################
@ -272,7 +272,7 @@ static inline void hasp_send_obj_attribute_txt(lv_obj_t * obj, const char * txt)
* @param obj pointer to a button object
* @param event type of event that occured
*/
void IRAM_ATTR generic_event_handler(lv_obj_t * obj, lv_event_t event)
void generic_event_handler(lv_obj_t * obj, lv_event_t event)
{
uint8_t eventid;
@ -333,6 +333,7 @@ void IRAM_ATTR generic_event_handler(lv_obj_t * obj, lv_event_t event)
hasp_update_sleep_state(); // wakeup?
dispatch_object_event(obj, eventid); // send object event
dispatch_normalized_group_value(obj->user_data.groupid, NORMALIZE(dispatch_get_event_state(eventid), 0, 1), obj);
}
/**
@ -349,31 +350,39 @@ void wakeup_event_handler(lv_obj_t * obj, lv_event_t event)
}
/**
* Called when a toggle button is clicked
* @param obj pointer to a button
* @param event type of event that occured
*/
void IRAM_ATTR toggle_event_handler(lv_obj_t * obj, lv_event_t event)
{
if(event == LV_EVENT_VALUE_CHANGED) {
hasp_update_sleep_state(); // wakeup?
hasp_send_obj_attribute_val(obj, lv_checkbox_is_checked(obj));
} else if(event == LV_EVENT_DELETE) {
Log.verbose(TAG_HASP, F("Object deleted Event %d occured"), event);
hasp_object_delete(obj);
}
}
/**
* Called when a switch is toggled
* Called when a object state is toggled on/off
* @param obj pointer to a switch object
* @param event type of event that occured
*/
static void switch_event_handler(lv_obj_t * obj, lv_event_t event)
void toggle_event_handler(lv_obj_t * obj, lv_event_t event)
{
if(event == LV_EVENT_VALUE_CHANGED) {
char property[4];
bool val = 0;
hasp_update_sleep_state(); // wakeup?
hasp_send_obj_attribute_val(obj, lv_switch_get_state(obj));
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);
dispatch_normalized_group_value(obj->user_data.groupid, NORMALIZE(val, 0, 1), obj);
} else if(event == LV_EVENT_DELETE) {
Log.verbose(TAG_HASP, F("Object deleted Event %d occured"), event);
hasp_object_delete(obj);
@ -381,22 +390,7 @@ static void switch_event_handler(lv_obj_t * obj, lv_event_t event)
}
/**
* Called when a checkboxed is clicked
* @param obj pointer to a checkbox
* @param event type of event that occured
*/
static void checkbox_event_handler(lv_obj_t * obj, lv_event_t event)
{
if(event == LV_EVENT_VALUE_CHANGED) {
hasp_send_obj_attribute_val(obj, lv_checkbox_is_checked(obj));
} else if(event == LV_EVENT_DELETE) {
Log.verbose(TAG_HASP, F("Object deleted Event %d occured"), event);
hasp_object_delete(obj);
}
}
/**
* Called when a dropdown or roller list is clicked
* Called when a range value has changed
* @param obj pointer to a dropdown list or roller
* @param event type of event that occured
*/
@ -406,17 +400,19 @@ static void selector_event_handler(lv_obj_t * obj, lv_event_t event)
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_DDLIST:
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;
@ -436,17 +432,19 @@ static void selector_event_handler(lv_obj_t * obj, lv_event_t event)
strncpy(buffer, txt, sizeof(buffer));
snprintf_P(property, sizeof(property), PSTR("row\":%d,\"col\":%d,\"txt"), row, col);
goto property_set;
hasp_send_obj_attribute_str(obj, property, buffer);
return;
}
default:
return;
}
// set the property
snprintf_P(property, sizeof(property), PSTR("val\":%d,\"txt"), val);
property_set:
hasp_send_obj_attribute_str(obj, property, buffer);
if(max > 0) dispatch_normalized_group_value(obj->user_data.groupid, NORMALIZE(val, 0, max), obj);
} else if(event == LV_EVENT_DELETE) {
Log.verbose(TAG_HASP, F("Object deleted Event %d occured"), event);
hasp_object_delete(obj);
@ -474,15 +472,23 @@ void slider_event_handler(lv_obj_t * obj, lv_event_t event)
}
*/
int16_t val;
int16_t val = 0;
int16_t min = 0;
int16_t max = 0;
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;
}
hasp_send_obj_attribute_val(obj, lv_slider_get_value(obj));
dispatch_object_value_changed(obj, val);
dispatch_normalized_group_value(obj->user_data.groupid, NORMALIZE(val, min, max), obj);
} else if(event == LV_EVENT_DELETE) {
Log.verbose(TAG_HASP, F("Object deleted Event %d occured"), event);
@ -501,6 +507,7 @@ static void cpicker_event_handler(lv_obj_t * obj, lv_event_t event)
snprintf_P(color, sizeof(color), PSTR("color"));
if(event == LV_EVENT_VALUE_CHANGED) {
hasp_update_sleep_state(); // wakeup?
hasp_send_obj_attribute_color(obj, color, lv_cpicker_get_color(obj));
} else if(event == LV_EVENT_DELETE) {
Log.verbose(TAG_HASP, F("Object deleted Event %d occured"), event);
@ -513,18 +520,60 @@ static void cpicker_event_handler(lv_obj_t * obj, lv_event_t event)
// 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)
{
if(groupid == 0) return;
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++) {
uint8_t startid = 1;
for(uint8_t objid = startid; objid < 20; 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
if(obj && obj != src_obj && obj->user_data.groupid == groupid) { // skip source object, if set
lv_obj_set_state(obj, state ? LV_STATE_PRESSED | LV_STATE_CHECKED : LV_STATE_DEFAULT);
}
}
}
}
void object_set_group_value(lv_obj_t * parent, uint8_t groupid, const char * payload)
{
if(groupid == 0 || parent == nullptr) return;
lv_obj_t * child;
child = lv_obj_get_child(parent, NULL);
while(child) {
/* child found, update it */
if(groupid == child->user_data.groupid) hasp_process_obj_attribute_val(child, NULL, payload, true);
/* update grandchildren */
object_set_group_value(child, groupid, payload);
/* check tabs */
if(check_obj_type(child, LV_HASP_TABVIEW)) {
//#if LVGL_VERSION_MAJOR == 7
uint16_t tabcount = lv_tabview_get_tab_count(child);
for(uint16_t i = 0; i < tabcount; i++) {
lv_obj_t * tab = lv_tabview_get_tab(child, i);
Log.verbose(TAG_HASP, F("Found tab %i"), i);
if(tab->user_data.groupid && groupid == tab->user_data.groupid)
hasp_process_obj_attribute_val(tab, NULL, payload, true); /* tab found, update it */
/* check grandchildren */
object_set_group_value(tab, groupid, payload);
}
//#endif
}
/* try next sibling */
child = lv_obj_get_child(parent, child);
}
}
void object_set_group_value(uint8_t groupid, int16_t state)
{
char payload[16];
itoa(state, payload, DEC);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
// Used in the dispatcher & hasp_new_object
@ -633,7 +682,7 @@ void hasp_new_object(const JsonObject & config, uint8_t & saved_page_id)
case HASP_OBJ_CB:
obj = lv_checkbox_create(parent_obj, NULL);
if(obj) {
lv_obj_set_event_cb(obj, checkbox_event_handler);
lv_obj_set_event_cb(obj, toggle_event_handler);
obj->user_data.objid = LV_HASP_CHECKBOX;
}
break;
@ -859,7 +908,7 @@ void hasp_new_object(const JsonObject & config, uint8_t & saved_page_id)
case HASP_OBJ_SWITCH:
obj = lv_switch_create(parent_obj, NULL);
if(obj) {
lv_obj_set_event_cb(obj, switch_event_handler);
lv_obj_set_event_cb(obj, toggle_event_handler);
obj->user_data.objid = LV_HASP_SWITCH;
}
break;

View File

@ -70,8 +70,8 @@ void hasp_process_attribute(uint8_t pageid, uint8_t objid, const char * attr, co
void object_set_group_state(uint8_t groupid, uint8_t eventid, lv_obj_t * src_obj);
void IRAM_ATTR generic_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 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 wakeup_event_handler(lv_obj_t * obj, lv_event_t event);

View File

@ -49,30 +49,44 @@ static void gpio_event_handler(AceButton * button, uint8_t eventType, uint8_t bu
{
uint8_t btnid = button->getId();
uint8_t eventid;
bool state = false;
switch(eventType) {
case AceButton::kEventPressed:
if(gpioConfig[btnid].type == HASP_GPIO_SWITCH || gpioConfig[btnid].type == HASP_GPIO_SWITCH_INVERTED) {
eventid = HASP_EVENT_ON;
} else {
eventid = HASP_EVENT_DOWN;
}
state = true;
break;
case 2: // AceButton::kEventClicked:
eventid = HASP_EVENT_SHORT;
break;
case AceButton::kEventDoubleClicked:
eventid = HASP_EVENT_DOUBLE;
break;
// case AceButton::kEventDoubleClicked:
// eventid = HASP_EVENT_DOUBLE;
// break;
case AceButton::kEventLongPressed:
eventid = HASP_EVENT_LONG;
// state = true; // do not repeat DOWN + LONG
break;
case AceButton::kEventRepeatPressed:
// return; // Fix needed for switches
eventid = HASP_EVENT_HOLD;
break;
// case AceButton::kEventRepeatPressed:
// eventid = HASP_EVENT_HOLD;
// state = true; // do not repeat DOWN + LONG + HOLD
// break;
case AceButton::kEventReleased:
if(gpioConfig[btnid].type == HASP_GPIO_SWITCH || gpioConfig[btnid].type == HASP_GPIO_SWITCH_INVERTED) {
eventid = HASP_EVENT_OFF;
} else {
eventid = HASP_EVENT_UP;
}
break;
default:
eventid = HASP_EVENT_LOST;
}
dispatch_gpio_event(gpioConfig[btnid].pin, gpioConfig[btnid].group, eventid);
dispatch_gpio_input_event(gpioConfig[btnid].pin, gpioConfig[btnid].group, eventid);
if(eventid != HASP_EVENT_LONG) // do not repeat DOWN + LONG
dispatch_normalized_group_value(gpioConfig[btnid].group, NORMALIZE(state, 0, 1), NULL);
}
void aceButtonSetup(void)
@ -81,8 +95,8 @@ void aceButtonSetup(void)
buttonConfig->setEventHandler(gpio_event_handler);
// Features
buttonConfig->setFeature(ButtonConfig::kFeatureClick);
buttonConfig->setFeature(ButtonConfig::kFeatureLongPress);
// buttonConfig->setFeature(ButtonConfig::kFeatureClick);
// buttonConfig->setFeature(ButtonConfig::kFeatureLongPress);
// buttonConfig->setFeature(ButtonConfig::kFeatureRepeatPress);
// buttonConfig->setFeature(ButtonConfig::kFeatureDoubleClick);
// buttonConfig->setFeature(ButtonConfig::kFeatureSuppressClickBeforeDoubleClick);
@ -98,7 +112,7 @@ void aceButtonSetup(void)
void IRAM_ATTR gpioLoop(void)
{
// Should be called every 4-5ms or faster, for the default debouncing time of ~20ms.
for(uint32_t i = 0; i < gpioUsedInputCount; i++) {
for(uint8_t i = 0; i < gpioUsedInputCount; i++) {
if(button[i]) button[i]->check();
}
}
@ -113,19 +127,19 @@ void gpioAddButton(uint8_t pin, uint8_t input_mode, uint8_t default_state, uint8
input_mode, default_state);
button[i] = new AceButton(pin, default_state, index);
// 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
buttonConfig->setFeature(ButtonConfig::kFeatureSuppressAfterClick);
Log.trace(TAG_GPIO, F("Button%d created on pin %d (index %d) mode %d default %d"), i, pin, index,
input_mode, default_state);
@ -138,6 +152,35 @@ void gpioAddButton(uint8_t pin, uint8_t input_mode, uint8_t default_state, uint8
index, HASP_NUM_INPUTS);
}
void gpioAddSwitch(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]) {
Log.notice(TAG_GPIO, F("Creating Switch%d on pin %d (index %d) mode %d default %d"), i, pin, index,
input_mode, default_state);
button[i] = new AceButton(pin, default_state, index);
if(button[i]) {
// pinMode(pin, input_mode);
ButtonConfig * buttonConfig = button[i]->getButtonConfig();
buttonConfig->setEventHandler(gpio_event_handler);
buttonConfig->setFeature(ButtonConfig::kFeatureSuppressAll);
Log.trace(TAG_GPIO, F("Button%d switch on pin %d (index %d) mode %d default %d"), i, pin, index,
input_mode, default_state);
gpioUsedInputCount = i + 1;
return;
}
}
}
Log.error(TAG_GPIO, F("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 index)
{
uint8_t i;
@ -173,7 +216,7 @@ void gpioSetup()
{
aceButtonSetup();
for(uint32_t i = 0; i < HASP_NUM_GPIO_CONFIG; i++) {
for(uint8_t i = 0; i < HASP_NUM_GPIO_CONFIG; i++) {
uint8_t input_mode;
switch(gpioConfig[i].gpio_function) {
case OUTPUT:
@ -193,29 +236,36 @@ void gpioSetup()
switch(gpioConfig[i].type) {
case HASP_GPIO_SWITCH:
gpioAddSwitch(gpioConfig[i].pin, input_mode, HIGH, i);
pinMode(gpioConfig[i].pin, INPUT_PULLUP);
break;
case HASP_GPIO_BUTTON:
gpioAddButton(gpioConfig[i].pin, input_mode, HIGH, i);
pinMode(gpioConfig[i].pin, INPUT_PULLUP);
break;
case HASP_GPIO_SWITCH_INVERTED:
gpioAddSwitch(gpioConfig[i].pin, input_mode, LOW, i);
pinMode(gpioConfig[i].pin, INPUT_PULLDOWN);
break;
case HASP_GPIO_BUTTON_INVERTED:
gpioAddButton(gpioConfig[i].pin, input_mode, LOW, i);
pinMode(gpioConfig[i].pin, INPUT_PULLDOWN);
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_LED:
case HASP_GPIO_LED_INVERTED:
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);
ledcSetup(gpioConfig[i].group, 20000, 12);
// attach the channel to the GPIO to be controlled
ledcAttachPin(gpioConfig[i].pin, gpioConfig[i].group);
#endif
@ -224,57 +274,76 @@ void gpioSetup()
}
}
void gpio_set_state(hasp_gpio_config_t gpio, bool state)
/* ********************************* State Setters *************************************** */
void gpio_set_normalized_value(hasp_gpio_config_t gpio, uint16_t state)
{
switch(gpio.type) {
case HASP_GPIO_RELAY:
case HASP_GPIO_LED:
digitalWrite(gpio.pin, state ? HIGH : LOW);
gpio.val = state >= 0x8000U ? HIGH : LOW;
digitalWrite(gpio.pin, gpio.val);
break;
case HASP_GPIO_RELAY_INVERTED:
case HASP_GPIO_LED_INVERTED:
digitalWrite(gpio.pin, state ? LOW : HIGH);
gpio.val = state >= 0x8000U ? LOW : HIGH;
digitalWrite(gpio.pin, gpio.val);
break;
#if defined(ARDUINO_ARCH_ESP32)
case HASP_GPIO_LED:
case HASP_GPIO_PWM:
ledcWrite(gpio.group, map(state, 0, 1, 0, 1023)); // ledChannel and value
gpio.val = map(state, 0, 0xFFFFU, 0, 4095);
ledcWrite(gpio.group, gpio.val); // ledChannel and value
break;
case HASP_GPIO_LED_INVERTED:
case HASP_GPIO_PWM_INVERTED:
ledcWrite(gpio.group, map(!state, 0, 1, 0, 1023)); // ledChannel and value
gpio.val = map(0xFFFFU - state, 0, 0xFFFFU, 0, 4095);
ledcWrite(gpio.group, gpio.val); // ledChannel and value
break;
#else
case HASP_GPIO_LED:
case HASP_GPIO_PWM:
analogWrite(gpio.pin, map(state, 0, 1, 0, 1023));
analogWrite(gpio.pin, map(state, 0, 0xFFFFU, 0, 1023));
break;
case HASP_GPIO_LED_INVERTED:
case HASP_GPIO_PWM_INVERTED:
analogWrite(gpio.pin, map(!state, 0, 1, 0, 1023));
analogWrite(gpio.pin, map(0xFFFFU - state, 0, 0xFFFFU, 0, 1023));
break;
#endif
default:;
}
}
void gpio_set_group_state(uint8_t groupid, uint8_t eventid)
{
bool state = dispatch_get_event_state(eventid);
for(uint32_t i = 0; i < HASP_NUM_GPIO_CONFIG; i++) {
if(gpioConfig[i].group == groupid) {
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(uint32_t i = 0; i < HASP_NUM_GPIO_CONFIG; i++) {
if(gpioConfig[i].pin == pin) {
gpio_set_state(gpioConfig[i], state);
default:
return;
}
Log.verbose(TAG_GPIO, F(" * Group %d - Pin %d = %d"), gpio.group, gpio.pin, gpio.val);
}
// void gpio_set_group_onoff(uint8_t groupid, bool ison)
// {
// for(uint8_t i = 0; i < HASP_NUM_GPIO_CONFIG; i++) {
// if(gpioConfig[i].group == groupid) {
// gpio_set_value(gpioConfig[i], ison ? gpioConfig[i].max : 0);
// }
// }
// }
void gpio_set_normalized_group_value(uint8_t groupid, uint16_t state)
{
// bool state = dispatch_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], state);
}
}
}
// not used
// void gpio_set_gpio_value(uint8_t pin, uint16_t state)
// {
// // 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_value(gpioConfig[i], state);
// return;
// }
// }
// }
bool gpioIsSystemPin(uint8_t gpio)
{
if((gpio >= NUM_DIGITAL_PINS) // invalid pins
@ -376,9 +445,9 @@ bool gpioIsSystemPin(uint8_t gpio)
#ifdef ARDUINO_ARCH_ESP8266
if((gpio >= 6) && (gpio <= 11)) return true; // VSPI
#ifndef TFT_SPI_OVERLAP
#ifndef TFT_SPI_OVERLAP
if((gpio >= 12) && (gpio <= 14)) return true; // HSPI
#endif
#endif
#endif
return false;
@ -386,8 +455,8 @@ bool gpioIsSystemPin(uint8_t gpio)
bool gpioInUse(uint8_t gpio)
{
for(uint32_t i = 0; i < HASP_NUM_GPIO_CONFIG; i++) {
if(gpioConfigInUse(i) && (gpioConfig[i].pin == gpio)) {
for(uint8_t i = 0; i < HASP_NUM_GPIO_CONFIG; i++) {
if((gpioConfig[i].pin == gpio) && gpioConfigInUse(i)) {
return true; // pin matches and is in use
}
}
@ -397,7 +466,7 @@ bool gpioInUse(uint8_t gpio)
bool gpioSavePinConfig(uint8_t config_num, uint8_t pin, uint8_t type, uint8_t group, uint8_t pinfunc)
{
// Input validation
// TODO: Input validation
// ESP8266: Only Pullups except on gpio16
@ -463,7 +532,7 @@ bool gpioGetConfig(const JsonObject & settings)
/* Build new Gpio array if the count is not correct */
if(i != HASP_NUM_GPIO_CONFIG) {
array = settings[FPSTR(F_GPIO_CONFIG)].to<JsonArray>(); // Clear JsonArray
for(uint32_t i = 0; i < HASP_NUM_GPIO_CONFIG; i++) {
for(uint8_t i = 0; i < HASP_NUM_GPIO_CONFIG; i++) {
uint32_t cur_val = gpioConfig[i].pin | (gpioConfig[i].group << 8) | (gpioConfig[i].type << 16) |
(gpioConfig[i].gpio_function << 24);
array.add(cur_val);

View File

@ -16,13 +16,15 @@ struct hasp_gpio_config_t
uint8_t group; // groupid
uint8_t type; // switch, button, ...
uint8_t gpio_function; // INPUT, OUTPUT, PULLUP, etc
uint16_t val;
};
void gpioSetup(void);
void IRAM_ATTR gpioLoop(void);
void gpio_set_group_state(uint8_t groupid, uint8_t eventid);
void gpio_set_gpio_state(uint8_t pin, uint8_t eventid);
// void gpio_set_group_onoff(uint8_t groupid, bool ison);
void gpio_set_normalized_group_value(uint8_t groupid, uint16_t state);
// void gpio_set_gpio_state(uint8_t pin, uint16_t state);
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

@ -1261,25 +1261,25 @@ void webHandleGpioConfig()
httpMessage += halGpioName(gpio);
httpMessage += F("</td><td>");
switch(conf.type) {
switch(conf.type & 0xfe) {
case HASP_GPIO_SWITCH:
case HASP_GPIO_SWITCH_INVERTED:
// case HASP_GPIO_SWITCH_INVERTED:
httpMessage += F("Switch");
break;
case HASP_GPIO_BUTTON:
case HASP_GPIO_BUTTON_INVERTED:
// case HASP_GPIO_BUTTON_INVERTED:
httpMessage += F("Button");
break;
case HASP_GPIO_LED:
case HASP_GPIO_LED_INVERTED:
// case HASP_GPIO_LED_INVERTED:
httpMessage += F("Led");
break;
case HASP_GPIO_RELAY:
case HASP_GPIO_RELAY_INVERTED:
// case HASP_GPIO_RELAY_INVERTED:
httpMessage += F("Relay");
break;
case HASP_GPIO_PWM:
case HASP_GPIO_PWM_INVERTED:
// case HASP_GPIO_PWM_INVERTED:
httpMessage += F("PWM");
break;
default:
@ -1290,14 +1290,12 @@ void webHandleGpioConfig()
httpMessage += conf.group;
httpMessage += F("</td><td>");
bool inverted = (conf.type == HASP_GPIO_BUTTON_INVERTED) ||
(conf.type == HASP_GPIO_SWITCH_INVERTED) || (conf.type == HASP_GPIO_LED_INVERTED) ||
(conf.type == HASP_GPIO_RELAY_INVERTED) || (conf.type == HASP_GPIO_PWM_INVERTED);
if(inverted) {
httpMessage += F("High");
} else {
httpMessage += F("Low");
}
// bool inverted = (conf.type == HASP_GPIO_BUTTON_INVERTED) ||
// (conf.type == HASP_GPIO_SWITCH_INVERTED) || (conf.type == HASP_GPIO_LED_INVERTED)
// || (conf.type == HASP_GPIO_RELAY_INVERTED) || (conf.type ==
// HASP_GPIO_PWM_INVERTED);
httpMessage += (conf.type & 0x1) ? F("High") : F("Low");
httpMessage += F("</td><td><a href='/config/gpio/options?id=");
httpMessage += id;