diff --git a/CMakeLists.txt b/CMakeLists.txt index dc7f00a..365902a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,6 +6,10 @@ if(${ESP_PLATFORM}) list(APPEND SRCS src/cfglr_nvs.c src/cfglr_signal_idf_event.c) endif() +# make LVGL configurable +list(APPEND REQUIRES lvgl) +list(APPEND SRCS src/cfglr_signal_lvgl.c) + idf_component_register( SRCS ${SRCS} INCLUDE_DIRS "include" diff --git a/include/cfglr_log.h b/include/cfglr_log.h index 7457f54..ff4363e 100644 --- a/include/cfglr_log.h +++ b/include/cfglr_log.h @@ -7,10 +7,14 @@ #define CFGLR_LOGI(TAG, STR, ...) ESP_LOGI(TAG, STR, ##__VA_ARGS__) #define CFGLR_LOGD(TAG, STR, ...) ESP_LOGD(TAG, STR, ##__VA_ARGS__) +#define CFGLR_LOGE(TAG, STR, ...) ESP_LOGE(TAG, STR, ##__VA_ARGS__) +#define CFGLR_LOGW(TAG, STR, ...) ESP_LOGW(TAG, STR, ##__VA_ARGS__) #else #define CFGLR_LOGI(TAG, STR, ...) print(TAG); printf(STR, ##__VA_ARGS__); #define CFGLR_LOGD(TAG, STR, ...) print(TAG); printf(STR, ##__VA_ARGS__); +#define CFGLR_LOGE(TAG, STR, ...) print(TAG); printf(STR, ##__VA_ARGS__); +#define CFGLR_LOGW(TAG, STR, ...) print(TAG); printf(STR, ##__VA_ARGS__); #endif #endif diff --git a/include/cfglr_signaler_lvgl.h b/include/cfglr_signaler_lvgl.h new file mode 100644 index 0000000..f47d484 --- /dev/null +++ b/include/cfglr_signaler_lvgl.h @@ -0,0 +1,16 @@ +#ifndef _CFGLR_SIGNAL_LVGL_H_ +#define _CFGLR_SIGNAL_LVGL_H_ + +#include "configulator.h" + +uint8_t cfglr_signaler_lvgl_init(cfglr_signaler_t *signaler, cfglr_element_t *element, cfglr_handle_t *handle); +uint8_t cfglr_signaler_lvgl_dispatch(cfglr_signaler_t *signaler, cfglr_element_t *element, cfglr_signal_e sig); + +#define CFGLR_SIGNALER_LVGL(KEY, LV_OBJ) {\ + .key = KEY,\ + .init = &cfglr_signaler_lvgl_init,\ + .dispatch = &cfglr_signaler_lvgl_dispatch,\ + .handle = LV_OBJ,\ +} + +#endif diff --git a/include/configulator.h b/include/configulator.h index 398317d..78a6c7e 100644 --- a/include/configulator.h +++ b/include/configulator.h @@ -4,7 +4,7 @@ #include #define CFGLR_BACKENDS_MAX (04) -#define CFGLR_ELEMENTS_MAX (04) +#define CFGLR_ELEMENTS_MAX (12) #define CFGLR_SIGNALERS_MAX (04) typedef enum { @@ -28,30 +28,35 @@ typedef enum { #define CFGLR_DATATYPE_COUNT (uint8_t)(CFGLR_DATATYPE_BIN - CFGLR_DATATYPE_U8) -typedef struct { - const char *key; - uint8_t dirty; - cfglr_datatype_e datatype; - uint8_t datatype_size; - void *data; - void *default_data; -} cfglr_element_t; - typedef struct cfglr_signaler cfglr_signaler_t; typedef struct cfglr_handle_struct cfglr_handle_t; +typedef struct cfglr_element cfglr_element_t; -typedef void (*cfglr_signaler_init_t)(cfglr_signaler_t *signaler, cfglr_handle_t *handle); +typedef void (*cfglr_signaler_init_t)(cfglr_signaler_t *signaler, cfglr_element_t *element, cfglr_handle_t *handle); typedef void (*cfglr_signaler_dispatch_t)(cfglr_signaler_t *signaler, cfglr_element_t *element, cfglr_signal_e sig); struct cfglr_signaler { + const char *key; cfglr_signaler_dispatch_t dispatch; cfglr_signaler_init_t init; void *handle; }; +struct cfglr_element { + const char *key; + uint8_t dirty; + uint8_t signaler_count; + cfglr_datatype_e datatype; + // TODO precalcualte sizes in an array and use datatype enum to look up + uint8_t datatype_size; + void *data; + void *default_data; + cfglr_handle_t *handle; + cfglr_signaler_t signalers[CFGLR_SIGNALERS_MAX]; +}; + #define CFGLR_ELEMENT(KEY, TYPE, DEFAULT, SIZE) (cfglr_element_t){\ .key = KEY,\ - .dirty = 1,\ .datatype = TYPE,\ .datatype_size = SIZE,\ .default_data = (void*)DEFAULT,\ @@ -59,7 +64,10 @@ struct cfglr_signaler { #define CFGLR_ELEMENT_U8(KEY, DEFAULT) CFGLR_ELEMENT(KEY, CFGLR_DATATYPE_U8, DEFAULT, sizeof(uint8_t)) #define CFGLR_ELEMENT_I8(KEY, DEFAULT) CFGLR_ELEMENT(KEY, CFGLR_DATATYPE_I8, DEFAULT, sizeof(int8_t)) - +#define CFGLR_ELEMENT_U16(KEY, DEFAULT) CFGLR_ELEMENT(KEY, CFGLR_DATATYPE_U16, DEFAULT, sizeof(uint16_t)) +#define CFGLR_ELEMENT_I16(KEY, DEFAULT) CFGLR_ELEMENT(KEY, CFGLR_DATATYPE_I16, DEFAULT, sizeof(int16_t)) +#define CFGLR_ELEMENT_U32(KEY, DEFAULT) CFGLR_ELEMENT(KEY, CFGLR_DATATYPE_U32, DEFAULT, sizeof(uint32_t)) +#define CFGLR_ELEMENT_I32(KEY, DEFAULT) CFGLR_ELEMENT(KEY, CFGLR_DATATYPE_I32, DEFAULT, sizeof(int32_t)) #define CFGLR_ELEMENT_U64(KEY, DEFAULT) CFGLR_ELEMENT(KEY, CFGLR_DATATYPE_U64, DEFAULT, sizeof(uint64_t)) #define CFGLR_ELEMENT_I64(KEY, DEFAULT) CFGLR_ELEMENT(KEY, CFGLR_DATATYPE_I64, DEFAULT, sizeof(int64_t)) @@ -70,6 +78,7 @@ typedef void (*cfglr_backend_close_t)(cfglr_backend_t *backend, cfglr_handle_t * typedef uint16_t (*cfglr_backend_get_t)(cfglr_backend_t *backend, cfglr_element_t *element, cfglr_handle_t *handle); typedef uint16_t (*cfglr_backend_set_t)(cfglr_backend_t *backend, cfglr_element_t *element, cfglr_handle_t *handle); +uint16_t cfglr_commit(cfglr_element_t *element); uint16_t cfglr_commit_data(cfglr_backend_t *backend, cfglr_element_t *element, cfglr_handle_t *handle); struct cfglr_backend { @@ -92,9 +101,7 @@ struct cfglr_handle_struct { uint8_t store_default; uint8_t backend_count; uint8_t element_count; - uint8_t signaler_count; - cfglr_signaler_t signalers[CFGLR_SIGNALERS_MAX]; - cfglr_backend_t backends[CFGLR_BACKENDS_MAX]; + cfglr_backend_t backend; cfglr_element_t elements[CFGLR_ELEMENTS_MAX]; }; @@ -103,5 +110,6 @@ uint8_t cfglr_fetch_data(cfglr_backend_t *backend, cfglr_element_t *element, cfg #include "cfglr_nvs.h" #include "cfglr_signaler_idf_event.h" +#include "cfglr_signaler_lvgl.h" #endif//__CONFIGULATOR_H__ diff --git a/src/cfglr_nvs.c b/src/cfglr_nvs.c index e9cfd11..8857b60 100644 --- a/src/cfglr_nvs.c +++ b/src/cfglr_nvs.c @@ -4,7 +4,10 @@ void cfglr_backend_nvs_open(cfglr_backend_t *backend, cfglr_handle_t *handle) { CFGLR_LOGI(TAG, "opening NVS partition: %s", handle->namespace); + esp_err_t err = nvs_open(handle->namespace, NVS_READWRITE, (nvs_handle_t*)&backend->handle); + + ESP_ERROR_CHECK(err); } void cfglr_backend_nvs_close(cfglr_backend_t *backend, cfglr_handle_t *handle) { @@ -24,7 +27,6 @@ uint16_t cfglr_backend_nvs_get(cfglr_backend_t *backend, cfglr_element_t *elemen err = nvs_get_i8((nvs_handle_t)backend->handle, element->key, (int8_t*)element->data); break; - /* case CFGLR_DATATYPE_U16: err = nvs_get_u16((nvs_handle_t)backend->handle, element->key, (uint16_t*)element->data); break; @@ -48,13 +50,13 @@ uint16_t cfglr_backend_nvs_get(cfglr_backend_t *backend, cfglr_element_t *elemen case CFGLR_DATATYPE_I64: err = nvs_get_i64((nvs_handle_t)backend->handle, element->key, (int64_t*)element->data); break; - */ default: CFGLR_LOGI(TAG, "unhandlable datatype: %d", element->datatype); } if(err == ESP_ERR_NVS_NOT_FOUND) { + CFGLR_LOGI(TAG, "NOT FOUN!!!!"); } else if(err != ESP_OK) { ESP_ERROR_CHECK(err); } else if(err == ESP_OK) { @@ -70,37 +72,40 @@ uint16_t cfglr_backend_nvs_get(cfglr_backend_t *backend, cfglr_element_t *elemen uint16_t cfglr_backend_nvs_set(cfglr_backend_t *backend, cfglr_element_t *element, cfglr_handle_t *handle) { esp_err_t err = ESP_OK; + CFGLR_LOGI(TAG, "setting %s", element->key); + switch(element->datatype) { case CFGLR_DATATYPE_U8: - err = nvs_set_u8((nvs_handle_t)backend->handle, element->key, (uint8_t)element->data); + CFGLR_LOGI(TAG, "value %d", *(int*)element->data); + err = nvs_set_u8((nvs_handle_t)backend->handle, element->key, *(uint8_t*)element->data); break; case CFGLR_DATATYPE_I8: - err = nvs_set_i8((nvs_handle_t)backend->handle, element->key, (int8_t)element->data); + err = nvs_set_i8((nvs_handle_t)backend->handle, element->key, *(int8_t*)element->data); break; case CFGLR_DATATYPE_U16: - err = nvs_set_u16((nvs_handle_t)backend->handle, element->key, (uint16_t)element->data); + err = nvs_set_u16((nvs_handle_t)backend->handle, element->key, *(uint16_t*)element->data); break; case CFGLR_DATATYPE_I16: - err = nvs_set_i16((nvs_handle_t)backend->handle, element->key, (int16_t)element->data); + err = nvs_set_i16((nvs_handle_t)backend->handle, element->key, *(int16_t*)element->data); break; case CFGLR_DATATYPE_U32: - err = nvs_set_u32((nvs_handle_t)backend->handle, element->key, (uint32_t)element->data); + err = nvs_set_u32((nvs_handle_t)backend->handle, element->key, *(uint32_t*)element->data); break; case CFGLR_DATATYPE_I32: - err = nvs_set_i32((nvs_handle_t)backend->handle, element->key, (int32_t)element->data); + err = nvs_set_i32((nvs_handle_t)backend->handle, element->key, *(int32_t*)element->data); break; case CFGLR_DATATYPE_U64: - err = nvs_set_u64((nvs_handle_t)backend->handle, element->key, (uint64_t)element->data); + err = nvs_set_u64((nvs_handle_t)backend->handle, element->key, *(uint64_t*)element->data); break; case CFGLR_DATATYPE_I64: - err = nvs_set_i64((nvs_handle_t)backend->handle, element->key, (int64_t)element->data); + err = nvs_set_i64((nvs_handle_t)backend->handle, element->key, *(int64_t*)element->data); break; case CFGLR_DATATYPE_STR: @@ -113,6 +118,8 @@ uint16_t cfglr_backend_nvs_set(cfglr_backend_t *backend, cfglr_element_t *elemen CFGLR_LOGI(TAG, "unhandlable datatype: %d", element->datatype); } + err = nvs_commit((nvs_handle_t)backend->handle); + if(err == ESP_OK) { } diff --git a/src/cfglr_signal_idf_event.c b/src/cfglr_signal_idf_event.c index c392170..8225837 100644 --- a/src/cfglr_signal_idf_event.c +++ b/src/cfglr_signal_idf_event.c @@ -12,6 +12,10 @@ const char* cfglr_signal_names[] = { "CFGLR_SIGNAL_DELETE", }; +uint8_t cfglr_signaler_idf_init(cfglr_signaler_t *signaler, cfglr_handle_t *handle) { + return 0; +} + uint8_t cfglr_signaler_idf_dispatch(cfglr_signaler_t *signaler, cfglr_element_t *element, cfglr_signal_e sig) { CFGLR_LOGI(TAG, "dispatch: %s", cfglr_signal_names[sig]); diff --git a/src/cfglr_signal_lvgl.c b/src/cfglr_signal_lvgl.c new file mode 100644 index 0000000..69b7e49 --- /dev/null +++ b/src/cfglr_signal_lvgl.c @@ -0,0 +1,49 @@ +#include "cfglr_log.h" +#include "cfglr_signaler_lvgl.h" +#include "lvgl.h" + +#define TAG "CFGLR_SIG_LVGL" + +void cfglr_signaler_lvgl_change_cb(lv_event_t *e) { + lv_obj_t *target = lv_event_get_current_target(e); + cfglr_element_t *element = lv_event_get_user_data(e); + + if(lv_obj_check_type(target, &lv_checkbox_class)) { + lv_state_t state = lv_obj_get_state(target); + + uint8_t mon = *(int*)element->data; + // A new event is pushed when dispatching so the loop needs to be broken if the value + // didn't actually change. + if(mon != (state & LV_STATE_CHECKED)) { + CFGLR_LOGD(TAG, "element->data: %p %d", element->data, *(uint8_t*)element->data); + + *(int*)(element->data) = (state & LV_STATE_CHECKED); + cfglr_commit(element); + } + } +} + +uint8_t cfglr_signaler_lvgl_init(cfglr_signaler_t *signaler, cfglr_element_t *element, cfglr_handle_t *handle) { + CFGLR_LOGI(TAG, "init"); + + CFGLR_LOGI(TAG, "ui handle: %p", signaler->handle); + lv_obj_add_event_cb((lv_obj_t*)signaler->handle, cfglr_signaler_lvgl_change_cb, LV_EVENT_VALUE_CHANGED, element); + + return 0; +} + +uint8_t cfglr_signaler_lvgl_dispatch(cfglr_signaler_t *signaler, cfglr_element_t *element, cfglr_signal_e sig) { + CFGLR_LOGI(TAG, "dispatch: %d", *(uint8_t*)element->data); + + if(strstr(element->key, "monitor") != NULL) { + if(*(uint8_t*)element->data == 1) { + lv_obj_add_state((lv_obj_t*)signaler->handle, LV_STATE_CHECKED); + } else { + lv_obj_clear_state((lv_obj_t*)signaler->handle, LV_STATE_CHECKED); + } + + lv_event_send((lv_obj_t*)signaler->handle, LV_EVENT_VALUE_CHANGED, NULL); + } + + return 0; +} diff --git a/src/configulator.c b/src/configulator.c index 0dcf798..173f140 100644 --- a/src/configulator.c +++ b/src/configulator.c @@ -5,75 +5,85 @@ #define TAG "CFGLR" uint8_t cfglr_init(cfglr_handle_t *handle) { - uint8_t tick = 0; - cfglr_backend_t *backend; + cfglr_backend_t *backend = &handle->backend; cfglr_element_t *element; cfglr_signaler_t *signaler; - handle->backend_count = 0; handle->element_count = 0; - CFGLR_LOGI(TAG, "initializing backends"); - - while((backend = &handle->backends[tick])) { - if(backend->open == NULL) break; + CFGLR_LOGI(TAG, "initializing backend"); + if(backend->open != NULL) { + CFGLR_LOGI(TAG, "opening backend"); backend->open(backend, handle); - // do error validation - - ++handle->backend_count; - ++tick; } - tick = 0; - - CFGLR_LOGI(TAG, "initializing signalers"); - - while((signaler = &handle->signalers[tick])) { - if(signaler->dispatch == NULL) break; - - if(signaler->init != NULL) { - signaler->init(signaler, handle); - } - - ++handle->signaler_count; - ++tick; - } - - tick = 0; - CFGLR_LOGI(TAG, "initializing elements"); - while((element = &handle->elements[tick])) { + while((element = &handle->elements[handle->element_count])) { if(element->key == NULL) break; - CFGLR_LOGD(TAG, "Initializing element: %s", element->key); - CFGLR_LOGD(TAG, "size: %d", element->datatype_size); - CFGLR_LOGD(TAG, "default: %d", (int)element->default_data); + CFGLR_LOGI(TAG, "Initializing element: %s", element->key); + CFGLR_LOGI(TAG, "size: %d", element->datatype_size); + CFGLR_LOGI(TAG, "default: %d", (int)element->default_data); + element->handle = handle; element->data = (void*)malloc(element->datatype_size); + CFGLR_LOGW(TAG, "malloc: %d @ %p", element->datatype_size, element->data); - for(uint8_t i = 0; i < handle->backend_count; i++) { - if(handle->backends[i].get(&handle->backends[i], element, handle) == 0) { - for(uint8_t j = 0; j < handle->signaler_count; j++) { - handle->signalers[i].dispatch(&handle->signalers[i], element, CFGLR_SIGNAL_LOADED); - } + //CFGLR_LOGI(TAG, "element->data: %p", element->data); + + while((signaler = &element->signalers[element->signaler_count])) { + if(signaler->init == NULL && signaler->dispatch == NULL) break; + + if(signaler->init != NULL) { + signaler->init(signaler, element, handle); + } + + element->signaler_count++; + } + + bool dispatch = false; + + if(handle->backend.get(&handle->backend, element, handle) == 0) { + dispatch = true; + } else { + CFGLR_LOGI(TAG, "failed to load %s, setting default", element->key); + + memcpy((void*)element->data, (void*)&element->default_data, element->datatype_size); + if(handle->backend.set(&handle->backend, element, handle) == 0) { + dispatch = true; + } + } + + if(dispatch) { + for(uint8_t i = 0; i < element->signaler_count; i++) { + element->signalers[i].dispatch(&element->signalers[i], element, CFGLR_SIGNAL_LOADED); } } ++handle->element_count; - ++tick; } return 0; } +uint16_t cfglr_commit(cfglr_element_t *element) { + cfglr_handle_t *handle = element->handle; + + cfglr_commit_data(&handle->backend, element, handle); + + return 0; +} + uint16_t cfglr_commit_data(cfglr_backend_t *backend, cfglr_element_t *element, cfglr_handle_t *handle) { uint16_t ret = backend->set(backend, element, handle); + CFGLR_LOGI(TAG, "%s = %d (ret %d) %p", element->key, (uint8_t)&element->data, ret, element->data); + if(ret == 0) { - for(uint8_t i = 0; i < handle->signaler_count; i++) { - handle->signalers[i].dispatch(&handle->signalers[i], element, CFGLR_SIGNAL_CHANGE); + for(uint8_t i = 0; i < element->signaler_count; i++) { + element->signalers[i].dispatch(&element->signalers[i], element, CFGLR_SIGNAL_CHANGE); } }