mirror of
https://github.com/espressif/esp-matter.git
synced 2026-04-27 19:13:13 +00:00
Merge branch 'deferred_attribute' into 'main'
esp_matter: Add deferred attribute flag for non-volatile attributes which might change rapidly Closes CON-909 See merge request app-frameworks/esp-matter!563
This commit is contained in:
@@ -20,6 +20,13 @@ menu "ESP Matter"
|
||||
help
|
||||
The NVS Partition name for ESP Matter to store the NONVOLATILE attribues
|
||||
|
||||
config ESP_MATTER_DEFERRED_ATTR_PERSISTENCE_TIME_MS
|
||||
int "ESP Matter deferred attribute persistence time (ms)"
|
||||
default 3000
|
||||
help
|
||||
Some non-volatile attributes might be changed frequently, which might result in rapid flash wearout.
|
||||
For those attributes, set the flag 'ATTRIBUTE_FLAG_DEFERRED' to defer the flash-writing for the time.
|
||||
|
||||
choice ESP_MATTER_DAC_PROVIDER
|
||||
prompt "DAC Provider options"
|
||||
default FACTORY_PARTITION_DAC_PROVIDER if ENABLE_ESP32_FACTORY_DATA_PROVIDER
|
||||
|
||||
@@ -84,6 +84,10 @@ typedef enum attribute_flags {
|
||||
/** The attribute read and write are overridden. The attribute value will be fetched from and will be updated using
|
||||
the override callback. The value of this attribute is not maintained internally. */
|
||||
ATTRIBUTE_FLAG_OVERRIDE = ATTRIBUTE_FLAG_NULLABLE << 1, /* 0x100 */
|
||||
/** The attribute is non-volatile but its value will be changed frequently. If an attribute has this flag, its value
|
||||
will not be written to flash immediately. A timer will be started and the attribute value will be written after
|
||||
timeout. */
|
||||
ATTRIBUTE_FLAG_DEFERRED = ATTRIBUTE_FLAG_NULLABLE << 2, /* 0x200 */
|
||||
} attribute_flags_t;
|
||||
|
||||
/** Command flags */
|
||||
|
||||
@@ -1233,6 +1233,17 @@ uint32_t get_id(attribute_t *attribute)
|
||||
return current_attribute->attribute_id;
|
||||
}
|
||||
|
||||
constexpr uint16_t k_deferred_attribute_persistence_time_ms = CONFIG_ESP_MATTER_DEFERRED_ATTR_PERSISTENCE_TIME_MS;
|
||||
|
||||
static void deferred_attribute_write(chip::System::Layer *layer, void *attribute_ptr)
|
||||
{
|
||||
_attribute_t *current_attribute = (_attribute_t *)attribute_ptr;
|
||||
ESP_LOGI(TAG, "Store the deferred attribute 0x%" PRIx32 " of cluster 0x%" PRIX32 " on endpoint 0x%" PRIx16,
|
||||
current_attribute->attribute_id, current_attribute->cluster_id, current_attribute->endpoint_id);
|
||||
store_val_in_nvs(current_attribute->endpoint_id, current_attribute->cluster_id, current_attribute->attribute_id,
|
||||
current_attribute->val);
|
||||
}
|
||||
|
||||
esp_err_t set_val(attribute_t *attribute, esp_matter_attr_val_t *val)
|
||||
{
|
||||
if (!attribute) {
|
||||
@@ -1269,8 +1280,17 @@ esp_err_t set_val(attribute_t *attribute, esp_matter_attr_val_t *val)
|
||||
}
|
||||
|
||||
if (current_attribute->flags & ATTRIBUTE_FLAG_NONVOLATILE) {
|
||||
store_val_in_nvs(current_attribute->endpoint_id, current_attribute->cluster_id,
|
||||
current_attribute->attribute_id, current_attribute->val);
|
||||
if (current_attribute->flags & ATTRIBUTE_FLAG_DEFERRED) {
|
||||
if (chip::DeviceLayer::SystemLayer().IsTimerActive(deferred_attribute_write, current_attribute)) {
|
||||
chip::DeviceLayer::SystemLayer().CancelTimer(deferred_attribute_write, current_attribute);
|
||||
}
|
||||
auto & system_layer = chip::DeviceLayer::SystemLayer();
|
||||
system_layer.StartTimer(chip::System::Clock::Milliseconds16(k_deferred_attribute_persistence_time_ms),
|
||||
deferred_attribute_write, current_attribute);
|
||||
} else {
|
||||
store_val_in_nvs(current_attribute->endpoint_id, current_attribute->cluster_id,
|
||||
current_attribute->attribute_id, current_attribute->val);
|
||||
}
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
@@ -1380,6 +1400,21 @@ callback_t get_override_callback(attribute_t *attribute)
|
||||
return current_attribute->override_callback;
|
||||
}
|
||||
|
||||
esp_err_t set_deferred_persistence(attribute_t *attribute)
|
||||
{
|
||||
if (!attribute) {
|
||||
ESP_LOGE(TAG, "Attribute cannot be NULL");
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
_attribute_t *current_attribute = (_attribute_t *)attribute;
|
||||
if (!(current_attribute->flags & ATTRIBUTE_FLAG_NONVOLATILE)) {
|
||||
ESP_LOGE(TAG, "Attribute should be non-volatile to set a deferred persistence time");
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
current_attribute->flags |= ATTRIBUTE_FLAG_DEFERRED;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
} /* attribute */
|
||||
|
||||
namespace command {
|
||||
|
||||
@@ -582,6 +582,22 @@ esp_err_t set_override_callback(attribute_t *attribute, callback_t callback);
|
||||
*/
|
||||
callback_t get_override_callback(attribute_t *attribute);
|
||||
|
||||
/** Set attribute deferred persistence
|
||||
*
|
||||
* Only non-volatile attributes can be set with deferred presistence. If an attribute is configured with deferred
|
||||
* presistence, any modifications to it will be enacted in its persistent storage with a specific delay
|
||||
* (CONFIG_ESP_MATTER_DEFERRED_ATTR_PERSISTENCE_TIME_MS)
|
||||
*
|
||||
* It could be used for the non-volatile attribues which might be changed rapidly, such as CurrentLevel in LevelControl
|
||||
* cluster.
|
||||
*
|
||||
* @param[in] attribute Attribute handle.
|
||||
*
|
||||
* @return ESP_OK on success.
|
||||
* @return error in case of failure.
|
||||
*/
|
||||
esp_err_t set_deferred_persistence(attribute_t *attribute);
|
||||
|
||||
} /* attribute */
|
||||
|
||||
namespace command {
|
||||
|
||||
@@ -176,6 +176,19 @@ extern "C" void app_main()
|
||||
light_endpoint_id = endpoint::get_id(endpoint);
|
||||
ESP_LOGI(TAG, "Light created with endpoint_id %d", light_endpoint_id);
|
||||
|
||||
/* Mark deferred persistence for some attributes that might be changed rapidly */
|
||||
cluster_t *level_control_cluster = cluster::get(endpoint, LevelControl::Id);
|
||||
attribute_t *current_level_attribute = attribute::get(level_control_cluster, LevelControl::Attributes::CurrentLevel::Id);
|
||||
attribute::set_deferred_persistence(current_level_attribute);
|
||||
|
||||
cluster_t *color_control_cluster = cluster::get(endpoint, ColorControl::Id);
|
||||
attribute_t *current_x_attribute = attribute::get(color_control_cluster, ColorControl::Attributes::CurrentX::Id);
|
||||
attribute::set_deferred_persistence(current_x_attribute);
|
||||
attribute_t *current_y_attribute = attribute::get(color_control_cluster, ColorControl::Attributes::CurrentY::Id);
|
||||
attribute::set_deferred_persistence(current_y_attribute);
|
||||
attribute_t *color_temp_attribute = attribute::get(color_control_cluster, ColorControl::Attributes::ColorTemperatureMireds::Id);
|
||||
attribute::set_deferred_persistence(color_temp_attribute);
|
||||
|
||||
#if CHIP_DEVICE_CONFIG_ENABLE_THREAD
|
||||
/* Set OpenThread platform config */
|
||||
esp_openthread_platform_config_t config = {
|
||||
|
||||
Reference in New Issue
Block a user