MeshX 0.4
This repository provides an implementation for Bluetooth Low Energy (BLE) Mesh network nodes. The project allows you to create BLE mesh nodes that can communicate with each other, enabling the development of smart home solutions or other IoT-based applications.
Loading...
Searching...
No Matches
meshx_gpio_kv.c File Reference

MeshX GPIO KV Engine Persistence Implementation. More...

#include <string.h>
#include <stdbool.h>
#include "interface/gpio/meshx_gpio.h"
#include "interface/gpio/meshx_gpio_types.h"
#include "interface/gpio/meshx_gpio_kv.h"
#include "interface/utils/meshx_fal_interface.h"
#include "meshx_kv_engine.h"
#include "meshx_err.h"
#include "interface/logging/meshx_log.h"
#include "module_id.h"

Macros

#define MESHX_GPIO_KV_MAX_CONFIG_SIZE   512
 Maximum buffer size for GPIO configuration serialization.
#define MESHX_GPIO_KV_MAX_PINS   32
 Maximum number of pins supported in KV storage.

Functions

static meshx_err_t serialize_gpio_config (const meshx_gpio_pin_config_t *configs, uint8_t pin_count, uint8_t *buf, uint16_t buf_len, uint16_t *out_size)
 Serialize GPIO configuration to buffer.
static meshx_err_t deserialize_gpio_config (const uint8_t *buf, uint16_t buf_len, meshx_gpio_pin_config_t *configs, uint8_t max_pins, uint8_t *out_pin_count)
 Deserialize GPIO configuration from buffer.
meshx_err_t meshx_gpio_kv_init (const meshx_fal_partition_t *kv_partition, const char *product_name)
 Initialize GPIO KV Engine persistence.
meshx_err_t meshx_gpio_save_config_to_kv (const meshx_gpio_pin_config_t *configs, uint8_t pin_count)
 Save GPIO configuration to KV Engine.
meshx_err_t meshx_gpio_load_config_from_kv (meshx_gpio_pin_config_t *configs, uint8_t max_pins, uint8_t *out_pin_count)
 Load GPIO configuration from KV Engine.
meshx_err_t meshx_gpio_config_exists_in_kv (bool *exists)
 Check if GPIO configuration exists in KV Engine.
meshx_err_t meshx_gpio_save_pin_state_to_kv (uint8_t logical_pin, const meshx_gpio_pin_state_t *state)
 Save current pin state to KV Engine.
meshx_err_t meshx_gpio_load_pin_state_from_kv (uint8_t logical_pin, meshx_gpio_pin_state_t *state)
 Load pin state from KV Engine.
meshx_err_t meshx_gpio_export_config (const meshx_gpio_pin_config_t *configs, uint8_t pin_count, uint8_t *buf, uint16_t buf_len, uint16_t *out_size)
 Export GPIO configuration to serialized format.
meshx_err_t meshx_gpio_import_config (const uint8_t *buf, uint16_t buf_len, meshx_gpio_pin_config_t *configs, uint8_t max_pins, uint8_t *out_pin_count)
 Import GPIO configuration from serialized format.
meshx_err_t meshx_gpio_clear_config_in_kv (void)
 Clear GPIO configuration from KV Engine.
meshx_err_t meshx_gpio_kv_deinit (void)
 Deinitialize GPIO KV Engine persistence.
bool meshx_gpio_kv_is_initialized (void)
 Check if GPIO KV persistence is initialized.

Variables

static const meshx_fal_partition_tgpio_kv_partition = NULL
 KV Engine partition reference (set during initialization).
static char current_product_name [16+1] = {0}
 Current product name for key prefix.
static bool kv_persistence_initialized = false
 Flag indicating if KV persistence is initialized.

Detailed Description

MeshX GPIO KV Engine Persistence Implementation.

This file implements the GPIO configuration persistence API using the MeshX KV Engine. It provides save/load functions for GPIO configuration with versioning, CRC validation, and corruption fallback to compiled defaults.

Author
MeshX Team
Date
2024

Macro Definition Documentation

◆ MESHX_GPIO_KV_MAX_CONFIG_SIZE

#define MESHX_GPIO_KV_MAX_CONFIG_SIZE   512

Maximum buffer size for GPIO configuration serialization.

◆ MESHX_GPIO_KV_MAX_PINS

#define MESHX_GPIO_KV_MAX_PINS   32

Maximum number of pins supported in KV storage.

Function Documentation

◆ deserialize_gpio_config()

