Merge branch 'task/cli-params' into 'master'

rmaker_console: Add set-param, update-param and get-param commands

See merge request app-frameworks/esp-rainmaker!583
This commit is contained in:
Piyush Shah
2025-11-12 23:17:44 +05:30
9 changed files with 394 additions and 3 deletions

View File

@@ -1,5 +1,10 @@
# Changelog
## 1.7.9
### New Feature
- Added set-param, get-param and update-param console commands to assist in some testing
## 1.7.8
## Changes

View File

@@ -288,6 +288,15 @@ menu "ESP RainMaker Config"
default 0 if ESP_RMAKER_CONSOLE_UART_NUM_0
default 1 if ESP_RMAKER_CONSOLE_UART_NUM_1
config ESP_RMAKER_CONSOLE_PARAM_CMDS_ENABLE
bool "Enable parameter console commands (set-param, update-param, get-param)"
default n
help
Enable console commands for interacting with device parameters:
- set-param: Set parameter value with callback invocation
- update-param: Update parameter value without callback
- get-param: Get current parameter value
config ESP_RMAKER_USE_CERT_BUNDLE
bool "Use Certificate Bundle"
default y

View File

@@ -1,5 +1,5 @@
## IDF Component Manager Manifest File
version: "1.7.8"
version: "1.7.9"
description: ESP RainMaker firmware agent
url: https://github.com/espressif/esp-rainmaker/tree/master/components/esp_rainmaker
repository: https://github.com/espressif/esp-rainmaker.git

View File

