mirror of
https://github.com/espressif/esp-matter.git
synced 2026-04-27 19:13:13 +00:00
Merge branch 'add_mode_select' into 'release/v1.1'
components/esp-matter: Add mode select device type See merge request app-frameworks/esp-matter!778
This commit is contained in:
@@ -2188,5 +2188,47 @@ attribute_t *create_control_mode(cluster_t *cluster, uint8_t value)
|
||||
} /* attribute */
|
||||
} /* pump_configuration_and_control */
|
||||
|
||||
namespace mode_select {
|
||||
namespace attribute {
|
||||
|
||||
attribute_t *create_mode_select_description(cluster_t *cluster, const char * value, uint16_t length)
|
||||
{
|
||||
if (length > k_max_mode_select_description_length) {
|
||||
ESP_LOGE(TAG, "Could not create attribute, string length out of bound");
|
||||
return NULL;
|
||||
}
|
||||
return esp_matter::attribute::create(cluster, ModeSelect::Attributes::Description::Id, ATTRIBUTE_FLAG_NONE,
|
||||
esp_matter_char_str((char *)value, length),
|
||||
k_max_mode_select_description_length);
|
||||
}
|
||||
|
||||
attribute_t *create_standard_namespace(cluster_t *cluster, const nullable<uint16_t> value)
|
||||
{
|
||||
return esp_matter::attribute::create(cluster, ModeSelect::Attributes::StandardNamespace::Id, ATTRIBUTE_FLAG_NULLABLE, esp_matter_nullable_enum16(value));
|
||||
}
|
||||
|
||||
attribute_t *create_supported_modes(cluster_t *cluster, const uint8_t * value, uint16_t length, uint16_t count)
|
||||
{
|
||||
return esp_matter::attribute::create(cluster, ModeSelect::Attributes::SupportedModes::Id, ATTRIBUTE_FLAG_NONE, esp_matter_array((uint8_t*)value, length, count));
|
||||
}
|
||||
|
||||
attribute_t *create_current_mode(cluster_t *cluster, uint8_t value)
|
||||
{
|
||||
return esp_matter::attribute::create(cluster, ModeSelect::Attributes::CurrentMode::Id, ATTRIBUTE_FLAG_NONVOLATILE, esp_matter_uint8(value));
|
||||
}
|
||||
|
||||
attribute_t *create_start_up_mode(cluster_t *cluster, nullable<uint8_t> value)
|
||||
{
|
||||
return esp_matter::attribute::create(cluster, ModeSelect::Attributes::StartUpMode::Id, ATTRIBUTE_FLAG_WRITABLE | ATTRIBUTE_FLAG_NULLABLE | ATTRIBUTE_FLAG_NONVOLATILE, esp_matter_nullable_uint8(value));
|
||||
}
|
||||
|
||||
attribute_t *create_on_mode(cluster_t *cluster, nullable<uint8_t> value)
|
||||
{
|
||||
return esp_matter::attribute::create(cluster, ModeSelect::Attributes::OnMode::Id, ATTRIBUTE_FLAG_WRITABLE | ATTRIBUTE_FLAG_NULLABLE | ATTRIBUTE_FLAG_NONVOLATILE, esp_matter_nullable_uint8(value));
|
||||
}
|
||||
|
||||
} /* attribute */
|
||||
} /* mode_select */
|
||||
|
||||
} /* cluster */
|
||||
} /* esp_matter */
|
||||
|
||||
@@ -531,5 +531,18 @@ attribute_t *create_control_mode(cluster_t *cluster, uint8_t value);
|
||||
} /* attribute */
|
||||
} /* pump_configuration_and_control */
|
||||
|
||||
namespace mode_select {
|
||||
constexpr uint8_t k_max_mode_select_description_length = 64;
|
||||
|
||||
namespace attribute {
|
||||
attribute_t *create_mode_select_description(cluster_t *cluster, const char * value, uint16_t length);
|
||||
attribute_t *create_standard_namespace(cluster_t *cluster, const nullable<uint16_t> value);
|
||||
attribute_t *create_supported_modes(cluster_t *cluster, const uint8_t * value, uint16_t length, uint16_t count);
|
||||
attribute_t *create_current_mode(cluster_t *cluster, uint8_t value);
|
||||
attribute_t *create_start_up_mode(cluster_t *cluster, nullable<uint8_t> value);
|
||||
attribute_t *create_on_mode(cluster_t *cluster, nullable<uint8_t> value);
|
||||
} /* attribute */
|
||||
} /* mode_select */
|
||||
|
||||
} /* cluster */
|
||||
} /* esp_matter */
|
||||
|
||||
@@ -319,6 +319,30 @@ esp_matter_attr_val_t esp_matter_nullable_enum8(nullable<uint8_t> val)
|
||||
return attr_val;
|
||||
}
|
||||
|
||||
esp_matter_attr_val_t esp_matter_enum16(uint16_t val)
|
||||
{
|
||||
esp_matter_attr_val_t attr_val = {
|
||||
.type = ESP_MATTER_VAL_TYPE_ENUM16,
|
||||
.val = {
|
||||
.u16 = val,
|
||||
},
|
||||
};
|
||||
return attr_val;
|
||||
}
|
||||
|
||||
esp_matter_attr_val_t esp_matter_nullable_enum16(nullable<uint16_t> val)
|
||||
{
|
||||
esp_matter_attr_val_t attr_val = {
|
||||
.type = ESP_MATTER_VAL_TYPE_NULLABLE_ENUM16,
|
||||
};
|
||||
if (val.is_null()) {
|
||||
chip::app::NumericAttributeTraits<uint16_t>::SetNull(attr_val.val.u16);
|
||||
} else {
|
||||
attr_val.val.u16 = val.value();
|
||||
}
|
||||
return attr_val;
|
||||
}
|
||||
|
||||
esp_matter_attr_val_t esp_matter_bitmap8(uint8_t val)
|
||||
{
|
||||
esp_matter_attr_val_t attr_val = {
|
||||
@@ -622,6 +646,18 @@ static esp_err_t console_set_handler(int argc, char **argv)
|
||||
uint8_t value = atoi(argv[3]);
|
||||
val = esp_matter_enum8(value);
|
||||
}
|
||||
} else if (type == ESP_MATTER_VAL_TYPE_ENUM16) {
|
||||
if (matter_attribute->IsNullable()) {
|
||||
if (strncmp(argv[3], "null", sizeof("null")) == 0) {
|
||||
val = esp_matter_nullable_enum16(nullable<uint16_t>());
|
||||
} else {
|
||||
uint16_t value = atoi(argv[3]);
|
||||
val = esp_matter_nullable_enum16(value);
|
||||
}
|
||||
} else {
|
||||
uint16_t value = atoi(argv[3]);
|
||||
val = esp_matter_enum16(value);
|
||||
}
|
||||
} else {
|
||||
ESP_LOGE(TAG, "Type not handled: %d", type);
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
@@ -834,6 +870,20 @@ static esp_err_t console_get_handler(int argc, char **argv)
|
||||
} else {
|
||||
val = esp_matter_enum8(Traits::StorageToWorking(value));
|
||||
}
|
||||
} else if (type == ESP_MATTER_VAL_TYPE_ENUM16) {
|
||||
using Traits = chip::app::NumericAttributeTraits<uint16_t>;
|
||||
Traits::StorageType value;
|
||||
uint8_t *read_able = Traits::ToAttributeStoreRepresentation(value);
|
||||
get_val_raw(endpoint_id, cluster_id, attribute_id, read_able, sizeof(value));
|
||||
if (matter_attribute->IsNullable()) {
|
||||
if (Traits::IsNullValue(value)) {
|
||||
val = esp_matter_nullable_enum16(nullable<uint16_t>());
|
||||
} else {
|
||||
val = esp_matter_nullable_enum16(Traits::StorageToWorking(value));
|
||||
}
|
||||
} else {
|
||||
val = esp_matter_enum16(Traits::StorageToWorking(value));
|
||||
}
|
||||
} else {
|
||||
ESP_LOGE(TAG, "Type not handled: %d", type);
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
@@ -1573,6 +1623,22 @@ static esp_err_t get_attr_val_from_data(esp_matter_attr_val_t *val, EmberAfAttri
|
||||
break;
|
||||
}
|
||||
|
||||
case ZCL_ENUM16_ATTRIBUTE_TYPE: {
|
||||
using Traits = chip::app::NumericAttributeTraits<uint16_t>;
|
||||
Traits::StorageType attribute_value;
|
||||
memcpy((uint16_t *)&attribute_value, value, sizeof(Traits::StorageType));
|
||||
if (attribute_metadata->IsNullable()) {
|
||||
if (Traits::IsNullValue(attribute_value)) {
|
||||
*val = esp_matter_nullable_enum16(nullable<uint16_t>());
|
||||
} else {
|
||||
*val = esp_matter_nullable_enum16(attribute_value);
|
||||
}
|
||||
} else {
|
||||
*val = esp_matter_enum16(attribute_value);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case ZCL_BITMAP8_ATTRIBUTE_TYPE: {
|
||||
using Traits = chip::app::NumericAttributeTraits<uint8_t>;
|
||||
Traits::StorageType attribute_value;
|
||||
|
||||
@@ -78,6 +78,8 @@ typedef enum {
|
||||
ESP_MATTER_VAL_TYPE_BITMAP16 = 17,
|
||||
/** 32 bit bitmap */
|
||||
ESP_MATTER_VAL_TYPE_BITMAP32 = 18,
|
||||
/** 16 bit enum */
|
||||
ESP_MATTER_VAL_TYPE_ENUM16 = 19,
|
||||
/** nullable types **/
|
||||
ESP_MATTER_VAL_TYPE_NULLABLE_INTEGER = ESP_MATTER_VAL_TYPE_INTEGER + ESP_MATTER_VAL_NULLABLE_BASE,
|
||||
ESP_MATTER_VAL_TYPE_NULLABLE_FLOAT = ESP_MATTER_VAL_TYPE_FLOAT + ESP_MATTER_VAL_NULLABLE_BASE,
|
||||
@@ -93,6 +95,7 @@ typedef enum {
|
||||
ESP_MATTER_VAL_TYPE_NULLABLE_BITMAP8 = ESP_MATTER_VAL_TYPE_BITMAP8 + ESP_MATTER_VAL_NULLABLE_BASE,
|
||||
ESP_MATTER_VAL_TYPE_NULLABLE_BITMAP16 = ESP_MATTER_VAL_TYPE_BITMAP16 + ESP_MATTER_VAL_NULLABLE_BASE,
|
||||
ESP_MATTER_VAL_TYPE_NULLABLE_BITMAP32= ESP_MATTER_VAL_TYPE_BITMAP32 + ESP_MATTER_VAL_NULLABLE_BASE,
|
||||
ESP_MATTER_VAL_TYPE_NULLABLE_ENUM16 = ESP_MATTER_VAL_TYPE_ENUM16 + ESP_MATTER_VAL_NULLABLE_BASE,
|
||||
} esp_matter_val_type_t;
|
||||
|
||||
/** ESP Matter Value */
|
||||
@@ -277,6 +280,10 @@ esp_matter_attr_val_t esp_matter_nullable_uint64(nullable<uint64_t> val);
|
||||
esp_matter_attr_val_t esp_matter_enum8(uint8_t val);
|
||||
esp_matter_attr_val_t esp_matter_nullable_enum8(nullable<uint8_t> val);
|
||||
|
||||
/** 16 bit enum */
|
||||
esp_matter_attr_val_t esp_matter_enum16(uint16_t val);
|
||||
esp_matter_attr_val_t esp_matter_nullable_enum16(nullable<uint16_t> val);
|
||||
|
||||
/** 8 bit bitmap */
|
||||
esp_matter_attr_val_t esp_matter_bitmap8(uint8_t val);
|
||||
esp_matter_attr_val_t esp_matter_nullable_bitmap8(nullable<uint8_t> val);
|
||||
|
||||
@@ -1903,6 +1903,55 @@ cluster_t *create(endpoint_t *endpoint, config_t *config, uint8_t flags)
|
||||
return cluster;
|
||||
}
|
||||
} /* pump_configuration_and_control */
|
||||
|
||||
namespace mode_select {
|
||||
const function_generic_t function_list[] = {
|
||||
(function_generic_t)emberAfModeSelectClusterServerInitCallback,
|
||||
};
|
||||
const int function_flags = CLUSTER_FLAG_INIT_FUNCTION;
|
||||
|
||||
cluster_t *create(endpoint_t *endpoint, config_t *config, uint8_t flags, uint32_t features)
|
||||
{
|
||||
cluster_t *cluster = cluster::create(endpoint, ModeSelect::Id, flags);
|
||||
if (!cluster) {
|
||||
ESP_LOGE(TAG, "Could not create cluster");
|
||||
return NULL;
|
||||
}
|
||||
if (flags & CLUSTER_FLAG_SERVER) {
|
||||
set_plugin_server_init_callback(cluster, MatterPumpConfigurationAndControlPluginServerInitCallback);
|
||||
add_function_list(cluster, function_list, function_flags);
|
||||
|
||||
/* Attributes managed internally */
|
||||
global::attribute::create_feature_map(cluster, 0);
|
||||
#if CHIP_CONFIG_ENABLE_EVENTLIST_ATTRIBUTE
|
||||
global::attribute::create_event_list(cluster, NULL, 0, 0);
|
||||
#endif
|
||||
attribute::create_supported_modes(cluster, NULL, 0, 0);
|
||||
/** Attributes not managed internally **/
|
||||
if (config) {
|
||||
global::attribute::create_cluster_revision(cluster, config->cluster_revision);
|
||||
attribute::create_mode_select_description(cluster, config->mode_select_description, strlen(config->mode_select_description));
|
||||
attribute::create_standard_namespace(cluster, config->standard_namespace);
|
||||
attribute::create_current_mode(cluster, config->current_mode);
|
||||
} else {
|
||||
ESP_LOGE(TAG, "Config is NULL. Cannot add some attributes.");
|
||||
}
|
||||
}
|
||||
if (flags & CLUSTER_FLAG_CLIENT) {
|
||||
create_default_binding_cluster(endpoint);
|
||||
}
|
||||
|
||||
/* Commands */
|
||||
command::create_change_to_mode(cluster);
|
||||
|
||||
/* Features */
|
||||
if (features & feature::on_off::get_id()) {
|
||||
feature::on_off::add(cluster, &(config->on_off));
|
||||
}
|
||||
return cluster;
|
||||
}
|
||||
} /* mode_select */
|
||||
|
||||
#endif /* CONFIG_ESP_MATTER_ENABLE_DATA_MODEL */
|
||||
} /* cluster */
|
||||
} /* esp_matter */
|
||||
|
||||
@@ -471,5 +471,35 @@ typedef struct config {
|
||||
cluster_t *create(endpoint_t *endpoint, config_t *config, uint8_t flags);
|
||||
} /* pump_configuration_and_control */
|
||||
|
||||
namespace mode_select {
|
||||
typedef struct config {
|
||||
uint16_t cluster_revision;
|
||||
char mode_select_description[k_max_mode_select_description_length + 1];
|
||||
const nullable<uint16_t> standard_namespace;
|
||||
uint8_t current_mode;
|
||||
feature::on_off::config_t on_off;
|
||||
config() : cluster_revision(2), mode_select_description{0}, standard_namespace(), current_mode(0) {}
|
||||
} config_t;
|
||||
|
||||
cluster_t *create(endpoint_t *endpoint, config_t *config, uint8_t flags, uint32_t features);
|
||||
} /* mode_select */
|
||||
|
||||
} /* cluster */
|
||||
} /* esp_matter */
|
||||
|
||||
// To avoid compilation error function is defined weak here
|
||||
namespace chip {
|
||||
namespace app {
|
||||
namespace Clusters {
|
||||
namespace ModeSelect {
|
||||
|
||||
void* __attribute__((weak)) getSupportedModesManager()
|
||||
{
|
||||
// weak func
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
} /* chip */
|
||||
} /* app */
|
||||
} /* Clusters */
|
||||
} /* ModeSelect */
|
||||
|
||||
@@ -80,6 +80,17 @@ void DispatchSingleClusterCommand(const ConcreteCommandPath &command_path, TLVRe
|
||||
} /* namespace app */
|
||||
} /* namespace chip */
|
||||
|
||||
static esp_err_t esp_matter_command_callback_change_to_mode(const ConcreteCommandPath &command_path, TLVReader &tlv_data, void *opaque_ptr)
|
||||
{
|
||||
chip::app::Clusters::ModeSelect::Commands::ChangeToMode::DecodableType command_data;
|
||||
CHIP_ERROR error = Decode(tlv_data, command_data);
|
||||
if (error == CHIP_NO_ERROR) {
|
||||
emberAfModeSelectClusterChangeToModeCallback((CommandHandler *)opaque_ptr, command_path, command_data);
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
|
||||
static esp_err_t esp_matter_command_callback_key_set_write(const ConcreteCommandPath &command_path, TLVReader &tlv_data,
|
||||
void *opaque_ptr)
|
||||
{
|
||||
@@ -2094,6 +2105,17 @@ command_t *create_go_to_tilt_percentage(cluster_t *cluster)
|
||||
} /* command */
|
||||
} /* window_covering */
|
||||
|
||||
namespace mode_select {
|
||||
namespace command {
|
||||
command_t *create_change_to_mode(cluster_t *cluster)
|
||||
{
|
||||
return esp_matter::command::create(cluster, ModeSelect::Commands::ChangeToMode::Id, COMMAND_FLAG_ACCEPTED, esp_matter_command_callback_change_to_mode);
|
||||
}
|
||||
|
||||
} /* command */
|
||||
} /* mode_select */
|
||||
|
||||
|
||||
} /* cluster */
|
||||
} /* esp_matter */
|
||||
|
||||
|
||||
@@ -255,5 +255,11 @@ command_t *create_go_to_tilt_percentage(cluster_t *cluster);
|
||||
} /* command */
|
||||
} /* window_covering */
|
||||
|
||||
namespace mode_select {
|
||||
namespace command {
|
||||
command_t *create_change_to_mode(cluster_t *cluster);
|
||||
} /* command */
|
||||
} /* mode_select */
|
||||
|
||||
} /* cluster */
|
||||
} /* esp_matter */
|
||||
|
||||
@@ -911,6 +911,49 @@ endpoint_t *add(endpoint_t *endpoint, config_t *config)
|
||||
}
|
||||
} /** pump **/
|
||||
|
||||
namespace mode_select_device {
|
||||
uint32_t get_device_type_id()
|
||||
{
|
||||
return ESP_MATTER_MODE_SELECT_DEVICE_TYPE_ID;
|
||||
}
|
||||
|
||||
uint8_t get_device_type_version()
|
||||
{
|
||||
return ESP_MATTER_MODE_SELECT_DEVICE_TYPE_VERSION;
|
||||
}
|
||||
|
||||
endpoint_t *create(node_t *node, config_t *config, uint8_t flags, void *priv_data)
|
||||
{
|
||||
endpoint_t *endpoint = endpoint::create(node, flags, priv_data);
|
||||
add(endpoint, config);
|
||||
return endpoint;
|
||||
}
|
||||
|
||||
esp_err_t add(endpoint_t *endpoint, config_t *config)
|
||||
{
|
||||
if (!endpoint) {
|
||||
ESP_LOGE(TAG, "Endpoint cannot be NULL");
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
esp_err_t err = add_device_type(endpoint, get_device_type_id(), get_device_type_version());
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to add device type id:%" PRIu32 ",err: %d", get_device_type_id(), err);
|
||||
return err;
|
||||
}
|
||||
|
||||
cluster_t *cluster = descriptor::create(endpoint, CLUSTER_FLAG_SERVER);
|
||||
if (!cluster) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
cluster = mode_select::create(endpoint, &(config->mode_select), CLUSTER_FLAG_SERVER, ESP_MATTER_NONE_FEATURE_ID);
|
||||
if (!cluster) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
} /** mode_select_device **/
|
||||
|
||||
} /* endpoint */
|
||||
|
||||
namespace node {
|
||||
|
||||
@@ -74,6 +74,8 @@
|
||||
#define ESP_MATTER_WINDOW_COVERING_DEVICE_TYPE_VERSION 2
|
||||
#define ESP_MATTER_PUMP_DEVICE_TYPE_ID 0x0303
|
||||
#define ESP_MATTER_PUMP_DEVICE_TYPE_VERSION 2
|
||||
#define ESP_MATTER_MODE_SELECT_DEVICE_TYPE_ID 0x0027
|
||||
#define ESP_MATTER_MODE_SELECT_DEVICE_TYPE_VERSION 1
|
||||
|
||||
namespace esp_matter {
|
||||
|
||||
@@ -417,6 +419,17 @@ endpoint_t *create(node_t *node, config_t *config, uint8_t flags, void *priv_dat
|
||||
endpoint_t *add(endpoint_t *endpoint, config_t *config);
|
||||
} /** pump **/
|
||||
|
||||
namespace mode_select_device {
|
||||
typedef struct config {
|
||||
cluster::mode_select::config_t mode_select;
|
||||
} config_t;
|
||||
|
||||
uint32_t get_device_type_id();
|
||||
uint8_t get_device_type_version();
|
||||
endpoint_t *create(node_t *node, config_t *config, uint8_t flags, void *priv_data);
|
||||
esp_err_t add(endpoint_t *endpoint, config_t *config);
|
||||
} /** mode_select_device **/
|
||||
|
||||
} /* endpoint */
|
||||
|
||||
namespace node {
|
||||
|
||||
@@ -986,5 +986,32 @@ esp_err_t add(cluster_t *cluster, config_t *config)
|
||||
} /* feature */
|
||||
} /* time_format_localization */
|
||||
|
||||
namespace mode_select {
|
||||
namespace feature {
|
||||
|
||||
namespace on_off {
|
||||
|
||||
uint32_t get_id()
|
||||
{
|
||||
return (uint32_t)ModeSelect::ModeSelectFeature::kDeponoff;
|
||||
}
|
||||
|
||||
esp_err_t add(cluster_t *cluster, config_t *config)
|
||||
{
|
||||
if (!cluster) {
|
||||
ESP_LOGE(TAG, "Cluster cannot be NULL");
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
update_feature_map(cluster, get_id());
|
||||
|
||||
attribute::create_on_mode(cluster, config->on_mode);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
} /* on_off */
|
||||
|
||||
} /* feature */
|
||||
} /* mode_select */
|
||||
|
||||
} /* cluster */
|
||||
} /* esp_matter */
|
||||
|
||||
@@ -422,5 +422,23 @@ esp_err_t add(cluster_t *cluster, config_t *config);
|
||||
} /* feature */
|
||||
} /* time_format_localization */
|
||||
|
||||
namespace mode_select {
|
||||
namespace feature {
|
||||
|
||||
namespace on_off {
|
||||
|
||||
typedef struct config {
|
||||
nullable<uint8_t> on_mode;
|
||||
config() : on_mode() {}
|
||||
} config_t;
|
||||
|
||||
uint32_t get_id();
|
||||
esp_err_t add(cluster_t *cluster, config_t *config);
|
||||
|
||||
} /* on_off */
|
||||
|
||||
} /* feature */
|
||||
} /* mode_select */
|
||||
|
||||
} /* cluster */
|
||||
} /* esp_matter */
|
||||
|
||||
Reference in New Issue
Block a user