meshx_err_t deserialize_gpio_config ( const uint8_t * buf,
uint16_t buf_len,
meshx_gpio_pin_config_t * configs,
uint8_t max_pins,
uint8_t * out_pin_count )
static

Deserialize GPIO configuration from buffer.

Parameters
bufInput buffer
buf_lenBuffer length
configsArray to store pin configurations
max_pinsMaximum pins that can be stored
[out]out_pin_countActual pin count read
Returns
meshx_err_t MESHX_SUCCESS on success, error code on failure
141{
142 if (!buf || !configs || !out_pin_count) {
143 return MESHX_INVALID_ARG;
144 }
145
146 if (buf_len < MESHX_GPIO_CONFIG_HEADER_SIZE) {
147 MESHX_LOGE(MODULE_ID_COMPONENT_MESHX_GPIO, "Buffer too small for header");
148 return MESHX_INVALID_ARG;
149 }
150
151 /* Parse header */
153
154 /* Validate version */
156 MESHX_LOGE(MODULE_ID_COMPONENT_MESHX_GPIO, "Unsupported config version: %d", header->version);
158 }
159
160 /* Verify CRC16 */
161 if (!meshx_gpio_kv_verify_crc16(buf, buf_len)) {
162 MESHX_LOGE(MODULE_ID_COMPONENT_MESHX_GPIO, "CRC verification failed");
164 }
165
166 /* Validate pin count */
167 if (header->pin_count > max_pins) {
168 MESHX_LOGE(MODULE_ID_COMPONENT_MESHX_GPIO, "Pin count %d exceeds max %d",
169 header->pin_count, max_pins);
170 return MESHX_NO_MEM;
171 }
172
173 /* Deserialize pin configurations */
174 const uint8_t *ptr = buf + MESHX_GPIO_CONFIG_HEADER_SIZE;
175 uint8_t pin_count = header->pin_count;
176
177 for (uint8_t i = 0; i < pin_count; i++) {
178 if (ptr + MESHX_GPIO_PIN_CONFIG_SIZE > buf + buf_len) {
179 MESHX_LOGE(MODULE_ID_COMPONENT_MESHX_GPIO, "Unexpected end of data at pin %d", i);
181 }
182
183 const meshx_gpio_pin_config_kv_t *pin_cfg = (const meshx_gpio_pin_config_kv_t *)ptr;
184 meshx_gpio_kv_deserialize_pin(pin_cfg, &configs[i]);
186
187 /* Deserialize PWM configuration if present */
188 if (pin_cfg->config_type == MESHX_GPIO_CONFIG_TYPE_PWM) {
189 if (ptr + MESHX_GPIO_PWM_CONFIG_SIZE > buf + buf_len) {
190 MESHX_LOGE(MODULE_ID_COMPONENT_MESHX_GPIO, "Unexpected end of PWM data at pin %d", i);
192 }
193 const meshx_gpio_pwm_config_kv_t *pwm_cfg = (const meshx_gpio_pwm_config_kv_t *)ptr;
194 meshx_gpio_kv_deserialize_pwm(pwm_cfg, &configs[i]);
196 }
197
198 /* Deserialize interrupt configuration if present */
200 if (ptr + MESHX_GPIO_INTR_CONFIG_SIZE > buf + buf_len) {
201 MESHX_LOGE(MODULE_ID_COMPONENT_MESHX_GPIO, "Unexpected end of intr data at pin %d", i);
203 }
204 const meshx_gpio_intr_config_kv_t *intr_cfg = (const meshx_gpio_intr_config_kv_t *)ptr;
205 meshx_gpio_kv_deserialize_intr(intr_cfg, &configs[i]);
207 }
208 }
209
210 *out_pin_count = pin_count;
211
212 MESHX_LOGD(MODULE_ID_COMPONENT_MESHX_GPIO, "Deserialized %d pins", pin_count);
213 return MESHX_SUCCESS;
214}
@ MESHX_INVALID_ARG
Definition meshx_err.h:46
@ MESHX_ERR_GPIO_CONFIG_INVALID
Definition meshx_err.h:71
@ MESHX_NO_MEM
Definition meshx_err.h:48
static void meshx_gpio_kv_deserialize_pin(const meshx_gpio_pin_config_kv_t *src, meshx_gpio_pin_config_t *dst)
Convert serialized pin config to runtime format.
Definition meshx_gpio_kv.h:426
static bool meshx_gpio_kv_verify_crc16(const uint8_t *data, uint32_t len)
Verify CRC16 of serialized GPIO configuration.
Definition meshx_gpio_kv.h:329
#define MESHX_GPIO_PWM_CONFIG_SIZE
Size of PWM configuration extension.
Definition meshx_gpio_kv.h:246
#define MESHX_GPIO_PIN_CONFIG_SIZE
Size of basic pin configuration.
Definition meshx_gpio_kv.h:243
static bool meshx_gpio_kv_is_version_supported(uint8_t version)
Check if a configuration version is supported.
Definition meshx_gpio_kv.h:521
#define MESHX_GPIO_CONFIG_TYPE_PWM
PWM configuration follows.
Definition meshx_gpio_kv.h:286
#define MESHX_GPIO_CONFIG_HEADER_SIZE
Size of configuration header.
Definition meshx_gpio_kv.h:240
static void meshx_gpio_kv_deserialize_intr(const meshx_gpio_intr_config_kv_t *src, meshx_gpio_pin_config_t *dst)
Deserialize interrupt configuration.
Definition meshx_gpio_kv.h:501
#define MESHX_GPIO_CONFIG_TYPE_INTR
Interrupt configuration follows.
Definition meshx_gpio_kv.h:289
static void meshx_gpio_kv_deserialize_pwm(const meshx_gpio_pwm_config_kv_t *src, meshx_gpio_pin_config_t *dst)
Deserialize PWM configuration.
Definition meshx_gpio_kv.h:464
#define MESHX_GPIO_INTR_CONFIG_SIZE
Size of interrupt configuration extension.
Definition meshx_gpio_kv.h:249
#define MESHX_LOGE(module_id, format,...)
Definition meshx_log.h:114
#define MESHX_LOGD(module_id, format,...)
Definition meshx_log.h:132
**This function is called by the parent element when a state change request *is received It validates the request and returns a result to the element not the model layer **return * MESHX_SUCCESS
Definition meshx_model_level.cpp:385
@ MODULE_ID_COMPONENT_MESHX_GPIO
Definition module_id.h:44
Header for serialized GPIO configuration stored in KV Engine.
Definition meshx_gpio_kv.h:162
uint8_t pin_count
Definition meshx_gpio_kv.h:164
uint8_t version
Definition meshx_gpio_kv.h:163
Serialized interrupt configuration for KV Engine storage.
Definition meshx_gpio_kv.h:211
Serialized GPIO pin configuration for KV Engine storage.
Definition meshx_gpio_kv.h:178
uint8_t config_type
Definition meshx_gpio_kv.h:186
Serialized PWM configuration for KV Engine storage.
Definition meshx_gpio_kv.h:196

