Skip to content

Commit 657d118

Browse files
committed
feat(matter): fixes step attibute issue from esp-matter
1 parent 51d1bd8 commit 657d118

File tree

3 files changed

+49
-20
lines changed

3 files changed

+49
-20
lines changed

docs/en/matter/ep_temperature_controlled_cabinet.rst

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,17 @@ MatterTemperatureControlledCabinet
55
About
66
-----
77

8-
The ``MatterTemperatureControlledCabinet`` class provides a temperature controlled cabinet endpoint for Matter networks. This endpoint implements the Matter temperature control standard for managing temperature setpoints with min/max limits, optional step control, or temperature level support.
8+
The ``MatterTemperatureControlledCabinet`` class provides a temperature controlled cabinet endpoint for Matter networks. This endpoint implements the Matter temperature control standard for managing temperature setpoints with min/max limits, step control (always enabled), or temperature level support.
99

1010
**Important:** The ``temperature_number`` and ``temperature_level`` features are **mutually exclusive**. Only one can be enabled at a time. Use ``begin(tempSetpoint, minTemp, maxTemp, step)`` for temperature_number mode or ``begin(supportedLevels, levelCount, selectedLevel)`` for temperature_level mode.
1111

1212
**Features:**
1313
* Two initialization modes:
14-
* **Temperature Number Mode** (``begin(tempSetpoint, minTemp, maxTemp, step)``): Temperature setpoint control with min/max limits and optional step
14+
* **Temperature Number Mode** (``begin(tempSetpoint, minTemp, maxTemp, step)``): Temperature setpoint control with min/max limits and step control (step value can be set in begin() or later)
1515
* **Temperature Level Mode** (``begin(supportedLevels, levelCount, selectedLevel)``): Temperature level control with array of supported levels
1616
* 1/100th degree Celsius precision (for temperature_number mode)
1717
* Min/max temperature limits with validation (temperature_number mode)
18-
* Optional temperature step control (temperature_number mode)
18+
* Temperature step control (temperature_number mode, always enabled)
1919
* Temperature level array support (temperature_level mode)
2020
* Automatic setpoint validation against limits
2121
* Feature validation - methods return errors if called with wrong feature mode
@@ -62,11 +62,11 @@ Initializes the Matter temperature controlled cabinet endpoint with **temperatur
6262
* ``tempSetpoint`` - Initial temperature setpoint in Celsius (default: 0.00)
6363
* ``minTemperature`` - Minimum allowed temperature in Celsius (default: -10.0)
6464
* ``maxTemperature`` - Maximum allowed temperature in Celsius (default: 32.0)
65-
* ``step`` - Temperature step value in Celsius for step control feature (default: 0.50, disabled if 0)
65+
* ``step`` - Initial temperature step value in Celsius (default: 0.50)
6666

6767
This function will return ``true`` if successful, ``false`` otherwise.
6868

69-
**Note:** The implementation stores temperature with 1/100th degree Celsius precision internally. If step is greater than 0, the temperature_step feature will be enabled.
69+
**Note:** The implementation stores temperature with 1/100th degree Celsius precision internally. The temperature_step feature is always enabled for temperature_number mode, allowing ``setStep()`` to be called later even if step is not provided in ``begin()``.
7070

7171
begin (overloaded)
7272
^^^^^^^^^^^^^^^^^^
@@ -182,13 +182,13 @@ Gets the maximum allowed temperature.
182182
183183
This function will return the maximum temperature in Celsius with 1/100th degree precision.
184184

185-
Temperature Step Control (Optional)
186-
***********************************
185+
Temperature Step Control
186+
*************************
187187

188188
setStep
189189
^^^^^^^
190190

191-
Sets the temperature step value. This enables the temperature_step feature.
191+
Sets the temperature step value.
192192

193193
**Requires:** temperature_number feature mode (use ``begin()``)
194194

@@ -200,7 +200,7 @@ Sets the temperature step value. This enables the temperature_step feature.
200200

201201
This function will return ``true`` if successful, ``false`` otherwise.
202202

203-
**Note:** The temperature_step feature requires the temperature_number feature to be enabled. This method will return ``false`` and log an error if called when using temperature_level mode.
203+
**Note:** The temperature_step feature is always enabled when using temperature_number mode, so this method can be called at any time to set or change the step value, even if step was not provided in ``begin()``. This method will return ``false`` and log an error if called when using temperature_level mode.
204204

