Skip to content

Commit

Permalink
Merge branch 'rmaker_cluster_invoke' into 'main'
Browse files Browse the repository at this point in the history
rainmaker: Fix the parsing of payload received in configuration command and add some comments

See merge request app-frameworks/esp-matter!517
  • Loading branch information
dhrishi committed Oct 23, 2023
2 parents c707e66 + 91d8626 commit df8ed2d
Showing 1 changed file with 46 additions and 5 deletions.
51 changes: 46 additions & 5 deletions components/esp_matter_rainmaker/esp_matter_rainmaker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ static const char *TAG = "esp_matter_rainmaker";

namespace esp_matter {

// Rainmaker cluster data model definition
// RainMaker cluster data model definition
namespace cluster {
namespace rainmaker {
static constexpr chip::EndpointId endpoint_id = 0x00000000; /* Same as root node endpoint. This will always be
Expand Down Expand Up @@ -181,7 +181,21 @@ static void user_node_association_event_handler(void *arg, esp_event_base_t even
}
}

static esp_err_t command_callback(const ConcreteCommandPath &command_path, TLVReader &tlv_data, void *opaque_ptr)
// RainMaker cluster, has two commands: "configuration" and "sign message."
// The "configuration" command has been deprecated, and the iOS app uses "sign message" command for user node
// association.
//
// As per Matter specification, the payload for an invoke command should be encapsulated in a TLV structure, and each
// argument should be encoded using a context-specific tag.
//
// However, the iOS app continues to send the payload without the TLV structure and context-specific tag. Future
// versions of iOS will support both methods of RainMaker user-node association and so, no specific action is required from
// firmware developers.
//
// On the other hand, the "config_command_callback()" correctly parses the payload. It initially extracts the TLV
// structure and then examines the context-specific tag before decoding the actual argument, which is of type octet
// string.
static esp_err_t config_command_callback(const ConcreteCommandPath &command_path, TLVReader &tlv_data, void *opaque_ptr)
{
/* Get ids */
uint16_t endpoint_id = command_path.mEndpointId;
Expand All @@ -203,8 +217,31 @@ static esp_err_t command_callback(const ConcreteCommandPath &command_path, TLVRe
command_count--;

/* Parse the tlv data */

if (chip::TLV::kTLVType_Structure != tlv_data.GetType()) {
return ESP_FAIL;
}
chip::TLV::TLVType mOuter;
if (CHIP_NO_ERROR != tlv_data.EnterContainer(mOuter)) {
return ESP_FAIL;
}
if (CHIP_NO_ERROR != tlv_data.Next()) {
return ESP_FAIL;
}
chip::TLV::Tag tag = tlv_data.GetTag();
if (!IsContextTag(tag)) {
return ESP_FAIL;
}
// check tag number, since this has only one argument, checking against 0
if (0 != TagNumFromTag(tag)) {
return ESP_FAIL;
}
// decode the octet string argument
chip::CharSpan config_value;
DataModel::Decode(tlv_data, config_value);
if (CHIP_NO_ERROR != DataModel::Decode(tlv_data, config_value)) {
return ESP_FAIL;
}

const char *data = config_value.data();
int size = config_value.size();
if (!data || size <= 0) {
Expand All @@ -213,6 +250,10 @@ static esp_err_t command_callback(const ConcreteCommandPath &command_path, TLVRe
return ESP_FAIL;
}

if (CHIP_NO_ERROR != tlv_data.ExitContainer(mOuter)) {
return ESP_FAIL;
}

/* The expected format of the data is "<user_id>::<secret_key>" */
char ch = ':';
char *check_first = strchr(data, (int)ch);
Expand Down Expand Up @@ -351,7 +392,7 @@ static esp_err_t custom_cluster_create()

/* Create custom configuration command */
command::create(cluster, cluster::rainmaker::command::configuration::Id,
COMMAND_FLAG_ACCEPTED | COMMAND_FLAG_CUSTOM, command_callback);
COMMAND_FLAG_ACCEPTED | COMMAND_FLAG_CUSTOM, config_command_callback);

/* Create custom sign_data command */
command::create(cluster, cluster::rainmaker::command::sign_data::Id,
Expand All @@ -363,7 +404,7 @@ static esp_err_t custom_cluster_create()
class RainmakerAttrAccess : public AttributeAccessInterface
{
public:
// Register for the Rainmaker cluster on endpoint 0.
// Register for the RainMaker cluster on endpoint 0.
RainmakerAttrAccess() : AttributeAccessInterface(chip::Optional<chip::EndpointId>(cluster::rainmaker::endpoint_id),
cluster::rainmaker::Id) {}

Expand Down

0 comments on commit df8ed2d

Please sign in to comment.