◆ meshx_gpio_clear_config_in_kv()

meshx_err_t meshx_gpio_clear_config_in_kv ( void )

Clear GPIO configuration from KV Engine.

Removes the stored GPIO configuration, forcing fallback to defaults on next load.

Returns
meshx_err_t MESHX_SUCCESS on success, error code on failure
581{
583 MESHX_LOGE(MODULE_ID_COMPONENT_MESHX_GPIO, "KV persistence not initialized");
585 }
586
587 /* Construct KV key */
589 if (meshx_gpio_kv_make_config_key(current_product_name, key, sizeof(key)) == 0) {
590 MESHX_LOGE(MODULE_ID_COMPONENT_MESHX_GPIO, "Failed to construct config key");
591 return MESHX_FAIL;
592 }
593
594 /* Remove from KV Engine */
596 if (err != MESHX_SUCCESS) {
597 MESHX_LOGE(MODULE_ID_COMPONENT_MESHX_GPIO, "Failed to remove config: %d", err);
598 return err;
599 }
600
601 /* Commit the removal */
603 if (err != MESHX_SUCCESS) {
604 MESHX_LOGE(MODULE_ID_COMPONENT_MESHX_GPIO, "Failed to commit removal: %d", err);
605 return err;
606 }
607
608 MESHX_LOGI(MODULE_ID_COMPONENT_MESHX_GPIO, "Cleared GPIO config from KV");
609 return MESHX_SUCCESS;
610}
meshx_err_t
MeshX Error Codes.
Definition meshx_err.h:43
@ MESHX_FAIL
Definition meshx_err.h:45
@ MESHX_ERR_GPIO_NOT_INITIALIZED
Definition meshx_err.h:70
static bool kv_persistence_initialized
Flag indicating if KV persistence is initialized.
Definition meshx_gpio_kv.c:46
static char current_product_name[16+1]
Current product name for key prefix.
Definition meshx_gpio_kv.c:43
#define MESHX_GPIO_KV_KEY_MAX_LEN
Maximum total key length (KV Engine limit is 32).
Definition meshx_gpio_kv.h:51
static uint8_t meshx_gpio_kv_make_config_key(const char *product_name, char *buf, uint8_t buf_len)
Construct KV Engine key for GPIO configuration.
Definition meshx_gpio_kv.h:72
meshx_err_t meshx_kv_engine_commit(void)
Commit all buffered changes to flash.
Definition meshx_kv_engine.c:181
meshx_err_t meshx_kv_engine_remove(const char *key)
Remove a key from the KV engine.
Definition meshx_kv_engine.c:223
#define MESHX_LOGI(module_id, format,...)
Definition meshx_log.h:126

