Generated API
Initialization
#include "dm.h"
// With event callbacks:
void my_callback(uint32_t key) { /* handle change */ }
DataModel_Initialize(my_callback);
// Without events (--no-events):
DataModel_Initialize();
// Cleanup:
DataModel_TearDown();
Reading and Writing Values
All integral types (bool, integers) use a type-dispatch API:
#include "dm.h"
#include "key_definitions.h"
// Set a value
dm_val_t val = { 0 };
val.u16val = 42;
DM_RETURN_CODE rc = DataModel_SetIntegralTypeByKey(DM_KEY_..., val);
// Get a value
dm_val_t out = DataModel_GetIntegralTypeByKey(DM_KEY_...);
uint16_t temp = out.u16val;
Typed convenience setters are also generated:
DataModel_SetBooleanByKey(DM_KEY_..., true);
DataModel_SetUInt16ByKey(DM_KEY_..., 42);
DataModel_SetInt32ByKey(DM_KEY_..., -7);
String API
// Get
const char *str = NULL;
DM_RETURN_CODE rc = DataModel_GetStringByKey(DM_KEY_..., &str);
// Set (read-write strings only)
rc = DataModel_SetStringByKey(DM_KEY_..., "new value");
String sets are bounds-checked against max_size. Strings exceeding the limit
are rejected.
Helper Functions
Keys with helpers = true get named getter/setter functions:
#include "dm_helpers.h"
// Integral types: static inline in the header
uint16_t temp = DataModel_Get_MY_DEVICE_STATUS_TEMPERATURE();
DataModel_Set_MY_DEVICE_STATUS_TEMPERATURE(2950);
// String types: declarations in header, implementations in dm_helpers.c
const char *name = DataModel_Get_MY_DEVICE_CONFIG_DEVICE_NAME();
DataModel_Set_MY_DEVICE_CONFIG_DEVICE_NAME("new-name");
Return Codes
typedef enum {
DM_RETURN_CODE_SUCCESS = 1,
DM_RETURN_CODE_NOT_INITIALIZED = -1,
DM_RETURN_CODE_KEY_TYPE_INCORRECT = -2,
DM_RETURN_CODE_SET_ON_READONLY_KEY = -3,
DM_RETURN_CODE_STORAGE_LOOKUP_FAILURE = -4,
DM_RETURN_CODE_SET_VALUE_UNCHANGED = -5,
DM_RETURN_CODE_NO_KEYS_OF_TYPE = -6,
DM_RETURN_CODE_OUTPUT_VARIABLE_NULL = -7,
// When persistence is enabled:
DM_RETURN_CODE_PERSISTENCE_FILE_NOT_FOUND = -8,
DM_RETURN_CODE_PERSISTENCE_READ_FAILURE = -9,
DM_RETURN_CODE_PERSISTENCE_WRITE_FAILURE = -10,
DM_RETURN_CODE_PERSISTENCE_MAGIC_MISMATCH = -11,
} DM_RETURN_CODE;
Key Query Macros
The generated dm_key.h provides macros to inspect key properties at runtime:
#include "dm_key.h"
DM_IS_KEY_READONLY(key) // Is this key read-only?
DM_IS_KEY_THREADSAFE(key) // Does this key require mutex protection?
DM_IS_KEY_DATA_TYPE(key, t) // Does this key have data type t?
DM_IS_KEY_IN_NAMESPACE(key, n)// Is this key in namespace n?
DM_KEY_GET_TYPE(key) // Extract the 4-bit type code
Persistence
Keys marked persistent = true can be saved to and loaded from a binary file:
#include "persistence_storage.h"
// Save all persistent key values to a file
DM_RETURN_CODE rc = DataModel_SavePersistentKeys("/data/dm.bin");
// Load and restore persistent key values from a file
rc = DataModel_LoadPersistentKeys("/data/dm.bin");
// Pass NULL to use the default path ("/sdcard/dm.bin")
rc = DataModel_LoadPersistentKeys(NULL);
// Check if a specific key is persistent
bool is_persistent = PersistenceStorage_IsKeyPersistent(DM_KEY_...);
The binary format uses a packed struct with a magic number
(sizeof(struct) XOR num_keys) to detect layout changes. If the magic number
does not match on load, DM_RETURN_CODE_PERSISTENCE_MAGIC_MISMATCH is
returned and the live storage is not modified.