Skip to content

Latest commit

 

History

History
540 lines (427 loc) · 15.1 KB

File metadata and controls

540 lines (427 loc) · 15.1 KB

Sample Store Component - API Reference

Data Types

Handles

sample_store_handle_t

typedef struct sample_store_s *sample_store_handle_t;

Opaque handle for the sample store instance.

sample_store_iterator_handle_t

typedef struct sample_store_iterator_s *sample_store_iterator_handle_t;

Opaque handle for sample iterator instances.

Enumerations

sample_store_event_type_t

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.

Function Pointers

sample_store_event_handler_t

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 event
  • set_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

Core Functions

Initialization and Cleanup

sample_store_init()

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: Success
  • ESP_ERR_INVALID_ARG: Invalid handle pointer
  • ESP_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;
}

sample_store_deinit()

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);

Data Operations

sample_store_write_to_set()

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 handle
  • set_name: [in] Name of the set (max 15 chars + null terminator)
  • data: [in] Pointer to the data blob
  • size: [in] Size of the data blob

Returns:

  • ESP_OK: Success
  • ESP_ERR_INVALID_ARG: Invalid parameters
  • ESP_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));

sample_store_read_from_set()

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 handle
  • set_name: [in] Name of the set
  • hex_key: [in] Sample key in 6-digit hex format (e.g., "000001")
  • data: [out] Buffer to store the blob, or NULL to get required size
  • size: [inout] Pointer to buffer size; updated with actual size

Returns:

  • ESP_OK: Success
  • ESP_ERR_INVALID_ARG: Invalid parameters
  • ESP_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);
}

Metadata Operations

sample_store_get_set_range()

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 handle
  • set_name: [in] Name of the set
  • min_counter: [out] Oldest sample index
  • max_counter: [out] Newest sample index

Returns:

  • ESP_OK: Success
  • ESP_ERR_INVALID_ARG: Invalid parameters
  • ESP_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);
}

sample_store_list_sets()

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 handle
  • sets: [out] Array of set name strings (must be freed by caller)
  • count: [out] Number of sets returned

Returns:

  • ESP_OK: Success
  • ESP_ERR_INVALID_ARG: Invalid parameters
  • ESP_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);
    }
}

Event Management

sample_store_set_event_handler()

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 handle
  • cb: [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);

Iterator Functions

Iterator Creation and Destruction

sample_store_iterator_new()

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 handle
  • set_name: [in] Name of the set
  • start_counter: [in] Starting sample index (inclusive)
  • end_counter: [in] Ending sample index (inclusive)
  • iterator: [out] Pointer to store the iterator handle

Returns:

  • ESP_OK: Success
  • ESP_ERR_INVALID_ARG: Invalid parameters or start > end
  • ESP_ERR_NO_MEM: Memory allocation failed
  • ESP_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);
}

sample_store_iterator_free()

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)

Iterator Navigation

sample_store_iterator_next()

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: Success
  • ESP_ERR_INVALID_ARG: Invalid iterator
  • ESP_ERR_NOT_FOUND: Already at end or beyond range

sample_store_iterator_prev()

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: Success
  • ESP_ERR_INVALID_ARG: Invalid iterator
  • ESP_ERR_NOT_FOUND: Already at beginning or beyond range

sample_store_iterator_goto()

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 handle
  • counter: [in] Sample index to move to

Returns:

  • ESP_OK: Success
  • ESP_ERR_INVALID_ARG: Invalid iterator
  • ESP_ERR_NOT_FOUND: Counter outside iterator range or sample doesn't exist

Iterator Data Access

sample_store_iterator_get_sample()

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 handle
  • data: [out] Pointer to store the sample data pointer
  • size: [out] Pointer to store the sample size

Returns:

  • ESP_OK: Success
  • ESP_ERR_INVALID_ARG: Invalid parameters
  • ESP_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);
}

sample_store_iterator_get_current_counter()

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 handle
  • counter: [out] Pointer to store the current counter

Returns:

  • ESP_OK: Success
  • ESP_ERR_INVALID_ARG: Invalid parameters

Iterator Modification

sample_store_iterator_delete_sample()

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: Success
  • ESP_ERR_INVALID_ARG: Invalid iterator
  • ESP_ERR_INVALID_STATE: Sample is not first or last in set
  • ESP_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);

Error Codes

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

Usage Patterns

Sequential Sample Processing

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);

Partial Range Processing

// 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

Cleanup Pattern

// 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
}