◆ meshx_gpio_config_exists_in_kv()

meshx_err_t meshx_gpio_config_exists_in_kv ( bool * exists)

Check if GPIO configuration exists in KV Engine.

Parameters
[out]existstrue if configuration exists, false otherwise
Returns
meshx_err_t MESHX_SUCCESS on success, error code on failure
385{
387 MESHX_LOGE(MODULE_ID_COMPONENT_MESHX_GPIO, "KV persistence not initialized");
389 }
390
391 if (!exists) {
392 return MESHX_INVALID_ARG;
393 }
394
395 /* Construct KV key */
397 if (meshx_gpio_kv_make_config_key(current_product_name, key, sizeof(key)) == 0) {
398 MESHX_LOGE(MODULE_ID_COMPONENT_MESHX_GPIO, "Failed to construct config key");
399 return MESHX_FAIL;
400 }
401
402 /* Try to read with zero-length buffer to check existence */
403 uint8_t dummy;
404 meshx_err_t err = meshx_kv_engine_read(key, &dummy, 0);
405
406 *exists = (err == MESHX_SUCCESS);
407
408 return MESHX_SUCCESS;
409}
meshx_err_t meshx_kv_engine_read(const char *key, void *buf, uint16_t len)
Read a value from the KV engine.
Definition meshx_kv_engine.c:105

◆ meshx_gpio_export_config()

meshx_err_t meshx_gpio_export_config ( const meshx_gpio_pin_config_t * configs,
uint8_t pin_count,
uint8_t * buf,
uint16_t buf_len,
uint16_t * out_size )

Export GPIO configuration to serialized format.

Exports the configuration in binary format for transfer to another device.

Parameters
configsArray of pin configurations
pin_countNumber of pins
[out]bufOutput buffer
buf_lenBuffer length
[out]out_sizeActual exported size
Returns
meshx_err_t MESHX_SUCCESS on success, error code on failure
537{
538 if (!configs || !buf || !out_size) {
539 return MESHX_INVALID_ARG;
540 }
541
542 /* Export uses the same serialization format as KV storage */
543 return serialize_gpio_config(configs, pin_count, buf, buf_len, out_size);
544}
static meshx_err_t serialize_gpio_config(const meshx_gpio_pin_config_t *configs, uint8_t pin_count, uint8_t *buf, uint16_t buf_len, uint16_t *out_size)
Serialize GPIO configuration to buffer.
Definition meshx_gpio_kv.c:62

◆ meshx_gpio_import_config()

meshx_err_t meshx_gpio_import_config ( const uint8_t * buf,
uint16_t buf_len,
meshx_gpio_pin_config_t * configs,
uint8_t max_pins,
uint8_t * out_pin_count )

Import GPIO configuration from serialized format.

Imports configuration from binary format received from another device.

Parameters
bufInput buffer
buf_lenBuffer length
[out]configsArray to store imported configurations
max_pinsMaximum pins that can be stored
[out]out_pin_countActual number of pins imported
Returns
meshx_err_t MESHX_SUCCESS on success, error code on failure
563{
564 if (!buf || !configs || !out_pin_count) {
565 return MESHX_INVALID_ARG;
566 }
567
568 /* Import uses the same deserialization format as KV storage */
569 return deserialize_gpio_config(buf, buf_len, configs, max_pins, out_pin_count);
570}
static meshx_err_t deserialize_gpio_config(const uint8_t *buf, uint16_t buf_len, meshx_gpio_pin_config_t *configs, uint8_t max_pins, uint8_t *out_pin_count)
Deserialize GPIO configuration from buffer.
Definition meshx_gpio_kv.c:136

◆ meshx_gpio_kv_deinit()

