From 7fffc18406f514e4cecd30888c4638f7c0340dfb Mon Sep 17 00:00:00 2001 From: WanqQixiang Date: Wed, 12 Oct 2022 13:38:04 +0800 Subject: [PATCH] esp_matter: Add endpoint resume logic endpoint: make it easier to create mutiple device_types endpoint Bridge: store bridged device information in flash --- components/esp_matter/esp_matter_core.cpp | 141 +++++++- components/esp_matter/esp_matter_core.h | 15 + components/esp_matter/esp_matter_endpoint.cpp | 198 +++++++---- components/esp_matter/esp_matter_endpoint.h | 70 +++- components/esp_matter_bridge/Kconfig | 6 + .../esp_matter_bridge/esp_matter_bridge.cpp | 335 ++++++++++++++++-- .../esp_matter_bridge/esp_matter_bridge.h | 34 +- examples/blemesh_bridge/main/app_main.cpp | 5 + .../blemesh_bridge/main/blemesh_bridge.cpp | 22 +- examples/blemesh_bridge/partitions.csv | 4 +- .../common/app_bridge/app_bridged_device.cpp | 183 ++++++++-- .../common/app_bridge/app_bridged_device.h | 11 +- examples/zigbee_bridge/main/app_main.cpp | 5 + examples/zigbee_bridge/main/zigbee_bridge.cpp | 25 +- examples/zigbee_bridge/partitions.csv | 4 +- 15 files changed, 871 insertions(+), 187 deletions(-) diff --git a/components/esp_matter/esp_matter_core.cpp b/components/esp_matter/esp_matter_core.cpp index 6d68f36b4..8c6657d41 100644 --- a/components/esp_matter/esp_matter_core.cpp +++ b/components/esp_matter/esp_matter_core.cpp @@ -63,8 +63,10 @@ using chip::DeviceLayer::ThreadStackMgr; #define ESP_MATTER_NVS_PART_NAME CONFIG_ESP_MATTER_NVS_PART_NAME #define ESP_MATTER_MAX_DEVICE_TYPE_COUNT CONFIG_ESP_MATTER_MAX_DEVICE_TYPE_COUNT +#define ESP_MATTER_NVS_NODE_NAMESPACE "node" static const char *TAG = "esp_matter_core"; +static bool esp_matter_started = false; namespace esp_matter { @@ -161,9 +163,54 @@ typedef struct _endpoint { typedef struct _node { _endpoint_t *endpoint_list; - uint16_t current_endpoint_id; + uint16_t min_unused_endpoint_id; } _node_t; +namespace node { + +static _node_t *node = NULL; + +static esp_err_t store_min_unused_endpoint_id() +{ + if (!node || !esp_matter_started) { + ESP_LOGE(TAG, "Node does not exist or esp_matter does not start"); + return ESP_ERR_INVALID_STATE; + } + + nvs_handle_t handle; + esp_err_t err = nvs_open_from_partition(ESP_MATTER_NVS_PART_NAME, ESP_MATTER_NVS_NODE_NAMESPACE, + NVS_READWRITE, &handle); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Failed to open the node nvs_namespace"); + return err; + } + err = nvs_set_u16(handle, "min_uu_ep_id", node->min_unused_endpoint_id); + nvs_commit(handle); + nvs_close(handle); + return err; +} + +static esp_err_t read_min_unused_endpoint_id() +{ + if (!node || !esp_matter_started) { + ESP_LOGE(TAG, "Node does not exist or esp_matter does not start"); + return ESP_ERR_INVALID_STATE; + } + + nvs_handle_t handle; + esp_err_t err = nvs_open_from_partition(ESP_MATTER_NVS_PART_NAME, ESP_MATTER_NVS_NODE_NAMESPACE, + NVS_READONLY, &handle); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Failed to open the node nvs_namespace"); + return err; + } + err = nvs_get_u16(handle, "min_uu_ep_id", &node->min_unused_endpoint_id); + nvs_close(handle); + return err; +} + +} /* node */ + namespace cluster { static int get_count(_cluster_t *current) { @@ -851,13 +898,23 @@ static esp_err_t chip_init(event_callback_t callback) esp_err_t start(event_callback_t callback) { + if (esp_matter_started) { + ESP_LOGE(TAG, "esp_matter has started"); + return ESP_ERR_INVALID_STATE; + } esp_matter_ota_requestor_init(); esp_err_t err = chip_init(callback); if (err != ESP_OK) { ESP_LOGE(TAG, "Error initializing matter"); + return err; + } + esp_matter_started = true; + err = node::read_min_unused_endpoint_id(); + // If the min_unused_endpoint_id is not found, we will write the current min_unused_endpoint_id in nvs. + if (err == ESP_ERR_NVS_NOT_FOUND) { + err = node::store_min_unused_endpoint_id(); } - return err; } @@ -867,6 +924,13 @@ esp_err_t factory_reset() node_t *node = node::get(); if (node) { /* ESP Matter data model is used. Erase all the data that we have added in nvs. */ + nvs_handle_t node_handle; + err = nvs_open_from_partition(ESP_MATTER_NVS_PART_NAME, ESP_MATTER_NVS_NODE_NAMESPACE, + NVS_READWRITE, &node_handle); + if (err == ESP_OK) { + nvs_erase_all(node_handle); + } + endpoint_t *endpoint = endpoint::get_first(node); while (endpoint) { uint16_t endpoint_id = endpoint::get_id(endpoint); @@ -907,9 +971,9 @@ attribute_t *create(cluster_t *cluster, uint32_t attribute_id, uint8_t flags, es _cluster_t *current_cluster = (_cluster_t *)cluster; attribute_t *existing_attribute = get(cluster, attribute_id); if (existing_attribute) { - ESP_LOGE(TAG, "Attribute 0x%04x on cluster 0x%04x already exists. Not creating again.", attribute_id, + ESP_LOGW(TAG, "Attribute 0x%04x on cluster 0x%04x already exists. Not creating again.", attribute_id, current_cluster->cluster_id); - return NULL; + return existing_attribute; } /* Allocate */ @@ -1263,9 +1327,9 @@ command_t *create(cluster_t *cluster, uint32_t command_id, uint8_t flags, callba _cluster_t *current_cluster = (_cluster_t *)cluster; command_t *existing_command = get(cluster, command_id, flags); if (existing_command) { - ESP_LOGE(TAG, "Command 0x%04x on cluster 0x%04x already exists. Not creating again.", command_id, + ESP_LOGW(TAG, "Command 0x%04x on cluster 0x%04x already exists. Not creating again.", command_id, current_cluster->cluster_id); - return NULL; + return existing_command; } /* Allocate */ @@ -1397,16 +1461,16 @@ cluster_t *create(endpoint_t *endpoint, uint32_t cluster_id, uint8_t flags) /* If a server already exists, do not create it again */ _cluster_t *_existing_cluster = (_cluster_t *)existing_cluster; if ((_existing_cluster->flags & CLUSTER_FLAG_SERVER) && (flags & CLUSTER_FLAG_SERVER)) { - ESP_LOGE(TAG, "Server Cluster 0x%04x on endpoint 0x%04x already exists. Not creating again.", cluster_id, + ESP_LOGW(TAG, "Server Cluster 0x%04x on endpoint 0x%04x already exists. Not creating again.", cluster_id, current_endpoint->endpoint_id); - return NULL; + return existing_cluster; } /* If a client already exists, do not create it again */ if ((_existing_cluster->flags & CLUSTER_FLAG_CLIENT) && (flags & CLUSTER_FLAG_CLIENT)) { - ESP_LOGE(TAG, "Client Cluster 0x%04x on endpoint 0x%04x already exists. Not creating again.", cluster_id, + ESP_LOGW(TAG, "Client Cluster 0x%04x on endpoint 0x%04x already exists. Not creating again.", cluster_id, current_endpoint->endpoint_id); - return NULL; + return existing_cluster; } /* The cluster already exists, but is of a different type. Just update the 'Set' part from below. */ @@ -1595,11 +1659,16 @@ endpoint_t *create(node_t *node, uint8_t flags, void *priv_data) } /* Set */ - endpoint->endpoint_id = current_node->current_endpoint_id++; + endpoint->endpoint_id = current_node->min_unused_endpoint_id++; endpoint->device_type_count = 0; endpoint->flags = flags; endpoint->priv_data = priv_data; + /* Store */ + if (esp_matter_started) { + node::store_min_unused_endpoint_id(); + } + /* Add */ _endpoint_t *previous_endpoint = NULL; _endpoint_t *current_endpoint = current_node->endpoint_list; @@ -1616,6 +1685,54 @@ endpoint_t *create(node_t *node, uint8_t flags, void *priv_data) return (endpoint_t *)endpoint; } +endpoint_t *resume(node_t *node, uint8_t flags, uint16_t endpoint_id, void *priv_data) +{ + /* Find */ + if (!node) { + ESP_LOGE(TAG, "Node cannot be NULL"); + return NULL; + } + _node_t *current_node = (_node_t *)node; + _endpoint_t *previous_endpoint = NULL; + _endpoint_t *current_endpoint = current_node->endpoint_list; + while (current_endpoint) { + if (current_endpoint->endpoint_id == endpoint_id) { + ESP_LOGE(TAG, "Could not resume an endpoint that has been added to the node"); + return NULL; + } + previous_endpoint = current_endpoint; + current_endpoint = current_endpoint->next; + } + + /* Check */ + if (endpoint_id >= current_node->min_unused_endpoint_id) { + ESP_LOGE(TAG, "The endpoint_id of the resumed endpoint should have been used"); + return NULL; + } + + /* Allocate */ + _endpoint_t *endpoint = (_endpoint_t *)calloc(1, sizeof(_endpoint_t)); + if (!endpoint) { + ESP_LOGE(TAG, "Couldn't allocate _endpoint_t"); + return NULL; + } + + /* Set */ + endpoint->endpoint_id = endpoint_id; + endpoint->device_type_count = 0; + endpoint->flags = flags; + endpoint->priv_data = priv_data; + + /* Add */ + if (previous_endpoint == NULL) { + current_node->endpoint_list = endpoint; + } else { + previous_endpoint->next = endpoint; + } + + return (endpoint_t *)endpoint; +} + esp_err_t destroy(node_t *node, endpoint_t *endpoint) { if (!node || !endpoint) { @@ -1780,8 +1897,6 @@ void *get_priv_data(uint16_t endpoint_id) namespace node { -static _node_t *node = NULL; - node_t *create_raw() { if (node) { diff --git a/components/esp_matter/esp_matter_core.h b/components/esp_matter/esp_matter_core.h index 5b05426c0..dde9267c7 100644 --- a/components/esp_matter/esp_matter_core.h +++ b/components/esp_matter/esp_matter_core.h @@ -138,6 +138,21 @@ namespace endpoint { */ endpoint_t *create(node_t *node, uint8_t flags, void *priv_data); +/** Resume endpoint + * + * This will resume an endpoint after reboot and add it to the node. + * + * @param[in] node Node handle. + * @param[in] flags Bitmap of `endpoint_flags_t`. + * @param[in] endpoint_id Endpoint ID of the endpoint resumed. + * @param[in] priv_data (Optional) Private data associated with the endpoint. This will be passed to the + * attribute_update and identify callbacks. It should stay allocated throughout the lifetime of the device. + * + * @return Endpoint handle on success. + * @return NULL in case of failure. + */ +endpoint_t *resume(node_t *node, uint8_t flags, uint16_t endpoint_id, void *priv_data); + /** Destroy endpoint * * This will destroy the endpoint which has been created and added to the node. It also destroys the associated diff --git a/components/esp_matter/esp_matter_endpoint.cpp b/components/esp_matter/esp_matter_endpoint.cpp index 98d86ffaa..6875118fa 100644 --- a/components/esp_matter/esp_matter_endpoint.cpp +++ b/components/esp_matter/esp_matter_endpoint.cpp @@ -16,53 +16,6 @@ #include #include -/* Replace these with IDs from submodule whenever they are implemented */ -#define ESP_MATTER_ROOT_NODE_DEVICE_TYPE_ID 0x0016 -#define ESP_MATTER_ROOT_NODE_DEVICE_TYPE_VERSION 1 -#define ESP_MATTER_AGGREGATOR_DEVICE_TYPE_ID 0x000E -#define ESP_MATTER_AGGREGATOR_DEVICE_TYPE_VERSION 1 -#define ESP_MATTER_BRIDGED_NODE_DEVICE_TYPE_ID 0x0013 -#define ESP_MATTER_BRIDGED_NODE_DEVICE_TYPE_VERSION 1 - -#define ESP_MATTER_ON_OFF_LIGHT_DEVICE_TYPE_ID 0x0100 -#define ESP_MATTER_ON_OFF_LIGHT_DEVICE_TYPE_VERSION 2 -#define ESP_MATTER_DIMMABLE_LIGHT_DEVICE_TYPE_ID 0x0101 -#define ESP_MATTER_DIMMABLE_LIGHT_DEVICE_TYPE_VERSION 2 -#define ESP_MATTER_COLOR_TEMPERATURE_LIGHT_DEVICE_TYPE_ID 0x010C -#define ESP_MATTER_COLOR_TEMPERATURE_LIGHT_DEVICE_TYPE_VERSION 2 -#define ESP_MATTER_EXTENDED_COLOR_LIGHT_DEVICE_TYPE_ID 0x010D -#define ESP_MATTER_EXTENDED_COLOR_LIGHT_DEVICE_TYPE_VERSION 2 - -#define ESP_MATTER_ON_OFF_SWITCH_DEVICE_TYPE_ID 0x0103 -#define ESP_MATTER_ON_OFF_SWITCH_DEVICE_TYPE_VERSION 2 -#define ESP_MATTER_DIMMER_SWITCH_DEVICE_TYPE_ID 0x0104 -#define ESP_MATTER_DIMMER_SWITCH_DEVICE_TYPE_VERSION 2 -#define ESP_MATTER_COLOR_DIMMER_SWITCH_DEVICE_TYPE_ID 0x0105 -#define ESP_MATTER_COLOR_DIMMER_SWITCH_DEVICE_TYPE_VERSION 2 -#define ESP_MATTER_GENERIC_SWITCH_DEVICE_TYPE_ID 0x000F -#define ESP_MATTER_GENERIC_SWITCH_DEVICE_TYPE_VERSION 1 - -#define ESP_MATTER_ON_OFF_PLUGIN_UNIT_DEVICE_TYPE_ID 0x010A -#define ESP_MATTER_ON_OFF_PLUGIN_UNIT_DEVICE_TYPE_VERSION 2 -#define ESP_MATTER_DIMMABLE_PLUGIN_UNIT_DEVICE_TYPE_ID 0x010B -#define ESP_MATTER_DIMMABLE_PLUGIN_UNIT_DEVICE_TYPE_VERSION 2 - -#define ESP_MATTER_TEMPERATURE_SENSOR_DEVICE_TYPE_ID 0x0302 -#define ESP_MATTER_TEMPERATURE_SENSOR_DEVICE_TYPE_VERSION 2 -#define ESP_MATTER_OCCUPANCY_SENSOR_DEVICE_TYPE_ID 0x0107 -#define ESP_MATTER_OCCUPANCY_SENSOR_DEVICE_TYPE_VERSION 2 -#define ESP_MATTER_CONTACT_SENSOR_DEVICE_TYPE_ID 0x0015 -#define ESP_MATTER_CONTACT_SENSOR_DEVICE_TYPE_VERSION 1 - -#define ESP_MATTER_FAN_DEVICE_TYPE_ID 0x002B -#define ESP_MATTER_FAN_DEVICE_TYPE_VERSION 1 -#define ESP_MATTER_THERMOSTAT_DEVICE_TYPE_ID 0x0301 -#define ESP_MATTER_THERMOSTAT_DEVICE_TYPE_VERSION 2 -#define ESP_MATTER_DOOR_LOCK_DEVICE_TYPE_ID 0x000A -#define ESP_MATTER_DOOR_LOCK_DEVICE_TYPE_VERSION 2 -#define ESP_MATTER_WINDOW_COVERING_DEVICE_TYPE_ID 0x0202 -#define ESP_MATTER_WINDOW_COVERING_DEVICE_TYPE_VERSION 2 - static const char *TAG = "esp_matter_endpoint"; namespace esp_matter { @@ -83,8 +36,13 @@ uint8_t get_device_type_version() endpoint_t *create(node_t *node, config_t *config, uint8_t flags, void *priv_data) { endpoint_t *endpoint = endpoint::create(node, flags, priv_data); + return add(endpoint, config); +} + +endpoint_t *add(endpoint_t *endpoint, config_t *config) +{ if (!endpoint) { - ESP_LOGE(TAG, "Could not create endpoint"); + ESP_LOGE(TAG, "Endpoint cannot be NULL"); return NULL; } add_device_type(endpoint, get_device_type_id(), get_device_type_version()); @@ -124,8 +82,13 @@ uint8_t get_device_type_version() endpoint_t *create(node_t *node, config_t *config, uint8_t flags, void *priv_data) { endpoint_t *endpoint = endpoint::create(node, flags, priv_data); + return add(endpoint, config); +} + +endpoint_t *add(endpoint_t *endpoint, config_t *config) +{ if (!endpoint) { - ESP_LOGE(TAG, "Could not create endpoint"); + ESP_LOGE(TAG, "Endpoint cannot be NULL"); return NULL; } add_device_type(endpoint, get_device_type_id(), get_device_type_version()); @@ -138,6 +101,7 @@ endpoint_t *create(node_t *node, config_t *config, uint8_t flags, void *priv_dat return endpoint; } + } /* on_off_light */ namespace dimmable_light { @@ -154,8 +118,13 @@ uint8_t get_device_type_version() endpoint_t *create(node_t *node, config_t *config, uint8_t flags, void *priv_data) { endpoint_t *endpoint = endpoint::create(node, flags, priv_data); + return add(endpoint, config); +} + +endpoint_t *add(endpoint_t *endpoint, config_t *config) +{ if (!endpoint) { - ESP_LOGE(TAG, "Could not create endpoint"); + ESP_LOGE(TAG, "Endpoint cannot be NULL"); return NULL; } add_device_type(endpoint, get_device_type_id(), get_device_type_version()); @@ -186,8 +155,13 @@ uint8_t get_device_type_version() endpoint_t *create(node_t *node, config_t *config, 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 add(endpoint, config); +} + +endpoint_t *add(endpoint_t *endpoint, config_t *config) +{ + if (!endpoint) { + ESP_LOGE(TAG, "Endpoint cannot be NULL"); return NULL; } add_device_type(endpoint, get_device_type_id(), get_device_type_version()); @@ -204,6 +178,7 @@ endpoint_t *create(node_t *node, config_t *config, uint8_t flags, void *priv_dat return endpoint; } + } /* color_temperature_light */ namespace extended_color_light { @@ -220,8 +195,13 @@ uint8_t get_device_type_version() endpoint_t *create(node_t *node, config_t *config, uint8_t flags, void *priv_data) { endpoint_t *endpoint = endpoint::create(node, flags, priv_data); + return add(endpoint, config); +} + +endpoint_t *add(endpoint_t *endpoint, config_t *config) +{ if (!endpoint) { - ESP_LOGE(TAG, "Could not create endpoint"); + ESP_LOGE(TAG, "Endpoint cannot be NULL"); return NULL; } add_device_type(endpoint, get_device_type_id(), get_device_type_version()); @@ -254,8 +234,13 @@ uint8_t get_device_type_version() endpoint_t *create(node_t *node, config_t *config, uint8_t flags, void *priv_data) { endpoint_t *endpoint = endpoint::create(node, flags, priv_data); + return add(endpoint, config); +} + +endpoint_t *add(endpoint_t *endpoint, config_t *config) +{ if (!endpoint) { - ESP_LOGE(TAG, "Could not create endpoint"); + ESP_LOGE(TAG, "Endpoint cannot be NULL"); return NULL; } add_device_type(endpoint, get_device_type_id(), get_device_type_version()); @@ -283,8 +268,13 @@ uint8_t get_device_type_version() endpoint_t *create(node_t *node, config_t *config, uint8_t flags, void *priv_data) { endpoint_t *endpoint = endpoint::create(node, flags, priv_data); + return add(endpoint, config); +} + +endpoint_t *add(endpoint_t *endpoint, config_t *config) +{ if (!endpoint) { - ESP_LOGE(TAG, "Could not create endpoint"); + ESP_LOGE(TAG, "Endpoint cannot be NULL"); return NULL; } add_device_type(endpoint, get_device_type_id(), get_device_type_version()); @@ -297,6 +287,7 @@ endpoint_t *create(node_t *node, config_t *config, uint8_t flags, void *priv_dat return endpoint; } + } /* dimmer_switch */ namespace color_dimmer_switch { @@ -313,8 +304,13 @@ uint8_t get_device_type_version() endpoint_t *create(node_t *node, config_t *config, uint8_t flags, void *priv_data) { endpoint_t *endpoint = endpoint::create(node, flags, priv_data); + return add(endpoint, config); +} + +endpoint_t *add(endpoint_t *endpoint, config_t *config) +{ if (!endpoint) { - ESP_LOGE(TAG, "Could not create endpoint"); + ESP_LOGE(TAG, "Endpoint cannot be NULL"); return NULL; } add_device_type(endpoint, get_device_type_id(), get_device_type_version()); @@ -344,8 +340,13 @@ uint8_t get_device_type_version() endpoint_t *create(node_t *node, config_t *config, uint8_t flags, void *priv_data) { endpoint_t *endpoint = endpoint::create(node, flags, priv_data); + return add(endpoint, config); +} + +endpoint_t *add(endpoint_t *endpoint, config_t *config) +{ if (!endpoint) { - ESP_LOGE(TAG, "Could not create endpoint"); + ESP_LOGE(TAG, "Endpoint cannot be NULL"); return NULL; } add_device_type(endpoint, get_device_type_id(), get_device_type_version()); @@ -372,8 +373,13 @@ uint8_t get_device_type_version() endpoint_t *create(node_t *node, config_t *config, uint8_t flags, void *priv_data) { endpoint_t *endpoint = endpoint::create(node, flags, priv_data); + return add(endpoint, config); +} + +endpoint_t *add(endpoint_t *endpoint, config_t *config) +{ if (!endpoint) { - ESP_LOGE(TAG, "Could not create endpoint"); + ESP_LOGE(TAG, "Endpoint cannot be NULL"); return NULL; } add_device_type(endpoint, get_device_type_id(), get_device_type_version()); @@ -402,8 +408,13 @@ uint8_t get_device_type_version() endpoint_t *create(node_t *node, config_t *config, uint8_t flags, void *priv_data) { endpoint_t *endpoint = endpoint::create(node, flags, priv_data); + return add(endpoint, config); +} + +endpoint_t *add(endpoint_t *endpoint, config_t *config) +{ if (!endpoint) { - ESP_LOGE(TAG, "Could not create endpoint"); + ESP_LOGE(TAG, "Endpoint cannot be NULL"); return NULL; } add_device_type(endpoint, get_device_type_id(), get_device_type_version()); @@ -434,8 +445,13 @@ uint8_t get_device_type_version() endpoint_t *create(node_t *node, config_t *config, uint8_t flags, void *priv_data) { endpoint_t *endpoint = endpoint::create(node, flags, priv_data); + return add(endpoint, config); +} + +endpoint_t *add(endpoint_t *endpoint, config_t *config) +{ if (!endpoint) { - ESP_LOGE(TAG, "Could not create endpoint"); + ESP_LOGE(TAG, "Endpoint cannot be NULL"); return NULL; } add_device_type(endpoint, get_device_type_id(), get_device_type_version()); @@ -463,8 +479,13 @@ uint8_t get_device_type_version() endpoint_t *create(node_t *node, config_t *config, uint8_t flags, void *priv_data) { endpoint_t *endpoint = endpoint::create(node, flags, priv_data); + return add(endpoint, config); +} + +endpoint_t *add(endpoint_t *endpoint, config_t *config) +{ if (!endpoint) { - ESP_LOGE(TAG, "Could not create endpoint"); + ESP_LOGE(TAG, "Endpoint cannot be NULL"); return NULL; } add_device_type(endpoint, get_device_type_id(), get_device_type_version()); @@ -491,8 +512,13 @@ uint8_t get_device_type_version() endpoint_t *create(node_t *node, uint8_t flags, void *priv_data) { endpoint_t *endpoint = endpoint::create(node, flags, priv_data); + return add(endpoint); +} + +endpoint_t *add(endpoint_t *endpoint) +{ if (!endpoint) { - ESP_LOGE(TAG, "Could not create endpoint"); + ESP_LOGE(TAG, "Endpoint cannot be NULL"); return NULL; } add_device_type(endpoint, get_device_type_id(), get_device_type_version()); @@ -518,8 +544,13 @@ endpoint_t *create(node_t *node, config_t *config, uint8_t flags, void *priv_dat { // bridged node endpoints are always deletable endpoint_t *endpoint = endpoint::create(node, flags | ENDPOINT_FLAG_DESTROYABLE, priv_data); + return add(endpoint, config); +} + +endpoint_t *add(endpoint_t *endpoint, config_t *config) +{ if (!endpoint) { - ESP_LOGE(TAG, "Could not create endpoint"); + ESP_LOGE(TAG, "Endpoint cannot be NULL"); return NULL; } @@ -530,6 +561,12 @@ endpoint_t *create(node_t *node, config_t *config, uint8_t flags, void *priv_dat return endpoint; } + +endpoint_t *resume(node_t *node, config_t *config, uint8_t flags, uint16_t endpoint_id, void *priv_data) +{ + endpoint_t *endpoint = endpoint::resume(node, flags | ENDPOINT_FLAG_DESTROYABLE, endpoint_id, priv_data); + return add(endpoint, config); +} } /* bridged_node */ namespace door_lock { @@ -546,8 +583,13 @@ uint8_t get_device_type_version() endpoint_t *create(node_t *node, config_t *config, uint8_t flags, void *priv_data) { endpoint_t *endpoint = endpoint::create(node, flags, priv_data); + return add(endpoint, config); +} + +endpoint_t *add(endpoint_t *endpoint, config_t *config) +{ if (!endpoint) { - ESP_LOGE(TAG, "Could not create endpoint"); + ESP_LOGE(TAG, "Endpoint cannot be NULL"); return NULL; } @@ -575,8 +617,13 @@ uint8_t get_device_type_version() endpoint_t *create(node_t *node, config_t *config, uint8_t flags, void * priv_data) { endpoint_t *endpoint = endpoint::create(node, flags, priv_data); + return add(endpoint, config); +} + +endpoint_t *add(endpoint_t *endpoint, config_t *config) +{ if (!endpoint) { - ESP_LOGE(TAG, "Could not create endpoint"); + ESP_LOGE(TAG, "Endpoint cannot be NULL"); return NULL; } @@ -604,8 +651,13 @@ uint8_t get_device_type_version() endpoint_t *create(node_t *node, config_t *config, uint8_t flags, void *priv_data) { endpoint_t *endpoint = endpoint::create(node, flags, priv_data); + return add(endpoint, config); +} + +endpoint_t *add(endpoint_t *endpoint, config_t *config) +{ if (!endpoint) { - ESP_LOGE(TAG, "Could not create endpoint"); + ESP_LOGE(TAG, "Endpoint cannot be NULL"); return NULL; } add_device_type(endpoint, get_device_type_id(), get_device_type_version()); @@ -631,8 +683,13 @@ uint8_t get_device_type_version() endpoint_t *create(node_t *node, config_t *config, uint8_t flags, void *priv_data) { endpoint_t *endpoint = endpoint::create(node, flags, priv_data); + return add(endpoint, config); +} + +endpoint_t *add(endpoint_t *endpoint, config_t *config) +{ if (!endpoint) { - ESP_LOGE(TAG, "Could not create endpoint"); + ESP_LOGE(TAG, "Endpoint cannot be NULL"); return NULL; } add_device_type(endpoint, get_device_type_id(), get_device_type_version()); @@ -658,8 +715,13 @@ uint8_t get_device_type_version() endpoint_t *create(node_t *node, config_t *config, uint8_t flags, void *priv_data) { endpoint_t *endpoint = endpoint::create(node, flags, priv_data); + return add(endpoint, config); +} + +endpoint_t *add(endpoint_t *endpoint, config_t *config) +{ if (!endpoint) { - ESP_LOGE(TAG, "Could not create endpoint"); + ESP_LOGE(TAG, "Endpoint cannot be NULL"); return NULL; } add_device_type(endpoint, get_device_type_id(), get_device_type_version()); diff --git a/components/esp_matter/esp_matter_endpoint.h b/components/esp_matter/esp_matter_endpoint.h index 32370689e..cca043aff 100644 --- a/components/esp_matter/esp_matter_endpoint.h +++ b/components/esp_matter/esp_matter_endpoint.h @@ -18,6 +18,53 @@ #include #include +/* Replace these with IDs from submodule whenever they are implemented */ +#define ESP_MATTER_ROOT_NODE_DEVICE_TYPE_ID 0x0016 +#define ESP_MATTER_ROOT_NODE_DEVICE_TYPE_VERSION 1 +#define ESP_MATTER_AGGREGATOR_DEVICE_TYPE_ID 0x000E +#define ESP_MATTER_AGGREGATOR_DEVICE_TYPE_VERSION 1 +#define ESP_MATTER_BRIDGED_NODE_DEVICE_TYPE_ID 0x0013 +#define ESP_MATTER_BRIDGED_NODE_DEVICE_TYPE_VERSION 1 + +#define ESP_MATTER_ON_OFF_LIGHT_DEVICE_TYPE_ID 0x0100 +#define ESP_MATTER_ON_OFF_LIGHT_DEVICE_TYPE_VERSION 2 +#define ESP_MATTER_DIMMABLE_LIGHT_DEVICE_TYPE_ID 0x0101 +#define ESP_MATTER_DIMMABLE_LIGHT_DEVICE_TYPE_VERSION 2 +#define ESP_MATTER_COLOR_TEMPERATURE_LIGHT_DEVICE_TYPE_ID 0x010C +#define ESP_MATTER_COLOR_TEMPERATURE_LIGHT_DEVICE_TYPE_VERSION 2 +#define ESP_MATTER_EXTENDED_COLOR_LIGHT_DEVICE_TYPE_ID 0x010D +#define ESP_MATTER_EXTENDED_COLOR_LIGHT_DEVICE_TYPE_VERSION 2 + +#define ESP_MATTER_ON_OFF_SWITCH_DEVICE_TYPE_ID 0x0103 +#define ESP_MATTER_ON_OFF_SWITCH_DEVICE_TYPE_VERSION 2 +#define ESP_MATTER_DIMMER_SWITCH_DEVICE_TYPE_ID 0x0104 +#define ESP_MATTER_DIMMER_SWITCH_DEVICE_TYPE_VERSION 2 +#define ESP_MATTER_COLOR_DIMMER_SWITCH_DEVICE_TYPE_ID 0x0105 +#define ESP_MATTER_COLOR_DIMMER_SWITCH_DEVICE_TYPE_VERSION 2 +#define ESP_MATTER_GENERIC_SWITCH_DEVICE_TYPE_ID 0x000F +#define ESP_MATTER_GENERIC_SWITCH_DEVICE_TYPE_VERSION 1 + +#define ESP_MATTER_ON_OFF_PLUGIN_UNIT_DEVICE_TYPE_ID 0x010A +#define ESP_MATTER_ON_OFF_PLUGIN_UNIT_DEVICE_TYPE_VERSION 2 +#define ESP_MATTER_DIMMABLE_PLUGIN_UNIT_DEVICE_TYPE_ID 0x010B +#define ESP_MATTER_DIMMABLE_PLUGIN_UNIT_DEVICE_TYPE_VERSION 2 + +#define ESP_MATTER_TEMPERATURE_SENSOR_DEVICE_TYPE_ID 0x0302 +#define ESP_MATTER_TEMPERATURE_SENSOR_DEVICE_TYPE_VERSION 2 +#define ESP_MATTER_OCCUPANCY_SENSOR_DEVICE_TYPE_ID 0x0107 +#define ESP_MATTER_OCCUPANCY_SENSOR_DEVICE_TYPE_VERSION 2 +#define ESP_MATTER_CONTACT_SENSOR_DEVICE_TYPE_ID 0x0015 +#define ESP_MATTER_CONTACT_SENSOR_DEVICE_TYPE_VERSION 1 + +#define ESP_MATTER_FAN_DEVICE_TYPE_ID 0x002B +#define ESP_MATTER_FAN_DEVICE_TYPE_VERSION 1 +#define ESP_MATTER_THERMOSTAT_DEVICE_TYPE_ID 0x0301 +#define ESP_MATTER_THERMOSTAT_DEVICE_TYPE_VERSION 2 +#define ESP_MATTER_DOOR_LOCK_DEVICE_TYPE_ID 0x000A +#define ESP_MATTER_DOOR_LOCK_DEVICE_TYPE_VERSION 2 +#define ESP_MATTER_WINDOW_COVERING_DEVICE_TYPE_ID 0x0202 +#define ESP_MATTER_WINDOW_COVERING_DEVICE_TYPE_VERSION 2 + namespace esp_matter { /** Specific endpoint (device type) create APIs @@ -45,6 +92,7 @@ typedef struct config { uint32_t get_device_type_id(); uint8_t get_device_type_version(); endpoint_t *create(node_t *node, config_t *config, uint8_t flags, void *priv_data); +endpoint_t *add(endpoint_t *endpoint, config_t *config); } /* root_node */ namespace on_off_light { @@ -58,6 +106,7 @@ typedef struct config { uint32_t get_device_type_id(); uint8_t get_device_type_version(); endpoint_t *create(node_t *node, config_t *config, uint8_t flags, void *priv_data); +endpoint_t *add(endpoint_t *endpoint, config_t *config); } /* on_off_light */ namespace dimmable_light { @@ -72,6 +121,7 @@ typedef struct config { uint32_t get_device_type_id(); uint8_t get_device_type_version(); endpoint_t *create(node_t *node, config_t *config, uint8_t flags, void *priv_data); +endpoint_t *add(endpoint_t *endpoint, config_t *config); } /* dimmable_light */ namespace color_temperature_light { @@ -87,6 +137,7 @@ typedef struct config { uint32_t get_device_type_id(); uint8_t get_device_type_version(); endpoint_t *create(node_t *node, config_t *config, uint8_t flags, void *priv_data); +endpoint_t *add(endpoint_t *endpoint, config_t *config); } /* color_temperature_light */ namespace extended_color_light { @@ -102,6 +153,7 @@ typedef struct config { uint32_t get_device_type_id(); uint8_t get_device_type_version(); endpoint_t *create(node_t *node, config_t *config, uint8_t flags, void *priv_data); +endpoint_t *add(endpoint_t *endpoint, config_t *config); } /* extended_color_light */ namespace on_off_switch { @@ -113,6 +165,7 @@ typedef struct config { uint32_t get_device_type_id(); uint8_t get_device_type_version(); endpoint_t *create(node_t *node, config_t *config, uint8_t flags, void *priv_data); +endpoint_t *add(endpoint_t *endpoint, config_t *config); } /* on_off_switch */ namespace dimmer_switch { @@ -124,6 +177,7 @@ typedef struct config { uint32_t get_device_type_id(); uint8_t get_device_type_version(); endpoint_t *create(node_t *node, config_t *config, uint8_t flags, void *priv_data); +endpoint_t *add(endpoint_t *endpoint, config_t *config); } /* dimmer_switch */ namespace color_dimmer_switch { @@ -135,6 +189,7 @@ typedef struct config { uint32_t get_device_type_id(); uint8_t get_device_type_version(); endpoint_t *create(node_t *node, config_t *config, uint8_t flags, void *priv_data); +endpoint_t *add(endpoint_t *endpoint, config_t *config); } /* color_dimmer_switch */ namespace generic_switch { @@ -146,6 +201,7 @@ typedef struct config { uint32_t get_device_type_id(); uint8_t get_device_type_version(); endpoint_t *create(node_t *node, config_t *config, uint8_t flags, void *priv_data); +endpoint_t *add(endpoint_t *endpoint, config_t *config); } /* generic_switch */ namespace on_off_plugin_unit { @@ -159,6 +215,7 @@ typedef struct config { uint32_t get_device_type_id(); uint8_t get_device_type_version(); endpoint_t *create(node_t *node, config_t *config, uint8_t flags, void *priv_data); +endpoint_t *add(endpoint_t *endpoint, config_t *config); } /* on_off_plugin_unit */ namespace dimmable_plugin_unit { @@ -173,6 +230,7 @@ typedef struct config { uint32_t get_device_type_id(); uint8_t get_device_type_version(); endpoint_t *create(node_t *node, config_t *config, uint8_t flags, void *priv_data); +endpoint_t *add(endpoint_t *endpoint, config_t *config); } /* dimmable_plugin_unit */ namespace fan { @@ -185,6 +243,7 @@ typedef struct config { uint32_t get_device_type_id(); uint8_t get_device_type_version(); endpoint_t *create(node_t *node, config_t *config, uint8_t flags, void *priv_data); +endpoint_t *add(endpoint_t *endpoint, config_t *config); } /* fan */ namespace thermostat { @@ -197,13 +256,15 @@ typedef struct config { uint32_t get_device_type_id(); uint8_t get_device_type_version(); endpoint_t *create(node_t *node, config_t *config, uint8_t flags, void *priv_data); +endpoint_t *add(endpoint_t *endpoint, config_t *config); } /* thermostat */ namespace aggregator { uint32_t get_device_type_id(); uint8_t get_device_type_version(); endpoint_t *create(node_t *node, uint8_t flags, void *priv_data); -} /* bridge */ +endpoint_t *add(endpoint_t *endpoint); +} /* aggregator */ namespace bridged_node { typedef struct config { @@ -213,6 +274,8 @@ typedef struct config { uint32_t get_device_type_id(); uint8_t get_device_type_version(); endpoint_t *create(node_t *node, config_t *config, uint8_t flags, void *priv_data); +endpoint_t *add(endpoint_t *endpoint, config_t *config); +endpoint_t *resume(node_t *node, config_t *config, uint8_t flags, uint16_t endpoint_id, void *priv_data); } /* bridged_node */ namespace door_lock { @@ -224,6 +287,7 @@ typedef struct config { uint32_t get_device_type_id(); uint8_t get_device_type_version(); endpoint_t *create(node_t *node, config_t *config, uint8_t flags, void *priv_data); +endpoint_t *add(endpoint_t *endpoint, config_t *config); } /* door_lock */ namespace window_covering_device { @@ -237,6 +301,7 @@ typedef struct config { uint32_t get_device_type_id(); uint8_t get_device_type_version(); endpoint_t *create(node_t *node, config_t *config, uint8_t flags, void *priv_data); +endpoint_t *add(endpoint_t *endpoint, config_t *config); } /* window_covering */ namespace temperature_sensor { @@ -248,6 +313,7 @@ typedef struct config { uint32_t get_device_type_id(); uint8_t get_device_type_version(); endpoint_t *create(node_t *node, config_t *config, uint8_t flags, void *priv_data); +endpoint_t *add(endpoint_t *endpoint, config_t *config); } /* temperature_sensor */ namespace occupancy_sensor { @@ -259,6 +325,7 @@ typedef struct config { uint32_t get_device_type_id(); uint8_t get_device_type_version(); endpoint_t *create(node_t *node, config_t *config, uint8_t flags, void *priv_data); +endpoint_t *add(endpoint_t *endpoint, config_t *config); } /* occupancy_sensor */ namespace contact_sensor { @@ -270,6 +337,7 @@ typedef struct config { uint32_t get_device_type_id(); uint8_t get_device_type_version(); endpoint_t *create(node_t *node, config_t *config, uint8_t flags, void *priv_data); +endpoint_t *add(endpoint_t *endpoint, config_t *config); } /* contact_sensor */ } /* endpoint */ diff --git a/components/esp_matter_bridge/Kconfig b/components/esp_matter_bridge/Kconfig index 6db661045..919c64c65 100644 --- a/components/esp_matter_bridge/Kconfig +++ b/components/esp_matter_bridge/Kconfig @@ -7,4 +7,10 @@ menu "ESP Matter Bridge" help The number of aggregator endpoint for the bridge device + config ESP_MATTER_BRIDGE_INFO_PART_NAME + string "Bridge device information partition name" + default "nvs" + help + The NVS Partition name for Matter Bridge to store the bridged devices' information. + endmenu diff --git a/components/esp_matter_bridge/esp_matter_bridge.cpp b/components/esp_matter_bridge/esp_matter_bridge.cpp index f46b3f279..e31db4dc4 100644 --- a/components/esp_matter_bridge/esp_matter_bridge.cpp +++ b/components/esp_matter_bridge/esp_matter_bridge.cpp @@ -14,60 +14,300 @@ #include #include +#include +#include #include #include +#if MAX_BRIDGED_DEVICE_COUNT > 0 +#define ESP_MATTER_BRIDGE_PESISTENT_INFO_KEY "persistent_info" +#define ESP_MATTER_BRIDGE_NAMESPACE "bridge" +#define ESP_MATTER_BRIDGE_ENDPOINT_ID_ARRAY_KEY "ep_id_array" 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, uint16_t parent_endpoint_id) +namespace esp_matter_bridge { + +static uint16_t bridged_endpoint_id_array[MAX_BRIDGED_DEVICE_COUNT]; + +/** Persistent Bridged Device Info **/ +static esp_err_t store_device_persistent_info(device_t *device) { + esp_err_t err = ESP_OK; + if (!device) { + ESP_LOGE(TAG, "device cannot be NULL"); + return ESP_ERR_INVALID_ARG; + } + + nvs_handle_t handle; + char namespace_name[16] = {0}; + snprintf(namespace_name, 16, "bridge_ep_%X", device->persistent_info.device_endpoint_id); + err = nvs_open_from_partition(CONFIG_ESP_MATTER_BRIDGE_INFO_PART_NAME, namespace_name, NVS_READWRITE, &handle); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Error opening partition %s namespace %s. Err: %d", CONFIG_ESP_MATTER_BRIDGE_INFO_PART_NAME, + namespace_name, err); + return err; + } + err = nvs_set_blob(handle, ESP_MATTER_BRIDGE_PESISTENT_INFO_KEY, &device->persistent_info, + sizeof(device_persistent_info_t)); + nvs_commit(handle); + nvs_close(handle); + return err; +} + +static esp_err_t read_device_persistent_info(device_persistent_info_t *persistent_info, uint16_t endpoint_id) +{ + esp_err_t err = ESP_OK; + if (!persistent_info) { + ESP_LOGE(TAG, "persistent_info cannot be NULL"); + return ESP_ERR_INVALID_ARG; + } + + nvs_handle_t handle; + char namespace_name[16] = {0}; + snprintf(namespace_name, 16, "bridge_ep_%X", endpoint_id); + err = nvs_open_from_partition(CONFIG_ESP_MATTER_BRIDGE_INFO_PART_NAME, namespace_name, NVS_READONLY, &handle); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Error opening partition %s namespace %s. Err: %d", CONFIG_ESP_MATTER_BRIDGE_INFO_PART_NAME, + namespace_name, err); + return err; + } + size_t len = sizeof(device_persistent_info_t); + err = nvs_get_blob(handle, ESP_MATTER_BRIDGE_PESISTENT_INFO_KEY, persistent_info, &len); + nvs_close(handle); + return err; +} + +static esp_err_t store_bridged_endpoint_ids() +{ + esp_err_t err = ESP_OK; + nvs_handle_t handle; + err = nvs_open_from_partition(CONFIG_ESP_MATTER_BRIDGE_INFO_PART_NAME, ESP_MATTER_BRIDGE_NAMESPACE, NVS_READWRITE, + &handle); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Error opening partition %s namespace %s. Err: %d", CONFIG_ESP_MATTER_BRIDGE_INFO_PART_NAME, + ESP_MATTER_BRIDGE_NAMESPACE, err); + return err; + } + err = nvs_set_blob(handle, ESP_MATTER_BRIDGE_ENDPOINT_ID_ARRAY_KEY, bridged_endpoint_id_array, + sizeof(bridged_endpoint_id_array)); + nvs_commit(handle); + nvs_close(handle); + return err; +} + +static esp_err_t read_bridged_endpoint_ids() +{ + esp_err_t err = ESP_OK; + nvs_handle_t handle; + err = nvs_open_from_partition(CONFIG_ESP_MATTER_BRIDGE_INFO_PART_NAME, ESP_MATTER_BRIDGE_NAMESPACE, NVS_READONLY, + &handle); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Error opening partition %s namespace %s. Err: %d", CONFIG_ESP_MATTER_BRIDGE_INFO_PART_NAME, + ESP_MATTER_BRIDGE_NAMESPACE, err); + return err; + } + size_t len = sizeof(bridged_endpoint_id_array); + err = nvs_get_blob(handle, ESP_MATTER_BRIDGE_ENDPOINT_ID_ARRAY_KEY, bridged_endpoint_id_array, &len); + nvs_close(handle); + return err; +} + +esp_err_t get_bridged_endpoint_ids(uint16_t *matter_endpoint_id_array) +{ + if (!matter_endpoint_id_array) { + ESP_LOGE(TAG, "matter_endpoint_id_array is NULL. Failed to copy the bridged_endpoint_id_array to it"); + return ESP_ERR_INVALID_ARG; + } + memcpy(matter_endpoint_id_array, bridged_endpoint_id_array, sizeof(bridged_endpoint_id_array)); + return ESP_OK; +} + +esp_err_t erase_bridged_device_info(uint16_t endpoint_id) +{ + // Remove endpoint id from the endpoint id array + esp_err_t err = ESP_OK; + for (size_t idx = 0; idx < MAX_BRIDGED_DEVICE_COUNT; ++idx) { + if (bridged_endpoint_id_array[idx] == endpoint_id) { + bridged_endpoint_id_array[idx] = chip::kInvalidEndpointId; + } + } + err = store_bridged_endpoint_ids(); + if (err != ESP_OK) { + ESP_LOGE(TAG, "failed to store the endpoint_id array"); + return err; + } + // Clear the persistent information of the removed endpoint + nvs_handle_t handle; + char namespace_name[16] = {0}; + snprintf(namespace_name, 16, "bridge_ep_%X", endpoint_id); + err = nvs_open_from_partition(CONFIG_ESP_MATTER_BRIDGE_INFO_PART_NAME, namespace_name, NVS_READWRITE, &handle); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Error opening partition %s namespace %s. Err: %d", CONFIG_ESP_MATTER_BRIDGE_INFO_PART_NAME, + namespace_name, err); + return err; + } + err = nvs_erase_all(handle); + nvs_close(handle); + return err; +} + +esp_err_t set_device_type(device_t *bridged_device, uint32_t device_type_id) +{ + if (!bridged_device) { + ESP_LOGE(TAG, "bridged_device cannot be NULL"); + return ESP_ERR_INVALID_ARG; + } + switch (device_type_id) { + case ESP_MATTER_ON_OFF_LIGHT_DEVICE_TYPE_ID: { + on_off_light::config_t on_off_light_conf; + bridged_device->endpoint = on_off_light::add(bridged_device->endpoint, &on_off_light_conf); + break; + } + case ESP_MATTER_DIMMABLE_LIGHT_DEVICE_TYPE_ID: { + dimmable_light::config_t dimmable_light_conf; + bridged_device->endpoint = dimmable_light::add(bridged_device->endpoint, &dimmable_light_conf); + break; + } + case ESP_MATTER_COLOR_TEMPERATURE_LIGHT_DEVICE_TYPE_ID: { + color_temperature_light::config_t color_temperature_light_conf; + bridged_device->endpoint = + color_temperature_light::add(bridged_device->endpoint, &color_temperature_light_conf); + break; + } + case ESP_MATTER_EXTENDED_COLOR_LIGHT_DEVICE_TYPE_ID: { + extended_color_light::config_t extended_color_light_conf; + bridged_device->endpoint = extended_color_light::add(bridged_device->endpoint, &extended_color_light_conf); + break; + } + default: { + ESP_LOGE(TAG, "Unsupported bridged matter device type"); + return ESP_ERR_INVALID_ARG; + } + } + return bridged_device->endpoint ? ESP_OK : ESP_FAIL; +} + +static bool parent_endpoint_is_valid(node_t *node, uint16_t parent_endpoint_id) +{ + if (!node) { + ESP_LOGE(TAG, "Node cannot be NULL"); + return false; + } 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; + if (!parent_endpoint) { + ESP_LOGE(TAG, "Parent endpoint cannot be NULL"); + return false; } 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 (device_type_ids_ptr == NULL || device_type_count == 0) { + ESP_LOGE(TAG, "Device type id array cannot be NULL"); + return false; + } + for (uint8_t i = 0; i < device_type_count; ++i) { + if (device_type_ids_ptr[i] == esp_matter::endpoint::aggregator::get_device_type_id()) { + return true; } - 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"); + } + ESP_LOGE(TAG, "The device types of the parent endpoint must include aggregator"); + return false; +} + +device_t *create_device(node_t *node, uint16_t parent_endpoint_id, uint32_t device_type_id) +{ + // Check whether the parent endpoint is valid + if (!parent_endpoint_is_valid(node, parent_endpoint_id)) { + ESP_LOGE(TAG, "Parent endpoint is invalid"); return NULL; } - esp_matter_bridge_device_t *dev = (esp_matter_bridge_device_t *)calloc(1, sizeof(esp_matter_bridge_device_t)); + // Create bridged device + device_t *dev = (device_t *)calloc(1, sizeof(device_t)); dev->node = node; - dev->parent_endpoint_id = parent_endpoint_id; + dev->persistent_info.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); + dev->endpoint = + bridged_node::create(node, &bridged_node_config, ENDPOINT_FLAG_DESTROYABLE | ENDPOINT_FLAG_BRIDGE, NULL); if (!(dev->endpoint)) { ESP_LOGE(TAG, "Could not create esp_matter endpoint for bridged device"); free(dev); return NULL; } + if (set_device_type(dev, device_type_id) != ESP_OK) { + ESP_LOGE(TAG, "Failed to add the device type for the bridged device"); + remove_device(dev); + return NULL; + } + + // Store the persistent information + dev->persistent_info.device_endpoint_id = esp_matter::endpoint::get_id(dev->endpoint); + dev->persistent_info.device_type_id = device_type_id; + if (store_device_persistent_info(dev) != ESP_OK) { + ESP_LOGE(TAG, "Failed to store the persistent info for the bridged device"); + remove_device(dev); + return NULL; + } + + // Store the endpoint_id in endpoint_id_array + size_t idx; + for (idx = 0; idx < MAX_BRIDGED_DEVICE_COUNT; ++idx) { + if (bridged_endpoint_id_array[idx] == chip::kInvalidEndpointId) { + bridged_endpoint_id_array[idx] = dev->persistent_info.device_endpoint_id; + break; + } + } + if (idx == MAX_BRIDGED_DEVICE_COUNT) { + ESP_LOGE(TAG, "Endpoints are used up"); + remove_device(dev); + return NULL; + } + store_bridged_endpoint_ids(); return dev; } -esp_err_t esp_matter_bridge_remove_device(esp_matter_bridge_device_t *bridged_device) +device_t *resume_device(node_t *node, uint16_t device_endpoint_id) +{ + esp_err_t err = ESP_OK; + device_persistent_info_t persistent_info; + err = read_device_persistent_info(&persistent_info, device_endpoint_id); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Failed to read the persistent info for the resumed device"); + return NULL; + } + if (!parent_endpoint_is_valid(node, persistent_info.parent_endpoint_id)) { + ESP_LOGE(TAG, "Parent endpoint is invalid"); + return NULL; + } + device_t *dev = (device_t *)calloc(1, sizeof(device_t)); + dev->node = node; + dev->persistent_info = persistent_info; + bridged_node::config_t bridged_node_config; + dev->endpoint = bridged_node::resume(node, &bridged_node_config, ENDPOINT_FLAG_DESTROYABLE | ENDPOINT_FLAG_BRIDGE, + device_endpoint_id, NULL); + if (!(dev->endpoint)) { + ESP_LOGE(TAG, "Could not resume esp_matter endpoint for bridged device"); + free(dev); + erase_bridged_device_info(device_endpoint_id); + return NULL; + } + if (set_device_type(dev, persistent_info.device_type_id) != ESP_OK) { + ESP_LOGE(TAG, "Failed to add the device type for the bridged device"); + remove_device(dev); + return NULL; + } + return dev; +} + +esp_err_t remove_device(device_t *bridged_device) { if (!bridged_device) { return ESP_ERR_INVALID_ARG; } + erase_bridged_device_info(bridged_device->persistent_info.device_endpoint_id); esp_err_t error = endpoint::destroy(bridged_device->node, bridged_device->endpoint); if (error != ESP_OK) { ESP_LOGE(TAG, "Failed to delete bridged endpoint"); @@ -75,3 +315,54 @@ esp_err_t esp_matter_bridge_remove_device(esp_matter_bridge_device_t *bridged_de free(bridged_device); return error; } + +esp_err_t initialize(node_t *node) +{ + if (!node) { + ESP_LOGE(TAG, "node could not be NULL"); + return ESP_ERR_INVALID_ARG; + } + + esp_err_t err = nvs_flash_init_partition(CONFIG_ESP_MATTER_BRIDGE_INFO_PART_NAME); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Failed to initialize the bridge info partition"); + return err; + } + // Read the bridged endpoint array + err = read_bridged_endpoint_ids(); + if (err == ESP_ERR_NVS_NOT_FOUND) { + ESP_LOGI(TAG, "The bridged endpoint id array is not found in partition %s, Try to initialize it", + CONFIG_ESP_MATTER_BRIDGE_INFO_PART_NAME); + for (size_t idx = 0; idx < MAX_BRIDGED_DEVICE_COUNT; ++idx) { + bridged_endpoint_id_array[idx] = chip::kInvalidEndpointId; + } + if (store_bridged_endpoint_ids() != ESP_OK) { + ESP_LOGE(TAG, "Failed to store the initialized endpoint id array"); + return err; + } + return ESP_OK; + } else if (err != ESP_OK) { + ESP_LOGE(TAG, "Failed to read the bridged endpoint id array"); + } + return err; +} + +// TODO: Add a factory_reset_cb_register so that when we call esp_matter::factory_reset, we can erase other namespaces/partitions. +esp_err_t factory_reset() +{ + if (read_bridged_endpoint_ids() != ESP_OK) { + ESP_LOGE(TAG, "Failed to read the endpoint id array"); + } + + for (size_t idx = 0; idx < MAX_BRIDGED_DEVICE_COUNT; ++idx) { + if (bridged_endpoint_id_array[idx] != chip::kInvalidEndpointId) { + erase_bridged_device_info(bridged_endpoint_id_array[idx]); + bridged_endpoint_id_array[idx] = chip::kInvalidEndpointId; + } + } + return store_bridged_endpoint_ids(); +} + +} // namespace esp_matter_bridge + +#endif // MAX_BRIDGED_DEVICE_COUNT > 0 diff --git a/components/esp_matter_bridge/esp_matter_bridge.h b/components/esp_matter_bridge/esp_matter_bridge.h index fe8a03ba1..28bc68e60 100644 --- a/components/esp_matter_bridge/esp_matter_bridge.h +++ b/components/esp_matter_bridge/esp_matter_bridge.h @@ -18,15 +18,37 @@ #include #include -#define MAX_BRIDGED_DEVICE_COUNT CHIP_DEVICE_CONFIG_DYNAMIC_ENDPOINT_COUNT - 1 - CONFIG_ESP_MATTER_AGGREGATOR_ENDPOINT_COUNT +#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 { +namespace esp_matter_bridge { + +typedef struct device_persistent_info { + uint16_t parent_endpoint_id; + uint16_t device_endpoint_id; + uint32_t device_type_id; +} device_persistent_info_t; + +typedef struct device { esp_matter::node_t *node; esp_matter::endpoint_t *endpoint; - uint16_t parent_endpoint_id; -} esp_matter_bridge_device_t; + device_persistent_info_t persistent_info; +} device_t; -esp_matter_bridge_device_t *esp_matter_bridge_create_device(esp_matter::node_t *node, uint16_t parent_endpoint_id); +esp_err_t get_bridged_endpoint_ids(uint16_t *matter_endpoint_id_array); -esp_err_t esp_matter_bridge_remove_device(esp_matter_bridge_device_t *bridged_device); +esp_err_t erase_bridged_device_info(uint16_t matter_endpoint_id); + +device_t *create_device(esp_matter::node_t *node, uint16_t parent_endpoint_id, uint32_t device_type_id); + +device_t *resume_device(esp_matter::node_t *node, uint16_t device_endpoint_id); + +esp_err_t set_device_type(device_t *bridged_device, uint32_t device_type_id); + +esp_err_t remove_device(device_t *bridged_device); + +esp_err_t initialize(esp_matter::node_t *node); + +esp_err_t factory_reset(); +} // namespace esp_matter_bridge diff --git a/examples/blemesh_bridge/main/app_main.cpp b/examples/blemesh_bridge/main/app_main.cpp index 867d66e80..168dfee53 100644 --- a/examples/blemesh_bridge/main/app_main.cpp +++ b/examples/blemesh_bridge/main/app_main.cpp @@ -102,6 +102,11 @@ extern "C" void app_main() ESP_LOGE(TAG, "Matter start failed: %d", err); } + err = app_bridge_initialize(node); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Failed to resume the bridged endpoints: %d", err); + } + #if CONFIG_ENABLE_CHIP_SHELL esp_matter::console::diagnostics_register_commands(); esp_matter::console::init(); diff --git a/examples/blemesh_bridge/main/blemesh_bridge.cpp b/examples/blemesh_bridge/main/blemesh_bridge.cpp index cf971dd61..9adbd4bdf 100644 --- a/examples/blemesh_bridge/main/blemesh_bridge.cpp +++ b/examples/blemesh_bridge/main/blemesh_bridge.cpp @@ -43,24 +43,6 @@ static uint8_t expect_composition[] = {/* CID */0XE5, 0x02, /* PID */0x00, 0x00, /* NumS */0x02, /* NumV */0x00, /* Config Server Model */0x00, 0x00, /* Generic OnOff Server Model */0x00, 0x10}; -static esp_err_t blemesh_bridge_init_bridged_onoff_light(esp_matter_bridge_device_t *dev) -{ - if (!dev) { - ESP_LOGE(TAG, "Invalid bridge device to be initialized"); - return ESP_ERR_INVALID_ARG; - } - on_off::config_t config; - on_off::create(dev->endpoint, &config, CLUSTER_MASK_SERVER, ESP_MATTER_NONE_FEATURE_ID); - endpoint::add_device_type(dev->endpoint, endpoint::on_off_light::get_device_type_id(), - endpoint::on_off_light::get_device_type_version()); - 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; - } - return ESP_OK; -} - esp_err_t blemesh_bridge_match_bridged_onoff_light(uint8_t *composition_data, uint16_t blemesh_addr) { /** Compare Composition Data Page 0 to find expected device */ @@ -73,10 +55,10 @@ esp_err_t blemesh_bridge_match_bridged_onoff_light(uint8_t *composition_data, ui app_bridge_get_matter_endpointid_by_blemesh_addr(blemesh_addr)); } else { app_bridged_device_t *bridged_device = - app_bridge_create_bridged_device(node, aggregator_endpoint_id, ESP_MATTER_BRIDGED_DEVICE_TYPE_BLEMESH, + app_bridge_create_bridged_device(node, aggregator_endpoint_id, ESP_MATTER_ON_OFF_LIGHT_DEVICE_TYPE_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, app_bridge_get_matter_endpointid_by_blemesh_addr(blemesh_addr)); } diff --git a/examples/blemesh_bridge/partitions.csv b/examples/blemesh_bridge/partitions.csv index c590e73c3..9945223f7 100644 --- a/examples/blemesh_bridge/partitions.csv +++ b/examples/blemesh_bridge/partitions.csv @@ -1,9 +1,9 @@ # Name, Type, SubType, Offset, Size, Flags # Note: Firmware partition offset needs to be 64K aligned, initial 36K (9 sectors) are reserved for bootloader and partition table sec_cert, 0x3F, ,0xd000, 0x3000, , # Never mark this as an encrypted partition -nvs, data, nvs, 0x10000, 0x6000, +nvs, data, nvs, 0x10000, 0x8000, otadata, data, ota, , 0x2000 phy_init, data, phy, , 0x1000, -ota_0, app, ota_0, 0x20000, 0x1D0000, +ota_0, app, ota_0, , 0x1D0000, ota_1, app, ota_1, , 0x1D0000, fctry, data, nvs, , 0x6000, diff --git a/examples/common/app_bridge/app_bridged_device.cpp b/examples/common/app_bridge/app_bridged_device.cpp index 74a8ea3ab..4f1385c72 100644 --- a/examples/common/app_bridge/app_bridged_device.cpp +++ b/examples/common/app_bridge/app_bridged_device.cpp @@ -14,16 +14,87 @@ #include #include +#include #include #include +// The bridge app can be used only when MAX_BRIDGED_DEVICE_COUNT > 0 +#if defined(MAX_BRIDGED_DEVICE_COUNT) && MAX_BRIDGED_DEVICE_COUNT > 0 +#define APP_BRIDGE_BRIDGED_DEVICE_ADDR_KEY "dev_addr" +#define APP_BRIDGE_BRIDGED_DEVICE_TYPE_KEY "dev_type" + using namespace esp_matter; static const char *TAG = "app_bridged_device"; static app_bridged_device_t *g_bridged_device_list = NULL; static uint8_t g_current_bridged_device_count = 0; +/** Persistent Bridged Device Info **/ + +static esp_err_t app_bridge_store_bridged_device_info(app_bridged_device_t *bridged_device) +{ + esp_err_t err = ESP_OK; + if (!bridged_device) { + ESP_LOGE(TAG, "bridged device cannot be NULL"); + return ESP_ERR_INVALID_ARG; + } + nvs_handle_t handle; + char namespace_name[16] = {0}; + snprintf(namespace_name, 16, "bridge_ep_%X", bridged_device->dev->persistent_info.device_endpoint_id); + err = nvs_open_from_partition(CONFIG_ESP_MATTER_BRIDGE_INFO_PART_NAME, namespace_name, NVS_READWRITE, &handle); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Error opening partition %s namespace %s. Err: %d", CONFIG_ESP_MATTER_BRIDGE_INFO_PART_NAME, + namespace_name, err); + return err; + } + err = nvs_set_blob(handle, APP_BRIDGE_BRIDGED_DEVICE_ADDR_KEY, &bridged_device->dev_addr, + sizeof(app_bridged_device_address_t)); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Error storing the device address"); + } + err = nvs_set_blob(handle, APP_BRIDGE_BRIDGED_DEVICE_TYPE_KEY, &bridged_device->dev_type, + sizeof(app_bridged_device_type_t)); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Error storing the device type"); + } + nvs_commit(handle); + nvs_close(handle); + return err; +} + +static esp_err_t app_bridge_read_bridged_device_info(app_bridged_device_type_t *device_type, + app_bridged_device_address_t *device_addr, + uint16_t matter_endpoint_id) +{ + esp_err_t err = ESP_OK; + if (!device_type || !device_addr) { + ESP_LOGE(TAG, "device_type or device_addr cannot be NULL"); + return ESP_ERR_INVALID_ARG; + } + nvs_handle_t handle; + char namespace_name[16] = {0}; + snprintf(namespace_name, 16, "bridge_ep_%X", matter_endpoint_id); + err = nvs_open_from_partition(CONFIG_ESP_MATTER_BRIDGE_INFO_PART_NAME, namespace_name, NVS_READONLY, &handle); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Error opening partition %s namespace %s. Err: %d", CONFIG_ESP_MATTER_BRIDGE_INFO_PART_NAME, + namespace_name, err); + return err; + } + size_t len = sizeof(app_bridged_device_address_t); + err = nvs_get_blob(handle, APP_BRIDGE_BRIDGED_DEVICE_ADDR_KEY, device_addr, &len); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Error reading the device address"); + } + len = sizeof(app_bridged_device_type_t); + err = nvs_get_blob(handle, APP_BRIDGE_BRIDGED_DEVICE_TYPE_KEY, device_type, &len); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Error reading the device type"); + } + nvs_close(handle); + return err; +} + /** Bridged Device's Address APIs */ app_bridged_device_address_t app_bridge_zigbee_address(uint8_t zigbee_endpointid, uint16_t zigbee_shortaddr) { @@ -46,37 +117,81 @@ 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, uint16_t parent_endpoint_id, - app_bridged_device_type_t bridged_device_type, app_bridged_device_address_t bridged_device_address) + uint32_t matter_device_type_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) { ESP_LOGE(TAG, "The device list is full, Could not add a zigbee bridged device"); 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, parent_endpoint_id); + new_dev->dev = esp_matter_bridge::create_device(node, parent_endpoint_id, matter_device_type_id); if (!(new_dev->dev)) { - ESP_LOGE(TAG, "Failed to create the basic bridged device"); + ESP_LOGE(TAG, "Failed to create the bridged device"); free(new_dev); return NULL; } + new_dev->dev_type = bridged_device_type; new_dev->dev_addr = bridged_device_address; new_dev->next = g_bridged_device_list; g_bridged_device_list = new_dev; g_current_bridged_device_count++; + + if (ESP_OK != app_bridge_store_bridged_device_info(new_dev)) { + ESP_LOGW(TAG, "Failed to store the bridged device information"); + } + + // Enable the created endpoint + esp_matter::endpoint::enable(new_dev->dev->endpoint, new_dev->dev->persistent_info.parent_endpoint_id); + return new_dev; } -app_bridged_device_t *app_bridge_get_device_by_matter_endpointid(uint16_t matter_endpointid) +esp_err_t app_bridge_initialize(node_t *node) { - app_bridged_device_t *current_dev = g_bridged_device_list; - while (current_dev) { - if (current_dev->dev && (esp_matter::endpoint::get_id(current_dev->dev->endpoint) == matter_endpointid)) { - return current_dev; - } - current_dev = current_dev->next; + esp_err_t err = esp_matter_bridge::initialize(node); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Failed to initialize the esp_matter_bridge"); + return err; } - return NULL; + + uint16_t matter_endpoint_id_array[MAX_BRIDGED_DEVICE_COUNT]; + esp_matter_bridge::get_bridged_endpoint_ids(matter_endpoint_id_array); + for (size_t idx = 0; idx < MAX_BRIDGED_DEVICE_COUNT; ++idx) { + if (matter_endpoint_id_array[idx] != chip::kInvalidEndpointId) { + app_bridged_device_type_t device_type; + app_bridged_device_address_t device_addr; + err = app_bridge_read_bridged_device_info(&device_type, &device_addr, matter_endpoint_id_array[idx]); + if (err != ESP_OK) { + ESP_LOGE(TAG, + "Failed to read the app_bridged_device_type and app_bridged_device_address for endpoint %d", + matter_endpoint_id_array[idx]); + continue; + } + app_bridged_device_t *new_dev = (app_bridged_device_t *)calloc(1, sizeof(app_bridged_device_t)); + if (!new_dev) { + ESP_LOGE(TAG, "Failed to alloc memory for the resumed bridged device"); + continue; + } + new_dev->dev = esp_matter_bridge::resume_device(node, matter_endpoint_id_array[idx]); + if (!(new_dev->dev)) { + ESP_LOGE(TAG, "Failed to resume the bridged device"); + free(new_dev); + continue; + } + new_dev->dev_type = device_type; + new_dev->dev_addr = device_addr; + new_dev->next = g_bridged_device_list; + g_bridged_device_list = new_dev; + g_current_bridged_device_count++; + + //Enable the resumed endpoint + esp_matter::endpoint::enable(new_dev->dev->endpoint, new_dev->dev->persistent_info.parent_endpoint_id); + } + } + return ESP_OK; } esp_err_t app_bridge_remove_device(app_bridged_device_t *bridged_device) @@ -87,7 +202,7 @@ esp_err_t app_bridge_remove_device(app_bridged_device_t *bridged_device) return ESP_ERR_INVALID_ARG; } if (g_bridged_device_list == bridged_device) { - // the delete bridged device is on the head of device list + // The delete bridged device is on the head of device list g_bridged_device_list = bridged_device->next; } else { current_dev = g_bridged_device_list; @@ -103,21 +218,36 @@ esp_err_t app_bridge_remove_device(app_bridged_device_t *bridged_device) return ESP_ERR_NOT_FOUND; } } - error = esp_matter_bridge_remove_device(bridged_device->dev); + + // Remove the bridged device from the node. + error = esp_matter_bridge::remove_device(bridged_device->dev); if (error != ESP_OK) { - ESP_LOGE(TAG, "Failed to delete basic bridged devie"); + ESP_LOGE(TAG, "Failed to delete bridged device"); } free(bridged_device); + return error; } /** ZigBee Device APIs */ +app_bridged_device_t *app_bridge_get_device_by_matter_endpointid(uint16_t matter_endpointid) +{ + app_bridged_device_t *current_dev = g_bridged_device_list; + while (current_dev) { + if (current_dev->dev && (esp_matter::endpoint::get_id(current_dev->dev->endpoint) == matter_endpointid)) { + return current_dev; + } + current_dev = current_dev->next; + } + return NULL; +} + app_bridged_device_t *app_bridge_get_device_by_zigbee_shortaddr(uint16_t zigbee_shortaddr) { 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_addr.zigbee_shortaddr == zigbee_shortaddr) { + 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; } current_dev = current_dev->next; @@ -129,8 +259,8 @@ uint16_t app_bridge_get_matter_endpointid_by_zigbee_shortaddr(uint16_t zigbee_sh { 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_addr.zigbee_shortaddr == zigbee_shortaddr) { + if (current_dev->dev_type == ESP_MATTER_BRIDGED_DEVICE_TYPE_ZIGBEE && current_dev->dev && + current_dev->dev_addr.zigbee_shortaddr == zigbee_shortaddr) { return esp_matter::endpoint::get_id(current_dev->dev->endpoint); } current_dev = current_dev->next; @@ -142,8 +272,8 @@ 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 - && (esp_matter::endpoint::get_id(current_dev->dev->endpoint) == matter_endpointid)) { + if ((current_dev->dev_type == ESP_MATTER_BRIDGED_DEVICE_TYPE_ZIGBEE) && current_dev->dev && + (esp_matter::endpoint::get_id(current_dev->dev->endpoint) == matter_endpointid)) { return current_dev->dev_addr.zigbee_shortaddr; } current_dev = current_dev->next; @@ -156,8 +286,8 @@ app_bridged_device_t *app_bridge_get_device_by_blemesh_addr(uint16_t blemesh_add { 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_addr.blemesh_addr == blemesh_addr)) { + 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; } current_dev = current_dev->next; @@ -169,8 +299,8 @@ uint16_t app_bridge_get_matter_endpointid_by_blemesh_addr(uint16_t blemesh_addr) { 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_addr.blemesh_addr == blemesh_addr)) { + if ((current_dev->dev_type == ESP_MATTER_BRIDGED_DEVICE_TYPE_BLEMESH) && current_dev->dev && + (current_dev->dev_addr.blemesh_addr == blemesh_addr)) { return esp_matter::endpoint::get_id(current_dev->dev->endpoint); } current_dev = current_dev->next; @@ -182,11 +312,12 @@ 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 - && (esp_matter::endpoint::get_id(current_dev->dev->endpoint) == matter_endpointid)) { + if ((current_dev->dev_type == ESP_MATTER_BRIDGED_DEVICE_TYPE_BLEMESH) && current_dev->dev && + (esp_matter::endpoint::get_id(current_dev->dev->endpoint) == matter_endpointid)) { return current_dev->dev_addr.blemesh_addr; } current_dev = current_dev->next; } return 0xFFFF; } +#endif diff --git a/examples/common/app_bridge/app_bridged_device.h b/examples/common/app_bridge/app_bridged_device.h index 9e80bc8d9..cddcac5d4 100644 --- a/examples/common/app_bridge/app_bridged_device.h +++ b/examples/common/app_bridge/app_bridged_device.h @@ -15,7 +15,6 @@ #pragma once #include - #include using esp_matter::node_t; @@ -44,7 +43,7 @@ typedef union { /* Bridged Device */ typedef struct app_bridged_device { /** Bridged Device */ - esp_matter_bridge_device_t *dev; + esp_matter_bridge::device_t *dev; /** Type of Bridged Device */ app_bridged_device_type_t dev_type; /** Address of Bridged Device */ @@ -60,12 +59,16 @@ 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, uint16_t parent_endpoint_id, - app_bridged_device_type_t bridged_device_type, app_bridged_device_address_t bridged_device_address); + uint32_t matter_device_type_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); +esp_err_t app_bridge_initialize(node_t *node); esp_err_t app_bridge_remove_device(app_bridged_device_t *bridged_device); +app_bridged_device_t *app_bridge_get_device_by_matter_endpointid(uint16_t matter_endpointid); + /** ZigBee Device APIs */ app_bridged_device_t *app_bridge_get_device_by_zigbee_shortaddr(uint16_t zigbee_shortaddr); diff --git a/examples/zigbee_bridge/main/app_main.cpp b/examples/zigbee_bridge/main/app_main.cpp index 270849637..a035c69c6 100644 --- a/examples/zigbee_bridge/main/app_main.cpp +++ b/examples/zigbee_bridge/main/app_main.cpp @@ -101,6 +101,11 @@ extern "C" void app_main() ESP_LOGE(TAG, "Matter start failed: %d", err); } + err = app_bridge_initialize(node); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Failed to resume the bridged endpoints: %d", err); + } + #if CONFIG_ENABLE_CHIP_SHELL esp_matter::console::diagnostics_register_commands(); esp_matter::console::init(); diff --git a/examples/zigbee_bridge/main/zigbee_bridge.cpp b/examples/zigbee_bridge/main/zigbee_bridge.cpp index 4f943e5db..2bc7bc54f 100644 --- a/examples/zigbee_bridge/main/zigbee_bridge.cpp +++ b/examples/zigbee_bridge/main/zigbee_bridge.cpp @@ -22,24 +22,6 @@ 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) { - ESP_LOGE(TAG, "Invalid bridge device to be initialized"); - return ESP_ERR_INVALID_ARG; - } - - on_off::config_t config; - on_off::create(dev->endpoint, &config, CLUSTER_MASK_SERVER, ESP_MATTER_NONE_FEATURE_ID); - endpoint::add_device_type(dev->endpoint, endpoint::on_off_light::get_device_type_id(), - endpoint::on_off_light::get_device_type_version()); - 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; - } - return ESP_OK; -} void zigbee_bridge_find_bridged_on_off_light_cb(zb_uint8_t zdo_status, zb_uint16_t addr, zb_uint8_t endpoint) { ESP_LOGI(TAG, "on_off_light found: address:0x%x, endpoint:%d, response_status:%d", addr, endpoint, zdo_status); @@ -54,16 +36,13 @@ void zigbee_bridge_find_bridged_on_off_light_cb(zb_uint8_t zdo_status, zb_uint16 app_bridge_get_matter_endpointid_by_zigbee_shortaddr(addr)); } else { app_bridged_device_t *bridged_device = - app_bridge_create_bridged_device(node, aggregator_endpoint_id, ESP_MATTER_BRIDGED_DEVICE_TYPE_ZIGBEE, + app_bridge_create_bridged_device(node, aggregator_endpoint_id, ESP_MATTER_ON_OFF_LIGHT_DEVICE_TYPE_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; } - if (zigbee_bridge_init_bridged_onoff_light(bridged_device->dev) != ESP_OK) { - ESP_LOGE(TAG, "Failed to initialize the bridged node"); - return; - } ESP_LOGI(TAG, "Create/Update bridged node for 0x%04x zigbee device on endpoint %d", addr, app_bridge_get_matter_endpointid_by_zigbee_shortaddr(addr)); } diff --git a/examples/zigbee_bridge/partitions.csv b/examples/zigbee_bridge/partitions.csv index 61438d2ee..d0b51efb4 100644 --- a/examples/zigbee_bridge/partitions.csv +++ b/examples/zigbee_bridge/partitions.csv @@ -1,10 +1,10 @@ # Name, Type, SubType, Offset, Size, Flags # Note: Firmware partition offset needs to be 64K aligned, initial 36K (9 sectors) are reserved for bootloader and partition table sec_cert, 0x3F, ,0xd000, 0x3000, , # Never mark this as an encrypted partition -nvs, data, nvs, 0x10000, 0x6000, +nvs, data, nvs, 0x10000, 0x8000, otadata, data, ota, , 0x2000 phy_init, data, phy, , 0x1000, -ota_0, app, ota_0, 0x20000, 0x1D0000, +ota_0, app, ota_0, , 0x1D0000, ota_1, app, ota_1, , 0x1D0000, fctry, data, nvs, , 0x6000, zb_storage, data, fat, , 0x20000