mirror of
https://github.com/espressif/esp-matter.git
synced 2026-04-27 19:13:13 +00:00
Merge branch 'feature/aggregator_device' into 'main'
esp_matter: Add aggregator device type for bridge apps See merge request app-frameworks/esp-matter!187
This commit is contained in:
@@ -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 {
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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 {
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -377,7 +377,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");
|
||||
@@ -568,7 +568,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;
|
||||
@@ -634,7 +634,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;
|
||||
|
||||
@@ -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 */
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -18,15 +18,15 @@
|
||||
#include <esp_err.h>
|
||||
#include <esp_matter_core.h>
|
||||
|
||||
#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);
|
||||
|
||||
@@ -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) {
|
||||
@@ -88,6 +90,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) {
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -24,6 +24,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) {
|
||||
@@ -87,6 +89,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) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user