配置管理器¶
概述¶
配置管理器为 Nexus 嵌入式平台提供灵活、安全、持久化的键值配置存储。它支持多种数据类型、命名空间、变更通知和可选加密。
特性¶
多类型支持: int32/64、uint32、float、bool、string、blob
命名空间隔离: 按模块分离配置
默认值管理: 注册默认值,支持一键恢复
变更通知: 配置变更时触发回调
持久化存储: RAM、Flash 和自定义后端
导入/导出: 支持二进制和 JSON 格式
可选加密: AES-128/256 加密敏感数据
线程安全: 多任务环境下安全使用
资源可配置: 支持静态分配,适用于资源受限系统
快速开始¶
基本用法:
#include "config/config.h"
void app_init(void)
{
// Initialize with default config
config_init(NULL);
// Store configuration values
config_set_i32("app.timeout", 5000);
config_set_str("app.name", "MyApp");
config_set_bool("app.debug", true);
config_set_float("sensor.threshold", 3.14f);
// Read configuration values
int32_t timeout = 0;
config_get_i32("app.timeout", &timeout, 1000); // Default: 1000
char name[32];
config_get_str("app.name", name, sizeof(name));
bool debug = false;
config_get_bool("app.debug", &debug, false);
// Commit to storage
config_commit();
// Cleanup
config_deinit();
}
配置¶
自定义配置:
config_manager_config_t config = {
.max_keys = 128, // Max key count
.max_key_len = 32, // Max key length
.max_value_size = 256, // Max value size
.max_namespaces = 8, // Max namespace count
.max_callbacks = 16, // Max callback count
.auto_commit = true // Auto-commit mode
};
config_init(&config);
默认配置:
参数 |
默认值 |
描述 |
|---|---|---|
|
|
最大键数量 |
|
|
最大键长度 |
|
|
最大值大小 |
|
|
最大命名空间数 |
|
|
最大回调数 |
|
|
自动提交模式 |
数据类型¶
类型 |
值 |
描述 |
|---|---|---|
|
0 |
32 位有符号整数 |
|
1 |
32 位无符号整数 |
|
2 |
64 位有符号整数 |
|
3 |
单精度浮点数 |
|
4 |
布尔值 |
|
5 |
空终止字符串 |
|
6 |
二进制数据 |
类型操作¶
32-bit Signed Integer (int32)¶
// Store 32-bit signed integer
config_set_i32("app.timeout", 5000);
config_set_i32("sensor.offset", -100);
// Read with default value
int32_t timeout;
config_get_i32("app.timeout", &timeout, 1000); // Default: 1000
// Check if exists before reading
bool exists;
config_exists("app.timeout", &exists);
if (exists) {
config_get_i32("app.timeout", &timeout, 0);
}
32-bit Unsigned Integer (uint32)¶
// Store 32-bit unsigned integer
config_set_u32("app.count", 100);
config_set_u32("network.retry_count", 5);
// Read with default value
uint32_t count;
config_get_u32("app.count", &count, 0); // Default: 0
// Use for counters and IDs
uint32_t device_id;
config_get_u32("device.id", &device_id, 0xFFFFFFFF);
64-bit Signed Integer (int64)¶
// Store 64-bit signed integer (timestamps, large values)
config_set_i64("app.timestamp", 1234567890123LL);
config_set_i64("system.boot_time", -1000000LL);
// Read with default value
int64_t timestamp;
config_get_i64("app.timestamp", ×tamp, 0);
// Use for timestamps
int64_t last_sync;
config_get_i64("network.last_sync", &last_sync, 0);
Float (Single-Precision)¶
// Store floating-point values
config_set_float("sensor.threshold", 3.14f);
config_set_float("calibration.offset", -0.5f);
config_set_float("pid.kp", 1.2f);
// Read with default value
float threshold;
config_get_float("sensor.threshold", &threshold, 0.0f);
// Use for sensor calibration
float temp_offset;
config_get_float("sensor.temp_offset", &temp_offset, 0.0f);
Boolean¶
// Store boolean values
config_set_bool("app.debug", true);
config_set_bool("network.dhcp_enabled", false);
config_set_bool("sensor.auto_calibrate", true);
// Read with default value
bool debug;
config_get_bool("app.debug", &debug, false);
// Use for feature flags
bool use_ssl;
config_get_bool("network.use_ssl", &use_ssl, true);
字符串¶
// Store string values
config_set_str("app.name", "MyApp");
config_set_str("network.hostname", "device-001");
config_set_str("wifi.ssid", "MyNetwork");
// Read string
char name[32];
config_get_str("app.name", name, sizeof(name));
// Get string length first
size_t len;
config_get_str_len("app.name", &len);
char* dynamic_buf = malloc(len + 1);
config_get_str("app.name", dynamic_buf, len + 1);
// Use for configuration strings
char server_url[128];
config_get_str("network.server_url", server_url, sizeof(server_url));
Binary Blob¶
// Store binary data (certificates, keys, raw data)
uint8_t cert_data[] = {0x30, 0x82, 0x01, 0x0A, ...};
config_set_blob("security.certificate", cert_data, sizeof(cert_data));
// Store encryption key
uint8_t aes_key[16] = {0x00, 0x01, 0x02, ...};
config_set_blob("security.aes_key", aes_key, sizeof(aes_key));
// Read binary data
uint8_t buffer[256];
size_t actual_size;
config_get_blob("security.certificate", buffer, sizeof(buffer), &actual_size);
// Get blob size first
size_t blob_size;
config_get_blob_len("security.certificate", &blob_size);
uint8_t* dynamic_buf = malloc(blob_size);
config_get_blob("security.certificate", dynamic_buf, blob_size, &actual_size);
命名空间¶
命名空间用于隔离不同模块的配置:
// Open namespace
config_ns_handle_t ns;
config_open_namespace("network", &ns);
// Operations within namespace
config_ns_set_i32(ns, "port", 8080);
config_ns_set_str(ns, "host", "192.168.1.1");
config_ns_set_bool(ns, "ssl", true);
// Read from namespace
int32_t port = 0;
config_ns_get_i32(ns, "port", &port, 80);
// Check if key exists
bool exists;
config_ns_exists(ns, "port", &exists);
// Delete key
config_ns_delete(ns, "port");
// Close namespace
config_close_namespace(ns);
// Erase entire namespace
config_erase_namespace("network");
默认值¶
单个默认值:
// Register defaults
config_set_default_i32("app.timeout", 5000);
config_set_default_str("app.name", "DefaultApp");
config_set_default_bool("app.debug", false);
// Reset to default
config_reset_to_default("app.timeout");
// Reset all to defaults
config_reset_all_to_defaults();
批量注册:
static const config_default_t app_defaults[] = {
{"app.timeout", CONFIG_TYPE_I32, {.i32_val = 5000}},
{"app.name", CONFIG_TYPE_STR, {.str_val = "MyApp"}},
{"app.debug", CONFIG_TYPE_BOOL, {.bool_val = false}},
{"app.rate", CONFIG_TYPE_FLOAT, {.float_val = 1.5f}},
};
config_register_defaults(app_defaults,
sizeof(app_defaults) / sizeof(app_defaults[0]));
变更通知¶
监听特定键:
void on_timeout_change(const char* key, config_type_t type,
const void* old_val, const void* new_val,
void* user_data)
{
int32_t old_timeout = old_val ? *(int32_t*)old_val : 0;
int32_t new_timeout = *(int32_t*)new_val;
printf("Timeout changed: %d -> %d\n", old_timeout, new_timeout);
}
config_cb_handle_t handle;
config_register_callback("app.timeout", on_timeout_change, NULL, &handle);
// Triggers callback
config_set_i32("app.timeout", 10000);
// Unregister
config_unregister_callback(handle);
监听所有变更:
void on_any_change(const char* key, config_type_t type,
const void* old_val, const void* new_val,
void* user_data)
{
printf("Config changed: %s\n", key);
}
config_cb_handle_t handle;
config_register_wildcard_callback(on_any_change, NULL, &handle);
存储后端¶
The Config Manager supports multiple storage backends for different use cases. Each backend implements the same interface, allowing easy switching between storage types.
RAM Backend (Volatile)¶
The RAM backend stores configuration in memory. Data is lost on power cycle. Ideal for testing, temporary storage, and development.
#include "config/config_backend.h"
// Create RAM backend with 4KB buffer
config_backend_t* ram = config_backend_ram_create(4096);
if (ram == NULL) {
printf("Failed to create RAM backend\n");
return -1;
}
// Set as active backend
config_set_backend(ram);
// Use configuration normally
config_set_i32("app.timeout", 5000);
config_set_str("app.name", "TestApp");
// Data is stored in RAM
config_commit(); // No-op for RAM backend
// When done, destroy backend
config_backend_ram_destroy(ram);
Use cases: - Unit testing - Temporary configuration - Development and debugging - Systems without persistent storage
Flash Backend (Persistent)¶
The Flash backend stores configuration in non-volatile Flash memory. Data persists across power cycles. Requires HAL Flash driver.
#include "config/config_backend.h"
#include "hal/hal_flash.h"
// Define Flash partition for configuration
#define CONFIG_FLASH_ADDR 0x08080000 // Flash address
#define CONFIG_FLASH_SIZE 0x00010000 // 64KB partition
// Initialize Flash HAL
hal_flash_init();
// Create Flash backend
config_backend_t* flash = config_backend_flash_create(
CONFIG_FLASH_ADDR,
CONFIG_FLASH_SIZE
);
if (flash == NULL) {
printf("Failed to create Flash backend\n");
return -1;
}
// Set as active backend
config_set_backend(flash);
// Load existing configuration from Flash
config_status_t status = config_load();
if (status != CONFIG_OK) {
printf("No existing config, using defaults\n");
// Set default values
config_set_i32("app.timeout", 5000);
config_set_str("app.name", "MyApp");
}
// Modify configuration
config_set_bool("app.debug", true);
// Save to Flash
config_commit();
// When done, destroy backend
config_backend_flash_destroy(flash);
hal_flash_deinit();
Use cases: - Production systems - Persistent user settings - Device configuration - Calibration data
Flash considerations: - Wear leveling: Flash has limited write cycles - Erase granularity: Flash erases in sectors/pages - Write time: Flash writes are slower than RAM - Power loss: Use atomic writes or checksums
自定义后端¶
Implement a custom backend for specialized storage needs (EEPROM, SD card, network storage, etc.).
#include "config/config_backend.h"
// Custom context (your storage state)
typedef struct {
void* storage_handle;
uint32_t base_address;
} my_backend_ctx_t;
// Read function
static config_status_t my_backend_read(void* ctx, const char* key,
void* value, size_t* size)
{
my_backend_ctx_t* backend = (my_backend_ctx_t*)ctx;
// Implement read logic
// 1. Find key in storage
// 2. Read value
// 3. Copy to value buffer
// 4. Set size
return CONFIG_OK;
}
// Write function
static config_status_t my_backend_write(void* ctx, const char* key,
const void* value, size_t size)
{
my_backend_ctx_t* backend = (my_backend_ctx_t*)ctx;
// Implement write logic
// 1. Find or allocate space for key
// 2. Write value
// 3. Update metadata
return CONFIG_OK;
}
// Erase function
static config_status_t my_backend_erase(void* ctx, const char* key)
{
my_backend_ctx_t* backend = (my_backend_ctx_t*)ctx;
// Implement erase logic
// 1. Find key
// 2. Mark as deleted or reclaim space
return CONFIG_OK;
}
// Commit function (flush to storage)
static config_status_t my_backend_commit(void* ctx)
{
my_backend_ctx_t* backend = (my_backend_ctx_t*)ctx;
// Implement commit logic
// 1. Flush any cached writes
// 2. Update checksums
// 3. Ensure data integrity
return CONFIG_OK;
}
// Create custom backend
config_backend_t* my_backend_create(void)
{
// Allocate context
my_backend_ctx_t* ctx = malloc(sizeof(my_backend_ctx_t));
if (ctx == NULL) {
return NULL;
}
// Initialize context
ctx->storage_handle = open_storage();
ctx->base_address = 0x1000;
// Allocate backend structure
config_backend_t* backend = malloc(sizeof(config_backend_t));
if (backend == NULL) {
free(ctx);
return NULL;
}
// Set function pointers
backend->read = my_backend_read;
backend->write = my_backend_write;
backend->erase = my_backend_erase;
backend->commit = my_backend_commit;
backend->ctx = ctx;
return backend;
}
// Destroy custom backend
void my_backend_destroy(config_backend_t* backend)
{
if (backend != NULL) {
my_backend_ctx_t* ctx = (my_backend_ctx_t*)backend->ctx;
if (ctx != NULL) {
close_storage(ctx->storage_handle);
free(ctx);
}
free(backend);
}
}
// Usage
config_backend_t* backend = my_backend_create();
config_set_backend(backend);
// Use configuration
config_set_i32("app.value", 42);
config_commit();
// Cleanup
my_backend_destroy(backend);
Custom backend use cases: - EEPROM storage - SD card configuration files - Network-based configuration (cloud sync) - Database storage - Encrypted storage with custom crypto
Backend Comparison¶
Feature |
RAM |
Flash |
Custom |
注意事项 |
|---|---|---|---|---|
Persistent |
否 |
是 |
Depends |
Across reboot |
速度 |
Fast |
Medium |
Varies |
Read/write |
Wear leveling |
N/A |
必需 |
Depends |
Write cycles |
Size limit |
RAM size |
Flash size |
Varies |
Storage cap |
Power loss |
Data lost |
Safe |
Depends |
Data integrity |
Complexity |
Simple |
Medium |
High |
Implementation |
Backend Selection Guide¶
Choose RAM backend when: - Testing and development - Temporary configuration - No persistent storage needed - Maximum performance required
Choose Flash backend when: - Production deployment - Configuration must persist - Limited RAM available - Standard embedded system
Choose Custom backend when: - Special storage requirements - External storage (SD, EEPROM) - Network/cloud synchronization - Custom encryption or compression
导入/导出¶
二进制格式:
// Export
size_t export_size;
config_get_export_size(CONFIG_FORMAT_BINARY, 0, &export_size);
uint8_t* buffer = malloc(export_size);
size_t actual_size;
config_export(CONFIG_FORMAT_BINARY, 0, buffer, export_size, &actual_size);
// Import
config_import(CONFIG_FORMAT_BINARY, 0, buffer, actual_size);
JSON 格式:
// Export as JSON
char json_buffer[1024];
size_t json_size;
config_export(CONFIG_FORMAT_JSON, 0, json_buffer,
sizeof(json_buffer), &json_size);
// Import JSON
const char* json = "{\"app.timeout\": 5000, \"app.name\": \"Test\"}";
config_import(CONFIG_FORMAT_JSON, 0, json, strlen(json));
命名空间导出:
// Export specific namespace only
config_export_namespace("network", CONFIG_FORMAT_JSON, 0,
buffer, buf_size, &actual_size);
加密¶
设置加密密钥:
uint8_t key[16] = {0x00, 0x01, 0x02, ...}; // AES-128 key
config_set_encryption_key(key, sizeof(key), CONFIG_CRYPTO_AES128);
存储加密数据:
// Encrypt and store string
config_set_str_encrypted("auth.password", "secret123");
// Encrypt and store binary
uint8_t token[32] = {...};
config_set_blob_encrypted("auth.token", token, sizeof(token));
// Reading auto-decrypts
char password[64];
config_get_str("auth.password", password, sizeof(password));
// Check if key is encrypted
bool encrypted;
config_is_encrypted("auth.password", &encrypted);
密钥轮换:
// Re-encrypt all encrypted data with new key
uint8_t new_key[16] = {...};
config_rotate_encryption_key(new_key, sizeof(new_key), CONFIG_CRYPTO_AES128);
查询操作¶
// Check if key exists
bool exists;
config_exists("app.timeout", &exists);
// Get value type
config_type_t type;
config_get_type("app.timeout", &type);
// Delete key
config_delete("app.timeout");
// Get key count
size_t count;
config_get_count(&count);
// Iterate all entries
bool print_entry(const config_entry_info_t* info, void* user_data)
{
printf("Key: %s, Type: %d, Size: %d\n",
info->key, info->type, info->value_size);
return true; // Continue iteration
}
config_iterate(print_entry, NULL);
错误处理¶
config_status_t status = config_set_i32("key", 100);
if (status != CONFIG_OK) {
const char* msg = config_error_to_str(status);
printf("Error: %s\n", msg);
}
状态码:
状态 |
描述 |
|---|---|
|
成功 |
|
无效参数 |
|
未初始化 |
|
已初始化 |
|
键未找到 |
|
类型不匹配 |
|
缓冲区太小 |
|
存储已满 |
|
后端错误 |
|
加密错误 |
编译时配置¶
宏定义 |
默认值 |
描述 |
|---|---|---|
|
|
默认最大键数 |
|
|
默认最大键长度 |
|
|
默认最大值大小 |
|
|
默认最大命名空间数 |
|
|
默认最大回调数 |
|
|
启用加密 |
|
|
启用 JSON 支持 |
依赖¶
OSAL: 操作系统抽象层(Mutex 用于线程安全)
HAL: 硬件抽象层(Flash 后端)
API 参考¶
完整 API 文档请参阅 配置管理器 API 参考。