diff --git a/src/app/clusters/level-control/level-control.cpp b/src/app/clusters/level-control/level-control.cpp index 8807846ee69ca3..0596cbbeb37582 100644 --- a/src/app/clusters/level-control/level-control.cpp +++ b/src/app/clusters/level-control/level-control.cpp @@ -99,7 +99,6 @@ typedef struct CommandId commandId; uint8_t moveToLevel; bool increasing; - bool useOnLevel; uint8_t onLevel; uint8_t minLevel; uint8_t maxLevel; @@ -248,18 +247,6 @@ void emberAfLevelControlClusterServerTickCallback(EndpointId endpoint) state->commandId == Commands::StepWithOnOff::Id) { setOnOffValue(endpoint, (currentLevel != state->minLevel)); - if (currentLevel == state->minLevel && state->useOnLevel) - { - status = Attributes::CurrentLevel::Set(endpoint, state->onLevel); - if (status != EMBER_ZCL_STATUS_SUCCESS) - { - emberAfLevelControlClusterPrintln("ERR: writing current level %x", status); - } - else - { - updateCoupledColorTemp(endpoint); - } - } } else { @@ -635,9 +622,6 @@ static EmberAfStatus moveToLevelHandler(EndpointId endpoint, CommandId commandId state->eventDurationMs = state->transitionTimeMs / actualStepSize; state->elapsedTimeMs = 0; - // OnLevel is not used for Move commands. - state->useOnLevel = false; - state->storedLevel = storedLevel; // The setup was successful, so mark the new state as active and return. @@ -755,9 +739,6 @@ static void moveHandler(EndpointId endpoint, CommandId commandId, uint8_t moveMo state->transitionTimeMs = difference * state->eventDurationMs; state->elapsedTimeMs = 0; - // OnLevel is not used for Move commands. - state->useOnLevel = false; - // storedLevel is not used for Move commands. state->storedLevel = INVALID_STORED_LEVEL; @@ -876,9 +857,6 @@ static void stepHandler(EndpointId endpoint, CommandId commandId, uint8_t stepMo state->eventDurationMs = state->transitionTimeMs / actualStepSize; state->elapsedTimeMs = 0; - // OnLevel is not used for Step commands. - state->useOnLevel = false; - // storedLevel is not used for Step commands state->storedLevel = INVALID_STORED_LEVEL; @@ -924,6 +902,7 @@ void emberAfOnOffClusterLevelControlEffectCallback(EndpointId endpoint, bool new uint8_t temporaryCurrentLevelCache; uint16_t currentOnOffTransitionTime; EmberAfStatus status; + bool useOnLevel = false; EmberAfLevelControlState * state = getState(endpoint); if (state == nullptr) @@ -942,14 +921,13 @@ void emberAfOnOffClusterLevelControlEffectCallback(EndpointId endpoint, bool new return; } - // Read the OnLevel attribute. #ifndef IGNORE_LEVEL_CONTROL_CLUSTER_ON_LEVEL_ATTRIBUTE if (emberAfContainsAttribute(endpoint, LevelControl::Id, Attributes::OnLevel::Id)) { status = Attributes::OnLevel::Get(endpoint, resolvedLevel); if (status != EMBER_ZCL_STATUS_SUCCESS) { - emberAfLevelControlClusterPrintln("ERR: reading current level %x", status); + emberAfLevelControlClusterPrintln("ERR: reading on level %x", status); return; } @@ -958,6 +936,10 @@ void emberAfOnOffClusterLevelControlEffectCallback(EndpointId endpoint, bool new // OnLevel has undefined value; fall back to CurrentLevel. resolvedLevel.SetNonNull(temporaryCurrentLevelCache); } + else + { + useOnLevel = true; + } } else { @@ -1007,12 +989,18 @@ void emberAfOnOffClusterLevelControlEffectCallback(EndpointId endpoint, bool new // ...else if newValue is OnOff::Commands::Off::Id... // "Move CurrentLevel to the minimum level allowed for the device over the // time period OnOffTransitionTime." - moveToLevelHandler(endpoint, Commands::MoveToLevel::Id, minimumLevelAllowedForTheDevice, currentOnOffTransitionTime, 0xFF, - 0xFF, temporaryCurrentLevelCache); - - // "If OnLevel is not defined, set the CurrentLevel to the stored level." - // The emberAfLevelControlClusterServerTickCallback implementation handles - // this. + if (useOnLevel) + { + // If OnLevel is defined, don't revert to stored level. + moveToLevelHandler(endpoint, Commands::MoveToLevel::Id, minimumLevelAllowedForTheDevice, currentOnOffTransitionTime, + 0xFF, 0xFF, INVALID_STORED_LEVEL); + } + else + { + // If OnLevel is not defined, set the CurrentLevel to the stored level. + moveToLevelHandler(endpoint, Commands::MoveToLevel::Id, minimumLevelAllowedForTheDevice, currentOnOffTransitionTime, + 0xFF, 0xFF, temporaryCurrentLevelCache); + } } } diff --git a/src/app/tests/suites/TestLevelControlWithOnOffDependency.yaml b/src/app/tests/suites/TestLevelControlWithOnOffDependency.yaml new file mode 100644 index 00000000000000..4f05a9fbeaf690 --- /dev/null +++ b/src/app/tests/suites/TestLevelControlWithOnOffDependency.yaml @@ -0,0 +1,249 @@ +# Copyright (c) 2021 Project CHIP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +name: Dependency with the On/Off cluster Verification (DUT as Server) + +config: + nodeId: 0x12344321 + cluster: "Level Control" + endpoint: 1 + +tests: + - label: "Wait for the commissioned device to be retrieved" + cluster: "DelayCommands" + command: "WaitForCommissionee" + arguments: + values: + - name: "nodeId" + value: nodeId + + - label: "Sends a MoveToLevel command to set current level to min value" + command: "MoveToLevel" + arguments: + values: + - name: "level" + value: 1 + - name: "transitionTime" + value: 0 + - name: "optionMask" + value: 1 + - name: "optionOverride" + value: 1 + + - label: "Wait 100 ms" + cluster: "DelayCommands" + command: "WaitForMs" + arguments: + values: + - name: "ms" + value: 100 + + - label: "Reads CurrentLevel attribute from DUT" + command: "readAttribute" + attribute: "current level" + response: + value: 1 + + - label: "Write OnOffTransitionTime attribute" + command: "writeAttribute" + attribute: "on off transition time" + arguments: + value: 0 + + - label: "Wait 100 ms" + cluster: "DelayCommands" + command: "WaitForMs" + arguments: + values: + - name: "ms" + value: 100 + + - label: "Read OnOffTransitionTime attribute" + command: "readAttribute" + attribute: "on off transition time" + response: + value: 0 + + - label: "Write OnLevel attribute" + command: "writeAttribute" + attribute: "on level" + arguments: + value: 254 + + - label: "Wait 100 ms" + cluster: "DelayCommands" + command: "WaitForMs" + arguments: + values: + - name: "ms" + value: 100 + + - label: "Read OnLevel attribute" + command: "readAttribute" + attribute: "on level" + response: + value: 254 + + - label: "Read MinValue attribute" + command: "readAttribute" + attribute: "min level" + response: + value: 1 + + - label: "Send On Command" + cluster: "On/Off" + command: "On" + + - label: "Check on/off attribute value is true after on command" + cluster: "On/Off" + command: "readAttribute" + attribute: "OnOff" + response: + value: 1 + + - label: "Wait OnOffTransitionTime" + cluster: "DelayCommands" + command: "WaitForMs" + arguments: + values: + - name: "ms" + value: 100 + + - label: "If OnLevel is defined, check CurrentLevel is OnLevel value" + command: "readAttribute" + attribute: "current level" + response: + value: 254 + + - label: "Send Off Command" + cluster: "On/Off" + command: "Off" + + - label: "Check on/off attribute value is false after off command" + cluster: "On/Off" + command: "readAttribute" + attribute: "OnOff" + response: + value: 0 + + - label: "Wait OnOffTransitionTime" + cluster: "DelayCommands" + command: "WaitForMs" + arguments: + values: + - name: "ms" + value: 0 + + - label: "If OnLevel is defined, check CurrentLevel is min value" + command: "readAttribute" + attribute: "current level" + response: + value: 1 + + - label: "Sends a MoveToLevel command to set current level to a mid value" + command: "MoveToLevel" + arguments: + values: + - name: "level" + value: 127 + - name: "transitionTime" + value: 0 + - name: "optionMask" + value: 1 + - name: "optionOverride" + value: 1 + + - label: "Wait 100 ms" + cluster: "DelayCommands" + command: "WaitForMs" + arguments: + values: + - name: "ms" + value: 100 + + - label: "Reads CurrentLevel attribute from DUT" + command: "readAttribute" + attribute: "current level" + response: + value: 127 + + - label: "Set OnLevel attribute to null" + command: "writeAttribute" + attribute: "on level" + arguments: + value: null + + - label: "Wait 100 ms" + cluster: "DelayCommands" + command: "WaitForMs" + arguments: + values: + - name: "ms" + value: 100 + + - label: "Read OnLevel attribute" + command: "readAttribute" + attribute: "on level" + response: + value: null + + - label: "Send On Command" + cluster: "On/Off" + command: "On" + + - label: "Check on/off attribute value is true after on command" + cluster: "On/Off" + command: "readAttribute" + attribute: "OnOff" + response: + value: 1 + + - label: "Wait OnOffTransitionTime" + cluster: "DelayCommands" + command: "WaitForMs" + arguments: + values: + - name: "ms" + value: 100 + + - label: "If OnLevel is not defined, check CurrentLevel is restored" + command: "readAttribute" + attribute: "current level" + response: + value: 127 + + - label: "Send Off Command" + cluster: "On/Off" + command: "Off" + + - label: "Check on/off attribute value is false after off command" + cluster: "On/Off" + command: "readAttribute" + attribute: "OnOff" + response: + value: 0 + + - label: "Wait OnOffTransitionTime" + cluster: "DelayCommands" + command: "WaitForMs" + arguments: + values: + - name: "ms" + value: 0 + + - label: "If OnLevel is not defined, check CurrentLevel is restored" + command: "readAttribute" + attribute: "current level" + response: + value: 127 diff --git a/src/app/tests/suites/tests.js b/src/app/tests/suites/tests.js index edcb79614284c5..eced33afc14ded 100644 --- a/src/app/tests/suites/tests.js +++ b/src/app/tests/suites/tests.js @@ -843,6 +843,7 @@ function getTests() { "TestArmFailSafe", "TestFanControl", "TestAccessControlConstraints", + "TestLevelControlWithOnOffDependency" ]; const MultiAdmin = [ diff --git a/zzz_generated/chip-tool/zap-generated/test/Commands.h b/zzz_generated/chip-tool/zap-generated/test/Commands.h index 4f707a86b477c5..3477137a51ed1e 100644 --- a/zzz_generated/chip-tool/zap-generated/test/Commands.h +++ b/zzz_generated/chip-tool/zap-generated/test/Commands.h @@ -208,6 +208,7 @@ class TestList : public Command printf("TestArmFailSafe\n"); printf("TestFanControl\n"); printf("TestAccessControlConstraints\n"); + printf("TestLevelControlWithOnOffDependency\n"); printf("TestMultiAdmin\n"); printf("Test_TC_DGSW_2_1\n"); printf("Test_TC_DGSW_2_2\n"); @@ -53888,6 +53889,462 @@ class TestAccessControlConstraintsSuite : public TestCommand } }; +class TestLevelControlWithOnOffDependencySuite : public TestCommand +{ +public: + TestLevelControlWithOnOffDependencySuite(CredentialIssuerCommands * credsIssuerConfig) : + TestCommand("TestLevelControlWithOnOffDependency", 33, credsIssuerConfig) + { + AddArgument("nodeId", 0, UINT64_MAX, &mNodeId); + AddArgument("cluster", &mCluster); + AddArgument("endpoint", 0, UINT16_MAX, &mEndpoint); + AddArgument("timeout", 0, UINT16_MAX, &mTimeout); + } + + ~TestLevelControlWithOnOffDependencySuite() {} + + chip::System::Clock::Timeout GetWaitDuration() const override + { + return chip::System::Clock::Seconds16(mTimeout.ValueOr(kTimeoutInSeconds)); + } + +private: + chip::Optional mNodeId; + chip::Optional mCluster; + chip::Optional mEndpoint; + chip::Optional mTimeout; + + chip::EndpointId GetEndpoint(chip::EndpointId endpoint) { return mEndpoint.HasValue() ? mEndpoint.Value() : endpoint; } + + // + // Tests methods + // + + void OnResponse(const chip::app::StatusIB & status, chip::TLV::TLVReader * data) override + { + bool shouldContinue = false; + + switch (mTestIndex - 1) + { + case 0: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + shouldContinue = true; + break; + case 1: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + break; + case 2: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + shouldContinue = true; + break; + case 3: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + { + uint8_t value; + VerifyOrReturn(CheckDecodeValue(chip::app::DataModel::Decode(*data, value))); + VerifyOrReturn(CheckValue("currentLevel", value, 1U)); + } + break; + case 4: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + break; + case 5: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + shouldContinue = true; + break; + case 6: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + { + uint16_t value; + VerifyOrReturn(CheckDecodeValue(chip::app::DataModel::Decode(*data, value))); + VerifyOrReturn(CheckValue("onOffTransitionTime", value, 0U)); + } + break; + case 7: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + break; + case 8: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + shouldContinue = true; + break; + case 9: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + { + chip::app::DataModel::Nullable value; + VerifyOrReturn(CheckDecodeValue(chip::app::DataModel::Decode(*data, value))); + VerifyOrReturn(CheckValueNonNull("onLevel", value)); + VerifyOrReturn(CheckValue("onLevel.Value()", value.Value(), 254U)); + } + break; + case 10: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + { + uint8_t value; + VerifyOrReturn(CheckDecodeValue(chip::app::DataModel::Decode(*data, value))); + VerifyOrReturn(CheckValue("minLevel", value, 1U)); + } + break; + case 11: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + break; + case 12: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + { + bool value; + VerifyOrReturn(CheckDecodeValue(chip::app::DataModel::Decode(*data, value))); + VerifyOrReturn(CheckValue("onOff", value, 1)); + } + break; + case 13: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + shouldContinue = true; + break; + case 14: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + { + uint8_t value; + VerifyOrReturn(CheckDecodeValue(chip::app::DataModel::Decode(*data, value))); + VerifyOrReturn(CheckValue("currentLevel", value, 254U)); + } + break; + case 15: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + break; + case 16: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + { + bool value; + VerifyOrReturn(CheckDecodeValue(chip::app::DataModel::Decode(*data, value))); + VerifyOrReturn(CheckValue("onOff", value, 0)); + } + break; + case 17: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + shouldContinue = true; + break; + case 18: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + { + uint8_t value; + VerifyOrReturn(CheckDecodeValue(chip::app::DataModel::Decode(*data, value))); + VerifyOrReturn(CheckValue("currentLevel", value, 1U)); + } + break; + case 19: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + break; + case 20: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + shouldContinue = true; + break; + case 21: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + { + uint8_t value; + VerifyOrReturn(CheckDecodeValue(chip::app::DataModel::Decode(*data, value))); + VerifyOrReturn(CheckValue("currentLevel", value, 127U)); + } + break; + case 22: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + break; + case 23: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + shouldContinue = true; + break; + case 24: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + { + chip::app::DataModel::Nullable value; + VerifyOrReturn(CheckDecodeValue(chip::app::DataModel::Decode(*data, value))); + VerifyOrReturn(CheckValueNull("onLevel", value)); + } + break; + case 25: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + break; + case 26: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + { + bool value; + VerifyOrReturn(CheckDecodeValue(chip::app::DataModel::Decode(*data, value))); + VerifyOrReturn(CheckValue("onOff", value, 1)); + } + break; + case 27: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + shouldContinue = true; + break; + case 28: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + { + uint8_t value; + VerifyOrReturn(CheckDecodeValue(chip::app::DataModel::Decode(*data, value))); + VerifyOrReturn(CheckValue("currentLevel", value, 127U)); + } + break; + case 29: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + break; + case 30: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + { + bool value; + VerifyOrReturn(CheckDecodeValue(chip::app::DataModel::Decode(*data, value))); + VerifyOrReturn(CheckValue("onOff", value, 0)); + } + break; + case 31: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + shouldContinue = true; + break; + case 32: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + { + uint8_t value; + VerifyOrReturn(CheckDecodeValue(chip::app::DataModel::Decode(*data, value))); + VerifyOrReturn(CheckValue("currentLevel", value, 127U)); + } + break; + default: + LogErrorOnFailure(ContinueOnChipMainThread(CHIP_ERROR_INVALID_ARGUMENT)); + } + + if (shouldContinue) + { + ContinueOnChipMainThread(CHIP_NO_ERROR); + } + } + + CHIP_ERROR DoTestStep(uint16_t testIndex) override + { + using namespace chip::app::Clusters; + switch (testIndex) + { + case 0: { + LogStep(0, "Wait for the commissioned device to be retrieved"); + ListFreer listFreer; + chip::app::Clusters::DelayCommands::Commands::WaitForCommissionee::Type value; + value.nodeId = mNodeId.HasValue() ? mNodeId.Value() : 305414945ULL; + return WaitForCommissionee(kIdentityAlpha, value); + } + case 1: { + LogStep(1, "Sends a MoveToLevel command to set current level to min value"); + ListFreer listFreer; + chip::app::Clusters::LevelControl::Commands::MoveToLevel::Type value; + value.level = 1U; + value.transitionTime = 0U; + value.optionMask = 1U; + value.optionOverride = 1U; + return SendCommand(kIdentityAlpha, GetEndpoint(1), LevelControl::Id, LevelControl::Commands::MoveToLevel::Id, value, + chip::NullOptional + + ); + } + case 2: { + LogStep(2, "Wait 100 ms"); + ListFreer listFreer; + chip::app::Clusters::DelayCommands::Commands::WaitForMs::Type value; + value.ms = 100UL; + return WaitForMs(kIdentityAlpha, value); + } + case 3: { + LogStep(3, "Reads CurrentLevel attribute from DUT"); + return ReadAttribute(kIdentityAlpha, GetEndpoint(1), LevelControl::Id, LevelControl::Attributes::CurrentLevel::Id, true, + chip::NullOptional); + } + case 4: { + LogStep(4, "Write OnOffTransitionTime attribute"); + ListFreer listFreer; + uint16_t value; + value = 0U; + return WriteAttribute(kIdentityAlpha, GetEndpoint(1), LevelControl::Id, + LevelControl::Attributes::OnOffTransitionTime::Id, value, chip::NullOptional, chip::NullOptional); + } + case 5: { + LogStep(5, "Wait 100 ms"); + ListFreer listFreer; + chip::app::Clusters::DelayCommands::Commands::WaitForMs::Type value; + value.ms = 100UL; + return WaitForMs(kIdentityAlpha, value); + } + case 6: { + LogStep(6, "Read OnOffTransitionTime attribute"); + return ReadAttribute(kIdentityAlpha, GetEndpoint(1), LevelControl::Id, + LevelControl::Attributes::OnOffTransitionTime::Id, true, chip::NullOptional); + } + case 7: { + LogStep(7, "Write OnLevel attribute"); + ListFreer listFreer; + chip::app::DataModel::Nullable value; + value.SetNonNull(); + value.Value() = 254U; + return WriteAttribute(kIdentityAlpha, GetEndpoint(1), LevelControl::Id, LevelControl::Attributes::OnLevel::Id, value, + chip::NullOptional, chip::NullOptional); + } + case 8: { + LogStep(8, "Wait 100 ms"); + ListFreer listFreer; + chip::app::Clusters::DelayCommands::Commands::WaitForMs::Type value; + value.ms = 100UL; + return WaitForMs(kIdentityAlpha, value); + } + case 9: { + LogStep(9, "Read OnLevel attribute"); + return ReadAttribute(kIdentityAlpha, GetEndpoint(1), LevelControl::Id, LevelControl::Attributes::OnLevel::Id, true, + chip::NullOptional); + } + case 10: { + LogStep(10, "Read MinValue attribute"); + return ReadAttribute(kIdentityAlpha, GetEndpoint(1), LevelControl::Id, LevelControl::Attributes::MinLevel::Id, true, + chip::NullOptional); + } + case 11: { + LogStep(11, "Send On Command"); + ListFreer listFreer; + chip::app::Clusters::OnOff::Commands::On::Type value; + return SendCommand(kIdentityAlpha, GetEndpoint(1), OnOff::Id, OnOff::Commands::On::Id, value, chip::NullOptional + + ); + } + case 12: { + LogStep(12, "Check on/off attribute value is true after on command"); + return ReadAttribute(kIdentityAlpha, GetEndpoint(1), OnOff::Id, OnOff::Attributes::OnOff::Id, true, chip::NullOptional); + } + case 13: { + LogStep(13, "Wait OnOffTransitionTime"); + ListFreer listFreer; + chip::app::Clusters::DelayCommands::Commands::WaitForMs::Type value; + value.ms = 100UL; + return WaitForMs(kIdentityAlpha, value); + } + case 14: { + LogStep(14, "If OnLevel is defined, check CurrentLevel is OnLevel value"); + return ReadAttribute(kIdentityAlpha, GetEndpoint(1), LevelControl::Id, LevelControl::Attributes::CurrentLevel::Id, true, + chip::NullOptional); + } + case 15: { + LogStep(15, "Send Off Command"); + ListFreer listFreer; + chip::app::Clusters::OnOff::Commands::Off::Type value; + return SendCommand(kIdentityAlpha, GetEndpoint(1), OnOff::Id, OnOff::Commands::Off::Id, value, chip::NullOptional + + ); + } + case 16: { + LogStep(16, "Check on/off attribute value is false after off command"); + return ReadAttribute(kIdentityAlpha, GetEndpoint(1), OnOff::Id, OnOff::Attributes::OnOff::Id, true, chip::NullOptional); + } + case 17: { + LogStep(17, "Wait OnOffTransitionTime"); + ListFreer listFreer; + chip::app::Clusters::DelayCommands::Commands::WaitForMs::Type value; + value.ms = 0UL; + return WaitForMs(kIdentityAlpha, value); + } + case 18: { + LogStep(18, "If OnLevel is defined, check CurrentLevel is min value"); + return ReadAttribute(kIdentityAlpha, GetEndpoint(1), LevelControl::Id, LevelControl::Attributes::CurrentLevel::Id, true, + chip::NullOptional); + } + case 19: { + LogStep(19, "Sends a MoveToLevel command to set current level to a mid value"); + ListFreer listFreer; + chip::app::Clusters::LevelControl::Commands::MoveToLevel::Type value; + value.level = 127U; + value.transitionTime = 0U; + value.optionMask = 1U; + value.optionOverride = 1U; + return SendCommand(kIdentityAlpha, GetEndpoint(1), LevelControl::Id, LevelControl::Commands::MoveToLevel::Id, value, + chip::NullOptional + + ); + } + case 20: { + LogStep(20, "Wait 100 ms"); + ListFreer listFreer; + chip::app::Clusters::DelayCommands::Commands::WaitForMs::Type value; + value.ms = 100UL; + return WaitForMs(kIdentityAlpha, value); + } + case 21: { + LogStep(21, "Reads CurrentLevel attribute from DUT"); + return ReadAttribute(kIdentityAlpha, GetEndpoint(1), LevelControl::Id, LevelControl::Attributes::CurrentLevel::Id, true, + chip::NullOptional); + } + case 22: { + LogStep(22, "Set OnLevel attribute to null"); + ListFreer listFreer; + chip::app::DataModel::Nullable value; + value.SetNull(); + return WriteAttribute(kIdentityAlpha, GetEndpoint(1), LevelControl::Id, LevelControl::Attributes::OnLevel::Id, value, + chip::NullOptional, chip::NullOptional); + } + case 23: { + LogStep(23, "Wait 100 ms"); + ListFreer listFreer; + chip::app::Clusters::DelayCommands::Commands::WaitForMs::Type value; + value.ms = 100UL; + return WaitForMs(kIdentityAlpha, value); + } + case 24: { + LogStep(24, "Read OnLevel attribute"); + return ReadAttribute(kIdentityAlpha, GetEndpoint(1), LevelControl::Id, LevelControl::Attributes::OnLevel::Id, true, + chip::NullOptional); + } + case 25: { + LogStep(25, "Send On Command"); + ListFreer listFreer; + chip::app::Clusters::OnOff::Commands::On::Type value; + return SendCommand(kIdentityAlpha, GetEndpoint(1), OnOff::Id, OnOff::Commands::On::Id, value, chip::NullOptional + + ); + } + case 26: { + LogStep(26, "Check on/off attribute value is true after on command"); + return ReadAttribute(kIdentityAlpha, GetEndpoint(1), OnOff::Id, OnOff::Attributes::OnOff::Id, true, chip::NullOptional); + } + case 27: { + LogStep(27, "Wait OnOffTransitionTime"); + ListFreer listFreer; + chip::app::Clusters::DelayCommands::Commands::WaitForMs::Type value; + value.ms = 100UL; + return WaitForMs(kIdentityAlpha, value); + } + case 28: { + LogStep(28, "If OnLevel is not defined, check CurrentLevel is restored"); + return ReadAttribute(kIdentityAlpha, GetEndpoint(1), LevelControl::Id, LevelControl::Attributes::CurrentLevel::Id, true, + chip::NullOptional); + } + case 29: { + LogStep(29, "Send Off Command"); + ListFreer listFreer; + chip::app::Clusters::OnOff::Commands::Off::Type value; + return SendCommand(kIdentityAlpha, GetEndpoint(1), OnOff::Id, OnOff::Commands::Off::Id, value, chip::NullOptional + + ); + } + case 30: { + LogStep(30, "Check on/off attribute value is false after off command"); + return ReadAttribute(kIdentityAlpha, GetEndpoint(1), OnOff::Id, OnOff::Attributes::OnOff::Id, true, chip::NullOptional); + } + case 31: { + LogStep(31, "Wait OnOffTransitionTime"); + ListFreer listFreer; + chip::app::Clusters::DelayCommands::Commands::WaitForMs::Type value; + value.ms = 0UL; + return WaitForMs(kIdentityAlpha, value); + } + case 32: { + LogStep(32, "If OnLevel is not defined, check CurrentLevel is restored"); + return ReadAttribute(kIdentityAlpha, GetEndpoint(1), LevelControl::Id, LevelControl::Attributes::CurrentLevel::Id, true, + chip::NullOptional); + } + } + return CHIP_NO_ERROR; + } +}; + class TestMultiAdminSuite : public TestCommand { public: @@ -91157,6 +91614,7 @@ void registerCommandsTests(Commands & commands, CredentialIssuerCommands * creds make_unique(credsIssuerConfig), make_unique(credsIssuerConfig), make_unique(credsIssuerConfig), + make_unique(credsIssuerConfig), make_unique(credsIssuerConfig), make_unique(credsIssuerConfig), make_unique(credsIssuerConfig), diff --git a/zzz_generated/darwin-framework-tool/zap-generated/test/Commands.h b/zzz_generated/darwin-framework-tool/zap-generated/test/Commands.h index 0edeb7084a01c3..9bb662a107588d 100644 --- a/zzz_generated/darwin-framework-tool/zap-generated/test/Commands.h +++ b/zzz_generated/darwin-framework-tool/zap-generated/test/Commands.h @@ -195,6 +195,7 @@ class TestList : public Command { printf("TestArmFailSafe\n"); printf("TestFanControl\n"); printf("TestAccessControlConstraints\n"); + printf("TestLevelControlWithOnOffDependency\n"); printf("TestMultiAdmin\n"); printf("Test_TC_DGSW_2_1\n"); printf("Test_TC_DGSW_2_2\n"); @@ -92199,6 +92200,890 @@ class TestAccessControlConstraints : public TestCommandBridge { } }; +class TestLevelControlWithOnOffDependency : public TestCommandBridge { +public: + // NOLINTBEGIN(clang-analyzer-nullability.NullPassedToNonnull): Test constructor nullability not enforced + TestLevelControlWithOnOffDependency() + : TestCommandBridge("TestLevelControlWithOnOffDependency") + , mTestIndex(0) + { + AddArgument("nodeId", 0, UINT64_MAX, &mNodeId); + AddArgument("cluster", &mCluster); + AddArgument("endpoint", 0, UINT16_MAX, &mEndpoint); + AddArgument("timeout", 0, UINT16_MAX, &mTimeout); + } + // NOLINTEND(clang-analyzer-nullability.NullPassedToNonnull) + + ~TestLevelControlWithOnOffDependency() {} + + /////////// TestCommand Interface ///////// + void NextTest() override + { + CHIP_ERROR err = CHIP_NO_ERROR; + + if (0 == mTestIndex) { + ChipLogProgress(chipTool, " **** Test Start: TestLevelControlWithOnOffDependency\n"); + } + + if (mTestCount == mTestIndex) { + ChipLogProgress(chipTool, " **** Test Complete: TestLevelControlWithOnOffDependency\n"); + SetCommandExitStatus(CHIP_NO_ERROR); + return; + } + + Wait(); + + // Ensure we increment mTestIndex before we start running the relevant + // command. That way if we lose the timeslice after we send the message + // but before our function call returns, we won't end up with an + // incorrect mTestIndex value observed when we get the response. + switch (mTestIndex++) { + case 0: + ChipLogProgress(chipTool, " ***** Test Step 0 : Wait for the commissioned device to be retrieved\n"); + err = TestWaitForTheCommissionedDeviceToBeRetrieved_0(); + break; + case 1: + ChipLogProgress(chipTool, " ***** Test Step 1 : Sends a MoveToLevel command to set current level to min value\n"); + err = TestSendsAMoveToLevelCommandToSetCurrentLevelToMinValue_1(); + break; + case 2: + ChipLogProgress(chipTool, " ***** Test Step 2 : Wait 100 ms\n"); + err = TestWait100Ms_2(); + break; + case 3: + ChipLogProgress(chipTool, " ***** Test Step 3 : Reads CurrentLevel attribute from DUT\n"); + err = TestReadsCurrentLevelAttributeFromDut_3(); + break; + case 4: + ChipLogProgress(chipTool, " ***** Test Step 4 : Write OnOffTransitionTime attribute\n"); + err = TestWriteOnOffTransitionTimeAttribute_4(); + break; + case 5: + ChipLogProgress(chipTool, " ***** Test Step 5 : Wait 100 ms\n"); + err = TestWait100Ms_5(); + break; + case 6: + ChipLogProgress(chipTool, " ***** Test Step 6 : Read OnOffTransitionTime attribute\n"); + err = TestReadOnOffTransitionTimeAttribute_6(); + break; + case 7: + ChipLogProgress(chipTool, " ***** Test Step 7 : Write OnLevel attribute\n"); + err = TestWriteOnLevelAttribute_7(); + break; + case 8: + ChipLogProgress(chipTool, " ***** Test Step 8 : Wait 100 ms\n"); + err = TestWait100Ms_8(); + break; + case 9: + ChipLogProgress(chipTool, " ***** Test Step 9 : Read OnLevel attribute\n"); + err = TestReadOnLevelAttribute_9(); + break; + case 10: + ChipLogProgress(chipTool, " ***** Test Step 10 : Read MinValue attribute\n"); + err = TestReadMinValueAttribute_10(); + break; + case 11: + ChipLogProgress(chipTool, " ***** Test Step 11 : Send On Command\n"); + err = TestSendOnCommand_11(); + break; + case 12: + ChipLogProgress(chipTool, " ***** Test Step 12 : Check on/off attribute value is true after on command\n"); + err = TestCheckOnOffAttributeValueIsTrueAfterOnCommand_12(); + break; + case 13: + ChipLogProgress(chipTool, " ***** Test Step 13 : Wait OnOffTransitionTime\n"); + err = TestWaitOnOffTransitionTime_13(); + break; + case 14: + ChipLogProgress(chipTool, " ***** Test Step 14 : If OnLevel is defined, check CurrentLevel is OnLevel value\n"); + err = TestIfOnLevelIsDefinedCheckCurrentLevelIsOnLevelValue_14(); + break; + case 15: + ChipLogProgress(chipTool, " ***** Test Step 15 : Send Off Command\n"); + err = TestSendOffCommand_15(); + break; + case 16: + ChipLogProgress(chipTool, " ***** Test Step 16 : Check on/off attribute value is false after off command\n"); + err = TestCheckOnOffAttributeValueIsFalseAfterOffCommand_16(); + break; + case 17: + ChipLogProgress(chipTool, " ***** Test Step 17 : Wait OnOffTransitionTime\n"); + err = TestWaitOnOffTransitionTime_17(); + break; + case 18: + ChipLogProgress(chipTool, " ***** Test Step 18 : If OnLevel is defined, check CurrentLevel is min value\n"); + err = TestIfOnLevelIsDefinedCheckCurrentLevelIsMinValue_18(); + break; + case 19: + ChipLogProgress(chipTool, " ***** Test Step 19 : Sends a MoveToLevel command to set current level to a mid value\n"); + err = TestSendsAMoveToLevelCommandToSetCurrentLevelToAMidValue_19(); + break; + case 20: + ChipLogProgress(chipTool, " ***** Test Step 20 : Wait 100 ms\n"); + err = TestWait100Ms_20(); + break; + case 21: + ChipLogProgress(chipTool, " ***** Test Step 21 : Reads CurrentLevel attribute from DUT\n"); + err = TestReadsCurrentLevelAttributeFromDut_21(); + break; + case 22: + ChipLogProgress(chipTool, " ***** Test Step 22 : Set OnLevel attribute to null\n"); + err = TestSetOnLevelAttributeToNull_22(); + break; + case 23: + ChipLogProgress(chipTool, " ***** Test Step 23 : Wait 100 ms\n"); + err = TestWait100Ms_23(); + break; + case 24: + ChipLogProgress(chipTool, " ***** Test Step 24 : Read OnLevel attribute\n"); + err = TestReadOnLevelAttribute_24(); + break; + case 25: + ChipLogProgress(chipTool, " ***** Test Step 25 : Send On Command\n"); + err = TestSendOnCommand_25(); + break; + case 26: + ChipLogProgress(chipTool, " ***** Test Step 26 : Check on/off attribute value is true after on command\n"); + err = TestCheckOnOffAttributeValueIsTrueAfterOnCommand_26(); + break; + case 27: + ChipLogProgress(chipTool, " ***** Test Step 27 : Wait OnOffTransitionTime\n"); + err = TestWaitOnOffTransitionTime_27(); + break; + case 28: + ChipLogProgress(chipTool, " ***** Test Step 28 : If OnLevel is not defined, check CurrentLevel is restored\n"); + err = TestIfOnLevelIsNotDefinedCheckCurrentLevelIsRestored_28(); + break; + case 29: + ChipLogProgress(chipTool, " ***** Test Step 29 : Send Off Command\n"); + err = TestSendOffCommand_29(); + break; + case 30: + ChipLogProgress(chipTool, " ***** Test Step 30 : Check on/off attribute value is false after off command\n"); + err = TestCheckOnOffAttributeValueIsFalseAfterOffCommand_30(); + break; + case 31: + ChipLogProgress(chipTool, " ***** Test Step 31 : Wait OnOffTransitionTime\n"); + err = TestWaitOnOffTransitionTime_31(); + break; + case 32: + ChipLogProgress(chipTool, " ***** Test Step 32 : If OnLevel is not defined, check CurrentLevel is restored\n"); + err = TestIfOnLevelIsNotDefinedCheckCurrentLevelIsRestored_32(); + break; + } + + if (CHIP_NO_ERROR != err) { + ChipLogError(chipTool, " ***** Test Failure: %s\n", chip::ErrorStr(err)); + SetCommandExitStatus(err); + } + } + + void OnStatusUpdate(const chip::app::StatusIB & status) override + { + switch (mTestIndex - 1) { + case 0: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + break; + case 1: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + break; + case 2: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + break; + case 3: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + break; + case 4: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + break; + case 5: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + break; + case 6: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + break; + case 7: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + break; + case 8: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + break; + case 9: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + break; + case 10: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + break; + case 11: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + break; + case 12: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + break; + case 13: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + break; + case 14: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + break; + case 15: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + break; + case 16: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + break; + case 17: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + break; + case 18: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + break; + case 19: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + break; + case 20: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + break; + case 21: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + break; + case 22: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + break; + case 23: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + break; + case 24: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + break; + case 25: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + break; + case 26: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + break; + case 27: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + break; + case 28: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + break; + case 29: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + break; + case 30: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + break; + case 31: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + break; + case 32: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + break; + } + + // Go on to the next test. + ContinueOnChipMainThread(CHIP_NO_ERROR); + } + + chip::System::Clock::Timeout GetWaitDuration() const override + { + return chip::System::Clock::Seconds16(mTimeout.ValueOr(kTimeoutInSeconds)); + } + +private: + std::atomic_uint16_t mTestIndex; + const uint16_t mTestCount = 33; + + chip::Optional mNodeId; + chip::Optional mCluster; + chip::Optional mEndpoint; + chip::Optional mTimeout; + + CHIP_ERROR TestWaitForTheCommissionedDeviceToBeRetrieved_0() + { + chip::app::Clusters::DelayCommands::Commands::WaitForCommissionee::Type value; + value.nodeId = mNodeId.HasValue() ? mNodeId.Value() : 305414945ULL; + return WaitForCommissionee("alpha", value); + } + + CHIP_ERROR TestSendsAMoveToLevelCommandToSetCurrentLevelToMinValue_1() + { + MTRBaseDevice * device = GetDevice("alpha"); + MTRBaseClusterLevelControl * cluster = [[MTRBaseClusterLevelControl alloc] initWithDevice:device + endpoint:1 + queue:mCallbackQueue]; + VerifyOrReturnError(cluster != nil, CHIP_ERROR_INCORRECT_STATE); + + __auto_type * params = [[MTRLevelControlClusterMoveToLevelParams alloc] init]; + params.level = [NSNumber numberWithUnsignedChar:1U]; + params.transitionTime = [NSNumber numberWithUnsignedShort:0U]; + params.optionMask = [NSNumber numberWithUnsignedChar:1U]; + params.optionOverride = [NSNumber numberWithUnsignedChar:1U]; + [cluster moveToLevelWithParams:params + completionHandler:^(NSError * _Nullable err) { + NSLog(@"Sends a MoveToLevel command to set current level to min value Error: %@", err); + + VerifyOrReturn(CheckValue("status", err ? err.code : 0, 0)); + + NextTest(); + }]; + + return CHIP_NO_ERROR; + } + + CHIP_ERROR TestWait100Ms_2() + { + chip::app::Clusters::DelayCommands::Commands::WaitForMs::Type value; + value.ms = 100UL; + return WaitForMs("alpha", value); + } + + CHIP_ERROR TestReadsCurrentLevelAttributeFromDut_3() + { + MTRBaseDevice * device = GetDevice("alpha"); + MTRBaseClusterLevelControl * cluster = [[MTRBaseClusterLevelControl alloc] initWithDevice:device + endpoint:1 + queue:mCallbackQueue]; + VerifyOrReturnError(cluster != nil, CHIP_ERROR_INCORRECT_STATE); + + [cluster readAttributeCurrentLevelWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable err) { + NSLog(@"Reads CurrentLevel attribute from DUT Error: %@", err); + + VerifyOrReturn(CheckValue("status", err ? err.code : 0, 0)); + + { + id actualValue = value; + VerifyOrReturn(CheckValue("current level", actualValue, 1U)); + } + + NextTest(); + }]; + + return CHIP_NO_ERROR; + } + + CHIP_ERROR TestWriteOnOffTransitionTimeAttribute_4() + { + MTRBaseDevice * device = GetDevice("alpha"); + MTRBaseClusterLevelControl * cluster = [[MTRBaseClusterLevelControl alloc] initWithDevice:device + endpoint:1 + queue:mCallbackQueue]; + VerifyOrReturnError(cluster != nil, CHIP_ERROR_INCORRECT_STATE); + + id onOffTransitionTimeArgument; + onOffTransitionTimeArgument = [NSNumber numberWithUnsignedShort:0U]; + [cluster writeAttributeOnOffTransitionTimeWithValue:onOffTransitionTimeArgument + completionHandler:^(NSError * _Nullable err) { + NSLog(@"Write OnOffTransitionTime attribute Error: %@", err); + + VerifyOrReturn(CheckValue("status", err ? err.code : 0, 0)); + + NextTest(); + }]; + + return CHIP_NO_ERROR; + } + + CHIP_ERROR TestWait100Ms_5() + { + chip::app::Clusters::DelayCommands::Commands::WaitForMs::Type value; + value.ms = 100UL; + return WaitForMs("alpha", value); + } + + CHIP_ERROR TestReadOnOffTransitionTimeAttribute_6() + { + MTRBaseDevice * device = GetDevice("alpha"); + MTRBaseClusterLevelControl * cluster = [[MTRBaseClusterLevelControl alloc] initWithDevice:device + endpoint:1 + queue:mCallbackQueue]; + VerifyOrReturnError(cluster != nil, CHIP_ERROR_INCORRECT_STATE); + + [cluster readAttributeOnOffTransitionTimeWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable err) { + NSLog(@"Read OnOffTransitionTime attribute Error: %@", err); + + VerifyOrReturn(CheckValue("status", err ? err.code : 0, 0)); + + { + id actualValue = value; + VerifyOrReturn(CheckValue("on off transition time", actualValue, 0U)); + } + + NextTest(); + }]; + + return CHIP_NO_ERROR; + } + + CHIP_ERROR TestWriteOnLevelAttribute_7() + { + MTRBaseDevice * device = GetDevice("alpha"); + MTRBaseClusterLevelControl * cluster = [[MTRBaseClusterLevelControl alloc] initWithDevice:device + endpoint:1 + queue:mCallbackQueue]; + VerifyOrReturnError(cluster != nil, CHIP_ERROR_INCORRECT_STATE); + + id onLevelArgument; + onLevelArgument = [NSNumber numberWithUnsignedChar:254U]; + [cluster writeAttributeOnLevelWithValue:onLevelArgument + completionHandler:^(NSError * _Nullable err) { + NSLog(@"Write OnLevel attribute Error: %@", err); + + VerifyOrReturn(CheckValue("status", err ? err.code : 0, 0)); + + NextTest(); + }]; + + return CHIP_NO_ERROR; + } + + CHIP_ERROR TestWait100Ms_8() + { + chip::app::Clusters::DelayCommands::Commands::WaitForMs::Type value; + value.ms = 100UL; + return WaitForMs("alpha", value); + } + + CHIP_ERROR TestReadOnLevelAttribute_9() + { + MTRBaseDevice * device = GetDevice("alpha"); + MTRBaseClusterLevelControl * cluster = [[MTRBaseClusterLevelControl alloc] initWithDevice:device + endpoint:1 + queue:mCallbackQueue]; + VerifyOrReturnError(cluster != nil, CHIP_ERROR_INCORRECT_STATE); + + [cluster readAttributeOnLevelWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable err) { + NSLog(@"Read OnLevel attribute Error: %@", err); + + VerifyOrReturn(CheckValue("status", err ? err.code : 0, 0)); + + { + id actualValue = value; + VerifyOrReturn(CheckValueNonNull("on level", actualValue)); + VerifyOrReturn(CheckValue("on level", actualValue, 254U)); + } + + NextTest(); + }]; + + return CHIP_NO_ERROR; + } + + CHIP_ERROR TestReadMinValueAttribute_10() + { + MTRBaseDevice * device = GetDevice("alpha"); + MTRBaseClusterLevelControl * cluster = [[MTRBaseClusterLevelControl alloc] initWithDevice:device + endpoint:1 + queue:mCallbackQueue]; + VerifyOrReturnError(cluster != nil, CHIP_ERROR_INCORRECT_STATE); + + [cluster readAttributeMinLevelWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable err) { + NSLog(@"Read MinValue attribute Error: %@", err); + + VerifyOrReturn(CheckValue("status", err ? err.code : 0, 0)); + + { + id actualValue = value; + VerifyOrReturn(CheckValue("min level", actualValue, 1U)); + } + + NextTest(); + }]; + + return CHIP_NO_ERROR; + } + + CHIP_ERROR TestSendOnCommand_11() + { + MTRBaseDevice * device = GetDevice("alpha"); + MTRBaseClusterOnOff * cluster = [[MTRBaseClusterOnOff alloc] initWithDevice:device endpoint:1 queue:mCallbackQueue]; + VerifyOrReturnError(cluster != nil, CHIP_ERROR_INCORRECT_STATE); + + [cluster onWithCompletionHandler:^(NSError * _Nullable err) { + NSLog(@"Send On Command Error: %@", err); + + VerifyOrReturn(CheckValue("status", err ? err.code : 0, 0)); + + NextTest(); + }]; + + return CHIP_NO_ERROR; + } + + CHIP_ERROR TestCheckOnOffAttributeValueIsTrueAfterOnCommand_12() + { + MTRBaseDevice * device = GetDevice("alpha"); + MTRBaseClusterOnOff * cluster = [[MTRBaseClusterOnOff alloc] initWithDevice:device endpoint:1 queue:mCallbackQueue]; + VerifyOrReturnError(cluster != nil, CHIP_ERROR_INCORRECT_STATE); + + [cluster readAttributeOnOffWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable err) { + NSLog(@"Check on/off attribute value is true after on command Error: %@", err); + + VerifyOrReturn(CheckValue("status", err ? err.code : 0, 0)); + + { + id actualValue = value; + VerifyOrReturn(CheckValue("OnOff", actualValue, 1)); + } + + NextTest(); + }]; + + return CHIP_NO_ERROR; + } + + CHIP_ERROR TestWaitOnOffTransitionTime_13() + { + chip::app::Clusters::DelayCommands::Commands::WaitForMs::Type value; + value.ms = 100UL; + return WaitForMs("alpha", value); + } + + CHIP_ERROR TestIfOnLevelIsDefinedCheckCurrentLevelIsOnLevelValue_14() + { + MTRBaseDevice * device = GetDevice("alpha"); + MTRBaseClusterLevelControl * cluster = [[MTRBaseClusterLevelControl alloc] initWithDevice:device + endpoint:1 + queue:mCallbackQueue]; + VerifyOrReturnError(cluster != nil, CHIP_ERROR_INCORRECT_STATE); + + [cluster readAttributeCurrentLevelWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable err) { + NSLog(@"If OnLevel is defined, check CurrentLevel is OnLevel value Error: %@", err); + + VerifyOrReturn(CheckValue("status", err ? err.code : 0, 0)); + + { + id actualValue = value; + VerifyOrReturn(CheckValue("current level", actualValue, 254U)); + } + + NextTest(); + }]; + + return CHIP_NO_ERROR; + } + + CHIP_ERROR TestSendOffCommand_15() + { + MTRBaseDevice * device = GetDevice("alpha"); + MTRBaseClusterOnOff * cluster = [[MTRBaseClusterOnOff alloc] initWithDevice:device endpoint:1 queue:mCallbackQueue]; + VerifyOrReturnError(cluster != nil, CHIP_ERROR_INCORRECT_STATE); + + [cluster offWithCompletionHandler:^(NSError * _Nullable err) { + NSLog(@"Send Off Command Error: %@", err); + + VerifyOrReturn(CheckValue("status", err ? err.code : 0, 0)); + + NextTest(); + }]; + + return CHIP_NO_ERROR; + } + + CHIP_ERROR TestCheckOnOffAttributeValueIsFalseAfterOffCommand_16() + { + MTRBaseDevice * device = GetDevice("alpha"); + MTRBaseClusterOnOff * cluster = [[MTRBaseClusterOnOff alloc] initWithDevice:device endpoint:1 queue:mCallbackQueue]; + VerifyOrReturnError(cluster != nil, CHIP_ERROR_INCORRECT_STATE); + + [cluster readAttributeOnOffWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable err) { + NSLog(@"Check on/off attribute value is false after off command Error: %@", err); + + VerifyOrReturn(CheckValue("status", err ? err.code : 0, 0)); + + { + id actualValue = value; + VerifyOrReturn(CheckValue("OnOff", actualValue, 0)); + } + + NextTest(); + }]; + + return CHIP_NO_ERROR; + } + + CHIP_ERROR TestWaitOnOffTransitionTime_17() + { + chip::app::Clusters::DelayCommands::Commands::WaitForMs::Type value; + value.ms = 0UL; + return WaitForMs("alpha", value); + } + + CHIP_ERROR TestIfOnLevelIsDefinedCheckCurrentLevelIsMinValue_18() + { + MTRBaseDevice * device = GetDevice("alpha"); + MTRBaseClusterLevelControl * cluster = [[MTRBaseClusterLevelControl alloc] initWithDevice:device + endpoint:1 + queue:mCallbackQueue]; + VerifyOrReturnError(cluster != nil, CHIP_ERROR_INCORRECT_STATE); + + [cluster readAttributeCurrentLevelWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable err) { + NSLog(@"If OnLevel is defined, check CurrentLevel is min value Error: %@", err); + + VerifyOrReturn(CheckValue("status", err ? err.code : 0, 0)); + + { + id actualValue = value; + VerifyOrReturn(CheckValue("current level", actualValue, 1U)); + } + + NextTest(); + }]; + + return CHIP_NO_ERROR; + } + + CHIP_ERROR TestSendsAMoveToLevelCommandToSetCurrentLevelToAMidValue_19() + { + MTRBaseDevice * device = GetDevice("alpha"); + MTRBaseClusterLevelControl * cluster = [[MTRBaseClusterLevelControl alloc] initWithDevice:device + endpoint:1 + queue:mCallbackQueue]; + VerifyOrReturnError(cluster != nil, CHIP_ERROR_INCORRECT_STATE); + + __auto_type * params = [[MTRLevelControlClusterMoveToLevelParams alloc] init]; + params.level = [NSNumber numberWithUnsignedChar:127U]; + params.transitionTime = [NSNumber numberWithUnsignedShort:0U]; + params.optionMask = [NSNumber numberWithUnsignedChar:1U]; + params.optionOverride = [NSNumber numberWithUnsignedChar:1U]; + [cluster moveToLevelWithParams:params + completionHandler:^(NSError * _Nullable err) { + NSLog(@"Sends a MoveToLevel command to set current level to a mid value Error: %@", err); + + VerifyOrReturn(CheckValue("status", err ? err.code : 0, 0)); + + NextTest(); + }]; + + return CHIP_NO_ERROR; + } + + CHIP_ERROR TestWait100Ms_20() + { + chip::app::Clusters::DelayCommands::Commands::WaitForMs::Type value; + value.ms = 100UL; + return WaitForMs("alpha", value); + } + + CHIP_ERROR TestReadsCurrentLevelAttributeFromDut_21() + { + MTRBaseDevice * device = GetDevice("alpha"); + MTRBaseClusterLevelControl * cluster = [[MTRBaseClusterLevelControl alloc] initWithDevice:device + endpoint:1 + queue:mCallbackQueue]; + VerifyOrReturnError(cluster != nil, CHIP_ERROR_INCORRECT_STATE); + + [cluster readAttributeCurrentLevelWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable err) { + NSLog(@"Reads CurrentLevel attribute from DUT Error: %@", err); + + VerifyOrReturn(CheckValue("status", err ? err.code : 0, 0)); + + { + id actualValue = value; + VerifyOrReturn(CheckValue("current level", actualValue, 127U)); + } + + NextTest(); + }]; + + return CHIP_NO_ERROR; + } + + CHIP_ERROR TestSetOnLevelAttributeToNull_22() + { + MTRBaseDevice * device = GetDevice("alpha"); + MTRBaseClusterLevelControl * cluster = [[MTRBaseClusterLevelControl alloc] initWithDevice:device + endpoint:1 + queue:mCallbackQueue]; + VerifyOrReturnError(cluster != nil, CHIP_ERROR_INCORRECT_STATE); + + id onLevelArgument; + onLevelArgument = nil; + [cluster writeAttributeOnLevelWithValue:onLevelArgument + completionHandler:^(NSError * _Nullable err) { + NSLog(@"Set OnLevel attribute to null Error: %@", err); + + VerifyOrReturn(CheckValue("status", err ? err.code : 0, 0)); + + NextTest(); + }]; + + return CHIP_NO_ERROR; + } + + CHIP_ERROR TestWait100Ms_23() + { + chip::app::Clusters::DelayCommands::Commands::WaitForMs::Type value; + value.ms = 100UL; + return WaitForMs("alpha", value); + } + + CHIP_ERROR TestReadOnLevelAttribute_24() + { + MTRBaseDevice * device = GetDevice("alpha"); + MTRBaseClusterLevelControl * cluster = [[MTRBaseClusterLevelControl alloc] initWithDevice:device + endpoint:1 + queue:mCallbackQueue]; + VerifyOrReturnError(cluster != nil, CHIP_ERROR_INCORRECT_STATE); + + [cluster readAttributeOnLevelWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable err) { + NSLog(@"Read OnLevel attribute Error: %@", err); + + VerifyOrReturn(CheckValue("status", err ? err.code : 0, 0)); + + { + id actualValue = value; + VerifyOrReturn(CheckValueNull("on level", actualValue)); + } + + NextTest(); + }]; + + return CHIP_NO_ERROR; + } + + CHIP_ERROR TestSendOnCommand_25() + { + MTRBaseDevice * device = GetDevice("alpha"); + MTRBaseClusterOnOff * cluster = [[MTRBaseClusterOnOff alloc] initWithDevice:device endpoint:1 queue:mCallbackQueue]; + VerifyOrReturnError(cluster != nil, CHIP_ERROR_INCORRECT_STATE); + + [cluster onWithCompletionHandler:^(NSError * _Nullable err) { + NSLog(@"Send On Command Error: %@", err); + + VerifyOrReturn(CheckValue("status", err ? err.code : 0, 0)); + + NextTest(); + }]; + + return CHIP_NO_ERROR; + } + + CHIP_ERROR TestCheckOnOffAttributeValueIsTrueAfterOnCommand_26() + { + MTRBaseDevice * device = GetDevice("alpha"); + MTRBaseClusterOnOff * cluster = [[MTRBaseClusterOnOff alloc] initWithDevice:device endpoint:1 queue:mCallbackQueue]; + VerifyOrReturnError(cluster != nil, CHIP_ERROR_INCORRECT_STATE); + + [cluster readAttributeOnOffWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable err) { + NSLog(@"Check on/off attribute value is true after on command Error: %@", err); + + VerifyOrReturn(CheckValue("status", err ? err.code : 0, 0)); + + { + id actualValue = value; + VerifyOrReturn(CheckValue("OnOff", actualValue, 1)); + } + + NextTest(); + }]; + + return CHIP_NO_ERROR; + } + + CHIP_ERROR TestWaitOnOffTransitionTime_27() + { + chip::app::Clusters::DelayCommands::Commands::WaitForMs::Type value; + value.ms = 100UL; + return WaitForMs("alpha", value); + } + + CHIP_ERROR TestIfOnLevelIsNotDefinedCheckCurrentLevelIsRestored_28() + { + MTRBaseDevice * device = GetDevice("alpha"); + MTRBaseClusterLevelControl * cluster = [[MTRBaseClusterLevelControl alloc] initWithDevice:device + endpoint:1 + queue:mCallbackQueue]; + VerifyOrReturnError(cluster != nil, CHIP_ERROR_INCORRECT_STATE); + + [cluster readAttributeCurrentLevelWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable err) { + NSLog(@"If OnLevel is not defined, check CurrentLevel is restored Error: %@", err); + + VerifyOrReturn(CheckValue("status", err ? err.code : 0, 0)); + + { + id actualValue = value; + VerifyOrReturn(CheckValue("current level", actualValue, 127U)); + } + + NextTest(); + }]; + + return CHIP_NO_ERROR; + } + + CHIP_ERROR TestSendOffCommand_29() + { + MTRBaseDevice * device = GetDevice("alpha"); + MTRBaseClusterOnOff * cluster = [[MTRBaseClusterOnOff alloc] initWithDevice:device endpoint:1 queue:mCallbackQueue]; + VerifyOrReturnError(cluster != nil, CHIP_ERROR_INCORRECT_STATE); + + [cluster offWithCompletionHandler:^(NSError * _Nullable err) { + NSLog(@"Send Off Command Error: %@", err); + + VerifyOrReturn(CheckValue("status", err ? err.code : 0, 0)); + + NextTest(); + }]; + + return CHIP_NO_ERROR; + } + + CHIP_ERROR TestCheckOnOffAttributeValueIsFalseAfterOffCommand_30() + { + MTRBaseDevice * device = GetDevice("alpha"); + MTRBaseClusterOnOff * cluster = [[MTRBaseClusterOnOff alloc] initWithDevice:device endpoint:1 queue:mCallbackQueue]; + VerifyOrReturnError(cluster != nil, CHIP_ERROR_INCORRECT_STATE); + + [cluster readAttributeOnOffWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable err) { + NSLog(@"Check on/off attribute value is false after off command Error: %@", err); + + VerifyOrReturn(CheckValue("status", err ? err.code : 0, 0)); + + { + id actualValue = value; + VerifyOrReturn(CheckValue("OnOff", actualValue, 0)); + } + + NextTest(); + }]; + + return CHIP_NO_ERROR; + } + + CHIP_ERROR TestWaitOnOffTransitionTime_31() + { + chip::app::Clusters::DelayCommands::Commands::WaitForMs::Type value; + value.ms = 0UL; + return WaitForMs("alpha", value); + } + + CHIP_ERROR TestIfOnLevelIsNotDefinedCheckCurrentLevelIsRestored_32() + { + MTRBaseDevice * device = GetDevice("alpha"); + MTRBaseClusterLevelControl * cluster = [[MTRBaseClusterLevelControl alloc] initWithDevice:device + endpoint:1 + queue:mCallbackQueue]; + VerifyOrReturnError(cluster != nil, CHIP_ERROR_INCORRECT_STATE); + + [cluster readAttributeCurrentLevelWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable err) { + NSLog(@"If OnLevel is not defined, check CurrentLevel is restored Error: %@", err); + + VerifyOrReturn(CheckValue("status", err ? err.code : 0, 0)); + + { + id actualValue = value; + VerifyOrReturn(CheckValue("current level", actualValue, 127U)); + } + + NextTest(); + }]; + + return CHIP_NO_ERROR; + } +}; + class TestMultiAdmin : public TestCommandBridge { public: // NOLINTBEGIN(clang-analyzer-nullability.NullPassedToNonnull): Test constructor nullability not enforced @@ -111765,6 +112650,7 @@ void registerCommandsTests(Commands & commands) make_unique(), make_unique(), make_unique(), + make_unique(), make_unique(), make_unique(), make_unique(),