@@ -163,6 +163,8 @@ typedef enum {
ESP_RMAKER_REQ_SRC_LOCAL,
/** Request received via command-response framework */
ESP_RMAKER_REQ_SRC_CMD_RESP,
/** Request initiated from firmware/console commands */
ESP_RMAKER_REQ_SRC_FIRMWARE,
/** This will always be the last value. Any value equal to or
* greater than this should be considered invalid.
*/

View File

@@ -14,22 +14,25 @@
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <inttypes.h>
#include <esp_log.h>
#include <esp_wifi.h>
#include <esp_console.h>
#include <string.h>
#include <esp_rmaker_core.h>
#include <esp_rmaker_user_mapping.h>
#include <esp_rmaker_utils.h>
#include <esp_rmaker_cmd_resp.h>
#include <esp_rmaker_internal.h>
#include <esp_rmaker_console_internal.h>
#include <network_provisioning/manager.h>
/* Include internal header to access device structure */
#include "esp_rmaker_internal.h"
static const char *TAG = "esp_rmaker_commands";
static int user_node_mapping_handler(int argc, char** argv)
{
if (argc == 3) {
@@ -185,6 +188,365 @@ static void register_sign_data_command()
esp_console_cmd_register(&cmd);
}
#ifdef CONFIG_ESP_RMAKER_CONSOLE_PARAM_CMDS_ENABLE
static int set_param_handler(int argc, char** argv)
{
if (argc != 4) {
printf("%s: Invalid Usage.\n", TAG);
printf("Usage: set-param <device_name> <param_name> <value>\n");
printf(" Note: This command invokes device callbacks (simulates real parameter changes)\n");
return ESP_ERR_INVALID_ARG;
}
const char *device_name = argv[1];
const char *param_name = argv[2];
const char *value_str_raw = argv[3];
/* Strip surrounding quotes if present */
char *value_str = strdup(value_str_raw);
if (!value_str) {
printf("%s: Failed to process value string\n", TAG);
return ESP_ERR_NO_MEM;
}
// Get the device handle
esp_rmaker_device_t *device = esp_rmaker_node_get_device_by_name(esp_rmaker_get_node(), device_name);
if (!device) {
printf("%s: Device %s not found\n", TAG, device_name);
free(value_str);
return ESP_FAIL;
}
// Get the parameter handle
esp_rmaker_param_t *param = esp_rmaker_device_get_param_by_name(device, param_name);
if (!param) {
printf("%s: Parameter %s not found in device %s\n", TAG, param_name, device_name);
free(value_str);
return ESP_FAIL;
}
// Get current value to determine type
esp_rmaker_param_val_t *val = esp_rmaker_param_get_val(param);
if (!val) {
printf("%s: Failed to get parameter value\n", TAG);
free(value_str);
return ESP_FAIL;
}
// Update value based on type
esp_rmaker_param_val_t new_val;
new_val.type = val->type;
switch(val->type) {
case RMAKER_VAL_TYPE_BOOLEAN:
new_val.val.b = (strcmp(value_str, "true") == 0 || strcmp(value_str, "1") == 0);
break;
case RMAKER_VAL_TYPE_INTEGER:
new_val.val.i = atoi(value_str);
break;
case RMAKER_VAL_TYPE_FLOAT:
new_val.val.f = atof(value_str);
break;
case RMAKER_VAL_TYPE_STRING:
new_val.val.s = strdup(value_str); // Create a copy to avoid lifetime issues
if (!new_val.val.s) {
printf("%s: Failed to allocate memory for string value\n", TAG);
free(value_str);
return ESP_FAIL;
}
break;
case RMAKER_VAL_TYPE_OBJECT:
new_val.val.s = strdup(value_str); // JSON objects are stored as strings
if (!new_val.val.s) {
printf("%s: Failed to allocate memory for object value\n", TAG);
free(value_str);
return ESP_FAIL;
}
break;
case RMAKER_VAL_TYPE_ARRAY:
new_val.val.s = strdup(value_str); // JSON arrays are stored as strings
if (!new_val.val.s) {
printf("%s: Failed to allocate memory for array value\n", TAG);
free(value_str);
return ESP_FAIL;
}
break;
default:
printf("%s: Unsupported value type\n", TAG);
free(value_str);
return ESP_FAIL;
}
esp_err_t err = ESP_OK;
/* Create JSON for esp_rmaker_handle_set_params to invoke callbacks */
char json_str[1024]; /* Increased buffer size for complex JSON */
int json_len = 0;
switch(val->type) {
case RMAKER_VAL_TYPE_BOOLEAN:
json_len = snprintf(json_str, sizeof(json_str), "{\"%s\":{\"%s\":%s}}",
device_name, param_name, new_val.val.b ? "true" : "false");
break;
case RMAKER_VAL_TYPE_INTEGER:
json_len = snprintf(json_str, sizeof(json_str), "{\"%s\":{\"%s\":%d}}",
device_name, param_name, new_val.val.i);
break;
case RMAKER_VAL_TYPE_FLOAT:
json_len = snprintf(json_str, sizeof(json_str), "{\"%s\":{\"%s\":%f}}",
device_name, param_name, new_val.val.f);
break;
case RMAKER_VAL_TYPE_STRING:
json_len = snprintf(json_str, sizeof(json_str), "{\"%s\":{\"%s\":\"%s\"}}",
device_name, param_name, new_val.val.s);
break;
case RMAKER_VAL_TYPE_OBJECT:
/* JSON objects are embedded directly without quotes */
json_len = snprintf(json_str, sizeof(json_str), "{\"%s\":{\"%s\":%s}}",
device_name, param_name, new_val.val.s);
break;
case RMAKER_VAL_TYPE_ARRAY:
/* JSON arrays are embedded directly without quotes */
json_len = snprintf(json_str, sizeof(json_str), "{\"%s\":{\"%s\":%s}}",
device_name, param_name, new_val.val.s);
break;
default:
printf("%s: Unsupported value type for callback\n", TAG);
/* Fall back to direct update */
err = esp_rmaker_param_update_and_report(param, new_val);
break;
}
if (json_len > 0 && json_len < sizeof(json_str)) {
/* Use the standard parameter handling function to invoke callbacks */
err = esp_rmaker_handle_set_params(json_str, json_len, ESP_RMAKER_REQ_SRC_FIRMWARE);
if (err == ESP_OK) {
printf("%s: Successfully set %s.%s with callback\n", TAG, device_name, param_name);
} else {
printf("%s: Callback failed for %s.%s\n", TAG, device_name, param_name);
}
} else {
printf("%s: Failed to create JSON for callback (len=%d, max=%zu)\n", TAG, json_len, sizeof(json_str));
err = ESP_FAIL;
}
/* Free allocated string memory if it was a string, object, or array type */
if ((val->type == RMAKER_VAL_TYPE_STRING || val->type == RMAKER_VAL_TYPE_OBJECT || val->type == RMAKER_VAL_TYPE_ARRAY) && new_val.val.s) {
free(new_val.val.s);
}
if (err != ESP_OK) {
printf("%s: Failed to update parameter value\n", TAG);
free(value_str);
return err;
}
printf("%s: Successfully set %s.%s to %s\n", TAG, device_name, param_name, value_str);
/* Free the processed value string */
free(value_str);
return ESP_OK;
}
static int update_param_handler(int argc, char** argv)
{
if (argc != 4) {
printf("%s: Invalid Usage.\n", TAG);
printf("Usage: update-param <device_name> <param_name> <value>\n");
printf(" Note: This command only updates the value without invoking callbacks\n");
return ESP_ERR_INVALID_ARG;
}
const char *device_name = argv[1];
const char *param_name = argv[2];
const char *value_str_raw = argv[3];
/* Strip surrounding quotes if present */
char *value_str = strdup(value_str_raw);
if (!value_str) {
printf("%s: Failed to process value string\n", TAG);
return ESP_ERR_NO_MEM;
}
// Get the device handle
esp_rmaker_device_t *device = esp_rmaker_node_get_device_by_name(esp_rmaker_get_node(), device_name);
if (!device) {
printf("%s: Device %s not found\n", TAG, device_name);
free(value_str);
return ESP_FAIL;
}
// Get the parameter handle
esp_rmaker_param_t *param = esp_rmaker_device_get_param_by_name(device, param_name);
if (!param) {
printf("%s: Parameter %s not found in device %s\n", TAG, param_name, device_name);
free(value_str);
return ESP_FAIL;
}
// Get current value to determine type
esp_rmaker_param_val_t *val = esp_rmaker_param_get_val(param);
if (!val) {
printf("%s: Failed to get parameter value\n", TAG);
free(value_str);
return ESP_FAIL;
}
// Update value based on type
esp_rmaker_param_val_t new_val;
new_val.type = val->type;
switch(val->type) {
case RMAKER_VAL_TYPE_BOOLEAN:
new_val.val.b = (strcmp(value_str, "true") == 0 || strcmp(value_str, "1") == 0);
break;
case RMAKER_VAL_TYPE_INTEGER:
new_val.val.i = atoi(value_str);
break;
case RMAKER_VAL_TYPE_FLOAT:
new_val.val.f = atof(value_str);
break;
case RMAKER_VAL_TYPE_STRING:
new_val.val.s = strdup(value_str); // Create a copy to avoid lifetime issues
if (!new_val.val.s) {
printf("%s: Failed to allocate memory for string value\n", TAG);
free(value_str);
return ESP_FAIL;
}
break;
case RMAKER_VAL_TYPE_OBJECT:
new_val.val.s = strdup(value_str); // JSON objects are stored as strings
if (!new_val.val.s) {
printf("%s: Failed to allocate memory for object value\n", TAG);
free(value_str);
return ESP_FAIL;
}
break;
case RMAKER_VAL_TYPE_ARRAY:
new_val.val.s = strdup(value_str); // JSON arrays are stored as strings
if (!new_val.val.s) {
printf("%s: Failed to allocate memory for array value\n", TAG);
free(value_str);
return ESP_FAIL;
}
break;
default:
printf("%s: Unsupported value type\n", TAG);
free(value_str);
return ESP_FAIL;
}
/* Update the parameter value without invoking callback */
esp_err_t err = esp_rmaker_param_update_and_report(param, new_val);
/* Free allocated string memory if it was a string, object, or array type */
if ((val->type == RMAKER_VAL_TYPE_STRING || val->type == RMAKER_VAL_TYPE_OBJECT || val->type == RMAKER_VAL_TYPE_ARRAY) && new_val.val.s) {
free(new_val.val.s);
}
if (err != ESP_OK) {
printf("%s: Failed to update parameter value\n", TAG);
free(value_str);
return err;
}
printf("%s: Successfully updated %s.%s to %s (no callback)\n", TAG, device_name, param_name, value_str);
/* Free the processed value string */
free(value_str);
return ESP_OK;
}
static int get_param_handler(int argc, char** argv)
{
if (argc != 3) {
printf("%s: Invalid Usage.\n", TAG);
printf("Usage: get-param <device_name> <param_name>\n");
return ESP_ERR_INVALID_ARG;
}
const char *device_name = argv[1];
const char *param_name = argv[2];
// Get the device handle
esp_rmaker_device_t *device = esp_rmaker_node_get_device_by_name(esp_rmaker_get_node(), device_name);
if (!device) {
printf("%s: Device %s not found\n", TAG, device_name);
return ESP_FAIL;
}
// Get the parameter handle
esp_rmaker_param_t *param = esp_rmaker_device_get_param_by_name(device, param_name);
if (!param) {
printf("%s: Parameter %s not found in device %s\n", TAG, param_name, device_name);
return ESP_FAIL;
}
// Get the parameter value
esp_rmaker_param_val_t *val = esp_rmaker_param_get_val(param);
if (!val) {
printf("%s: Failed to get parameter value\n", TAG);
return ESP_FAIL;
}
// Print value based on type
switch(val->type) {
case RMAKER_VAL_TYPE_BOOLEAN:
printf("%s: %s.%s = %s\n", TAG, device_name, param_name, val->val.b ? "true" : "false");
break;
case RMAKER_VAL_TYPE_INTEGER:
printf("%s: %s.%s = %d\n", TAG, device_name, param_name, val->val.i);
break;
case RMAKER_VAL_TYPE_FLOAT:
printf("%s: %s.%s = %f\n", TAG, device_name, param_name, val->val.f);
break;
case RMAKER_VAL_TYPE_STRING:
printf("%s: %s.%s = %s\n", TAG, device_name, param_name, val->val.s);
break;
case RMAKER_VAL_TYPE_OBJECT:
printf("%s: %s.%s = %s\n", TAG, device_name, param_name, val->val.s);
break;
case RMAKER_VAL_TYPE_ARRAY:
printf("%s: %s.%s = %s\n", TAG, device_name, param_name, val->val.s);
break;
default:
printf("%s: Unsupported value type\n", TAG);
return ESP_FAIL;
}
return ESP_OK;
}
static void register_param_commands()
{
const esp_console_cmd_t set_cmd = {
.command = "set-param",
.help = "Set device parameter value with callback. Usage: set-param <device_name> <param_name> <value>",
.func = &set_param_handler,
};
ESP_LOGI(TAG, "Registering command: %s", set_cmd.command);
esp_console_cmd_register(&set_cmd);
const esp_console_cmd_t update_cmd = {
.command = "update-param",
.help = "Update device parameter value without callback. Usage: update-param <device_name> <param_name> <value>",
.func = &update_param_handler,
};
ESP_LOGI(TAG, "Registering command: %s", update_cmd.command);
esp_console_cmd_register(&update_cmd);
const esp_console_cmd_t get_cmd = {
.command = "get-param",
.help = "Get device parameter value. Usage: get-param <device_name> <param_name>",
.func = &get_param_handler,
};
ESP_LOGI(TAG, "Registering command: %s", get_cmd.command);
esp_console_cmd_register(&get_cmd);
}
#endif /* CONFIG_ESP_RMAKER_CONSOLE_PARAM_CMDS_ENABLE */
void register_commands()
{
register_user_node_mapping();
@@ -194,4 +556,7 @@ void register_commands()
register_cmd_resp_command();
#endif
register_sign_data_command();
#ifdef CONFIG_ESP_RMAKER_CONSOLE_PARAM_CMDS_ENABLE
register_param_commands();
#endif
}

View File

@@ -54,6 +54,7 @@ static const char *cb_srcs[ESP_RMAKER_REQ_SRC_MAX] = {
[ESP_RMAKER_REQ_SRC_SCENE_DEACTIVATE] = "Scene Deactivate",
[ESP_RMAKER_REQ_SRC_LOCAL] = "Local",
[ESP_RMAKER_REQ_SRC_CMD_RESP] = "Command Response",
[ESP_RMAKER_REQ_SRC_FIRMWARE] = "Firmware",
};
const char *esp_rmaker_device_cb_src_to_str(esp_rmaker_req_src_t src)

View File

@@ -38,6 +38,9 @@ CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH=3120
# For additional security on reset to factory
CONFIG_ESP_RMAKER_USER_ID_CHECK=y
# Enable parameter console commands
CONFIG_ESP_RMAKER_CONSOLE_PARAM_CMDS_ENABLE=y
# Application Rollback
CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE=y

View File

@@ -28,6 +28,9 @@ CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH=3120
# For additional security on reset to factory
CONFIG_ESP_RMAKER_USER_ID_CHECK=y
# Enable parameter console commands
CONFIG_ESP_RMAKER_CONSOLE_PARAM_CMDS_ENABLE=y
# Secure Local Control
CONFIG_ESP_RMAKER_LOCAL_CTRL_AUTO_ENABLE=y
#CONFIG_ESP_RMAKER_LOCAL_CTRL_ENABLE is deprecated but will continue to work

View File

@@ -28,6 +28,9 @@ CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH=3120
# For additional security on reset to factory
CONFIG_ESP_RMAKER_USER_ID_CHECK=y
# Enable parameter console commands
CONFIG_ESP_RMAKER_CONSOLE_PARAM_CMDS_ENABLE=y
# Secure Local Control
CONFIG_ESP_RMAKER_LOCAL_CTRL_AUTO_ENABLE=y
#CONFIG_ESP_RMAKER_LOCAL_CTRL_ENABLE is deprecated but will continue to work