mirror of
https://github.com/espressif/esp-matter.git
synced 2026-04-27 19:13:13 +00:00
controller: Add groupsettings command
controller: Add invoking commands and writing attributes commands for group_key_management cluster controller: Add invoking commands for groups cluster
This commit is contained in:
@@ -935,7 +935,6 @@ esp_err_t group_send_step_color_temperature(uint8_t fabric_index, uint16_t group
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
|
||||
} // namespace command
|
||||
} // namespace color_control
|
||||
|
||||
@@ -965,5 +964,77 @@ esp_err_t group_send_identify(uint8_t fabric_index, uint16_t group_id, uint16_t
|
||||
} // namespace command
|
||||
} // namespace identify
|
||||
|
||||
namespace group_key_management {
|
||||
namespace command {
|
||||
|
||||
esp_err_t send_keyset_write(peer_device_t *remote_device, uint16_t remote_endpoint_id, group_keyset_struct group_keyset)
|
||||
{
|
||||
GroupKeyManagement::Commands::KeySetWrite::Type command_data;
|
||||
command_data.groupKeySet = group_keyset;
|
||||
|
||||
chip::Controller::GroupKeyManagementCluster cluster(*remote_device->GetExchangeManager(),
|
||||
remote_device->GetSecureSession().Value(), remote_endpoint_id);
|
||||
cluster.InvokeCommand(command_data, NULL, send_command_success_callback, send_command_failure_callback);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t send_keyset_read(peer_device_t *remote_device, uint16_t remote_endpoint_id, uint16_t keyset_id,
|
||||
keyset_read_callback keyset_read_cb)
|
||||
{
|
||||
GroupKeyManagement::Commands::KeySetRead::Type command_data;
|
||||
command_data.groupKeySetID = keyset_id;
|
||||
|
||||
chip::Controller::GroupKeyManagementCluster cluster(*remote_device->GetExchangeManager(),
|
||||
remote_device->GetSecureSession().Value(), remote_endpoint_id);
|
||||
cluster.InvokeCommand(command_data, NULL, keyset_read_cb, send_command_failure_callback);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
} // namespace command
|
||||
} // namespace group_key_management
|
||||
|
||||
namespace groups {
|
||||
namespace command {
|
||||
|
||||
esp_err_t send_add_group(peer_device_t *remote_device, uint16_t remote_endpoint_id, uint16_t group_id, char *group_name,
|
||||
add_group_callback add_group_cb)
|
||||
{
|
||||
Groups::Commands::AddGroup::Type command_data;
|
||||
command_data.groupId = group_id;
|
||||
command_data.groupName = chip::CharSpan(group_name, strnlen(group_name, 16));
|
||||
|
||||
chip::Controller::GroupsCluster cluster(*remote_device->GetExchangeManager(),
|
||||
remote_device->GetSecureSession().Value(), remote_endpoint_id);
|
||||
cluster.InvokeCommand(command_data, NULL, add_group_cb, send_command_failure_callback);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t send_view_group(peer_device_t *remote_device, uint16_t remote_endpoint_id, uint16_t group_id,
|
||||
view_group_callback view_group_cb)
|
||||
{
|
||||
Groups::Commands::ViewGroup::Type command_data;
|
||||
command_data.groupId = group_id;
|
||||
|
||||
chip::Controller::GroupsCluster cluster(*remote_device->GetExchangeManager(),
|
||||
remote_device->GetSecureSession().Value(), remote_endpoint_id);
|
||||
cluster.InvokeCommand(command_data, NULL, view_group_cb, send_command_failure_callback);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t send_remove_group(peer_device_t *remote_device, uint16_t remote_endpoint_id, uint16_t group_id,
|
||||
remove_group_callback remove_group_cb)
|
||||
{
|
||||
Groups::Commands::RemoveGroup::Type command_data;
|
||||
command_data.groupId = group_id;
|
||||
|
||||
chip::Controller::GroupsCluster cluster(*remote_device->GetExchangeManager(),
|
||||
remote_device->GetSecureSession().Value(), remote_endpoint_id);
|
||||
cluster.InvokeCommand(command_data, NULL, remove_group_cb, send_command_failure_callback);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
} // namespace command
|
||||
} // namespace groups
|
||||
|
||||
} // namespace cluster
|
||||
} // namespace esp_matter
|
||||
|
||||
@@ -156,5 +156,41 @@ esp_err_t group_send_identify(uint8_t fabric_index, uint16_t group_id, uint16_t
|
||||
} // namespace command
|
||||
} // namespace identify
|
||||
|
||||
namespace group_key_management {
|
||||
namespace command {
|
||||
using group_keyset_struct = chip::app::Clusters::GroupKeyManagement::Structs::GroupKeySetStruct::Type;
|
||||
using keyset_read_callback =
|
||||
void (*)(void *, const chip::app::Clusters::GroupKeyManagement::Commands::KeySetRead::Type::ResponseType &);
|
||||
|
||||
esp_err_t send_keyset_write(peer_device_t *remote_device, uint16_t remote_endpoint_id,
|
||||
group_keyset_struct group_keyset);
|
||||
|
||||
esp_err_t send_keyset_read(peer_device_t *remote_device, uint16_t remote_endpoint_id, uint16_t keyset_id,
|
||||
keyset_read_callback read_callback);
|
||||
|
||||
} // namespace command
|
||||
} // namespace group_key_management
|
||||
|
||||
namespace groups {
|
||||
namespace command {
|
||||
using add_group_callback = void (*)(void *,
|
||||
const chip::app::Clusters::Groups::Commands::AddGroup::Type::ResponseType &);
|
||||
using view_group_callback = void (*)(void *,
|
||||
const chip::app::Clusters::Groups::Commands::ViewGroup::Type::ResponseType &);
|
||||
using remove_group_callback = void (*)(void *,
|
||||
const chip::app::Clusters::Groups::Commands::RemoveGroup::Type::ResponseType &);
|
||||
|
||||
esp_err_t send_add_group(peer_device_t *remote_device, uint16_t remote_endpoint_id, uint16_t group_id, char *group_name,
|
||||
add_group_callback add_group_cb);
|
||||
|
||||
esp_err_t send_view_group(peer_device_t *remote_device, uint16_t remote_endpoint_id, uint16_t group_id,
|
||||
view_group_callback view_group_cb);
|
||||
|
||||
esp_err_t send_remove_group(peer_device_t *remote_device, uint16_t remote_endpoint_id, uint16_t group_id,
|
||||
remove_group_callback remove_group_cb);
|
||||
|
||||
} // namespace command
|
||||
} // namespace groups
|
||||
|
||||
} // namespace cluster
|
||||
} // namespace esp_matter
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <DataModelLogger.h>
|
||||
#include <controller/CommissioneeDeviceProxy.h>
|
||||
#if CONFIG_ESP_MATTER_COMMISSIONER_ENABLE
|
||||
#include <esp_matter_commissioner.h>
|
||||
@@ -20,6 +21,7 @@
|
||||
#endif
|
||||
#include <esp_matter_controller_cluster_command.h>
|
||||
#include <esp_matter_controller_utils.h>
|
||||
#include <json_parser.h>
|
||||
|
||||
using namespace chip::app::Clusters;
|
||||
static const char *TAG = "cluster_command";
|
||||
@@ -49,6 +51,28 @@ static esp_err_t send_command(command_data_t *command_data, peer_device_t *remot
|
||||
return ESP_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
static esp_err_t send_group_command(command_data_t *command_data, uint16_t group_id)
|
||||
{
|
||||
if (command_data->command_data_count != 0) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
uint8_t fabric_index = commissioner::get_device_commissioner()->GetFabricIndex();
|
||||
switch (command_data->command_id) {
|
||||
case OnOff::Commands::On::Id:
|
||||
return esp_matter::cluster::on_off::command::group_send_on(fabric_index, group_id);
|
||||
break;
|
||||
case OnOff::Commands::Off::Id:
|
||||
return esp_matter::cluster::on_off::command::group_send_off(fabric_index, group_id);
|
||||
break;
|
||||
case OnOff::Commands::Toggle::Id:
|
||||
return esp_matter::cluster::on_off::command::group_send_toggle(fabric_index, group_id);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return ESP_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
} // namespace on_off
|
||||
|
||||
namespace level_control {
|
||||
@@ -80,7 +104,7 @@ static esp_err_t send_command(command_data_t *command_data, peer_device_t *remot
|
||||
/* level */ string_to_uint8(command_data->command_data_str[0]),
|
||||
/* transition_time */ string_to_uint16(command_data->command_data_str[1]),
|
||||
/* option_mask */ string_to_uint8(command_data->command_data_str[2]),
|
||||
/* option_override */string_to_uint8(command_data->command_data_str[3]) );
|
||||
/* option_override */ string_to_uint8(command_data->command_data_str[3]));
|
||||
break;
|
||||
case LevelControl::Commands::Step::Id:
|
||||
if (command_data->command_data_count != 5) {
|
||||
@@ -174,6 +198,172 @@ static esp_err_t send_command(command_data_t *command_data, peer_device_t *remot
|
||||
|
||||
} // namespace color_control
|
||||
|
||||
namespace group_key_management {
|
||||
using chip::app::Clusters::GroupKeyManagement::GroupKeySecurityPolicy;
|
||||
using cluster::group_key_management::command::group_keyset_struct;
|
||||
|
||||
constexpr size_t k_epoch_key_bytes_len = chip::Credentials::GroupDataProvider::EpochKey::kLengthBytes;
|
||||
|
||||
typedef struct epoch_keys {
|
||||
uint8_t epoch_key0_bytes[k_epoch_key_bytes_len];
|
||||
uint8_t epoch_key1_bytes[k_epoch_key_bytes_len];
|
||||
uint8_t epoch_key2_bytes[k_epoch_key_bytes_len];
|
||||
} epoch_keys_t;
|
||||
|
||||
static bool parse_group_keyset(group_keyset_struct *keyset, char *json_str, epoch_keys_t *keys)
|
||||
{
|
||||
jparse_ctx_t jctx;
|
||||
if (json_parse_start(&jctx, json_str, strlen(json_str)) != 0) {
|
||||
return false;
|
||||
}
|
||||
int int_val;
|
||||
int64_t int64_val;
|
||||
char epoch_key_oct_str[k_epoch_key_bytes_len * 2 + 1];
|
||||
// groupKeySetID
|
||||
if (json_obj_get_int(&jctx, "groupKeySetID", &int_val) != 0) {
|
||||
return false;
|
||||
}
|
||||
keyset->groupKeySetID = int_val;
|
||||
// groupKeySecurityPolicy
|
||||
if (json_obj_get_int(&jctx, "groupKeySecurityPolicy", &int_val) != 0) {
|
||||
return false;
|
||||
}
|
||||
keyset->groupKeySecurityPolicy = static_cast<GroupKeySecurityPolicy>(int_val);
|
||||
// epochKey0 & epochStartTime0
|
||||
if (json_obj_get_int64(&jctx, "epochStartTime0", &int64_val) == 0 &&
|
||||
json_obj_get_string(&jctx, "epochKey0", epoch_key_oct_str, k_epoch_key_bytes_len * 2 + 1) == 0 &&
|
||||
oct_str_to_byte_arr(epoch_key_oct_str, keys->epoch_key0_bytes) == k_epoch_key_bytes_len) {
|
||||
keyset->epochKey0.SetNonNull(chip::ByteSpan(keys->epoch_key0_bytes, k_epoch_key_bytes_len));
|
||||
keyset->epochStartTime0.SetNonNull(int64_val);
|
||||
} else {
|
||||
keyset->epochKey0.SetNull();
|
||||
keyset->epochStartTime0.SetNull();
|
||||
}
|
||||
// epochKey1 & epochStartTime1
|
||||
if (json_obj_get_int64(&jctx, "epochStartTime1", &int64_val) == 0 &&
|
||||
json_obj_get_string(&jctx, "epochKey1", epoch_key_oct_str, k_epoch_key_bytes_len * 2 + 1) == 0 &&
|
||||
oct_str_to_byte_arr(epoch_key_oct_str, keys->epoch_key1_bytes) == k_epoch_key_bytes_len) {
|
||||
keyset->epochKey1.SetNonNull(chip::ByteSpan(keys->epoch_key1_bytes, k_epoch_key_bytes_len));
|
||||
keyset->epochStartTime1.SetNonNull(int64_val);
|
||||
} else {
|
||||
keyset->epochKey1.SetNull();
|
||||
keyset->epochStartTime1.SetNull();
|
||||
}
|
||||
// epochKey2 & epochStartTime2
|
||||
if (json_obj_get_int64(&jctx, "epochStartTime2", &int64_val) == 0 &&
|
||||
json_obj_get_string(&jctx, "epochKey2", epoch_key_oct_str, k_epoch_key_bytes_len * 2 + 1) == 0 &&
|
||||
oct_str_to_byte_arr(epoch_key_oct_str, keys->epoch_key2_bytes) == k_epoch_key_bytes_len) {
|
||||
keyset->epochKey2.SetNonNull(chip::ByteSpan(keys->epoch_key2_bytes, k_epoch_key_bytes_len));
|
||||
keyset->epochStartTime2.SetNonNull(int64_val);
|
||||
} else {
|
||||
keyset->epochKey2.SetNull();
|
||||
keyset->epochStartTime2.SetNull();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static void keyset_read_response_callback(void *ctx,
|
||||
const GroupKeyManagement::Commands::KeySetRead::Type::ResponseType &response)
|
||||
{
|
||||
DataModelLogger::LogValue("groupKeySet", 1, response);
|
||||
}
|
||||
|
||||
static esp_err_t send_command(command_data_t *command_data, peer_device_t *remote_device, uint16_t remote_endpoint_id)
|
||||
{
|
||||
switch (command_data->command_id) {
|
||||
case GroupKeyManagement::Commands::KeySetWrite::Id: {
|
||||
if (command_data->command_data_count != 1) {
|
||||
ESP_LOGE(TAG, "The command date should in following order: group_keyset");
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
group_keyset_struct keyset_struct;
|
||||
epoch_keys_t keys;
|
||||
if (!parse_group_keyset(&keyset_struct, command_data->command_data_str[0], &keys)) {
|
||||
ESP_LOGE(TAG, "Failed to parse the group_keyset json string");
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
return esp_matter::cluster::group_key_management::command::send_keyset_write(remote_device, remote_endpoint_id,
|
||||
keyset_struct);
|
||||
break;
|
||||
}
|
||||
case GroupKeyManagement::Commands::KeySetRead::Id: {
|
||||
if (command_data->command_data_count != 1) {
|
||||
ESP_LOGE(TAG, "The command date should in following order: group_keyset_id");
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
return esp_matter::cluster::group_key_management::command::send_keyset_read(
|
||||
remote_device, remote_endpoint_id,
|
||||
/* group_keyset_id */ string_to_uint16(command_data->command_data_str[0]), keyset_read_response_callback);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return ESP_ERR_NOT_SUPPORTED;
|
||||
break;
|
||||
}
|
||||
return ESP_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
} // namespace group_key_management
|
||||
|
||||
namespace groups {
|
||||
|
||||
static void add_group_response_callback(void *ctx, const Groups::Commands::AddGroup::Type::ResponseType &response)
|
||||
{
|
||||
DataModelLogger::LogValue("addGroupResponse", 1, response);
|
||||
}
|
||||
|
||||
static void view_group_response_callback(void *ctx, const Groups::Commands::ViewGroup::Type::ResponseType &response)
|
||||
{
|
||||
DataModelLogger::LogValue("viewGroupResponse", 1, response);
|
||||
}
|
||||
|
||||
static void remove_group_response_callback(void *ctx, const Groups::Commands::RemoveGroup::Type::ResponseType &response)
|
||||
{
|
||||
DataModelLogger::LogValue("removeGroupResponse", 1, response);
|
||||
}
|
||||
|
||||
static esp_err_t send_command(command_data_t *command_data, peer_device_t *remote_device, uint16_t remote_endpoint_id)
|
||||
{
|
||||
switch (command_data->command_id) {
|
||||
case Groups::Commands::AddGroup::Id: {
|
||||
if (command_data->command_data_count != 2) {
|
||||
ESP_LOGE(TAG, "The command date should in following order: group_id group_name");
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
return esp_matter::cluster::groups::command::send_add_group(
|
||||
remote_device, remote_endpoint_id,
|
||||
/* group_id */ string_to_uint16(command_data->command_data_str[0]),
|
||||
/* group_name */ command_data->command_data_str[1], add_group_response_callback);
|
||||
break;
|
||||
}
|
||||
case Groups::Commands::ViewGroup::Id: {
|
||||
if (command_data->command_data_count != 1) {
|
||||
ESP_LOGE(TAG, "The command date should in following order: group_id");
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
return esp_matter::cluster::groups::command::send_view_group(
|
||||
remote_device, remote_endpoint_id,
|
||||
/* group_id */ string_to_uint16(command_data->command_data_str[0]), view_group_response_callback);
|
||||
break;
|
||||
}
|
||||
case Groups::Commands::RemoveGroup::Id: {
|
||||
if (command_data->command_data_count != 1) {
|
||||
ESP_LOGE(TAG, "The command date should in following order: group_id");
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
return esp_matter::cluster::groups::command::send_remove_group(
|
||||
remote_device, remote_endpoint_id,
|
||||
/* group_id */ string_to_uint16(command_data->command_data_str[0]), remove_group_response_callback);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return ESP_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
} // namespace groups
|
||||
|
||||
} // namespace clusters
|
||||
|
||||
void cluster_command::on_device_connected_fcn(void *context, ExchangeManager &exchangeMgr, SessionHandle &sessionHandle)
|
||||
@@ -190,6 +380,12 @@ void cluster_command::on_device_connected_fcn(void *context, ExchangeManager &ex
|
||||
case ColorControl::Id:
|
||||
clusters::color_control::send_command(cmd->m_command_data, &device_proxy, cmd->m_endpoint_id);
|
||||
break;
|
||||
case GroupKeyManagement::Id:
|
||||
clusters::group_key_management::send_command(cmd->m_command_data, &device_proxy, cmd->m_endpoint_id);
|
||||
break;
|
||||
case Groups::Id:
|
||||
clusters::groups::send_command(cmd->m_command_data, &device_proxy, cmd->m_endpoint_id);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -204,11 +400,28 @@ void cluster_command::on_device_connection_failure_fcn(void *context, const Scop
|
||||
return;
|
||||
}
|
||||
|
||||
esp_err_t cluster_command::dispatch_group_command(void *context)
|
||||
{
|
||||
cluster_command *cmd = reinterpret_cast<cluster_command *>(context);
|
||||
uint16_t group_id = cmd->m_destination_id & 0xFFFF;
|
||||
switch (cmd->m_command_data->cluster_id) {
|
||||
case OnOff::Id:
|
||||
return clusters::on_off::send_group_command(cmd->m_command_data, group_id);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return ESP_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
esp_err_t cluster_command::send_command()
|
||||
{
|
||||
if (is_group_command()) {
|
||||
return dispatch_group_command(reinterpret_cast<void *>(this));
|
||||
}
|
||||
#if CONFIG_ESP_MATTER_COMMISSIONER_ENABLE
|
||||
if (CHIP_NO_ERROR ==
|
||||
commissioner::get_device_commissioner()->GetConnectedDevice(m_node_id, &on_device_connected_cb,
|
||||
commissioner::get_device_commissioner()->GetConnectedDevice(m_destination_id, &on_device_connected_cb,
|
||||
&on_device_connection_failure_cb)) {
|
||||
return ESP_OK;
|
||||
}
|
||||
@@ -222,7 +435,8 @@ esp_err_t cluster_command::send_command()
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
esp_err_t send_invoke_cluster_command(uint64_t node_id, uint16_t endpoint_id, int cmd_data_argc, char **cmd_data_argv)
|
||||
esp_err_t send_invoke_cluster_command(uint64_t destination_id, uint16_t endpoint_id, int cmd_data_argc,
|
||||
char **cmd_data_argv)
|
||||
{
|
||||
command_data_t *command_data = (command_data_t *)calloc(1, sizeof(command_data_t));
|
||||
if (!command_data) {
|
||||
@@ -238,7 +452,7 @@ esp_err_t send_invoke_cluster_command(uint64_t node_id, uint16_t endpoint_id, in
|
||||
strnlen(cmd_data_argv[2 + idx], k_max_command_data_str_len));
|
||||
command_data->command_data_str[idx][controller::k_max_command_data_str_len - 1] = 0;
|
||||
}
|
||||
cluster_command *cmd = chip::Platform::New<cluster_command>(node_id, endpoint_id, command_data);
|
||||
cluster_command *cmd = chip::Platform::New<cluster_command>(destination_id, endpoint_id, command_data);
|
||||
if (!cmd) {
|
||||
ESP_LOGE(TAG, "Failed to alloc memory for cluster_command");
|
||||
return ESP_ERR_NO_MEM;
|
||||
|
||||
@@ -25,7 +25,7 @@ using chip::SessionHandle;
|
||||
using chip::Messaging::ExchangeManager;
|
||||
using esp_matter::client::peer_device_t;
|
||||
|
||||
constexpr size_t k_max_command_data_str_len = 16;
|
||||
constexpr size_t k_max_command_data_str_len = 256;
|
||||
constexpr size_t k_max_command_data_size = 8;
|
||||
|
||||
typedef struct command_data {
|
||||
@@ -37,8 +37,8 @@ typedef struct command_data {
|
||||
|
||||
class cluster_command {
|
||||
public:
|
||||
cluster_command(uint64_t node_id, uint16_t endpoint_id, command_data_t *command_data)
|
||||
: m_node_id(node_id)
|
||||
cluster_command(uint64_t destination_id, uint16_t endpoint_id, command_data_t *command_data)
|
||||
: m_destination_id(destination_id)
|
||||
, m_endpoint_id(endpoint_id)
|
||||
, m_command_data(command_data)
|
||||
, on_device_connected_cb(on_device_connected_fcn, this)
|
||||
@@ -55,14 +55,20 @@ public:
|
||||
|
||||
esp_err_t send_command();
|
||||
|
||||
bool is_group_command() {
|
||||
return chip::IsGroupId(m_destination_id);
|
||||
}
|
||||
|
||||
private:
|
||||
uint64_t m_node_id;
|
||||
uint64_t m_destination_id;
|
||||
uint16_t m_endpoint_id;
|
||||
command_data_t *m_command_data;
|
||||
|
||||
static void on_device_connected_fcn(void *context, ExchangeManager &exchangeMgr, SessionHandle &sessionHandle);
|
||||
static void on_device_connection_failure_fcn(void *context, const ScopedNodeId &peerId, CHIP_ERROR error);
|
||||
|
||||
static esp_err_t dispatch_group_command(void *context);
|
||||
|
||||
chip::Callback::Callback<chip::OnDeviceConnected> on_device_connected_cb;
|
||||
chip::Callback::Callback<chip::OnDeviceConnectionFailure> on_device_connection_failure_cb;
|
||||
};
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
|
||||
#include <esp_matter_controller_cluster_command.h>
|
||||
#include <esp_matter_controller_console.h>
|
||||
#include <esp_matter_controller_group_settings.h>
|
||||
#include <esp_matter_controller_pairing_command.h>
|
||||
#include <esp_matter_controller_read_command.h>
|
||||
#include <esp_matter_controller_subscribe_command.h>
|
||||
@@ -38,6 +39,8 @@ using chip::Inet::IPAddress;
|
||||
using chip::Transport::PeerAddress;
|
||||
using esp_matter::controller::command_data_t;
|
||||
|
||||
const static char *TAG = "controller_console";
|
||||
|
||||
namespace esp_matter {
|
||||
|
||||
namespace console {
|
||||
@@ -71,6 +74,71 @@ static esp_err_t controller_pairing_handler(int argc, char **argv)
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
static esp_err_t controller_group_settings_handler(int argc, char **argv)
|
||||
{
|
||||
if (argc >= 1) {
|
||||
if (strncmp(argv[0], "show-groups", sizeof("show-groups")) == 0) {
|
||||
return controller::group_settings::show_groups();
|
||||
} else if (strncmp(argv[0], "add-group", sizeof("add-group")) == 0) {
|
||||
if (argc != 3) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
uint16_t group_id = string_to_uint16(argv[1]);
|
||||
char *group_name = argv[2];
|
||||
return controller::group_settings::add_group(group_name, group_id);
|
||||
} else if (strncmp(argv[0], "remove-group", sizeof("remove-group")) == 0) {
|
||||
if (argc != 2) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
uint16_t group_id = string_to_uint16(argv[1]);
|
||||
return controller::group_settings::remove_group(group_id);
|
||||
} else if (strncmp(argv[0], "show-keysets", sizeof("show-keysets")) == 0) {
|
||||
return controller::group_settings::show_keysets();
|
||||
} else if (strncmp(argv[0], "add-keyset", sizeof("add-keyset")) == 0) {
|
||||
if (argc != 5) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
uint16_t keyset_id = string_to_uint16(argv[1]);
|
||||
uint8_t key_policy = string_to_uint8(argv[2]);
|
||||
uint64_t validity_time = string_to_uint64(argv[3]);
|
||||
char *epoch_key_oct_str = argv[4];
|
||||
return controller::group_settings::add_keyset(keyset_id, key_policy, validity_time, epoch_key_oct_str);
|
||||
} else if (strncmp(argv[0], "remove-keyset", sizeof("remove_keyset")) == 0) {
|
||||
if (argc != 2) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
uint16_t keyset_id = string_to_uint16(argv[1]);
|
||||
return controller::group_settings::remove_keyset(keyset_id);
|
||||
} else if (strncmp(argv[0], "bind-keyset", sizeof("bind_keyset")) == 0) {
|
||||
if (argc != 3) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
uint16_t group_id = string_to_uint16(argv[1]);
|
||||
uint16_t keyset_id = string_to_uint16(argv[2]);
|
||||
return controller::group_settings::bind_keyset(group_id, keyset_id);
|
||||
} else if (strncmp(argv[0], "unbind-keyset", sizeof("unbind_keyset")) == 0) {
|
||||
if (argc != 3) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
uint16_t group_id = string_to_uint16(argv[1]);
|
||||
uint16_t keyset_id = string_to_uint16(argv[2]);
|
||||
return controller::group_settings::unbind_keyset(group_id, keyset_id);
|
||||
}
|
||||
}
|
||||
ESP_LOGI(TAG, "Subcommands of group-settings:");
|
||||
ESP_LOGI(TAG, "Show groups : controller group-settings show-groups");
|
||||
ESP_LOGI(TAG, "Add group : controller group-settings add-group <group_id> <group_name>");
|
||||
ESP_LOGI(TAG, "Remove group : controller group-settings remove-group <group_id>");
|
||||
ESP_LOGI(TAG, "Show keysets : controller group-settings show-keysets");
|
||||
ESP_LOGI(TAG,
|
||||
"Add keyset : controller group-settings add-keyset <ketset_id> <policy> <validity_time> "
|
||||
"<epoch_key_oct_str>");
|
||||
ESP_LOGI(TAG, "Remove keyset : controller group-settings remove-keyset <ketset_id>");
|
||||
ESP_LOGI(TAG, "Bind keyset : controller group-settings bind-keyset <group_id> <ketset_id>");
|
||||
ESP_LOGI(TAG, "Unbind keyset : controller group-settings unbind-keyset <group_id> <ketset_id>");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t controller_invoke_command_handler(int argc, char **argv)
|
||||
{
|
||||
if (argc < 4) {
|
||||
@@ -188,62 +256,72 @@ esp_err_t controller_register_commands()
|
||||
#if CONFIG_ESP_MATTER_COMMISSIONER_ENABLE
|
||||
{
|
||||
.name = "pairing",
|
||||
.description = "Pairing a node. "
|
||||
"Usage: controller pairing onnetwork [nodeid] [pincode] Or "
|
||||
"controller pairing ble-wifi [nodeid] [pincode] [discriminator] [ssid] [password] Or "
|
||||
"controller pairing ble-thread [nodeid] [pincode] [discriminator] [dataset]",
|
||||
.description = "Pairing a node.\n"
|
||||
"\tUsage: controller pairing onnetwork [nodeid] [pincode] Or\n"
|
||||
"\tcontroller pairing ble-wifi [nodeid] [pincode] [discriminator] [ssid] [password] Or\n"
|
||||
"\tcontroller pairing ble-thread [nodeid] [pincode] [discriminator] [dataset]",
|
||||
.handler = controller_pairing_handler,
|
||||
},
|
||||
#endif
|
||||
{
|
||||
.name = "group-settings",
|
||||
.description = "Managing the groups and keysets of the controller.\n"
|
||||
"\tUsage: controller group-settings <sub-commands>",
|
||||
.handler = controller_group_settings_handler,
|
||||
},
|
||||
{
|
||||
.name = "invoke-cmd",
|
||||
.description = "Send command to the nodes. "
|
||||
"Usage: controller invoke-cmd [node-id] [endpoint-id] [cluster-id] [command-id] [payload]",
|
||||
.description =
|
||||
"Send command to the nodes.\n"
|
||||
"\tUsage: controller invoke-cmd [node-id|group-id] [endpoint-id] [cluster-id] [command-id] [payload]\n"
|
||||
"\tNotes: group-id should start with prefix '0xFFFFFFFFFFFF', endpoint-id will be ignored if the fist "
|
||||
"parameter is group-id.",
|
||||
.handler = controller_invoke_command_handler,
|
||||
},
|
||||
{
|
||||
.name = "read-attr",
|
||||
.description = "Read attributes of the nodes. "
|
||||
"Usage: controller read-attr [node-id] [endpoint-id] [cluster-id] [attr-id]",
|
||||
.description = "Read attributes of the nodes.\n"
|
||||
"\tUsage: controller read-attr [node-id] [endpoint-id] [cluster-id] [attr-id]",
|
||||
.handler = controller_read_attr_handler,
|
||||
},
|
||||
{
|
||||
.name = "write-attr",
|
||||
.description = "Write attributes of the nodes. "
|
||||
"Usage: controller write-attr [node-id] [endpoint-id] [cluster-id] [attr-id] [attr-value]",
|
||||
.description =
|
||||
"Write attributes of the nodes.\n"
|
||||
"\tUsage: controller write-attr [node-id|group-id] [endpoint-id] [cluster-id] [attr-id] [attr-value]",
|
||||
.handler = controller_write_attr_handler,
|
||||
},
|
||||
{
|
||||
.name = "read-event",
|
||||
.description = "Read events of the nodes. "
|
||||
"Usage: controller read-event [node-id] [endpoint-id] [cluster-id] [event-id]",
|
||||
.description = "Read events of the nodes.\n"
|
||||
"\tUsage: controller read-event [node-id] [endpoint-id] [cluster-id] [event-id]",
|
||||
.handler = controller_read_event_handler,
|
||||
},
|
||||
{
|
||||
.name = "subs-attr",
|
||||
.description = "Subscribe attributes of the nodes. "
|
||||
"Usage: controller subs-attr [node-id] [endpoint-id] [cluster-id] [attr-id] [min-interval] "
|
||||
"[max-interval]",
|
||||
.description = "Subscribe attributes of the nodes.\n"
|
||||
"\tUsage: controller subs-attr [node-id] [endpoint-id] [cluster-id] [attr-id] "
|
||||
"[min-interval] [max-interval]",
|
||||
.handler = controller_subscribe_attr_handler,
|
||||
},
|
||||
{
|
||||
.name = "subs-event",
|
||||
.description = "Subscribe events of the nodes. "
|
||||
"Usage: controller subs-attr [node-id] [endpoint-id] [cluster-id] [event-id] [min-interval] "
|
||||
"[max-interval]",
|
||||
.description = "Subscribe events of the nodes.\n"
|
||||
"\tUsage: controller subs-attr [node-id] [endpoint-id] [cluster-id] [event-id] "
|
||||
"[min-interval] [max-interval]",
|
||||
.handler = controller_subscribe_event_handler,
|
||||
},
|
||||
{
|
||||
.name = "shutdown-subs",
|
||||
.description = "Shutdown subscription."
|
||||
"Usage: controller shutdown-subs [node-id] [subscription-id]",
|
||||
.description = "Shutdown subscription.\n"
|
||||
"\tUsage: controller shutdown-subs [node-id] [subscription-id]",
|
||||
.handler = controller_shutdown_subscription_handler,
|
||||
},
|
||||
};
|
||||
|
||||
const static command_t controller_command = {
|
||||
.name = "controller",
|
||||
.description = "Controller commands. Usage: matter controller [command_name]",
|
||||
.description = "Controller commands. Usage: matter esp controller [command_name]",
|
||||
.handler = controller_dispatch,
|
||||
};
|
||||
// Register the controller commands
|
||||
|
||||
@@ -0,0 +1,229 @@
|
||||
// Copyright 2022 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <esp_check.h>
|
||||
#include <esp_matter_commissioner.h>
|
||||
#include <esp_matter_controller_group_settings.h>
|
||||
#include <esp_matter_controller_utils.h>
|
||||
|
||||
using chip::FabricIndex;
|
||||
using chip::KeysetId;
|
||||
using chip::Credentials::GroupDataProvider;
|
||||
|
||||
constexpr char TAG[] = "groupsettings";
|
||||
|
||||
namespace esp_matter {
|
||||
namespace controller {
|
||||
namespace group_settings {
|
||||
|
||||
static bool find_keyset_id(FabricIndex fabric_index, uint16_t group_id, KeysetId &keyset_id)
|
||||
{
|
||||
GroupDataProvider *group_data_provider = chip::Credentials::GetGroupDataProvider();
|
||||
auto iter = group_data_provider->IterateGroupKeys(fabric_index);
|
||||
GroupDataProvider::GroupKey group_key;
|
||||
while (iter->Next(group_key)) {
|
||||
if (group_key.group_id == group_id) {
|
||||
keyset_id = group_key.keyset_id;
|
||||
iter->Release();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
iter->Release();
|
||||
return false;
|
||||
}
|
||||
|
||||
esp_err_t show_groups()
|
||||
{
|
||||
ESP_LOGI(TAG, " +-------------------------------------------------------------------------------------+");
|
||||
ESP_LOGI(TAG, " | Available Groups : |");
|
||||
ESP_LOGI(TAG, " +-------------------------------------------------------------------------------------+");
|
||||
ESP_LOGI(TAG, " | Group Id | KeySet Id | Group Name |");
|
||||
FabricIndex fabric_index = commissioner::get_device_commissioner()->GetFabricIndex();
|
||||
GroupDataProvider *group_data_provider = chip::Credentials::GetGroupDataProvider();
|
||||
auto iter = group_data_provider->IterateGroupInfo(fabric_index);
|
||||
GroupDataProvider::GroupInfo group_info;
|
||||
if (iter) {
|
||||
while (iter->Next(group_info)) {
|
||||
chip::KeysetId keyset_id;
|
||||
if (find_keyset_id(fabric_index, group_info.group_id, keyset_id)) {
|
||||
ESP_LOGI(TAG, " | 0x%-12x 0x%-13x %-50s |", group_info.group_id, keyset_id, group_info.name);
|
||||
} else {
|
||||
ESP_LOGI(TAG, " | 0x%-12x %-15s %-50s |", group_info.group_id, "None", group_info.name);
|
||||
}
|
||||
}
|
||||
iter->Release();
|
||||
}
|
||||
ESP_LOGI(TAG, " +-------------------------------------------------------------------------------------+");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t add_group(char *group_name, uint16_t group_id)
|
||||
{
|
||||
if (strlen(group_name) > CHIP_CONFIG_MAX_GROUP_NAME_LENGTH || group_id == chip::kUndefinedGroupId) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
FabricIndex fabric_index = commissioner::get_device_commissioner()->GetFabricIndex();
|
||||
GroupDataProvider *group_data_provider = chip::Credentials::GetGroupDataProvider();
|
||||
GroupDataProvider::GroupInfo group_info;
|
||||
|
||||
group_info.SetName(group_name);
|
||||
group_info.group_id = group_id;
|
||||
ESP_RETURN_ON_FALSE(CHIP_NO_ERROR == group_data_provider->SetGroupInfo(fabric_index, group_info), ESP_FAIL, TAG,
|
||||
"Failed to set the group info");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t remove_group(uint16_t group_id)
|
||||
{
|
||||
if (group_id == chip::kUndefinedGroupId) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
FabricIndex fabric_index = commissioner::get_device_commissioner()->GetFabricIndex();
|
||||
GroupDataProvider *group_data_provider = chip::Credentials::GetGroupDataProvider();
|
||||
ESP_RETURN_ON_FALSE(CHIP_NO_ERROR == group_data_provider->RemoveGroupInfo(fabric_index, group_id), ESP_FAIL, TAG,
|
||||
"Failed to remove the group info");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t show_keysets()
|
||||
{
|
||||
FabricIndex fabric_index = commissioner::get_device_commissioner()->GetFabricIndex();
|
||||
GroupDataProvider *group_data_provider = chip::Credentials::GetGroupDataProvider();
|
||||
GroupDataProvider::KeySet keyset;
|
||||
|
||||
ESP_LOGI(TAG, " +-------------------------------------------------------------------------------------+");
|
||||
ESP_LOGI(TAG, " | Available KeySets : |");
|
||||
ESP_LOGI(TAG, " +-------------------------------------------------------------------------------------+");
|
||||
ESP_LOGI(TAG, " | KeySet Id | Key Policy |");
|
||||
|
||||
auto iter = group_data_provider->IterateKeySets(fabric_index);
|
||||
if (iter) {
|
||||
while (iter->Next(keyset)) {
|
||||
ESP_LOGI(TAG, " | 0x%-12x %-66s |", keyset.keyset_id,
|
||||
(keyset.policy == GroupDataProvider::SecurityPolicy::kCacheAndSync) ? "Cache and Sync"
|
||||
: "Trust First");
|
||||
}
|
||||
iter->Release();
|
||||
}
|
||||
ESP_LOGI(TAG, " +-------------------------------------------------------------------------------------+");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t bind_keyset(uint16_t group_id, uint16_t keyset_id)
|
||||
{
|
||||
size_t current_count = 0;
|
||||
FabricIndex fabric_index = commissioner::get_device_commissioner()->GetFabricIndex();
|
||||
GroupDataProvider *group_data_provider = chip::Credentials::GetGroupDataProvider();
|
||||
|
||||
auto iter = group_data_provider->IterateGroupKeys(fabric_index);
|
||||
current_count = iter->Count();
|
||||
iter->Release();
|
||||
|
||||
if (CHIP_NO_ERROR !=
|
||||
group_data_provider->SetGroupKeyAt(fabric_index, current_count,
|
||||
GroupDataProvider::GroupKey(group_id, keyset_id))) {
|
||||
ESP_LOGE(TAG, "Failed to bind keyset");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t unbind_keyset(uint16_t group_id, uint16_t keyset_id)
|
||||
{
|
||||
size_t index = 0;
|
||||
FabricIndex fabric_index = commissioner::get_device_commissioner()->GetFabricIndex();
|
||||
GroupDataProvider *group_data_provider = chip::Credentials::GetGroupDataProvider();
|
||||
|
||||
auto iter = group_data_provider->IterateGroupKeys(fabric_index);
|
||||
size_t max_count = iter->Count();
|
||||
GroupDataProvider::GroupKey group_key;
|
||||
while (iter->Next(group_key)) {
|
||||
if (group_key.group_id == group_id && group_key.keyset_id == keyset_id) {
|
||||
break;
|
||||
}
|
||||
index++;
|
||||
}
|
||||
iter->Release();
|
||||
ESP_RETURN_ON_FALSE(index < max_count, ESP_ERR_NOT_FOUND, TAG, "Failed to find the group key");
|
||||
ESP_RETURN_ON_FALSE(CHIP_NO_ERROR == group_data_provider->RemoveGroupKeyAt(fabric_index, index), ESP_FAIL, TAG,
|
||||
"Failed to remove the group key");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t add_keyset(uint16_t keyset_id, uint8_t key_policy, uint64_t validity_time, char *epoch_key_oct_str)
|
||||
{
|
||||
FabricIndex fabric_index = commissioner::get_device_commissioner()->GetFabricIndex();
|
||||
GroupDataProvider *group_data_provider = chip::Credentials::GetGroupDataProvider();
|
||||
uint8_t compressed_fabric_id[sizeof(uint64_t)];
|
||||
chip::MutableByteSpan compressed_fabric_id_span(compressed_fabric_id);
|
||||
if (CHIP_NO_ERROR !=
|
||||
commissioner::get_device_commissioner()->GetCompressedFabricIdBytes(compressed_fabric_id_span)) {
|
||||
ESP_LOGE(TAG, "Failed to get the compressed fabric_id");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
if (key_policy != 0 && key_policy != 1) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
GroupDataProvider::KeySet keyset(keyset_id, GroupDataProvider::SecurityPolicy(key_policy), 1);
|
||||
GroupDataProvider::EpochKey epoch_key;
|
||||
epoch_key.start_time = validity_time;
|
||||
uint8_t epoch_key_buf[GroupDataProvider::EpochKey::kLengthBytes];
|
||||
if (oct_str_to_byte_arr(epoch_key_oct_str, epoch_key_buf) != GroupDataProvider::EpochKey::kLengthBytes) {
|
||||
ESP_LOGE(TAG, "The epoch key octstring is wrong");
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
memcpy(epoch_key.key, epoch_key_buf, GroupDataProvider::EpochKey::kLengthBytes);
|
||||
memcpy(keyset.epoch_keys, &epoch_key, sizeof(GroupDataProvider::EpochKey));
|
||||
if (CHIP_NO_ERROR != group_data_provider->SetKeySet(fabric_index, compressed_fabric_id_span, keyset)) {
|
||||
ESP_LOGE(TAG, "Failed to set keyset");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t remove_keyset(uint16_t keyset_id)
|
||||
{
|
||||
FabricIndex fabric_index = commissioner::get_device_commissioner()->GetFabricIndex();
|
||||
GroupDataProvider *group_data_provider = chip::Credentials::GetGroupDataProvider();
|
||||
|
||||
size_t index = 0;
|
||||
CHIP_ERROR err = CHIP_NO_ERROR;
|
||||
auto iter = group_data_provider->IterateGroupKeys(fabric_index);
|
||||
GroupDataProvider::GroupKey group_key;
|
||||
while (iter->Next(group_key)) {
|
||||
if (group_key.keyset_id == keyset_id) {
|
||||
err = group_data_provider->RemoveGroupKeyAt(fabric_index, index);
|
||||
if (err != CHIP_NO_ERROR) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
index++;
|
||||
}
|
||||
iter->Release();
|
||||
|
||||
if (err == CHIP_NO_ERROR) {
|
||||
return ESP_OK;
|
||||
}
|
||||
ESP_RETURN_ON_FALSE(CHIP_NO_ERROR == group_data_provider->RemoveKeySet(fabric_index, keyset_id), ESP_FAIL, TAG,
|
||||
"Failed to remove the keyset");
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
} // namespace group_settings
|
||||
} // namespace controller
|
||||
} // namespace esp_matter
|
||||
@@ -0,0 +1,40 @@
|
||||
// Copyright 2022 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#pragma once
|
||||
#include <esp_err.h>
|
||||
|
||||
namespace esp_matter {
|
||||
namespace controller {
|
||||
namespace group_settings {
|
||||
|
||||
esp_err_t show_groups();
|
||||
|
||||
esp_err_t add_group(char *group_name, uint16_t group_id);
|
||||
|
||||
esp_err_t remove_group(uint16_t group_id);
|
||||
|
||||
esp_err_t show_keysets();
|
||||
|
||||
esp_err_t bind_keyset(uint16_t group_id, uint16_t keyset_id);
|
||||
|
||||
esp_err_t unbind_keyset(uint16_t group_id, uint16_t keyset_id);
|
||||
|
||||
esp_err_t add_keyset(uint16_t keyset_id, uint8_t key_policy, uint64_t validity_time, char *epoch_key_oct_str);
|
||||
|
||||
esp_err_t remove_keyset(uint16_t keyset_id);
|
||||
|
||||
} // namespace group_settings
|
||||
} // namespace controller
|
||||
} // namespace esp_matter
|
||||
@@ -465,6 +465,75 @@ static esp_err_t write_attribute(uint64_t node_id, uint16_t endpoint_id, uint32_
|
||||
|
||||
} // namespace binding
|
||||
|
||||
namespace group_key_management {
|
||||
|
||||
using group_key_map_obj = GroupKeyManagement::Structs::GroupKeyMapStruct::Type;
|
||||
|
||||
constexpr size_t k_max_group_key_map_size = CHIP_CONFIG_MAX_GROUP_KEYS_PER_FABRIC;
|
||||
|
||||
typedef struct group_key_map_attr {
|
||||
group_key_map_obj group_key_map_array[k_max_group_key_map_size];
|
||||
} group_key_map_attr_t;
|
||||
|
||||
static void group_key_map_attr_free(void *ctx)
|
||||
{
|
||||
group_key_map_attr_t *attr_ptr = reinterpret_cast<group_key_map_attr_t *>(ctx);
|
||||
chip::Platform::Delete(attr_ptr);
|
||||
}
|
||||
|
||||
static esp_err_t parse_group_key_map_json(char *json_str, group_key_map_attr_t *group_key_map,
|
||||
size_t *group_key_map_size)
|
||||
{
|
||||
jparse_ctx_t jctx;
|
||||
ESP_RETURN_ON_FALSE(json_parse_start(&jctx, json_str, strlen(json_str)) == 0, ESP_ERR_INVALID_ARG, TAG,
|
||||
"Group key map json string is wrong");
|
||||
size_t index = 0;
|
||||
while (index < k_max_group_key_map_size && json_arr_get_object(&jctx, index) == 0) {
|
||||
int int_val;
|
||||
// Fabric
|
||||
if (json_obj_get_int(&jctx, "fabricIndex", &int_val) == 0) {
|
||||
group_key_map->group_key_map_array[index].fabricIndex = int_val;
|
||||
}
|
||||
ESP_RETURN_ON_FALSE(json_obj_get_int(&jctx, "groupId", &int_val) == 0, ESP_ERR_INVALID_ARG, TAG,
|
||||
"Failed to get groupId");
|
||||
group_key_map->group_key_map_array[index].groupId = int_val;
|
||||
ESP_RETURN_ON_FALSE(json_obj_get_int(&jctx, "groupKeySetID", &int_val) == 0, ESP_ERR_INVALID_ARG, TAG,
|
||||
"Failed to get groupKeySetId");
|
||||
group_key_map->group_key_map_array[index].groupKeySetID = int_val;
|
||||
json_arr_leave_object(&jctx);
|
||||
index++;
|
||||
}
|
||||
*group_key_map_size = index;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t write_attribute(uint64_t node_id, uint16_t endpoint_id, uint32_t attribute_id, char *attribute_val_str)
|
||||
{
|
||||
esp_err_t err = ESP_OK;
|
||||
switch (attribute_id) {
|
||||
case GroupKeyManagement::Attributes::GroupKeyMap::Id: {
|
||||
size_t group_key_map_size = 0;
|
||||
group_key_map_attr_t *attr_val = chip::Platform::New<group_key_map_attr_t>();
|
||||
ESP_RETURN_ON_FALSE(attr_val, ESP_ERR_NO_MEM, TAG, "Failed to alloc group_key_map_attr_t");
|
||||
ESP_RETURN_ON_ERROR(parse_group_key_map_json(attribute_val_str, attr_val, &group_key_map_size), TAG,
|
||||
"Failed to parse group_key_map json string");
|
||||
List<group_key_map_obj> group_key_map_list(attr_val->group_key_map_array, group_key_map_size);
|
||||
write_command<List<group_key_map_obj>> *cmd = New<write_command<List<group_key_map_obj>>>(
|
||||
node_id, endpoint_id, GroupKeyManagement::Id, attribute_id, group_key_map_list);
|
||||
ESP_RETURN_ON_FALSE(cmd, ESP_ERR_NO_MEM, TAG, "Failed to alloc memory for write_command");
|
||||
cmd->set_attribute_free_handler(group_key_map_attr_free, attr_val);
|
||||
return cmd->send_command();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
err = ESP_ERR_NOT_SUPPORTED;
|
||||
break;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
} // namespace group_key_management
|
||||
|
||||
} // namespace clusters
|
||||
|
||||
esp_err_t send_write_attr_command(uint64_t node_id, uint16_t endpoint_id, uint32_t cluster_id, uint32_t attribute_id,
|
||||
@@ -486,6 +555,9 @@ esp_err_t send_write_attr_command(uint64_t node_id, uint16_t endpoint_id, uint32
|
||||
case Binding::Id:
|
||||
return clusters::binding::write_attribute(node_id, endpoint_id, attribute_id, attribute_val_str);
|
||||
break;
|
||||
case GroupKeyManagement::Id:
|
||||
return clusters::group_key_management::write_attribute(node_id, endpoint_id, attribute_id, attribute_val_str);
|
||||
break;
|
||||
default:
|
||||
return ESP_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
@@ -34,7 +34,6 @@ public:
|
||||
static CHIP_ERROR LogCommand(const chip::app::ConcreteCommandPath & path, chip::TLV::TLVReader * data);
|
||||
static CHIP_ERROR LogEvent(const chip::app::EventHeader & header, chip::TLV::TLVReader * data);
|
||||
|
||||
private:
|
||||
static CHIP_ERROR LogValue(const char * label, size_t indent, bool value)
|
||||
{
|
||||
DataModelLogger::LogString(label, indent, value ? "TRUE" : "FALSE");
|
||||
|
||||
Reference in New Issue
Block a user