Skip to content

Commit 8c79a18

Browse files
committed
[HVAC] Check if number of preset scenarios exceeds maximum number of scenarios
1 parent 3bf596f commit 8c79a18

File tree

3 files changed

+49
-50
lines changed

3 files changed

+49
-50
lines changed

examples/thermostat/thermostat-common/include/thermostat-delegate-impl.h

+2
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ static constexpr uint8_t kMaxNumberOfPresetTypes = 6;
3939
// We will support only one preset of each preset type.
4040
static constexpr uint8_t kMaxNumberOfPresetsOfEachType = 1;
4141

42+
static constexpr uint8_t kMaxNumberOfPresetsSupported = kMaxNumberOfPresetTypes * kMaxNumberOfPresetsOfEachType - 1;
43+
4244
class ThermostatDelegate : public Delegate
4345
{
4446
public:

examples/thermostat/thermostat-common/src/thermostat-delegate-impl.cpp

+4-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ ThermostatDelegate ThermostatDelegate::sInstance;
3131

3232
ThermostatDelegate::ThermostatDelegate()
3333
{
34-
mNumberOfPresets = kMaxNumberOfPresetTypes * kMaxNumberOfPresetsOfEachType;
34+
mNumberOfPresets = kMaxNumberOfPresetsSupported;
3535
mNextFreeIndexInPresetsList = 0;
3636
mNextFreeIndexInPendingPresetsList = 0;
3737

@@ -87,6 +87,9 @@ CHIP_ERROR ThermostatDelegate::GetPresetTypeAtIndex(size_t index, PresetTypeStru
8787
{ .presetScenario = PresetScenarioEnum::kVacation,
8888
.numberOfPresets = kMaxNumberOfPresetsOfEachType,
8989
.presetTypeFeatures = to_underlying(PresetTypeFeaturesBitmap::kSupportsNames) },
90+
{ .presetScenario = PresetScenarioEnum::kUserDefined,
91+
.numberOfPresets = kMaxNumberOfPresetsOfEachType,
92+
.presetTypeFeatures = to_underlying(PresetTypeFeaturesBitmap::kSupportsNames) },
9093
};
9194
if (index < ArraySize(presetTypes))
9295
{

src/app/clusters/thermostat-server/thermostat-server-presets.cpp

+43-49
Original file line numberDiff line numberDiff line change
@@ -152,51 +152,14 @@ bool GetMatchingPresetInPresets(Delegate * delegate, const DataModel::Nullable<B
152152
}
153153

154154
/**
155-
* @brief Returns the length of the list of presets if the pending presets were to be applied. The size of the pending presets list
156-
* calculated, after all the constraint checks are done, is the new size of the updated Presets attribute since the pending
157-
* preset list is expected to have all existing presets with or without edits plus new presets.
158-
* This is called before changes are actually applied.
159-
*
160-
* @param[in] delegate The delegate to use.
161-
*
162-
* @return count of the updated Presets attribute if the pending presets were applied to it. Return 0 for error cases.
163-
*/
164-
uint8_t CountNumberOfPendingPresets(Delegate * delegate)
165-
{
166-
uint8_t numberOfPendingPresets = 0;
167-
168-
VerifyOrReturnValue(delegate != nullptr, 0);
169-
170-
for (uint8_t i = 0; true; i++)
171-
{
172-
PresetStructWithOwnedMembers pendingPreset;
173-
CHIP_ERROR err = delegate->GetPendingPresetAtIndex(i, pendingPreset);
174-
175-
if (err == CHIP_ERROR_PROVIDER_LIST_EXHAUSTED)
176-
{
177-
break;
178-
}
179-
if (err != CHIP_NO_ERROR)
180-
{
181-
ChipLogError(Zcl, "CountNumberOfPendingPresets: GetPendingPresetAtIndex failed with error %" CHIP_ERROR_FORMAT,
182-
err.Format());
183-
return 0;
184-
}
185-
numberOfPendingPresets++;
186-
}
187-
188-
return numberOfPendingPresets;
189-
}
190-
191-
/**
192-
* @brief Checks if the presetScenario is present in the PresetTypes attribute.
155+
* @brief Gets the maximum number of presets allowed for a given preset scenario.
193156
*
194157
* @param[in] delegate The delegate to use.
195158
* @param[in] presetScenario The presetScenario to match with.
196159
*
197-
* @return true if the presetScenario is found, false otherwise.
160+
* @return The maximum number of presets allowed for the preset scenario
198161
*/
199-
bool PresetScenarioExistsInPresetTypes(Delegate * delegate, PresetScenarioEnum presetScenario)
162+
uint8_t MaximumPresetScenarioCount(Delegate * delegate, PresetScenarioEnum presetScenario)
200163
{
201164
VerifyOrReturnValue(delegate != nullptr, false);
202165

@@ -206,15 +169,17 @@ bool PresetScenarioExistsInPresetTypes(Delegate * delegate, PresetScenarioEnum p
206169
auto err = delegate->GetPresetTypeAtIndex(i, presetType);
207170
if (err != CHIP_NO_ERROR)
208171
{
209-
return false;
172+
// Either we failed to fetch the next preset type, in which case we should error higher,
173+
// or we exhausted the list trying to find the preset type
174+
return 0;
210175
}
211176

212177
if (presetType.presetScenario == presetScenario)
213178
{
214-
return true;
179+
return presetType.numberOfPresets;
215180
}
216181
}
217-
return false;
182+
return 0;
218183
}
219184

220185
/**
@@ -359,6 +324,10 @@ CHIP_ERROR ThermostatAttrAccess::AppendPendingPreset(Thermostat::Delegate * dele
359324
return CHIP_IM_GLOBAL_STATUS(ConstraintError);
360325
}
361326

327+
// We're going to append this preset, so let's assume a count as though it had already been inserted
328+
size_t presetCount = 1;
329+
size_t presetScenarioCount = 1;
330+
362331
if (preset.GetPresetHandle().IsNull())
363332
{
364333
if (IsBuiltIn(preset))
@@ -410,8 +379,12 @@ CHIP_ERROR ThermostatAttrAccess::AppendPendingPreset(Thermostat::Delegate * dele
410379
}
411380
}
412381

413-
if (!PresetScenarioExistsInPresetTypes(delegate, preset.GetPresetScenario()))
382+
size_t maximumPresetCount = delegate->GetNumberOfPresets();
383+
size_t maximumPresetScenarioCount = MaximumPresetScenarioCount(delegate, preset.GetPresetScenario());
384+
385+
if (maximumPresetScenarioCount == 0)
414386
{
387+
// This is not a supported preset scenario
415388
return CHIP_IM_GLOBAL_STATUS(ConstraintError);
416389
}
417390

@@ -423,16 +396,37 @@ CHIP_ERROR ThermostatAttrAccess::AppendPendingPreset(Thermostat::Delegate * dele
423396
// Before adding this preset to the pending presets, if the expected length of the pending presets' list
424397
// exceeds the total number of presets supported, return RESOURCE_EXHAUSTED. Note that the preset has not been appended yet.
425398

426-
uint8_t numberOfPendingPresets = CountNumberOfPendingPresets(delegate);
399+
for (uint8_t i = 0; true; i++)
400+
{
401+
PresetStructWithOwnedMembers otherPreset;
402+
CHIP_ERROR err = delegate->GetPendingPresetAtIndex(i, otherPreset);
427403

428-
// We will be adding one more preset, so reject if the length is already at max.
429-
if (numberOfPendingPresets >= delegate->GetNumberOfPresets())
404+
if (err == CHIP_ERROR_PROVIDER_LIST_EXHAUSTED)
405+
{
406+
break;
407+
}
408+
if (err != CHIP_NO_ERROR)
409+
{
410+
return CHIP_IM_GLOBAL_STATUS(InvalidInState);
411+
}
412+
presetCount++;
413+
if (preset.GetPresetScenario() == otherPreset.GetPresetScenario())
414+
{
415+
presetScenarioCount++;
416+
}
417+
}
418+
419+
if (presetCount > maximumPresetCount)
430420
{
421+
ChipLogError(Zcl, "Preset count exceeded %zu: %zu ", maximumPresetCount, presetCount);
431422
return CHIP_IM_GLOBAL_STATUS(ResourceExhausted);
432423
}
433424

434-
// TODO #34556 : Check if the number of presets for each presetScenario exceeds the max number of presets supported for that
435-
// scenario. We plan to support only one preset for each presetScenario for our use cases so defer this for re-evaluation.
425+
if (presetScenarioCount > maximumPresetScenarioCount)
426+
{
427+
ChipLogError(Zcl, "Preset scenario count exceeded %zu: %zu ", maximumPresetScenarioCount, presetScenarioCount);
428+
return CHIP_IM_GLOBAL_STATUS(ResourceExhausted);
429+
}
436430

437431
return delegate->AppendToPendingPresetList(preset);
438432
}

0 commit comments

Comments
 (0)