File espos_config.h¶
File List > espos_config > include > espos_config.h
Go to the documentation of this file
/*
* SPDX-FileCopyrightText: 2026 Dirk Wahrheit
* SPDX-License-Identifier: Apache-2.0
*
* espos_config โ NVS-backed, schema-described configuration store.
*
* Every value lives in an NVS namespace under a short key. What namespaces
* and keys exist, their types, defaults and limits, is declared once in a
* config descriptor (JSON) per component and turned into the tables in
* espos_config_desc.h at build time. Use the generated espos_cfg_keys.h
* constants rather than string literals.
*
* Reads never fail on missing or corrupt values: they fall back to the
* compiled-in default. Writes are validated against the descriptor first and
* committed per key; a JSON import validates the whole document before it
* writes anything.
*
* Thread-safe: all calls take an internal mutex. Change callbacks run on the
* caller's task with the mutex NOT held.
*/
#pragma once
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include "esp_err.h"
#include "espos_config_desc.h"
#include "espos_config_backend.h"
#ifdef __cplusplus
extern "C" {
#endif
/* Sentinel returned in place of secret values on export; ignored on import. */
#define ESPOS_CONFIG_SECRET_SENTINEL "********"
/* ---------------------------------------------------------------- lifecycle */
esp_err_t espos_config_init(const espos_config_backend_t *backend, void *backend_ctx);
bool espos_config_is_ready(void);
void espos_config_deinit(void);
bool espos_config_storage_was_reset(void);
esp_err_t espos_config_factory_reset(void);
/* --------------------------------------------------------------- migrations */
typedef struct espos_config_migrate_ctx espos_config_migrate_ctx_t;
typedef esp_err_t (*espos_config_migrate_fn_t)(espos_config_migrate_ctx_t *ctx, void *arg);
esp_err_t espos_config_register_migration(const char *ns, uint16_t from_version,
espos_config_migrate_fn_t fn, void *arg);
/* Raw accessors usable only inside a migration callback (no validation,
* arbitrary types โ a migration may read a key in its OLD type). */
esp_err_t espos_config_migrate_get(espos_config_migrate_ctx_t *ctx, const char *key,
espos_cfg_type_t type, void *buf, size_t *len);
esp_err_t espos_config_migrate_set(espos_config_migrate_ctx_t *ctx, const char *key,
espos_cfg_type_t type, const void *buf, size_t len);
esp_err_t espos_config_migrate_erase(espos_config_migrate_ctx_t *ctx, const char *key);
uint16_t espos_config_migrate_from_version(const espos_config_migrate_ctx_t *ctx);
esp_err_t espos_config_get_version(const char *ns, uint16_t *stored, uint16_t *current);
/* ---------------------------------------------------------------- accessors */
/* Reads: return ESP_OK with the stored value or the compiled-in default.
* ESP_ERR_NOT_FOUND only if ns/key are not declared. */
esp_err_t espos_config_get_bool(const char *ns, const char *key, bool *out);
esp_err_t espos_config_get_i32(const char *ns, const char *key, int32_t *out);
esp_err_t espos_config_get_float(const char *ns, const char *key, float *out);
esp_err_t espos_config_get_str(const char *ns, const char *key, char *buf, size_t buf_size,
size_t *out_len);
esp_err_t espos_config_get_blob(const char *ns, const char *key, void *buf, size_t *len);
/* Writes: validated against the descriptor. ESP_ERR_INVALID_ARG on type/range/
* length/enum violation, ESP_ERR_NOT_FOUND on undeclared key. Change callbacks
* fire only if the effective value actually changed. */
esp_err_t espos_config_set_bool(const char *ns, const char *key, bool v);
esp_err_t espos_config_set_i32(const char *ns, const char *key, int32_t v);
esp_err_t espos_config_set_float(const char *ns, const char *key, float v);
esp_err_t espos_config_set_str(const char *ns, const char *key, const char *v);
esp_err_t espos_config_set_blob(const char *ns, const char *key, const void *buf, size_t len);
esp_err_t espos_config_reset_key(const char *ns, const char *key);
esp_err_t espos_config_reset_ns(const char *ns);
bool espos_config_is_set(const char *ns, const char *key);
/* --------------------------------------------------------------- descriptor */
const espos_cfg_ns_t *espos_config_find_ns(const char *ns);
const espos_cfg_key_t *espos_config_find_key(const espos_cfg_ns_t *ns, const char *key);
/* ---------------------------------------------------- runtime namespaces */
esp_err_t espos_config_register_ns(const espos_cfg_ns_t *ns);
esp_err_t espos_config_unregister_ns(const char *ns);
size_t espos_config_runtime_ns_count(void);
esp_err_t espos_config_flow_ns_name(const char *id, char *out, size_t out_size);
/* -------------------------------------------------------------- schema */
#define ESPOS_CFG_ETAG_MAX 24
esp_err_t espos_config_schema_json(char **out, char etag[ESPOS_CFG_ETAG_MAX]);
void espos_config_schema_etag(char etag[ESPOS_CFG_ETAG_MAX]);
/* -------------------------------------------------------------- change feed */
typedef void (*espos_config_change_cb_t)(const char *ns, const char *key, void *arg);
esp_err_t espos_config_subscribe(espos_config_change_cb_t cb, void *arg);
esp_err_t espos_config_unsubscribe(espos_config_change_cb_t cb, void *arg);
/* ------------------------------------------------------------------- JSON */
esp_err_t espos_config_export_json(const char *only_ns, bool include_secrets, char **out_json);
typedef struct {
size_t changed; /* keys whose effective value changed */
bool restart_required; /* at least one changed key is flagged restart_required */
/* On validation failure: the first offending "ns.key" and a reason. */
char error_path[40];
char error_msg[96];
} espos_config_import_result_t;
esp_err_t espos_config_import_json(const char *json, size_t json_len, bool ignore_unknown,
espos_config_import_result_t *result, char **out_report_json);
#ifdef __cplusplus
}
#endif