From 2f83990a6d303eea4225af127acd16357dab8479 Mon Sep 17 00:00:00 2001 From: WanqQixiang Date: Thu, 30 Nov 2023 11:30:21 +0800 Subject: [PATCH] controller: Add multiple paths subscription and read --- .../esp_matter_controller_console.cpp | 127 ++++++++++++++--- .../esp_matter_controller_read_command.cpp | 132 +++++++++++++----- .../esp_matter_controller_read_command.h | 58 +++++--- ...sp_matter_controller_subscribe_command.cpp | 118 ++++++++++++---- .../esp_matter_controller_subscribe_command.h | 65 ++++++--- .../esp_matter_controller_utils.h | 7 +- 6 files changed, 391 insertions(+), 116 deletions(-) diff --git a/components/esp_matter_controller/esp_matter_controller_console.cpp b/components/esp_matter_controller/esp_matter_controller_console.cpp index 1c6783e85..3c2c8cbe6 100644 --- a/components/esp_matter_controller/esp_matter_controller_console.cpp +++ b/components/esp_matter_controller/esp_matter_controller_console.cpp @@ -15,6 +15,7 @@ * limitations under the License. */ +#include #include #include #include @@ -35,6 +36,7 @@ #include using chip::NodeId; +using chip::Platform::ScopedMemoryBufferWithSize; using chip::Inet::IPAddress; using chip::Transport::PeerAddress; using esp_matter::controller::command_data_t; @@ -43,6 +45,86 @@ const static char *TAG = "controller_console"; namespace esp_matter { +static size_t get_array_size(const char *str) +{ + if (!str) { + return 0; + } + size_t ret = 1; + for (size_t i = 0; i < strlen(str); ++ i) { + if (str[i] == ',') { + ret++; + } + } + return ret; +} + +static esp_err_t string_to_uint32_array(const char *str, ScopedMemoryBufferWithSize &uint32_array) +{ + size_t array_len = get_array_size(str); + if (array_len == 0) { + return ESP_ERR_INVALID_ARG; + } + uint32_array.Calloc(array_len); + if (!uint32_array.Get()) { + return ESP_ERR_NO_MEM; + } + char number[11]; // max(strlen("0xFFFFFFFF"), strlen("4294967295")) + 1 + const char *next_number_start = str; + char *next_number_end = NULL; + size_t next_number_len = 0; + for (size_t i = 0; i < array_len; ++i) { + next_number_end = strchr(next_number_start, ','); + if (next_number_end > next_number_start) { + next_number_len = std::min((size_t)(next_number_end - next_number_start), sizeof(number) - 1); + } else if (i == array_len - 1) { + next_number_len = strnlen(next_number_start, sizeof(number) - 1); + } else { + return ESP_ERR_INVALID_ARG; + } + strncpy(number, next_number_start, next_number_len); + number[next_number_len] = 0; + uint32_array[i] = string_to_uint32(number); + if (next_number_end > next_number_start) { + next_number_start = next_number_end + 1; + } + } + return ESP_OK; +} + +esp_err_t string_to_uint16_array(const char *str, ScopedMemoryBufferWithSize &uint16_array) +{ + size_t array_len = get_array_size(str); + if (array_len == 0) { + return ESP_ERR_INVALID_ARG; + } + uint16_array.Calloc(array_len); + if (!uint16_array.Get()) { + return ESP_ERR_NO_MEM; + } + char number[7]; // max(strlen(0xFFFF), strlen(65535)) + 1 + const char *next_number_start = str; + char *next_number_end = NULL; + size_t next_number_len = 0; + for (size_t i = 0; i < array_len; ++i) { + next_number_end = strchr(next_number_start, ','); + if (next_number_end > next_number_start) { + next_number_len = std::min((size_t)(next_number_end - next_number_start), sizeof(number) - 1); + } else if (i == array_len - 1) { + next_number_len = strnlen(next_number_start, sizeof(number) - 1); + } else { + return ESP_ERR_INVALID_ARG; + } + strncpy(number, next_number_start, next_number_len); + number[next_number_len] = 0; + uint16_array[i] = string_to_uint16(number); + if (next_number_end > next_number_start) { + next_number_start = next_number_end + 1; + } + } + return ESP_OK; +} + namespace console { static engine controller_console; @@ -187,11 +269,14 @@ static esp_err_t controller_read_attr_handler(int argc, char **argv) } uint64_t node_id = string_to_uint64(argv[0]); - uint16_t endpoint_id = string_to_uint16(argv[1]); - uint32_t cluster_id = string_to_uint32(argv[2]); - uint32_t attribute_id = string_to_uint32(argv[3]); + ScopedMemoryBufferWithSize endpoint_ids; + ScopedMemoryBufferWithSize cluster_ids; + ScopedMemoryBufferWithSize attribute_ids; + ESP_RETURN_ON_ERROR(string_to_uint16_array(argv[1], endpoint_ids), TAG, "Failed to parse endpoint IDs"); + ESP_RETURN_ON_ERROR(string_to_uint32_array(argv[2], cluster_ids), TAG, "Failed to parse cluster IDs"); + ESP_RETURN_ON_ERROR(string_to_uint32_array(argv[3], attribute_ids), TAG, "Failed to parse attribute IDs"); - return controller::send_read_attr_command(node_id, endpoint_id, cluster_id, attribute_id); + return controller::send_read_attr_command(node_id, endpoint_ids, cluster_ids, attribute_ids); } static esp_err_t controller_write_attr_handler(int argc, char **argv) @@ -216,11 +301,14 @@ static esp_err_t controller_read_event_handler(int argc, char **argv) } uint64_t node_id = string_to_uint64(argv[0]); - uint16_t endpoint_id = string_to_uint16(argv[1]); - uint32_t cluster_id = string_to_uint32(argv[2]); - uint32_t event_id = string_to_uint32(argv[3]); + ScopedMemoryBufferWithSize endpoint_ids; + ScopedMemoryBufferWithSize cluster_ids; + ScopedMemoryBufferWithSize event_ids; + ESP_RETURN_ON_ERROR(string_to_uint16_array(argv[1], endpoint_ids), TAG, "Failed to parse endpoint IDs"); + ESP_RETURN_ON_ERROR(string_to_uint32_array(argv[2], cluster_ids), TAG, "Failed to parse cluster IDs"); + ESP_RETURN_ON_ERROR(string_to_uint32_array(argv[3], event_ids), TAG, "Failed to parse event IDs"); - return controller::send_read_event_command(node_id, endpoint_id, cluster_id, event_id); + return controller::send_read_event_command(node_id, endpoint_ids, cluster_ids, event_ids); } static esp_err_t controller_subscribe_attr_handler(int argc, char **argv) @@ -230,12 +318,16 @@ static esp_err_t controller_subscribe_attr_handler(int argc, char **argv) } uint64_t node_id = string_to_uint64(argv[0]); - uint16_t endpoint_id = string_to_uint16(argv[1]); - uint32_t cluster_id = string_to_uint32(argv[2]); - uint32_t attribute_id = string_to_uint32(argv[3]); + ScopedMemoryBufferWithSize endpoint_ids; + ScopedMemoryBufferWithSize cluster_ids; + ScopedMemoryBufferWithSize attribute_ids; + ESP_RETURN_ON_ERROR(string_to_uint16_array(argv[1], endpoint_ids), TAG, "Failed to parse endpoint IDs"); + ESP_RETURN_ON_ERROR(string_to_uint32_array(argv[2], cluster_ids), TAG, "Failed to parse cluster IDs"); + ESP_RETURN_ON_ERROR(string_to_uint32_array(argv[3], attribute_ids), TAG, "Failed to parse attribute IDs"); uint16_t min_interval = string_to_uint16(argv[4]); uint16_t max_interval = string_to_uint16(argv[5]); - return controller::send_subscribe_attr_command(node_id, endpoint_id, cluster_id, attribute_id, min_interval, + + return controller::send_subscribe_attr_command(node_id, endpoint_ids, cluster_ids, attribute_ids, min_interval, max_interval); } @@ -246,12 +338,15 @@ static esp_err_t controller_subscribe_event_handler(int argc, char **argv) } uint64_t node_id = string_to_uint64(argv[0]); - uint16_t endpoint_id = string_to_uint16(argv[1]); - uint32_t cluster_id = string_to_uint32(argv[2]); - uint32_t event_id = string_to_uint32(argv[3]); + ScopedMemoryBufferWithSize endpoint_ids; + ScopedMemoryBufferWithSize cluster_ids; + ScopedMemoryBufferWithSize event_ids; + ESP_RETURN_ON_ERROR(string_to_uint16_array(argv[1], endpoint_ids), TAG, "Failed to parse endpoint IDs"); + ESP_RETURN_ON_ERROR(string_to_uint32_array(argv[2], cluster_ids), TAG, "Failed to parse cluster IDs"); + ESP_RETURN_ON_ERROR(string_to_uint32_array(argv[3], event_ids), TAG, "Failed to parse event IDs"); uint16_t min_interval = string_to_uint16(argv[4]); uint16_t max_interval = string_to_uint16(argv[5]); - return controller::send_subscribe_event_command(node_id, endpoint_id, cluster_id, event_id, min_interval, + return controller::send_subscribe_event_command(node_id, endpoint_ids, cluster_ids, event_ids, min_interval, max_interval); } diff --git a/components/esp_matter_controller/esp_matter_controller_read_command.cpp b/components/esp_matter_controller/esp_matter_controller_read_command.cpp index dfa973c61..72af00157 100644 --- a/components/esp_matter_controller/esp_matter_controller_read_command.cpp +++ b/components/esp_matter_controller/esp_matter_controller_read_command.cpp @@ -40,24 +40,21 @@ void read_command::on_device_connected_fcn(void *context, ExchangeManager &excha read_command *cmd = (read_command *)context; ReadPrepareParams params(sessionHandle); - if (cmd->get_command_type() == READ_ATTRIBUTE) { - params.mpEventPathParamsList = nullptr; - params.mEventPathParamsListSize = 0; - params.mpAttributePathParamsList = &cmd->get_attr_path(); - params.mAttributePathParamsListSize = 1; - } else if (cmd->get_command_type() == READ_EVENT) { - params.mpEventPathParamsList = &cmd->get_event_path(); - params.mEventPathParamsListSize = 1; - params.mpAttributePathParamsList = nullptr; - params.mAttributePathParamsListSize = 0; + if (cmd->m_attr_paths.AllocatedSize() == 0 && cmd->m_event_paths.AllocatedSize() == 0) { + ESP_LOGE(TAG, "Cannot send the read command with NULL attribute path and NULL event path"); + chip::Platform::Delete(cmd); + return; } + params.mpAttributePathParamsList = cmd->m_attr_paths.Get(); + params.mAttributePathParamsListSize = cmd->m_attr_paths.AllocatedSize(); + params.mpEventPathParamsList = cmd->m_event_paths.Get(); + params.mEventPathParamsListSize = cmd->m_event_paths.AllocatedSize(); params.mIsFabricFiltered = 0; params.mpDataVersionFilterList = nullptr; params.mDataVersionFilterListSize = 0; - ReadClient *client = - chip::Platform::New(InteractionModelEngine::GetInstance(), &exchangeMgr, - cmd->get_buffered_read_cb(), ReadClient::InteractionType::Read); + ReadClient *client = chip::Platform::New(InteractionModelEngine::GetInstance(), &exchangeMgr, + cmd->m_buffered_read_cb, ReadClient::InteractionType::Read); if (!client) { ESP_LOGE(TAG, "Failed to alloc memory for read client"); chip::Platform::Delete(cmd); @@ -111,16 +108,14 @@ void read_command::OnAttributeData(const chip::app::ConcreteDataAttributePath &p return; } if (attribute_data_cb) { - attribute_data_cb(m_node_id, path, data); + chip::TLV::TLVReader data_cpy; + data_cpy.Init(*data); + attribute_data_cb(m_node_id, path, &data_cpy); } - else - { - error = DataModelLogger::LogAttribute(path, data); - if (CHIP_NO_ERROR != error) { + error = DataModelLogger::LogAttribute(path, data); + if (CHIP_NO_ERROR != error) { ESP_LOGE(TAG, "Response Failure: Can not decode Data"); - } } - } void read_command::OnEventData(const chip::app::EventHeader &event_header, chip::TLV::TLVReader *data, @@ -139,14 +134,15 @@ void read_command::OnEventData(const chip::app::EventHeader &event_header, chip: ESP_LOGE(TAG, "Response Failure: No Data"); return; } + if (event_data_cb) { + chip::TLV::TLVReader data_cpy; + data_cpy.Init(*data); + event_data_cb(m_node_id, event_header, &data_cpy); + } error = DataModelLogger::LogEvent(event_header, data); if (CHIP_NO_ERROR != error) { ESP_LOGE(TAG, "Response Failure: Can not decode Data"); } - - if (event_data_cb) { - event_data_cb(m_node_id, event_header, data); - } } void read_command::OnError(CHIP_ERROR error) @@ -164,34 +160,100 @@ void read_command::OnDone(ReadClient *apReadClient) { ESP_LOGI(TAG, "read done"); if (read_done_cb) { - read_done_cb(m_node_id, m_attr_path); + read_done_cb(m_node_id, m_attr_paths, m_event_paths); } chip::Platform::Delete(apReadClient); chip::Platform::Delete(this); } -esp_err_t send_read_attr_command(uint64_t node_id, uint16_t endpoint_id, uint32_t cluster_id, uint32_t attribute_id) +esp_err_t send_read_attr_command(uint64_t node_id, ScopedMemoryBufferWithSize &endpoint_ids, + ScopedMemoryBufferWithSize &cluster_ids, + ScopedMemoryBufferWithSize &attribute_ids) { - read_command *cmd = chip::Platform::New(node_id, endpoint_id, cluster_id, attribute_id, - READ_ATTRIBUTE, nullptr, nullptr, nullptr); + if (endpoint_ids.AllocatedSize() != cluster_ids.AllocatedSize() || + endpoint_ids.AllocatedSize() != attribute_ids.AllocatedSize()) { + ESP_LOGE(TAG, + "The endpoint_id array length should be the same as the cluster_ids array length" + "and the attribute_ids array length"); + return ESP_ERR_INVALID_ARG; + } + ScopedMemoryBufferWithSize attr_paths; + ScopedMemoryBufferWithSize event_paths; + attr_paths.Alloc(endpoint_ids.AllocatedSize()); + if (!attr_paths.Get()) { + ESP_LOGE(TAG, "Failed to alloc memory for attribute paths"); + return ESP_ERR_NO_MEM; + } + for (size_t i = 0; i < attr_paths.AllocatedSize(); ++i) { + attr_paths[i] = AttributePathParams(endpoint_ids[i], cluster_ids[i], attribute_ids[i]); + } + + read_command *cmd = + chip::Platform::New(node_id, std::move(attr_paths), std::move(event_paths), nullptr, nullptr, nullptr); if (!cmd) { ESP_LOGE(TAG, "Failed to alloc memory for read_command"); return ESP_ERR_NO_MEM; } - return cmd->send_command(); } +esp_err_t send_read_event_command(uint64_t node_id, ScopedMemoryBufferWithSize &endpoint_ids, + ScopedMemoryBufferWithSize &cluster_ids, + ScopedMemoryBufferWithSize &event_ids) +{ + if (endpoint_ids.AllocatedSize() != cluster_ids.AllocatedSize() || + endpoint_ids.AllocatedSize() != event_ids.AllocatedSize()) { + ESP_LOGE(TAG, + "The endpoint_id array length should be the same as the cluster_ids array length" + "and the attribute_ids array length"); + return ESP_ERR_INVALID_ARG; + } + ScopedMemoryBufferWithSize attr_paths; + ScopedMemoryBufferWithSize event_paths; + event_paths.Alloc(endpoint_ids.AllocatedSize()); + if (!event_paths.Get()) { + ESP_LOGE(TAG, "Failed to alloc memory for attribute paths"); + return ESP_ERR_NO_MEM; + } + for (size_t i = 0; i < event_paths.AllocatedSize(); ++i) { + event_paths[i] = EventPathParams(endpoint_ids[i], cluster_ids[i], event_ids[i]); + } + + read_command *cmd = + chip::Platform::New(node_id, std::move(attr_paths), std::move(event_paths), nullptr, nullptr, nullptr); + if (!cmd) { + ESP_LOGE(TAG, "Failed to alloc memory for read_command"); + return ESP_ERR_NO_MEM; + } + return cmd->send_command(); +} + +esp_err_t send_read_attr_command(uint64_t node_id, uint16_t endpoint_id, uint32_t cluster_id, uint32_t attribute_id) +{ + ScopedMemoryBufferWithSize endpoint_ids; + ScopedMemoryBufferWithSize cluster_ids; + ScopedMemoryBufferWithSize attribute_ids; + endpoint_ids.Alloc(1); + cluster_ids.Alloc(1); + attribute_ids.Alloc(1); + if (!(endpoint_ids.Get() && cluster_ids.Get() && attribute_ids.Get())) { + return ESP_ERR_NO_MEM; + } + return send_read_attr_command(node_id, endpoint_ids, cluster_ids, attribute_ids); +} + esp_err_t send_read_event_command(uint64_t node_id, uint16_t endpoint_id, uint32_t cluster_id, uint32_t event_id) { - read_command *cmd = - chip::Platform::New(node_id, endpoint_id, cluster_id, event_id, READ_EVENT, nullptr, nullptr, nullptr); - if (!cmd) { - ESP_LOGE(TAG, "Failed to alloc memory for read_command"); + ScopedMemoryBufferWithSize endpoint_ids; + ScopedMemoryBufferWithSize cluster_ids; + ScopedMemoryBufferWithSize event_ids; + endpoint_ids.Alloc(1); + cluster_ids.Alloc(1); + event_ids.Alloc(1); + if (!(endpoint_ids.Get() && cluster_ids.Get() && event_ids.Get())) { return ESP_ERR_NO_MEM; } - - return cmd->send_command(); + return send_read_event_command(node_id, endpoint_ids, cluster_ids, event_ids); } } // namespace controller diff --git a/components/esp_matter_controller/esp_matter_controller_read_command.h b/components/esp_matter_controller/esp_matter_controller_read_command.h index e8dccc770..a9bc034ab 100644 --- a/components/esp_matter_controller/esp_matter_controller_read_command.h +++ b/components/esp_matter_controller/esp_matter_controller_read_command.h @@ -18,6 +18,7 @@ #include #include #include +#include namespace esp_matter { namespace controller { @@ -29,6 +30,7 @@ using chip::app::BufferedReadCallback; using chip::app::EventPathParams; using chip::app::ReadClient; using chip::Messaging::ExchangeManager; +using chip::Platform::ScopedMemoryBufferWithSize; using esp_matter::client::peer_device_t; typedef enum { @@ -38,10 +40,25 @@ typedef enum { class read_command : public ReadClient::Callback { public: - read_command(uint64_t node_id, uint16_t endpoint_id, uint32_t cluster_id, uint32_t attribute_or_event_id, - read_command_type_t command_type, attribute_report_cb_t attribute_cb, read_done_cb_t read_cb_done, event_report_cb_t event_cb) + read_command(uint64_t node_id, ScopedMemoryBufferWithSize &&attr_paths, + ScopedMemoryBufferWithSize &&event_paths, attribute_report_cb_t attribute_cb, + read_done_cb_t read_cb_done, event_report_cb_t event_cb) + : m_node_id(node_id) + , m_buffered_read_cb(*this) + , m_attr_paths(std::move(attr_paths)) + , m_event_paths(std::move(event_paths)) + , on_device_connected_cb(on_device_connected_fcn, this) + , on_device_connection_failure_cb(on_device_connection_failure_fcn, this) + , attribute_data_cb(attribute_cb) + , read_done_cb(read_cb_done) + , event_data_cb(event_cb) + { + } + + read_command(uint64_t node_id, uint16_t endpoint_id, uint32_t cluster_id, uint32_t attribute_or_event_id, + read_command_type_t command_type, attribute_report_cb_t attribute_cb, read_done_cb_t read_cb_done, + event_report_cb_t event_cb) : m_node_id(node_id) - , m_command_type(command_type) , m_buffered_read_cb(*this) , on_device_connected_cb(on_device_connected_fcn, this) , on_device_connection_failure_cb(on_device_connection_failure_fcn, this) @@ -50,10 +67,15 @@ public: , event_data_cb(event_cb) { if (command_type == READ_ATTRIBUTE) { - m_attr_path = AttributePathParams(endpoint_id, cluster_id, attribute_or_event_id); - + m_attr_paths.Alloc(1); + if (m_attr_paths.Get()) { + m_attr_paths[0] = AttributePathParams(endpoint_id, cluster_id, attribute_or_event_id); + } } else if (command_type == READ_EVENT) { - m_event_path = EventPathParams(endpoint_id, cluster_id, attribute_or_event_id); + m_event_paths.Alloc(1); + if (m_event_paths.Get()) { + m_event_paths[0] = EventPathParams(endpoint_id, cluster_id, attribute_or_event_id); + } } } @@ -61,14 +83,6 @@ public: esp_err_t send_command(); - AttributePathParams &get_attr_path() { return m_attr_path; } - - EventPathParams &get_event_path() { return m_event_path; } - - read_command_type_t get_command_type() { return m_command_type; } - - BufferedReadCallback &get_buffered_read_cb() { return m_buffered_read_cb; } - // ReadClient Callback Interface void OnAttributeData(const chip::app::ConcreteDataAttributePath &path, chip::TLV::TLVReader *data, const chip::app::StatusIB &status) override; @@ -84,12 +98,10 @@ public: private: uint64_t m_node_id; - read_command_type_t m_command_type; - union { - AttributePathParams m_attr_path; - EventPathParams m_event_path; - }; BufferedReadCallback m_buffered_read_cb; + ScopedMemoryBufferWithSize m_attr_paths; + ScopedMemoryBufferWithSize m_event_paths; + size_t m_event_path_len; static void on_device_connected_fcn(void *context, ExchangeManager &exchangeMgr, const SessionHandle &sessionHandle); @@ -104,6 +116,14 @@ private: }; +esp_err_t send_read_attr_command(uint64_t node_id, ScopedMemoryBufferWithSize &endpoint_ids, + ScopedMemoryBufferWithSize &cluster_ids, + ScopedMemoryBufferWithSize &attribute_ids); + +esp_err_t send_read_event_command(uint64_t node_id, ScopedMemoryBufferWithSize &endpoint_ids, + ScopedMemoryBufferWithSize &cluster_ids, + ScopedMemoryBufferWithSize &event_ids); + esp_err_t send_read_attr_command(uint64_t node_id, uint16_t endpoint_id, uint32_t cluster_id, uint32_t attribute_id); esp_err_t send_read_event_command(uint64_t node_id, uint16_t endpoint_id, uint32_t cluster_id, uint32_t event_id); diff --git a/components/esp_matter_controller/esp_matter_controller_subscribe_command.cpp b/components/esp_matter_controller/esp_matter_controller_subscribe_command.cpp index 7957171c1..6bb1b2b26 100644 --- a/components/esp_matter_controller/esp_matter_controller_subscribe_command.cpp +++ b/components/esp_matter_controller/esp_matter_controller_subscribe_command.cpp @@ -42,18 +42,16 @@ void subscribe_command::on_device_connected_fcn(void *context, ExchangeManager & subscribe_command *cmd = (subscribe_command *)context; ReadPrepareParams params(sessionHandle); CHIP_ERROR err = CHIP_NO_ERROR; - - if (cmd->m_command_type == SUBSCRIBE_ATTRIBUTE) { - params.mpEventPathParamsList = nullptr; - params.mEventPathParamsListSize = 0; - params.mpAttributePathParamsList = &cmd->m_attr_path; - params.mAttributePathParamsListSize = 1; - } else if (cmd->m_command_type == SUBSCRIBE_EVENT) { - params.mpEventPathParamsList = &cmd->m_event_path; - params.mEventPathParamsListSize = 1; - params.mpAttributePathParamsList = nullptr; - params.mAttributePathParamsListSize = 0; + if (cmd->m_attr_paths.AllocatedSize() == 0 && cmd->m_event_paths.AllocatedSize() == 0) { + ESP_LOGE(TAG, "Cannot send Subscribe command with NULL attribute path and NULL event path"); + chip::Platform::Delete(cmd); + return; } + + params.mpAttributePathParamsList = cmd->m_attr_paths.Get(); + params.mAttributePathParamsListSize = cmd->m_attr_paths.AllocatedSize(); + params.mpEventPathParamsList = cmd->m_event_paths.Get(); + params.mEventPathParamsListSize = cmd->m_event_paths.AllocatedSize(); params.mIsFabricFiltered = 0; params.mpDataVersionFilterList = nullptr; params.mDataVersionFilterListSize = 0; @@ -186,7 +184,8 @@ CHIP_ERROR subscribe_command::OnResubscriptionNeeded(ReadClient *apReadClient, C { m_resubscribe_retries++; if (m_resubscribe_retries > k_max_resubscribe_retries) { - ESP_LOGE(TAG, "Could not find the devices in %d retries, terminate the subscription", k_max_resubscribe_retries); + ESP_LOGE(TAG, "Could not find the devices in %d retries, terminate the subscription", + k_max_resubscribe_retries); return aTerminationCause; } return apReadClient->DefaultResubscribePolicy(aTerminationCause); @@ -203,32 +202,101 @@ void subscribe_command::OnDone(ReadClient *apReadClient) chip::Platform::Delete(this); } -esp_err_t send_subscribe_attr_command(uint64_t node_id, uint16_t endpoint_id, uint32_t cluster_id, - uint32_t attribute_id, uint16_t min_interval, uint16_t max_interval, - bool auto_resubscribe) +esp_err_t send_subscribe_attr_command(uint64_t node_id, ScopedMemoryBufferWithSize &endpoint_ids, + ScopedMemoryBufferWithSize &cluster_ids, + ScopedMemoryBufferWithSize &attribute_ids, uint16_t min_interval, + uint16_t max_interval, bool auto_resubscribe) { - subscribe_command *cmd = - chip::Platform::New(node_id, endpoint_id, cluster_id, attribute_id, SUBSCRIBE_ATTRIBUTE, - min_interval, max_interval, auto_resubscribe); + if (endpoint_ids.AllocatedSize() != cluster_ids.AllocatedSize() || + endpoint_ids.AllocatedSize() != attribute_ids.AllocatedSize()) { + ESP_LOGE(TAG, + "The endpoint_id array length should be the same as the cluster_ids array length and the " + "attribute_ids array length"); + return ESP_ERR_INVALID_ARG; + } + ScopedMemoryBufferWithSize attr_paths; + ScopedMemoryBufferWithSize event_paths; + attr_paths.Alloc(endpoint_ids.AllocatedSize()); + if (!attr_paths.Get()) { + ESP_LOGE(TAG, "Failed to alloc memory for attribute paths"); + return ESP_ERR_NO_MEM; + } + for (size_t i = 0; i < attr_paths.AllocatedSize(); ++i) { + attr_paths[i] = AttributePathParams(endpoint_ids[i], cluster_ids[i], attribute_ids[i]); + } + + subscribe_command *cmd = chip::Platform::New( + node_id, std::move(attr_paths), std::move(event_paths), min_interval, max_interval, auto_resubscribe); if (!cmd) { ESP_LOGE(TAG, "Failed to alloc memory for subscribe_command"); return ESP_ERR_NO_MEM; } - return cmd->send_command(); } +esp_err_t send_subscribe_event_command(uint64_t node_id, ScopedMemoryBufferWithSize &endpoint_ids, + ScopedMemoryBufferWithSize &cluster_ids, + ScopedMemoryBufferWithSize &event_ids, uint16_t min_interval, + uint16_t max_interval, bool auto_resubscribe) +{ + if (endpoint_ids.AllocatedSize() != cluster_ids.AllocatedSize() || + endpoint_ids.AllocatedSize() != event_ids.AllocatedSize()) { + ESP_LOGE(TAG, + "The endpoint_id array length should be the same as the cluster_ids array length and the " + "attribute_ids array length"); + return ESP_ERR_INVALID_ARG; + } + ScopedMemoryBufferWithSize attr_paths; + ScopedMemoryBufferWithSize event_paths; + event_paths.Alloc(endpoint_ids.AllocatedSize()); + if (!event_paths.Get()) { + ESP_LOGE(TAG, "Failed to alloc memory for attribute paths"); + return ESP_ERR_NO_MEM; + } + for (size_t i = 0; i < event_paths.AllocatedSize(); ++i) { + event_paths[i] = EventPathParams(endpoint_ids[i], cluster_ids[i], event_ids[i]); + } + + subscribe_command *cmd = chip::Platform::New( + node_id, std::move(attr_paths), std::move(event_paths), min_interval, max_interval, auto_resubscribe); + if (!cmd) { + ESP_LOGE(TAG, "Failed to alloc memory for subscribe_command"); + return ESP_ERR_NO_MEM; + } + return cmd->send_command(); +} + +esp_err_t send_subscribe_attr_command(uint64_t node_id, uint16_t endpoint_id, uint32_t cluster_id, + uint32_t attribute_id, uint16_t min_interval, uint16_t max_interval, + bool auto_resubscribe) +{ + ScopedMemoryBufferWithSize endpoint_ids; + ScopedMemoryBufferWithSize cluster_ids; + ScopedMemoryBufferWithSize attribute_ids; + endpoint_ids.Alloc(1); + cluster_ids.Alloc(1); + attribute_ids.Alloc(1); + if (!(endpoint_ids.Get() && cluster_ids.Get() && attribute_ids.Get())) { + return ESP_ERR_NO_MEM; + } + return send_subscribe_attr_command(node_id, endpoint_ids, cluster_ids, attribute_ids, min_interval, max_interval, + auto_resubscribe); +} + esp_err_t send_subscribe_event_command(uint64_t node_id, uint16_t endpoint_id, uint32_t cluster_id, uint32_t event_id, uint16_t min_interval, uint16_t max_interval, bool auto_resubscribe) { - subscribe_command *cmd = chip::Platform::New( - node_id, endpoint_id, cluster_id, event_id, SUBSCRIBE_EVENT, min_interval, max_interval, auto_resubscribe); - if (!cmd) { - ESP_LOGE(TAG, "Failed to alloc memory for subscribe_command"); + ScopedMemoryBufferWithSize endpoint_ids; + ScopedMemoryBufferWithSize cluster_ids; + ScopedMemoryBufferWithSize event_ids; + endpoint_ids.Alloc(1); + cluster_ids.Alloc(1); + event_ids.Alloc(1); + if (!(endpoint_ids.Get() && cluster_ids.Get() && event_ids.Get())) { return ESP_ERR_NO_MEM; } - - return cmd->send_command(); + return send_subscribe_event_command(node_id, endpoint_ids, cluster_ids, event_ids, min_interval, max_interval, + auto_resubscribe); } esp_err_t send_shutdown_subscription(uint64_t node_id, uint32_t subscription_id) diff --git a/components/esp_matter_controller/esp_matter_controller_subscribe_command.h b/components/esp_matter_controller/esp_matter_controller_subscribe_command.h index 5215b7b82..7b2df2ae9 100644 --- a/components/esp_matter_controller/esp_matter_controller_subscribe_command.h +++ b/components/esp_matter_controller/esp_matter_controller_subscribe_command.h @@ -18,6 +18,7 @@ #include #include #include +#include namespace esp_matter { namespace controller { @@ -29,6 +30,7 @@ using chip::app::BufferedReadCallback; using chip::app::EventPathParams; using chip::app::ReadClient; using chip::Messaging::ExchangeManager; +using chip::Platform::ScopedMemoryBufferWithSize; using esp_matter::client::peer_device_t; typedef enum { @@ -38,6 +40,27 @@ typedef enum { class subscribe_command : public ReadClient::Callback { public: + subscribe_command(uint64_t node_id, ScopedMemoryBufferWithSize &&attr_paths, + ScopedMemoryBufferWithSize &&event_paths, uint16_t min_interval, + uint16_t max_interval, bool auto_resubscribe = true, attribute_report_cb_t attribute_cb = nullptr, + event_report_cb_t event_cb = nullptr, subscribe_done_cb_t done_cb = nullptr, + subscribe_failure_cb_t connect_failure_cb = nullptr) + : m_node_id(node_id) + , m_min_interval(min_interval) + , m_max_interval(max_interval) + , m_auto_resubscribe(auto_resubscribe) + , m_buffered_read_cb(*this) + , m_attr_paths(std::move(attr_paths)) + , m_event_paths(std::move(event_paths)) + , on_device_connected_cb(on_device_connected_fcn, this) + , on_device_connection_failure_cb(on_device_connection_failure_fcn, this) + , attribute_data_cb(attribute_cb) + , event_data_cb(event_cb) + , subscribe_done_cb(done_cb) + , subscribe_failure_cb(connect_failure_cb) + { + } + subscribe_command(uint64_t node_id, uint16_t endpoint_id, uint32_t cluster_id, uint32_t attribute_or_event_id, subscribe_command_type_t command_type, uint16_t min_interval, uint16_t max_interval, bool auto_resubscribe = true, attribute_report_cb_t attribute_cb = nullptr, @@ -47,7 +70,6 @@ public: , m_min_interval(min_interval) , m_max_interval(max_interval) , m_auto_resubscribe(auto_resubscribe) - , m_command_type(command_type) , m_buffered_read_cb(*this) , on_device_connected_cb(on_device_connected_fcn, this) , on_device_connection_failure_cb(on_device_connection_failure_fcn, this) @@ -57,9 +79,15 @@ public: , subscribe_failure_cb(connect_failure_cb) { if (command_type == SUBSCRIBE_ATTRIBUTE) { - m_attr_path = AttributePathParams(endpoint_id, cluster_id, attribute_or_event_id); + m_attr_paths.Alloc(1); + if (m_attr_paths.Get()) { + m_attr_paths[0] = AttributePathParams(endpoint_id, cluster_id, attribute_or_event_id); + } } else if (command_type == SUBSCRIBE_EVENT) { - m_event_path = EventPathParams(endpoint_id, cluster_id, attribute_or_event_id); + m_event_paths.Alloc(1); + if (m_event_paths.Get()) { + m_event_paths[0] = EventPathParams(endpoint_id, cluster_id, attribute_or_event_id); + } } } @@ -67,16 +95,6 @@ public: esp_err_t send_command(); - AttributePathParams &get_attr_path() { return m_attr_path; } - - EventPathParams &get_event_path() { return m_event_path; } - - subscribe_command_type_t get_command_type() { return m_command_type; } - - uint16_t get_min_interval() { return m_min_interval; } - - uint16_t get_max_interval() { return m_max_interval; } - // ReadClient Callback Interface void OnAttributeData(const chip::app::ConcreteDataAttributePath &path, chip::TLV::TLVReader *data, const chip::app::StatusIB &status) override; @@ -92,21 +110,18 @@ public: void OnSubscriptionEstablished(chip::SubscriptionId subscriptionId) override; - CHIP_ERROR OnResubscriptionNeeded(ReadClient * apReadClient, CHIP_ERROR aTerminationCause) override; + CHIP_ERROR OnResubscriptionNeeded(ReadClient *apReadClient, CHIP_ERROR aTerminationCause) override; private: uint64_t m_node_id; uint16_t m_min_interval; uint16_t m_max_interval; bool m_auto_resubscribe; + BufferedReadCallback m_buffered_read_cb; uint32_t m_subscription_id = 0; uint8_t m_resubscribe_retries = 0; - subscribe_command_type_t m_command_type; - union { - AttributePathParams m_attr_path; - EventPathParams m_event_path; - }; - BufferedReadCallback m_buffered_read_cb; + ScopedMemoryBufferWithSize m_attr_paths; + ScopedMemoryBufferWithSize m_event_paths; static void on_device_connected_fcn(void *context, ExchangeManager &exchangeMgr, const SessionHandle &sessionHandle); @@ -120,6 +135,16 @@ private: subscribe_failure_cb_t subscribe_failure_cb; }; +esp_err_t send_subscribe_attr_command(uint64_t node_id, ScopedMemoryBufferWithSize &endpoint_ids, + ScopedMemoryBufferWithSize &cluster_ids, + ScopedMemoryBufferWithSize &attribute_ids, uint16_t min_interval, + uint16_t max_interval, bool auto_resubscribe = true); + +esp_err_t send_subscribe_event_command(uint64_t node_id, ScopedMemoryBufferWithSize &endpoint_ids, + ScopedMemoryBufferWithSize &cluster_ids, + ScopedMemoryBufferWithSize &event_ids, uint16_t min_interval, + uint16_t max_interval, bool auto_resubscribe = true); + esp_err_t send_subscribe_attr_command(uint64_t node_id, uint16_t endpoint_id, uint32_t cluster_id, uint32_t attribute_id, uint16_t min_interval, uint16_t max_interval, bool auto_resubscribe = true); diff --git a/components/esp_matter_controller/esp_matter_controller_utils.h b/components/esp_matter_controller/esp_matter_controller_utils.h index b1480ae18..115b9d865 100644 --- a/components/esp_matter_controller/esp_matter_controller_utils.h +++ b/components/esp_matter_controller/esp_matter_controller_utils.h @@ -21,6 +21,10 @@ #include #include +using chip::Platform::ScopedMemoryBufferWithSize; +using chip::app::AttributePathParams; +using chip::app::EventPathParams; + namespace esp_matter { namespace controller { using attribute_report_cb_t = void (*)(uint64_t remote_node_id, const chip::app::ConcreteDataAttributePath &path, @@ -29,7 +33,8 @@ using event_report_cb_t = void (*)(uint64_t remote_node_id, const chip::app::Eve chip::TLV::TLVReader *data); using subscribe_done_cb_t = void (*)(uint64_t remote_node_id, uint32_t subscription_id); using subscribe_failure_cb_t = void (*)(void *subscribe_command); -using read_done_cb_t = void (*)(uint64_t remote_node_id, const chip::app::AttributePathParams &path); +using read_done_cb_t = void (*)(uint64_t remote_node_id, const ScopedMemoryBufferWithSize &attr_paths, + const ScopedMemoryBufferWithSize &EventPathParams); #if !CONFIG_ESP_MATTER_COMMISSIONER_ENABLE /**