meshx_err_t meshx_gpio_kv_deinit ( void )

Deinitialize GPIO KV Engine persistence.

Cleans up KV persistence resources. Does not affect the underlying KV Engine partition.

Returns
meshx_err_t MESHX_SUCCESS on success, error code on failure
621{
623 return MESHX_SUCCESS;
624 }
625
626 gpio_kv_partition = NULL;
627 memset(current_product_name, 0, sizeof(current_product_name));
629
630 MESHX_LOGI(MODULE_ID_COMPONENT_MESHX_GPIO, "GPIO KV persistence deinitialized");
631 return MESHX_SUCCESS;
632}
static const meshx_fal_partition_t * gpio_kv_partition
KV Engine partition reference (set during initialization).
Definition meshx_gpio_kv.c:40

◆ meshx_gpio_kv_init()

meshx_err_t meshx_gpio_kv_init ( const meshx_fal_partition_t * kv_partition,
const char * product_name )

Initialize GPIO KV Engine persistence.

This function initializes the KV Engine for GPIO configuration storage. It must be called before any other GPIO KV functions.

Parameters
kv_partitionPointer to the flash partition to use for KV storage
product_nameProduct name for key prefix (max 16 chars)
Returns
meshx_err_t MESHX_SUCCESS on success, error code on failure
232{
233 if (!kv_partition || !product_name) {
234 MESHX_LOGE(MODULE_ID_COMPONENT_MESHX_GPIO, "Invalid arguments for KV init");
235 return MESHX_INVALID_ARG;
236 }
237
238 /* Initialize KV Engine */
239 meshx_err_t err = meshx_kv_engine_init(kv_partition);
240 if (err != MESHX_SUCCESS) {
241 MESHX_LOGE(MODULE_ID_COMPONENT_MESHX_GPIO, "Failed to initialize KV Engine: %d", err);
242 return err;
243 }
244
245 /* Store partition reference */
246 gpio_kv_partition = kv_partition;
247
248 /* Store product name for key prefix */
251
253
254 MESHX_LOGI(MODULE_ID_COMPONENT_MESHX_GPIO, "GPIO KV persistence initialized for product: %s",
256 return MESHX_SUCCESS;
257}
#define MESHX_GPIO_KV_PRODUCT_NAME_MAX_LEN
Maximum length for product name in key prefix.
Definition meshx_gpio_kv.h:48
meshx_err_t meshx_kv_engine_init(const meshx_fal_partition_t *part)
Initialize the KV engine.
Definition meshx_kv_engine.c:66

◆ meshx_gpio_kv_is_initialized()

bool meshx_gpio_kv_is_initialized ( void )

Check if GPIO KV persistence is initialized.

Returns
true if initialized, false otherwise
640{
642}

◆ meshx_gpio_load_config_from_kv()

meshx_err_t meshx_gpio_load_config_from_kv ( meshx_gpio_pin_config_t * configs,
uint8_t max_pins,
uint8_t * out_pin_count )

Load GPIO configuration from KV Engine.

This function loads and deserializes GPIO configuration from KV Engine. If the configuration is not found or corrupted, returns MESHX_NOT_FOUND to allow fallback to compiled defaults.

Parameters
configsArray to store loaded pin configurations
max_pinsMaximum pins that can be stored
[out]out_pin_countActual number of pins loaded
Returns
meshx_err_t MESHX_SUCCESS on success, MESHX_NOT_FOUND if not found, error code on other failures
334{
336 MESHX_LOGE(MODULE_ID_COMPONENT_MESHX_GPIO, "KV persistence not initialized");
338 }
339
340 if (!configs || !out_pin_count) {
341 MESHX_LOGE(MODULE_ID_COMPONENT_MESHX_GPIO, "Invalid arguments for load");
342 return MESHX_INVALID_ARG;
343 }
344
345 /* Construct KV key */
347 if (meshx_gpio_kv_make_config_key(current_product_name, key, sizeof(key)) == 0) {
348 MESHX_LOGE(MODULE_ID_COMPONENT_MESHX_GPIO, "Failed to construct config key");
349 return MESHX_FAIL;
350 }
351
352 /* Read from KV Engine */
353 uint8_t buffer[MESHX_GPIO_KV_MAX_CONFIG_SIZE];
354 uint16_t read_size = sizeof(buffer);
355
356 meshx_err_t err = meshx_kv_engine_read(key, buffer, read_size);
357 if (err != MESHX_SUCCESS) {
358 if (err == MESHX_NOT_FOUND) {
359 MESHX_LOGI(MODULE_ID_COMPONENT_MESHX_GPIO, "No GPIO config found in KV, using defaults");
360 } else {
361 MESHX_LOGE(MODULE_ID_COMPONENT_MESHX_GPIO, "Failed to read KV: %d", err);
362 }
363 return err;
364 }
365
366 /* Deserialize configuration */
367 err = deserialize_gpio_config(buffer, read_size, configs, max_pins, out_pin_count);
368 if (err != MESHX_SUCCESS) {
369 MESHX_LOGE(MODULE_ID_COMPONENT_MESHX_GPIO, "Failed to deserialize config (corrupted?): %d", err);
370 /* Return NOT_FOUND to trigger fallback to defaults */
371 return MESHX_NOT_FOUND;
372 }
373
374 MESHX_LOGI(MODULE_ID_COMPONENT_MESHX_GPIO, "Loaded GPIO config: %d pins", *out_pin_count);
375 return MESHX_SUCCESS;
376}
@ MESHX_NOT_FOUND
Definition meshx_err.h:50
#define MESHX_GPIO_KV_MAX_CONFIG_SIZE
Maximum buffer size for GPIO configuration serialization.
Definition meshx_gpio_kv.c:30

