typedef struct sample_store_s *sample_store_handle_t;Opaque handle for the sample store instance.
typedef struct sample_store_iterator_s *sample_store_iterator_handle_t;Opaque handle for sample iterator instances.
typedef enum {
SAMPLE_STORE_EVENT_PRE_OVERWRITE_SAMPLE = 0, /**< Before overwriting oldest sample in a set */
SAMPLE_STORE_EVENT_POST_OVERWRITE_SAMPLE, /**< After overwriting oldest sample in a set */
SAMPLE_STORE_EVENT_PRE_OVERWRITE_SET, /**< Before overwriting oldest set */
SAMPLE_STORE_EVENT_POST_OVERWRITE_SET /**< After overwriting oldest set */
} sample_store_event_type_t;Event types for retention control callbacks.
typedef void (*sample_store_event_handler_t)(sample_store_event_type_t type,
const char *set_name,
const char *key,
void *user_ctx);Event handler callback function signature.
Parameters:
type: Type of retention eventset_name: Name of the affected set (can be NULL)key: Affected sample key in hex format (can be NULL)user_ctx: User-provided context pointer
esp_err_t sample_store_init(sample_store_handle_t *handle);Initialize the sample store handle and NVS partition.
Parameters:
handle: [out] Pointer to store the initialized handle
Returns:
ESP_OK: SuccessESP_ERR_INVALID_ARG: Invalid handle pointerESP_ERR_NO_MEM: Memory allocation failed- Other ESP-IDF NVS error codes
Example:
sample_store_handle_t store = NULL;
esp_err_t err = sample_store_init(&store);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Failed to initialize sample store: %s", esp_err_to_name(err));
return;
}void sample_store_deinit(sample_store_handle_t handle);Deinitialize the sample store handle and free resources.
Parameters:
handle: [in] Handle to deinitialize (can be NULL)
Example:
sample_store_deinit(store);esp_err_t sample_store_write_to_set(sample_store_handle_t handle,
const char *set_name,
const void *data,
size_t size);Write a sample blob to a user-defined set (namespace).
Parameters:
handle: [in] Sample store handleset_name: [in] Name of the set (max 15 chars + null terminator)data: [in] Pointer to the data blobsize: [in] Size of the data blob
Returns:
ESP_OK: SuccessESP_ERR_INVALID_ARG: Invalid parametersESP_ERR_NVS_NOT_ENOUGH_SPACE: No space left in partition- Other ESP-IDF NVS error codes
Notes:
- If the set doesn't exist, it will be created automatically
- If maximum sets exceeded, oldest set may be removed (with events)
- If maximum samples per set exceeded, oldest sample may be removed (with events)
Example:
typedef struct {
float temperature;
uint32_t timestamp;
} sensor_data_t;
sensor_data_t data = {25.5, esp_timer_get_time()};
esp_err_t err = sample_store_write_to_set(store, "temperature", &data, sizeof(data));esp_err_t sample_store_read_from_set(sample_store_handle_t handle,
const char *set_name,
const char *hex_key,
void *data,
size_t *size);Read a sample blob from a set using its hex key.
Parameters:
handle: [in] Sample store handleset_name: [in] Name of the sethex_key: [in] Sample key in 6-digit hex format (e.g., "000001")data: [out] Buffer to store the blob, or NULL to get required sizesize: [inout] Pointer to buffer size; updated with actual size
Returns:
ESP_OK: SuccessESP_ERR_INVALID_ARG: Invalid parametersESP_ERR_NVS_NOT_FOUND: Set or key not found- Other ESP-IDF NVS error codes
Size Query Pattern:
// First, get the required size
size_t required_size = 0;
esp_err_t err = sample_store_read_from_set(store, "sensors", "000001", NULL, &required_size);
if (err == ESP_OK) {
// Allocate buffer and read actual data
void *buffer = malloc(required_size);
size_t actual_size = required_size;
err = sample_store_read_from_set(store, "sensors", "000001", buffer, &actual_size);
// Use data...
free(buffer);
}esp_err_t sample_store_get_set_range(sample_store_handle_t handle,
const char *set_name,
uint32_t *min_counter,
uint32_t *max_counter);Get the range of sample indices (oldest and newest) for a specific set.
Parameters:
handle: [in] Sample store handleset_name: [in] Name of the setmin_counter: [out] Oldest sample indexmax_counter: [out] Newest sample index
Returns:
ESP_OK: SuccessESP_ERR_INVALID_ARG: Invalid parametersESP_ERR_NOT_FOUND: Set doesn't exist
Example:
uint32_t min_counter, max_counter;
esp_err_t err = sample_store_get_set_range(store, "sensors", &min_counter, &max_counter);
if (err == ESP_OK) {
uint32_t total_samples = max_counter - min_counter + 1;
ESP_LOGI(TAG, "Set 'sensors' has %lu samples (range: %06lx-%06lx)",
total_samples, min_counter, max_counter);
}esp_err_t sample_store_list_sets(sample_store_handle_t handle,
char ***sets,
size_t *count);List all sets with stored samples, ordered from oldest to newest.
Parameters:
handle: [in] Sample store handlesets: [out] Array of set name strings (must be freed by caller)count: [out] Number of sets returned
Returns:
ESP_OK: SuccessESP_ERR_INVALID_ARG: Invalid parametersESP_ERR_NO_MEM: Memory allocation failed
Memory Management:
char **set_list = NULL;
size_t set_count = 0;
esp_err_t err = sample_store_list_sets(store, &set_list, &set_count);
if (err == ESP_OK) {
for (size_t i = 0; i < set_count; i++) {
ESP_LOGI(TAG, "Set %zu: %s", i, set_list[i]);
}
// Free allocated memory
if (set_list) {
for (size_t i = 0; i < set_count; i++) {
free(set_list[i]);
}
free(set_list);
}
}void sample_store_set_event_handler(sample_store_handle_t handle,
sample_store_event_handler_t cb,
void *user_ctx);Register an event handler for retention events.
Parameters:
handle: [in] Sample store handlecb: [in] Event handler callback (can be NULL to unregister)user_ctx: [in] User context pointer passed to callback
Example:
static void my_event_handler(sample_store_event_type_t type,
const char *set_name,
const char *key,
void *user_ctx) {
const char *event_names[] = {
"PRE_OVERWRITE_SAMPLE", "POST_OVERWRITE_SAMPLE",
"PRE_OVERWRITE_SET", "POST_OVERWRITE_SET"
};
ESP_LOGW(TAG, "Retention event: %s (set: %s, key: %s)",
event_names[type], set_name ? set_name : "N/A", key ? key : "N/A");
}
// Register handler
sample_store_set_event_handler(store, my_event_handler, NULL);esp_err_t sample_store_iterator_new(sample_store_handle_t handle,
const char *set_name,
uint32_t start_counter,
uint32_t end_counter,
sample_store_iterator_handle_t *iterator);Create a new iterator for a subset of samples in a set.
Parameters:
handle: [in] Sample store handleset_name: [in] Name of the setstart_counter: [in] Starting sample index (inclusive)end_counter: [in] Ending sample index (inclusive)iterator: [out] Pointer to store the iterator handle
Returns:
ESP_OK: SuccessESP_ERR_INVALID_ARG: Invalid parameters or start > endESP_ERR_NO_MEM: Memory allocation failedESP_ERR_NOT_FOUND: First sample not found (iterator still created)
Example:
sample_store_iterator_handle_t iterator;
uint32_t min_counter, max_counter;
sample_store_get_set_range(store, "sensors", &min_counter, &max_counter);
esp_err_t err = sample_store_iterator_new(store, "sensors", min_counter, max_counter, &iterator);
if (err == ESP_OK) {
// Use iterator...
sample_store_iterator_free(iterator);
}void sample_store_iterator_free(sample_store_iterator_handle_t iterator);Free an iterator and its resources.
Parameters:
iterator: [in] Iterator handle to free (can be NULL)
esp_err_t sample_store_iterator_next(sample_store_iterator_handle_t iterator);Move iterator to the next sample (toward newer samples).
Parameters:
iterator: [in] Iterator handle
Returns:
ESP_OK: SuccessESP_ERR_INVALID_ARG: Invalid iteratorESP_ERR_NOT_FOUND: Already at end or beyond range
esp_err_t sample_store_iterator_prev(sample_store_iterator_handle_t iterator);Move iterator to the previous sample (toward older samples).
Parameters:
iterator: [in] Iterator handle
Returns:
ESP_OK: SuccessESP_ERR_INVALID_ARG: Invalid iteratorESP_ERR_NOT_FOUND: Already at beginning or beyond range
esp_err_t sample_store_iterator_goto(sample_store_iterator_handle_t iterator,
uint32_t counter);Move iterator to a specific sample index.
Parameters:
iterator: [in] Iterator handlecounter: [in] Sample index to move to
Returns:
ESP_OK: SuccessESP_ERR_INVALID_ARG: Invalid iteratorESP_ERR_NOT_FOUND: Counter outside iterator range or sample doesn't exist
esp_err_t sample_store_iterator_get_sample(sample_store_iterator_handle_t iterator,
void **data,
size_t *size);Get the current sample data from the iterator.
Parameters:
iterator: [in] Iterator handledata: [out] Pointer to store the sample data pointersize: [out] Pointer to store the sample size
Returns:
ESP_OK: SuccessESP_ERR_INVALID_ARG: Invalid parametersESP_ERR_NOT_FOUND: Current position invalid or no data
Notes:
- Returned data pointer is managed by the iterator
- Data is valid until iterator is moved or freed
- Do not modify or free the returned data
Example:
void *data;
size_t size;
esp_err_t err = sample_store_iterator_get_sample(iterator, &data, &size);
if (err == ESP_OK && size == sizeof(sensor_data_t)) {
sensor_data_t *sensor = (sensor_data_t*)data;
ESP_LOGI(TAG, "Temperature: %.1f°C", sensor->temperature);
}esp_err_t sample_store_iterator_get_current_counter(sample_store_iterator_handle_t iterator,
uint32_t *counter);Get the current sample index of the iterator.
Parameters:
iterator: [in] Iterator handlecounter: [out] Pointer to store the current counter
Returns:
ESP_OK: SuccessESP_ERR_INVALID_ARG: Invalid parameters
esp_err_t sample_store_iterator_delete_sample(sample_store_iterator_handle_t iterator);Delete the current sample pointed to by the iterator.
Parameters:
iterator: [in] Iterator handle
Returns:
ESP_OK: SuccessESP_ERR_INVALID_ARG: Invalid iteratorESP_ERR_INVALID_STATE: Sample is not first or last in setESP_ERR_NOT_FOUND: Set not found or no current sample
Restrictions:
- Only oldest (first) or newest (last) samples can be deleted
- After deletion, iterator is repositioned to the new first/last sample
- If set becomes empty, iterator becomes invalid
Example:
// Delete oldest sample
sample_store_iterator_handle_t iterator;
uint32_t min_counter, max_counter;
sample_store_get_set_range(store, "sensors", &min_counter, &max_counter);
sample_store_iterator_new(store, "sensors", min_counter, max_counter, &iterator);
// Iterator starts at oldest sample
esp_err_t err = sample_store_iterator_delete_sample(iterator);
if (err == ESP_OK) {
ESP_LOGI(TAG, "Deleted oldest sample");
}
sample_store_iterator_free(iterator);The component returns standard ESP-IDF error codes:
| Error Code | Description |
|---|---|
ESP_OK |
Operation successful |
ESP_ERR_INVALID_ARG |
Invalid argument passed |
ESP_ERR_NO_MEM |
Memory allocation failed |
ESP_ERR_NOT_FOUND |
Set, sample, or data not found |
ESP_ERR_INVALID_STATE |
Operation not allowed in current state |
ESP_ERR_NVS_* |
NVS-specific error codes |
sample_store_iterator_handle_t iterator;
uint32_t min_counter, max_counter;
// Get full range
sample_store_get_set_range(store, "data", &min_counter, &max_counter);
sample_store_iterator_new(store, "data", min_counter, max_counter, &iterator);
// Process all samples
do {
void *data;
size_t size;
uint32_t counter;
if (sample_store_iterator_get_sample(iterator, &data, &size) == ESP_OK) {
sample_store_iterator_get_current_counter(iterator, &counter);
process_sample(data, size, counter);
}
} while (sample_store_iterator_next(iterator) == ESP_OK);
sample_store_iterator_free(iterator);// Process only last 10 samples
uint32_t min_counter, max_counter;
sample_store_get_set_range(store, "data", &min_counter, &max_counter);
uint32_t start = (max_counter >= 9) ? max_counter - 9 : min_counter;
sample_store_iterator_new(store, "data", start, max_counter, &iterator);
// ... process range// Delete all samples in a set (oldest first)
uint32_t min_counter, max_counter;
while (sample_store_get_set_range(store, "temp_data", &min_counter, &max_counter) == ESP_OK) {
sample_store_iterator_handle_t iterator;
sample_store_iterator_new(store, "temp_data", min_counter, max_counter, &iterator);
esp_err_t err = sample_store_iterator_delete_sample(iterator);
sample_store_iterator_free(iterator);
if (err != ESP_OK) break; // Set is empty or error occurred
}