Skip to content

Commit a5cbab9

Browse files
authored
Merge branch 'master' into feature/fix-invalid-pid-vid
2 parents a210940 + 010d982 commit a5cbab9

File tree

12 files changed

+108
-125
lines changed

12 files changed

+108
-125
lines changed

examples/rvc-app/rvc-common/include/rvc-service-area-delegate.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -79,8 +79,8 @@ class RvcServiceAreaDelegate : public Delegate
7979
// command support
8080
bool IsSetSelectedAreasAllowed(MutableCharSpan & statusText) override;
8181

82-
bool IsValidSelectAreasSet(const ServiceArea::Commands::SelectAreas::DecodableType & req,
83-
ServiceArea::SelectAreasStatus & areaStatus, MutableCharSpan & statusText) override;
82+
bool IsValidSelectAreasSet(const Span<const uint32_t> & selectedAreas, ServiceArea::SelectAreasStatus & areaStatus,
83+
MutableCharSpan & statusText) override;
8484

8585
bool HandleSkipArea(uint32_t skippedArea, MutableCharSpan & skipStatusText) override;
8686

examples/rvc-app/rvc-common/rvc-app.matter

+2-3
Original file line numberDiff line numberDiff line change
@@ -1438,9 +1438,8 @@ provisional cluster ServiceArea = 336 {
14381438
enum SelectAreasStatus : enum8 {
14391439
kSuccess = 0;
14401440
kUnsupportedArea = 1;
1441-
kDuplicatedAreas = 2;
1442-
kInvalidInMode = 3;
1443-
kInvalidSet = 4;
1441+
kInvalidInMode = 2;
1442+
kInvalidSet = 3;
14441443
}
14451444

14461445
enum SkipAreaStatus : enum8 {

examples/rvc-app/rvc-common/src/rvc-service-area-delegate.cpp

+22-41
Original file line numberDiff line numberDiff line change
@@ -113,23 +113,12 @@ bool RvcServiceAreaDelegate::IsSetSelectedAreasAllowed(MutableCharSpan & statusT
113113
return (mIsSetSelectedAreasAllowedDeviceInstance->*mIsSetSelectedAreasAllowedCallback)(statusText);
114114
};
115115

116-
bool RvcServiceAreaDelegate::IsValidSelectAreasSet(const Commands::SelectAreas::DecodableType & req, SelectAreasStatus & areaStatus,
116+
bool RvcServiceAreaDelegate::IsValidSelectAreasSet(const Span<const uint32_t> & selectedAreas, SelectAreasStatus & areaStatus,
117117
MutableCharSpan & statusText)
118118
{
119-
// if req is empty list return true.
119+
if (selectedAreas.empty())
120120
{
121-
size_t reqSize;
122-
if (req.newAreas.ComputeSize(&reqSize) != CHIP_NO_ERROR)
123-
{
124-
areaStatus = SelectAreasStatus::kInvalidSet; // todo Not sure this is the correct error to use here
125-
CopyCharSpanToMutableCharSpan("error computing number of selected areas"_span, statusText);
126-
return false;
127-
}
128-
129-
if (reqSize == 0)
130-
{
131-
return true;
132-
}
121+
return true;
133122
}
134123

135124
// If there is 1 or 0 supported maps, any combination of areas is valid.
@@ -139,42 +128,34 @@ bool RvcServiceAreaDelegate::IsValidSelectAreasSet(const Commands::SelectAreas::
139128
}
140129

141130
// Check that all the requested areas are in the same map.
142-
auto newAreasIter = req.newAreas.begin();
143-
newAreasIter.Next();
144-
145-
AreaStructureWrapper tempArea;
146-
uint32_t ignoredIndex;
147-
if (!GetSupportedAreaById(newAreasIter.GetValue(), ignoredIndex, tempArea))
148131
{
149-
areaStatus = SelectAreasStatus::kUnsupportedArea;
150-
CopyCharSpanToMutableCharSpan("unable to find selected area in supported areas"_span, statusText);
151-
return false;
152-
}
153-
154-
auto mapId = tempArea.mapID.Value(); // It is safe to call `.Value()` as we confirmed that there are at least 2 maps.
155-
156-
while (newAreasIter.Next())
157-
{
158-
if (!GetSupportedAreaById(newAreasIter.GetValue(), ignoredIndex, tempArea))
132+
AreaStructureWrapper tempArea;
133+
uint32_t ignoredIndex;
134+
if (!GetSupportedAreaById(selectedAreas[0], ignoredIndex, tempArea))
159135
{
160136
areaStatus = SelectAreasStatus::kUnsupportedArea;
161137
CopyCharSpanToMutableCharSpan("unable to find selected area in supported areas"_span, statusText);
162138
return false;
163139
}
164140

165-
if (tempArea.mapID.Value() != mapId)
141+
auto mapId = tempArea.mapID.Value(); // It is safe to call `.Value()` as we confirmed that there are at least 2 maps.
142+
143+
for (const auto & areaId : selectedAreas.SubSpan(1))
166144
{
167-
areaStatus = SelectAreasStatus::kInvalidSet;
168-
CopyCharSpanToMutableCharSpan("all selected areas must be in the same map"_span, statusText);
169-
return false;
170-
}
171-
}
145+
if (!GetSupportedAreaById(areaId, ignoredIndex, tempArea))
146+
{
147+
areaStatus = SelectAreasStatus::kUnsupportedArea;
148+
CopyCharSpanToMutableCharSpan("unable to find selected area in supported areas"_span, statusText);
149+
return false;
150+
}
172151

173-
if (CHIP_NO_ERROR != newAreasIter.GetStatus())
174-
{
175-
areaStatus = SelectAreasStatus::kInvalidSet;
176-
CopyCharSpanToMutableCharSpan("error processing new areas."_span, statusText);
177-
return false;
152+
if (tempArea.mapID.Value() != mapId)
153+
{
154+
areaStatus = SelectAreasStatus::kInvalidSet;
155+
CopyCharSpanToMutableCharSpan("all selected areas must be in the same map"_span, statusText);
156+
return false;
157+
}
158+
}
178159
}
179160

180161
return true;

src/app/clusters/service-area-server/service-area-delegate.h

+3-3
Original file line numberDiff line numberDiff line change
@@ -80,18 +80,18 @@ class Delegate
8080
* If the set of locations is invalid, the locationStatus should be set to InvalidSet and
8181
* the statusText SHALL include a vendor-defined error description.
8282
*
83-
* The caller of this method will ensure that there are no duplicates is the list
83+
* The caller of this method will ensure that there are no duplicates in the list
8484
* and that all the locations in the set are valid supported locations.
8585
*
86-
* @param[in] req List of new selected locations.
86+
* @param[in] selectedAreas List of new selected locations.
8787
* @param[out] locationStatus Success if all checks pass, error code if failure.
8888
* @param[out] statusText text describing failure (see description above), size kMaxSizeStatusText.
8989
* @return true if success.
9090
*
9191
* @note If the SelectAreas command is allowed when the device is operating and the selected locations change to none, the
9292
* device must stop.
9393
*/
94-
virtual bool IsValidSelectAreasSet(const Commands::SelectAreas::DecodableType & req, SelectAreasStatus & locationStatus,
94+
virtual bool IsValidSelectAreasSet(const Span<const uint32_t> & selectedAreas, SelectAreasStatus & locationStatus,
9595
MutableCharSpan & statusText) = 0;
9696

9797
/**

src/app/clusters/service-area-server/service-area-server.cpp

+53-46
Original file line numberDiff line numberDiff line change
@@ -240,64 +240,72 @@ void Instance::HandleSelectAreasCmd(HandlerContext & ctx, const Commands::Select
240240
}
241241
}
242242

243+
uint32_t selectedAreasBuffer[kMaxNumSelectedAreas];
244+
auto selectedAreasSpan = Span<uint32_t>(selectedAreasBuffer, kMaxNumSelectedAreas);
245+
uint32_t numberOfSelectedAreas = 0;
246+
247+
// Closure for checking if an area ID exists in the selectedAreasSpan
248+
auto areaAlreadyExists = [&numberOfSelectedAreas, &selectedAreasSpan](uint32_t areaId) {
249+
for (uint32_t i = 0; i < numberOfSelectedAreas; i++)
250+
{
251+
if (areaId == selectedAreasSpan[i])
252+
{
253+
return true;
254+
}
255+
}
256+
return false;
257+
};
258+
243259
// if number of selected locations in parameter matches number in attribute - the locations *might* be the same
244260
bool matchesCurrentSelectedAreas = (numberOfAreas == mDelegate->GetNumberOfSelectedAreas());
245261

262+
// do as much parameter validation as we can
246263
if (numberOfAreas != 0)
247264
{
248-
// do as much parameter validation as we can
265+
uint32_t ignoredIndex = 0;
266+
uint32_t oldSelectedArea;
267+
auto iAreaIter = req.newAreas.begin();
268+
while (iAreaIter.Next())
249269
{
250-
uint32_t ignoredIndex = 0;
251-
uint32_t oldSelectedArea;
252-
uint32_t i = 0;
253-
auto iAreaIter = req.newAreas.begin();
254-
while (iAreaIter.Next())
255-
{
256-
uint32_t aSelectedArea = iAreaIter.GetValue();
270+
uint32_t selectedArea = iAreaIter.GetValue();
257271

258-
// each item in this list SHALL match the AreaID field of an entry on the SupportedAreas attribute's list
259-
// If the Status field is set to UnsupportedArea, the StatusText field SHALL be an empty string.
260-
if (!IsSupportedArea(aSelectedArea))
261-
{
262-
exitResponse(SelectAreasStatus::kUnsupportedArea, ""_span);
263-
return;
264-
}
272+
// If aSelectedArea is already in selectedAreasSpan skip
273+
if (areaAlreadyExists(selectedArea))
274+
{
275+
continue;
276+
}
265277

266-
// Checking for duplicate locations.
267-
uint32_t j = 0;
268-
auto jAreaIter = req.newAreas.begin();
269-
while (j < i)
270-
{
271-
jAreaIter.Next(); // Since j < i and i is valid, we can safely call Next() without checking the return value.
272-
if (jAreaIter.GetValue() == aSelectedArea)
273-
{
274-
exitResponse(SelectAreasStatus::kDuplicatedAreas, ""_span);
275-
return;
276-
}
277-
j += 1;
278-
}
278+
// each item in this list SHALL match the AreaID field of an entry on the SupportedAreas attribute's list
279+
// If the Status field is set to UnsupportedArea, the StatusText field SHALL be an empty string.
280+
if (!IsSupportedArea(selectedArea))
281+
{
282+
exitResponse(SelectAreasStatus::kUnsupportedArea, ""_span);
283+
return;
284+
}
279285

280-
// check to see if parameter list and attribute still match
281-
if (matchesCurrentSelectedAreas)
286+
// check to see if parameter list and attribute still match
287+
if (matchesCurrentSelectedAreas)
288+
{
289+
if (!mDelegate->GetSelectedAreaByIndex(ignoredIndex, oldSelectedArea) || (selectedArea != oldSelectedArea))
282290
{
283-
if (!mDelegate->GetSelectedAreaByIndex(ignoredIndex, oldSelectedArea) || (aSelectedArea != oldSelectedArea))
284-
{
285-
matchesCurrentSelectedAreas = false;
286-
}
291+
matchesCurrentSelectedAreas = false;
287292
}
288-
289-
i += 1;
290293
}
291294

292-
// after iterating with Next through DecodableType - check for failure
293-
if (CHIP_NO_ERROR != iAreaIter.GetStatus())
294-
{
295-
ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::InvalidCommand);
296-
return;
297-
}
295+
selectedAreasSpan[numberOfSelectedAreas] = selectedArea;
296+
numberOfSelectedAreas += 1;
297+
}
298+
299+
// after iterating with Next through DecodableType - check for failure
300+
if (CHIP_NO_ERROR != iAreaIter.GetStatus())
301+
{
302+
ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::InvalidCommand);
303+
return;
298304
}
299305
}
300306

307+
selectedAreasSpan.reduce_size(numberOfSelectedAreas);
308+
301309
// If the newAreas field is the same as the value of the SelectedAreas attribute
302310
// the SelectAreasResponse command SHALL have the Status field set to Success and
303311
// the StatusText field MAY be supplied with a human-readable string or include an empty string.
@@ -327,7 +335,7 @@ void Instance::HandleSelectAreasCmd(HandlerContext & ctx, const Commands::Select
327335
// ask the device to handle SelectAreas Command
328336
// (note - locationStatusText to be filled out by delegated function for kInvalidInMode and InvalidSet)
329337
auto locationStatus = SelectAreasStatus::kSuccess;
330-
if (!mDelegate->IsValidSelectAreasSet(req, locationStatus, delegateStatusText))
338+
if (!mDelegate->IsValidSelectAreasSet(selectedAreasSpan, locationStatus, delegateStatusText))
331339
{
332340
exitResponse(locationStatus, delegateStatusText);
333341
return;
@@ -342,11 +350,10 @@ void Instance::HandleSelectAreasCmd(HandlerContext & ctx, const Commands::Select
342350

343351
if (numberOfAreas != 0)
344352
{
345-
auto locationIter = req.newAreas.begin();
346353
uint32_t ignored;
347-
while (locationIter.Next())
354+
for (uint32_t areaId : selectedAreasSpan)
348355
{
349-
mDelegate->AddSelectedArea(locationIter.GetValue(), ignored);
356+
mDelegate->AddSelectedArea(areaId, ignored);
350357
}
351358
}
352359

src/app/zap-templates/zcl/data-model/chip/service-area-cluster.xml

+2-3
Original file line numberDiff line numberDiff line change
@@ -63,9 +63,8 @@ limitations under the License.
6363
<cluster code="0x0150"/>
6464
<item value="0x00" name="Success"/>
6565
<item value="0x01" name="UnsupportedArea"/>
66-
<item value="0x02" name="DuplicatedAreas"/>
67-
<item value="0x03" name="InvalidInMode"/>
68-
<item value="0x04" name="InvalidSet"/>
66+
<item value="0x02" name="InvalidInMode"/>
67+
<item value="0x03" name="InvalidSet"/>
6968
</enum>
7069

7170
<enum name="SkipAreaStatus" type="enum8">

src/controller/data_model/controller-clusters.matter

+2-3
Original file line numberDiff line numberDiff line change
@@ -6463,9 +6463,8 @@ provisional cluster ServiceArea = 336 {
64636463
enum SelectAreasStatus : enum8 {
64646464
kSuccess = 0;
64656465
kUnsupportedArea = 1;
6466-
kDuplicatedAreas = 2;
6467-
kInvalidInMode = 3;
6468-
kInvalidSet = 4;
6466+
kInvalidInMode = 2;
6467+
kInvalidSet = 3;
64696468
}
64706469

64716470
enum SkipAreaStatus : enum8 {

src/controller/python/chip/clusters/Objects.py

+3-4
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters.h

+2-3
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/python_testing/TC_SEAR_1_3.py

+14-12
Original file line numberDiff line numberDiff line change
@@ -109,15 +109,17 @@ async def test_TC_SEAR_1_3(self):
109109

110110
duplicated_areas = [valid_area_id, valid_area_id]
111111

112-
# FIXME need to check if this is the correct name of this status code
113-
await self.send_cmd_select_areas_expect_response(step=3, new_areas=duplicated_areas, expected_response=Clusters.ServiceArea.Enums.SelectAreasStatus.kDuplicatedAreas)
112+
await self.send_cmd_select_areas_expect_response(step=3, new_areas=duplicated_areas, expected_response=Clusters.ServiceArea.Enums.SelectAreasStatus.kSuccess)
114113

115-
await self.send_cmd_select_areas_expect_response(step=4, new_areas=[], expected_response=Clusters.ServiceArea.Enums.SelectAreasStatus.kSuccess)
114+
selected_areas = await self.read_selected_areas(step=4)
115+
asserts.assert_true(selected_areas == [valid_area_id], "SelectedAreas should be empty")
116116

117-
selected_areas = await self.read_selected_areas(step=5)
117+
await self.send_cmd_select_areas_expect_response(step=5, new_areas=[], expected_response=Clusters.ServiceArea.Enums.SelectAreasStatus.kSuccess)
118+
119+
selected_areas = await self.read_selected_areas(step=6)
118120
asserts.assert_true(len(selected_areas) == 0, "SelectedAreas should be empty")
119121

120-
await self.send_cmd_select_areas_expect_response(step=6, new_areas=[invalid_area_id], expected_response=Clusters.ServiceArea.Enums.SelectAreasStatus.kUnsupportedArea)
122+
await self.send_cmd_select_areas_expect_response(step=8, new_areas=[invalid_area_id], expected_response=Clusters.ServiceArea.Enums.SelectAreasStatus.kUnsupportedArea)
121123

122124
if self.check_pics("SEAR.S.M.INVALID_STATE_FOR_SELECT_AREAS") and self.check_pics("SEAR.S.M.HAS_MANUAL_SELAREA_STATE_CONTROL"):
123125
test_step = "Manually intervene to put the device in a state that prevents it from executing the SelectAreas command"
@@ -127,7 +129,7 @@ async def test_TC_SEAR_1_3(self):
127129
else:
128130
self.wait_for_user_input(prompt_msg=f"{test_step}, and press Enter when done.\n")
129131

130-
await self.send_cmd_select_areas_expect_response(step=8, new_areas=[valid_area_id], expected_response=Clusters.ServiceArea.Enums.SelectAreasStatus.kInvalidInMode)
132+
await self.send_cmd_select_areas_expect_response(step=10, new_areas=[valid_area_id], expected_response=Clusters.ServiceArea.Enums.SelectAreasStatus.kInvalidInMode)
131133

132134
if self.check_pics("SEAR.S.M.VALID_STATE_FOR_SELECT_AREAS") and self.check_pics("SEAR.S.M.HAS_MANUAL_SELAREA_STATE_CONTROL"):
133135
test_step = f"Manually intervene to put the device in a state that allows it to execute the SelectAreas({supported_area_ids}) command"
@@ -137,27 +139,27 @@ async def test_TC_SEAR_1_3(self):
137139
else:
138140
self.wait_for_user_input(prompt_msg=f"{test_step}, and press Enter when done.\n")
139141

140-
await self.send_cmd_select_areas_expect_response(step=10, new_areas=supported_area_ids, expected_response=Clusters.ServiceArea.Enums.SelectAreasStatus.kSuccess)
142+
await self.send_cmd_select_areas_expect_response(step=11, new_areas=supported_area_ids, expected_response=Clusters.ServiceArea.Enums.SelectAreasStatus.kSuccess)
141143

142-
selected_areas = await self.read_selected_areas(step=11)
144+
selected_areas = await self.read_selected_areas(step=12)
143145
asserts.assert_true(len(selected_areas) == len(supported_area_ids),
144146
f"SelectedAreas({selected_areas}) should match SupportedAreas({supported_area_ids})")
145147

146-
await self.send_cmd_select_areas_expect_response(step=12, new_areas=supported_area_ids, expected_response=Clusters.ServiceArea.Enums.SelectAreasStatus.kSuccess)
148+
await self.send_cmd_select_areas_expect_response(step=13, new_areas=supported_area_ids, expected_response=Clusters.ServiceArea.Enums.SelectAreasStatus.kSuccess)
147149

148150
if self.check_pics("SEAR.S.M.VALID_STATE_FOR_SELECT_AREAS") and self.check_pics("SEAR.S.M.HAS_MANUAL_SELAREA_STATE_CONTROL") and self.check_pics("SEAR.S.M.SELECT_AREAS_WHILE_NON_IDLE"):
149151
test_step = f"Manually intervene to put the device in a state that allows it to execute the SelectAreas({valid_area_id}) command, and put the device in a non-idle state"
150-
self.print_step("13", test_step)
152+
self.print_step("14", test_step)
151153
if self.is_ci:
152154
self.write_to_app_pipe('{"Name": "Reset"}')
153155
await self.send_single_cmd(cmd=Clusters.Objects.RvcRunMode.Commands.ChangeToMode(newMode=1), endpoint=self.endpoint)
154156
else:
155157
self.wait_for_user_input(prompt_msg=f"{test_step}, and press Enter when done.\n")
156158

157159
if self.check_pics("SEAR.S.F00"):
158-
await self.send_cmd_select_areas_expect_response(step=14, new_areas=[valid_area_id], expected_response=Clusters.ServiceArea.Enums.SelectAreasStatus.kSuccess)
160+
await self.send_cmd_select_areas_expect_response(step=15, new_areas=[valid_area_id], expected_response=Clusters.ServiceArea.Enums.SelectAreasStatus.kSuccess)
159161
else:
160-
await self.send_cmd_select_areas_expect_response(step=14, new_areas=[valid_area_id], expected_response=Clusters.ServiceArea.Enums.SelectAreasStatus.kInvalidInMode)
162+
await self.send_cmd_select_areas_expect_response(step=15, new_areas=[valid_area_id], expected_response=Clusters.ServiceArea.Enums.SelectAreasStatus.kInvalidInMode)
161163

162164

163165
if __name__ == "__main__":

zzz_generated/app-common/app-common/zap-generated/cluster-enums-check.h

-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)