Skip to content

Commit 940d44d

Browse files
committedJun 17, 2024
Return invalid command on move when rate is 0 or rate is null and defaultRate is 0
1 parent 8ba371a commit 940d44d

File tree

2 files changed

+45
-40
lines changed

2 files changed

+45
-40
lines changed
 

‎src/app/clusters/level-control/level-control.cpp

+42-39
Original file line numberDiff line numberDiff line change
@@ -962,18 +962,56 @@ static void moveHandler(app::CommandHandler * commandObj, const app::ConcreteCom
962962
goto send_default_response;
963963
}
964964

965+
// Always validate the rate parameter received. A rate of 0 is invalid.
965966
if (!rate.IsNull() && (rate.Value() == 0))
966967
{
967-
// Move at a rate of zero is no move at all. Immediately succeed without touching anything.
968-
ChipLogProgress(Zcl, "Immediate success due to move rate of 0 (would move at no rate).");
969-
status = Status::Success;
968+
// Providing rate of 0 is not allowed.
969+
status = Status::InvalidCommand;
970970
goto send_default_response;
971971
}
972972

973+
uint8_t eventDuration; // use this local var so state->eventDurationMs is only set once the command is validated.
974+
#ifndef IGNORE_LEVEL_CONTROL_CLUSTER_TRANSITION
975+
// If the Rate field is null, the device should move at the default move rate, if available,
976+
// Otherwise, move as fast as possible
977+
if (rate.IsNull())
978+
{
979+
app::DataModel::Nullable<uint8_t> defaultMoveRate;
980+
status = Attributes::DefaultMoveRate::Get(endpoint, defaultMoveRate);
981+
if (status != Status::Success || defaultMoveRate.IsNull())
982+
{
983+
ChipLogProgress(Zcl, "ERR: reading default move rate %x", to_underlying(status));
984+
eventDuration = FASTEST_TRANSITION_TIME_MS;
985+
}
986+
else
987+
{
988+
// The defaultMoveRate cannot be 0
989+
if (defaultMoveRate.Value() == 0)
990+
{
991+
status = Status::InvalidCommand;
992+
goto send_default_response;
993+
}
994+
// Already checked that defaultMoveRate.Value() != 0.
995+
eventDuration = static_cast<uint8_t>(MILLISECOND_TICKS_PER_SECOND / defaultMoveRate.Value());
996+
}
997+
}
998+
else
999+
{
1000+
// Already confirmed rate.Value() != 0.
1001+
eventDuration = static_cast<uint8_t>(MILLISECOND_TICKS_PER_SECOND / rate.Value());
1002+
}
1003+
#else
1004+
// Transition/rate is not supported so always use fastest transition time and ignore
1005+
// both the provided transition time as well as OnOffTransitionTime.
1006+
ChipLogProgress(Zcl, "Device does not support transition, ignoring rate");
1007+
eventDuration = FASTEST_TRANSITION_TIME_MS;
1008+
#endif // IGNORE_LEVEL_CONTROL_CLUSTER_TRANSITION
1009+
9731010
// Cancel any currently active command before fiddling with the state.
9741011
cancelEndpointTimerCallback(endpoint);
9751012

976-
status = Attributes::CurrentLevel::Get(endpoint, currentLevel);
1013+
state->eventDurationMs = eventDuration;
1014+
status = Attributes::CurrentLevel::Get(endpoint, currentLevel);
9771015
if (status != Status::Success)
9781016
{
9791017
ChipLogProgress(Zcl, "ERR: reading current level %x", to_underlying(status));
@@ -1026,41 +1064,6 @@ static void moveHandler(app::CommandHandler * commandObj, const app::ConcreteCom
10261064
}
10271065
}
10281066

1029-
#ifndef IGNORE_LEVEL_CONTROL_CLUSTER_TRANSITION
1030-
// If the Rate field is null, the device should move at the default move rate, if available,
1031-
// Otherwise, move as fast as possible
1032-
if (rate.IsNull())
1033-
{
1034-
app::DataModel::Nullable<uint8_t> defaultMoveRate;
1035-
status = Attributes::DefaultMoveRate::Get(endpoint, defaultMoveRate);
1036-
if (status != Status::Success || defaultMoveRate.IsNull())
1037-
{
1038-
ChipLogProgress(Zcl, "ERR: reading default move rate %x", to_underlying(status));
1039-
state->eventDurationMs = FASTEST_TRANSITION_TIME_MS;
1040-
}
1041-
else
1042-
{
1043-
// nonsensical case, means "don't move", so we're done
1044-
if (defaultMoveRate.Value() == 0)
1045-
{
1046-
status = Status::Success;
1047-
goto send_default_response;
1048-
}
1049-
// Already checked that defaultMoveRate.Value() != 0.
1050-
state->eventDurationMs = MILLISECOND_TICKS_PER_SECOND / defaultMoveRate.Value();
1051-
}
1052-
}
1053-
else
1054-
{
1055-
state->eventDurationMs = MILLISECOND_TICKS_PER_SECOND / std::max(static_cast<uint8_t>(1u), rate.Value());
1056-
}
1057-
#else
1058-
// Transition/rate is not supported so always use fastest transition time and ignore
1059-
// both the provided transition time as well as OnOffTransitionTime.
1060-
ChipLogProgress(Zcl, "Device does not support transition, ignoring rate");
1061-
state->eventDurationMs = FASTEST_TRANSITION_TIME_MS;
1062-
#endif // IGNORE_LEVEL_CONTROL_CLUSTER_TRANSITION
1063-
10641067
state->transitionTimeMs = difference * state->eventDurationMs;
10651068
state->elapsedTimeMs = 0;
10661069

‎src/app/tests/suites/certification/Test_TC_LVL_4_1.yaml

+3-1
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,7 @@ tests:
269269

270270
- label:
271271
"Step 4h: TH sends a Move command to the DUT with MoveMode =0x00 (up)
272-
and Rate =0 (units/s), expect success"
272+
and Rate =0 (units/s), expect failure"
273273
PICS: LVL.S.C01.Rsp
274274
command: "Move"
275275
arguments:
@@ -282,6 +282,8 @@ tests:
282282
value: 1
283283
- name: "OptionsOverride"
284284
value: 1
285+
response:
286+
error: INVALID_COMMAND
285287

286288
- label: "Wait 5s"
287289
cluster: "DelayCommands"

0 commit comments

Comments
 (0)