Added support of mode select

This commit is contained in:
Rohit Jadhav
2023-03-23 16:40:25 +05:30
parent e2382ede17
commit f5e80e7482
18 changed files with 460 additions and 5 deletions
+3
View File
@@ -1,4 +1,5 @@
set(SRC_DIRS_LIST "."
"${MATTER_SDK_PATH}"
"${MATTER_SDK_PATH}/zzz_generated/app-common/app-common/zap-generated/attributes"
"${MATTER_SDK_PATH}/src/app"
"${MATTER_SDK_PATH}/src/app/server"
@@ -61,6 +62,8 @@ set(SRC_DIRS_LIST "."
"${MATTER_SDK_PATH}/src/app/clusters/wake-on-lan-server"
"${MATTER_SDK_PATH}/src/app/clusters/wifi-network-diagnostics-server"
"${MATTER_SDK_PATH}/src/app/clusters/window-covering-server"
"${MATTER_SDK_PATH}/src/app/clusters/mode-select-server"
"${MATTER_SDK_PATH}/examples/platform/esp32/mode-support"
)
set(INCLUDE_DIRS_LIST "."
@@ -2176,5 +2176,41 @@ 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, char * value, uint16_t length)
{
return esp_matter::attribute::create(cluster, ModeSelect::Attributes::Description::Id, ATTRIBUTE_FLAG_NONE, esp_matter_char_str(value, 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_NONE, 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 */
@@ -523,5 +523,16 @@ 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, 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;
@@ -980,6 +1030,10 @@ static esp_matter_val_type_t get_val_type_from_attribute_type(int attribute_type
return ESP_MATTER_VAL_TYPE_ENUM8;
break;
case ZCL_ENUM16_ATTRIBUTE_TYPE:
return ESP_MATTER_VAL_TYPE_ENUM16;
break;
case ZCL_BITMAP8_ATTRIBUTE_TYPE:
return ESP_MATTER_VAL_TYPE_BITMAP8;
break;
@@ -1011,6 +1065,7 @@ bool val_is_null(esp_matter_attr_val_t *val)
return chip::app::NumericAttributeTraits<uint8_t>::IsNullValue(val->val.u8);
break;
case ESP_MATTER_VAL_TYPE_NULLABLE_UINT16:
case ESP_MATTER_VAL_TYPE_NULLABLE_ENUM16:
case ESP_MATTER_VAL_TYPE_NULLABLE_BITMAP16:
return chip::app::NumericAttributeTraits<uint16_t>::IsNullValue(val->val.u16);
break;
@@ -1300,6 +1355,24 @@ esp_err_t get_data_from_attr_val(esp_matter_attr_val_t *val, EmberAfAttributeTyp
}
break;
case ESP_MATTER_VAL_TYPE_ENUM16:
case ESP_MATTER_VAL_TYPE_NULLABLE_ENUM16:
if (attribute_type) {
*attribute_type = ZCL_ENUM16_ATTRIBUTE_TYPE;
}
if (attribute_size) {
*attribute_size = sizeof(uint16_t);
}
if (value) {
using Traits = chip::app::NumericAttributeTraits<uint16_t>;
if ((val->type & ESP_MATTER_VAL_NULLABLE_BASE) && Traits::IsNullValue(val->val.u16)) {
Traits::SetNull(*(uint16_t *)value);
} else {
Traits::WorkingToStorage(val->val.u16, *(uint16_t *)value);
}
}
break;
case ESP_MATTER_VAL_TYPE_BITMAP8:
case ESP_MATTER_VAL_TYPE_NULLABLE_BITMAP8:
if (attribute_type) {
@@ -1548,6 +1621,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;
@@ -1617,8 +1706,7 @@ void val_print(uint16_t endpoint_id, uint32_t cluster_id, uint32_t attribute_id,
} else if (val->type == ESP_MATTER_VAL_TYPE_INT16 || val->type == ESP_MATTER_VAL_TYPE_NULLABLE_INT16) {
ESP_LOGI(TAG, "********** %c : Endpoint 0x%04" PRIX16 "'s Cluster 0x%08" PRIX32 "'s Attribute 0x%08" PRIX32 " is %" PRIi16 " **********", action,
endpoint_id, cluster_id, attribute_id, val->val.i16);
} else if (val->type == ESP_MATTER_VAL_TYPE_UINT16 || val->type == ESP_MATTER_VAL_TYPE_BITMAP16
|| val->type == ESP_MATTER_VAL_TYPE_NULLABLE_UINT16 || val->type == ESP_MATTER_VAL_TYPE_NULLABLE_BITMAP16) {
} else if (val->type == ESP_MATTER_VAL_TYPE_UINT16 || val->type == ESP_MATTER_VAL_TYPE_BITMAP16 || val->type == ESP_MATTER_VAL_TYPE_ENUM16 || val->type == ESP_MATTER_VAL_TYPE_NULLABLE_UINT16 || val->type == ESP_MATTER_VAL_TYPE_NULLABLE_BITMAP16 || val->type == ESP_MATTER_VAL_TYPE_NULLABLE_ENUM16) {
ESP_LOGI(TAG, "********** %c : Endpoint 0x%04" PRIX16 "'s Cluster 0x%08" PRIX32 "'s Attribute 0x%08" PRIX32 " is %" PRIu16 " **********", action,
endpoint_id, cluster_id, attribute_id, val->val.u16);
} else if (val->type == ESP_MATTER_VAL_TYPE_INT32|| val->type == ESP_MATTER_VAL_TYPE_NULLABLE_INT32) {
@@ -72,12 +72,14 @@ typedef enum {
ESP_MATTER_VAL_TYPE_UINT64 = 14,
/** 8 bit enum */
ESP_MATTER_VAL_TYPE_ENUM8 = 15,
/** 16 bit enum */
ESP_MATTER_VAL_TYPE_ENUM16 = 16,
/** 8 bit bitmap */
ESP_MATTER_VAL_TYPE_BITMAP8 = 16,
ESP_MATTER_VAL_TYPE_BITMAP8 = 17,
/** 16 bit bitmap */
ESP_MATTER_VAL_TYPE_BITMAP16 = 17,
ESP_MATTER_VAL_TYPE_BITMAP16 = 18,
/** 32 bit bitmap */
ESP_MATTER_VAL_TYPE_BITMAP32 = 18,
ESP_MATTER_VAL_TYPE_BITMAP32 = 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,
@@ -90,6 +92,7 @@ typedef enum {
ESP_MATTER_VAL_TYPE_NULLABLE_INT64 = ESP_MATTER_VAL_TYPE_INT64 + ESP_MATTER_VAL_NULLABLE_BASE,
ESP_MATTER_VAL_TYPE_NULLABLE_UINT64 = ESP_MATTER_VAL_TYPE_UINT64 + ESP_MATTER_VAL_NULLABLE_BASE,
ESP_MATTER_VAL_TYPE_NULLABLE_ENUM8 = ESP_MATTER_VAL_TYPE_ENUM8 + 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_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,
@@ -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);
@@ -1760,6 +1760,54 @@ 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, MatterModeSelectPluginServerInitCallback);
add_function_list(cluster, function_list, function_flags);
}
if (flags & CLUSTER_FLAG_CLIENT) {
create_default_binding_cluster(endpoint);
}
if (flags & CLUSTER_FLAG_SERVER) {
/* Attributes managed internally */
global::attribute::create_feature_map(cluster, 0);
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, sizeof(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.");
}
}
/* Commands */
command::create_change_to_mode(cluster);
/* Features */
if (features & feature::dep_on_off::get_id()) {
feature::dep_on_off::add(cluster, &(config->dep_on_off));
}
return cluster;
}
} /* mode_select */
#endif /* CONFIG_ESP_MATTER_ENABLE_DATA_MODEL */
} /* cluster */
} /* esp_matter */
@@ -470,5 +470,18 @@ 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[64];
const nullable<uint16_t> standard_namespace;
uint8_t current_mode;
feature::dep_on_off::config_t dep_on_off;
config() : cluster_revision(1), 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 */
@@ -986,6 +986,16 @@ static esp_err_t esp_matter_command_callback_go_to_tilt_percentage(const Concret
return ESP_OK;
}
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_instance_action(const ConcreteCommandPath &command_path,
TLVReader &tlv_data, void *opaque_ptr)
{
@@ -2010,6 +2020,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 */
+15
View File
@@ -2068,6 +2068,21 @@ endpoint_t *get_next(endpoint_t *endpoint)
return (endpoint_t *)current_endpoint->next;
}
uint16_t get_endpoint_count(node_t *node)
{
if (!node) {
ESP_LOGE(TAG, "Node cannot be NULL");
return 0;
}
uint16_t count = 0;
endpoint_t *endpoint = get_first(node);
while (endpoint) {
count++;
endpoint = get_next(endpoint);
}
return count;
}
uint16_t get_id(endpoint_t *endpoint)
{
if (!endpoint) {
+2
View File
@@ -201,6 +201,8 @@ endpoint_t *get_first(node_t *node);
*/
endpoint_t *get_next(endpoint_t *endpoint);
uint16_t get_endpoint_count(node_t *node);
/** Get endpoint ID
*
* Get the endpoint ID for the endpoint.
@@ -911,6 +911,38 @@ 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);
return add(endpoint, config);
}
endpoint_t *add(endpoint_t *endpoint, config_t *config)
{
if (!endpoint) {
ESP_LOGE(TAG, "Could not create endpoint");
return NULL;
}
add_device_type(endpoint, get_device_type_id(), get_device_type_version());
descriptor::create(endpoint, CLUSTER_FLAG_SERVER);
mode_select::create(endpoint, &(config->mode_select), CLUSTER_FLAG_SERVER, ESP_MATTER_NONE_FEATURE_ID);
return endpoint;
}
} /** 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);
endpoint_t *add(endpoint_t *endpoint, config_t *config);
} /** mode_select_device **/
} /* endpoint */
namespace node {
@@ -986,5 +986,34 @@ esp_err_t add(cluster_t *cluster, config_t *config)
} /* feature */
} /* time_format_localization */
namespace mode_select {
namespace feature {
namespace dep_on_off {
uint32_t get_id()
{
// enum class for DepOnOff is not present in the upstream code.
// Return the code according to the SPEC
return 0x00;
}
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;
}
} /* dep_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 dep_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);
} /* dep_on_off */
} /* feature */
} /* mode_select */
} /* cluster */
} /* esp_matter */
+47
View File
@@ -1201,3 +1201,50 @@ Please follow the steps below to enable and use encrypted application images for
NOTE: There are several ways to store the private key, such as hardcoding it in the firmware, embedding it as a text
file, or reading it from the NVS. We have demonstrated the use of the private key by embedding it as a text file in the
light example.
2.7.2 Mode Select
==================
This cluster provides an interface for controlling a characteristic of a device that can be set to one of several predefined values. For example, the light pattern of a disco ball, the mode of a massage chair, or the wash cycle of a laundry machine.
2.7.2.1 Attribute Supported Modes
---------------------------------
This attribute is the list of supported modes that may be selected for the CurrentMode attribute. Each item in this list represents a unique mode as indicated by the Mode field of the ModeOptionStruct. Each entry in this list SHALL have a unique value for the Mode field.
ESP_MATTER uses factory partition to set the values of Supported Modes attribute.
2.7.2.2 Generate Factory Partition Using mfg_tool
-------------------------------------------------
Use `mfg_tool <https://github.com/espressif/esp-matter/blob/main/tools/mfg_tool/README.md>`__ to generate factory partition of the supported modes attribute.
2.7.2.2.1 Usage
---------------
::
cd tools/mfg_tool
./mfg_tool.py -cn "My bulb" -v 0xFFF2 -p 0x8001 --pai \
-k path/to/esp-matter/connectedhomeip/connectedhomeip/credentials/test/attestation/Chip-Test-PAI-FFF2-8001-Key.pem \
-c path/to/esp-matter/connectedhomeip/connectedhomeip/credentials/test/attestation/Chip-Test-PAI-FFF2-8001-Cert.pem \
-cd path/to/esp-matter/connectedhomeip/connectedhomeip/credentials/test/certification-declaration/Chip-Test-CD-FFF2-8001.der \
--supported-modes mode1/label1/endpointId/"value\\mfgCode, value\\mfgCode" mode2/label2/endpointId/"value\\mfgCode, value\\mfgCode"
2.7.2.3 Build example
---------------------
For example we want to use mode_select cluster in light example.
- In file example/light/app_main.cpp.
::
#include <examples/platform/esp32/mode-support/static-supported-modes-manager.h>
{
cluster::mode_select::config_t ms_config;
cluster_t *ms_cluster = cluster::mode_select::create(endpoint, &ms_config, CLUSTER_FLAG_SERVER, ESP_MATTER_NONE_FEATURE_ID);
ModeSelect::StaticSupportedModesManager obj;
obj.InitEndpointArray(get_endpoint_count(node));
}
+39
View File
@@ -524,6 +524,9 @@ def get_args():
g_dev_inst.add_argument('--fixed-labels', nargs='+',
help='List of fixed labels, eg: "0/orientation/up" "1/orientation/down" "2/orientation/down"')
g_dev_inst.add_argument('--supported-modes', type=str, nargs='+', required=False,
help='List of supported modes, eg: mode1/label1/ep/"tagValue1\\mfgCode, tagValue2\\mfgCode" mode2/label2/ep/"tagValue1\\mfgCode, tagValue2\\mfgCode" mode3/label3/ep/"tagValue1\\mfgCode, tagValue2\\mfgCode"')
g_basic = parser.add_argument_group('Few more Basic clusters options')
g_basic.add_argument('--product-label', help='Product label')
g_basic.add_argument('--product-url', help='Product URL')
@@ -598,6 +601,42 @@ def add_optional_KVs(args):
chip_factory_append('fl-k/{:x}/{:x}'.format(int(key), i), 'data', 'string', list(entry.keys())[0])
chip_factory_append('fl-v/{:x}/{:x}'.format(int(key), i), 'data', 'string', list(entry.values())[0])
# SupportedModes are stored as multiple entries
# - sm-sz/<ep> : number of supported modes for the endpoint
# - sm-label/<ep>/<index> : supported modes label key for the endpoint and index
# - sm-mode/<ep>/<index> : supported modes mode key for the endpoint and index
# - sm-st-sz/<ep>/<index> : supported modes SemanticTag key for the endpoint and index
# - st-v/<ep>/<index>/<ind> : semantic tag value key for the endpoint and index and ind
# - st-mfg/<ep>/<index>/<ind> : semantic tag mfg code key for the endpoint and index and ind
if (args.supported_modes is not None):
dictionary = get_supported_modes_dict(args.supported_modes)
for ep in dictionary.keys():
chip_factory_append('sm-sz/{:x}'.format(int(ep)), 'data', 'u32', len(dictionary[ep]))
for i in range(len(dictionary[ep])):
item = dictionary[ep][i]
chip_factory_append('sm-label/{:x}/{:x}'.format(int(ep), i), 'data', 'string', item["Label"])
chip_factory_append('sm-mode/{:x}/{:x}'.format(int(ep), i), 'data', 'u32', item["Mode"])
chip_factory_append('sm-st-sz/{:x}/{:x}'.format(int(ep), i), 'data', 'u32', len(item["Semantic_Tag"]))
for j in range(len(item["Semantic_Tag"])):
entry = item["Semantic_Tag"][j]
_value = {
'type': 'data',
'encoding': 'u32',
'value': entry["value"]
}
_mfg_code = {
'type': 'data',
'encoding': 'u32',
'value': entry["mfgCode"]
}
chip_factory_append('st-v/{:x}/{:x}/{:x}'.format(int(ep), i, j), 'data', 'u32', entry["value"])
chip_factory_append('st-mfg/{:x}/{:x}/{:x}'.format(int(ep), i, j), 'data', 'u32', entry["mfgCode"])
# Keys from basic clusters
if args.product_label is not None:
chip_factory_append('product-label', 'data', 'string', args.product_label)
+27
View File
@@ -234,6 +234,33 @@ def get_fixed_label_dict(fixed_labels):
return fl_dict
# get_supported_modes_dict() converts the list of strings to per endpoint dictionaries.
# example input : ['0/label1/1/"1\0x8000, 2\0x8000", 1/label2/1/"1\0x8000, 2\0x8000"']
# example outout : {'1': [{'Label': 'label1', 'Mode': 0, 'Semantic_Tag': [{'value': 1, 'mfgCode': 32768}, {'value': 2, 'mfgCode': 32768}]}, {'Label': 'label2', 'Mode': 1, 'Semantic_Tag': [{'value': 1, 'mfgCode': 32768}, {'value': 2, 'mfgCode': 32768}]}]}
def get_supported_modes_dict(supported_modes):
output_dict = {}
for mode_str in supported_modes:
mode_label_strs = mode_str.split('/')
mode = mode_label_strs[0]
label = mode_label_strs[1]
ep = mode_label_strs[2]
semantic_tag_strs = mode_label_strs[3].split(', ')
semantic_tags = [{"value": int(v.split('\\')[0]), "mfgCode": int(v.split('\\')[1], 16)} for v in semantic_tag_strs]
mode_dict = {"Label": label, "Mode": int(mode), "Semantic_Tag": semantic_tags}
if ep in output_dict:
output_dict[ep].append(mode_dict)
else:
output_dict[ep] = [mode_dict]
return output_dict
# Convert the certificate in PEM format to DER format
def convert_x509_cert_from_pem_to_der(pem_file, out_der_file):
with open(pem_file, 'rb') as f: