Merge branch 'endpoint_resume' into 'main'

esp_matter: Add endpoint resume logic for bridged_node endpoint

See merge request app-frameworks/esp-matter!206
This commit is contained in:
Shu Chen
2022-11-09 20:05:24 +08:00
15 changed files with 871 additions and 187 deletions
+128 -13
View File
@@ -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) {
+15
View File
@@ -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
+130 -68
View File
@@ -16,53 +16,6 @@
#include <esp_matter.h>
#include <esp_matter_endpoint.h>
/* 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());
+69 -1
View File
@@ -18,6 +18,53 @@
#include <esp_matter_core.h>
#include <esp_matter_identify.h>
/* 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 */
+6
View File
@@ -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
@@ -14,60 +14,300 @@
#include <esp_log.h>
#include <esp_matter.h>
#include <nvs.h>
#include <nvs_flash.h>
#include <string.h>
#include <esp_matter_bridge.h>
#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
@@ -18,15 +18,37 @@
#include <esp_err.h>
#include <esp_matter_core.h>
#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
@@ -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();
@@ -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));
}
+2 -2
View File
@@ -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,
1 # Name, Type, SubType, Offset, Size, Flags
2 # Note: Firmware partition offset needs to be 64K aligned, initial 36K (9 sectors) are reserved for bootloader and partition table
3 sec_cert, 0x3F, ,0xd000, 0x3000, , # Never mark this as an encrypted partition
4 nvs, data, nvs, 0x10000, 0x6000, nvs, data, nvs, 0x10000, 0x8000,
5 otadata, data, ota, , 0x2000
6 phy_init, data, phy, , 0x1000,
7 ota_0, app, ota_0, 0x20000, 0x1D0000, ota_0, app, ota_0, , 0x1D0000,
8 ota_1, app, ota_1, , 0x1D0000,
9 fctry, data, nvs, , 0x6000,
+157 -26
View File
@@ -14,16 +14,87 @@
#include <esp_log.h>
#include <esp_matter.h>
#include <nvs.h>
#include <string.h>
#include <app_bridged_device.h>
// 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
@@ -15,7 +15,6 @@
#pragma once
#include <sdkconfig.h>
#include <esp_matter_bridge.h>
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);
+5
View File
@@ -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();
+2 -23
View File
@@ -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));
}
+2 -2
View File
@@ -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
1 # Name, Type, SubType, Offset, Size, Flags
2 # Note: Firmware partition offset needs to be 64K aligned, initial 36K (9 sectors) are reserved for bootloader and partition table
3 sec_cert, 0x3F, ,0xd000, 0x3000, , # Never mark this as an encrypted partition
4 nvs, data, nvs, 0x10000, 0x6000, nvs, data, nvs, 0x10000, 0x8000,
5 otadata, data, ota, , 0x2000
6 phy_init, data, phy, , 0x1000,
7 ota_0, app, ota_0, 0x20000, 0x1D0000, ota_0, app, ota_0, , 0x1D0000,
8 ota_1, app, ota_1, , 0x1D0000,
9 fctry, data, nvs, , 0x6000,
10 zb_storage, data, fat, , 0x20000