diff --git a/components/esp_matter/esp_matter_attribute_utils.cpp b/components/esp_matter/esp_matter_attribute_utils.cpp index f861685c2..53a4ac8f9 100644 --- a/components/esp_matter/esp_matter_attribute_utils.cpp +++ b/components/esp_matter/esp_matter_attribute_utils.cpp @@ -263,186 +263,213 @@ namespace attribute { static esp_matter_val_type_t get_val_type_from_attribute_type(int attribute_type); static callback_t attribute_callback = NULL; +#if CONFIG_ENABLE_CHIP_SHELL +static esp_matter::console::engine attribute_console; -static esp_err_t console_handler(int argc, char **argv) +static esp_err_t console_set_handler(int argc, char **argv) { - if (argc == 5 && strncmp(argv[0], "set", sizeof("set")) == 0) { - uint16_t endpoint_id = strtol((const char *)&argv[1][2], NULL, 16); - uint32_t cluster_id = strtol((const char *)&argv[2][2], NULL, 16); - uint32_t attribute_id = strtol((const char *)&argv[3][2], NULL, 16); + uint16_t endpoint_id = strtol((const char *)&argv[0][2], NULL, 16); + uint32_t cluster_id = strtol((const char *)&argv[1][2], NULL, 16); + uint32_t attribute_id = strtol((const char *)&argv[2][2], NULL, 16); - /* Get type from matter_attribute */ - const EmberAfAttributeMetadata *matter_attribute = emberAfLocateAttributeMetadata(endpoint_id, cluster_id, - attribute_id); - if (!matter_attribute) { - ESP_LOGE(TAG, "Matter attribute not found"); - return ESP_ERR_INVALID_ARG; - } - - /* Use the type to create the val and then update te attribute */ - esp_matter_val_type_t type = get_val_type_from_attribute_type(matter_attribute->attributeType); - esp_matter_attr_val_t val = esp_matter_invalid(NULL); - if (type == ESP_MATTER_VAL_TYPE_BOOLEAN) { - bool value = atoi(argv[4]); - val = esp_matter_bool(value); - } else if (type == ESP_MATTER_VAL_TYPE_INT8) { - int8_t value = atoi(argv[4]); - val = esp_matter_int8(value); - } else if (type == ESP_MATTER_VAL_TYPE_UINT8) { - uint8_t value = atoi(argv[4]); - val = esp_matter_uint8(value); - } else if (type == ESP_MATTER_VAL_TYPE_INT16) { - int16_t value = atoi(argv[4]); - val = esp_matter_int16(value); - } else if (type == ESP_MATTER_VAL_TYPE_UINT16) { - uint16_t value = atoi(argv[4]); - val = esp_matter_uint16(value); - } else if (type == ESP_MATTER_VAL_TYPE_INT32) { - int32_t value = atoi(argv[4]); - val = esp_matter_int32(value); - } else if (type == ESP_MATTER_VAL_TYPE_UINT32) { - uint32_t value = atoi(argv[4]); - val = esp_matter_uint32(value); - } else if (type == ESP_MATTER_VAL_TYPE_INT64) { - int64_t value = atoi(argv[4]); - val = esp_matter_int64(value); - } else if (type == ESP_MATTER_VAL_TYPE_UINT64) { - uint64_t value = atoi(argv[4]); - val = esp_matter_uint64(value); - } else if (type == ESP_MATTER_VAL_TYPE_CHAR_STRING) { - char *value = argv[4]; - val = esp_matter_char_str(value, strlen(value)); - } else if (type == ESP_MATTER_VAL_TYPE_BITMAP8) { - uint8_t value = atoi(argv[4]); - val = esp_matter_bitmap8(value); - } else if (type == ESP_MATTER_VAL_TYPE_BITMAP16) { - uint16_t value = atoi(argv[4]); - val = esp_matter_bitmap16(value); - } else if (type == ESP_MATTER_VAL_TYPE_BITMAP32) { - uint32_t value = atoi(argv[4]); - val = esp_matter_bitmap32(value); - } else if (type == ESP_MATTER_VAL_TYPE_ENUM8) { - uint8_t value = atoi(argv[4]); - val = esp_matter_enum8(value); - } else { - ESP_LOGE(TAG, "Type not handled: %d", type); - return ESP_ERR_INVALID_ARG; - } - update(endpoint_id, cluster_id, attribute_id, &val); - } else if (argc == 4 && strncmp(argv[0], "get", sizeof("get")) == 0) { - uint16_t endpoint_id = strtol((const char *)&argv[1][2], NULL, 16); - uint32_t cluster_id = strtol((const char *)&argv[2][2], NULL, 16); - uint32_t attribute_id = strtol((const char *)&argv[3][2], NULL, 16); - - /* Get type from matter_attribute */ - const EmberAfAttributeMetadata *matter_attribute = emberAfLocateAttributeMetadata(endpoint_id, cluster_id, - attribute_id); - if (!matter_attribute) { - ESP_LOGE(TAG, "Matter attribute not found"); - return ESP_ERR_INVALID_ARG; - } - - /* Use the type to read the raw value and then print */ - esp_matter_val_type_t type = get_val_type_from_attribute_type(matter_attribute->attributeType); - esp_matter_attr_val_t val = esp_matter_invalid(NULL); - if (type == ESP_MATTER_VAL_TYPE_BOOLEAN) { - bool value = false; - get_val_raw(endpoint_id, cluster_id, attribute_id, (uint8_t *)&value, sizeof(value)); - val = esp_matter_bool(value); - } else if (type == ESP_MATTER_VAL_TYPE_INT8) { - int8_t value = 0; - get_val_raw(endpoint_id, cluster_id, attribute_id, (uint8_t *)&value, sizeof(value)); - val = esp_matter_int8(value); - } else if (type == ESP_MATTER_VAL_TYPE_UINT8) { - uint8_t value = 0; - get_val_raw(endpoint_id, cluster_id, attribute_id, (uint8_t *)&value, sizeof(value)); - val = esp_matter_uint8(value); - } else if (type == ESP_MATTER_VAL_TYPE_INT16) { - int16_t value = 0; - get_val_raw(endpoint_id, cluster_id, attribute_id, (uint8_t *)&value, sizeof(value)); - val = esp_matter_int16(value); - } else if (type == ESP_MATTER_VAL_TYPE_UINT16) { - uint16_t value = 0; - get_val_raw(endpoint_id, cluster_id, attribute_id, (uint8_t *)&value, sizeof(value)); - val = esp_matter_uint16(value); - } else if (type == ESP_MATTER_VAL_TYPE_INT32) { - int32_t value = 0; - get_val_raw(endpoint_id, cluster_id, attribute_id, (uint8_t *)&value, sizeof(value)); - val = esp_matter_int32(value); - } else if (type == ESP_MATTER_VAL_TYPE_UINT32) { - uint32_t value = 0; - get_val_raw(endpoint_id, cluster_id, attribute_id, (uint8_t *)&value, sizeof(value)); - val = esp_matter_uint32(value); - } else if (type == ESP_MATTER_VAL_TYPE_INT64) { - int64_t value = 0; - get_val_raw(endpoint_id, cluster_id, attribute_id, (uint8_t *)&value, sizeof(value)); - val = esp_matter_int64(value); - } else if (type == ESP_MATTER_VAL_TYPE_UINT64) { - uint64_t value = 0; - get_val_raw(endpoint_id, cluster_id, attribute_id, (uint8_t *)&value, sizeof(value)); - val = esp_matter_uint64(value); - } else if (type == ESP_MATTER_VAL_TYPE_CHAR_STRING) { - /* Get raw value */ - char value[256] = {0}; /* It can go upto 256 since only 1 byte (first) is used for size */ - get_val_raw(endpoint_id, cluster_id, attribute_id, (uint8_t *)&value, sizeof(value)); - /* Get val from raw value */ - val = esp_matter_char_str(NULL, 0); - int data_size_len = val.val.a.t - val.val.a.s; - int data_count = 0; - memcpy(&data_count, &value[0], data_size_len); - val = esp_matter_char_str((char *)(value + data_size_len), data_count); - } else if (type == ESP_MATTER_VAL_TYPE_BITMAP8) { - uint8_t value = 0; - get_val_raw(endpoint_id, cluster_id, attribute_id, (uint8_t *)&value, sizeof(value)); - val = esp_matter_bitmap8(value); - } else if (type == ESP_MATTER_VAL_TYPE_BITMAP16) { - uint16_t value = 0; - get_val_raw(endpoint_id, cluster_id, attribute_id, (uint8_t *)&value, sizeof(value)); - val = esp_matter_bitmap16(value); - } else if (type == ESP_MATTER_VAL_TYPE_BITMAP32) { - uint32_t value = 0; - get_val_raw(endpoint_id, cluster_id, attribute_id, (uint8_t *)&value, sizeof(value)); - val = esp_matter_bitmap32(value); - } else if (type == ESP_MATTER_VAL_TYPE_ENUM8) { - uint8_t value = 0; - get_val_raw(endpoint_id, cluster_id, attribute_id, (uint8_t *)&value, sizeof(value)); - val = esp_matter_enum8(value); - } else { - ESP_LOGE(TAG, "Type not handled: %d", type); - return ESP_ERR_INVALID_ARG; - } - val_print(endpoint_id, cluster_id, attribute_id, &val); - } else { - ESP_LOGE(TAG, "Incorrect arguments"); + /* Get type from matter_attribute */ + const EmberAfAttributeMetadata *matter_attribute = emberAfLocateAttributeMetadata(endpoint_id, cluster_id, + attribute_id); + if (!matter_attribute) { + ESP_LOGE(TAG, "Matter attribute not found"); return ESP_ERR_INVALID_ARG; } + + /* Use the type to create the val and then update te attribute */ + esp_matter_val_type_t type = get_val_type_from_attribute_type(matter_attribute->attributeType); + esp_matter_attr_val_t val = esp_matter_invalid(NULL); + if (type == ESP_MATTER_VAL_TYPE_BOOLEAN) { + bool value = atoi(argv[3]); + val = esp_matter_bool(value); + } else if (type == ESP_MATTER_VAL_TYPE_INT8) { + int8_t value = atoi(argv[3]); + val = esp_matter_int8(value); + } else if (type == ESP_MATTER_VAL_TYPE_UINT8) { + uint8_t value = atoi(argv[3]); + val = esp_matter_uint8(value); + } else if (type == ESP_MATTER_VAL_TYPE_INT16) { + int16_t value = atoi(argv[3]); + val = esp_matter_int16(value); + } else if (type == ESP_MATTER_VAL_TYPE_UINT16) { + uint16_t value = atoi(argv[3]); + val = esp_matter_uint16(value); + } else if (type == ESP_MATTER_VAL_TYPE_INT32) { + int32_t value = atoi(argv[3]); + val = esp_matter_int32(value); + } else if (type == ESP_MATTER_VAL_TYPE_UINT32) { + uint32_t value = atoi(argv[3]); + val = esp_matter_uint32(value); + } else if (type == ESP_MATTER_VAL_TYPE_INT64) { + int64_t value = atoi(argv[3]); + val = esp_matter_int64(value); + } else if (type == ESP_MATTER_VAL_TYPE_UINT64) { + uint64_t value = atoi(argv[3]); + val = esp_matter_uint64(value); + } else if (type == ESP_MATTER_VAL_TYPE_CHAR_STRING) { + char *value = argv[3]; + val = esp_matter_char_str(value, strlen(value)); + } else if (type == ESP_MATTER_VAL_TYPE_BITMAP8) { + uint8_t value = atoi(argv[3]); + val = esp_matter_bitmap8(value); + } else if (type == ESP_MATTER_VAL_TYPE_BITMAP16) { + uint16_t value = atoi(argv[3]); + val = esp_matter_bitmap16(value); + } else if (type == ESP_MATTER_VAL_TYPE_BITMAP32) { + uint32_t value = atoi(argv[3]); + val = esp_matter_bitmap32(value); + } else if (type == ESP_MATTER_VAL_TYPE_ENUM8) { + uint8_t value = atoi(argv[3]); + val = esp_matter_enum8(value); + } else { + ESP_LOGE(TAG, "Type not handled: %d", type); + return ESP_ERR_INVALID_ARG; + } + return update(endpoint_id, cluster_id, attribute_id, &val); +} + +static esp_err_t console_get_handler(int argc, char **argv) +{ + uint16_t endpoint_id = strtol((const char *)&argv[0][2], NULL, 16); + uint32_t cluster_id = strtol((const char *)&argv[1][2], NULL, 16); + uint32_t attribute_id = strtol((const char *)&argv[2][2], NULL, 16); + + /* Get type from matter_attribute */ + const EmberAfAttributeMetadata *matter_attribute = emberAfLocateAttributeMetadata(endpoint_id, cluster_id, + attribute_id); + if (!matter_attribute) { + ESP_LOGE(TAG, "Matter attribute not found"); + return ESP_ERR_INVALID_ARG; + } + + /* Use the type to read the raw value and then print */ + esp_matter_val_type_t type = get_val_type_from_attribute_type(matter_attribute->attributeType); + esp_matter_attr_val_t val = esp_matter_invalid(NULL); + if (type == ESP_MATTER_VAL_TYPE_BOOLEAN) { + bool value = false; + get_val_raw(endpoint_id, cluster_id, attribute_id, (uint8_t *)&value, sizeof(value)); + val = esp_matter_bool(value); + } else if (type == ESP_MATTER_VAL_TYPE_INT8) { + int8_t value = 0; + get_val_raw(endpoint_id, cluster_id, attribute_id, (uint8_t *)&value, sizeof(value)); + val = esp_matter_int8(value); + } else if (type == ESP_MATTER_VAL_TYPE_UINT8) { + uint8_t value = 0; + get_val_raw(endpoint_id, cluster_id, attribute_id, (uint8_t *)&value, sizeof(value)); + val = esp_matter_uint8(value); + } else if (type == ESP_MATTER_VAL_TYPE_INT16) { + int16_t value = 0; + get_val_raw(endpoint_id, cluster_id, attribute_id, (uint8_t *)&value, sizeof(value)); + val = esp_matter_int16(value); + } else if (type == ESP_MATTER_VAL_TYPE_UINT16) { + uint16_t value = 0; + get_val_raw(endpoint_id, cluster_id, attribute_id, (uint8_t *)&value, sizeof(value)); + val = esp_matter_uint16(value); + } else if (type == ESP_MATTER_VAL_TYPE_INT32) { + int32_t value = 0; + get_val_raw(endpoint_id, cluster_id, attribute_id, (uint8_t *)&value, sizeof(value)); + val = esp_matter_int32(value); + } else if (type == ESP_MATTER_VAL_TYPE_UINT32) { + uint32_t value = 0; + get_val_raw(endpoint_id, cluster_id, attribute_id, (uint8_t *)&value, sizeof(value)); + val = esp_matter_uint32(value); + } else if (type == ESP_MATTER_VAL_TYPE_INT64) { + int64_t value = 0; + get_val_raw(endpoint_id, cluster_id, attribute_id, (uint8_t *)&value, sizeof(value)); + val = esp_matter_int64(value); + } else if (type == ESP_MATTER_VAL_TYPE_UINT64) { + uint64_t value = 0; + get_val_raw(endpoint_id, cluster_id, attribute_id, (uint8_t *)&value, sizeof(value)); + val = esp_matter_uint64(value); + } else if (type == ESP_MATTER_VAL_TYPE_CHAR_STRING) { + /* Get raw value */ + char value[256] = {0}; /* It can go upto 256 since only 1 byte (first) is used for size */ + get_val_raw(endpoint_id, cluster_id, attribute_id, (uint8_t *)&value, sizeof(value)); + /* Get val from raw value */ + val = esp_matter_char_str(NULL, 0); + int data_size_len = val.val.a.t - val.val.a.s; + int data_count = 0; + memcpy(&data_count, &value[0], data_size_len); + val = esp_matter_char_str((char *)(value + data_size_len), data_count); + } else if (type == ESP_MATTER_VAL_TYPE_BITMAP8) { + uint8_t value = 0; + get_val_raw(endpoint_id, cluster_id, attribute_id, (uint8_t *)&value, sizeof(value)); + val = esp_matter_bitmap8(value); + } else if (type == ESP_MATTER_VAL_TYPE_BITMAP16) { + uint16_t value = 0; + get_val_raw(endpoint_id, cluster_id, attribute_id, (uint8_t *)&value, sizeof(value)); + val = esp_matter_bitmap16(value); + } else if (type == ESP_MATTER_VAL_TYPE_BITMAP32) { + uint32_t value = 0; + get_val_raw(endpoint_id, cluster_id, attribute_id, (uint8_t *)&value, sizeof(value)); + val = esp_matter_bitmap32(value); + } else if (type == ESP_MATTER_VAL_TYPE_ENUM8) { + uint8_t value = 0; + get_val_raw(endpoint_id, cluster_id, attribute_id, (uint8_t *)&value, sizeof(value)); + val = esp_matter_enum8(value); + } else { + ESP_LOGE(TAG, "Type not handled: %d", type); + return ESP_ERR_INVALID_ARG; + } + val_print(endpoint_id, cluster_id, attribute_id, &val); return ESP_OK; } -static void register_commands() +static esp_err_t console_dispatch(int argc, char **argv) +{ + if (argc <= 0) { + attribute_console.for_each_command(esp_matter::console::print_description, NULL); + return ESP_OK; + } + return attribute_console.exec_command(argc, argv); +} + +static void register_console_commands() { static bool init_done = false; if (init_done) { return; } - esp_matter_console_command_t command = { + static const esp_matter::console::command_t command = { .name = "attribute", - .description = "This can be used to simulate on-device control. " - "Usage: matter esp attribute [value]. " - "Example1: matter esp attribute set 0x0001 0x0006 0x0000 1. " - "Example2: matter esp attribute get 0x0001 0x0006 0x0000.", - .handler = console_handler, + .description = "This can be used to simulate on-device control. ", + .handler = console_dispatch, }; - esp_matter_console_add_command(&command); + + static const esp_matter::console::command_t attribute_commands[] = { + { + .name = "set", + .description = "Set an attribute value of a cluster on an endpoint. " + "Usage: matter esp attribute set . " + "Example: matter esp attribute set 0x0001 0x0006 0x0000 1.", + .handler = console_set_handler, + }, + { + .name = "get", + .description = "Get an attribute value of a cluster on an endpoint. " + "Usage: matter esp attribute get . " + "Example: matter esp attribute get 0x0001 0x0006 0x0000.", + .handler = console_get_handler, + }, + }; + attribute_console.register_commands(attribute_commands, sizeof(attribute_commands)/sizeof(esp_matter::console::command_t)); + esp_matter::console::add_commands(&command, 1); init_done = true; } +#endif // CONFIG_ENABLE_CHIP_SHELL esp_err_t set_callback(callback_t callback) { attribute_callback = callback; /* Other initialisations */ - register_commands(); +#if CONFIG_ENABLE_CHIP_SHELL + register_console_commands(); +#endif return ESP_OK; } diff --git a/components/esp_matter_console/CMakeLists.txt b/components/esp_matter_console/CMakeLists.txt index f69a51c9e..37a933eb0 100644 --- a/components/esp_matter_console/CMakeLists.txt +++ b/components/esp_matter_console/CMakeLists.txt @@ -1,3 +1,7 @@ -idf_component_register(SRCS esp_matter_console.cpp esp_matter_console_diagnostics.cpp +set(srcs_list ) +if (CONFIG_ENABLE_CHIP_SHELL) + list(APPEND srcs_list esp_matter_console.cpp esp_matter_console_diagnostics.cpp) +endif() +idf_component_register(SRCS ${srcs_list} INCLUDE_DIRS . - PRIV_REQUIRES chip esp32_mbedtls esp_timer) + PRIV_REQUIRES chip esp32_mbedtls esp_timer bt openthread) diff --git a/components/esp_matter_console/esp_matter_console.cpp b/components/esp_matter_console/esp_matter_console.cpp index c1a66d794..ba23f0b9e 100644 --- a/components/esp_matter_console/esp_matter_console.cpp +++ b/components/esp_matter_console/esp_matter_console.cpp @@ -19,80 +19,100 @@ #include #include +#include -#define MAX_CONSOLE_COMMANDS CONFIG_ESP_MATTER_CONSOLE_MAX_COMMANDS +namespace esp_matter { +namespace console { static const char *TAG = "esp_matter_console"; -static esp_matter_console_command_t commands[MAX_CONSOLE_COMMANDS]; -static int total_added_commands = 0; +static engine base_engine; -esp_err_t esp_matter_console_add_command(esp_matter_console_command_t *command) +void engine::for_each_command(command_iterator_t *on_command, void *arg) { - if (total_added_commands + 1 > MAX_CONSOLE_COMMANDS) { - ESP_LOGE(TAG, "Could not add command. Increase the max limit to add more."); + for (unsigned i = 0; i < _command_set_count; ++i) { + for (unsigned j = 0; j < _command_set_size[i]; ++j) { + if (on_command(&_command_set[i][j], arg) != ESP_OK) { + return; + } + } + } +} + +esp_err_t engine::exec_command(int argc, char *argv[]) +{ + esp_err_t err = ESP_ERR_INVALID_ARG; + if (argc <= 0) { + return err; + } + // find the command from the command set + for (unsigned i = 0; i < _command_set_count; ++i) { + for (unsigned j = 0; j < _command_set_size[i]; ++j) { + if (strcmp(argv[0], _command_set[i][j].name) == 0 && _command_set[i][j].handler) { + err = _command_set[i][j].handler(argc - 1, &argv[1]); + break; + } + } + } + return err; +} + +esp_err_t engine::register_commands(const command_t *command_set, unsigned count) +{ + if (_command_set_count >= CONSOLE_MAX_COMMAND_SETS) { + ESP_LOGE(TAG, "Max number of command sets reached"); return ESP_FAIL; } - /* Since the strings in esp_matter_console_command_t are constants, this will work */ - commands[total_added_commands] = *command; - total_added_commands++; + + _command_set[_command_set_count] = command_set; + _command_set_size[_command_set_count] = count; + ++_command_set_count; return ESP_OK; } -static void esp_matter_console_print_help() +esp_err_t add_commands(const command_t *command_set, unsigned count) { - ESP_LOGI(TAG, "Usage: matter esp "); - ESP_LOGI(TAG, "Sub commands:"); - for (int i = 0; i < total_added_commands; i++) { - ESP_LOGI(TAG, "\t%s: %s", commands[i].name, commands[i].description); - } + return base_engine.register_commands(command_set, count); } -static esp_err_t esp_matter_console_help_handler(int argc, char **argv) +esp_err_t print_description(const command_t *command, void *arg) { - esp_matter_console_print_help(); + ESP_LOGI(TAG, "\t%s: %s", command->name, command->description); return ESP_OK; } -static esp_err_t esp_matter_console_register_default_commands() + +static esp_err_t help_handler(int argc, char **argv) { - esp_matter_console_command_t command = { + base_engine.for_each_command(print_description, NULL); + return ESP_OK; +} + +static esp_err_t register_default_commands() +{ + static const command_t command= { .name = "help", .description = "Print help", - .handler = esp_matter_console_help_handler, + .handler = help_handler, }; - return esp_matter_console_add_command(&command); + return add_commands(&command, 1); } -static CHIP_ERROR esp_matter_console_common_handler(int argc, char **argv) +static CHIP_ERROR common_handler(int argc, char **argv) { /* This common handler is added to avoid adding `CHIP_ERROR` and its component requirements in other esp-matter * components */ if (argc <= 0) { - esp_matter_console_print_help(); + help_handler(argc, argv); return CHIP_NO_ERROR; } - for (int i = 0; i < total_added_commands; i++) { - if (strncmp(argv[0], commands[i].name, strlen(commands[i].name) + 1) == 0) { - if (commands[i].handler == NULL) { - ESP_LOGW(TAG, "No handler set for the command: %s", argv[0]); - return CHIP_NO_ERROR; - } - if (commands[i].handler(argc - 1, &argv[1]) == ESP_OK) { /* Removing the first argument from argv */ - return CHIP_NO_ERROR; - } - /* The command handler returned error */ - return CHIP_ERROR_INVALID_ARGUMENT; - } - } - ESP_LOGE(TAG, "Could not find the command: %s. Try the help command for more details: matter esp help", argv[0]); - return CHIP_ERROR_INVALID_ARGUMENT; + return chip::DeviceLayer::Internal::ESP32Utils::MapError(base_engine.exec_command(argc, argv)); } -static esp_err_t esp_matter_console_register_common_shell_handler() +static esp_err_t register_common_shell_handler() { - static chip::Shell::shell_command_t cmds[] = { + static const chip::Shell::shell_command_t cmds[] = { { - .cmd_func = esp_matter_console_common_handler, + .cmd_func = common_handler, .cmd_name = "esp", .cmd_help = "Usage: matter esp ", }, @@ -107,14 +127,14 @@ static void ChipShellTask(void *args) chip::Shell::Engine::Root().RunMainLoop(); } -esp_err_t esp_matter_console_init() +esp_err_t init() { esp_err_t err = ESP_OK; - err = esp_matter_console_register_default_commands(); + err = register_default_commands(); if (err != ESP_OK) { ESP_LOGE(TAG, "Couldn't register default console commands"); } - err = esp_matter_console_register_common_shell_handler(); + err = register_common_shell_handler(); if (err != ESP_OK) { ESP_LOGE(TAG, "Couldn't register common handler"); return err; @@ -126,3 +146,6 @@ esp_err_t esp_matter_console_init() } return err; } + +} // namespace console +} // namespace esp_matter diff --git a/components/esp_matter_console/esp_matter_console.h b/components/esp_matter_console/esp_matter_console.h index 001dbd451..0f507d548 100644 --- a/components/esp_matter_console/esp_matter_console.h +++ b/components/esp_matter_console/esp_matter_console.h @@ -15,10 +15,12 @@ #pragma once #include +#include -#ifdef __cplusplus -extern "C" { -#endif +#define CONSOLE_MAX_COMMAND_SETS CONFIG_ESP_MATTER_CONSOLE_MAX_COMMANDS + +namespace esp_matter { +namespace console { /** Callback for console commands * @@ -27,7 +29,7 @@ extern "C" { * @return ESP_OK on success. * @return error in case of failure. */ -typedef esp_err_t (*esp_matter_console_handler_t)(int argc, char **argv); +typedef esp_err_t (*command_handler_t)(int argc, char **argv); /** ESP Matter Console Command */ typedef struct { @@ -36,8 +38,64 @@ typedef struct { /** Command Description/Help */ const char *description; /** Command Handler */ - esp_matter_console_handler_t handler; -} esp_matter_console_command_t; + command_handler_t handler; +} command_t; + +/** Command iterator callback for the console commands + * + * @param command The console command being iterated. + * @param arg A context variable passed to the iterator function. + * + * @return ESP_OK to continue iteration; anything else to break iteration. + */ +typedef esp_err_t command_iterator_t(const command_t *command, void *arg); + +class engine +{ +protected: + const command_t *_command_set[CONSOLE_MAX_COMMAND_SETS]; + unsigned _command_set_size[CONSOLE_MAX_COMMAND_SETS]; + unsigned _command_set_count; +public: + engine(): _command_set_count(0) {} + + /** Execution callback for a console command. + * + * @param[in] on_command An iterator callback to be called for each command. + * @param[in] arg A context variable to be passed to each command iterated. + */ + void for_each_command(command_iterator_t *on_command, void *arg); + + /** Dispatch and execute the command for the given argument list. + * + * @param[in] argc Number of arguments in argv. + * @param[in] argv Array of arguments in the tokenized command line to execute. + * + * @return ESP_OK on success + * @return error in case of failure. + */ + esp_err_t exec_command(int argc, char *argv[]); + + /** Registers a command set, or array of commands with the console. + * + * @param command_set[in] An array of commands to add to the console. + * @param count[in] The number of commands in the command set array. + * + * @return ESP_OK on success + * @return error in case of failure. + */ + esp_err_t register_commands(const command_t *command_set, unsigned count); +}; + +/** Print the description of a command + * + * @param command[in] The command which's description will be printed. + * @param arg[in] A context variable passed to the iterator function. + * + * @return ESP_OK on success + * @return error in case of failure. + */ +esp_err_t print_description(const command_t *command, void *arg); /** Initialize Console * @@ -46,19 +104,20 @@ typedef struct { * @return ESP_OK on success. * @return error in case of failure. */ -esp_err_t esp_matter_console_init(void); +esp_err_t init(void); -/** Add Console Command +/** Add Console Command Set * * Add a new console command. * This can be done before calling `esp_matter_console_init()` but the commands will not work until initialized. * - * @param[in] command Pointer to command struct + * @param[in] command_set Command struct set array pointer + * @param[in] count Command struct set array size * * @return ESP_OK on success. * @return error in case of failure. */ -esp_err_t esp_matter_console_add_command(esp_matter_console_command_t *command); +esp_err_t add_commands(const command_t *command_set, unsigned count); /** Add Diagnostics Commands * @@ -67,8 +126,7 @@ esp_err_t esp_matter_console_add_command(esp_matter_console_command_t *command); * @return ESP_OK on success. * @return error in case of failure. */ -esp_err_t esp_matter_console_diagnostics_register_commands(); +esp_err_t diagnostics_register_commands(); -#ifdef __cplusplus -} -#endif +} // namespace console +} // namespace esp_matter diff --git a/components/esp_matter_console/esp_matter_console_diagnostics.cpp b/components/esp_matter_console/esp_matter_console_diagnostics.cpp index 60d7637e4..1e91aa343 100644 --- a/components/esp_matter_console/esp_matter_console_diagnostics.cpp +++ b/components/esp_matter_console/esp_matter_console_diagnostics.cpp @@ -18,7 +18,11 @@ #include #include +namespace esp_matter { +namespace console { + static const char *TAG = "esp_matter_console_diagnostics"; +static engine diagnostics_console; static esp_err_t mem_dump_console_handler(int argc, char *argv[]) { @@ -39,26 +43,38 @@ static esp_err_t up_time_console_handler(int argc, char *argv[]) return ESP_OK; } -static esp_err_t esp_matter_console_diagnostics_handler(int argc, char **argv) +static esp_err_t diagnostics_dispatch(int argc, char **argv) { - if (argc == 1 && strncmp(argv[0], "mem-dump", sizeof("mem-dump")) == 0) { - return mem_dump_console_handler(argc, argv); - } else if (argc == 1 && strncmp(argv[0], "up-time", sizeof("up-time")) == 0) { - return up_time_console_handler(argc, argv); - } else { - ESP_LOGE(TAG, "Incorrect arguments"); - return ESP_FAIL; + if (argc <= 0) { + diagnostics_console.for_each_command(print_description, NULL); + return ESP_OK; } - return ESP_OK; + return diagnostics_console.exec_command(argc, argv); } -esp_err_t esp_matter_console_diagnostics_register_commands() +esp_err_t diagnostics_register_commands() { - esp_matter_console_command_t command = { + static const command_t command = { .name = "diagnostics", - .description = "Diagnostic commands. Usage matter esp diagnostics . Diagnostics commands: " - "mem-dump, up-time", - .handler = esp_matter_console_diagnostics_handler, + .description = "Diagnostic commands. Usage matter esp diagnostics .", + .handler = diagnostics_dispatch, }; - return esp_matter_console_add_command(&command); + + static const command_t diagnostics_commands[] = { + { + .name = "mem-dump", + .description = "help for memory analysis", + .handler = mem_dump_console_handler, + }, + { + .name = "up-time", + .description = "print the uptime of the device", + .handler = up_time_console_handler, + }, + }; + diagnostics_console.register_commands(diagnostics_commands, sizeof(diagnostics_commands)/sizeof(command_t)); + + return add_commands(&command, 1); } +} // namespace console +} // namespace esp_matter diff --git a/examples/blemesh_bridge/main/CMakeLists.txt b/examples/blemesh_bridge/main/CMakeLists.txt index 6697be26c..c68ff1cc4 100644 --- a/examples/blemesh_bridge/main/CMakeLists.txt +++ b/examples/blemesh_bridge/main/CMakeLists.txt @@ -1,4 +1,4 @@ -set(PRIV_REQUIRES_LIST device esp_matter esp_matter_console route_hook app_bridge) +set(PRIV_REQUIRES_LIST device esp_matter route_hook app_bridge) idf_component_register(SRC_DIRS "." PRIV_INCLUDE_DIRS "." diff --git a/examples/blemesh_bridge/main/app_main.cpp b/examples/blemesh_bridge/main/app_main.cpp index 29507f9ef..867d66e80 100644 --- a/examples/blemesh_bridge/main/app_main.cpp +++ b/examples/blemesh_bridge/main/app_main.cpp @@ -103,7 +103,7 @@ extern "C" void app_main() } #if CONFIG_ENABLE_CHIP_SHELL - esp_matter_console_diagnostics_register_commands(); - esp_matter_console_init(); + esp_matter::console::diagnostics_register_commands(); + esp_matter::console::init(); #endif } diff --git a/examples/light/main/app_main.cpp b/examples/light/main/app_main.cpp index 24f646861..65d4913d1 100644 --- a/examples/light/main/app_main.cpp +++ b/examples/light/main/app_main.cpp @@ -131,7 +131,7 @@ extern "C" void app_main() app_driver_light_set_defaults(light_endpoint_id); #if CONFIG_ENABLE_CHIP_SHELL - esp_matter_console_diagnostics_register_commands(); - esp_matter_console_init(); + esp_matter::console::diagnostics_register_commands(); + esp_matter::console::init(); #endif } diff --git a/examples/light_switch/main/app_driver.cpp b/examples/light_switch/main/app_driver.cpp index c06bbe325..1640c1bff 100644 --- a/examples/light_switch/main/app_driver.cpp +++ b/examples/light_switch/main/app_driver.cpp @@ -28,6 +28,7 @@ using namespace esp_matter::cluster; static const char *TAG = "app_driver"; extern uint16_t switch_endpoint_id; +#if CONFIG_ENABLE_CHIP_SHELL static esp_err_t app_driver_bound_console_handler(int argc, char **argv) { if (argc == 1 && strncmp(argv[0], "help", sizeof("help")) == 0) { @@ -87,25 +88,26 @@ static esp_err_t app_driver_client_console_handler(int argc, char **argv) static void app_driver_register_commands() { /* Add console command for bound devices */ - esp_matter_console_command_t bound_command = { + static const esp_matter::console::command_t bound_command = { .name = "bound", .description = "This can be used to simulate on-device control for bound devices." "Usage: matter esp bound . " "Bound commands: help, invoke", .handler = app_driver_bound_console_handler, }; - esp_matter_console_add_command(&bound_command); + esp_matter::console::add_commands(&bound_command, 1); /* Add console command for client to control non-bound devices */ - esp_matter_console_command_t client_command = { + static const esp_matter::console::command_t client_command = { .name = "client", .description = "This can be used to simulate on-device control for client devices." "Usage: matter esp client . " "Client commands: help, invoke", .handler = app_driver_client_console_handler, }; - esp_matter_console_add_command(&client_command); + esp_matter::console::add_commands(&client_command, 1); } +#endif // CONFIG_ENABLE_CHIP_SHELL void app_driver_client_command_callback(client::peer_device_t *peer_device, uint16_t remote_endpoint_id, client::command_handle_t *cmd_handle, void *priv_data) @@ -163,8 +165,10 @@ app_driver_handle_t app_driver_switch_init() iot_button_register_cb(handle, BUTTON_PRESS_DOWN, app_driver_button_toggle_cb); /* Other initializations */ +#if CONFIG_ENABLE_CHIP_SHELL app_driver_register_commands(); client::set_command_callback(app_driver_client_command_callback, app_driver_client_group_command_callback, NULL); +#endif // CONFIG_ENABLE_CHIP_SHELL return (app_driver_handle_t)handle; } diff --git a/examples/light_switch/main/app_main.cpp b/examples/light_switch/main/app_main.cpp index de8efb738..db595e2ee 100644 --- a/examples/light_switch/main/app_main.cpp +++ b/examples/light_switch/main/app_main.cpp @@ -118,7 +118,7 @@ extern "C" void app_main() } #if CONFIG_ENABLE_CHIP_SHELL - esp_matter_console_diagnostics_register_commands(); - esp_matter_console_init(); + esp_matter::console::diagnostics_register_commands(); + esp_matter::console::init(); #endif } diff --git a/examples/zap_light/main/app_main.cpp b/examples/zap_light/main/app_main.cpp index 6bc8dd8c9..9193b50c4 100644 --- a/examples/zap_light/main/app_main.cpp +++ b/examples/zap_light/main/app_main.cpp @@ -99,7 +99,7 @@ extern "C" void app_main() app_driver_light_set_defaults(light_endpoint_id); #if CONFIG_ENABLE_CHIP_SHELL - esp_matter_console_diagnostics_register_commands(); - esp_matter_console_init(); + esp_matter::console::diagnostics_register_commands(); + esp_matter::console::init(); #endif } diff --git a/examples/zigbee_bridge/main/app_main.cpp b/examples/zigbee_bridge/main/app_main.cpp index ebdf22e7d..270849637 100644 --- a/examples/zigbee_bridge/main/app_main.cpp +++ b/examples/zigbee_bridge/main/app_main.cpp @@ -102,8 +102,8 @@ extern "C" void app_main() } #if CONFIG_ENABLE_CHIP_SHELL - esp_matter_console_diagnostics_register_commands(); - esp_matter_console_init(); + esp_matter::console::diagnostics_register_commands(); + esp_matter::console::init(); #endif launch_app_zboss(); }