◆ meshx_gpio_load_pin_state_from_kv()

meshx_err_t meshx_gpio_load_pin_state_from_kv ( uint8_t logical_pin,
meshx_gpio_pin_state_t * state )

Load pin state from KV Engine.

Loads previously persisted runtime state of a GPIO pin.

Parameters
logical_pinLogical pin number
[out]statePointer to store loaded pin state
Returns
meshx_err_t MESHX_SUCCESS on success, MESHX_NOT_FOUND if not found, error code on other failures
479{
481 MESHX_LOGE(MODULE_ID_COMPONENT_MESHX_GPIO, "KV persistence not initialized");
483 }
484
485 if (!state) {
486 return MESHX_INVALID_ARG;
487 }
488
489 /* Construct KV key for state */
491 if (meshx_gpio_kv_make_state_key(current_product_name, logical_pin, key, sizeof(key)) == 0) {
492 MESHX_LOGE(MODULE_ID_COMPONENT_MESHX_GPIO, "Failed to construct state key");
493 return MESHX_FAIL;
494 }
495
496 /* Read from KV Engine */
498 uint16_t read_size = sizeof(state_kv);
499
500 meshx_err_t err = meshx_kv_engine_read(key, &state_kv, read_size);
501 if (err != MESHX_SUCCESS) {
502 if (err == MESHX_NOT_FOUND) {
503 MESHX_LOGD(MODULE_ID_COMPONENT_MESHX_GPIO, "No state found for pin %u", logical_pin);
504 } else {
505 MESHX_LOGE(MODULE_ID_COMPONENT_MESHX_GPIO, "Failed to read pin state: %d", err);
506 }
507 return err;
508 }
509
510 /* Apply loaded state */
511 state->current_level = state_kv.current_level;
512 state->mode_state.pwm.started = state_kv.pwm_started;
513 state->mode_state.pwm.duty_cycle = state_kv.current_duty;
514
515 MESHX_LOGD(MODULE_ID_COMPONENT_MESHX_GPIO, "Loaded state for pin %u: level=%u",
516 logical_pin, state->current_level);
517 return MESHX_SUCCESS;
518}
static uint8_t meshx_gpio_kv_make_state_key(const char *product_name, uint8_t logical_pin, char *buf, uint8_t buf_len)
Construct KV Engine key for GPIO pin state.
Definition meshx_gpio_kv.h:92
uint8_t state
Definition meshx_serial.c:39
Serialized GPIO pin state for KV Engine storage.
Definition meshx_gpio_kv.h:226
uint8_t current_duty
Definition meshx_gpio_kv.h:230
uint8_t current_level
Definition meshx_gpio_kv.h:228
uint8_t pwm_started
Definition meshx_gpio_kv.h:229

◆ meshx_gpio_save_config_to_kv()

meshx_err_t meshx_gpio_save_config_to_kv ( const meshx_gpio_pin_config_t * configs,
uint8_t pin_count )

Save GPIO configuration to KV Engine.

This function serializes and saves the GPIO configuration to KV Engine with versioning and CRC validation.

