From 37ad275215ac9cbd7f07d2aae2746fbe399b596f Mon Sep 17 00:00:00 2001 From: WanqQixiang Date: Thu, 15 Aug 2024 17:44:25 +0800 Subject: [PATCH] client: Use EncodableToTLV class for encoding command data field and attribute value --- components/esp_matter/esp_matter_client.cpp | 86 +++++++++---------- components/esp_matter/esp_matter_client.h | 58 +++++++++++++ components/esp_matter_controller/Kconfig | 8 -- .../esp_matter_controller_cluster_command.cpp | 4 - .../esp_matter_controller_cluster_command.h | 14 +-- .../esp_matter_controller_write_command.cpp | 2 +- .../esp_matter_controller_write_command.h | 18 +--- 7 files changed, 105 insertions(+), 85 deletions(-) diff --git a/components/esp_matter/esp_matter_client.cpp b/components/esp_matter/esp_matter_client.cpp index 0c2b780c2..5651806ea 100644 --- a/components/esp_matter/esp_matter_client.cpp +++ b/components/esp_matter/esp_matter_client.cpp @@ -33,6 +33,7 @@ #include "app/CommandPathParams.h" #include "app/CommandSender.h" #include "app/InteractionModelEngine.h" +#include "app/data-model/EncodableToTLV.h" using namespace chip::app::Clusters; using chip::DeviceProxy; @@ -220,6 +221,8 @@ void binding_init() } namespace interaction { +using chip::app::DataModel::EncodableToTLV; + namespace invoke { using command_data_tag = chip::app::CommandDataIB::Tag; @@ -230,6 +233,22 @@ esp_err_t send_request(void *ctx, peer_device_t *remote_device, const CommandPat const char *command_data_json_str, custom_command_callback::on_success_callback_t on_success, custom_command_callback::on_error_callback_t on_error, const Optional &timed_invoke_timeout_ms, const Optional &response_timeout) +{ + custom_encodable_type type(command_data_json_str, custom_encodable_type::interaction_type::k_invoke_cmd); + return send_request(ctx, remote_device, command_path, type, on_success, on_error, timed_invoke_timeout_ms, response_timeout); +} + +esp_err_t send_group_request(const uint8_t fabric_index, const CommandPathParams &command_path, + const char *command_data_json_str) +{ + custom_encodable_type type(command_data_json_str, custom_encodable_type::interaction_type::k_invoke_cmd); + return send_group_request(fabric_index, command_path, type); +} + +esp_err_t send_request(void *ctx, peer_device_t *remote_device, const CommandPathParams &command_path, + const EncodableToTLV &encodable, custom_command_callback::on_success_callback_t on_success, + custom_command_callback::on_error_callback_t on_error, + const Optional &timed_invoke_timeout_ms, const Optional &response_timeout) { if (!remote_device->GetSecureSession().HasValue() || remote_device->GetSecureSession().Value()->IsGroupSession()) { ESP_LOGE(TAG, "Invalid Session Type"); @@ -256,26 +275,8 @@ esp_err_t send_request(void *ctx, peer_device_t *remote_device, const CommandPat ESP_LOGE(TAG, "No memory for command sender"); return ESP_ERR_NO_MEM; } - chip::app::CommandSender::PrepareCommandParameters prepare_command_params; - if (command_sender->PrepareCommand(command_path, prepare_command_params) != CHIP_NO_ERROR) { - ESP_LOGE(TAG, "Failed to prepare command"); - return ESP_FAIL; - } - TLVWriter *writer = command_sender->GetCommandDataIBTLVWriter(); - if (writer == nullptr) { - ESP_LOGE(TAG, "No TLV writer in command sender"); - return ESP_ERR_INVALID_STATE; - } - esp_err_t err = json_to_tlv(command_data_json_str, *writer, ContextTag(command_data_tag::kFields)); - if (err != ESP_OK) { - ESP_LOGE(TAG, "Failed to convert json string to TLV"); - return err; - } - chip::app::CommandSender::FinishCommandParameters finish_command_params(timed_invoke_timeout_ms); - if (command_sender->FinishCommand(finish_command_params) != CHIP_NO_ERROR) { - ESP_LOGE(TAG, "Failed to finish command"); - return ESP_FAIL; - } + chip::app::CommandSender::AddRequestDataParameters add_request_data_params(timed_invoke_timeout_ms); + command_sender->AddRequestData(command_path, encodable, add_request_data_params); if (command_sender->SendCommandRequest(remote_device->GetSecureSession().Value(), response_timeout) != CHIP_NO_ERROR) { ESP_LOGE(TAG, "Failed to send command request"); @@ -287,7 +288,7 @@ esp_err_t send_request(void *ctx, peer_device_t *remote_device, const CommandPat } esp_err_t send_group_request(const uint8_t fabric_index, const CommandPathParams &command_path, - const char *command_data_json_str) + const EncodableToTLV &encodeable) { if (!command_path.mFlags.Has(chip::app::CommandPathFlags::kGroupIdValid)) { ESP_LOGE(TAG, "Invalid CommandPathFlags"); @@ -301,26 +302,8 @@ esp_err_t send_group_request(const uint8_t fabric_index, const CommandPathParams ESP_LOGE(TAG, "No memory for command sender"); return ESP_ERR_NO_MEM; } - chip::app::CommandSender::PrepareCommandParameters prepare_command_params; - if (command_sender->PrepareCommand(command_path, prepare_command_params) != CHIP_NO_ERROR) { - ESP_LOGE(TAG, "Failed to prepare command"); - return ESP_FAIL; - } - TLVWriter *writer = command_sender->GetCommandDataIBTLVWriter(); - if (writer == nullptr) { - ESP_LOGE(TAG, "No TLV writer in command sender"); - return ESP_ERR_INVALID_STATE; - } - esp_err_t err = json_to_tlv(command_data_json_str, *writer, ContextTag(command_data_tag::kFields)); - if (err != ESP_OK) { - ESP_LOGE(TAG, "Failed to convert json string to TLV"); - return err; - } - chip::app::CommandSender::FinishCommandParameters finish_command_params; - if (command_sender->FinishCommand(finish_command_params) != CHIP_NO_ERROR) { - ESP_LOGE(TAG, "Failed to finish command"); - return ESP_FAIL; - } + chip::app::CommandSender::AddRequestDataParameters add_request_data_params; + command_sender->AddRequestData(command_path, encodeable, add_request_data_params); if (command_sender->SendGroupCommandRequest(SessionHandle(session)) != CHIP_NO_ERROR) { ESP_LOGE(TAG, "Failed to send command request"); return ESP_FAIL; @@ -545,7 +528,7 @@ private: WriteClient::Callback &m_callback; }; -static esp_err_t encode_attribute_value(uint8_t *encoded_buf, size_t encoded_buf_size, const char *attr_val_json_str, +static esp_err_t encode_attribute_value(uint8_t *encoded_buf, size_t encoded_buf_size, const EncodableToTLV &encodable, TLVReader &out_reader) { TLVWriter writer; @@ -554,9 +537,9 @@ static esp_err_t encode_attribute_value(uint8_t *encoded_buf, size_t encoded_buf esp_err_t err = ESP_OK; writer.Init(encoded_buf, encoded_buf_size); - if ((err = json_to_tlv(attr_val_json_str, writer, chip::TLV::AnonymousTag())) != ESP_OK) { - ESP_LOGE(TAG, "Failed to parse attribute value"); - return err; + if (encodable.EncodeTo(writer, chip::TLV::AnonymousTag()) != CHIP_NO_ERROR) { + ESP_LOGE(TAG, "Failed to encode attribute value"); + return ESP_FAIL; } if (writer.Finalize() != CHIP_NO_ERROR) { ESP_LOGE(TAG, "Failed to finalize tlv writer"); @@ -584,7 +567,7 @@ static esp_err_t encode_attribute_value(uint8_t *encoded_buf, size_t encoded_buf } esp_err_t send_request(client::peer_device_t *remote_device, AttributePathParams &attr_path, - const char *attr_val_json_str, WriteClient::Callback &callback, + const chip::app::DataModel::EncodableToTLV &encodable, WriteClient::Callback &callback, const chip::Optional &timeout_ms) { esp_err_t err = ESP_OK; @@ -617,7 +600,7 @@ esp_err_t send_request(client::peer_device_t *remote_device, AttributePathParams return ESP_ERR_NO_MEM; } TLVReader attr_val_reader; - err = encode_attribute_value(encoded_buf.Get(), k_encoded_buf_size, attr_val_json_str, attr_val_reader); + err = encode_attribute_value(encoded_buf.Get(), k_encoded_buf_size, encodable, attr_val_reader); if (err != ESP_OK) { ESP_LOGE(TAG, "Failed to encode attribute value to a TLV reader"); return err; @@ -634,6 +617,15 @@ esp_err_t send_request(client::peer_device_t *remote_device, AttributePathParams write_client.release(); client_deleter_callback.release(); return ESP_OK; + +} + +esp_err_t send_request(client::peer_device_t *remote_device, AttributePathParams &attr_path, + const char *attr_val_json_str, WriteClient::Callback &callback, + const chip::Optional &timeout_ms) +{ + custom_encodable_type type(attr_val_json_str, custom_encodable_type::interaction_type::k_write_attr); + return send_request(remote_device, attr_path, type, callback, timeout_ms); } } // namespace write diff --git a/components/esp_matter/esp_matter_client.h b/components/esp_matter/esp_matter_client.h index 2be2b88d0..b0fdf25c7 100644 --- a/components/esp_matter/esp_matter_client.h +++ b/components/esp_matter/esp_matter_client.h @@ -14,9 +14,13 @@ #pragma once +#include #include +#include +#include #include #include +#include namespace esp_matter { namespace client { @@ -35,6 +39,44 @@ using chip::Messaging::ExchangeManager; using chip::System::Clock::Timeout; using chip::TLV::TLVReader; using client::peer_device_t; +using chip::app::DataModel::EncodableToTLV; + +class custom_encodable_type : public EncodableToTLV +{ +public: + const char *k_empty_command_data = "{}"; + const char *k_null_attribute_data = "null"; + enum interaction_type { + k_invoke_cmd = 0, + k_write_attr, + }; + + custom_encodable_type(const char *json_str, interaction_type usage) + { + if (json_str) { + m_json_str = strdup(json_str); + } else { + if (usage == k_invoke_cmd) { + m_json_str = strdup("{}"); + } else if (usage == k_write_attr) { + m_json_str = strdup("null"); + } + } + assert(m_json_str); + } + + ~custom_encodable_type() { free(m_json_str); } + + CHIP_ERROR EncodeTo(chip::TLV::TLVWriter & writer, chip::TLV::Tag tag) const override + { + if (json_to_tlv(m_json_str, writer, tag) != ESP_OK) { + return CHIP_ERROR_INTERNAL; + } + return CHIP_NO_ERROR; + } +private: + char *m_json_str = NULL; +}; /** Command invoke APIs * @@ -108,6 +150,18 @@ esp_err_t send_request(void *ctx, peer_device_t *remote_device, const CommandPat esp_err_t send_group_request(const uint8_t fabric_index, const CommandPathParams &command_path, const char *command_data_json_str); + +esp_err_t send_request(void *ctx, peer_device_t *remote_device, const CommandPathParams &command_path, + const chip::app::DataModel::EncodableToTLV &encodable, + custom_command_callback::on_success_callback_t on_success, + custom_command_callback::on_error_callback_t on_error, + const Optional &timed_invoke_timeout_ms, + const Optional &response_timeout = chip::NullOptional); + + +esp_err_t send_group_request(const uint8_t fabric_index, const CommandPathParams &command_path, + const chip::app::DataModel::EncodableToTLV &encodable); + } // namespace invoke /** Attribute/event read API @@ -127,6 +181,10 @@ namespace write { esp_err_t send_request(client::peer_device_t *remote_device, AttributePathParams &attr_path, const char *attr_val_json_str, WriteClient::Callback &callback, const chip::Optional &timeout_ms); + +esp_err_t send_request(client::peer_device_t *remote_device, AttributePathParams &attr_path, + const chip::app::DataModel::EncodableToTLV &encodable, WriteClient::Callback &callback, + const chip::Optional &timeout_ms); } // namespace write namespace subscribe { diff --git a/components/esp_matter_controller/Kconfig b/components/esp_matter_controller/Kconfig index 7d497b4a3..a788500d6 100644 --- a/components/esp_matter_controller/Kconfig +++ b/components/esp_matter_controller/Kconfig @@ -20,14 +20,6 @@ menu "ESP Matter Controller" help Enable the matter commissioner in the ESP Matter controller. - config ESP_MATTER_CONTROLLER_JSON_STRING_BUFFER_LEN - int "Max JSON string buffer length" - depends on ESP_MATTER_CONTROLLER_ENABLE - default 1024 - help - Max JSON string buffer length. This buffer will be used to store the command data field - for cluster-invoked command or attribute value for write-attribute command. - choice ESP_MATTER_COMMISSIONER_ATTESTATION_TRUST_STORE prompt "Attestation Trust Store" depends on ESP_MATTER_COMMISSIONER_ENABLE diff --git a/components/esp_matter_controller/commands/esp_matter_controller_cluster_command.cpp b/components/esp_matter_controller/commands/esp_matter_controller_cluster_command.cpp index 65219653a..0c658ff97 100644 --- a/components/esp_matter_controller/commands/esp_matter_controller_cluster_command.cpp +++ b/components/esp_matter_controller/commands/esp_matter_controller_cluster_command.cpp @@ -259,10 +259,6 @@ esp_err_t send_invoke_cluster_command(uint64_t destination_id, uint16_t endpoint uint32_t command_id, const char *command_data_field, chip::Optional timed_invoke_timeout_ms) { - if (command_data_field && strlen(command_data_field) >= k_command_data_field_buffer_size) { - ESP_LOGE(TAG, "The command data field buffer is too small for this command, please increase the buffer size"); - return ESP_ERR_INVALID_ARG; - } cluster_command *cmd = chip::Platform::New(destination_id, endpoint_id, cluster_id, command_id, command_data_field, timed_invoke_timeout_ms); if (!cmd) { diff --git a/components/esp_matter_controller/commands/esp_matter_controller_cluster_command.h b/components/esp_matter_controller/commands/esp_matter_controller_cluster_command.h index 700932b23..1dfd66ac0 100644 --- a/components/esp_matter_controller/commands/esp_matter_controller_cluster_command.h +++ b/components/esp_matter_controller/commands/esp_matter_controller_cluster_command.h @@ -31,9 +31,7 @@ using chip::Messaging::ExchangeManager; using chip::TLV::TLVReader; using esp_matter::client::peer_device_t; using esp_matter::client::interaction::invoke::custom_command_callback; - -constexpr char k_empty_command_data_field[] = "{}"; -constexpr size_t k_command_data_field_buffer_size = CONFIG_ESP_MATTER_CONTROLLER_JSON_STRING_BUFFER_LEN; +using esp_matter::client::interaction::custom_encodable_type; /** Cluster command class to send an invoke interaction command to a server **/ class cluster_command { @@ -47,19 +45,13 @@ public: , m_endpoint_id(endpoint_id) , m_cluster_id(cluster_id) , m_command_id(command_id) + , m_command_data_field(command_data_field, custom_encodable_type::interaction_type::k_invoke_cmd) , m_timed_invoke_timeout_ms(timed_invoke_timeout_ms) , on_device_connected_cb(on_device_connected_fcn, this) , on_device_connection_failure_cb(on_device_connection_failure_fcn, this) , on_success_cb(on_success) , on_error_cb(on_error) { - if (command_data_field) { - strncpy(m_command_data_field, command_data_field, k_command_data_field_buffer_size - 1); - m_command_data_field[strnlen(command_data_field, k_command_data_field_buffer_size - 1)] = 0; - } else { - strcpy(m_command_data_field, k_empty_command_data_field); - m_command_data_field[strlen(k_empty_command_data_field)] = 0; - } } ~cluster_command() {} @@ -73,7 +65,7 @@ private: uint16_t m_endpoint_id; uint32_t m_cluster_id; uint32_t m_command_id; - char m_command_data_field[k_command_data_field_buffer_size]; + custom_encodable_type m_command_data_field; chip::Optional m_timed_invoke_timeout_ms; static void on_device_connected_fcn(void *context, ExchangeManager &exchangeMgr, diff --git a/components/esp_matter_controller/commands/esp_matter_controller_write_command.cpp b/components/esp_matter_controller/commands/esp_matter_controller_write_command.cpp index cbbd97f64..6731c8c49 100644 --- a/components/esp_matter_controller/commands/esp_matter_controller_write_command.cpp +++ b/components/esp_matter_controller/commands/esp_matter_controller_write_command.cpp @@ -46,7 +46,7 @@ void write_command::on_device_connected_fcn(void *context, ExchangeManager &exch { write_command *cmd = (write_command *)context; chip::OperationalDeviceProxy device_proxy(&exchangeMgr, sessionHandle); - esp_err_t err = interaction::write::send_request(&device_proxy, cmd->m_attr_path, cmd->m_attr_val_str, + esp_err_t err = interaction::write::send_request(&device_proxy, cmd->m_attr_path, cmd->m_attr_val, cmd->m_chunked_callback, chip::NullOptional); if (err != ESP_OK) { chip::Platform::Delete(cmd); diff --git a/components/esp_matter_controller/commands/esp_matter_controller_write_command.h b/components/esp_matter_controller/commands/esp_matter_controller_write_command.h index d07ffec32..3e4ea5ab8 100644 --- a/components/esp_matter_controller/commands/esp_matter_controller_write_command.h +++ b/components/esp_matter_controller/commands/esp_matter_controller_write_command.h @@ -33,9 +33,7 @@ using chip::app::WriteClient; using chip::Messaging::ExchangeManager; using chip::TLV::TLVElementType; using esp_matter::client::peer_device_t; - -constexpr char *k_null_attribute_val_str = "null"; -constexpr size_t k_attr_val_str_buf_size = CONFIG_ESP_MATTER_CONTROLLER_JSON_STRING_BUFFER_LEN; +using esp_matter::client::interaction::custom_encodable_type; /** Write command class to send a write interaction command to a server **/ class write_command : public WriteClient::Callback { @@ -46,17 +44,9 @@ public: : m_node_id(node_id) , m_attr_path(endpoint_id, cluster_id, attribute_id) , m_chunked_callback(this) + , m_attr_val(attribute_val_str, custom_encodable_type::interaction_type::k_write_attr) , on_device_connected_cb(on_device_connected_fcn, this) - , on_device_connection_failure_cb(on_device_connection_failure_fcn, this) - { - if (attribute_val_str) { - strncpy(m_attr_val_str, attribute_val_str, k_attr_val_str_buf_size - 1); - m_attr_val_str[strnlen(attribute_val_str, k_attr_val_str_buf_size - 1)] = 0; - } else { - strcpy(m_attr_val_str, k_null_attribute_val_str); - m_attr_val_str[strlen(k_null_attribute_val_str)] = 0; - } - } + , on_device_connection_failure_cb(on_device_connection_failure_fcn, this) {} ~write_command() {} @@ -86,7 +76,7 @@ private: uint64_t m_node_id; AttributePathParams m_attr_path; ChunkedWriteCallback m_chunked_callback; - char m_attr_val_str[k_attr_val_str_buf_size]; + custom_encodable_type m_attr_val; static void on_device_connected_fcn(void *context, ExchangeManager &exchangeMgr, const SessionHandle &sessionHandle);