From af5ac793d142285e3c3897930a0ef09299c11e58 Mon Sep 17 00:00:00 2001 From: WanqQixiang Date: Mon, 29 Aug 2022 11:09:03 +0800 Subject: [PATCH] esp_matter_bridge: Add aggregator device type and add parent_endpoint_id for bridged_endpoint example: Add aggregator endpoint for bridge examples --- .../esp_matter/esp_matter_attribute.cpp | 24 ++ components/esp_matter/esp_matter_attribute.h | 8 + components/esp_matter/esp_matter_cluster.cpp | 33 +++ components/esp_matter/esp_matter_cluster.h | 4 + components/esp_matter/esp_matter_command.cpp | 209 ++++++++++++++++++ components/esp_matter/esp_matter_command.h | 17 ++ components/esp_matter/esp_matter_core.cpp | 7 +- components/esp_matter/esp_matter_core.h | 3 +- components/esp_matter/esp_matter_endpoint.cpp | 22 +- components/esp_matter/esp_matter_endpoint.h | 3 +- components/esp_matter/esp_matter_event.cpp | 17 ++ components/esp_matter_bridge/Kconfig | 10 + .../esp_matter_bridge/esp_matter_bridge.cpp | 28 ++- .../esp_matter_bridge/esp_matter_bridge.h | 6 +- examples/blemesh_bridge/main/app_main.cpp | 9 + .../blemesh_bridge/main/blemesh_bridge.cpp | 8 +- .../common/app_bridge/app_bridged_device.cpp | 14 +- .../common/app_bridge/app_bridged_device.h | 2 +- examples/zigbee_bridge/main/app_main.cpp | 9 + examples/zigbee_bridge/main/zigbee_bridge.cpp | 11 +- 20 files changed, 416 insertions(+), 28 deletions(-) create mode 100644 components/esp_matter_bridge/Kconfig diff --git a/components/esp_matter/esp_matter_attribute.cpp b/components/esp_matter/esp_matter_attribute.cpp index dd03b3232..b9ffb49d4 100644 --- a/components/esp_matter/esp_matter_attribute.cpp +++ b/components/esp_matter/esp_matter_attribute.cpp @@ -70,6 +70,30 @@ attribute_t *create_parts_list(cluster_t *cluster, uint8_t *value, uint16_t leng } /* attribute */ } /* descriptor */ +namespace actions { +namespace attribute { + +attribute_t *create_action_list(cluster_t *cluster, uint8_t *value, uint16_t length, uint16_t count) +{ + return esp_matter::attribute::create(cluster, Actions::Attributes::ActionList::Id, ATTRIBUTE_FLAG_NONE, + esp_matter_array(value, length, count)); +} + +attribute_t *create_endpoint_lists(cluster_t *cluster, uint8_t *value, uint16_t length, uint16_t count) +{ + return esp_matter::attribute::create(cluster, Actions::Attributes::EndpointLists::Id, ATTRIBUTE_FLAG_NONE, + esp_matter_array(value, length, count)); +} + +attribute_t *create_setup_url(cluster_t *cluster, char *value, uint16_t length) +{ + return esp_matter::attribute::create(cluster, Actions::Attributes::SetupURL::Id, ATTRIBUTE_FLAG_NONE, + esp_matter_char_str(value, length)); +} + +} /* attribute */ +} /* actions */ + namespace access_control { namespace attribute { diff --git a/components/esp_matter/esp_matter_attribute.h b/components/esp_matter/esp_matter_attribute.h index 10497b227..c250ccf64 100644 --- a/components/esp_matter/esp_matter_attribute.h +++ b/components/esp_matter/esp_matter_attribute.h @@ -42,6 +42,14 @@ attribute_t *create_parts_list(cluster_t *cluster, uint8_t *value, uint16_t leng } /* attribute */ } /* descriptor */ +namespace actions { +namespace attribute { +attribute_t *create_action_list(cluster_t *cluster, uint8_t *value, uint16_t length, uint16_t count); +attribute_t *create_endpoint_lists(cluster_t *cluster, uint8_t *value, uint16_t length, uint16_t count); +attribute_t *create_setup_url(cluster_t *cluster, char *value, uint16_t length); +} /* attribute */ +} /* actions */ + namespace access_control { namespace attribute { attribute_t *create_acl(cluster_t *cluster, uint8_t *value, uint16_t length, uint16_t count); diff --git a/components/esp_matter/esp_matter_cluster.cpp b/components/esp_matter/esp_matter_cluster.cpp index fb23f684e..55aa9bf5d 100644 --- a/components/esp_matter/esp_matter_cluster.cpp +++ b/components/esp_matter/esp_matter_cluster.cpp @@ -102,6 +102,39 @@ cluster_t *create(endpoint_t *endpoint, uint8_t flags) } } /* descriptor */ +namespace actions { +const function_generic_t *function_list = NULL; +const int function_flags = CLUSTER_FLAG_NONE; + +cluster_t *create(endpoint_t *endpoint, uint8_t flags) +{ + cluster_t *cluster = cluster::create(endpoint, Descriptor::Id, flags); + if (!cluster) { + ESP_LOGE(TAG, "Could not create cluster"); + return NULL; + } + + if (flags & CLUSTER_FLAG_SERVER) { + set_plugin_server_init_callback(cluster, NULL); + add_function_list(cluster, function_list, function_flags); + } + if (flags & CLUSTER_FLAG_CLIENT) { + set_plugin_client_init_callback(cluster, NULL); + create_default_binding_cluster(endpoint); + } + + if (flags & CLUSTER_FLAG_SERVER) { + /* Attributes managed internally */ + global::attribute::create_cluster_revision(cluster, 1); + global::attribute::create_feature_map(cluster, 0); + attribute::create_action_list(cluster, NULL, 0, 0); + attribute::create_endpoint_lists(cluster, NULL, 0, 0); + } + + return cluster; +} +} /* actions */ + namespace access_control { const function_generic_t *function_list = NULL; const int function_flags = CLUSTER_FLAG_NONE; diff --git a/components/esp_matter/esp_matter_cluster.h b/components/esp_matter/esp_matter_cluster.h index a24fadd57..94b4c297d 100644 --- a/components/esp_matter/esp_matter_cluster.h +++ b/components/esp_matter/esp_matter_cluster.h @@ -44,6 +44,10 @@ namespace descriptor { cluster_t *create(endpoint_t *endpoint, uint8_t flags); } /* descriptor */ +namespace actions { +cluster_t *create(endpoint_t *endpoint, uint8_t flags); +} /* actions */ + namespace access_control { cluster_t *create(endpoint_t *endpoint, uint8_t flags); } /* access_control */ diff --git a/components/esp_matter/esp_matter_command.cpp b/components/esp_matter/esp_matter_command.cpp index 3878eca83..667fd2d7d 100644 --- a/components/esp_matter/esp_matter_command.cpp +++ b/components/esp_matter/esp_matter_command.cpp @@ -1102,9 +1102,218 @@ static esp_err_t esp_matter_command_callback_go_to_tilt_percentage(const Concret return ESP_OK; } +static esp_err_t esp_matter_command_callback_instance_action(const ConcreteCommandPath &command_path, + TLVReader &tlv_data, void *opaque_ptr) +{ + // No actions are implemented, just return status NotFound. + // TODO: Add action callbacks for actions cluster. + CommandHandler *command_handler = (CommandHandler *)opaque_ptr; + command_handler->AddStatus(command_path, chip::Protocols::InteractionModel::Status::NotFound); + + return ESP_OK; +} + +static esp_err_t esp_matter_command_callback_instance_action_with_transition(const ConcreteCommandPath &command_path, + TLVReader &tlv_data, void *opaque_ptr) +{ + // No actions are implemented, just return status NotFound. + // TODO: Add action callbacks for actions cluster. + CommandHandler *command_handler = (CommandHandler *)opaque_ptr; + command_handler->AddStatus(command_path, chip::Protocols::InteractionModel::Status::NotFound); + + return ESP_OK; +} + +static esp_err_t esp_matter_command_callback_start_action(const ConcreteCommandPath &command_path, + TLVReader &tlv_data, void *opaque_ptr) +{ + // No actions are implemented, just return status NotFound. + // TODO: Add action callbacks for actions cluster. + CommandHandler *command_handler = (CommandHandler *)opaque_ptr; + command_handler->AddStatus(command_path, chip::Protocols::InteractionModel::Status::NotFound); + + return ESP_OK; +} + +static esp_err_t esp_matter_command_callback_start_action_with_duration(const ConcreteCommandPath &command_path, + TLVReader &tlv_data, void *opaque_ptr) +{ + // No actions are implemented, just return status NotFound. + // TODO: Add action callbacks for actions cluster. + CommandHandler *command_handler = (CommandHandler *)opaque_ptr; + command_handler->AddStatus(command_path, chip::Protocols::InteractionModel::Status::NotFound); + + return ESP_OK; +} + +static esp_err_t esp_matter_command_callback_stop_action(const ConcreteCommandPath &command_path, + TLVReader &tlv_data, void *opaque_ptr) +{ + // No actions are implemented, just return status NotFound. + // TODO: Add action callbacks for actions cluster. + CommandHandler *command_handler = (CommandHandler *)opaque_ptr; + command_handler->AddStatus(command_path, chip::Protocols::InteractionModel::Status::NotFound); + + return ESP_OK; +} + +static esp_err_t esp_matter_command_callback_pause_action(const ConcreteCommandPath &command_path, + TLVReader &tlv_data, void *opaque_ptr) +{ + // No actions are implemented, just return status NotFound. + // TODO: Add action callbacks for actions cluster. + CommandHandler *command_handler = (CommandHandler *)opaque_ptr; + command_handler->AddStatus(command_path, chip::Protocols::InteractionModel::Status::NotFound); + + return ESP_OK; +} + +static esp_err_t esp_matter_command_callback_pause_action_with_duration(const ConcreteCommandPath &command_path, + TLVReader &tlv_data, void *opaque_ptr) +{ + // No actions are implemented, just return status NotFound. + // TODO: Add action callbacks for actions cluster. + CommandHandler *command_handler = (CommandHandler *)opaque_ptr; + command_handler->AddStatus(command_path, chip::Protocols::InteractionModel::Status::NotFound); + + return ESP_OK; +} + +static esp_err_t esp_matter_command_callback_resume_action(const ConcreteCommandPath &command_path, + TLVReader &tlv_data, void *opaque_ptr) +{ + // No actions are implemented, just return status NotFound. + // TODO: Add action callbacks for actions cluster. + CommandHandler *command_handler = (CommandHandler *)opaque_ptr; + command_handler->AddStatus(command_path, chip::Protocols::InteractionModel::Status::NotFound); + + return ESP_OK; +} + +static esp_err_t esp_matter_command_callback_enable_action(const ConcreteCommandPath &command_path, + TLVReader &tlv_data, void *opaque_ptr) +{ + // No actions are implemented, just return status NotFound. + // TODO: Add action callbacks for actions cluster. + CommandHandler *command_handler = (CommandHandler *)opaque_ptr; + command_handler->AddStatus(command_path, chip::Protocols::InteractionModel::Status::NotFound); + + return ESP_OK; +} + +static esp_err_t esp_matter_command_callback_enable_action_with_duration(const ConcreteCommandPath &command_path, + TLVReader &tlv_data, void *opaque_ptr) +{ + // No actions are implemented, just return status NotFound. + // TODO: Add action callbacks for actions cluster. + CommandHandler *command_handler = (CommandHandler *)opaque_ptr; + command_handler->AddStatus(command_path, chip::Protocols::InteractionModel::Status::NotFound); + + return ESP_OK; +} + +static esp_err_t esp_matter_command_callback_disable_action(const ConcreteCommandPath &command_path, + TLVReader &tlv_data, void *opaque_ptr) +{ + // No actions are implemented, just return status NotFound. + // TODO: Add action callbacks for actions cluster. + CommandHandler *command_handler = (CommandHandler *)opaque_ptr; + command_handler->AddStatus(command_path, chip::Protocols::InteractionModel::Status::NotFound); + + return ESP_OK; +} + +static esp_err_t esp_matter_command_callback_disable_action_with_duration(const ConcreteCommandPath &command_path, + TLVReader &tlv_data, void *opaque_ptr) +{ + // No actions are implemented, just return status NotFound. + // TODO: Add action callbacks for actions cluster. + CommandHandler *command_handler = (CommandHandler *)opaque_ptr; + command_handler->AddStatus(command_path, chip::Protocols::InteractionModel::Status::NotFound); + + return ESP_OK; +} + namespace esp_matter { namespace cluster { +namespace actions { +namespace command { +command_t *create_instant_action(cluster_t *cluster) +{ + return esp_matter::command::create(cluster, Actions::Commands::InstantAction::Id, COMMAND_FLAG_ACCEPTED, + esp_matter_command_callback_instance_action); +} + +command_t *create_instant_action_with_transition(cluster_t *cluster) +{ + return esp_matter::command::create(cluster, Actions::Commands::InstantActionWithTransition::Id, COMMAND_FLAG_ACCEPTED, + esp_matter_command_callback_instance_action_with_transition); +} + +command_t *create_start_action(cluster_t *cluster) +{ + return esp_matter::command::create(cluster, Actions::Commands::StartAction::Id, COMMAND_FLAG_ACCEPTED, + esp_matter_command_callback_start_action); +} + +command_t *create_start_action_with_duration(cluster_t *cluster) +{ + return esp_matter::command::create(cluster, Actions::Commands::StartActionWithDuration::Id, COMMAND_FLAG_ACCEPTED, + esp_matter_command_callback_start_action_with_duration); +} + +command_t *create_stop_action(cluster_t *cluster) +{ + return esp_matter::command::create(cluster, Actions::Commands::StopAction::Id, COMMAND_FLAG_ACCEPTED, + esp_matter_command_callback_stop_action); +} + +command_t *create_pause_action(cluster_t *cluster) +{ + return esp_matter::command::create(cluster, Actions::Commands::PauseAction::Id, COMMAND_FLAG_ACCEPTED, + esp_matter_command_callback_pause_action); +} + +command_t *create_pause_action_with_duration(cluster_t *cluster) +{ + return esp_matter::command::create(cluster, Actions::Commands::PauseActionWithDuration::Id, COMMAND_FLAG_ACCEPTED, + esp_matter_command_callback_pause_action_with_duration); +} + +command_t *create_resume_action(cluster_t *cluster) +{ + return esp_matter::command::create(cluster, Actions::Commands::ResumeAction::Id, COMMAND_FLAG_ACCEPTED, + esp_matter_command_callback_resume_action); +} + +command_t *create_enable_action(cluster_t *cluster) +{ + return esp_matter::command::create(cluster, Actions::Commands::EnableAction::Id, COMMAND_FLAG_ACCEPTED, + esp_matter_command_callback_enable_action); +} + +command_t *create_enable_action_with_duration(cluster_t *cluster) +{ + return esp_matter::command::create(cluster, Actions::Commands::EnableActionWithDuration::Id, COMMAND_FLAG_ACCEPTED, + esp_matter_command_callback_enable_action_with_duration); +} + +command_t *create_disable_action(cluster_t *cluster) +{ + return esp_matter::command::create(cluster, Actions::Commands::DisableAction::Id, COMMAND_FLAG_ACCEPTED, + esp_matter_command_callback_disable_action); +} + +command_t *create_disable_action_with_duration(cluster_t *cluster) +{ + return esp_matter::command::create(cluster, Actions::Commands::DisableActionWithDuration::Id, COMMAND_FLAG_ACCEPTED, + esp_matter_command_callback_disable_action_with_duration); +} + +} /* command */ +} /* actions */ + namespace diagnostics_network_thread { namespace command { diff --git a/components/esp_matter/esp_matter_command.h b/components/esp_matter/esp_matter_command.h index 69cd07697..42671bd10 100644 --- a/components/esp_matter/esp_matter_command.h +++ b/components/esp_matter/esp_matter_command.h @@ -25,6 +25,23 @@ namespace cluster { * If a custom command needs to be created, the low level esp_matter::command::create() API can be used. */ +namespace actions { +namespace command { +command_t *create_instant_action(cluster_t *cluster); +command_t *create_instant_action_with_transition(cluster_t *cluster); +command_t *create_start_action(cluster_t *cluster); +command_t *create_start_action_with_duration(cluster_t *cluster); +command_t *create_stop_action(cluster_t *cluster); +command_t *create_pause_action(cluster_t *cluster); +command_t *create_pause_action_with_duration(cluster_t *cluster); +command_t *create_resume_action(cluster_t *cluster); +command_t *create_enable_action(cluster_t *cluster); +command_t *create_enable_action_with_duration(cluster_t *cluster); +command_t *create_disable_action(cluster_t *cluster); +command_t *create_disable_action_with_duration(cluster_t *cluster); +} /* command */ +} /* actions */ + namespace diagnostics_network_thread { namespace command { command_t *create_reset_counts(cluster_t *cluster); diff --git a/components/esp_matter/esp_matter_core.cpp b/components/esp_matter/esp_matter_core.cpp index 3faee7eb4..0f3098b32 100644 --- a/components/esp_matter/esp_matter_core.cpp +++ b/components/esp_matter/esp_matter_core.cpp @@ -376,7 +376,7 @@ static esp_err_t disable(endpoint_t *endpoint) return ESP_OK; } -esp_err_t enable(endpoint_t *endpoint) +esp_err_t enable(endpoint_t *endpoint, uint16_t parent_endpoint_id) { if (!endpoint) { ESP_LOGE(TAG, "Endpoint cannot be NULL"); @@ -567,7 +567,7 @@ esp_err_t enable(endpoint_t *endpoint) /* Add Endpoint */ endpoint_index = endpoint::get_next_index(); status = emberAfSetDynamicEndpoint(endpoint_index, current_endpoint->endpoint_id, endpoint_type, data_versions, - device_types); + device_types, parent_endpoint_id); if (status != EMBER_ZCL_STATUS_SUCCESS) { ESP_LOGE(TAG, "Error adding dynamic endpoint %d: 0x%x", current_endpoint->endpoint_id, status); err = ESP_FAIL; @@ -633,7 +633,8 @@ static esp_err_t enable_all() endpoint_t *endpoint = get_first(node); while (endpoint) { - enable(endpoint); + /* The normal endpoints do not have parent endpoint */ + enable(endpoint, chip::kInvalidEndpointId); endpoint = get_next(endpoint); } return ESP_OK; diff --git a/components/esp_matter/esp_matter_core.h b/components/esp_matter/esp_matter_core.h index dd0e9a905..0e4651ef5 100644 --- a/components/esp_matter/esp_matter_core.h +++ b/components/esp_matter/esp_matter_core.h @@ -239,11 +239,12 @@ void *get_priv_data(uint16_t endpoint_id); * called after all the clusters, attributes and commands have been added to the created endpoint. * * @param[in] endpoint Endpoint handle. + * @param[in] parent_endpoint_id Parent Endpoint Id for the endpoint to be enabled, applicable only for bridges. * * @return ESP_OK on success. * @return error in case of failure. */ -esp_err_t enable(endpoint_t *endpoint); +esp_err_t enable(endpoint_t *endpoint, uint16_t parent_endpoint_id); } /* endpoint */ diff --git a/components/esp_matter/esp_matter_endpoint.cpp b/components/esp_matter/esp_matter_endpoint.cpp index 19af9bdf8..863e12d25 100644 --- a/components/esp_matter/esp_matter_endpoint.cpp +++ b/components/esp_matter/esp_matter_endpoint.cpp @@ -18,7 +18,7 @@ /* Replace these with IDs from submodule whenever they are implemented */ #define ESP_MATTER_ROOT_NODE_DEVICE_TYPE_ID 0x0016 -#define ESP_MATTER_BRIDGE_DEVICE_TYPE_ID 0x000E +#define ESP_MATTER_AGGREGATOR_DEVICE_TYPE_ID 0x000E #define ESP_MATTER_BRIDGED_NODE_DEVICE_TYPE_ID 0x0013 #define ESP_MATTER_ON_OFF_LIGHT_DEVICE_TYPE_ID 0x0100 @@ -368,12 +368,26 @@ endpoint_t *create(node_t *node, config_t *config, uint8_t flags, void *priv_dat } } /* thermostat */ -namespace bridge { +namespace aggregator { uint32_t get_device_type_id() { - return ESP_MATTER_BRIDGE_DEVICE_TYPE_ID; + return ESP_MATTER_AGGREGATOR_DEVICE_TYPE_ID; } -} /* bridge */ + +endpoint_t *create(node_t *node, uint8_t flags, void *priv_data) +{ + endpoint_t *endpoint = endpoint::create(node, flags, priv_data); + if (!endpoint) { + ESP_LOGE(TAG, "Could not create endpoint"); + return NULL; + } + add_device_type_id(endpoint, get_device_type_id()); + + descriptor::create(endpoint,CLUSTER_FLAG_SERVER); + + return endpoint; +} +} /* aggregator */ namespace bridged_node { uint32_t get_device_type_id() diff --git a/components/esp_matter/esp_matter_endpoint.h b/components/esp_matter/esp_matter_endpoint.h index e6aff216c..38e91b50b 100644 --- a/components/esp_matter/esp_matter_endpoint.h +++ b/components/esp_matter/esp_matter_endpoint.h @@ -176,8 +176,9 @@ uint32_t get_device_type_id(); endpoint_t *create(node_t *node, config_t *config, uint8_t flags, void *priv_data); } /* thermostat */ -namespace bridge { +namespace aggregator { uint32_t get_device_type_id(); +endpoint_t *create(node_t *node, uint8_t flags, void *priv_data); } /* bridge */ namespace bridged_node { diff --git a/components/esp_matter/esp_matter_event.cpp b/components/esp_matter/esp_matter_event.cpp index 9e37d39c3..fb467468d 100644 --- a/components/esp_matter/esp_matter_event.cpp +++ b/components/esp_matter/esp_matter_event.cpp @@ -171,6 +171,23 @@ esp_err_t send_turbine_operation() } /* event */ } /* pump_configuration_and_control */ +namespace actions { +namespace event { +esp_err_t send_state_changed(EndpointId endpoint, uint16_t action_id, uint32_t invoke_id, uint8_t action_state) +{ + /* Not implemented */ + return ESP_OK; +} + +esp_err_t send_action_failed(EndpointId endpoint, uint16_t action_id, uint32_t invoke_id, uint8_t action_state, + uint8_t error) +{ + /* Not implemented */ + return ESP_OK; +} +} /* event */ +} /* actions */ + namespace switch_cluster { namespace event { diff --git a/components/esp_matter_bridge/Kconfig b/components/esp_matter_bridge/Kconfig new file mode 100644 index 000000000..6db661045 --- /dev/null +++ b/components/esp_matter_bridge/Kconfig @@ -0,0 +1,10 @@ +menu "ESP Matter Bridge" + + config ESP_MATTER_AGGREGATOR_ENDPOINT_COUNT + int "The number of aggregator endpoints" + range 1 5 + default 1 + help + The number of aggregator endpoint for the bridge device + +endmenu diff --git a/components/esp_matter_bridge/esp_matter_bridge.cpp b/components/esp_matter_bridge/esp_matter_bridge.cpp index 9b6f4f6a6..f46b3f279 100644 --- a/components/esp_matter_bridge/esp_matter_bridge.cpp +++ b/components/esp_matter_bridge/esp_matter_bridge.cpp @@ -23,10 +23,35 @@ static const char *TAG = "esp_matter_bridge"; using namespace esp_matter; using namespace esp_matter::endpoint; -esp_matter_bridge_device_t *esp_matter_bridge_create_device(node_t *node) +esp_matter_bridge_device_t *esp_matter_bridge_create_device(node_t *node, uint16_t parent_endpoint_id) { + endpoint_t *parent_endpoint = endpoint::get(node, parent_endpoint_id); + if (!node || !parent_endpoint) { + ESP_LOGE(TAG, "Cannot create a bridged device for a NULL node or an invalid parent endpoint"); + return NULL; + } + uint8_t device_type_count = 0; + bool parent_endpoint_valid = false; + uint32_t *device_type_ids_ptr = get_device_type_ids(parent_endpoint, &device_type_count); + if (device_type_ids_ptr != NULL) { + for (uint8_t i = 0; i <= device_type_count; ++i) { + if (device_type_ids_ptr[i] == esp_matter::endpoint::aggregator::get_device_type_id()) { + parent_endpoint_valid = true; + break; + } + } + if (!parent_endpoint_valid) { + ESP_LOGE(TAG, "The device types of the parent endpoint must include aggregator"); + return NULL; + } + } else { + ESP_LOGE(TAG, "Failed to get the device types of the parent endpoint"); + return NULL; + } + esp_matter_bridge_device_t *dev = (esp_matter_bridge_device_t *)calloc(1, sizeof(esp_matter_bridge_device_t)); dev->node = node; + dev->parent_endpoint_id = parent_endpoint_id; bridged_node::config_t bridged_node_config; dev->endpoint = bridged_node::create(node, &bridged_node_config, ENDPOINT_FLAG_DESTROYABLE | ENDPOINT_FLAG_BRIDGE, NULL); @@ -35,7 +60,6 @@ esp_matter_bridge_device_t *esp_matter_bridge_create_device(node_t *node) free(dev); return NULL; } - dev->endpoint_id = endpoint::get_id(dev->endpoint); return dev; } diff --git a/components/esp_matter_bridge/esp_matter_bridge.h b/components/esp_matter_bridge/esp_matter_bridge.h index f1821b78c..fe8a03ba1 100644 --- a/components/esp_matter_bridge/esp_matter_bridge.h +++ b/components/esp_matter_bridge/esp_matter_bridge.h @@ -18,15 +18,15 @@ #include #include -#define MAX_BRIDGED_DEVICE_COUNT CHIP_DEVICE_CONFIG_DYNAMIC_ENDPOINT_COUNT - 1 +#define MAX_BRIDGED_DEVICE_COUNT CHIP_DEVICE_CONFIG_DYNAMIC_ENDPOINT_COUNT - 1 - CONFIG_ESP_MATTER_AGGREGATOR_ENDPOINT_COUNT // There is an endpoint reserved as root endpoint typedef struct esp_matter_bridge_device { esp_matter::node_t *node; esp_matter::endpoint_t *endpoint; - uint16_t endpoint_id; + uint16_t parent_endpoint_id; } esp_matter_bridge_device_t; -esp_matter_bridge_device_t *esp_matter_bridge_create_device(esp_matter::node_t *node); +esp_matter_bridge_device_t *esp_matter_bridge_create_device(esp_matter::node_t *node, uint16_t parent_endpoint_id); esp_err_t esp_matter_bridge_remove_device(esp_matter_bridge_device_t *bridged_device); diff --git a/examples/blemesh_bridge/main/app_main.cpp b/examples/blemesh_bridge/main/app_main.cpp index 8fbe97ef6..0693b492e 100644 --- a/examples/blemesh_bridge/main/app_main.cpp +++ b/examples/blemesh_bridge/main/app_main.cpp @@ -26,6 +26,8 @@ static const char *TAG = "app_main"; using namespace esp_matter; using namespace esp_matter::attribute; +uint16_t aggregator_endpoint_id = chip::kInvalidEndpointId; + static void app_event_cb(const ChipDeviceEvent *event, intptr_t arg) { switch (event->Type) { @@ -92,6 +94,13 @@ extern "C" void app_main() ESP_LOGE(TAG, "Matter node creation failed"); } + endpoint_t *aggregator = endpoint::aggregator::create(node, ENDPOINT_FLAG_NONE, NULL); + if (!aggregator) { + ESP_LOGE(TAG, "Matter aggregator endpoint creation failed"); + } + + aggregator_endpoint_id = endpoint::get_id(aggregator); + /* Matter start */ err = esp_matter::start(app_event_cb); if (err != ESP_OK) { diff --git a/examples/blemesh_bridge/main/blemesh_bridge.cpp b/examples/blemesh_bridge/main/blemesh_bridge.cpp index 4405667d4..643f645bd 100644 --- a/examples/blemesh_bridge/main/blemesh_bridge.cpp +++ b/examples/blemesh_bridge/main/blemesh_bridge.cpp @@ -23,6 +23,8 @@ static const char *TAG = "blemesh_bridge"; using namespace chip::app::Clusters; using namespace esp_matter; using namespace esp_matter::cluster; +extern uint16_t aggregator_endpoint_id; + /** Mesh Spec 4.2.1: "The Composition Data state contains information about a node, * the elements it includes, and the supported models. Composition Data Page 0 is mandatory." @@ -50,7 +52,7 @@ static esp_err_t blemesh_bridge_init_bridged_onoff_light(esp_matter_bridge_devic on_off::config_t config; on_off::create(dev->endpoint, &config, CLUSTER_MASK_SERVER, ESP_MATTER_NONE_FEATURE_ID); endpoint::add_device_type_id(dev->endpoint, endpoint::on_off_light::get_device_type_id()); - if (endpoint::enable(dev->endpoint) != ESP_OK) { + if (endpoint::enable(dev->endpoint, dev->parent_endpoint_id) != ESP_OK) { ESP_LOGE(TAG, "ESP Matter enable dynamic endpoint failed"); endpoint::destroy(dev->node, dev->endpoint); return ESP_FAIL; @@ -69,7 +71,9 @@ esp_err_t blemesh_bridge_match_bridged_onoff_light(uint8_t *composition_data, ui ESP_LOGI(TAG, "Bridged node for 0x%04x bridged device on endpoint %d has been created", blemesh_addr, app_bridge_get_matter_endpointid_by_blemesh_addr(blemesh_addr)); } else { - app_bridged_device_t *bridged_device = app_bridge_create_bridged_device(node, ESP_MATTER_BRIDGED_DEVICE_TYPE_BLEMESH, app_bridge_blemesh_address(blemesh_addr)); + app_bridged_device_t *bridged_device = + app_bridge_create_bridged_device(node, aggregator_endpoint_id, ESP_MATTER_BRIDGED_DEVICE_TYPE_BLEMESH, + app_bridge_blemesh_address(blemesh_addr)); ESP_RETURN_ON_FALSE(bridged_device, ESP_FAIL, TAG, "Failed to create bridged device (on_off light)"); ESP_RETURN_ON_ERROR(blemesh_bridge_init_bridged_onoff_light(bridged_device->dev), TAG, "Failed to initialize the bridged node"); ESP_LOGI(TAG, "Create/Update bridged node for 0x%04x bridged device on endpoint %d", blemesh_addr, diff --git a/examples/common/app_bridge/app_bridged_device.cpp b/examples/common/app_bridge/app_bridged_device.cpp index d075d402b..74a8ea3ab 100644 --- a/examples/common/app_bridge/app_bridged_device.cpp +++ b/examples/common/app_bridge/app_bridged_device.cpp @@ -45,7 +45,7 @@ app_bridged_device_address_t app_bridge_blemesh_address(uint16_t blemesh_addr) } /** Bridged Device APIs */ -app_bridged_device_t *app_bridge_create_bridged_device(node_t *node, +app_bridged_device_t *app_bridge_create_bridged_device(node_t *node, uint16_t parent_endpoint_id, app_bridged_device_type_t bridged_device_type, app_bridged_device_address_t bridged_device_address) { if (g_current_bridged_device_count >= MAX_BRIDGED_DEVICE_COUNT) { @@ -53,7 +53,7 @@ app_bridged_device_t *app_bridge_create_bridged_device(node_t *node, return NULL; } app_bridged_device_t *new_dev = (app_bridged_device_t *)calloc(1, sizeof(app_bridged_device_t)); - new_dev->dev = esp_matter_bridge_create_device(node); + new_dev->dev = esp_matter_bridge_create_device(node, parent_endpoint_id); if (!(new_dev->dev)) { ESP_LOGE(TAG, "Failed to create the basic bridged device"); free(new_dev); @@ -71,7 +71,7 @@ app_bridged_device_t *app_bridge_get_device_by_matter_endpointid(uint16_t matter { app_bridged_device_t *current_dev = g_bridged_device_list; while (current_dev) { - if (current_dev->dev && (current_dev->dev->endpoint_id == matter_endpointid)) { + if (current_dev->dev && (esp_matter::endpoint::get_id(current_dev->dev->endpoint) == matter_endpointid)) { return current_dev; } current_dev = current_dev->next; @@ -131,7 +131,7 @@ uint16_t app_bridge_get_matter_endpointid_by_zigbee_shortaddr(uint16_t zigbee_sh while (current_dev) { if (current_dev->dev_type == ESP_MATTER_BRIDGED_DEVICE_TYPE_ZIGBEE && current_dev->dev && current_dev->dev_addr.zigbee_shortaddr == zigbee_shortaddr) { - return current_dev->dev->endpoint_id; + return esp_matter::endpoint::get_id(current_dev->dev->endpoint); } current_dev = current_dev->next; } @@ -143,7 +143,7 @@ uint16_t app_bridge_get_zigbee_shortaddr_by_matter_endpointid(uint16_t matter_en app_bridged_device_t *current_dev = g_bridged_device_list; while (current_dev) { if ((current_dev->dev_type == ESP_MATTER_BRIDGED_DEVICE_TYPE_ZIGBEE) && current_dev->dev - && (current_dev->dev->endpoint_id == matter_endpointid)) { + && (esp_matter::endpoint::get_id(current_dev->dev->endpoint) == matter_endpointid)) { return current_dev->dev_addr.zigbee_shortaddr; } current_dev = current_dev->next; @@ -171,7 +171,7 @@ uint16_t app_bridge_get_matter_endpointid_by_blemesh_addr(uint16_t blemesh_addr) while (current_dev) { if ((current_dev->dev_type == ESP_MATTER_BRIDGED_DEVICE_TYPE_BLEMESH) && current_dev->dev && (current_dev->dev_addr.blemesh_addr == blemesh_addr)) { - return current_dev->dev->endpoint_id; + return esp_matter::endpoint::get_id(current_dev->dev->endpoint); } current_dev = current_dev->next; } @@ -183,7 +183,7 @@ uint16_t app_bridge_get_blemesh_addr_by_matter_endpointid(uint16_t matter_endpoi app_bridged_device_t *current_dev = g_bridged_device_list; while (current_dev) { if ((current_dev->dev_type == ESP_MATTER_BRIDGED_DEVICE_TYPE_BLEMESH) && current_dev->dev - && (current_dev->dev->endpoint_id == matter_endpointid)) { + && (esp_matter::endpoint::get_id(current_dev->dev->endpoint) == matter_endpointid)) { return current_dev->dev_addr.blemesh_addr; } current_dev = current_dev->next; diff --git a/examples/common/app_bridge/app_bridged_device.h b/examples/common/app_bridge/app_bridged_device.h index 64025ba1e..9e80bc8d9 100644 --- a/examples/common/app_bridge/app_bridged_device.h +++ b/examples/common/app_bridge/app_bridged_device.h @@ -59,7 +59,7 @@ app_bridged_device_address_t app_bridge_zigbee_address(uint8_t zigbee_endpointid app_bridged_device_address_t app_bridge_blemesh_address(uint16_t blemesh_addr); /** Bridged Device APIs */ -app_bridged_device_t *app_bridge_create_bridged_device(node_t *node, +app_bridged_device_t *app_bridge_create_bridged_device(node_t *node, uint16_t parent_endpoint_id, app_bridged_device_type_t bridged_device_type, app_bridged_device_address_t bridged_device_address); app_bridged_device_t *app_bridge_get_device_by_matter_endpointid(uint16_t matter_endpointid); diff --git a/examples/zigbee_bridge/main/app_main.cpp b/examples/zigbee_bridge/main/app_main.cpp index bb40871dc..f929a49dd 100644 --- a/examples/zigbee_bridge/main/app_main.cpp +++ b/examples/zigbee_bridge/main/app_main.cpp @@ -25,6 +25,8 @@ static const char *TAG = "app_main"; using namespace esp_matter; using namespace esp_matter::attribute; +uint16_t aggregator_endpoint_id = chip::kInvalidEndpointId; + static void app_event_cb(const ChipDeviceEvent *event, intptr_t arg) { switch (event->Type) { @@ -91,6 +93,13 @@ extern "C" void app_main() ESP_LOGE(TAG, "Matter node creation failed"); } + endpoint_t *aggregator = endpoint::aggregator::create(node, ENDPOINT_FLAG_NONE, NULL); + if (!aggregator) { + ESP_LOGE(TAG, "Matter aggregator endpoint creation failed"); + } else { + aggregator_endpoint_id = endpoint::get_id(aggregator); + } + /* Matter start */ err = esp_matter::start(app_event_cb); if (err != ESP_OK) { diff --git a/examples/zigbee_bridge/main/zigbee_bridge.cpp b/examples/zigbee_bridge/main/zigbee_bridge.cpp index a5623a45d..8f4532fd2 100644 --- a/examples/zigbee_bridge/main/zigbee_bridge.cpp +++ b/examples/zigbee_bridge/main/zigbee_bridge.cpp @@ -20,6 +20,8 @@ using namespace chip::app::Clusters; using namespace esp_matter; using namespace esp_matter::cluster; +extern uint16_t aggregator_endpoint_id; + static esp_err_t zigbee_bridge_init_bridged_onoff_light(esp_matter_bridge_device_t *dev) { if (!dev) { @@ -30,7 +32,7 @@ static esp_err_t zigbee_bridge_init_bridged_onoff_light(esp_matter_bridge_device on_off::config_t config; on_off::create(dev->endpoint, &config, CLUSTER_MASK_SERVER, ESP_MATTER_NONE_FEATURE_ID); endpoint::add_device_type_id(dev->endpoint, endpoint::on_off_light::get_device_type_id()); - if (endpoint::enable(dev->endpoint) != ESP_OK) { + if (endpoint::enable(dev->endpoint, dev->parent_endpoint_id) != ESP_OK) { ESP_LOGE(TAG, "ESP Matter enable dynamic endpoint failed"); endpoint::destroy(dev->node, dev->endpoint); return ESP_FAIL; @@ -50,8 +52,9 @@ void zigbee_bridge_find_bridged_on_off_light_cb(zb_uint8_t zdo_status, zb_uint16 ESP_LOGI(TAG, "Bridged node for 0x%04x zigbee device on endpoint %d has been created", addr, app_bridge_get_matter_endpointid_by_zigbee_shortaddr(addr)); } else { - app_bridged_device_t *bridged_device = app_bridge_create_bridged_device( - node, ESP_MATTER_BRIDGED_DEVICE_TYPE_ZIGBEE, app_bridge_zigbee_address(endpoint, addr)); + app_bridged_device_t *bridged_device = + app_bridge_create_bridged_device(node, aggregator_endpoint_id, ESP_MATTER_BRIDGED_DEVICE_TYPE_ZIGBEE, + app_bridge_zigbee_address(endpoint, addr)); if (!bridged_device) { ESP_LOGE(TAG, "Failed to create zigbee bridged device (on_off light)"); return; @@ -78,7 +81,7 @@ esp_err_t zigbee_bridge_attribute_update(uint16_t endpoint_id, uint32_t cluster_ esp_zb_zcl_on_off_cmd_t cmd_req; cmd_req.zcl_basic_cmd.dst_addr_u.addr_short = zigbee_device->dev_addr.zigbee_shortaddr; cmd_req.zcl_basic_cmd.dst_endpoint = zigbee_device->dev_addr.zigbee_endpointid; - cmd_req.zcl_basic_cmd.src_endpoint = zigbee_device->dev->endpoint_id; + cmd_req.zcl_basic_cmd.src_endpoint = esp_matter::endpoint::get_id(zigbee_device->dev->endpoint); cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_ENDP_PRESENT; cmd_req.on_off_cmd_id = val->val.b ? ZB_ZCL_CMD_ON_OFF_ON_ID : ZB_ZCL_CMD_ON_OFF_OFF_ID; esp_zb_zcl_on_off_cmd_req(&cmd_req);