Parameters
configsArray of pin configurations to save
pin_countNumber of pins in configuration
Returns
meshx_err_t MESHX_SUCCESS on success, error code on failure
271{
273 MESHX_LOGE(MODULE_ID_COMPONENT_MESHX_GPIO, "KV persistence not initialized");
275 }
276
277 if (!configs || pin_count == 0) {
278 MESHX_LOGE(MODULE_ID_COMPONENT_MESHX_GPIO, "Invalid arguments for save");
279 return MESHX_INVALID_ARG;
280 }
281
282 /* Construct KV key */
284 if (meshx_gpio_kv_make_config_key(current_product_name, key, sizeof(key)) == 0) {
285 MESHX_LOGE(MODULE_ID_COMPONENT_MESHX_GPIO, "Failed to construct config key");
286 return MESHX_FAIL;
287 }
288
289 /* Serialize configuration */
290 uint8_t buffer[MESHX_GPIO_KV_MAX_CONFIG_SIZE];
291 uint16_t config_size = 0;
292
293 meshx_err_t err = serialize_gpio_config(configs, pin_count, buffer, sizeof(buffer), &config_size);
294 if (err != MESHX_SUCCESS) {
295 MESHX_LOGE(MODULE_ID_COMPONENT_MESHX_GPIO, "Failed to serialize config: %d", err);
296 return err;
297 }
298
299 /* Save to KV Engine (buffered in RAM) */
300 err = meshx_kv_engine_set(key, buffer, config_size);
301 if (err != MESHX_SUCCESS) {
302 MESHX_LOGE(MODULE_ID_COMPONENT_MESHX_GPIO, "Failed to set KV value: %d", err);
303 return err;
304 }
305
306 /* Commit to flash */
308 if (err != MESHX_SUCCESS) {
309 MESHX_LOGE(MODULE_ID_COMPONENT_MESHX_GPIO, "Failed to commit KV: %d", err);
310 return err;
311 }
312
313 MESHX_LOGI(MODULE_ID_COMPONENT_MESHX_GPIO, "Saved GPIO config: %d pins, %d bytes",
314 pin_count, config_size);
315 return MESHX_SUCCESS;
316}
meshx_err_t meshx_kv_engine_set(const char *key, const void *buf, uint16_t len)
Buffer a write operation in RAM.
Definition meshx_kv_engine.c:157

◆ meshx_gpio_save_pin_state_to_kv()

meshx_err_t meshx_gpio_save_pin_state_to_kv ( uint8_t logical_pin,
const meshx_gpio_pin_state_t * state )

Save current pin state to KV Engine.

Persists the runtime state of a GPIO pin across reboots.

Parameters
logical_pinLogical pin number
statePointer to pin state to save
Returns
meshx_err_t MESHX_SUCCESS on success, error code on failure
422{
424 MESHX_LOGE(MODULE_ID_COMPONENT_MESHX_GPIO, "KV persistence not initialized");
426 }
427
428 if (!state) {
429 return MESHX_INVALID_ARG;
430 }
431
432 /* Construct KV key for state */
434 if (meshx_gpio_kv_make_state_key(current_product_name, logical_pin, key, sizeof(key)) == 0) {
435 MESHX_LOGE(MODULE_ID_COMPONENT_MESHX_GPIO, "Failed to construct state key");
436 return MESHX_FAIL;
437 }
438
439 /* Serialize pin state */
440 meshx_gpio_pin_state_kv_t state_kv = {
441 .logical_pin = logical_pin,
442 .current_level = state->current_level,
443 .pwm_started = state->mode_state.pwm.started,
444 .current_duty = state->mode_state.pwm.duty_cycle,
445 .reserved = 0
446 };
447
448 /* Save to KV Engine */
449 meshx_err_t err = meshx_kv_engine_set(key, &state_kv, sizeof(state_kv));
450 if (err != MESHX_SUCCESS) {
451 MESHX_LOGE(MODULE_ID_COMPONENT_MESHX_GPIO, "Failed to save pin state: %d", err);
452 return err;
453 }
454
455 /* Commit to flash */
457 if (err != MESHX_SUCCESS) {
458 MESHX_LOGE(MODULE_ID_COMPONENT_MESHX_GPIO, "Failed to commit pin state: %d", err);
459 return err;
460 }
461
462 MESHX_LOGD(MODULE_ID_COMPONENT_MESHX_GPIO, "Saved state for pin %u: level=%u",
463 logical_pin, state->current_level);
464 return MESHX_SUCCESS;
465}

◆ serialize_gpio_config()

