diff --git a/CMakeLists.txt b/CMakeLists.txt index 11653e5..485cc7b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,7 +3,7 @@ set(SRCS "src/configulator.c") if(${ESP_PLATFORM}) list(APPEND REQUIRES nvs_flash) - list(APPEND SRCS "src/cfglr_nvs.c") + list(APPEND SRCS src/cfglr_nvs.c src/cfglr_signal_idf_event.c) endif() idf_component_register( diff --git a/include/cfglr_log.h b/include/cfglr_log.h index 5a3defd..7457f54 100644 --- a/include/cfglr_log.h +++ b/include/cfglr_log.h @@ -6,9 +6,11 @@ #include "cfglr_nvs.h" #define CFGLR_LOGI(TAG, STR, ...) ESP_LOGI(TAG, STR, ##__VA_ARGS__) +#define CFGLR_LOGD(TAG, STR, ...) ESP_LOGD(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__); #endif #endif diff --git a/include/cfglr_nvs.h b/include/cfglr_nvs.h index 1772812..8e6e07d 100644 --- a/include/cfglr_nvs.h +++ b/include/cfglr_nvs.h @@ -6,8 +6,10 @@ void cfglr_backend_nvs_open(cfglr_backend_t *backend, cfglr_handle_t *handle); void cfglr_backend_nvs_close(cfglr_backend_t *backend, cfglr_handle_t *handle); +uint16_t cfglr_backend_nvs_get(cfglr_backend_t *backend, cfglr_element_t *element, cfglr_handle_t *handle); +uint16_t cfglr_backend_nvs_set(cfglr_backend_t *backend, cfglr_element_t *element, cfglr_handle_t *handle); -#define CFGLR_BACKEND_NVS() CFGLR_BACKEND(&cfglr_backend_nvs_open, &cfglr_backend_nvs_close) +#define CFGLR_BACKEND_NVS() CFGLR_BACKEND(&cfglr_backend_nvs_open, &cfglr_backend_nvs_close, &cfglr_backend_nvs_get, cfglr_backend_nvs_set) #endif #endif diff --git a/include/cfglr_signaler_idf_event.h b/include/cfglr_signaler_idf_event.h new file mode 100644 index 0000000..30faadc --- /dev/null +++ b/include/cfglr_signaler_idf_event.h @@ -0,0 +1,13 @@ +#ifndef __IDF_EVENT_H__ +#define __IDF_EVENT_H__ + +#include "configulator.h" + +uint8_t cfglr_signaler_idf_init(cfglr_signaler_t *signaler, cfglr_handle_t *handle); +uint8_t cfglr_signaler_idf_dispatch(cfglr_signaler_t *signaler, cfglr_element_t *element, cfglr_signal_e sig); + +#define CFGLR_SIGNALER_IDF_EVENT() {\ + .dispatch = &cfglr_signaler_idf_dispatch,\ +} + +#endif diff --git a/include/configulator.h b/include/configulator.h index 33b27c1..398317d 100644 --- a/include/configulator.h +++ b/include/configulator.h @@ -5,9 +5,16 @@ #define CFGLR_BACKENDS_MAX (04) #define CFGLR_ELEMENTS_MAX (04) +#define CFGLR_SIGNALERS_MAX (04) typedef enum { - CFGLR_DATATYPE_U8, + CFGLR_SIGNAL_LOADED = 0, + CFGLR_SIGNAL_CHANGE, + CFGLR_SIGNAL_DELETE, +} cfglr_signal_e; + +typedef enum { + CFGLR_DATATYPE_U8 = 0, CFGLR_DATATYPE_I8, CFGLR_DATATYPE_U16, CFGLR_DATATYPE_I16, @@ -19,53 +26,74 @@ typedef enum { CFGLR_DATATYPE_BIN, } cfglr_datatype_e; -typedef void (*cfglr_read_callback)(const char *key, void *out); -typedef void (*cfglr_write_callback)(const char *key, void *valoue, uint8_t length); - -typedef struct { - cfglr_read_callback read; - cfglr_write_callback write; -} cfglr_data_handler_t; +#define CFGLR_DATATYPE_COUNT (uint8_t)(CFGLR_DATATYPE_BIN - CFGLR_DATATYPE_U8) typedef struct { const char *key; uint8_t dirty; cfglr_datatype_e datatype; - void *default_data; + uint8_t datatype_size; void *data; + void *default_data; } cfglr_element_t; -#define CFGLR_ELEMENT(KEY, TYPE, DEFAULT) (cfglr_element_t){\ +typedef struct cfglr_signaler cfglr_signaler_t; +typedef struct cfglr_handle_struct cfglr_handle_t; + +typedef void (*cfglr_signaler_init_t)(cfglr_signaler_t *signaler, 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 { + cfglr_signaler_dispatch_t dispatch; + cfglr_signaler_init_t init; + void *handle; +}; + +#define CFGLR_ELEMENT(KEY, TYPE, DEFAULT, SIZE) (cfglr_element_t){\ .key = KEY,\ .dirty = 1,\ + .datatype = TYPE,\ + .datatype_size = SIZE,\ .default_data = (void*)DEFAULT,\ - .datatype = TYPE\ } -#define CFGLR_ELEMENT_U8(KEY, DEFAULT) CFGLR_ELEMENT(KEY, CFGLR_DATATYPE_U8, DEFAULT) +#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_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)) typedef struct cfglr_backend cfglr_backend_t; -typedef struct cfglr_handle_struct cfglr_handle_t; typedef void (*cfglr_backend_open_t)(cfglr_backend_t *backend, cfglr_handle_t *handle); typedef void (*cfglr_backend_close_t)(cfglr_backend_t *backend, cfglr_handle_t *handle); -typedef void (*cfglr_backend_get_t)(cfglr_backend_t *backend, cfglr_element_t *element, cfglr_handle_t *handle); +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_data(cfglr_backend_t *backend, cfglr_element_t *element, cfglr_handle_t *handle); struct cfglr_backend { cfglr_backend_open_t open; cfglr_backend_close_t close; cfglr_backend_get_t get; + cfglr_backend_set_t set; void *handle; }; -#define CFGLR_BACKEND(OPEN, CLOSE) {\ +#define CFGLR_BACKEND(OPEN, CLOSE, GET, SET) {\ .open = OPEN,\ .close = CLOSE,\ + .get = GET,\ + .set = SET,\ } struct cfglr_handle_struct { const char *namespace; - uint8_t store_defaults; + 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_element_t elements[CFGLR_ELEMENTS_MAX]; }; @@ -74,5 +102,6 @@ uint8_t cfglr_init(cfglr_handle_t *handle); uint8_t cfglr_fetch_data(cfglr_backend_t *backend, cfglr_element_t *element, cfglr_handle_t *handler); #include "cfglr_nvs.h" +#include "cfglr_signaler_idf_event.h" #endif//__CONFIGULATOR_H__ diff --git a/src/cfglr_nvs.c b/src/cfglr_nvs.c index 298bda7..e9cfd11 100644 --- a/src/cfglr_nvs.c +++ b/src/cfglr_nvs.c @@ -9,3 +9,112 @@ void cfglr_backend_nvs_open(cfglr_backend_t *backend, cfglr_handle_t *handle) { void cfglr_backend_nvs_close(cfglr_backend_t *backend, cfglr_handle_t *handle) { } + + +uint16_t cfglr_backend_nvs_get(cfglr_backend_t *backend, cfglr_element_t *element, cfglr_handle_t *handle) { + esp_err_t err = ESP_OK; + + if(element->datatype <= CFGLR_DATATYPE_I32) { + switch(element->datatype) { + case CFGLR_DATATYPE_U8: + err = nvs_get_u8((nvs_handle_t)backend->handle, element->key, (uint8_t*)element->data); + break; + + case CFGLR_DATATYPE_I8: + 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; + + case CFGLR_DATATYPE_I16: + err = nvs_get_i16((nvs_handle_t)backend->handle, element->key, (int16_t*)element->data); + break; + + case CFGLR_DATATYPE_U32: + err = nvs_get_u32((nvs_handle_t)backend->handle, element->key, (uint32_t*)element->data); + break; + + case CFGLR_DATATYPE_I32: + err = nvs_get_i32((nvs_handle_t)backend->handle, element->key, (int32_t*)element->data); + break; + + case CFGLR_DATATYPE_U64: + err = nvs_get_u64((nvs_handle_t)backend->handle, element->key, (uint64_t*)element->data); + break; + + 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) { + } else if(err != ESP_OK) { + ESP_ERROR_CHECK(err); + } else if(err == ESP_OK) { + element->dirty = 0; + } + } else { + // handle [UI]64, STR and BIN datatype + } + + return err; +} + +uint16_t cfglr_backend_nvs_set(cfglr_backend_t *backend, cfglr_element_t *element, cfglr_handle_t *handle) { + esp_err_t err = ESP_OK; + + switch(element->datatype) { + case CFGLR_DATATYPE_U8: + 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); + break; + + case CFGLR_DATATYPE_U16: + 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); + break; + + case CFGLR_DATATYPE_U32: + 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); + break; + + case CFGLR_DATATYPE_U64: + 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); + break; + + case CFGLR_DATATYPE_STR: + case CFGLR_DATATYPE_BIN: + // determine length + // fetch data by length + break; + + default: + CFGLR_LOGI(TAG, "unhandlable datatype: %d", element->datatype); + } + + if(err == ESP_OK) { + } + + return err; +} diff --git a/src/cfglr_signal_idf_event.c b/src/cfglr_signal_idf_event.c new file mode 100644 index 0000000..3b116c2 --- /dev/null +++ b/src/cfglr_signal_idf_event.c @@ -0,0 +1,10 @@ +#include "cfglr_log.h" +#include "cfglr_signaler_idf_event.h" + +#define TAG "CFGLR_SIG_IDF" + +uint8_t cfglr_signaler_idf_dispatch(cfglr_signaler_t *signaler, cfglr_element_t *element, cfglr_signal_e sig) { + CFGLR_LOGI(TAG, "Dispatch!: %d", sig); + + return 0; +} diff --git a/src/configulator.c b/src/configulator.c index fd1fcd8..0dcf798 100644 --- a/src/configulator.c +++ b/src/configulator.c @@ -1,3 +1,4 @@ +#include "string.h" #include "configulator.h" #include "cfglr_log.h" @@ -7,25 +8,74 @@ uint8_t cfglr_init(cfglr_handle_t *handle) { uint8_t tick = 0; cfglr_backend_t *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; 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])) { if(element->key == NULL) break; - // all elements should start out dirty, = - // they should be fetched, or defaulted - if(element->dirty) { - backend->get(backend, element, handle); + 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); + + element->data = (void*)malloc(element->datatype_size); + + 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); + } + } } + + ++handle->element_count; + ++tick; } + 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); + + if(ret == 0) { + for(uint8_t i = 0; i < handle->signaler_count; i++) { + handle->signalers[i].dispatch(&handle->signalers[i], element, CFGLR_SIGNAL_CHANGE); + } + } + + return ret; +}