diff --git a/components/esp_matter/esp_matter_cluster.cpp b/components/esp_matter/esp_matter_cluster.cpp index f815b219f..36ab7ace7 100644 --- a/components/esp_matter/esp_matter_cluster.cpp +++ b/components/esp_matter/esp_matter_cluster.cpp @@ -56,6 +56,12 @@ const int esp_matter_cluster_group_key_management_function_flags = CLUSTER_MASK_ const esp_matter_cluster_function_generic_t *esp_matter_cluster_binding_function_list = NULL; const int esp_matter_cluster_binding_function_flags = CLUSTER_MASK_NONE; +const esp_matter_cluster_function_generic_t *esp_matter_cluster_bridged_device_basic_function_list = NULL; +const int esp_matter_cluster_bridged_device_basic_function_flags = CLUSTER_MASK_NONE; + +const esp_matter_cluster_function_generic_t *esp_matter_cluster_fixed_label_function_list = NULL; +const int esp_matter_cluster_fixed_label_function_flags = CLUSTER_MASK_NONE; + const esp_matter_cluster_function_generic_t esp_matter_cluster_access_control_function_list[] = { (esp_matter_cluster_function_generic_t)emberAfAccessControlClusterServerInitCallback, }; @@ -872,3 +878,53 @@ esp_matter_cluster_t *esp_matter_cluster_create_thermostat(esp_matter_endpoint_t return cluster; } + +esp_matter_cluster_t *esp_matter_cluster_create_bridged_device_basic(esp_matter_endpoint_t *endpoint, + esp_matter_cluster_bridged_device_basic_config_t *config, + uint8_t flags) +{ + esp_matter_cluster_t *cluster = esp_matter_cluster_create(endpoint, ZCL_BRIDGED_DEVICE_BASIC_CLUSTER_ID, flags); + if (!cluster) { + ESP_LOGE(TAG, "Could not create cluster"); + return NULL; + } + + if (flags & CLUSTER_MASK_SERVER) { + // There is not PluginServer(Client)InitCallback for this cluster + esp_matter_cluster_add_function_list(cluster, esp_matter_cluster_bridged_device_basic_function_list, + esp_matter_cluster_bridged_device_basic_function_flags); + } + + esp_matter_attribute_create(cluster, ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID, ATTRIBUTE_MASK_NONE, + esp_matter_uint16(config->cluster_revision)); + esp_matter_attribute_create(cluster, ZCL_NODE_LABEL_ATTRIBUTE_ID, ATTRIBUTE_MASK_NONE, + esp_matter_char_str(config->node_label, sizeof(config->node_label))); + esp_matter_attribute_create(cluster, ZCL_REACHABLE_ATTRIBUTE_ID, ATTRIBUTE_MASK_NONE, + esp_matter_bool(config->reachable)); + return cluster; +} + +esp_matter_cluster_t *esp_matter_cluster_create_fixed_label(esp_matter_endpoint_t *endpoint, + esp_matter_cluster_fixed_label_config_t *config, uint8_t flags) +{ + esp_matter_cluster_t *cluster = esp_matter_cluster_create(endpoint, ZCL_FIXED_LABEL_CLUSTER_ID, flags); + if (!cluster) { + ESP_LOGE(TAG, "Could not create cluster"); + return NULL; + } + + if (flags & CLUSTER_MASK_SERVER) { + esp_matter_cluster_set_plugin_server_init_callback(cluster, MatterFixedLabelPluginServerInitCallback); + esp_matter_cluster_add_function_list(cluster, esp_matter_cluster_fixed_label_function_list, + esp_matter_cluster_fixed_label_function_flags); + } + if (flags & CLUSTER_MASK_CLIENT) { + esp_matter_cluster_set_plugin_client_init_callback(cluster, MatterFixedLabelPluginClientInitCallback); + } + + esp_matter_attribute_create(cluster, ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID, ATTRIBUTE_MASK_NONE, + esp_matter_uint16(config->cluster_revision)); + esp_matter_attribute_create(cluster, ZCL_LABEL_LIST_ATTRIBUTE_ID, ATTRIBUTE_MASK_NONE, + esp_matter_array(config->label_list, sizeof(config->label_list), 0)); + return cluster; +} diff --git a/components/esp_matter/esp_matter_cluster.h b/components/esp_matter/esp_matter_cluster.h index 1d6f55667..7cd28dd70 100644 --- a/components/esp_matter/esp_matter_cluster.h +++ b/components/esp_matter/esp_matter_cluster.h @@ -186,6 +186,19 @@ .system_mode = 1, \ } +#define CLUSTER_CONFIG_BRIDGED_DEVICE_BASIC_DEFAULT() \ + { \ + .cluster_revision = 1, \ + .node_label = {0}, \ + .reachable = true, \ + } + +#define CLUSTER_CONFIG_FIXED_LABEL_DEFAULT() \ + { \ + .cluster_revision = 1, \ + .label_list = {0}, \ + } + typedef struct esp_matter_cluster_descriptor_config { uint16_t cluster_revision; uint8_t device_type_list[254]; @@ -336,6 +349,17 @@ typedef struct esp_matter_cluster_thermostat_config { uint8_t system_mode; } esp_matter_cluster_thermostat_config_t; +typedef struct esp_matter_cluster_bridged_device_basic_config { + uint16_t cluster_revision; + char node_label[32]; + bool reachable; +} esp_matter_cluster_bridged_device_basic_config_t; + +typedef struct esp_matter_cluster_fixed_label_config { + uint16_t cluster_revision; + uint8_t label_list[254]; +} esp_matter_cluster_fixed_label_config_t; + void esp_matter_cluster_plugin_init_callback_common(); esp_matter_cluster_t *esp_matter_cluster_create_descriptor(esp_matter_endpoint_t *endpoint, @@ -391,3 +415,8 @@ esp_matter_cluster_t *esp_matter_cluster_create_color_control(esp_matter_endpoin esp_matter_cluster_t *esp_matter_cluster_create_thermostat(esp_matter_endpoint_t *endpoint, esp_matter_cluster_thermostat_config_t *config, uint8_t flags); +esp_matter_cluster_t *esp_matter_cluster_create_bridged_device_basic(esp_matter_endpoint_t *endpoint, + esp_matter_cluster_bridged_device_basic_config_t *config, + uint8_t flags); +esp_matter_cluster_t *esp_matter_cluster_create_fixed_label(esp_matter_endpoint_t *endpoint, + esp_matter_cluster_fixed_label_config_t *config, uint8_t flags); diff --git a/components/esp_matter/esp_matter_core.cpp b/components/esp_matter/esp_matter_core.cpp index b7a48d87e..70e20f248 100644 --- a/components/esp_matter/esp_matter_core.cpp +++ b/components/esp_matter/esp_matter_core.cpp @@ -128,6 +128,10 @@ static esp_err_t esp_matter_endpoint_disable(esp_matter_endpoint_t *endpoint) } emberAfClearDynamicEndpoint(endpoint_index); + if (!(current_endpoint->endpoint_type)) { + ESP_LOGE(TAG, "endpoint %d's endpoint_type is NULL", current_endpoint->endpoint_id); + return ESP_ERR_INVALID_STATE; + } /* Free all clusters */ EmberAfEndpointType *endpoint_type = current_endpoint->endpoint_type; int cluster_count = endpoint_type->clusterCount; @@ -171,6 +175,8 @@ esp_err_t esp_matter_endpoint_enable(esp_matter_endpoint_t *endpoint) EmberAfCluster *matter_clusters = (EmberAfCluster *)calloc(1, cluster_count * sizeof(EmberAfCluster)); if (!matter_clusters) { ESP_LOGE(TAG, "Couldn't allocate matter_clusters"); + free(endpoint_type); + current_endpoint->endpoint_type = NULL; return ESP_ERR_NO_MEM; } @@ -183,6 +189,9 @@ esp_err_t esp_matter_endpoint_enable(esp_matter_endpoint_t *endpoint) attribute_count * sizeof(EmberAfAttributeMetadata)); if (!matter_attributes) { ESP_LOGE(TAG, "Couldn't allocate matter_attributes"); + free(matter_clusters); + free(endpoint_type); + current_endpoint->endpoint_type = NULL; return ESP_ERR_NO_MEM; } @@ -218,6 +227,12 @@ esp_err_t esp_matter_endpoint_enable(esp_matter_endpoint_t *endpoint) EmberAfStatus err = emberAfSetDynamicEndpoint(endpoint_index, current_endpoint->endpoint_id, endpoint_type, current_endpoint->device_type_id, 1); if (err != EMBER_ZCL_STATUS_SUCCESS) { ESP_LOGE(TAG, "Error adding dynamic endpoint %d: %d", current_endpoint->endpoint_id, err); + for (uint8_t idx = 0; idx < cluster_count; ++idx) { + free(matter_clusters[idx].attributes); + } + free(matter_clusters); + free(endpoint_type); + current_endpoint->endpoint_type = NULL; } return ESP_OK; } diff --git a/components/esp_matter/esp_matter_endpoint.cpp b/components/esp_matter/esp_matter_endpoint.cpp index 6cff2f75b..9dd1b376e 100644 --- a/components/esp_matter/esp_matter_endpoint.cpp +++ b/components/esp_matter/esp_matter_endpoint.cpp @@ -109,6 +109,26 @@ esp_matter_endpoint_t *esp_matter_endpoint_create_thermostat(esp_matter_node_t * return endpoint; } +esp_matter_endpoint_t *esp_matter_endpoint_create_bridged_node(esp_matter_node_t *node, + esp_matter_endpoint_bridged_node_config_t *config, + uint8_t flags) +{ + // bridged node endpoints are always deletable + esp_matter_endpoint_t *endpoint = esp_matter_endpoint_create_raw(node, flags | ENDPOINT_MASK_DELETABLE); + if (!endpoint) { + ESP_LOGE(TAG, "Could not create endpoint"); + return NULL; + } + + esp_matter_endpoint_set_device_type_id(endpoint, ESP_MATTER_BRIDGED_NODE_DEVICE_TYPE_ID); + + esp_matter_cluster_create_descriptor(endpoint, &(config->descriptor), CLUSTER_MASK_SERVER); + esp_matter_cluster_create_bridged_device_basic(endpoint, &(config->bridged_device_basic), CLUSTER_MASK_SERVER); + esp_matter_cluster_create_fixed_label(endpoint, &(config->fixed_label), CLUSTER_MASK_SERVER); + + return endpoint; +} + esp_matter_node_t *esp_matter_node_create(esp_matter_node_config_t *config, esp_matter_attribute_callback_t callback, void *priv_data) { diff --git a/components/esp_matter/esp_matter_endpoint.h b/components/esp_matter/esp_matter_endpoint.h index b91754f87..2947ab8fe 100644 --- a/components/esp_matter/esp_matter_endpoint.h +++ b/components/esp_matter/esp_matter_endpoint.h @@ -17,10 +17,11 @@ #include #include -#define ESP_MATTER_ROOT_NODE_DEVICE_TYPE_ID 0x016 -#define ESP_MATTER_COLOR_DIMMABLE_LIGHT_DEVICE_TYPE_ID 0x102 +#define ESP_MATTER_ROOT_NODE_DEVICE_TYPE_ID 0x0016 +#define ESP_MATTER_COLOR_DIMMABLE_LIGHT_DEVICE_TYPE_ID 0x0102 #define ESP_MATTER_ON_OFF_SWITCH_DEVICE_TYPE_ID 0x0103 #define ESP_MATTER_THERMOSTAT_DEVICE_TYPE_ID 0x0301 +#define ESP_MATTER_BRIDGED_NODE_DEVICE_TYPE_ID 0x0013 #define ENDPOINT_CONFIG_ROOT_NODE_DEFAULT() \ { \ @@ -67,6 +68,13 @@ .thermostat = CLUSTER_CONFIG_THERMOSTAT_DEFAULT(), \ } +#define ENDPOINT_CONFIG_BRIDGED_NODE_DEFAULT() \ + { \ + .descriptor = CLUSTER_CONFIG_DESCRIPTOR_DEFAULT(), \ + .bridged_device_basic = CLUSTER_CONFIG_BRIDGED_DEVICE_BASIC_DEFAULT(), \ + .fixed_label = CLUSTER_CONFIG_FIXED_LABEL_DEFAULT(), \ + } + #define NODE_CONFIG_DEFAULT() \ { \ .root_node = ENDPOINT_CONFIG_ROOT_NODE_DEFAULT(), \ @@ -113,6 +121,12 @@ typedef struct esp_matter_endpoint_thermostat_config { esp_matter_cluster_thermostat_config_t thermostat; } esp_matter_endpoint_thermostat_config_t; +typedef struct esp_matter_endpoint_bridged_node_config { + esp_matter_cluster_descriptor_config_t descriptor; + esp_matter_cluster_bridged_device_basic_config_t bridged_device_basic; + esp_matter_cluster_fixed_label_config_t fixed_label; +} esp_matter_endpoint_bridged_node_config_t; + typedef struct esp_matter_node_config { esp_matter_endpoint_root_node_config_t root_node; } esp_matter_node_config_t; @@ -129,6 +143,9 @@ esp_matter_endpoint_t *esp_matter_endpoint_create_on_off_switch(esp_matter_node_ esp_matter_endpoint_t *esp_matter_endpoint_create_thermostat(esp_matter_node_t *node, esp_matter_endpoint_thermostat_config_t *config, uint8_t flags); +esp_matter_endpoint_t *esp_matter_endpoint_create_bridged_node(esp_matter_node_t *node, + esp_matter_endpoint_bridged_node_config_t *config, + uint8_t flags); esp_matter_node_t *esp_matter_node_create(esp_matter_node_config_t *config, esp_matter_attribute_callback_t callback, void *priv_data);