meshx_err_t serialize_gpio_config ( const meshx_gpio_pin_config_t * configs,
uint8_t pin_count,
uint8_t * buf,
uint16_t buf_len,
uint16_t * out_size )
static

Serialize GPIO configuration to buffer.

Parameters
configsArray of pin configurations
pin_countNumber of pins
bufOutput buffer
buf_lenBuffer length
[out]out_sizeActual serialized size
Returns
meshx_err_t MESHX_SUCCESS on success, error code on failure
67{
68 if (!configs || !buf || !out_size || pin_count > MESHX_GPIO_KV_MAX_PINS) {
69 return MESHX_INVALID_ARG;
70 }
71
72 /* Calculate required size */
73 uint16_t required_size = MESHX_GPIO_CONFIG_HEADER_SIZE;
74 required_size += pin_count * MESHX_GPIO_PIN_CONFIG_SIZE;
75
76 /* Check for PWM pins that need extended configuration */
77 for (uint8_t i = 0; i < pin_count; i++) {
78 if (configs[i].mode == MESHX_GPIO_MODE_PWM_OUTPUT) {
79 required_size += MESHX_GPIO_PWM_CONFIG_SIZE;
80 }
81 }
82
83 if (buf_len < required_size) {
84 MESHX_LOGE(MODULE_ID_COMPONENT_MESHX_GPIO, "Buffer too small: %d < %d", buf_len, required_size);
85 return MESHX_NO_MEM;
86 }
87
88 /* Initialize header */
90 meshx_gpio_kv_init_header(header, pin_count);
91
92 /* Set flags based on pin types */
93 for (uint8_t i = 0; i < pin_count; i++) {
94 if (configs[i].mode == MESHX_GPIO_MODE_PWM_OUTPUT) {
96 }
97 }
98
99 /* Serialize pin configurations */
100 uint8_t *ptr = buf + MESHX_GPIO_CONFIG_HEADER_SIZE;
101 for (uint8_t i = 0; i < pin_count; i++) {
103 meshx_gpio_kv_serialize_pin(&configs[i], pin_cfg);
105
106 /* Serialize PWM configuration if applicable */
107 if (configs[i].mode == MESHX_GPIO_MODE_PWM_OUTPUT) {
109 meshx_gpio_kv_serialize_pwm(&configs[i], pwm_cfg);
111 }
112 }
113
114 /* Update total size in header */
115 header->total_size = (uint16_t)(ptr - buf);
116
117 /* Calculate and set CRC16 */
119
120 *out_size = header->total_size;
121
122 MESHX_LOGD(MODULE_ID_COMPONENT_MESHX_GPIO, "Serialized %d pins, size=%d", pin_count, *out_size);
123 return MESHX_SUCCESS;
124}
@ MESHX_GPIO_MODE_PWM_OUTPUT
Definition meshx_gpio.h:34
#define MESHX_GPIO_KV_MAX_PINS
Maximum number of pins supported in KV storage.
Definition meshx_gpio_kv.c:33
static void meshx_gpio_kv_serialize_pin(const meshx_gpio_pin_config_t *src, meshx_gpio_pin_config_kv_t *dst)
Convert runtime pin config to serialized format.
Definition meshx_gpio_kv.h:396
#define MESHX_GPIO_CONFIG_FLAG_HAS_PWM
Flag: Configuration has PWM extensions.
Definition meshx_gpio_kv.h:267
static void meshx_gpio_kv_serialize_pwm(const meshx_gpio_pin_config_t *src, meshx_gpio_pwm_config_kv_t *dst)
Serialize PWM configuration.
Definition meshx_gpio_kv.h:446
static void meshx_gpio_kv_finalize_crc16(uint8_t *data, uint32_t len)
Calculate and set CRC16 for serialized configuration.
Definition meshx_gpio_kv.h:377
static void meshx_gpio_kv_init_header(meshx_gpio_config_header_kv_t *header, uint8_t pin_count)
Initialize a GPIO configuration header.
Definition meshx_gpio_kv.h:356
uint8_t flags
Definition meshx_gpio_kv.h:167
uint16_t total_size
Definition meshx_gpio_kv.h:166

Variable Documentation

◆ current_product_name

char current_product_name[16+1] = {0}
static

Current product name for key prefix.

43{0};

◆ gpio_kv_partition

const meshx_fal_partition_t* gpio_kv_partition = NULL
static

KV Engine partition reference (set during initialization).

◆ kv_persistence_initialized

bool kv_persistence_initialized = false
static

Flag indicating if KV persistence is initialized.