205205
getStep
206206
^^^^^^^

libraries/Matter/examples/MatterTemperatureControlledCabinet/README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ This example demonstrates how to create a Matter-compatible temperature controll
2727
- Matter protocol implementation for a temperature controlled cabinet device
2828
- Support for both Wi-Fi and Thread(*) connectivity
2929
- Temperature setpoint control with min/max limits
30-
- Temperature step control (optional)
30+
- Temperature step control (always enabled, can be set via begin() or setStep())
3131
- Temperature setpoint validation against min/max limits
3232
- Button control for factory reset (decommission)
3333
- Matter commissioning via QR code or manual pairing code
@@ -79,6 +79,7 @@ Before uploading the sketch, configure the following:
7979
```cpp
8080
TemperatureCabinet.begin(4.0, -10.0, 10.0, 0.5);
8181
// Parameters: setpoint, min_temp, max_temp, step (all in Celsius)
82+
// Note: Step can also be set later using setStep() even if not provided here
8283
```
8384

8485
## Building and Flashing

libraries/Matter/src/MatterEndpoints/MatterTemperatureControlledCabinet.cpp

Lines changed: 38 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,11 @@ bool MatterTemperatureControlledCabinet::begin(int16_t _rawTempSetpoint, int16_t
166166
return false;
167167
}
168168

