Merge branch 'controller/cb_improve' into 'main'

Controller: callbacks improvement

See merge request app-frameworks/esp-matter!1501
This commit is contained in:
Shu Chen
2026-04-16 10:06:53 +00:00
11 changed files with 182 additions and 77 deletions
@@ -53,6 +53,9 @@ void cluster_command::on_device_connected_fcn(void *context, ExchangeManager &ex
void cluster_command::on_device_connection_failure_fcn(void *context, const ScopedNodeId &peerId, CHIP_ERROR error)
{
cluster_command *cmd = reinterpret_cast<cluster_command *>(context);
if (cmd->on_connect_failure_cb) {
cmd->on_connect_failure_cb(context, peerId, error);
}
chip::Platform::Delete(cmd);
return;
}
@@ -18,7 +18,9 @@
#include <esp_matter.h>
#include <esp_matter_client.h>
#include <esp_matter_mem.h>
#include <esp_matter_controller_utils.h>
#include <lib/core/Optional.h>
#include <functional>
namespace esp_matter {
namespace controller {
@@ -40,7 +42,8 @@ public:
const char *command_data_field,
const chip::Optional<uint16_t> timed_invoke_timeout_ms = chip::NullOptional,
custom_command_callback::on_success_callback_t on_success = default_success_fcn,
custom_command_callback::on_error_callback_t on_error = default_error_fcn)
custom_command_callback::on_error_callback_t on_error = default_error_fcn,
on_connect_failure_cb_t connect_fail_cb = nullptr)
: m_destination_id(destination_id)
, m_endpoint_id(endpoint_id)
, m_cluster_id(cluster_id)
@@ -51,6 +54,7 @@ public:
, on_device_connection_failure_cb(on_device_connection_failure_fcn, this)
, on_success_cb(on_success)
, on_error_cb(on_error)
, on_connect_failure_cb(connect_fail_cb)
{
}
@@ -87,6 +91,8 @@ private:
custom_command_callback::on_success_callback_t on_success_cb;
custom_command_callback::on_error_callback_t on_error_cb;
on_connect_failure_cb_t on_connect_failure_cb;
};
/** Send cluster invoke command
@@ -51,6 +51,9 @@ void read_command::on_device_connected_fcn(void *context, ExchangeManager &excha
void read_command::on_device_connection_failure_fcn(void *context, const ScopedNodeId &peerId, CHIP_ERROR error)
{
read_command *cmd = (read_command *)context;
if (cmd->m_on_connect_failure_cb) {
cmd->m_on_connect_failure_cb(context, peerId, error);
}
chip::Platform::Delete(cmd);
return;
}
@@ -87,21 +90,21 @@ esp_err_t read_command::send_command()
void read_command::OnAttributeData(const chip::app::ConcreteDataAttributePath &path, chip::TLV::TLVReader *data,
const chip::app::StatusIB &status)
{
if (attribute_data_cb) {
chip::TLV::TLVReader data_cpy;
if (data == nullptr) {
attribute_data_cb(m_node_id, path, nullptr, status);
} else {
data_cpy.Init(*data);
attribute_data_cb(m_node_id, path, &data_cpy, status);
}
}
CHIP_ERROR error = status.ToChipError();
if (CHIP_NO_ERROR != error) {
ESP_LOGE(TAG, "Response Failure: %s", chip::ErrorStr(error));
return;
}
if (data == nullptr) {
ESP_LOGE(TAG, "Response Failure: No Data");
return;
}
if (attribute_data_cb) {
chip::TLV::TLVReader data_cpy;
data_cpy.Init(*data);
attribute_data_cb(m_node_id, path, &data_cpy);
}
error = DataModelLogger::LogAttribute(path, data);
if (CHIP_NO_ERROR != error) {
ESP_LOGE(TAG, "Response Failure: Can not decode Data");
@@ -111,6 +114,16 @@ void read_command::OnAttributeData(const chip::app::ConcreteDataAttributePath &p
void read_command::OnEventData(const chip::app::EventHeader &event_header, chip::TLV::TLVReader *data,
const chip::app::StatusIB *status)
{
if (event_data_cb) {
chip::TLV::TLVReader data_cpy;
if (data == nullptr) {
event_data_cb(m_node_id, event_header, nullptr, status);
} else {
data_cpy.Init(*data);
event_data_cb(m_node_id, event_header, &data_cpy, status);
}
}
CHIP_ERROR error = CHIP_NO_ERROR;
if (status != nullptr) {
error = status->ToChipError();
@@ -119,17 +132,9 @@ void read_command::OnEventData(const chip::app::EventHeader &event_header, chip:
return;
}
}
if (data == nullptr) {
ESP_LOGE(TAG, "Response Failure: No Data");
return;
if (data) {
error = DataModelLogger::LogEvent(event_header, data);
}
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");
}
@@ -138,6 +143,9 @@ void read_command::OnEventData(const chip::app::EventHeader &event_header, chip:
void read_command::OnError(CHIP_ERROR error)
{
ESP_LOGE(TAG, "Read Error: %s", chip::ErrorStr(error));
if (m_on_error_cb) {
m_on_error_cb(m_node_id, error);
}
}
void read_command::OnDeallocatePaths(chip::app::ReadPrepareParams &&aReadPrepareParams)
@@ -19,6 +19,7 @@
#include <esp_matter.h>
#include <esp_matter_controller_utils.h>
#include <esp_matter_mem.h>
#include <functional>
namespace esp_matter {
namespace controller {
@@ -41,10 +42,17 @@ typedef enum {
/** Read command class to send a read interaction command to a server **/
class read_command : public ReadClient::Callback {
public:
using on_error_callback = std::function<void(uint64_t node_id, CHIP_ERROR error)>;
using read_done_cb_t = std::function<void(uint64_t remote_node_id,
const ScopedMemoryBufferWithSize<AttributePathParams> &attr_paths,
const ScopedMemoryBufferWithSize<EventPathParams> &EventPathParams)>;
/** Constructor for command with multiple paths**/
read_command(uint64_t node_id, ScopedMemoryBufferWithSize<AttributePathParams> &&attr_paths,
ScopedMemoryBufferWithSize<EventPathParams> &&event_paths, attribute_report_cb_t attribute_cb,
read_done_cb_t read_cb_done, event_report_cb_t event_cb)
read_done_cb_t read_cb_done, event_report_cb_t event_cb,
on_connect_failure_cb_t connect_fail_cb = nullptr,
on_error_callback error_cb = nullptr)
: m_node_id(node_id)
, m_buffered_read_cb(*this)
, m_attr_paths(std::move(attr_paths))
@@ -54,6 +62,8 @@ public:
, attribute_data_cb(attribute_cb)
, read_done_cb(read_cb_done)
, event_data_cb(event_cb)
, m_on_connect_failure_cb(connect_fail_cb)
, m_on_error_cb(error_cb)
{
}
/** Constructor for command with single path.
@@ -62,7 +72,9 @@ 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)
event_report_cb_t event_cb,
on_connect_failure_cb_t connect_fail_cb = nullptr,
on_error_callback error_cb = nullptr)
: m_node_id(node_id)
, m_buffered_read_cb(*this)
, on_device_connected_cb(on_device_connected_fcn, this)
@@ -70,6 +82,8 @@ public:
, attribute_data_cb(attribute_cb)
, read_done_cb(read_cb_done)
, event_data_cb(event_cb)
, m_on_connect_failure_cb(connect_fail_cb)
, m_on_error_cb(error_cb)
{
if (command_type == READ_ATTRIBUTE) {
m_attr_paths.Alloc(1);
@@ -118,6 +132,9 @@ private:
attribute_report_cb_t attribute_data_cb;
read_done_cb_t read_done_cb;
event_report_cb_t event_data_cb;
on_connect_failure_cb_t m_on_connect_failure_cb;
on_error_callback m_on_error_cb;
};
/** Send read command with multiple attribute paths
@@ -54,8 +54,8 @@ void subscribe_command::on_device_connection_failure_fcn(void *context, const Sc
{
subscribe_command *cmd = (subscribe_command *)context;
if (cmd->subscribe_failure_cb) {
cmd->subscribe_failure_cb((void *)cmd);
if (cmd->on_connect_failure_cb) {
cmd->on_connect_failure_cb(cmd, peerId, error);
}
chip::Platform::Delete(cmd);
@@ -93,31 +93,40 @@ esp_err_t subscribe_command::send_command()
void subscribe_command::OnAttributeData(const chip::app::ConcreteDataAttributePath &path, chip::TLV::TLVReader *data,
const chip::app::StatusIB &status)
{
if (attribute_data_cb) {
chip::TLV::TLVReader data_cpy;
if (data == nullptr) {
attribute_data_cb(m_node_id, path, nullptr, status);
} else {
data_cpy.Init(*data);
attribute_data_cb(m_node_id, path, &data_cpy, status);
}
}
CHIP_ERROR error = status.ToChipError();
if (CHIP_NO_ERROR != error) {
ESP_LOGE(TAG, "Response Failure: %s", chip::ErrorStr(error));
return;
}
if (data == nullptr) {
ESP_LOGE(TAG, "Response Failure: No Data");
return;
}
chip::TLV::TLVReader log_data;
log_data.Init(*data);
error = DataModelLogger::LogAttribute(path, &log_data);
error = DataModelLogger::LogAttribute(path, data);
if (CHIP_NO_ERROR != error) {
ESP_LOGE(TAG, "Response Failure: Can not decode Data");
}
if (attribute_data_cb) {
attribute_data_cb(m_node_id, path, data);
}
}
void subscribe_command::OnEventData(const chip::app::EventHeader &event_header, chip::TLV::TLVReader *data,
const chip::app::StatusIB *status)
{
if (event_data_cb) {
chip::TLV::TLVReader data_cpy;
if (data == nullptr) {
event_data_cb(m_node_id, event_header, nullptr, status);
} else {
data_cpy.Init(*data);
event_data_cb(m_node_id, event_header, &data_cpy, status);
}
}
CHIP_ERROR error = CHIP_NO_ERROR;
if (status != nullptr) {
error = status->ToChipError();
@@ -126,21 +135,12 @@ void subscribe_command::OnEventData(const chip::app::EventHeader &event_header,
return;
}
}
if (data == nullptr) {
ESP_LOGE(TAG, "Response Failure: No Data");
return;
if (data) {
error = DataModelLogger::LogEvent(event_header, data);
}
chip::TLV::TLVReader log_data;
log_data.Init(*data);
error = DataModelLogger::LogEvent(event_header, &log_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 subscribe_command::OnError(CHIP_ERROR error)
@@ -41,12 +41,14 @@ typedef enum {
/** Subscribe command class to send a subscribe interaction command to a server **/
class subscribe_command : public ReadClient::Callback {
public:
using subscription_established_cb_t = void (*)(uint64_t remote_node_id, uint32_t subscription_id);
using subscription_terminated_cb_t = void (*)(uint64_t remote_node_id, uint32_t subscription_id);
/** Constructor for command with multiple paths**/
subscribe_command(uint64_t node_id, ScopedMemoryBufferWithSize<AttributePathParams> &&attr_paths,
ScopedMemoryBufferWithSize<EventPathParams> &&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, subscription_established_cb_t established_cb = nullptr,
subscription_terminated_cb_t terminated_cb = nullptr, subscribe_failure_cb_t connect_failure_cb = nullptr, bool keep_subscription = true)
subscription_terminated_cb_t terminated_cb = nullptr, on_connect_failure_cb_t connect_failure_cb = nullptr, bool keep_subscription = true)
: m_node_id(node_id)
, m_min_interval(min_interval)
, m_max_interval(max_interval)
@@ -61,7 +63,7 @@ public:
, event_data_cb(event_cb)
, subscription_established_cb(established_cb)
, subscription_terminated_cb(terminated_cb)
, subscribe_failure_cb(connect_failure_cb)
, on_connect_failure_cb(connect_failure_cb)
{
}
@@ -70,7 +72,7 @@ public:
ScopedMemoryBufferWithSize<EventPathParams> &&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, subscription_terminated_cb_t terminated_cb = nullptr,
subscribe_failure_cb_t connect_failure_cb = nullptr, bool keep_subscription = true)
on_connect_failure_cb_t connect_failure_cb = nullptr, bool keep_subscription = true)
: m_node_id(node_id)
, m_min_interval(min_interval)
, m_max_interval(max_interval)
@@ -84,7 +86,7 @@ public:
, attribute_data_cb(attribute_cb)
, event_data_cb(event_cb)
, subscription_terminated_cb(terminated_cb)
, subscribe_failure_cb(connect_failure_cb)
, on_connect_failure_cb(connect_failure_cb)
{
}
@@ -96,7 +98,7 @@ public:
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,
event_report_cb_t event_cb = nullptr, subscription_established_cb_t established_cb = nullptr,
subscription_terminated_cb_t terminated_cb = nullptr, subscribe_failure_cb_t connect_failure_cb = nullptr,
subscription_terminated_cb_t terminated_cb = nullptr, on_connect_failure_cb_t connect_failure_cb = nullptr,
bool keep_subscription = true)
: m_node_id(node_id)
, m_min_interval(min_interval)
@@ -110,7 +112,7 @@ public:
, event_data_cb(event_cb)
, subscription_established_cb(established_cb)
, subscription_terminated_cb(terminated_cb)
, subscribe_failure_cb(connect_failure_cb)
, on_connect_failure_cb(connect_failure_cb)
{
if (command_type == SUBSCRIBE_ATTRIBUTE) {
m_attr_paths.Alloc(1);
@@ -133,7 +135,7 @@ public:
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,
event_report_cb_t event_cb = nullptr, subscription_terminated_cb_t terminated_cb = nullptr,
subscribe_failure_cb_t connect_failure_cb = nullptr, bool keep_subscription = true)
on_connect_failure_cb_t connect_failure_cb = nullptr, bool keep_subscription = true)
: m_node_id(node_id)
, m_min_interval(min_interval)
, m_max_interval(max_interval)
@@ -145,7 +147,7 @@ public:
, attribute_data_cb(attribute_cb)
, event_data_cb(event_cb)
, subscription_terminated_cb(terminated_cb)
, subscribe_failure_cb(connect_failure_cb)
, on_connect_failure_cb(connect_failure_cb)
{
if (command_type == SUBSCRIBE_ATTRIBUTE) {
m_attr_paths.Alloc(1);
@@ -186,6 +188,11 @@ public:
return m_subscription_id;
}
uint64_t get_node_id()
{
return m_node_id;
}
private:
uint64_t m_node_id;
uint16_t m_min_interval;
@@ -208,7 +215,7 @@ private:
event_report_cb_t event_data_cb;
subscription_established_cb_t subscription_established_cb;
subscription_terminated_cb_t subscription_terminated_cb;
subscribe_failure_cb_t subscribe_failure_cb;
on_connect_failure_cb_t on_connect_failure_cb;
};
/** Send subscribe command with multiple attribute paths
@@ -56,6 +56,9 @@ void write_command::on_device_connected_fcn(void *context, ExchangeManager &exch
void write_command::on_device_connection_failure_fcn(void *context, const ScopedNodeId &peerId, CHIP_ERROR error)
{
write_command *cmd = (write_command *)context;
if (cmd->m_on_connect_failure_cb) {
cmd->m_on_connect_failure_cb(context, peerId, error);
}
chip::Platform::Delete(cmd);
return;
}
@@ -40,10 +40,17 @@ using esp_matter::client::interaction::multiple_write_encodable_type;
/** Write command class to send a write interaction command to a server **/
class write_command : public WriteClient::Callback {
public:
using on_error_callback = std::function<void(const ConcreteDataAttributePath &attr_path, CHIP_ERROR)>;
using on_success_callback = std::function<void(const ConcreteDataAttributePath &attr_path)>;
using on_write_done_callback = std::function<void(WriteClient *client)>;
/** Constructor for command with multiple paths**/
write_command(uint64_t node_id, ScopedMemoryBufferWithSize<AttributePathParams> &&attr_paths,
const char *attribute_val_str,
const chip::Optional<uint16_t> timed_write_timeout_ms = chip::NullOptional)
const chip::Optional<uint16_t> timed_write_timeout_ms = chip::NullOptional,
on_connect_failure_cb_t connect_fail_cb = nullptr,
on_success_callback write_success_cb = nullptr,
on_error_callback write_fail_cb = nullptr,
on_write_done_callback write_done_cb = nullptr)
: m_node_id(node_id)
, m_attr_paths(std::move(attr_paths))
, m_chunked_callback(this)
@@ -51,19 +58,31 @@ public:
, m_timed_write_timeout_ms(timed_write_timeout_ms)
, on_device_connected_cb(on_device_connected_fcn, this)
, on_device_connection_failure_cb(on_device_connection_failure_fcn, this)
, m_on_connect_failure_cb(connect_fail_cb)
, m_on_error_cb(write_fail_cb)
, m_on_success_cb(write_success_cb)
, m_on_write_done_cb(write_done_cb)
{
}
/** Constructor for command with an attribute path**/
write_command(uint64_t node_id, uint16_t endpoint_id, uint32_t cluster_id, uint32_t attribute_id,
const char *attribute_val_str,
const chip::Optional<uint16_t> timed_write_timeout_ms = chip::NullOptional)
const chip::Optional<uint16_t> timed_write_timeout_ms = chip::NullOptional,
on_connect_failure_cb_t connect_fail_cb = nullptr,
on_success_callback write_success_cb = nullptr,
on_error_callback write_fail_cb = nullptr,
on_write_done_callback write_done_cb = nullptr)
: m_node_id(node_id)
, m_chunked_callback(this)
, m_attr_vals(attribute_val_str)
, m_timed_write_timeout_ms(timed_write_timeout_ms)
, on_device_connected_cb(on_device_connected_fcn, this)
, on_device_connection_failure_cb(on_device_connection_failure_fcn, this)
, m_on_connect_failure_cb(connect_fail_cb)
, m_on_error_cb(write_fail_cb)
, m_on_success_cb(write_success_cb)
, m_on_write_done_cb(write_done_cb)
{
m_attr_paths.Alloc(1);
if (m_attr_paths.Get()) {
@@ -84,6 +103,13 @@ public:
CHIP_ERROR error = status.ToChipError();
if (CHIP_NO_ERROR != error) {
ChipLogError(chipTool, "Response Failure: %s", chip::ErrorStr(error));
if (m_on_error_cb) {
m_on_error_cb(path, error);
}
} else {
if (m_on_success_cb) {
m_on_success_cb(path);
}
}
}
@@ -95,6 +121,9 @@ public:
void OnDone(WriteClient *client) override
{
ChipLogProgress(chipTool, "Write Done");
if (m_on_write_done_cb) {
m_on_write_done_cb(client);
}
chip::Platform::Delete(this);
}
@@ -111,6 +140,10 @@ private:
chip::Callback::Callback<chip::OnDeviceConnected> on_device_connected_cb;
chip::Callback::Callback<chip::OnDeviceConnectionFailure> on_device_connection_failure_cb;
on_connect_failure_cb_t m_on_connect_failure_cb;
on_error_callback m_on_error_cb;
on_success_callback m_on_success_cb;
on_write_done_callback m_on_write_done_cb;
};
/** Send write attribute command
@@ -20,6 +20,10 @@
#include <app/ConcreteAttributePath.h>
#include <app/EventHeader.h>
#include <lib/core/TLVReader.h>
#include <lib/core/ScopedNodeId.h>
#include <app/MessageDef/StatusIB.h>
#include <functional>
using chip::app::AttributePathParams;
using chip::app::EventPathParams;
@@ -27,16 +31,11 @@ using chip::Platform::ScopedMemoryBufferWithSize;
namespace esp_matter {
namespace controller {
using attribute_report_cb_t = void (*)(uint64_t remote_node_id, const chip::app::ConcreteDataAttributePath &path,
chip::TLV::TLVReader *data);
using event_report_cb_t = void (*)(uint64_t remote_node_id, const chip::app::EventHeader &header,
chip::TLV::TLVReader *data);
using subscription_established_cb_t = void (*)(uint64_t remote_node_id, uint32_t subscription_id);
using subscription_terminated_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 ScopedMemoryBufferWithSize<AttributePathParams> &attr_paths,
const ScopedMemoryBufferWithSize<EventPathParams> &EventPathParams);
using attribute_report_cb_t = std::function<void(uint64_t remote_node_id, const chip::app::ConcreteDataAttributePath &path,
chip::TLV::TLVReader *data, const chip::app::StatusIB &status)>;
using event_report_cb_t = std::function<void(uint64_t remote_node_id, const chip::app::EventHeader &header,
chip::TLV::TLVReader *data, const chip::app::StatusIB *status)>;
using on_connect_failure_cb_t = std::function<void(void*, const chip::ScopedNodeId &, CHIP_ERROR)>;
#if CONFIG_ESP_MATTER_ENABLE_MATTER_SERVER
/**