Settings subsystem with non-volatile storage¶
The settings subsystem gives modules a way to store persistent per-device configuration and runtime state.
Settings items are stored as key-value pair strings. By convention,
the keys can be organized by the package and subtree defining the key,
for example the key id/serial
would define the serial
configuration
element for the package id
.
Convenience routines are provided for converting a key value to and from a string type.
Handlers¶
Settings handlers for subtree implement a set of handler functions.
These are registered using a call to settings_register()
.
- h_get
- This gets called when asking for a settings element value
by its name using
settings_get_value()
. - h_set
- This gets called when the value is being set using
settings_set_value()
, and also when setting is loaded from persisted storage withsettings_load()
. - h_commit
- This gets called after the settings have been loaded in full. Sometimes you don’t want an individual setting value to take effect right away, for example if there are multiple settings which are interdependent.
- h_export
- This gets called to write all current settings. This happens
when
settings_save()
tries to save the settings or transfer to any user-implemented back-end.
Persistence¶
Backend storage for the settings can be either FCB, a file in the filesystem, or both.
You can declare multiple sources for settings; settings from
all of these are restored when settings_load()
is called.
There can be only one target for writing settings; this is where
data is stored when you call settings_save()
, or settings_save_one()
.
FCB read target is registered using settings_fcb_src()
, and write target
using settings_fcb_dst()
. As a side-effect, settings_fcb_src()
initializes the FCB area, so it must be called before calling
settings_fcb_dst()
. File read target is registered using
settings_file_src()
, and write target by using settings_file_dst()
.
Example: Device Configuration¶
This is a simple example, where the settings handler only implements h_set
and h_export
. h_set
is called when the value is restored from storage
(or when set initially), and h_export
is used to write the value to
storage thanks to storage_func()
. The user can also implement some other
export functionality, for example, writing to the shell console).
static int8 foo_val;
struct settings_handler my_conf = {
.name = "foo",
.h_set = foo_settings_set,
.h_export = foo_settings_export
};
static int foo_settings_set(int argc, char **argv, char *val)
{
if (argc == 1) {
if (!strcmp(argv[0], "bar")) {
return SETTINGS_VALUE_SET(val, SETTINGS_INT8, foo_val);
}
}
return -ENOENT;
}
static int foo_settings_export(void (*storage_func)(char *name, char *val),
enum settings_export_tgt tgt)
{
char buf[4];
settings_str_from_value(SETTINGS_INT8, &foo_val, buf, sizeof(buf));
storage_func("foo/bar", buf)
return 0;
}
Example: Persist Runtime State¶
This is a simple example showing how to persist runtime state. In this example,
only h_set
is defined, which is used when restoring value from
persisted storage.
In this example, the foo_callout
function increments foo_val
, and then
persists the latest number. When the system restarts, the application calls
settings_load()
while initializing, and foo_val
will continue counting
up from where it was before restart.
static int8 foo_val;
struct settings_handler my_conf = {
.name = "foo",
.h_set = foo_settings_set
};
static int foo_settings_set(int argc, char **argv, char *val)
{
if (argc == 1) {
if (!strcmp(argv[0], "bar")) {
return SETTINGS_VALUE_SET(val, SETTINGS_INT8, foo_val);
}
}
return -ENOENT;
}
static void foo_callout(struct os_event *ev)
{
struct os_callout *c = (struct os_callout *)ev;
char buf[4];
foo_val++;
settings_str_from_value(SETTINGS_INT8, &foo_val, buf, sizeof(buf));
settings_save_one("foo/bar", bar);
k_sleep(1000);
sys_reboot(SYS_REBOOT_COLD);
}
API¶
The Settings subsystem APIs are provided by settings.h
:
-
group
settings
Defines
-
SETTINGS_MAX_DIR_DEPTH
¶
-
SETTINGS_MAX_NAME_LEN
¶
-
SETTINGS_MAX_VAL_LEN
¶
-
SETTINGS_NAME_SEPARATOR
¶
-
SETTINGS_EXTRA_LEN
¶
-
SETTINGS_NMGR_OP
¶
-
SETTINGS_STR_FROM_BYTES_LEN
(len)¶
-
SETTINGS_VALUE_SET
(str, type, val)¶
Enums
Functions
-
int
settings_subsys_init
(void)¶ Initialization of settings and backend
Can be called at application startup. In case the backend is NFFS Remember to call it after FS was mounted. For FCB backend it can be called without such a restriction.
- Return
- 0 on success, non-zero on failure.
-
int
settings_register
(struct settings_handler *cf)¶ Register a handler for settings items.
- Return
- 0 on success, non-zero on failure.
- Parameters
cf
: Structure containing registration info.
-
int
settings_load
(void)¶ Load serialized items from registered persistence sources. Handlers for serialized item subtrees registered earlier will be called for encountered values.
- Return
- 0 on success, non-zero on failure.
-
int
settings_save
(void)¶ Save currently running serialized items. All serialized items which are different from currently persisted values will be saved.
- Return
- 0 on success, non-zero on failure.
-
int
settings_save_one
(const char *name, char *var)¶ Write a single serialized value to persisted storage (if it has changed value).
- Return
- 0 on success, non-zero on failure.
- Parameters
name
: Name/key of the settings item.var
: Value of the settings item.
-
int
settings_set_value
(char *name, char *val_str)¶ Set settings item identified by
name
to be valueval_str
. This finds the settings handler for this subtree and calls it’s set handler.- Return
- 0 on success, non-zero on failure.
- Parameters
name
: Name/key of the settings item.val_str
: Value of the settings item.
-
char *
settings_get_value
(char *name, char *buf, int buf_len)¶ Get value of settings item identified by
name
. This calls the settings handler h_get for the subtree.Configuration handler can copy the string to
buf
, the maximum number of bytes it will copy is limited bybuf_len
.- Return
- value will be pointer to beginning of the buf, except for string it will pointer to beginning of string source.
- Parameters
name
: Name/key of the settings item.buf
: buffer for value of the settings item. If value is not string, the value will be filled in *buf.buf_len
: size of buf.
-
int
settings_commit
(char *name)¶ Call commit for all settings handler. This should apply all settings which has been set, but not applied yet.
- Return
- 0 on success, non-zero on failure.
- Parameters
name
: Name of the settings subtree, or NULL to commit everything.
-
int
settings_value_from_str
(char *val_str, enum settings_type type, void *vp, int maxlen)¶ Convenience routine for converting value passed as a string to native data type.
- Return
- 0 on success, non-zero on failure.
- Parameters
val_str
: Value of the settings item as string.type
: Type of the value to convert to.vp
: Pointer to variable to fill with the decoded value.maxlen
: the vp buffer size.
-
int
settings_bytes_from_str
(char *val_str, void *vp, int *len)¶ Convenience routine for converting byte array passed as a base64 encoded string.
- Return
- 0 on success, non-zero on failure.
- Parameters
val_str
: Value of the settings item as string.vp
: Pointer to variable to fill with the decoded value.len
: Size of that variable. On return the number of bytes in the array.
-
char *
settings_str_from_value
(enum settings_type type, void *vp, char *buf, int buf_len)¶ Convenience routine for converting native data type to a string.
- Return
- 0 on success, non-zero on failure.
- Parameters
type
: Type of the value to convert from.vp
: Pointer to variable to convert.buf
: Buffer where string value will be stored.buf_len
: Size of the buffer.
-
char *
settings_str_from_bytes
(void *vp, int vp_len, char *buf, int buf_len)¶ Convenience routine for converting byte array into a base64 encoded string.
- Return
- 0 on success, non-zero on failure.
- Parameters
vp
: Pointer to variable to convert.vp_len
: Number of bytes to convert.buf
: Buffer where string value will be stored.buf_len
: Size of the buffer.
-
struct
settings_handler
¶ - #include <settings.h>
Config handlers for subtree implement a set of handler functions. These are registered using a call to settings_register().
- Remark
- The User might limit a implementations of handler to serving only one keyword at one call - what will impose limit to get/set values using full subtree/key name.
- Parameters
settings_handler::node
: Linked list node info for module internal usage.settings_handler::name
: Name of subtree.settings_handler::h_get
: Get values handler of settings items identified by keyword names.Parameters:- argc - count of item in argv.
- argv - array of pointers to keyword names.
- val - buffer for a value.
- val_len_max - size of that buffer.
settings_handler::h_set
: Set value handler of settings items identified by keyword names. Parameters:- argc - count of item in argv, argv - array of pointers to keyword names.
- val- pointer to value to be set.
settings_handler::h_commit
: This handler gets called after settings has been loaded in full. User might use it to apply setting to the application.settings_handler::h_export
: This gets called to dump all current settings items. This happens when settings_save() tries to save the settings. Parameters:- tgt: indicates where data is going to.
- Export_function: the pointer to the internal function which appends a single key-value pair to persisted settings. Don’t store duplicated value. The name is subtree/key string, val is the string with value.
-