169+
// Note: esp-matter automatically creates all attributes from the config struct when features are enabled
170+
// - temperature_number feature creates: TemperatureSetpoint, MinTemperature, MaxTemperature
171+
// - temperature_step feature creates: Step (always enabled for temperature_number mode to allow setStep() later)
172+
// No need to manually set attributes here as they are already created with the config values
173+
169174
temperature_controlled_cabinet::config_t cabinet_config;
170175
cabinet_config.temperature_control.temperature_number.temp_setpoint = _rawTempSetpoint;
171176
cabinet_config.temperature_control.temperature_number.min_temperature = _rawMinTemperature;
@@ -178,11 +183,10 @@ bool MatterTemperatureControlledCabinet::begin(int16_t _rawTempSetpoint, int16_t
178183
// Only one of them can be enabled at a time.
179184
cabinet_config.temperature_control.features = temperature_control::feature::temperature_number::get_id();
180185

181-
// Enable temperature_step feature if step is provided
186+
// Always enable temperature_step feature to allow setStep() to be called later
182187
// Note: temperature_step requires temperature_number feature (which is always enabled for this mode)
183-
if (_rawStep > 0) {
184-
cabinet_config.temperature_control.features |= temperature_control::feature::temperature_step::get_id();
185-
}
188+
// The step value can be set initially via begin() or later via setStep()
189+
cabinet_config.temperature_control.features |= temperature_control::feature::temperature_step::get_id();
186190

187191
// endpoint handles can be used to add/modify clusters
188192
endpoint_t *endpoint = temperature_controlled_cabinet::create(node::get(), &cabinet_config, ENDPOINT_FLAG_NONE, (void *)this);
@@ -201,6 +205,33 @@ bool MatterTemperatureControlledCabinet::begin(int16_t _rawTempSetpoint, int16_t
201205
setEndPointId(endpoint::get_id(endpoint));
202206
log_i("Temperature Controlled Cabinet created with temperature_number feature, endpoint_id %d", getEndPointId());
203207

208+
// Workaround: Manually create Step attribute if it wasn't created automatically
209+
// This handles the case where temperature_step::add() fails due to feature map timing issue
210+
// The feature map check in temperature_step::add() may not see the temperature_number feature
211+
// immediately after it's added, causing the Step attribute to not be created
212+
cluster_t *cluster = cluster::get(endpoint, TemperatureControl::Id);
213+
if (cluster != nullptr) {
214+
attribute_t *step_attr = attribute::get(cluster, TemperatureControl::Attributes::Step::Id);
215+
if (step_attr == nullptr) {
216+
// Step attribute wasn't created, manually create it
217+
log_w("Step attribute not found after endpoint creation, manually creating it");
218+
step_attr = temperature_control::attribute::create_step(cluster, _rawStep);
219+
if (step_attr != nullptr) {
220+
// Update the feature map to include temperature_step feature
221+
// This ensures the feature is properly registered even though the attribute was created manually
222+
esp_matter_attr_val_t feature_map_val = esp_matter_invalid(NULL);
223+
attribute_t *feature_map_attr = attribute::get(cluster, Globals::Attributes::FeatureMap::Id);
224+
if (feature_map_attr != nullptr && attribute::get_val(feature_map_attr, &feature_map_val) == ESP_OK) {
225+
feature_map_val.val.u32 |= temperature_control::feature::temperature_step::get_id();
226+
attribute::set_val(feature_map_attr, &feature_map_val);
227+
}
228+
log_i("Step attribute manually created with value %.02fC", (float)_rawStep / 100.0);
229+
} else {
230+
log_e("Failed to manually create Step attribute");
231+
}
232+
}
233+
}
234+
204235
started = true;
205236
return true;
206237
}
@@ -315,7 +346,6 @@ bool MatterTemperatureControlledCabinet::setRawTemperatureSetpoint(int16_t _rawT
315346
}
316347

317348
esp_matter_attr_val_t tempVal = esp_matter_invalid(NULL);
318-
319349
if (!getAttributeVal(TemperatureControl::Id, TemperatureControl::Attributes::TemperatureSetpoint::Id, &tempVal)) {
320350
log_e("Failed to get Temperature Controlled Cabinet Temperature Setpoint Attribute.");
321351
return false;
@@ -369,7 +399,6 @@ bool MatterTemperatureControlledCabinet::setRawMinTemperature(int16_t _rawTemper
369399
}
370400

371401
esp_matter_attr_val_t tempVal = esp_matter_invalid(NULL);
372-
373402
if (!getAttributeVal(TemperatureControl::Id, TemperatureControl::Attributes::MinTemperature::Id, &tempVal)) {
374403
log_e("Failed to get Temperature Controlled Cabinet Min Temperature Attribute.");
375404
return false;
@@ -423,7 +452,6 @@ bool MatterTemperatureControlledCabinet::setRawMaxTemperature(int16_t _rawTemper
423452
}
424453

425454
esp_matter_attr_val_t tempVal = esp_matter_invalid(NULL);
426-
427455
if (!getAttributeVal(TemperatureControl::Id, TemperatureControl::Attributes::MaxTemperature::Id, &tempVal)) {
428456
log_e("Failed to get Temperature Controlled Cabinet Max Temperature Attribute.");
429457
return false;
@@ -477,9 +505,8 @@ bool MatterTemperatureControlledCabinet::setRawStep(int16_t _rawStep) {
477505
}
478506

479507
esp_matter_attr_val_t stepVal = esp_matter_invalid(NULL);
480-
481508
if (!getAttributeVal(TemperatureControl::Id, TemperatureControl::Attributes::Step::Id, &stepVal)) {
482-
log_e("Failed to get Temperature Controlled Cabinet Step Attribute.");
509+
log_e("Failed to get Temperature Controlled Cabinet Step Attribute. Temperature_step feature may not be enabled.");
483510
return false;
484511
}
485512
if (stepVal.val.i16 != _rawStep) {
@@ -508,6 +535,8 @@ double MatterTemperatureControlledCabinet::getStep() {
508535
return 0.0;
509536
}
510537

538+
// Read from attribute (should always exist after begin() due to workaround)
539+
// If read fails, use stored rawStep value from begin()
511540
esp_matter_attr_val_t stepVal = esp_matter_invalid(NULL);
512541
if (getAttributeVal(TemperatureControl::Id, TemperatureControl::Attributes::Step::Id, &stepVal)) {
513542
rawStep = stepVal.val.i16;
@@ -531,7 +560,6 @@ bool MatterTemperatureControlledCabinet::setSelectedTemperatureLevel(uint8_t lev
531560
}
532561

533562
esp_matter_attr_val_t levelVal = esp_matter_invalid(NULL);
534-
535563
if (!getAttributeVal(TemperatureControl::Id, TemperatureControl::Attributes::SelectedTemperatureLevel::Id, &levelVal)) {
536564
log_e("Failed to get Temperature Controlled Cabinet Selected Temperature Level Attribute.");
537565
return false;

0 commit comments

Comments
 (0)