diff --git a/examples/common/pigweed/rpc_services/Attributes.h b/examples/common/pigweed/rpc_services/Attributes.h index 99e348e3a205ba..261831ba9b6223 100644 --- a/examples/common/pigweed/rpc_services/Attributes.h +++ b/examples/common/pigweed/rpc_services/Attributes.h @@ -221,7 +221,7 @@ class Attributes : public pw_rpc::nanopb::Attributes::Service request.operationFlags.Set(app::DataModel::OperationFlags::kInternal); request.subjectDescriptor = &subjectDescriptor; - std::optional info = provider->GetClusterInfo(path); + std::optional info = provider->GetServerClusterInfo(path); if (!info.has_value()) { return ::pw::Status::NotFound(); diff --git a/examples/laundry-washer-app/nxp/common/main/AppTask.cpp b/examples/laundry-washer-app/nxp/common/main/AppTask.cpp index 5d82dcf92ef7b3..b9cb8716dbe776 100644 --- a/examples/laundry-washer-app/nxp/common/main/AppTask.cpp +++ b/examples/laundry-washer-app/nxp/common/main/AppTask.cpp @@ -22,6 +22,7 @@ #include "CHIPDeviceManager.h" #include "ICDUtil.h" #include +#include #include #include "static-supported-temperature-levels.h" @@ -85,8 +86,15 @@ static CHIP_ERROR cliOpState(int argc, char * argv[]) if (map_cmd_opstate.find(argv[0]) != map_cmd_opstate.end()) { - OperationalState::GetOperationalStateInstance()->SetOperationalState(map_cmd_opstate.at(argv[0])); - ChipLogDetail(Shell, "OpSState : Set to %s state", argv[0]); + auto error = OperationalState::GetOperationalStateInstance()->SetOperationalState(map_cmd_opstate.at(argv[0])); + ChipLogDetail(Shell, "OpSState : Set to %s state & CountdownTime", argv[0]); + if ((error == CHIP_NO_ERROR) && + (map_cmd_opstate.at(argv[0]) == to_underlying(chip::app::Clusters::OperationalState::OperationalStateEnum::kRunning))) + { + chip::app::Clusters::OperationalState::GenericOperationalError err( + to_underlying(chip::app::Clusters::OperationalState::ErrorStateEnum::kNoError)); + OperationalState::GetOperationalStateDelegate()->HandleStartStateCallback(err); + } if (!strcmp(argv[0], "error") && argc == 2) { OperationalState::Structs::ErrorStateStruct::Type err; diff --git a/examples/laundry-washer-app/nxp/common/main/include/operational-state-delegate-impl.h b/examples/laundry-washer-app/nxp/common/main/include/operational-state-delegate-impl.h deleted file mode 100644 index 79f2695eb0a628..00000000000000 --- a/examples/laundry-washer-app/nxp/common/main/include/operational-state-delegate-impl.h +++ /dev/null @@ -1,120 +0,0 @@ -/* - * - * Copyright (c) 2023 Project CHIP Authors - * All rights reserved. - * - * 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. - */ - -#pragma once - -#include -#include -#include - -namespace chip { -namespace app { -namespace Clusters { - -namespace OperationalState { - -// This is an application level delegate to handle operational state commands according to the specific business logic. -class GenericOperationalStateDelegateImpl : public Delegate -{ -public: - /** - * Get the countdown time. This attribute is not used in this application. - * @return The current countdown time. - */ - app::DataModel::Nullable GetCountdownTime() override { return {}; }; - - /** - * Fills in the provided GenericOperationalState with the state at index `index` if there is one, - * or returns CHIP_ERROR_NOT_FOUND if the index is out of range for the list of states. - * Note: This is used by the SDK to populate the operational state list attribute. If the contents of this list changes, - * the device SHALL call the Instance's ReportOperationalStateListChange method to report that this attribute has changed. - * @param index The index of the state, with 0 representing the first state. - * @param operationalState The GenericOperationalState is filled. - */ - CHIP_ERROR GetOperationalStateAtIndex(size_t index, GenericOperationalState & operationalState) override; - - /** - * Fills in the provided MutableCharSpan with the phase at index `index` if there is one, - * or returns CHIP_ERROR_NOT_FOUND if the index is out of range for the list of phases. - * - * If CHIP_ERROR_NOT_FOUND is returned for index 0, that indicates that the PhaseList attribute is null - * (there are no phases defined at all). - * - * Note: This is used by the SDK to populate the phase list attribute. If the contents of this list changes, the - * device SHALL call the Instance's ReportPhaseListChange method to report that this attribute has changed. - * @param index The index of the phase, with 0 representing the first phase. - * @param operationalPhase The MutableCharSpan is filled. - */ - CHIP_ERROR GetOperationalPhaseAtIndex(size_t index, MutableCharSpan & operationalPhase) override; - - // command callback - /** - * Handle Command Callback in application: Pause - * @param[out] get operational error after callback. - */ - void HandlePauseStateCallback(GenericOperationalError & err) override; - - /** - * Handle Command Callback in application: Resume - * @param[out] get operational error after callback. - */ - void HandleResumeStateCallback(GenericOperationalError & err) override; - - /** - * Handle Command Callback in application: Start - * @param[out] get operational error after callback. - */ - void HandleStartStateCallback(GenericOperationalError & err) override; - - /** - * Handle Command Callback in application: Stop - * @param[out] get operational error after callback. - */ - void HandleStopStateCallback(GenericOperationalError & err) override; - -protected: - Span mOperationalStateList; - Span mOperationalPhaseList; -}; - -// This is an application level delegate to handle operational state commands according to the specific business logic. -class OperationalStateDelegate : public GenericOperationalStateDelegateImpl -{ -private: - const GenericOperationalState opStateList[4] = { - GenericOperationalState(to_underlying(OperationalStateEnum::kStopped)), - GenericOperationalState(to_underlying(OperationalStateEnum::kRunning)), - GenericOperationalState(to_underlying(OperationalStateEnum::kPaused)), - GenericOperationalState(to_underlying(OperationalStateEnum::kError)), - }; - -public: - OperationalStateDelegate() - { - GenericOperationalStateDelegateImpl::mOperationalStateList = Span(opStateList); - } -}; - -Instance * GetOperationalStateInstance(); - -void Shutdown(); - -} // namespace OperationalState -} // namespace Clusters -} // namespace app -} // namespace chip diff --git a/examples/laundry-washer-app/nxp/common/main/operational-state-delegate-impl.cpp b/examples/laundry-washer-app/nxp/common/main/operational-state-delegate-impl.cpp deleted file mode 100644 index 961fc868ed12b5..00000000000000 --- a/examples/laundry-washer-app/nxp/common/main/operational-state-delegate-impl.cpp +++ /dev/null @@ -1,142 +0,0 @@ -/* - * - * Copyright (c) 2023 Project CHIP Authors - * All rights reserved. - * - * 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. - */ -#include - -using namespace chip; -using namespace chip::app; -using namespace chip::app::Clusters; -using namespace chip::app::Clusters::OperationalState; - -CHIP_ERROR GenericOperationalStateDelegateImpl::GetOperationalStateAtIndex(size_t index, GenericOperationalState & operationalState) -{ - if (index >= mOperationalStateList.size()) - { - return CHIP_ERROR_NOT_FOUND; - } - operationalState = mOperationalStateList[index]; - return CHIP_NO_ERROR; -} - -CHIP_ERROR GenericOperationalStateDelegateImpl::GetOperationalPhaseAtIndex(size_t index, MutableCharSpan & operationalPhase) -{ - if (index >= mOperationalPhaseList.size()) - { - return CHIP_ERROR_NOT_FOUND; - } - return CopyCharSpanToMutableCharSpan(mOperationalPhaseList[index], operationalPhase); -} - -void GenericOperationalStateDelegateImpl::HandlePauseStateCallback(GenericOperationalError & err) -{ - // placeholder implementation - auto error = GetInstance()->SetOperationalState(to_underlying(OperationalState::OperationalStateEnum::kPaused)); - if (error == CHIP_NO_ERROR) - { - err.Set(to_underlying(ErrorStateEnum::kNoError)); - } - else - { - err.Set(to_underlying(ErrorStateEnum::kUnableToCompleteOperation)); - } -} - -void GenericOperationalStateDelegateImpl::HandleResumeStateCallback(GenericOperationalError & err) -{ - // placeholder implementation - auto error = GetInstance()->SetOperationalState(to_underlying(OperationalStateEnum::kRunning)); - if (error == CHIP_NO_ERROR) - { - err.Set(to_underlying(ErrorStateEnum::kNoError)); - } - else - { - err.Set(to_underlying(ErrorStateEnum::kUnableToCompleteOperation)); - } -} - -void GenericOperationalStateDelegateImpl::HandleStartStateCallback(GenericOperationalError & err) -{ - uint8_t opState = GetInstance()->GetCurrentOperationalState(); - if (opState == to_underlying(OperationalStateEnum::kError)) - { - err.Set(to_underlying(ErrorStateEnum::kUnableToStartOrResume)); - return; - } - // placeholder implementation - auto error = GetInstance()->SetOperationalState(to_underlying(OperationalStateEnum::kRunning)); - if (error == CHIP_NO_ERROR) - { - err.Set(to_underlying(ErrorStateEnum::kNoError)); - } - else - { - err.Set(to_underlying(ErrorStateEnum::kUnableToCompleteOperation)); - } -} - -void GenericOperationalStateDelegateImpl::HandleStopStateCallback(GenericOperationalError & err) -{ - // placeholder implementation - auto error = GetInstance()->SetOperationalState(to_underlying(OperationalStateEnum::kStopped)); - if (error == CHIP_NO_ERROR) - { - err.Set(to_underlying(ErrorStateEnum::kNoError)); - } - else - { - err.Set(to_underlying(ErrorStateEnum::kUnableToCompleteOperation)); - } -} - -// Init Operational State cluster - -static OperationalState::Instance * gOperationalStateInstance = nullptr; -static OperationalStateDelegate * gOperationalStateDelegate = nullptr; - -OperationalState::Instance * OperationalState::GetOperationalStateInstance() -{ - return gOperationalStateInstance; -} - -void OperationalState::Shutdown() -{ - if (gOperationalStateInstance != nullptr) - { - delete gOperationalStateInstance; - gOperationalStateInstance = nullptr; - } - if (gOperationalStateDelegate != nullptr) - { - delete gOperationalStateDelegate; - gOperationalStateDelegate = nullptr; - } -} - -void emberAfOperationalStateClusterInitCallback(chip::EndpointId endpointId) -{ - VerifyOrDie(endpointId == 1); // this cluster is only enabled for endpoint 1. - VerifyOrDie(gOperationalStateInstance == nullptr && gOperationalStateDelegate == nullptr); - - gOperationalStateDelegate = new OperationalStateDelegate; - EndpointId operationalStateEndpoint = 0x01; - gOperationalStateInstance = new OperationalState::Instance(gOperationalStateDelegate, operationalStateEndpoint); - - gOperationalStateInstance->SetOperationalState(to_underlying(OperationalState::OperationalStateEnum::kStopped)); - - gOperationalStateInstance->Init(); -} diff --git a/examples/laundry-washer-app/nxp/rt/rt1060/BUILD.gn b/examples/laundry-washer-app/nxp/rt/rt1060/BUILD.gn index ee1e896987ae9b..4e417419464ee8 100644 --- a/examples/laundry-washer-app/nxp/rt/rt1060/BUILD.gn +++ b/examples/laundry-washer-app/nxp/rt/rt1060/BUILD.gn @@ -44,6 +44,8 @@ declare_args() { # Setup discriminator as argument setup_discriminator = 3840 + + chip_with_diag_logs_demo = true } example_platform_dir = @@ -116,6 +118,13 @@ rt_executable("laundry-washer") { defines += [ "CONFIG_NET_L2_OPENTHREAD=1" ] } + if (chip_with_diag_logs_demo) { + defines += [ + "CONFIG_DIAG_LOGS_DEMO=1", + "CHIP_DEVICE_CONFIG_MAX_DIAG_LOG_SIZE=1024", + ] + } + include_dirs = [ "../../common/main/include", "../../common/main", @@ -135,6 +144,17 @@ rt_executable("laundry-washer") { "../../common/main/main.cpp", ] + if (chip_with_diag_logs_demo) { + include_dirs += [ + "${common_example_dir}/diagnostic_logs/include", + "${chip_root}", + ] + sources += [ + "${common_example_dir}/diagnostic_logs/source/DiagnosticLogsDemo.cpp", + "${common_example_dir}/diagnostic_logs/source/DiagnosticLogsProviderDelegateImpl.cpp", + ] + } + # App common files include_dirs += [ "${common_example_dir}/icd/include", @@ -163,11 +183,10 @@ rt_executable("laundry-washer") { sources += [ "${chip_root}/examples/all-clusters-app/all-clusters-common/src/bridged-actions-stub.cpp", "${chip_root}/examples/all-clusters-app/all-clusters-common/src/laundry-washer-controls-delegate-impl.cpp", + "${chip_root}/examples/all-clusters-app/all-clusters-common/src/operational-state-delegate-impl.cpp", "${chip_root}/examples/all-clusters-app/all-clusters-common/src/smco-stub.cpp", - "${chip_root}/examples/all-clusters-app/all-clusters-common/src/static-supported-modes-manager.cpp", "${chip_root}/examples/all-clusters-app/all-clusters-common/src/static-supported-temperature-levels.cpp", "../../common/main/laundry-washer-mode.cpp", - "../../common/main/operational-state-delegate-impl.cpp", ] if (nxp_enable_matter_cli) { diff --git a/examples/laundry-washer-app/nxp/rt/rt1170/BUILD.gn b/examples/laundry-washer-app/nxp/rt/rt1170/BUILD.gn index 90be59719a193d..0e0e71e8c2dfc1 100644 --- a/examples/laundry-washer-app/nxp/rt/rt1170/BUILD.gn +++ b/examples/laundry-washer-app/nxp/rt/rt1170/BUILD.gn @@ -41,6 +41,8 @@ declare_args() { # Setup discriminator as argument setup_discriminator = 3840 + + chip_with_diag_logs_demo = true } example_platform_dir = @@ -106,6 +108,13 @@ rt_executable("laundry-washer-app") { defines += [ "CONFIG_NET_L2_OPENTHREAD=1" ] } + if (chip_with_diag_logs_demo) { + defines += [ + "CONFIG_DIAG_LOGS_DEMO=1", + "CHIP_DEVICE_CONFIG_MAX_DIAG_LOG_SIZE=1024", + ] + } + include_dirs = [ "../../common/main/include", "../../common/main", @@ -125,6 +134,17 @@ rt_executable("laundry-washer-app") { "../../common/main/main.cpp", ] + if (chip_with_diag_logs_demo) { + include_dirs += [ + "${common_example_dir}/diagnostic_logs/include", + "${chip_root}", + ] + sources += [ + "${common_example_dir}/diagnostic_logs/source/DiagnosticLogsDemo.cpp", + "${common_example_dir}/diagnostic_logs/source/DiagnosticLogsProviderDelegateImpl.cpp", + ] + } + # App common files include_dirs += [ "${common_example_dir}/icd/include", @@ -151,11 +171,10 @@ rt_executable("laundry-washer-app") { sources += [ "${chip_root}/examples/all-clusters-app/all-clusters-common/src/bridged-actions-stub.cpp", "${chip_root}/examples/all-clusters-app/all-clusters-common/src/laundry-washer-controls-delegate-impl.cpp", + "${chip_root}/examples/all-clusters-app/all-clusters-common/src/operational-state-delegate-impl.cpp", "${chip_root}/examples/all-clusters-app/all-clusters-common/src/smco-stub.cpp", - "${chip_root}/examples/all-clusters-app/all-clusters-common/src/static-supported-modes-manager.cpp", "${chip_root}/examples/all-clusters-app/all-clusters-common/src/static-supported-temperature-levels.cpp", "../../common/main/laundry-washer-mode.cpp", - "../../common/main/operational-state-delegate-impl.cpp", ] if (nxp_enable_matter_cli) { diff --git a/examples/laundry-washer-app/nxp/rt/rw61x/BUILD.gn b/examples/laundry-washer-app/nxp/rt/rw61x/BUILD.gn index 063cf49b81a2b5..1ef89a3852c2d9 100644 --- a/examples/laundry-washer-app/nxp/rt/rw61x/BUILD.gn +++ b/examples/laundry-washer-app/nxp/rt/rw61x/BUILD.gn @@ -1,5 +1,5 @@ # Copyright (c) 2021 Project CHIP Authors -# Copyright 2023 NXP +# Copyright 2023-2024 NXP # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -42,6 +42,8 @@ declare_args() { # Setup discriminator as argument setup_discriminator = 3840 + + chip_with_diag_logs_demo = true } example_platform_dir = @@ -114,6 +116,13 @@ rt_executable("laundry-washer") { defines += [ "CONFIG_NET_L2_OPENTHREAD=1" ] } + if (chip_with_diag_logs_demo) { + defines += [ + "CONFIG_DIAG_LOGS_DEMO=1", + "CHIP_DEVICE_CONFIG_MAX_DIAG_LOG_SIZE=1024", + ] + } + include_dirs = [ "../../common/main/include", "../../common/main", @@ -133,6 +142,17 @@ rt_executable("laundry-washer") { "../../common/main/main.cpp", ] + if (chip_with_diag_logs_demo) { + include_dirs += [ + "${common_example_dir}/diagnostic_logs/include", + "${chip_root}", + ] + sources += [ + "${common_example_dir}/diagnostic_logs/source/DiagnosticLogsDemo.cpp", + "${common_example_dir}/diagnostic_logs/source/DiagnosticLogsProviderDelegateImpl.cpp", + ] + } + if (nxp_enable_secure_whole_factory_data || nxp_enable_secure_EL2GO_factory_data) { sources += [ "${chip_root}/examples/platform/nxp/${nxp_platform}/factory_data/source/AppFactoryDataExample.cpp" ] @@ -173,11 +193,10 @@ rt_executable("laundry-washer") { sources += [ "${chip_root}/examples/all-clusters-app/all-clusters-common/src/bridged-actions-stub.cpp", "${chip_root}/examples/all-clusters-app/all-clusters-common/src/laundry-washer-controls-delegate-impl.cpp", + "${chip_root}/examples/all-clusters-app/all-clusters-common/src/operational-state-delegate-impl.cpp", "${chip_root}/examples/all-clusters-app/all-clusters-common/src/smco-stub.cpp", - "${chip_root}/examples/all-clusters-app/all-clusters-common/src/static-supported-modes-manager.cpp", "${chip_root}/examples/all-clusters-app/all-clusters-common/src/static-supported-temperature-levels.cpp", "../../common/main/laundry-washer-mode.cpp", - "../../common/main/operational-state-delegate-impl.cpp", ] if (nxp_enable_matter_cli) { diff --git a/examples/laundry-washer-app/nxp/zap/laundry-washer-app.matter b/examples/laundry-washer-app/nxp/zap/laundry-washer-app.matter index 28a2f46d284903..37b7786af95b80 100644 --- a/examples/laundry-washer-app/nxp/zap/laundry-washer-app.matter +++ b/examples/laundry-washer-app/nxp/zap/laundry-washer-app.matter @@ -870,6 +870,23 @@ cluster OtaSoftwareUpdateRequestor = 42 { command AnnounceOTAProvider(AnnounceOTAProviderRequest): DefaultSuccess = 0; } +/** Nodes should be expected to be deployed to any and all regions of the world. These global regions + may have differing common languages, units of measurements, and numerical formatting + standards. As such, Nodes that visually or audibly convey information need a mechanism by which + they can be configured to use a user’s preferred language, units, etc */ +cluster LocalizationConfiguration = 43 { + revision 1; // NOTE: Default/not specifically set + + attribute access(write: manage) char_string<35> activeLocale = 0; + readonly attribute char_string supportedLocales[] = 1; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; +} + /** Nodes should be expected to be deployed to any and all regions of the world. These global regions may have differing preferences for the units in which values are conveyed in communication to a user. As such, Nodes that visually or audibly convey measurable values to the user need a @@ -896,265 +913,6 @@ cluster UnitLocalization = 45 { readonly attribute int16u clusterRevision = 65533; } -/** This cluster is used to describe the configuration and capabilities of a physical power source that provides power to the Node. */ -cluster PowerSource = 47 { - revision 1; // NOTE: Default/not specifically set - - enum BatApprovedChemistryEnum : enum16 { - kUnspecified = 0; - kAlkaline = 1; - kLithiumCarbonFluoride = 2; - kLithiumChromiumOxide = 3; - kLithiumCopperOxide = 4; - kLithiumIronDisulfide = 5; - kLithiumManganeseDioxide = 6; - kLithiumThionylChloride = 7; - kMagnesium = 8; - kMercuryOxide = 9; - kNickelOxyhydride = 10; - kSilverOxide = 11; - kZincAir = 12; - kZincCarbon = 13; - kZincChloride = 14; - kZincManganeseDioxide = 15; - kLeadAcid = 16; - kLithiumCobaltOxide = 17; - kLithiumIon = 18; - kLithiumIonPolymer = 19; - kLithiumIronPhosphate = 20; - kLithiumSulfur = 21; - kLithiumTitanate = 22; - kNickelCadmium = 23; - kNickelHydrogen = 24; - kNickelIron = 25; - kNickelMetalHydride = 26; - kNickelZinc = 27; - kSilverZinc = 28; - kSodiumIon = 29; - kSodiumSulfur = 30; - kZincBromide = 31; - kZincCerium = 32; - } - - enum BatChargeFaultEnum : enum8 { - kUnspecified = 0; - kAmbientTooHot = 1; - kAmbientTooCold = 2; - kBatteryTooHot = 3; - kBatteryTooCold = 4; - kBatteryAbsent = 5; - kBatteryOverVoltage = 6; - kBatteryUnderVoltage = 7; - kChargerOverVoltage = 8; - kChargerUnderVoltage = 9; - kSafetyTimeout = 10; - } - - enum BatChargeLevelEnum : enum8 { - kOK = 0; - kWarning = 1; - kCritical = 2; - } - - enum BatChargeStateEnum : enum8 { - kUnknown = 0; - kIsCharging = 1; - kIsAtFullCharge = 2; - kIsNotCharging = 3; - } - - enum BatCommonDesignationEnum : enum16 { - kUnspecified = 0; - kAAA = 1; - kAA = 2; - kC = 3; - kD = 4; - k4v5 = 5; - k6v0 = 6; - k9v0 = 7; - k12AA = 8; - kAAAA = 9; - kA = 10; - kB = 11; - kF = 12; - kN = 13; - kNo6 = 14; - kSubC = 15; - kA23 = 16; - kA27 = 17; - kBA5800 = 18; - kDuplex = 19; - k4SR44 = 20; - k523 = 21; - k531 = 22; - k15v0 = 23; - k22v5 = 24; - k30v0 = 25; - k45v0 = 26; - k67v5 = 27; - kJ = 28; - kCR123A = 29; - kCR2 = 30; - k2CR5 = 31; - kCRP2 = 32; - kCRV3 = 33; - kSR41 = 34; - kSR43 = 35; - kSR44 = 36; - kSR45 = 37; - kSR48 = 38; - kSR54 = 39; - kSR55 = 40; - kSR57 = 41; - kSR58 = 42; - kSR59 = 43; - kSR60 = 44; - kSR63 = 45; - kSR64 = 46; - kSR65 = 47; - kSR66 = 48; - kSR67 = 49; - kSR68 = 50; - kSR69 = 51; - kSR516 = 52; - kSR731 = 53; - kSR712 = 54; - kLR932 = 55; - kA5 = 56; - kA10 = 57; - kA13 = 58; - kA312 = 59; - kA675 = 60; - kAC41E = 61; - k10180 = 62; - k10280 = 63; - k10440 = 64; - k14250 = 65; - k14430 = 66; - k14500 = 67; - k14650 = 68; - k15270 = 69; - k16340 = 70; - kRCR123A = 71; - k17500 = 72; - k17670 = 73; - k18350 = 74; - k18500 = 75; - k18650 = 76; - k19670 = 77; - k25500 = 78; - k26650 = 79; - k32600 = 80; - } - - enum BatFaultEnum : enum8 { - kUnspecified = 0; - kOverTemp = 1; - kUnderTemp = 2; - } - - enum BatReplaceabilityEnum : enum8 { - kUnspecified = 0; - kNotReplaceable = 1; - kUserReplaceable = 2; - kFactoryReplaceable = 3; - } - - enum PowerSourceStatusEnum : enum8 { - kUnspecified = 0; - kActive = 1; - kStandby = 2; - kUnavailable = 3; - } - - enum WiredCurrentTypeEnum : enum8 { - kAC = 0; - kDC = 1; - } - - enum WiredFaultEnum : enum8 { - kUnspecified = 0; - kOverVoltage = 1; - kUnderVoltage = 2; - } - - bitmap Feature : bitmap32 { - kWired = 0x1; - kBattery = 0x2; - kRechargeable = 0x4; - kReplaceable = 0x8; - } - - struct BatChargeFaultChangeType { - BatChargeFaultEnum current[] = 0; - BatChargeFaultEnum previous[] = 1; - } - - struct BatFaultChangeType { - BatFaultEnum current[] = 0; - BatFaultEnum previous[] = 1; - } - - struct WiredFaultChangeType { - WiredFaultEnum current[] = 0; - WiredFaultEnum previous[] = 1; - } - - info event WiredFaultChange = 0 { - WiredFaultEnum current[] = 0; - WiredFaultEnum previous[] = 1; - } - - info event BatFaultChange = 1 { - BatFaultEnum current[] = 0; - BatFaultEnum previous[] = 1; - } - - info event BatChargeFaultChange = 2 { - BatChargeFaultEnum current[] = 0; - BatChargeFaultEnum previous[] = 1; - } - - readonly attribute PowerSourceStatusEnum status = 0; - readonly attribute int8u order = 1; - readonly attribute char_string<60> description = 2; - readonly attribute optional nullable int32u wiredAssessedInputVoltage = 3; - readonly attribute optional nullable int16u wiredAssessedInputFrequency = 4; - readonly attribute optional WiredCurrentTypeEnum wiredCurrentType = 5; - readonly attribute optional nullable int32u wiredAssessedCurrent = 6; - readonly attribute optional int32u wiredNominalVoltage = 7; - readonly attribute optional int32u wiredMaximumCurrent = 8; - readonly attribute optional boolean wiredPresent = 9; - readonly attribute optional WiredFaultEnum activeWiredFaults[] = 10; - readonly attribute optional nullable int32u batVoltage = 11; - readonly attribute optional nullable int8u batPercentRemaining = 12; - readonly attribute optional nullable int32u batTimeRemaining = 13; - readonly attribute optional BatChargeLevelEnum batChargeLevel = 14; - readonly attribute optional boolean batReplacementNeeded = 15; - readonly attribute optional BatReplaceabilityEnum batReplaceability = 16; - readonly attribute optional boolean batPresent = 17; - readonly attribute optional BatFaultEnum activeBatFaults[] = 18; - readonly attribute optional char_string<60> batReplacementDescription = 19; - readonly attribute optional BatCommonDesignationEnum batCommonDesignation = 20; - readonly attribute optional char_string<20> batANSIDesignation = 21; - readonly attribute optional char_string<20> batIECDesignation = 22; - readonly attribute optional BatApprovedChemistryEnum batApprovedChemistry = 23; - readonly attribute optional int32u batCapacity = 24; - readonly attribute optional int8u batQuantity = 25; - readonly attribute optional BatChargeStateEnum batChargeState = 26; - readonly attribute optional nullable int32u batTimeToFullCharge = 27; - readonly attribute optional boolean batFunctionalWhileCharging = 28; - readonly attribute optional nullable int32u batChargingCurrent = 29; - readonly attribute optional BatChargeFaultEnum activeBatChargeFaults[] = 30; - readonly attribute endpoint_no endpointList[] = 31; - readonly attribute command_id generatedCommandList[] = 65528; - readonly attribute command_id acceptedCommandList[] = 65529; - readonly attribute event_id eventList[] = 65530; - readonly attribute attrib_id attributeList[] = 65531; - readonly attribute bitmap32 featureMap = 65532; - readonly attribute int16u clusterRevision = 65533; -} - /** This cluster is used to manage global aspects of the Commissioning flow. */ cluster GeneralCommissioning = 48 { revision 1; // NOTE: Default/not specifically set @@ -1427,6 +1185,53 @@ cluster NetworkCommissioning = 49 { command access(invoke: administer) QueryIdentity(QueryIdentityRequest): QueryIdentityResponse = 9; } +/** The cluster provides commands for retrieving unstructured diagnostic logs from a Node that may be used to aid in diagnostics. */ +cluster DiagnosticLogs = 50 { + revision 1; // NOTE: Default/not specifically set + + enum IntentEnum : enum8 { + kEndUserSupport = 0; + kNetworkDiag = 1; + kCrashLogs = 2; + } + + enum StatusEnum : enum8 { + kSuccess = 0; + kExhausted = 1; + kNoLogs = 2; + kBusy = 3; + kDenied = 4; + } + + enum TransferProtocolEnum : enum8 { + kResponsePayload = 0; + kBDX = 1; + } + + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; + + request struct RetrieveLogsRequestRequest { + IntentEnum intent = 0; + TransferProtocolEnum requestedProtocol = 1; + optional char_string<32> transferFileDesignator = 2; + } + + response struct RetrieveLogsResponse = 1 { + StatusEnum status = 0; + long_octet_string logContent = 1; + optional epoch_us UTCTimeStamp = 2; + optional systime_us timeSinceBoot = 3; + } + + /** Retrieving diagnostic logs from a Node */ + command RetrieveLogsRequest(RetrieveLogsRequestRequest): RetrieveLogsResponse = 0; +} + /** The General Diagnostics Cluster, along with other diagnostics clusters, provide a means to acquire standardized diagnostics metrics that MAY be used by a Node to assist a user or Administrative Node in diagnosing potential problems. */ cluster GeneralDiagnostics = 51 { revision 2; @@ -1558,6 +1363,43 @@ cluster GeneralDiagnostics = 51 { command PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; } +/** The Software Diagnostics Cluster provides a means to acquire standardized diagnostics metrics that MAY be used by a Node to assist a user or Administrative Node in diagnosing potential problems. */ +cluster SoftwareDiagnostics = 52 { + revision 1; // NOTE: Default/not specifically set + + bitmap Feature : bitmap32 { + kWatermarks = 0x1; + } + + struct ThreadMetricsStruct { + int64u id = 0; + optional char_string<8> name = 1; + optional int32u stackFreeCurrent = 2; + optional int32u stackFreeMinimum = 3; + optional int32u stackSize = 4; + } + + info event SoftwareFault = 0 { + int64u id = 0; + optional char_string name = 1; + optional octet_string faultRecording = 2; + } + + readonly attribute optional ThreadMetricsStruct threadMetrics[] = 0; + readonly attribute optional int64u currentHeapFree = 1; + readonly attribute optional int64u currentHeapUsed = 2; + readonly attribute optional int64u currentHeapHighWatermark = 3; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; + + /** Reception of this command SHALL reset the values: The StackFreeMinimum field of the ThreadMetrics attribute, CurrentHeapHighWaterMark attribute. */ + command access(invoke: manage) ResetWatermarks(): DefaultSuccess = 0; +} + /** The Wi-Fi Network Diagnostics Cluster provides a means to acquire standardized diagnostics metrics that MAY be used by a Node to assist a user or Administrative Node in diagnosing potential problems. */ cluster WiFiNetworkDiagnostics = 54 { revision 1; // NOTE: Default/not specifically set @@ -1926,46 +1768,6 @@ cluster UserLabel = 65 { readonly attribute int16u clusterRevision = 65533; } -/** Attributes and commands for selecting a mode from a list of supported options. */ -cluster ModeSelect = 80 { - revision 2; - - bitmap Feature : bitmap32 { - kOnOff = 0x1; - } - - struct SemanticTagStruct { - vendor_id mfgCode = 0; - enum16 value = 1; - } - - struct ModeOptionStruct { - char_string<64> label = 0; - int8u mode = 1; - SemanticTagStruct semanticTags[] = 2; - } - - readonly attribute char_string<64> description = 0; - readonly attribute nullable enum16 standardNamespace = 1; - readonly attribute ModeOptionStruct supportedModes[] = 2; - readonly attribute int8u currentMode = 3; - attribute optional nullable int8u startUpMode = 4; - attribute optional nullable int8u onMode = 5; - readonly attribute command_id generatedCommandList[] = 65528; - readonly attribute command_id acceptedCommandList[] = 65529; - readonly attribute event_id eventList[] = 65530; - readonly attribute attrib_id attributeList[] = 65531; - readonly attribute bitmap32 featureMap = 65532; - readonly attribute int16u clusterRevision = 65533; - - request struct ChangeToModeRequest { - int8u newMode = 0; - } - - /** On receipt of this command, if the NewMode field matches the Mode field in an entry of the SupportedModes list, the server SHALL set the CurrentMode attribute to the NewMode value, otherwise, the server SHALL respond with an INVALID_COMMAND status response. */ - command ChangeToMode(ChangeToModeRequest): DefaultSuccess = 0; -} - /** Attributes and commands for selecting a mode from a list of supported options. */ cluster LaundryWasherMode = 81 { revision 2; @@ -2154,7 +1956,8 @@ cluster OperationalState = 96 { } endpoint 0 { - device type ma_rootdevice = 22, version 1; + device type ma_rootdevice = 22, version 0; + device type ma_otarequestor = 18, version 1; binding cluster OtaSoftwareUpdateProvider; @@ -2163,6 +1966,9 @@ endpoint 0 { callback attribute serverList; callback attribute clientList; callback attribute partsList; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; callback attribute featureMap; callback attribute clusterRevision; } @@ -2171,10 +1977,11 @@ endpoint 0 { emits event AccessControlEntryChanged; emits event AccessControlExtensionChanged; callback attribute acl; - callback attribute extension; callback attribute subjectsPerAccessControlEntry; callback attribute targetsPerAccessControlEntry; callback attribute accessControlEntriesPerFabric; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; callback attribute attributeList; ram attribute featureMap default = 0; callback attribute clusterRevision; @@ -2182,28 +1989,19 @@ endpoint 0 { server cluster BasicInformation { emits event StartUp; - emits event ShutDown; - emits event Leave; callback attribute dataModelRevision; callback attribute vendorName; callback attribute vendorID; callback attribute productName; callback attribute productID; - persist attribute nodeLabel; + ram attribute nodeLabel; callback attribute location; callback attribute hardwareVersion; callback attribute hardwareVersionString; callback attribute softwareVersion; callback attribute softwareVersionString; - callback attribute manufacturingDate; - callback attribute partNumber; - callback attribute productURL; - callback attribute productLabel; - callback attribute serialNumber; - persist attribute localConfigDisabled default = 0; callback attribute uniqueID; callback attribute capabilityMinima; - callback attribute productAppearance; callback attribute specificationVersion; callback attribute maxPathsPerInvoke; callback attribute generatedCommandList; @@ -2230,7 +2028,9 @@ endpoint 0 { handle command AnnounceOTAProvider; } - server cluster UnitLocalization { + server cluster LocalizationConfiguration { + ram attribute activeLocale; + callback attribute supportedLocales; callback attribute generatedCommandList; callback attribute acceptedCommandList; callback attribute attributeList; @@ -2238,14 +2038,26 @@ endpoint 0 { ram attribute clusterRevision default = 1; } + server cluster UnitLocalization { + ram attribute temperatureUnit; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + ram attribute featureMap default = 1; + ram attribute clusterRevision default = 1; + } + server cluster GeneralCommissioning { ram attribute breadcrumb default = 0x0000000000000000; callback attribute basicCommissioningInfo; callback attribute regulatoryConfig; callback attribute locationCapability; callback attribute supportsConcurrentConnection; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; ram attribute featureMap default = 0; - ram attribute clusterRevision default = 1; + ram attribute clusterRevision default = 2; handle command ArmFailSafe; handle command ArmFailSafeResponse; @@ -2264,11 +2076,12 @@ endpoint 0 { ram attribute lastNetworkingStatus; ram attribute lastNetworkID; ram attribute lastConnectErrorValue; + callback attribute supportedWiFiBands; callback attribute generatedCommandList; callback attribute acceptedCommandList; callback attribute attributeList; ram attribute featureMap default = 2; - ram attribute clusterRevision default = 1; + ram attribute clusterRevision default = 3; handle command ScanNetworks; handle command ScanNetworksResponse; @@ -2281,6 +2094,17 @@ endpoint 0 { handle command ReorderNetwork; } + server cluster DiagnosticLogs { + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + ram attribute featureMap default = 0; + ram attribute clusterRevision default = 1; + + handle command RetrieveLogsRequest; + handle command RetrieveLogsResponse; + } + server cluster GeneralDiagnostics { emits event BootReason; callback attribute networkInterfaces; @@ -2300,24 +2124,53 @@ endpoint 0 { handle command TimeSnapshotResponse; } + server cluster SoftwareDiagnostics { + callback attribute threadMetrics; + callback attribute currentHeapFree; + callback attribute currentHeapUsed; + callback attribute currentHeapHighWatermark; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + callback attribute featureMap; + ram attribute clusterRevision default = 1; + + handle command ResetWatermarks; + } + server cluster WiFiNetworkDiagnostics { + emits event Disconnection; + emits event AssociationFailure; + emits event ConnectionStatus; callback attribute bssid; callback attribute securityType; callback attribute wiFiVersion; callback attribute channelNumber; callback attribute rssi; + callback attribute beaconLostCount; + callback attribute beaconRxCount; + callback attribute packetMulticastRxCount; + callback attribute packetMulticastTxCount; + callback attribute packetUnicastRxCount; + callback attribute packetUnicastTxCount; callback attribute currentMaxRate; + callback attribute overrunCount; callback attribute generatedCommandList; callback attribute acceptedCommandList; callback attribute attributeList; - ram attribute featureMap default = 0; + ram attribute featureMap default = 3; ram attribute clusterRevision default = 1; + + handle command ResetCounts; } server cluster AdministratorCommissioning { callback attribute windowStatus; callback attribute adminFabricIndex; callback attribute adminVendorId; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; ram attribute featureMap default = 0; ram attribute clusterRevision default = 1; @@ -2332,6 +2185,9 @@ endpoint 0 { callback attribute commissionedFabrics; callback attribute trustedRootCertificates; callback attribute currentFabricIndex; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; ram attribute featureMap default = 0; ram attribute clusterRevision default = 1; @@ -2354,6 +2210,9 @@ endpoint 0 { callback attribute groupTable; callback attribute maxGroupsPerFabric; callback attribute maxGroupKeysPerFabric; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; callback attribute featureMap; callback attribute clusterRevision; @@ -2411,8 +2270,8 @@ endpoint 1 { callback attribute generatedCommandList; callback attribute acceptedCommandList; callback attribute attributeList; - ram attribute featureMap default = 1; - ram attribute clusterRevision default = 5; + ram attribute featureMap default = 2; + ram attribute clusterRevision default = 6; handle command Off; handle command On; @@ -2443,19 +2302,6 @@ endpoint 1 { ram attribute clusterRevision default = 1; } - server cluster PowerSource { - ram attribute status; - ram attribute order; - ram attribute description; - ram attribute wiredCurrentType; - callback attribute endpointList; - callback attribute generatedCommandList; - callback attribute acceptedCommandList; - callback attribute attributeList; - ram attribute featureMap default = 1; - ram attribute clusterRevision default = 2; - } - server cluster FixedLabel { callback attribute labelList; callback attribute generatedCommandList; @@ -2474,22 +2320,6 @@ endpoint 1 { ram attribute clusterRevision default = 1; } - server cluster ModeSelect { - ram attribute description; - ram attribute standardNamespace; - callback attribute supportedModes; - ram attribute currentMode; - ram attribute startUpMode; - ram attribute onMode; - callback attribute generatedCommandList; - callback attribute acceptedCommandList; - callback attribute attributeList; - ram attribute featureMap default = 0; - ram attribute clusterRevision default = 1; - - handle command ChangeToMode; - } - server cluster LaundryWasherMode { callback attribute supportedModes; callback attribute currentMode; @@ -2499,7 +2329,7 @@ endpoint 1 { callback attribute acceptedCommandList; callback attribute attributeList; callback attribute featureMap; - ram attribute clusterRevision default = 1; + ram attribute clusterRevision default = 2; handle command ChangeToMode; handle command ChangeToModeResponse; @@ -2542,7 +2372,7 @@ endpoint 1 { callback attribute acceptedCommandList; callback attribute attributeList; ram attribute featureMap default = 0; - ram attribute clusterRevision default = 1; + ram attribute clusterRevision default = 2; handle command Pause; handle command Stop; diff --git a/examples/laundry-washer-app/nxp/zap/laundry-washer-app.zap b/examples/laundry-washer-app/nxp/zap/laundry-washer-app.zap index 8af4eaa8976040..9a8d968d15c421 100644 --- a/examples/laundry-washer-app/nxp/zap/laundry-washer-app.zap +++ b/examples/laundry-washer-app/nxp/zap/laundry-washer-app.zap @@ -1,6 +1,6 @@ { "fileFormat": 2, - "featureLevel": 103, + "featureLevel": 104, "creator": "zap", "keyValuePairs": [ { @@ -38,27 +38,38 @@ "id": 1, "name": "MA-rootdevice", "deviceTypeRef": { - "code": 22, + "code": 18, "profileId": 259, - "label": "MA-rootdevice", - "name": "MA-rootdevice" + "label": "MA-otarequestor", + "name": "MA-otarequestor", + "deviceTypeOrder": 0 }, "deviceTypes": [ + { + "code": 18, + "profileId": 259, + "label": "MA-otarequestor", + "name": "MA-otarequestor", + "deviceTypeOrder": 0 + }, { "code": 22, "profileId": 259, "label": "MA-rootdevice", - "name": "MA-rootdevice" + "name": "MA-rootdevice", + "deviceTypeOrder": 1 } ], "deviceVersions": [ - 1 + 1, + 0 ], "deviceIdentifiers": [ + 18, 22 ], - "deviceTypeName": "MA-rootdevice", - "deviceTypeCode": 22, + "deviceTypeName": "MA-otarequestor", + "deviceTypeCode": 18, "deviceTypeProfileId": 259, "clusters": [ { @@ -133,6 +144,54 @@ "maxInterval": 65344, "reportableChange": 0 }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, { "name": "FeatureMap", "code": 65532, @@ -192,11 +251,11 @@ "reportableChange": 0 }, { - "name": "Extension", - "code": 1, + "name": "SubjectsPerAccessControlEntry", + "code": 2, "mfgCode": null, "side": "server", - "type": "array", + "type": "int16u", "included": 1, "storageOption": "External", "singleton": 0, @@ -208,8 +267,8 @@ "reportableChange": 0 }, { - "name": "SubjectsPerAccessControlEntry", - "code": 2, + "name": "TargetsPerAccessControlEntry", + "code": 3, "mfgCode": null, "side": "server", "type": "int16u", @@ -224,8 +283,8 @@ "reportableChange": 0 }, { - "name": "TargetsPerAccessControlEntry", - "code": 3, + "name": "AccessControlEntriesPerFabric", + "code": 4, "mfgCode": null, "side": "server", "type": "int16u", @@ -240,11 +299,27 @@ "reportableChange": 0 }, { - "name": "AccessControlEntriesPerFabric", - "code": 4, + "name": "GeneratedCommandList", + "code": 65528, "mfgCode": null, "side": "server", - "type": "int16u", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", "included": 1, "storageOption": "External", "singleton": 0, @@ -416,7 +491,7 @@ "side": "server", "type": "char_string", "included": 1, - "storageOption": "NVM", + "storageOption": "RAM", "singleton": 1, "bounded": 0, "defaultValue": "", @@ -501,104 +576,8 @@ "bounded": 0, "defaultValue": null, "reportable": 1, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 - }, - { - "name": "ManufacturingDate", - "code": 11, - "mfgCode": null, - "side": "server", - "type": "char_string", - "included": 1, - "storageOption": "External", - "singleton": 1, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 - }, - { - "name": "PartNumber", - "code": 12, - "mfgCode": null, - "side": "server", - "type": "char_string", - "included": 1, - "storageOption": "External", - "singleton": 1, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 - }, - { - "name": "ProductURL", - "code": 13, - "mfgCode": null, - "side": "server", - "type": "long_char_string", - "included": 1, - "storageOption": "External", - "singleton": 1, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 - }, - { - "name": "ProductLabel", - "code": 14, - "mfgCode": null, - "side": "server", - "type": "char_string", - "included": 1, - "storageOption": "External", - "singleton": 1, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 - }, - { - "name": "SerialNumber", - "code": 15, - "mfgCode": null, - "side": "server", - "type": "char_string", - "included": 1, - "storageOption": "External", - "singleton": 1, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 - }, - { - "name": "LocalConfigDisabled", - "code": 16, - "mfgCode": null, - "side": "server", - "type": "boolean", - "included": 1, - "storageOption": "NVM", - "singleton": 1, - "bounded": 0, - "defaultValue": "0", - "reportable": 1, - "minInterval": 0, - "maxInterval": 65344, + "minInterval": 1, + "maxInterval": 65534, "reportableChange": 0 }, { @@ -625,22 +604,6 @@ "type": "CapabilityMinimaStruct", "included": 1, "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "ProductAppearance", - "code": 20, - "mfgCode": null, - "side": "server", - "type": "ProductAppearanceStruct", - "included": 1, - "storageOption": "External", "singleton": 1, "bounded": 0, "defaultValue": null, @@ -713,22 +676,6 @@ "maxInterval": 65534, "reportableChange": 0 }, - { - "name": "EventList", - "code": 65530, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 1, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, { "name": "AttributeList", "code": 65531, @@ -785,20 +732,6 @@ "mfgCode": null, "side": "server", "included": 1 - }, - { - "name": "ShutDown", - "code": 1, - "mfgCode": null, - "side": "server", - "included": 1 - }, - { - "name": "Leave", - "code": 2, - "mfgCode": null, - "side": "server", - "included": 1 } ] }, @@ -966,22 +899,6 @@ "maxInterval": 65534, "reportableChange": 0 }, - { - "name": "EventList", - "code": 65530, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, { "name": "AttributeList", "code": 65531, @@ -1056,32 +973,32 @@ ] }, { - "name": "Unit Localization", - "code": 45, + "name": "Localization Configuration", + "code": 43, "mfgCode": null, - "define": "UNIT_LOCALIZATION_CLUSTER", + "define": "LOCALIZATION_CONFIGURATION_CLUSTER", "side": "server", "enabled": 1, "attributes": [ { - "name": "GeneratedCommandList", - "code": 65528, + "name": "ActiveLocale", + "code": 0, "mfgCode": null, "side": "server", - "type": "array", + "type": "char_string", "included": 1, - "storageOption": "External", + "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": null, + "defaultValue": "", "reportable": 1, "minInterval": 1, "maxInterval": 65534, "reportableChange": 0 }, { - "name": "AcceptedCommandList", - "code": 65529, + "name": "SupportedLocales", + "code": 1, "mfgCode": null, "side": "server", "type": "array", @@ -1096,8 +1013,8 @@ "reportableChange": 0 }, { - "name": "EventList", - "code": 65530, + "name": "GeneratedCommandList", + "code": 65528, "mfgCode": null, "side": "server", "type": "array", @@ -1112,8 +1029,24 @@ "reportableChange": 0 }, { - "name": "AttributeList", - "code": 65531, + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, "mfgCode": null, "side": "server", "type": "array", @@ -1161,6 +1094,112 @@ } ] }, + { + "name": "Unit Localization", + "code": 45, + "mfgCode": null, + "define": "UNIT_LOCALIZATION_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "TemperatureUnit", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "TempUnitEnum", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, { "name": "General Commissioning", "code": 48, @@ -1299,6 +1338,54 @@ "maxInterval": 65534, "reportableChange": 0 }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, { "name": "FeatureMap", "code": 65532, @@ -1325,7 +1412,7 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "1", + "defaultValue": "2", "reportable": 1, "minInterval": 0, "maxInterval": 65344, @@ -1544,8 +1631,8 @@ "reportableChange": 0 }, { - "name": "GeneratedCommandList", - "code": 65528, + "name": "SupportedWiFiBands", + "code": 8, "mfgCode": null, "side": "server", "type": "array", @@ -1560,8 +1647,8 @@ "reportableChange": 0 }, { - "name": "AcceptedCommandList", - "code": 65529, + "name": "GeneratedCommandList", + "code": 65528, "mfgCode": null, "side": "server", "type": "array", @@ -1576,8 +1663,8 @@ "reportableChange": 0 }, { - "name": "EventList", - "code": 65530, + "name": "AcceptedCommandList", + "code": 65529, "mfgCode": null, "side": "server", "type": "array", @@ -1633,7 +1720,7 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "1", + "defaultValue": "3", "reportable": 1, "minInterval": 0, "maxInterval": 65344, @@ -1642,15 +1729,15 @@ ] }, { - "name": "General Diagnostics", - "code": 51, + "name": "Diagnostic Logs", + "code": 50, "mfgCode": null, - "define": "GENERAL_DIAGNOSTICS_CLUSTER", + "define": "DIAGNOSTIC_LOGS_CLUSTER", "side": "server", "enabled": 1, "commands": [ { - "name": "TestEventTrigger", + "name": "RetrieveLogsRequest", "code": 0, "mfgCode": null, "source": "client", @@ -1658,17 +1745,9 @@ "isEnabled": 1 }, { - "name": "TimeSnapshot", + "name": "RetrieveLogsResponse", "code": 1, "mfgCode": null, - "source": "client", - "isIncoming": 1, - "isEnabled": 1 - }, - { - "name": "TimeSnapshotResponse", - "code": 2, - "mfgCode": null, "source": "server", "isIncoming": 0, "isEnabled": 1 @@ -1676,8 +1755,8 @@ ], "attributes": [ { - "name": "NetworkInterfaces", - "code": 0, + "name": "GeneratedCommandList", + "code": 65528, "mfgCode": null, "side": "server", "type": "array", @@ -1687,32 +1766,16 @@ "bounded": 0, "defaultValue": null, "reportable": 1, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 - }, - { - "name": "RebootCount", - "code": 1, - "mfgCode": null, - "side": "server", - "type": "int16u", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 0, - "maxInterval": 65344, + "minInterval": 1, + "maxInterval": 65534, "reportableChange": 0 }, { - "name": "UpTime", - "code": 2, + "name": "AcceptedCommandList", + "code": 65529, "mfgCode": null, "side": "server", - "type": "int64u", + "type": "array", "included": 1, "storageOption": "External", "singleton": 0, @@ -1724,11 +1787,11 @@ "reportableChange": 0 }, { - "name": "TotalOperationalHours", - "code": 3, + "name": "AttributeList", + "code": 65531, "mfgCode": null, "side": "server", - "type": "int32u", + "type": "array", "included": 1, "storageOption": "External", "singleton": 0, @@ -1740,40 +1803,76 @@ "reportableChange": 0 }, { - "name": "BootReason", - "code": 4, + "name": "FeatureMap", + "code": 65532, "mfgCode": null, "side": "server", - "type": "BootReasonEnum", + "type": "bitmap32", "included": 1, - "storageOption": "External", + "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": null, + "defaultValue": "0", "reportable": 1, "minInterval": 1, "maxInterval": 65534, "reportableChange": 0 }, { - "name": "TestEventTriggersEnabled", - "code": 8, + "name": "ClusterRevision", + "code": 65533, "mfgCode": null, "side": "server", - "type": "boolean", + "type": "int16u", "included": 1, - "storageOption": "External", + "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "false", + "defaultValue": "1", "reportable": 1, "minInterval": 1, "maxInterval": 65534, "reportableChange": 0 - }, - { - "name": "GeneratedCommandList", - "code": 65528, + } + ] + }, + { + "name": "General Diagnostics", + "code": 51, + "mfgCode": null, + "define": "GENERAL_DIAGNOSTICS_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [ + { + "name": "TestEventTrigger", + "code": 0, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "TimeSnapshot", + "code": 1, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "TimeSnapshotResponse", + "code": 2, + "mfgCode": null, + "source": "server", + "isIncoming": 0, + "isEnabled": 1 + } + ], + "attributes": [ + { + "name": "NetworkInterfaces", + "code": 0, "mfgCode": null, "side": "server", "type": "array", @@ -1783,13 +1882,93 @@ "bounded": 0, "defaultValue": null, "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RebootCount", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "UpTime", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "int64u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, "minInterval": 1, "maxInterval": 65534, "reportableChange": 0 }, { - "name": "AcceptedCommandList", - "code": 65529, + "name": "TotalOperationalHours", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "BootReason", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "BootReasonEnum", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "TestEventTriggersEnabled", + "code": 8, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "false", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "GeneratedCommandList", + "code": 65528, "mfgCode": null, "side": "server", "type": "array", @@ -1804,8 +1983,8 @@ "reportableChange": 0 }, { - "name": "EventList", - "code": 65530, + "name": "AcceptedCommandList", + "code": 65529, "mfgCode": null, "side": "server", "type": "array", @@ -1879,98 +2058,76 @@ ] }, { - "name": "Wi-Fi Network Diagnostics", - "code": 54, + "name": "Software Diagnostics", + "code": 52, "mfgCode": null, - "define": "WIFI_NETWORK_DIAGNOSTICS_CLUSTER", + "define": "SOFTWARE_DIAGNOSTICS_CLUSTER", "side": "server", "enabled": 1, + "commands": [ + { + "name": "ResetWatermarks", + "code": 0, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + } + ], "attributes": [ { - "name": "BSSID", + "name": "ThreadMetrics", "code": 0, "mfgCode": null, "side": "server", - "type": "octet_string", + "type": "array", "included": 1, "storageOption": "External", "singleton": 0, "bounded": 0, "defaultValue": null, "reportable": 1, - "minInterval": 0, - "maxInterval": 65344, + "minInterval": 1, + "maxInterval": 65534, "reportableChange": 0 }, { - "name": "SecurityType", + "name": "CurrentHeapFree", "code": 1, "mfgCode": null, "side": "server", - "type": "SecurityTypeEnum", + "type": "int64u", "included": 1, "storageOption": "External", "singleton": 0, "bounded": 0, "defaultValue": null, "reportable": 1, - "minInterval": 0, - "maxInterval": 65344, + "minInterval": 1, + "maxInterval": 65534, "reportableChange": 0 }, { - "name": "WiFiVersion", + "name": "CurrentHeapUsed", "code": 2, "mfgCode": null, "side": "server", - "type": "WiFiVersionEnum", + "type": "int64u", "included": 1, "storageOption": "External", "singleton": 0, "bounded": 0, "defaultValue": null, "reportable": 1, - "minInterval": 0, - "maxInterval": 65344, + "minInterval": 1, + "maxInterval": 65534, "reportableChange": 0 }, { - "name": "ChannelNumber", + "name": "CurrentHeapHighWatermark", "code": 3, "mfgCode": null, "side": "server", - "type": "int16u", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 - }, - { - "name": "RSSI", - "code": 4, - "mfgCode": null, - "side": "server", - "type": "int8s", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 - }, - { - "name": "CurrentMaxRate", - "code": 11, - "mfgCode": null, - "side": "server", "type": "int64u", "included": 1, "storageOption": "External", @@ -1978,8 +2135,8 @@ "bounded": 0, "defaultValue": null, "reportable": 1, - "minInterval": 0, - "maxInterval": 65344, + "minInterval": 1, + "maxInterval": 65534, "reportableChange": 0 }, { @@ -2014,22 +2171,6 @@ "maxInterval": 65534, "reportableChange": 0 }, - { - "name": "EventList", - "code": 65530, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, { "name": "AttributeList", "code": 65531, @@ -2053,10 +2194,10 @@ "side": "server", "type": "bitmap32", "included": 1, - "storageOption": "RAM", + "storageOption": "External", "singleton": 0, "bounded": 0, - "defaultValue": "0", + "defaultValue": null, "reportable": 1, "minInterval": 1, "maxInterval": 65534, @@ -2074,232 +2215,196 @@ "bounded": 0, "defaultValue": "1", "reportable": 1, - "minInterval": 0, - "maxInterval": 65344, + "minInterval": 1, + "maxInterval": 65534, "reportableChange": 0 } ] }, { - "name": "Administrator Commissioning", - "code": 60, + "name": "Wi-Fi Network Diagnostics", + "code": 54, "mfgCode": null, - "define": "ADMINISTRATOR_COMMISSIONING_CLUSTER", + "define": "WIFI_NETWORK_DIAGNOSTICS_CLUSTER", "side": "server", "enabled": 1, "commands": [ { - "name": "OpenCommissioningWindow", + "name": "ResetCounts", "code": 0, "mfgCode": null, "source": "client", "isIncoming": 1, "isEnabled": 1 - }, - { - "name": "RevokeCommissioning", - "code": 2, - "mfgCode": null, - "source": "client", - "isIncoming": 1, - "isEnabled": 1 } ], "attributes": [ { - "name": "WindowStatus", + "name": "BSSID", "code": 0, "mfgCode": null, "side": "server", - "type": "CommissioningWindowStatusEnum", + "type": "octet_string", "included": 1, "storageOption": "External", "singleton": 0, "bounded": 0, "defaultValue": null, "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, + "minInterval": 0, + "maxInterval": 65344, "reportableChange": 0 }, { - "name": "AdminFabricIndex", + "name": "SecurityType", "code": 1, "mfgCode": null, "side": "server", - "type": "fabric_idx", + "type": "SecurityTypeEnum", "included": 1, "storageOption": "External", "singleton": 0, "bounded": 0, "defaultValue": null, "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, + "minInterval": 0, + "maxInterval": 65344, "reportableChange": 0 }, { - "name": "AdminVendorId", + "name": "WiFiVersion", "code": 2, "mfgCode": null, "side": "server", - "type": "vendor_id", + "type": "WiFiVersionEnum", "included": 1, "storageOption": "External", "singleton": 0, "bounded": 0, "defaultValue": null, "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, + "minInterval": 0, + "maxInterval": 65344, "reportableChange": 0 }, { - "name": "FeatureMap", - "code": 65532, + "name": "ChannelNumber", + "code": 3, "mfgCode": null, "side": "server", - "type": "bitmap32", + "type": "int16u", "included": 1, - "storageOption": "RAM", + "storageOption": "External", "singleton": 0, "bounded": 0, - "defaultValue": "0", + "defaultValue": null, "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, + "minInterval": 0, + "maxInterval": 65344, "reportableChange": 0 }, { - "name": "ClusterRevision", - "code": 65533, + "name": "RSSI", + "code": 4, "mfgCode": null, "side": "server", - "type": "int16u", + "type": "int8s", "included": 1, - "storageOption": "RAM", + "storageOption": "External", "singleton": 0, "bounded": 0, - "defaultValue": "1", + "defaultValue": null, "reportable": 1, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 - } - ] - }, - { - "name": "Operational Credentials", - "code": 62, - "mfgCode": null, - "define": "OPERATIONAL_CREDENTIALS_CLUSTER", - "side": "server", - "enabled": 1, - "commands": [ - { - "name": "AttestationRequest", - "code": 0, - "mfgCode": null, - "source": "client", - "isIncoming": 1, - "isEnabled": 1 - }, - { - "name": "AttestationResponse", - "code": 1, - "mfgCode": null, - "source": "server", - "isIncoming": 0, - "isEnabled": 1 - }, - { - "name": "CertificateChainRequest", - "code": 2, - "mfgCode": null, - "source": "client", - "isIncoming": 1, - "isEnabled": 1 - }, - { - "name": "CertificateChainResponse", - "code": 3, - "mfgCode": null, - "source": "server", - "isIncoming": 0, - "isEnabled": 1 - }, - { - "name": "CSRRequest", - "code": 4, - "mfgCode": null, - "source": "client", - "isIncoming": 1, - "isEnabled": 1 }, { - "name": "CSRResponse", + "name": "BeaconLostCount", "code": 5, "mfgCode": null, - "source": "server", - "isIncoming": 0, - "isEnabled": 1 + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 }, { - "name": "AddNOC", + "name": "BeaconRxCount", "code": 6, "mfgCode": null, - "source": "client", - "isIncoming": 1, - "isEnabled": 1 + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 }, { - "name": "UpdateNOC", + "name": "PacketMulticastRxCount", "code": 7, "mfgCode": null, - "source": "client", - "isIncoming": 1, - "isEnabled": 1 + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 }, { - "name": "NOCResponse", + "name": "PacketMulticastTxCount", "code": 8, "mfgCode": null, - "source": "server", - "isIncoming": 0, - "isEnabled": 1 + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 }, { - "name": "UpdateFabricLabel", + "name": "PacketUnicastRxCount", "code": 9, "mfgCode": null, - "source": "client", - "isIncoming": 1, - "isEnabled": 1 + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 }, { - "name": "RemoveFabric", + "name": "PacketUnicastTxCount", "code": 10, "mfgCode": null, - "source": "client", - "isIncoming": 1, - "isEnabled": 1 - }, - { - "name": "AddTrustedRootCertificate", - "code": 11, - "mfgCode": null, - "source": "client", - "isIncoming": 1, - "isEnabled": 1 - } - ], - "attributes": [ - { - "name": "NOCs", - "code": 0, - "mfgCode": null, "side": "server", - "type": "array", + "type": "int32u", "included": 1, "storageOption": "External", "singleton": 0, @@ -2311,11 +2416,11 @@ "reportableChange": 0 }, { - "name": "Fabrics", - "code": 1, + "name": "CurrentMaxRate", + "code": 11, "mfgCode": null, "side": "server", - "type": "array", + "type": "int64u", "included": 1, "storageOption": "External", "singleton": 0, @@ -2327,40 +2432,40 @@ "reportableChange": 0 }, { - "name": "SupportedFabrics", - "code": 2, + "name": "OverrunCount", + "code": 12, "mfgCode": null, "side": "server", - "type": "int8u", + "type": "int64u", "included": 1, "storageOption": "External", "singleton": 0, "bounded": 0, "defaultValue": null, "reportable": 1, - "minInterval": 0, - "maxInterval": 65344, + "minInterval": 1, + "maxInterval": 65534, "reportableChange": 0 }, { - "name": "CommissionedFabrics", - "code": 3, + "name": "GeneratedCommandList", + "code": 65528, "mfgCode": null, "side": "server", - "type": "int8u", + "type": "array", "included": 1, "storageOption": "External", "singleton": 0, "bounded": 0, "defaultValue": null, "reportable": 1, - "minInterval": 0, - "maxInterval": 65344, + "minInterval": 1, + "maxInterval": 65534, "reportableChange": 0 }, { - "name": "TrustedRootCertificates", - "code": 4, + "name": "AcceptedCommandList", + "code": 65529, "mfgCode": null, "side": "server", "type": "array", @@ -2370,16 +2475,16 @@ "bounded": 0, "defaultValue": null, "reportable": 1, - "minInterval": 0, - "maxInterval": 65344, + "minInterval": 1, + "maxInterval": 65534, "reportableChange": 0 }, { - "name": "CurrentFabricIndex", - "code": 5, + "name": "AttributeList", + "code": 65531, "mfgCode": null, "side": "server", - "type": "int8u", + "type": "array", "included": 1, "storageOption": "External", "singleton": 0, @@ -2400,7 +2505,7 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "0", + "defaultValue": "3", "reportable": 1, "minInterval": 1, "maxInterval": 65534, @@ -2422,18 +2527,41 @@ "maxInterval": 65344, "reportableChange": 0 } + ], + "events": [ + { + "name": "Disconnection", + "code": 0, + "mfgCode": null, + "side": "server", + "included": 1 + }, + { + "name": "AssociationFailure", + "code": 1, + "mfgCode": null, + "side": "server", + "included": 1 + }, + { + "name": "ConnectionStatus", + "code": 2, + "mfgCode": null, + "side": "server", + "included": 1 + } ] }, { - "name": "Group Key Management", - "code": 63, + "name": "Administrator Commissioning", + "code": 60, "mfgCode": null, - "define": "GROUP_KEY_MANAGEMENT_CLUSTER", + "define": "ADMINISTRATOR_COMMISSIONING_CLUSTER", "side": "server", "enabled": 1, "commands": [ { - "name": "KeySetWrite", + "name": "OpenCommissioningWindow", "code": 0, "mfgCode": null, "source": "client", @@ -2441,101 +2569,21 @@ "isEnabled": 1 }, { - "name": "KeySetRead", - "code": 1, + "name": "RevokeCommissioning", + "code": 2, "mfgCode": null, "source": "client", "isIncoming": 1, "isEnabled": 1 - }, + } + ], + "attributes": [ { - "name": "KeySetReadResponse", - "code": 2, - "mfgCode": null, - "source": "server", - "isIncoming": 0, - "isEnabled": 1 - }, - { - "name": "KeySetRemove", - "code": 3, - "mfgCode": null, - "source": "client", - "isIncoming": 1, - "isEnabled": 1 - }, - { - "name": "KeySetReadAllIndices", - "code": 4, - "mfgCode": null, - "source": "client", - "isIncoming": 1, - "isEnabled": 1 - }, - { - "name": "KeySetReadAllIndicesResponse", - "code": 5, - "mfgCode": null, - "source": "server", - "isIncoming": 0, - "isEnabled": 1 - } - ], - "attributes": [ - { - "name": "GroupKeyMap", + "name": "WindowStatus", "code": 0, "mfgCode": null, "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 - }, - { - "name": "GroupTable", - "code": 1, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 - }, - { - "name": "MaxGroupsPerFabric", - "code": 2, - "mfgCode": null, - "side": "server", - "type": "int16u", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "MaxGroupKeysPerFabric", - "code": 3, - "mfgCode": null, - "side": "server", - "type": "int16u", + "type": "CommissioningWindowStatusEnum", "included": 1, "storageOption": "External", "singleton": 0, @@ -2547,11 +2595,11 @@ "reportableChange": 0 }, { - "name": "FeatureMap", - "code": 65532, + "name": "AdminFabricIndex", + "code": 1, "mfgCode": null, "side": "server", - "type": "bitmap32", + "type": "fabric_idx", "included": 1, "storageOption": "External", "singleton": 0, @@ -2563,106 +2611,17 @@ "reportableChange": 0 }, { - "name": "ClusterRevision", - "code": 65533, + "name": "AdminVendorId", + "code": 2, "mfgCode": null, "side": "server", - "type": "int16u", + "type": "vendor_id", "included": 1, "storageOption": "External", "singleton": 0, "bounded": 0, "defaultValue": null, "reportable": 1, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 - } - ] - } - ] - }, - { - "id": 2, - "name": "Anonymous Endpoint Type", - "deviceTypeRef": { - "code": 115, - "profileId": 259, - "label": "MA-laundry-washer", - "name": "MA-laundry-washer" - }, - "deviceTypes": [ - { - "code": 115, - "profileId": 259, - "label": "MA-laundry-washer", - "name": "MA-laundry-washer" - } - ], - "deviceVersions": [ - 1 - ], - "deviceIdentifiers": [ - 115 - ], - "deviceTypeName": "MA-laundry-washer", - "deviceTypeCode": 115, - "deviceTypeProfileId": 259, - "clusters": [ - { - "name": "Identify", - "code": 3, - "mfgCode": null, - "define": "IDENTIFY_CLUSTER", - "side": "server", - "enabled": 1, - "commands": [ - { - "name": "Identify", - "code": 0, - "mfgCode": null, - "source": "client", - "isIncoming": 1, - "isEnabled": 1 - }, - { - "name": "TriggerEffect", - "code": 64, - "mfgCode": null, - "source": "client", - "isIncoming": 1, - "isEnabled": 1 - } - ], - "attributes": [ - { - "name": "IdentifyTime", - "code": 0, - "mfgCode": null, - "side": "server", - "type": "int16u", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "0x0", - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "IdentifyType", - "code": 1, - "mfgCode": null, - "side": "server", - "type": "IdentifyTypeEnum", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "0x00", - "reportable": 1, "minInterval": 1, "maxInterval": 65534, "reportableChange": 0 @@ -2699,22 +2658,6 @@ "maxInterval": 65534, "reportableChange": 0 }, - { - "name": "EventList", - "code": 65530, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, { "name": "AttributeList", "code": 65531, @@ -2757,24 +2700,24 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "4", + "defaultValue": "1", "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, + "minInterval": 0, + "maxInterval": 65344, "reportableChange": 0 } ] }, { - "name": "Groups", - "code": 4, + "name": "Operational Credentials", + "code": 62, "mfgCode": null, - "define": "GROUPS_CLUSTER", + "define": "OPERATIONAL_CREDENTIALS_CLUSTER", "side": "server", "enabled": 1, "commands": [ { - "name": "AddGroup", + "name": "AttestationRequest", "code": 0, "mfgCode": null, "source": "client", @@ -2782,73 +2725,89 @@ "isEnabled": 1 }, { - "name": "AddGroupResponse", - "code": 0, + "name": "AttestationResponse", + "code": 1, "mfgCode": null, "source": "server", "isIncoming": 0, "isEnabled": 1 }, { - "name": "ViewGroup", - "code": 1, + "name": "CertificateChainRequest", + "code": 2, "mfgCode": null, "source": "client", "isIncoming": 1, "isEnabled": 1 }, { - "name": "ViewGroupResponse", - "code": 1, + "name": "CertificateChainResponse", + "code": 3, "mfgCode": null, "source": "server", "isIncoming": 0, "isEnabled": 1 }, { - "name": "GetGroupMembership", - "code": 2, + "name": "CSRRequest", + "code": 4, "mfgCode": null, "source": "client", "isIncoming": 1, "isEnabled": 1 }, { - "name": "GetGroupMembershipResponse", - "code": 2, + "name": "CSRResponse", + "code": 5, "mfgCode": null, "source": "server", "isIncoming": 0, "isEnabled": 1 }, { - "name": "RemoveGroup", - "code": 3, + "name": "AddNOC", + "code": 6, "mfgCode": null, "source": "client", "isIncoming": 1, "isEnabled": 1 }, { - "name": "RemoveGroupResponse", - "code": 3, + "name": "UpdateNOC", + "code": 7, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "NOCResponse", + "code": 8, "mfgCode": null, "source": "server", "isIncoming": 0, "isEnabled": 1 }, { - "name": "RemoveAllGroups", - "code": 4, + "name": "UpdateFabricLabel", + "code": 9, "mfgCode": null, "source": "client", "isIncoming": 1, "isEnabled": 1 }, { - "name": "AddGroupIfIdentifying", - "code": 5, - "mfgCode": null, + "name": "RemoveFabric", + "code": 10, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "AddTrustedRootCertificate", + "code": 11, + "mfgCode": null, "source": "client", "isIncoming": 1, "isEnabled": 1 @@ -2856,16 +2815,300 @@ ], "attributes": [ { - "name": "NameSupport", + "name": "NOCs", "code": 0, "mfgCode": null, "side": "server", - "type": "NameSupportBitmap", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "Fabrics", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "SupportedFabrics", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "CommissionedFabrics", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "TrustedRootCertificates", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "CurrentFabricIndex", + "code": 5, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", "included": 1, "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "", + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Group Key Management", + "code": 63, + "mfgCode": null, + "define": "GROUP_KEY_MANAGEMENT_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [ + { + "name": "KeySetWrite", + "code": 0, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "KeySetRead", + "code": 1, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "KeySetReadResponse", + "code": 2, + "mfgCode": null, + "source": "server", + "isIncoming": 0, + "isEnabled": 1 + }, + { + "name": "KeySetRemove", + "code": 3, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "KeySetReadAllIndices", + "code": 4, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "KeySetReadAllIndicesResponse", + "code": 5, + "mfgCode": null, + "source": "server", + "isIncoming": 0, + "isEnabled": 1 + } + ], + "attributes": [ + { + "name": "GroupKeyMap", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "GroupTable", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "MaxGroupsPerFabric", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MaxGroupKeysPerFabric", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, "reportable": 1, "minInterval": 1, "maxInterval": 65534, @@ -2904,8 +3147,163 @@ "reportableChange": 0 }, { - "name": "EventList", - "code": 65530, + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + } + ] + }, + { + "id": 2, + "name": "Anonymous Endpoint Type", + "deviceTypeRef": { + "code": 115, + "profileId": 259, + "label": "MA-laundry-washer", + "name": "MA-laundry-washer", + "deviceTypeOrder": 0 + }, + "deviceTypes": [ + { + "code": 115, + "profileId": 259, + "label": "MA-laundry-washer", + "name": "MA-laundry-washer", + "deviceTypeOrder": 0 + } + ], + "deviceVersions": [ + 1 + ], + "deviceIdentifiers": [ + 115 + ], + "deviceTypeName": "MA-laundry-washer", + "deviceTypeCode": 115, + "deviceTypeProfileId": 259, + "clusters": [ + { + "name": "Identify", + "code": 3, + "mfgCode": null, + "define": "IDENTIFY_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [ + { + "name": "Identify", + "code": 0, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "TriggerEffect", + "code": 64, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + } + ], + "attributes": [ + { + "name": "IdentifyTime", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "IdentifyType", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "IdentifyTypeEnum", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, "mfgCode": null, "side": "server", "type": "array", @@ -2970,15 +3368,15 @@ ] }, { - "name": "On/Off", - "code": 6, + "name": "Groups", + "code": 4, "mfgCode": null, - "define": "ON_OFF_CLUSTER", + "define": "GROUPS_CLUSTER", "side": "server", "enabled": 1, "commands": [ { - "name": "Off", + "name": "AddGroup", "code": 0, "mfgCode": null, "source": "client", @@ -2986,7 +3384,15 @@ "isEnabled": 1 }, { - "name": "On", + "name": "AddGroupResponse", + "code": 0, + "mfgCode": null, + "source": "server", + "isIncoming": 0, + "isEnabled": 1 + }, + { + "name": "ViewGroup", "code": 1, "mfgCode": null, "source": "client", @@ -2994,7 +3400,15 @@ "isEnabled": 1 }, { - "name": "Toggle", + "name": "ViewGroupResponse", + "code": 1, + "mfgCode": null, + "source": "server", + "isIncoming": 0, + "isEnabled": 1 + }, + { + "name": "GetGroupMembership", "code": 2, "mfgCode": null, "source": "client", @@ -3002,24 +3416,40 @@ "isEnabled": 1 }, { - "name": "OffWithEffect", - "code": 64, + "name": "GetGroupMembershipResponse", + "code": 2, + "mfgCode": null, + "source": "server", + "isIncoming": 0, + "isEnabled": 1 + }, + { + "name": "RemoveGroup", + "code": 3, "mfgCode": null, "source": "client", "isIncoming": 1, "isEnabled": 1 }, { - "name": "OnWithRecallGlobalScene", - "code": 65, + "name": "RemoveGroupResponse", + "code": 3, + "mfgCode": null, + "source": "server", + "isIncoming": 0, + "isEnabled": 1 + }, + { + "name": "RemoveAllGroups", + "code": 4, "mfgCode": null, "source": "client", "isIncoming": 1, "isEnabled": 1 }, { - "name": "OnWithTimedOff", - "code": 66, + "name": "AddGroupIfIdentifying", + "code": 5, "mfgCode": null, "source": "client", "isIncoming": 1, @@ -3028,80 +3458,16 @@ ], "attributes": [ { - "name": "OnOff", + "name": "NameSupport", "code": 0, "mfgCode": null, "side": "server", - "type": "boolean", - "included": 1, - "storageOption": "NVM", - "singleton": 0, - "bounded": 0, - "defaultValue": "0", - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "GlobalSceneControl", - "code": 16384, - "mfgCode": null, - "side": "server", - "type": "boolean", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "1", - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "OnTime", - "code": 16385, - "mfgCode": null, - "side": "server", - "type": "int16u", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "0", - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "OffWaitTime", - "code": 16386, - "mfgCode": null, - "side": "server", - "type": "int16u", + "type": "NameSupportBitmap", "included": 1, "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "0", - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "StartUpOnOff", - "code": 16387, - "mfgCode": null, - "side": "server", - "type": "StartUpOnOffEnum", - "included": 1, - "storageOption": "NVM", - "singleton": 0, - "bounded": 0, - "defaultValue": "0xFF", + "defaultValue": "", "reportable": 1, "minInterval": 1, "maxInterval": 65534, @@ -3139,22 +3505,6 @@ "maxInterval": 65534, "reportableChange": 0 }, - { - "name": "EventList", - "code": 65530, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, { "name": "AttributeList", "code": 65531, @@ -3181,7 +3531,7 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "1", + "defaultValue": "0", "reportable": 1, "minInterval": 1, "maxInterval": 65534, @@ -3197,7 +3547,7 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "5", + "defaultValue": "4", "reportable": 1, "minInterval": 1, "maxInterval": 65534, @@ -3206,194 +3556,138 @@ ] }, { - "name": "Descriptor", - "code": 29, + "name": "On/Off", + "code": 6, "mfgCode": null, - "define": "DESCRIPTOR_CLUSTER", + "define": "ON_OFF_CLUSTER", "side": "server", "enabled": 1, - "attributes": [ + "commands": [ { - "name": "DeviceTypeList", + "name": "Off", "code": 0, "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 + "source": "client", + "isIncoming": 1, + "isEnabled": 1 }, { - "name": "ServerList", + "name": "On", "code": 1, "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 + "source": "client", + "isIncoming": 1, + "isEnabled": 1 }, { - "name": "ClientList", + "name": "Toggle", "code": 2, "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "PartsList", - "code": 3, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "GeneratedCommandList", - "code": 65528, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 + "source": "client", + "isIncoming": 1, + "isEnabled": 1 }, { - "name": "AcceptedCommandList", - "code": 65529, + "name": "OffWithEffect", + "code": 64, "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 + "source": "client", + "isIncoming": 1, + "isEnabled": 1 }, { - "name": "EventList", - "code": 65530, + "name": "OnWithRecallGlobalScene", + "code": 65, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "OnWithTimedOff", + "code": 66, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + } + ], + "attributes": [ + { + "name": "OnOff", + "code": 0, "mfgCode": null, "side": "server", - "type": "array", + "type": "boolean", "included": 1, - "storageOption": "External", + "storageOption": "NVM", "singleton": 0, "bounded": 0, - "defaultValue": null, + "defaultValue": "0", "reportable": 1, "minInterval": 1, "maxInterval": 65534, "reportableChange": 0 }, { - "name": "AttributeList", - "code": 65531, + "name": "GlobalSceneControl", + "code": 16384, "mfgCode": null, "side": "server", - "type": "array", + "type": "boolean", "included": 1, - "storageOption": "External", + "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": null, + "defaultValue": "1", "reportable": 1, "minInterval": 1, "maxInterval": 65534, "reportableChange": 0 }, { - "name": "FeatureMap", - "code": 65532, + "name": "OnTime", + "code": 16385, "mfgCode": null, "side": "server", - "type": "bitmap32", + "type": "int16u", "included": 1, - "storageOption": "External", + "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": null, + "defaultValue": "0", "reportable": 1, "minInterval": 1, "maxInterval": 65534, "reportableChange": 0 }, { - "name": "ClusterRevision", - "code": 65533, + "name": "OffWaitTime", + "code": 16386, "mfgCode": null, "side": "server", "type": "int16u", "included": 1, - "storageOption": "External", + "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": null, + "defaultValue": "0", "reportable": 1, "minInterval": 1, "maxInterval": 65534, "reportableChange": 0 - } - ] - }, - { - "name": "Binding", - "code": 30, - "mfgCode": null, - "define": "BINDING_CLUSTER", - "side": "server", - "enabled": 1, - "attributes": [ + }, { - "name": "Binding", - "code": 0, + "name": "StartUpOnOff", + "code": 16387, "mfgCode": null, "side": "server", - "type": "array", + "type": "StartUpOnOffEnum", "included": 1, - "storageOption": "External", + "storageOption": "NVM", "singleton": 0, "bounded": 0, - "defaultValue": null, + "defaultValue": "0xFF", "reportable": 1, "minInterval": 1, "maxInterval": 65534, @@ -3431,22 +3725,6 @@ "maxInterval": 65534, "reportableChange": 0 }, - { - "name": "EventList", - "code": 65530, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, { "name": "AttributeList", "code": 65531, @@ -3473,7 +3751,7 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "0", + "defaultValue": "2", "reportable": 1, "minInterval": 1, "maxInterval": 65534, @@ -3489,7 +3767,7 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "1", + "defaultValue": "6", "reportable": 1, "minInterval": 1, "maxInterval": 65534, @@ -3498,80 +3776,64 @@ ] }, { - "name": "Power Source", - "code": 47, + "name": "Descriptor", + "code": 29, "mfgCode": null, - "define": "POWER_SOURCE_CLUSTER", + "define": "DESCRIPTOR_CLUSTER", "side": "server", "enabled": 1, "attributes": [ { - "name": "Status", + "name": "DeviceTypeList", "code": 0, "mfgCode": null, "side": "server", - "type": "PowerSourceStatusEnum", + "type": "array", "included": 1, - "storageOption": "RAM", + "storageOption": "External", "singleton": 0, "bounded": 0, - "defaultValue": "", + "defaultValue": null, "reportable": 1, "minInterval": 1, "maxInterval": 65534, "reportableChange": 0 }, { - "name": "Order", + "name": "ServerList", "code": 1, "mfgCode": null, "side": "server", - "type": "int8u", + "type": "array", "included": 1, - "storageOption": "RAM", + "storageOption": "External", "singleton": 0, "bounded": 0, - "defaultValue": "", + "defaultValue": null, "reportable": 1, "minInterval": 1, "maxInterval": 65534, "reportableChange": 0 }, { - "name": "Description", + "name": "ClientList", "code": 2, "mfgCode": null, "side": "server", - "type": "char_string", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "", - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "WiredCurrentType", - "code": 5, - "mfgCode": null, - "side": "server", - "type": "WiredCurrentTypeEnum", + "type": "array", "included": 1, - "storageOption": "RAM", + "storageOption": "External", "singleton": 0, "bounded": 0, - "defaultValue": "", + "defaultValue": null, "reportable": 1, "minInterval": 1, "maxInterval": 65534, "reportableChange": 0 }, { - "name": "EndpointList", - "code": 31, + "name": "PartsList", + "code": 3, "mfgCode": null, "side": "server", "type": "array", @@ -3656,10 +3918,10 @@ "side": "server", "type": "bitmap32", "included": 1, - "storageOption": "RAM", + "storageOption": "External", "singleton": 0, "bounded": 0, - "defaultValue": "1", + "defaultValue": null, "reportable": 1, "minInterval": 1, "maxInterval": 65534, @@ -3672,10 +3934,10 @@ "side": "server", "type": "int16u", "included": 1, - "storageOption": "RAM", + "storageOption": "External", "singleton": 0, "bounded": 0, - "defaultValue": "2", + "defaultValue": null, "reportable": 1, "minInterval": 1, "maxInterval": 65534, @@ -3684,15 +3946,15 @@ ] }, { - "name": "Fixed Label", - "code": 64, + "name": "Binding", + "code": 30, "mfgCode": null, - "define": "FIXED_LABEL_CLUSTER", + "define": "BINDING_CLUSTER", "side": "server", "enabled": 1, "attributes": [ { - "name": "LabelList", + "name": "Binding", "code": 0, "mfgCode": null, "side": "server", @@ -3806,10 +4068,10 @@ ] }, { - "name": "User Label", - "code": 65, + "name": "Fixed Label", + "code": 64, "mfgCode": null, - "define": "USER_LABEL_CLUSTER", + "define": "FIXED_LABEL_CLUSTER", "side": "server", "enabled": 1, "attributes": [ @@ -3928,60 +4190,18 @@ ] }, { - "name": "Mode Select", - "code": 80, + "name": "User Label", + "code": 65, "mfgCode": null, - "define": "MODE_SELECT_CLUSTER", + "define": "USER_LABEL_CLUSTER", "side": "server", "enabled": 1, - "commands": [ - { - "name": "ChangeToMode", - "code": 0, - "mfgCode": null, - "source": "client", - "isIncoming": 1, - "isEnabled": 1 - } - ], "attributes": [ { - "name": "Description", + "name": "LabelList", "code": 0, "mfgCode": null, "side": "server", - "type": "char_string", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "", - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "StandardNamespace", - "code": 1, - "mfgCode": null, - "side": "server", - "type": "enum16", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "", - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "SupportedModes", - "code": 2, - "mfgCode": null, - "side": "server", "type": "array", "included": 1, "storageOption": "External", @@ -3993,54 +4213,6 @@ "maxInterval": 65534, "reportableChange": 0 }, - { - "name": "CurrentMode", - "code": 3, - "mfgCode": null, - "side": "server", - "type": "int8u", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "", - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "StartUpMode", - "code": 4, - "mfgCode": null, - "side": "server", - "type": "int8u", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "", - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "OnMode", - "code": 5, - "mfgCode": null, - "side": "server", - "type": "int8u", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "", - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, { "name": "GeneratedCommandList", "code": 65528, @@ -4319,7 +4491,7 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "1", + "defaultValue": "2", "reportable": 1, "minInterval": 1, "maxInterval": 65534, @@ -4881,7 +5053,7 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "1", + "defaultValue": "2", "reportable": 1, "minInterval": 1, "maxInterval": 65534, @@ -4926,4 +5098,4 @@ "parentEndpointIdentifier": null } ] -} \ No newline at end of file +} diff --git a/examples/laundry-washer-app/nxp/zephyr/CMakeLists.txt b/examples/laundry-washer-app/nxp/zephyr/CMakeLists.txt index 9103b6a5567102..b3a03be0403676 100644 --- a/examples/laundry-washer-app/nxp/zephyr/CMakeLists.txt +++ b/examples/laundry-washer-app/nxp/zephyr/CMakeLists.txt @@ -106,10 +106,9 @@ target_sources(app PRIVATE ${ALL_CLUSTERS_COMMON_DIR}/src/smco-stub.cpp ${ALL_CLUSTERS_COMMON_DIR}/src/bridged-actions-stub.cpp - ${ALL_CLUSTERS_COMMON_DIR}/src/static-supported-modes-manager.cpp ${ALL_CLUSTERS_COMMON_DIR}/src/static-supported-temperature-levels.cpp - ${ALL_CLUSTERS_COMMON_DIR}/src/laundry-washer-mode.cpp + ${LAUNDRY_WASHER_NXP_COMMON_DIR}/main/laundry-washer-mode.cpp ${ALL_CLUSTERS_COMMON_DIR}/src/laundry-washer-controls-delegate-impl.cpp - ${LAUNDRY_WASHER_NXP_COMMON_DIR}/main/operational-state-delegate-impl.cpp + ${ALL_CLUSTERS_COMMON_DIR}/src/operational-state-delegate-impl.cpp ${EXAMPLE_PLATFORM_NXP_COMMON_DIR}/icd/source/ICDUtil.cpp ) diff --git a/src/app/AttributePathExpandIterator.cpp b/src/app/AttributePathExpandIterator.cpp index 96aa2772912139..419067db9ddf23 100644 --- a/src/app/AttributePathExpandIterator.cpp +++ b/src/app/AttributePathExpandIterator.cpp @@ -115,13 +115,13 @@ std::optional AttributePathExpandIterator::NextClusterId() { if (mpAttributePath->mValue.HasWildcardClusterId()) { - ClusterEntry entry = mDataModelProvider->FirstCluster(mOutputPath.mEndpointId); + ClusterEntry entry = mDataModelProvider->FirstServerCluster(mOutputPath.mEndpointId); return entry.IsValid() ? std::make_optional(entry.path.mClusterId) : std::nullopt; } // only return a cluster if it is valid const ConcreteClusterPath clusterPath(mOutputPath.mEndpointId, mpAttributePath->mValue.mClusterId); - if (!mDataModelProvider->GetClusterInfo(clusterPath).has_value()) + if (!mDataModelProvider->GetServerClusterInfo(clusterPath).has_value()) { return std::nullopt; } @@ -131,7 +131,7 @@ std::optional AttributePathExpandIterator::NextClusterId() VerifyOrReturnValue(mpAttributePath->mValue.HasWildcardClusterId(), std::nullopt); - ClusterEntry entry = mDataModelProvider->NextCluster(mOutputPath); + ClusterEntry entry = mDataModelProvider->NextServerCluster(mOutputPath); return entry.IsValid() ? std::make_optional(entry.path.mClusterId) : std::nullopt; } @@ -141,8 +141,8 @@ std::optional AttributePathExpandIterator::NextEndpointId() { if (mpAttributePath->mValue.HasWildcardEndpointId()) { - EndpointId id = mDataModelProvider->FirstEndpoint(); - return (id != kInvalidEndpointId) ? std::make_optional(id) : std::nullopt; + EndpointEntry ep = mDataModelProvider->FirstEndpoint(); + return (ep.id != kInvalidEndpointId) ? std::make_optional(ep.id) : std::nullopt; } return mpAttributePath->mValue.mEndpointId; @@ -150,8 +150,8 @@ std::optional AttributePathExpandIterator::NextEndpointId() VerifyOrReturnValue(mpAttributePath->mValue.HasWildcardEndpointId(), std::nullopt); - EndpointId id = mDataModelProvider->NextEndpoint(mOutputPath.mEndpointId); - return (id != kInvalidEndpointId) ? std::make_optional(id) : std::nullopt; + EndpointEntry ep = mDataModelProvider->NextEndpoint(mOutputPath.mEndpointId); + return (ep.id != kInvalidEndpointId) ? std::make_optional(ep.id) : std::nullopt; } void AttributePathExpandIterator::ResetCurrentCluster() diff --git a/src/app/InteractionModelEngine.cpp b/src/app/InteractionModelEngine.cpp index 56acd096611565..78967c6d53c680 100644 --- a/src/app/InteractionModelEngine.cpp +++ b/src/app/InteractionModelEngine.cpp @@ -89,14 +89,14 @@ bool MayHaveAccessibleEventPathForEndpoint(DataModel::Provider * aProvider, Endp aSubjectDescriptor); } - DataModel::ClusterEntry clusterEntry = aProvider->FirstCluster(aEventPath.mEndpointId); + DataModel::ClusterEntry clusterEntry = aProvider->FirstServerCluster(aEventPath.mEndpointId); while (clusterEntry.IsValid()) { if (MayHaveAccessibleEventPathForEndpointAndCluster(clusterEntry.path, aEventPath, aSubjectDescriptor)) { return true; } - clusterEntry = aProvider->NextCluster(clusterEntry.path); + clusterEntry = aProvider->NextServerCluster(clusterEntry.path); } return false; @@ -112,10 +112,9 @@ bool MayHaveAccessibleEventPath(DataModel::Provider * aProvider, const EventPath return MayHaveAccessibleEventPathForEndpoint(aProvider, aEventPath.mEndpointId, aEventPath, subjectDescriptor); } - for (EndpointId endpointId = aProvider->FirstEndpoint(); endpointId != kInvalidEndpointId; - endpointId = aProvider->NextEndpoint(endpointId)) + for (DataModel::EndpointEntry ep = aProvider->FirstEndpoint(); ep.IsValid(); ep = aProvider->NextEndpoint(ep.id)) { - if (MayHaveAccessibleEventPathForEndpoint(aProvider, endpointId, aEventPath, subjectDescriptor)) + if (MayHaveAccessibleEventPathForEndpoint(aProvider, ep.id, aEventPath, subjectDescriptor)) { return true; } @@ -1793,17 +1792,16 @@ Protocols::InteractionModel::Status InteractionModelEngine::CheckCommandExistenc // We failed, figure out why ... // - if (provider->GetClusterInfo(aCommandPath).has_value()) + if (provider->GetServerClusterInfo(aCommandPath).has_value()) { return Protocols::InteractionModel::Status::UnsupportedCommand; // cluster exists, so command is invalid } // At this point either cluster or endpoint does not exist. If we find the endpoint, then the cluster // is invalid - for (EndpointId endpoint = provider->FirstEndpoint(); endpoint != kInvalidEndpointId; - endpoint = provider->NextEndpoint(endpoint)) + for (DataModel::EndpointEntry ep = provider->FirstEndpoint(); ep.IsValid(); ep = provider->NextEndpoint(ep.id)) { - if (endpoint == aCommandPath.mEndpointId) + if (ep.id == aCommandPath.mEndpointId) { // endpoint exists, so cluster is invalid return Protocols::InteractionModel::Status::UnsupportedCluster; diff --git a/src/app/ReadHandler.cpp b/src/app/ReadHandler.cpp index 4794ead97eb86b..43f9b9310df848 100644 --- a/src/app/ReadHandler.cpp +++ b/src/app/ReadHandler.cpp @@ -152,6 +152,7 @@ ReadHandler::~ReadHandler() auto * appCallback = mManagementCallback.GetAppCallback(); if (mFlags.Has(ReadHandlerFlags::ActiveSubscription) && appCallback) { + mFlags.Clear(ReadHandlerFlags::ActiveSubscription); appCallback->OnSubscriptionTerminated(*this); } diff --git a/src/app/clusters/descriptor/descriptor.cpp b/src/app/clusters/descriptor/descriptor.cpp index a8e50387646d5d..409240e66a8b9e 100644 --- a/src/app/clusters/descriptor/descriptor.cpp +++ b/src/app/clusters/descriptor/descriptor.cpp @@ -25,6 +25,8 @@ #include #include #include +#include +#include #include #include #include @@ -73,19 +75,13 @@ CHIP_ERROR DescriptorAttrAccess::ReadFeatureMap(EndpointId endpoint, AttributeVa CHIP_ERROR DescriptorAttrAccess::ReadTagListAttribute(EndpointId endpoint, AttributeValueEncoder & aEncoder) { return aEncoder.EncodeList([&endpoint](const auto & encoder) -> CHIP_ERROR { - Clusters::Descriptor::Structs::SemanticTagStruct::Type tag; - size_t index = 0; - CHIP_ERROR err = CHIP_NO_ERROR; - while ((err = GetSemanticTagForEndpointAtIndex(endpoint, index, tag)) == CHIP_NO_ERROR) + auto tag = InteractionModelEngine::GetInstance()->GetDataModelProvider()->GetFirstSemanticTag(endpoint); + while (tag.has_value()) { - ReturnErrorOnFailure(encoder.Encode(tag)); - index++; + ReturnErrorOnFailure(encoder.Encode(tag.value())); + tag = InteractionModelEngine::GetInstance()->GetDataModelProvider()->GetNextSemanticTag(endpoint, tag.value()); } - if (err == CHIP_ERROR_NOT_FOUND) - { - return CHIP_NO_ERROR; - } - return err; + return CHIP_NO_ERROR; }); } @@ -93,67 +89,63 @@ CHIP_ERROR DescriptorAttrAccess::ReadPartsAttribute(EndpointId endpoint, Attribu { CHIP_ERROR err = CHIP_NO_ERROR; + auto endpointInfo = InteractionModelEngine::GetInstance()->GetDataModelProvider()->GetEndpointInfo(endpoint); if (endpoint == 0x00) { err = aEncoder.EncodeList([](const auto & encoder) -> CHIP_ERROR { - for (uint16_t index = 0; index < emberAfEndpointCount(); index++) + auto endpointEntry = InteractionModelEngine::GetInstance()->GetDataModelProvider()->FirstEndpoint(); + while (endpointEntry.IsValid()) { - if (emberAfEndpointIndexIsEnabled(index)) + if (endpointEntry.id != 0) { - EndpointId endpointId = emberAfEndpointFromIndex(index); - if (endpointId == 0) - continue; - - ReturnErrorOnFailure(encoder.Encode(endpointId)); + ReturnErrorOnFailure(encoder.Encode(endpointEntry.id)); } + endpointEntry = InteractionModelEngine::GetInstance()->GetDataModelProvider()->NextEndpoint(endpointEntry.id); } - return CHIP_NO_ERROR; }); } - else if (IsFlatCompositionForEndpoint(endpoint)) + else if (endpointInfo.has_value() && + endpointInfo->compositionPattern == DataModel::EndpointCompositionPattern::kFullFamilyPattern) { err = aEncoder.EncodeList([endpoint](const auto & encoder) -> CHIP_ERROR { - for (uint16_t index = 0; index < emberAfEndpointCount(); index++) + auto endpointEntry = InteractionModelEngine::GetInstance()->GetDataModelProvider()->FirstEndpoint(); + while (endpointEntry.IsValid()) { - if (!emberAfEndpointIndexIsEnabled(index)) - continue; - - uint16_t childIndex = index; - while (childIndex != chip::kInvalidListIndex) + EndpointId parentEndpointId = endpointEntry.info.parentId; + while (parentEndpointId != chip::kInvalidEndpointId) { - EndpointId parentEndpointId = emberAfParentEndpointFromIndex(childIndex); - if (parentEndpointId == chip::kInvalidEndpointId) - break; - if (parentEndpointId == endpoint) { - ReturnErrorOnFailure(encoder.Encode(emberAfEndpointFromIndex(index))); + ReturnErrorOnFailure(encoder.Encode(endpointEntry.id)); break; } - - childIndex = emberAfIndexFromEndpoint(parentEndpointId); + auto parentEndpointInfo = + InteractionModelEngine::GetInstance()->GetDataModelProvider()->GetEndpointInfo(parentEndpointId); + if (!parentEndpointInfo.has_value()) + { + break; + } + parentEndpointId = parentEndpointInfo->parentId; } + endpointEntry = InteractionModelEngine::GetInstance()->GetDataModelProvider()->NextEndpoint(endpointEntry.id); } return CHIP_NO_ERROR; }); } - else if (IsTreeCompositionForEndpoint(endpoint)) + else if (endpointInfo.has_value() && endpointInfo->compositionPattern == DataModel::EndpointCompositionPattern::kTreePattern) { err = aEncoder.EncodeList([endpoint](const auto & encoder) -> CHIP_ERROR { - for (uint16_t index = 0; index < emberAfEndpointCount(); index++) + auto endpointEntry = InteractionModelEngine::GetInstance()->GetDataModelProvider()->FirstEndpoint(); + while (endpointEntry.IsValid()) { - if (!emberAfEndpointIndexIsEnabled(index)) - continue; - - EndpointId parentEndpointId = emberAfParentEndpointFromIndex(index); - if (parentEndpointId == endpoint) + if (endpointEntry.info.parentId == endpoint) { - ReturnErrorOnFailure(encoder.Encode(emberAfEndpointFromIndex(index))); + ReturnErrorOnFailure(encoder.Encode(endpointEntry.id)); } + endpointEntry = InteractionModelEngine::GetInstance()->GetDataModelProvider()->NextEndpoint(endpointEntry.id); } - return CHIP_NO_ERROR; }); } @@ -165,16 +157,15 @@ CHIP_ERROR DescriptorAttrAccess::ReadDeviceAttribute(EndpointId endpoint, Attrib { CHIP_ERROR err = aEncoder.EncodeList([&endpoint](const auto & encoder) -> CHIP_ERROR { Descriptor::Structs::DeviceTypeStruct::Type deviceStruct; - CHIP_ERROR err2; - auto deviceTypeList = emberAfDeviceTypeListFromEndpoint(endpoint, err2); - ReturnErrorOnFailure(err2); + auto deviceType = InteractionModelEngine::GetInstance()->GetDataModelProvider()->FirstDeviceType(endpoint); - for (auto & deviceType : deviceTypeList) + while (deviceType.has_value()) { - deviceStruct.deviceType = deviceType.deviceId; - deviceStruct.revision = deviceType.deviceVersion; + deviceStruct.deviceType = deviceType->deviceTypeId; + deviceStruct.revision = deviceType->deviceTypeRevision; ReturnErrorOnFailure(encoder.Encode(deviceStruct)); + deviceType = InteractionModelEngine::GetInstance()->GetDataModelProvider()->NextDeviceType(endpoint, *deviceType); } return CHIP_NO_ERROR; @@ -186,12 +177,24 @@ CHIP_ERROR DescriptorAttrAccess::ReadDeviceAttribute(EndpointId endpoint, Attrib CHIP_ERROR DescriptorAttrAccess::ReadClientServerAttribute(EndpointId endpoint, AttributeValueEncoder & aEncoder, bool server) { CHIP_ERROR err = aEncoder.EncodeList([&endpoint, server](const auto & encoder) -> CHIP_ERROR { - uint8_t clusterCount = emberAfClusterCount(endpoint, server); - - for (uint8_t clusterIndex = 0; clusterIndex < clusterCount; clusterIndex++) + if (server) { - const EmberAfCluster * cluster = emberAfGetNthCluster(endpoint, clusterIndex, server); - ReturnErrorOnFailure(encoder.Encode(cluster->clusterId)); + auto clusterEntry = InteractionModelEngine::GetInstance()->GetDataModelProvider()->FirstServerCluster(endpoint); + while (clusterEntry.IsValid()) + { + ReturnErrorOnFailure(encoder.Encode(clusterEntry.path.mClusterId)); + clusterEntry = InteractionModelEngine::GetInstance()->GetDataModelProvider()->NextServerCluster(clusterEntry.path); + } + } + else + { + ConcreteClusterPath clusterPath = + InteractionModelEngine::GetInstance()->GetDataModelProvider()->FirstClientCluster(endpoint); + while (clusterPath.HasValidIds()) + { + ReturnErrorOnFailure(encoder.Encode(clusterPath.mClusterId)); + clusterPath = InteractionModelEngine::GetInstance()->GetDataModelProvider()->NextClientCluster(clusterPath); + } } return CHIP_NO_ERROR; diff --git a/src/app/codegen-data-model-provider/CodegenDataModelProvider.cpp b/src/app/codegen-data-model-provider/CodegenDataModelProvider.cpp index b0815da48e0c08..4eae3de1e247db 100644 --- a/src/app/codegen-data-model-provider/CodegenDataModelProvider.cpp +++ b/src/app/codegen-data-model-provider/CodegenDataModelProvider.cpp @@ -128,10 +128,8 @@ std::variant LoadClusterInfo(const ConcreteC } DataModel::ClusterInfo info(*versionPtr); - // TODO: set entry flags: // info->flags.Set(ClusterQualityFlags::kDiagnosticsData) - return info; } @@ -194,6 +192,23 @@ DataModel::ClusterEntry FirstServerClusterEntry(EndpointId endpointId, const Emb return DataModel::ClusterEntry::kInvalid; } +ClusterId FirstClientClusterId(const EmberAfEndpointType * endpoint, unsigned start_index, unsigned & found_index) +{ + for (unsigned cluster_idx = start_index; cluster_idx < endpoint->clusterCount; cluster_idx++) + { + const EmberAfCluster & cluster = endpoint->cluster[cluster_idx]; + if (!cluster.IsClient()) + { + continue; + } + + found_index = cluster_idx; + return cluster.clusterId; + } + + return kInvalidClusterId; +} + /// Load the attribute information into the specified destination /// /// `info` is assumed to be default-constructed/clear (i.e. this sets flags, but does not reset them). @@ -255,8 +270,8 @@ DataModel::DeviceTypeEntry DeviceTypeEntryFromEmber(const EmberAfDeviceType & ot { DataModel::DeviceTypeEntry entry; - entry.deviceTypeId = other.deviceId; - entry.deviceTypeVersion = other.deviceVersion; + entry.deviceTypeId = other.deviceId; + entry.deviceTypeRevision = other.deviceVersion; return entry; } @@ -265,7 +280,7 @@ DataModel::DeviceTypeEntry DeviceTypeEntryFromEmber(const EmberAfDeviceType & ot // so you must do `a == b` and the `b == a` will not work. bool operator==(const DataModel::DeviceTypeEntry & a, const EmberAfDeviceType & b) { - return (a.deviceTypeId == b.deviceId) && (a.deviceTypeVersion == b.deviceVersion); + return (a.deviceTypeId == b.deviceId) && (a.deviceTypeRevision == b.deviceVersion); } /// Find the `index` where one of the following holds: @@ -300,6 +315,96 @@ unsigned FindNextDeviceTypeIndex(Span types, const Data const ConcreteCommandPath kInvalidCommandPath(kInvalidEndpointId, kInvalidClusterId, kInvalidCommandId); +std::optional GetEndpointInfoAtIndex(uint16_t endpointIndex) +{ + VerifyOrReturnValue(emberAfEndpointIndexIsEnabled(endpointIndex), std::nullopt); + EndpointId parent = emberAfParentEndpointFromIndex(endpointIndex); + if (GetCompositionForEndpointIndex(endpointIndex) == EndpointComposition::kFullFamily) + { + return DataModel::EndpointInfo(parent, DataModel::EndpointCompositionPattern::kFullFamilyPattern); + } + if (GetCompositionForEndpointIndex(endpointIndex) == EndpointComposition::kTree) + { + return DataModel::EndpointInfo(parent, DataModel::EndpointCompositionPattern::kTreePattern); + } + return std::nullopt; +} + +DataModel::EndpointEntry FirstEndpointEntry(unsigned start_index, uint16_t & found_index) +{ + // find the first enabled index after the start index + const uint16_t lastEndpointIndex = emberAfEndpointCount(); + for (uint16_t endpoint_idx = static_cast(start_index); endpoint_idx < lastEndpointIndex; endpoint_idx++) + { + if (emberAfEndpointIndexIsEnabled(endpoint_idx)) + { + found_index = endpoint_idx; + DataModel::EndpointEntry endpointEntry = DataModel::EndpointEntry::kInvalid; + endpointEntry.id = emberAfEndpointFromIndex(endpoint_idx); + auto endpointInfo = GetEndpointInfoAtIndex(endpoint_idx); + // The endpoint info should have value as this endpoint should be valid at this time + VerifyOrDie(endpointInfo.has_value()); + endpointEntry.info = endpointInfo.value(); + return endpointEntry; + } + } + + // No enabled endpoint found. Give up + return DataModel::EndpointEntry::kInvalid; +} + +bool operator==(const DataModel::Provider::SemanticTag & tagA, const DataModel::Provider::SemanticTag & tagB) +{ + // Label is an optional and nullable value of CharSpan. Optional and Nullable have overload for ==, + // But `==` is deleted for CharSpan. Here we only check whether the string is the same. + if (tagA.label.HasValue() != tagB.label.HasValue()) + { + return false; + } + if (tagA.label.HasValue()) + { + if (tagA.label.Value().IsNull() != tagB.label.Value().IsNull()) + { + return false; + } + if (!tagA.label.Value().IsNull()) + { + if (!tagA.label.Value().Value().data_equal(tagB.label.Value().Value())) + { + return false; + } + } + } + return (tagA.tag == tagB.tag) && (tagA.mfgCode == tagB.mfgCode) && (tagA.namespaceID == tagB.namespaceID); +} + +std::optional FindNextSemanticTagIndex(EndpointId endpoint, const DataModel::Provider::SemanticTag & previous, + unsigned hintWherePreviousMayBe) +{ + DataModel::Provider::SemanticTag hintTag; + // Check whether the hint is the previous tag + if (GetSemanticTagForEndpointAtIndex(endpoint, hintWherePreviousMayBe, hintTag) == CHIP_NO_ERROR) + { + if (previous == hintTag) + { + return std::make_optional(hintWherePreviousMayBe + 1); + } + } + // If the hint is not the previous tag, iterate over all the tags to find the index for the previous tag + unsigned index = 0; + // Ensure that the next index is in the range + while (GetSemanticTagForEndpointAtIndex(endpoint, index + 1, hintTag) == CHIP_NO_ERROR && + GetSemanticTagForEndpointAtIndex(endpoint, index, hintTag) == CHIP_NO_ERROR) + { + if (previous == hintTag) + { + return std::make_optional(index + 1); + } + index++; + } + return std::nullopt; +} + } // namespace std::optional CodegenDataModelProvider::EmberCommandListIterator::First(const CommandId * list) @@ -397,21 +502,19 @@ bool CodegenDataModelProvider::EndpointExists(EndpointId endpoint) return (emberAfIndexFromEndpoint(endpoint) != kEmberInvalidEndpointIndex); } -EndpointId CodegenDataModelProvider::FirstEndpoint() +std::optional CodegenDataModelProvider::GetEndpointInfo(EndpointId endpoint) { - // find the first enabled index - const uint16_t lastEndpointIndex = emberAfEndpointCount(); - for (uint16_t endpoint_idx = 0; endpoint_idx < lastEndpointIndex; endpoint_idx++) + std::optional endpoint_idx = TryFindEndpointIndex(endpoint); + if (endpoint_idx.has_value()) { - if (emberAfEndpointIndexIsEnabled(endpoint_idx)) - { - mEndpointIterationHint = endpoint_idx; - return emberAfEndpointFromIndex(endpoint_idx); - } + return GetEndpointInfoAtIndex(static_cast(*endpoint_idx)); } + return std::nullopt; +} - // No enabled endpoint found. Give up - return kInvalidEndpointId; +DataModel::EndpointEntry CodegenDataModelProvider::FirstEndpoint() +{ + return FirstEndpointEntry(0, mEndpointIterationHint); } std::optional CodegenDataModelProvider::TryFindEndpointIndex(EndpointId id) const @@ -434,51 +537,41 @@ std::optional CodegenDataModelProvider::TryFindEndpointIndex(EndpointI return std::make_optional(idx); } -EndpointId CodegenDataModelProvider::NextEndpoint(EndpointId before) +DataModel::EndpointEntry CodegenDataModelProvider::NextEndpoint(EndpointId before) { - const uint16_t lastEndpointIndex = emberAfEndpointCount(); - std::optional before_idx = TryFindEndpointIndex(before); if (!before_idx.has_value()) { - return kInvalidEndpointId; + return DataModel::EndpointEntry::kInvalid; } - - // find the first enabled index - for (uint16_t endpoint_idx = static_cast(*before_idx + 1); endpoint_idx < lastEndpointIndex; endpoint_idx++) - { - if (emberAfEndpointIndexIsEnabled(endpoint_idx)) - { - mEndpointIterationHint = endpoint_idx; - return emberAfEndpointFromIndex(endpoint_idx); - } - } - - // No enabled enpoint after "before" was found, give up - return kInvalidEndpointId; + return FirstEndpointEntry(*before_idx + 1, mEndpointIterationHint); } -DataModel::ClusterEntry CodegenDataModelProvider::FirstCluster(EndpointId endpointId) +DataModel::ClusterEntry CodegenDataModelProvider::FirstServerCluster(EndpointId endpointId) { const EmberAfEndpointType * endpoint = emberAfFindEndpointType(endpointId); VerifyOrReturnValue(endpoint != nullptr, DataModel::ClusterEntry::kInvalid); VerifyOrReturnValue(endpoint->clusterCount > 0, DataModel::ClusterEntry::kInvalid); VerifyOrReturnValue(endpoint->cluster != nullptr, DataModel::ClusterEntry::kInvalid); - return FirstServerClusterEntry(endpointId, endpoint, 0, mClusterIterationHint); + return FirstServerClusterEntry(endpointId, endpoint, 0, mServerClusterIterationHint); } -std::optional CodegenDataModelProvider::TryFindServerClusterIndex(const EmberAfEndpointType * endpoint, - ClusterId id) const +std::optional CodegenDataModelProvider::TryFindClusterIndex(const EmberAfEndpointType * endpoint, ClusterId id, + ClusterSide side) const { const unsigned clusterCount = endpoint->clusterCount; + unsigned hint = side == ClusterSide::kServer ? mServerClusterIterationHint : mClientClusterIterationHint; - if (mClusterIterationHint < clusterCount) + if (hint < clusterCount) { - const EmberAfCluster & cluster = endpoint->cluster[mClusterIterationHint]; - if (cluster.IsServer() && (cluster.clusterId == id)) + const EmberAfCluster & cluster = endpoint->cluster[hint]; + if (((side == ClusterSide::kServer) && cluster.IsServer()) || ((side == ClusterSide::kClient) && cluster.IsClient())) { - return std::make_optional(mClusterIterationHint); + if (cluster.clusterId == id) + { + return std::make_optional(hint); + } } } @@ -488,7 +581,11 @@ std::optional CodegenDataModelProvider::TryFindServerClusterIndex(cons for (unsigned cluster_idx = 0; cluster_idx < clusterCount; cluster_idx++) { const EmberAfCluster & cluster = endpoint->cluster[cluster_idx]; - if (cluster.IsServer() && (cluster.clusterId == id)) + if (((side == ClusterSide::kServer) && !cluster.IsServer()) || ((side == ClusterSide::kClient) && !cluster.IsClient())) + { + continue; + } + if (cluster.clusterId == id) { return std::make_optional(cluster_idx); } @@ -497,7 +594,7 @@ std::optional CodegenDataModelProvider::TryFindServerClusterIndex(cons return std::nullopt; } -DataModel::ClusterEntry CodegenDataModelProvider::NextCluster(const ConcreteClusterPath & before) +DataModel::ClusterEntry CodegenDataModelProvider::NextServerCluster(const ConcreteClusterPath & before) { // TODO: This search still seems slow (ember will loop). Should use index hints as long // as ember API supports it @@ -507,16 +604,16 @@ DataModel::ClusterEntry CodegenDataModelProvider::NextCluster(const ConcreteClus VerifyOrReturnValue(endpoint->clusterCount > 0, DataModel::ClusterEntry::kInvalid); VerifyOrReturnValue(endpoint->cluster != nullptr, DataModel::ClusterEntry::kInvalid); - std::optional cluster_idx = TryFindServerClusterIndex(endpoint, before.mClusterId); + std::optional cluster_idx = TryFindClusterIndex(endpoint, before.mClusterId, ClusterSide::kServer); if (!cluster_idx.has_value()) { return DataModel::ClusterEntry::kInvalid; } - return FirstServerClusterEntry(before.mEndpointId, endpoint, *cluster_idx + 1, mClusterIterationHint); + return FirstServerClusterEntry(before.mEndpointId, endpoint, *cluster_idx + 1, mServerClusterIterationHint); } -std::optional CodegenDataModelProvider::GetClusterInfo(const ConcreteClusterPath & path) +std::optional CodegenDataModelProvider::GetServerClusterInfo(const ConcreteClusterPath & path) { const EmberAfCluster * cluster = FindServerCluster(path); @@ -537,6 +634,35 @@ std::optional CodegenDataModelProvider::GetClusterInfo(c return std::make_optional(std::get(info)); } +ConcreteClusterPath CodegenDataModelProvider::FirstClientCluster(EndpointId endpointId) +{ + const EmberAfEndpointType * endpoint = emberAfFindEndpointType(endpointId); + VerifyOrReturnValue(endpoint != nullptr, ConcreteClusterPath(endpointId, kInvalidClusterId)); + VerifyOrReturnValue(endpoint->clusterCount > 0, ConcreteClusterPath(endpointId, kInvalidClusterId)); + VerifyOrReturnValue(endpoint->cluster != nullptr, ConcreteClusterPath(endpointId, kInvalidClusterId)); + + return ConcreteClusterPath(endpointId, FirstClientClusterId(endpoint, 0, mClientClusterIterationHint)); +} + +ConcreteClusterPath CodegenDataModelProvider::NextClientCluster(const ConcreteClusterPath & before) +{ + // TODO: This search still seems slow (ember will loop). Should use index hints as long + // as ember API supports it + const EmberAfEndpointType * endpoint = emberAfFindEndpointType(before.mEndpointId); + + VerifyOrReturnValue(endpoint != nullptr, ConcreteClusterPath(before.mEndpointId, kInvalidClusterId)); + VerifyOrReturnValue(endpoint->clusterCount > 0, ConcreteClusterPath(before.mEndpointId, kInvalidClusterId)); + VerifyOrReturnValue(endpoint->cluster != nullptr, ConcreteClusterPath(before.mEndpointId, kInvalidClusterId)); + + std::optional cluster_idx = TryFindClusterIndex(endpoint, before.mClusterId, ClusterSide::kClient); + if (!cluster_idx.has_value()) + { + return ConcreteClusterPath(before.mEndpointId, kInvalidClusterId); + } + + return ConcreteClusterPath(before.mEndpointId, FirstClientClusterId(endpoint, *cluster_idx + 1, mClientClusterIterationHint)); +} + DataModel::AttributeEntry CodegenDataModelProvider::FirstAttribute(const ConcreteClusterPath & path) { const EmberAfCluster * cluster = FindServerCluster(path); @@ -772,5 +898,29 @@ std::optional CodegenDataModelProvider::NextDeviceTy return DeviceTypeEntryFromEmber(deviceTypes[idx]); } +std::optional CodegenDataModelProvider::GetFirstSemanticTag(EndpointId endpoint) +{ + Clusters::Descriptor::Structs::SemanticTagStruct::Type tag; + // we start at the beginning + mSemanticTagIterationHint = 0; + if (GetSemanticTagForEndpointAtIndex(endpoint, 0, tag) == CHIP_NO_ERROR) + { + return std::make_optional(tag); + } + return std::nullopt; +} + +std::optional CodegenDataModelProvider::GetNextSemanticTag(EndpointId endpoint, + const SemanticTag & previous) +{ + Clusters::Descriptor::Structs::SemanticTagStruct::Type tag; + std::optional idx = FindNextSemanticTagIndex(endpoint, previous, mSemanticTagIterationHint); + if (idx.has_value() && GetSemanticTagForEndpointAtIndex(endpoint, *idx, tag) == CHIP_NO_ERROR) + { + return std::make_optional(tag); + } + return std::nullopt; +} + } // namespace app } // namespace chip diff --git a/src/app/codegen-data-model-provider/CodegenDataModelProvider.h b/src/app/codegen-data-model-provider/CodegenDataModelProvider.h index 59b91747a0ef07..35193a492f819b 100644 --- a/src/app/codegen-data-model-provider/CodegenDataModelProvider.h +++ b/src/app/codegen-data-model-provider/CodegenDataModelProvider.h @@ -149,17 +149,24 @@ class CodegenDataModelProvider : public chip::app::DataModel::Provider chip::TLV::TLVReader & input_arguments, CommandHandler * handler) override; /// attribute tree iteration - EndpointId FirstEndpoint() override; - EndpointId NextEndpoint(EndpointId before) override; + DataModel::EndpointEntry FirstEndpoint() override; + DataModel::EndpointEntry NextEndpoint(EndpointId before) override; + std::optional GetEndpointInfo(EndpointId endpoint) override; bool EndpointExists(EndpointId endpoint) override; std::optional FirstDeviceType(EndpointId endpoint) override; std::optional NextDeviceType(EndpointId endpoint, const DataModel::DeviceTypeEntry & previous) override; - DataModel::ClusterEntry FirstCluster(EndpointId endpoint) override; - DataModel::ClusterEntry NextCluster(const ConcreteClusterPath & before) override; - std::optional GetClusterInfo(const ConcreteClusterPath & path) override; + std::optional GetFirstSemanticTag(EndpointId endpoint) override; + std::optional GetNextSemanticTag(EndpointId endpoint, const SemanticTag & previous) override; + + DataModel::ClusterEntry FirstServerCluster(EndpointId endpoint) override; + DataModel::ClusterEntry NextServerCluster(const ConcreteClusterPath & before) override; + std::optional GetServerClusterInfo(const ConcreteClusterPath & path) override; + + ConcreteClusterPath FirstClientCluster(EndpointId endpoint) override; + ConcreteClusterPath NextClientCluster(const ConcreteClusterPath & before) override; DataModel::AttributeEntry FirstAttribute(const ConcreteClusterPath & cluster) override; DataModel::AttributeEntry NextAttribute(const ConcreteAttributePath & before) override; @@ -175,10 +182,12 @@ class CodegenDataModelProvider : public chip::app::DataModel::Provider private: // Iteration is often done in a tight loop going through all values. // To avoid N^2 iterations, cache a hint of where something is positioned - uint16_t mEndpointIterationHint = 0; - unsigned mClusterIterationHint = 0; - unsigned mAttributeIterationHint = 0; - unsigned mDeviceTypeIterationHint = 0; + uint16_t mEndpointIterationHint = 0; + unsigned mServerClusterIterationHint = 0; + unsigned mClientClusterIterationHint = 0; + unsigned mAttributeIterationHint = 0; + unsigned mDeviceTypeIterationHint = 0; + unsigned mSemanticTagIterationHint = 0; EmberCommandListIterator mAcceptedCommandsIterator; EmberCommandListIterator mGeneratedCommandsIterator; @@ -191,6 +200,13 @@ class CodegenDataModelProvider : public chip::app::DataModel::Provider ClusterReference(const ConcreteClusterPath p, const EmberAfCluster * c) : path(p), cluster(c) {} }; + + enum class ClusterSide : uint8_t + { + kServer, + kClient, + }; + std::optional mPreviouslyFoundCluster; unsigned mEmberMetadataStructureGeneration = 0; @@ -203,7 +219,8 @@ class CodegenDataModelProvider : public chip::app::DataModel::Provider std::optional TryFindAttributeIndex(const EmberAfCluster * cluster, chip::AttributeId id) const; /// Find the index of the given cluster id - std::optional TryFindServerClusterIndex(const EmberAfEndpointType * endpoint, chip::ClusterId id) const; + std::optional TryFindClusterIndex(const EmberAfEndpointType * endpoint, chip::ClusterId id, + ClusterSide clusterSide) const; /// Find the index of the given endpoint id std::optional TryFindEndpointIndex(chip::EndpointId id) const; diff --git a/src/app/codegen-data-model-provider/CodegenDataModelProvider_Write.cpp b/src/app/codegen-data-model-provider/CodegenDataModelProvider_Write.cpp index de2f8886476707..7dcfe7feccff4d 100644 --- a/src/app/codegen-data-model-provider/CodegenDataModelProvider_Write.cpp +++ b/src/app/codegen-data-model-provider/CodegenDataModelProvider_Write.cpp @@ -190,7 +190,7 @@ DataModel::ActionReturnStatus CodegenDataModelProvider::WriteAttribute(const Dat if (request.path.mDataVersion.HasValue()) { - std::optional clusterInfo = GetClusterInfo(request.path); + std::optional clusterInfo = GetServerClusterInfo(request.path); if (!clusterInfo.has_value()) { ChipLogError(DataManagement, "Unable to get cluster info for Endpoint 0x%x, Cluster " ChipLogFormatMEI, diff --git a/src/app/codegen-data-model-provider/tests/TestCodegenModelViaMocks.cpp b/src/app/codegen-data-model-provider/tests/TestCodegenModelViaMocks.cpp index c9b2a1b99a375c..50d8ec67df3deb 100644 --- a/src/app/codegen-data-model-provider/tests/TestCodegenModelViaMocks.cpp +++ b/src/app/codegen-data-model-provider/tests/TestCodegenModelViaMocks.cpp @@ -96,6 +96,17 @@ constexpr uint8_t kDeviceTypeId2Version = 11; constexpr DeviceTypeId kDeviceTypeId3 = 3; constexpr uint8_t kDeviceTypeId3Version = 33; +constexpr uint8_t kNamespaceID1 = 123; +constexpr uint8_t kTag1 = 10; +constexpr char kLabel1[] = "Label1"; + +constexpr uint8_t kNamespaceID2 = 254; +constexpr uint8_t kTag2 = 22; +constexpr char kLabel2[] = "Label2"; + +constexpr uint8_t kNamespaceID3 = 3; +constexpr uint8_t kTag3 = 32; + static_assert(kEndpointIdThatIsMissing != kInvalidEndpointId); static_assert(kEndpointIdThatIsMissing != kMockEndpoint1); static_assert(kEndpointIdThatIsMissing != kMockEndpoint2); @@ -280,10 +291,16 @@ const MockNodeConfig gTestNodeConfig({ MockClusterConfig(MockClusterId(2), { ClusterRevision::Id, FeatureMap::Id, MockAttributeId(1), }), + MockClusterConfig(MockClusterId(3), {}, {}, {}, {}, BitMask().Set(MockClusterSide::kClient)), + MockClusterConfig(MockClusterId(4), {}, {}, {}, {}, BitMask().Set(MockClusterSide::kClient)), }, { { kDeviceTypeId1, kDeviceTypeId1Version}, { kDeviceTypeId2, kDeviceTypeId2Version}, { kDeviceTypeId3, kDeviceTypeId3Version}, + },{ + { MakeNullable(VendorId::TestVendor1), kNamespaceID1, kTag1, MakeOptional(MakeNullable(CharSpan::fromCharString(kLabel1)))}, + { Nullable(), kNamespaceID2, kTag2, MakeOptional(MakeNullable(CharSpan::fromCharString(kLabel2)))}, + { MakeNullable(VendorId::TestVendor3), kNamespaceID3, kTag3, NullOptional}, }), MockEndpointConfig(kMockEndpoint2, { MockClusterConfig(MockClusterId(1), { @@ -308,11 +325,14 @@ const MockNodeConfig gTestNodeConfig({ }, /* attributes */ {}, /* events */ {11}, /* acceptedCommands */ - {4, 6} /* generatedCommands */ + {4, 6}, /* generatedCommands */ + BitMask().Set(MockClusterSide::kClient).Set(MockClusterSide::kServer) ), + MockClusterConfig(MockClusterId(4), {}, {}, {}, {}, MockClusterSide::kClient), }, { { kDeviceTypeId2, kDeviceTypeId2Version}, - }), + }, {}, + EndpointComposition::kTree), MockEndpointConfig(kMockEndpoint3, { MockClusterConfig(MockClusterId(1), { ClusterRevision::Id, FeatureMap::Id, MockAttributeId(1), @@ -875,43 +895,109 @@ TEST(TestCodegenModelViaMocks, IterateOverEndpoints) CodegenDataModelProviderWithContext model; // This iteration relies on the hard-coding that occurs when mock_ember is used - EXPECT_EQ(model.FirstEndpoint(), kMockEndpoint1); - EXPECT_EQ(model.NextEndpoint(kMockEndpoint1), kMockEndpoint2); - EXPECT_EQ(model.NextEndpoint(kMockEndpoint2), kMockEndpoint3); - EXPECT_EQ(model.NextEndpoint(kMockEndpoint3), kInvalidEndpointId); + EndpointEntry ep = model.FirstEndpoint(); + EXPECT_EQ(ep.id, kMockEndpoint1); + EXPECT_EQ(ep.info.parentId, kInvalidEndpointId); + EXPECT_EQ(ep.info.compositionPattern, EndpointCompositionPattern::kFullFamilyPattern); + ep = model.NextEndpoint(kMockEndpoint1); + EXPECT_EQ(ep.id, kMockEndpoint2); + EXPECT_EQ(ep.info.parentId, kInvalidEndpointId); + EXPECT_EQ(ep.info.compositionPattern, EndpointCompositionPattern::kTreePattern); + ep = model.NextEndpoint(kMockEndpoint2); + EXPECT_EQ(ep.id, kMockEndpoint3); + EXPECT_EQ(ep.info.parentId, kInvalidEndpointId); + EXPECT_EQ(ep.info.compositionPattern, EndpointCompositionPattern::kFullFamilyPattern); + ep = model.NextEndpoint(kMockEndpoint3); + EXPECT_EQ(ep.id, kInvalidEndpointId); /// Some out of order requests should work as well - EXPECT_EQ(model.NextEndpoint(kMockEndpoint2), kMockEndpoint3); - EXPECT_EQ(model.NextEndpoint(kMockEndpoint2), kMockEndpoint3); - EXPECT_EQ(model.NextEndpoint(kMockEndpoint1), kMockEndpoint2); - EXPECT_EQ(model.NextEndpoint(kMockEndpoint1), kMockEndpoint2); - EXPECT_EQ(model.NextEndpoint(kMockEndpoint2), kMockEndpoint3); - EXPECT_EQ(model.NextEndpoint(kMockEndpoint1), kMockEndpoint2); - EXPECT_EQ(model.NextEndpoint(kMockEndpoint3), kInvalidEndpointId); - EXPECT_EQ(model.NextEndpoint(kMockEndpoint3), kInvalidEndpointId); - EXPECT_EQ(model.FirstEndpoint(), kMockEndpoint1); - EXPECT_EQ(model.FirstEndpoint(), kMockEndpoint1); + ep = model.NextEndpoint(kMockEndpoint2); + EXPECT_EQ(ep.id, kMockEndpoint3); + EXPECT_EQ(ep.info.parentId, kInvalidEndpointId); + EXPECT_EQ(ep.info.compositionPattern, EndpointCompositionPattern::kFullFamilyPattern); + ep = model.NextEndpoint(kMockEndpoint2); + EXPECT_EQ(ep.id, kMockEndpoint3); + EXPECT_EQ(ep.info.parentId, kInvalidEndpointId); + EXPECT_EQ(ep.info.compositionPattern, EndpointCompositionPattern::kFullFamilyPattern); + ep = model.NextEndpoint(kMockEndpoint1); + EXPECT_EQ(ep.id, kMockEndpoint2); + EXPECT_EQ(ep.info.parentId, kInvalidEndpointId); + EXPECT_EQ(ep.info.compositionPattern, EndpointCompositionPattern::kTreePattern); + ep = model.NextEndpoint(kMockEndpoint1); + EXPECT_EQ(ep.id, kMockEndpoint2); + EXPECT_EQ(ep.info.parentId, kInvalidEndpointId); + EXPECT_EQ(ep.info.compositionPattern, EndpointCompositionPattern::kTreePattern); + ep = model.NextEndpoint(kMockEndpoint2); + EXPECT_EQ(ep.id, kMockEndpoint3); + EXPECT_EQ(ep.info.parentId, kInvalidEndpointId); + EXPECT_EQ(ep.info.compositionPattern, EndpointCompositionPattern::kFullFamilyPattern); + ep = model.NextEndpoint(kMockEndpoint1); + EXPECT_EQ(ep.id, kMockEndpoint2); + EXPECT_EQ(ep.info.parentId, kInvalidEndpointId); + EXPECT_EQ(ep.info.compositionPattern, EndpointCompositionPattern::kTreePattern); + ep = model.NextEndpoint(kMockEndpoint3); + EXPECT_EQ(ep.id, kInvalidEndpointId); + ep = model.NextEndpoint(kMockEndpoint3); + EXPECT_EQ(ep.id, kInvalidEndpointId); + ep = model.FirstEndpoint(); + EXPECT_EQ(ep.id, kMockEndpoint1); + EXPECT_EQ(ep.info.parentId, kInvalidEndpointId); + EXPECT_EQ(ep.info.compositionPattern, EndpointCompositionPattern::kFullFamilyPattern); + ep = model.FirstEndpoint(); + EXPECT_EQ(ep.id, kMockEndpoint1); + EXPECT_EQ(ep.info.parentId, kInvalidEndpointId); + EXPECT_EQ(ep.info.compositionPattern, EndpointCompositionPattern::kFullFamilyPattern); + + // invalid endpoiunts + ep = model.NextEndpoint(kInvalidEndpointId); + EXPECT_EQ(ep.id, kInvalidEndpointId); + ep = model.NextEndpoint(987u); + EXPECT_EQ(ep.id, kInvalidEndpointId); +} + +TEST(TestCodegenModelViaMocks, GetEndpointInfo) +{ + UseMockNodeConfig config(gTestNodeConfig); + CodegenDataModelProviderWithContext model; + + std::optional info = model.GetEndpointInfo(kMockEndpoint1); + ASSERT_TRUE(info.has_value()); + EXPECT_EQ(info->parentId, kInvalidEndpointId); // NOLINT(bugprone-unchecked-optional-access) + EXPECT_EQ(info->compositionPattern, // NOLINT(bugprone-unchecked-optional-access) + EndpointCompositionPattern::kFullFamilyPattern); + info = model.GetEndpointInfo(kMockEndpoint2); + ASSERT_TRUE(info.has_value()); + EXPECT_EQ(info->parentId, kInvalidEndpointId); // NOLINT(bugprone-unchecked-optional-access) + EXPECT_EQ(info->compositionPattern, // NOLINT(bugprone-unchecked-optional-access) + EndpointCompositionPattern::kTreePattern); + info = model.GetEndpointInfo(kMockEndpoint3); + ASSERT_TRUE(info.has_value()); + EXPECT_EQ(info->parentId, kInvalidEndpointId); // NOLINT(bugprone-unchecked-optional-access) + EXPECT_EQ(info->compositionPattern, // NOLINT(bugprone-unchecked-optional-access) + EndpointCompositionPattern::kFullFamilyPattern); // invalid endpoiunts - EXPECT_EQ(model.NextEndpoint(kInvalidEndpointId), kInvalidEndpointId); - EXPECT_EQ(model.NextEndpoint(987u), kInvalidEndpointId); + info = model.GetEndpointInfo(kInvalidEndpointId); + EXPECT_FALSE(info.has_value()); + info = model.GetEndpointInfo(987u); + EXPECT_FALSE(info.has_value()); } -TEST(TestCodegenModelViaMocks, IterateOverClusters) +TEST(TestCodegenModelViaMocks, IterateOverServerClusters) { UseMockNodeConfig config(gTestNodeConfig); CodegenDataModelProviderWithContext model; chip::Test::ResetVersion(); - EXPECT_FALSE(model.FirstCluster(kEndpointIdThatIsMissing).path.HasValidIds()); - EXPECT_FALSE(model.FirstCluster(kInvalidEndpointId).path.HasValidIds()); - EXPECT_FALSE(model.NextCluster(ConcreteClusterPath(kInvalidEndpointId, 123)).path.HasValidIds()); - EXPECT_FALSE(model.NextCluster(ConcreteClusterPath(kMockEndpoint1, kInvalidClusterId)).path.HasValidIds()); - EXPECT_FALSE(model.NextCluster(ConcreteClusterPath(kMockEndpoint1, 981u)).path.HasValidIds()); + EXPECT_FALSE(model.FirstServerCluster(kEndpointIdThatIsMissing).path.HasValidIds()); + EXPECT_FALSE(model.FirstServerCluster(kInvalidEndpointId).path.HasValidIds()); + EXPECT_FALSE(model.NextServerCluster(ConcreteClusterPath(kInvalidEndpointId, 123)).path.HasValidIds()); + EXPECT_FALSE(model.NextServerCluster(ConcreteClusterPath(kMockEndpoint1, kInvalidClusterId)).path.HasValidIds()); + EXPECT_FALSE(model.NextServerCluster(ConcreteClusterPath(kMockEndpoint1, 981u)).path.HasValidIds()); // mock endpoint 1 has 2 mock clusters: 1 and 2 - ClusterEntry entry = model.FirstCluster(kMockEndpoint1); + ClusterEntry entry = model.FirstServerCluster(kMockEndpoint1); ASSERT_TRUE(entry.path.HasValidIds()); EXPECT_EQ(entry.path.mEndpointId, kMockEndpoint1); EXPECT_EQ(entry.path.mClusterId, MockClusterId(1)); @@ -920,31 +1006,31 @@ TEST(TestCodegenModelViaMocks, IterateOverClusters) chip::Test::BumpVersion(); - entry = model.NextCluster(entry.path); + entry = model.NextServerCluster(entry.path); ASSERT_TRUE(entry.path.HasValidIds()); EXPECT_EQ(entry.path.mEndpointId, kMockEndpoint1); EXPECT_EQ(entry.path.mClusterId, MockClusterId(2)); EXPECT_EQ(entry.info.dataVersion, 1u); EXPECT_EQ(entry.info.flags.Raw(), 0u); - entry = model.NextCluster(entry.path); + entry = model.NextServerCluster(entry.path); EXPECT_FALSE(entry.path.HasValidIds()); // mock endpoint 3 has 4 mock clusters: 1 through 4 - entry = model.FirstCluster(kMockEndpoint3); + entry = model.FirstServerCluster(kMockEndpoint3); for (uint16_t clusterId = 1; clusterId <= 4; clusterId++) { ASSERT_TRUE(entry.path.HasValidIds()); EXPECT_EQ(entry.path.mEndpointId, kMockEndpoint3); EXPECT_EQ(entry.path.mClusterId, MockClusterId(clusterId)); - entry = model.NextCluster(entry.path); + entry = model.NextServerCluster(entry.path); } EXPECT_FALSE(entry.path.HasValidIds()); // repeat calls should work for (int i = 0; i < 10; i++) { - entry = model.FirstCluster(kMockEndpoint1); + entry = model.FirstServerCluster(kMockEndpoint1); ASSERT_TRUE(entry.path.HasValidIds()); EXPECT_EQ(entry.path.mEndpointId, kMockEndpoint1); EXPECT_EQ(entry.path.mClusterId, MockClusterId(1)); @@ -952,14 +1038,14 @@ TEST(TestCodegenModelViaMocks, IterateOverClusters) for (int i = 0; i < 10; i++) { - ClusterEntry nextEntry = model.NextCluster(entry.path); + ClusterEntry nextEntry = model.NextServerCluster(entry.path); ASSERT_TRUE(nextEntry.path.HasValidIds()); EXPECT_EQ(nextEntry.path.mEndpointId, kMockEndpoint1); EXPECT_EQ(nextEntry.path.mClusterId, MockClusterId(2)); } } -TEST(TestCodegenModelViaMocks, GetClusterInfo) +TEST(TestCodegenModelViaMocks, GetServerClusterInfo) { UseMockNodeConfig config(gTestNodeConfig); @@ -967,24 +1053,78 @@ TEST(TestCodegenModelViaMocks, GetClusterInfo) chip::Test::ResetVersion(); - ASSERT_FALSE(model.GetClusterInfo(ConcreteClusterPath(kInvalidEndpointId, kInvalidClusterId)).has_value()); - ASSERT_FALSE(model.GetClusterInfo(ConcreteClusterPath(kInvalidEndpointId, MockClusterId(1))).has_value()); - ASSERT_FALSE(model.GetClusterInfo(ConcreteClusterPath(kMockEndpoint1, kInvalidClusterId)).has_value()); - ASSERT_FALSE(model.GetClusterInfo(ConcreteClusterPath(kMockEndpoint1, MockClusterId(10))).has_value()); + ASSERT_FALSE(model.GetServerClusterInfo(ConcreteClusterPath(kInvalidEndpointId, kInvalidClusterId)).has_value()); + ASSERT_FALSE(model.GetServerClusterInfo(ConcreteClusterPath(kInvalidEndpointId, MockClusterId(1))).has_value()); + ASSERT_FALSE(model.GetServerClusterInfo(ConcreteClusterPath(kMockEndpoint1, kInvalidClusterId)).has_value()); + ASSERT_FALSE(model.GetServerClusterInfo(ConcreteClusterPath(kMockEndpoint1, MockClusterId(10))).has_value()); // now get the value - std::optional info = model.GetClusterInfo(ConcreteClusterPath(kMockEndpoint1, MockClusterId(1))); + std::optional info = model.GetServerClusterInfo(ConcreteClusterPath(kMockEndpoint1, MockClusterId(1))); ASSERT_TRUE(info.has_value()); EXPECT_EQ(info->dataVersion, 0u); // NOLINT(bugprone-unchecked-optional-access) EXPECT_EQ(info->flags.Raw(), 0u); // NOLINT(bugprone-unchecked-optional-access) chip::Test::BumpVersion(); - info = model.GetClusterInfo(ConcreteClusterPath(kMockEndpoint1, MockClusterId(1))); + info = model.GetServerClusterInfo(ConcreteClusterPath(kMockEndpoint1, MockClusterId(1))); ASSERT_TRUE(info.has_value()); EXPECT_EQ(info->dataVersion, 1u); // NOLINT(bugprone-unchecked-optional-access) EXPECT_EQ(info->flags.Raw(), 0u); // NOLINT(bugprone-unchecked-optional-access) } +TEST(TestCodegenModelViaMocks, IterateOverClientClusters) +{ + UseMockNodeConfig config(gTestNodeConfig); + CodegenDataModelProviderWithContext model; + + EXPECT_FALSE(model.FirstClientCluster(kEndpointIdThatIsMissing).HasValidIds()); + EXPECT_FALSE(model.FirstClientCluster(kInvalidEndpointId).HasValidIds()); + EXPECT_FALSE(model.NextClientCluster(ConcreteClusterPath(kInvalidEndpointId, 123)).HasValidIds()); + EXPECT_FALSE(model.NextClientCluster(ConcreteClusterPath(kMockEndpoint1, kInvalidClusterId)).HasValidIds()); + EXPECT_FALSE(model.NextClientCluster(ConcreteClusterPath(kMockEndpoint1, 981u)).HasValidIds()); + + // mock endpoint 1 has 2 mock client clusters: 3 and 4 + ConcreteClusterPath path = model.FirstClientCluster(kMockEndpoint1); + ASSERT_TRUE(path.HasValidIds()); + EXPECT_EQ(path.mEndpointId, kMockEndpoint1); + EXPECT_EQ(path.mClusterId, MockClusterId(3)); + + path = model.NextClientCluster(path); + ASSERT_TRUE(path.HasValidIds()); + EXPECT_EQ(path.mEndpointId, kMockEndpoint1); + EXPECT_EQ(path.mClusterId, MockClusterId(4)); + + path = model.NextClientCluster(path); + EXPECT_FALSE(path.HasValidIds()); + + // mock endpoint 2 has 1 mock client clusters: 3(has server side at the same time) and 4 + path = model.FirstClientCluster(kMockEndpoint2); + for (uint16_t clusterId = 3; clusterId <= 4; clusterId++) + { + ASSERT_TRUE(path.HasValidIds()); + EXPECT_EQ(path.mEndpointId, kMockEndpoint2); + EXPECT_EQ(path.mClusterId, MockClusterId(clusterId)); + path = model.NextClientCluster(path); + } + EXPECT_FALSE(path.HasValidIds()); + + // repeat calls should work + for (int i = 0; i < 10; i++) + { + path = model.FirstClientCluster(kMockEndpoint1); + ASSERT_TRUE(path.HasValidIds()); + EXPECT_EQ(path.mEndpointId, kMockEndpoint1); + EXPECT_EQ(path.mClusterId, MockClusterId(3)); + } + + for (int i = 0; i < 10; i++) + { + ConcreteClusterPath nextPath = model.NextClientCluster(path); + ASSERT_TRUE(nextPath.HasValidIds()); + EXPECT_EQ(nextPath.mEndpointId, kMockEndpoint1); + EXPECT_EQ(nextPath.mClusterId, MockClusterId(4)); + } +} + TEST(TestCodegenModelViaMocks, IterateOverAttributes) { UseMockNodeConfig config(gTestNodeConfig); @@ -2569,15 +2709,15 @@ TEST(TestCodegenModelViaMocks, DeviceTypeIteration) // Mock endpoint 1 has 3 device types std::optional entry = model.FirstDeviceType(kMockEndpoint1); ASSERT_EQ(entry, - std::make_optional(DeviceTypeEntry{ .deviceTypeId = kDeviceTypeId1, .deviceTypeVersion = kDeviceTypeId1Version })); + std::make_optional(DeviceTypeEntry{ .deviceTypeId = kDeviceTypeId1, .deviceTypeRevision = kDeviceTypeId1Version })); // NOLINTNEXTLINE(bugprone-unchecked-optional-access): Assert above that this is not none entry = model.NextDeviceType(kMockEndpoint1, *entry); ASSERT_EQ(entry, - std::make_optional(DeviceTypeEntry{ .deviceTypeId = kDeviceTypeId2, .deviceTypeVersion = kDeviceTypeId2Version })); + std::make_optional(DeviceTypeEntry{ .deviceTypeId = kDeviceTypeId2, .deviceTypeRevision = kDeviceTypeId2Version })); // NOLINTNEXTLINE(bugprone-unchecked-optional-access): Assert above that this is not none entry = model.NextDeviceType(kMockEndpoint1, *entry); ASSERT_EQ(entry, - std::make_optional(DeviceTypeEntry{ .deviceTypeId = kDeviceTypeId3, .deviceTypeVersion = kDeviceTypeId3Version })); + std::make_optional(DeviceTypeEntry{ .deviceTypeId = kDeviceTypeId3, .deviceTypeRevision = kDeviceTypeId3Version })); // NOLINTNEXTLINE(bugprone-unchecked-optional-access): Assert above that this is not none entry = model.NextDeviceType(kMockEndpoint1, *entry); ASSERT_FALSE(entry.has_value()); @@ -2585,19 +2725,19 @@ TEST(TestCodegenModelViaMocks, DeviceTypeIteration) // Mock endpoint 2 has 1 device types entry = model.FirstDeviceType(kMockEndpoint2); ASSERT_EQ(entry, - std::make_optional(DeviceTypeEntry{ .deviceTypeId = kDeviceTypeId2, .deviceTypeVersion = kDeviceTypeId2Version })); + std::make_optional(DeviceTypeEntry{ .deviceTypeId = kDeviceTypeId2, .deviceTypeRevision = kDeviceTypeId2Version })); // NOLINTNEXTLINE(bugprone-unchecked-optional-access): Assert above that this is not none entry = model.NextDeviceType(kMockEndpoint2, *entry); ASSERT_FALSE(entry.has_value()); // out of order query works - entry = std::make_optional(DeviceTypeEntry{ .deviceTypeId = kDeviceTypeId2, .deviceTypeVersion = kDeviceTypeId2Version }); + entry = std::make_optional(DeviceTypeEntry{ .deviceTypeId = kDeviceTypeId2, .deviceTypeRevision = kDeviceTypeId2Version }); entry = model.NextDeviceType(kMockEndpoint1, *entry); ASSERT_EQ(entry, - std::make_optional(DeviceTypeEntry{ .deviceTypeId = kDeviceTypeId3, .deviceTypeVersion = kDeviceTypeId3Version })); + std::make_optional(DeviceTypeEntry{ .deviceTypeId = kDeviceTypeId3, .deviceTypeRevision = kDeviceTypeId3Version })); // invalid query fails - entry = std::make_optional(DeviceTypeEntry{ .deviceTypeId = kDeviceTypeId1, .deviceTypeVersion = kDeviceTypeId1Version }); + entry = std::make_optional(DeviceTypeEntry{ .deviceTypeId = kDeviceTypeId1, .deviceTypeRevision = kDeviceTypeId1Version }); entry = model.NextDeviceType(kMockEndpoint2, *entry); ASSERT_FALSE(entry.has_value()); @@ -2605,3 +2745,60 @@ TEST(TestCodegenModelViaMocks, DeviceTypeIteration) entry = model.FirstDeviceType(kMockEndpoint3); ASSERT_FALSE(entry.has_value()); } + +TEST(TestCodegenModelViaMocks, SemanticTagIteration) +{ + UseMockNodeConfig config(gTestNodeConfig); + CodegenDataModelProviderWithContext model; + + // Mock endpoint 1 has 3 semantic tags + std::optional tag = model.GetFirstSemanticTag(kMockEndpoint1); + ASSERT_TRUE(tag.has_value()); + EXPECT_EQ(tag->mfgCode, MakeNullable(VendorId::TestVendor1)); // NOLINT(bugprone-unchecked-optional-access) + EXPECT_EQ(tag->namespaceID, kNamespaceID1); // NOLINT(bugprone-unchecked-optional-access) + EXPECT_EQ(tag->tag, kTag1); // NOLINT(bugprone-unchecked-optional-access) + ASSERT_TRUE(tag->label.HasValue() && (!tag->label.Value().IsNull())); // NOLINT(bugprone-unchecked-optional-access) + EXPECT_TRUE( + tag->label.Value().Value().data_equal(CharSpan::fromCharString(kLabel1))); // NOLINT(bugprone-unchecked-optional-access) + tag = model.GetNextSemanticTag(kMockEndpoint1, *tag); // NOLINT(bugprone-unchecked-optional-access) + ASSERT_TRUE(tag.has_value()); // NOLINT(bugprone-unchecked-optional-access) + EXPECT_TRUE(tag->mfgCode.IsNull()); // NOLINT(bugprone-unchecked-optional-access) + EXPECT_EQ(tag->namespaceID, kNamespaceID2); // NOLINT(bugprone-unchecked-optional-access) + EXPECT_EQ(tag->tag, kTag2); // NOLINT(bugprone-unchecked-optional-access) + ASSERT_TRUE(tag->label.HasValue() && (!tag->label.Value().IsNull())); // NOLINT(bugprone-unchecked-optional-access) + EXPECT_TRUE( + tag->label.Value().Value().data_equal(CharSpan::fromCharString(kLabel2))); // NOLINT(bugprone-unchecked-optional-access) + tag = model.GetNextSemanticTag(kMockEndpoint1, *tag); // NOLINT(bugprone-unchecked-optional-access) + ASSERT_TRUE(tag.has_value()); // NOLINT(bugprone-unchecked-optional-access) + EXPECT_EQ(tag->mfgCode, MakeNullable(VendorId::TestVendor3)); // NOLINT(bugprone-unchecked-optional-access) + EXPECT_EQ(tag->namespaceID, kNamespaceID3); // NOLINT(bugprone-unchecked-optional-access) + EXPECT_EQ(tag->tag, kTag3); // NOLINT(bugprone-unchecked-optional-access) + EXPECT_FALSE(tag->label.HasValue()); // NOLINT(bugprone-unchecked-optional-access) + tag = model.GetNextSemanticTag(kMockEndpoint1, *tag); // NOLINT(bugprone-unchecked-optional-access) + EXPECT_FALSE(tag.has_value()); + + // out of order query works + DataModel::Provider::SemanticTag existTag = { + .mfgCode = MakeNullable(VendorId::TestVendor1), + .namespaceID = kNamespaceID1, + .tag = kTag1, + .label = MakeOptional(MakeNullable(CharSpan::fromCharString(kLabel1))), + }; + tag = model.GetNextSemanticTag(kMockEndpoint1, existTag); + ASSERT_TRUE(tag.has_value()); + EXPECT_TRUE(tag->mfgCode.IsNull()); // NOLINT(bugprone-unchecked-optional-access) + EXPECT_EQ(tag->namespaceID, kNamespaceID2); // NOLINT(bugprone-unchecked-optional-access) + EXPECT_EQ(tag->tag, kTag2); // NOLINT(bugprone-unchecked-optional-access) + ASSERT_TRUE(tag->label.HasValue() && (!tag->label.Value().IsNull())); // NOLINT(bugprone-unchecked-optional-access) + EXPECT_TRUE( + tag->label.Value().Value().data_equal(CharSpan::fromCharString(kLabel2))); // NOLINT(bugprone-unchecked-optional-access) + + // invalid query fails + existTag.tag = kTag2; + tag = model.GetNextSemanticTag(kMockEndpoint1, existTag); + ASSERT_FALSE(tag.has_value()); + + // empty endpoint works + tag = model.GetFirstSemanticTag(kMockEndpoint2); + ASSERT_FALSE(tag.has_value()); +} diff --git a/src/app/data-model-provider/MetadataTypes.cpp b/src/app/data-model-provider/MetadataTypes.cpp index ed3e2667ddc9d7..2729698c49b1ed 100644 --- a/src/app/data-model-provider/MetadataTypes.cpp +++ b/src/app/data-model-provider/MetadataTypes.cpp @@ -30,12 +30,14 @@ const ClusterEntry ClusterEntry::kInvalid{ .info = ClusterInfo(0 /* version */), // version of invalid cluster entry does not matter }; +const EndpointEntry EndpointEntry::kInvalid{ .id = kInvalidEndpointId, .info = EndpointInfo(kInvalidEndpointId) }; + // A default implementation if just first/next exist bool ProviderMetadataTree::EndpointExists(EndpointId endpoint) { - for (EndpointId id = FirstEndpoint(); id != kInvalidEndpointId; id = NextEndpoint(id)) + for (EndpointEntry ep = FirstEndpoint(); ep.IsValid(); ep = NextEndpoint(ep.id)) { - if (id == endpoint) + if (ep.id == endpoint) { return true; } diff --git a/src/app/data-model-provider/MetadataTypes.h b/src/app/data-model-provider/MetadataTypes.h index c1d173c985ee7a..ab9005412e5261 100644 --- a/src/app/data-model-provider/MetadataTypes.h +++ b/src/app/data-model-provider/MetadataTypes.h @@ -20,16 +20,46 @@ #include #include +#include #include #include #include +#include #include #include +#include namespace chip { namespace app { namespace DataModel { +enum class EndpointCompositionPattern : uint8_t +{ + kTreePattern = 0x1, + kFullFamilyPattern = 0x2, +}; + +struct EndpointInfo +{ + // kInvalidEndpointId if there is no explicit parent endpoint (which means the parent is endpoint 0, + // for endpoints other than endpoint 0). + EndpointId parentId; + EndpointCompositionPattern compositionPattern; + + explicit EndpointInfo(EndpointId parent) : parentId(parent), compositionPattern(EndpointCompositionPattern::kFullFamilyPattern) + {} + explicit EndpointInfo(EndpointId parent, EndpointCompositionPattern pattern) : parentId(parent), compositionPattern(pattern) {} +}; + +struct EndpointEntry +{ + EndpointId id; + EndpointInfo info; + + bool IsValid() const { return id != kInvalidEndpointId; } + static const EndpointEntry kInvalid; +}; + enum class ClusterQualityFlags : uint32_t { kDiagnosticsData = 0x0001, // `K` quality, may be filtered out in subscriptions @@ -111,11 +141,11 @@ struct CommandEntry struct DeviceTypeEntry { DeviceTypeId deviceTypeId; - uint8_t deviceTypeVersion; + uint8_t deviceTypeRevision; bool operator==(const DeviceTypeEntry & other) const { - return (deviceTypeId == other.deviceTypeId) && (deviceTypeVersion == other.deviceTypeVersion); + return (deviceTypeId == other.deviceTypeId) && (deviceTypeRevision == other.deviceTypeRevision); } }; @@ -140,18 +170,31 @@ class ProviderMetadataTree public: virtual ~ProviderMetadataTree() = default; - virtual EndpointId FirstEndpoint() = 0; - virtual EndpointId NextEndpoint(EndpointId before) = 0; + // This iteration will list all the endpoints in the data model + virtual EndpointEntry FirstEndpoint() = 0; + virtual EndpointEntry NextEndpoint(EndpointId before) = 0; + virtual std::optional GetEndpointInfo(EndpointId id) = 0; virtual bool EndpointExists(EndpointId id); // This iteration describes device types registered on an endpoint virtual std::optional FirstDeviceType(EndpointId endpoint) = 0; virtual std::optional NextDeviceType(EndpointId endpoint, const DeviceTypeEntry & previous) = 0; - // This iteration will list all clusters on a given endpoint - virtual ClusterEntry FirstCluster(EndpointId endpoint) = 0; - virtual ClusterEntry NextCluster(const ConcreteClusterPath & before) = 0; - virtual std::optional GetClusterInfo(const ConcreteClusterPath & path) = 0; + // This iteration describes semantic tags registered on an endpoint + using SemanticTag = Clusters::Descriptor::Structs::SemanticTagStruct::Type; + virtual std::optional GetFirstSemanticTag(EndpointId endpoint) = 0; + virtual std::optional GetNextSemanticTag(EndpointId endpoint, const SemanticTag & previous) = 0; + + // This iteration will list all server clusters on a given endpoint + virtual ClusterEntry FirstServerCluster(EndpointId endpoint) = 0; + virtual ClusterEntry NextServerCluster(const ConcreteClusterPath & before) = 0; + virtual std::optional GetServerClusterInfo(const ConcreteClusterPath & path) = 0; + + // This iteration will list all client clusters on a given endpoint + // As the client cluster is only a client without any attributes/commands, + // these functions only return the cluster path. + virtual ConcreteClusterPath FirstClientCluster(EndpointId endpoint) = 0; + virtual ConcreteClusterPath NextClientCluster(const ConcreteClusterPath & before) = 0; // Attribute iteration and accessors provide cluster-level access over // attributes diff --git a/src/app/dynamic_server/DynamicDispatcher.cpp b/src/app/dynamic_server/DynamicDispatcher.cpp index ba4525e2fc7add..634055a9851a6d 100644 --- a/src/app/dynamic_server/DynamicDispatcher.cpp +++ b/src/app/dynamic_server/DynamicDispatcher.cpp @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -274,6 +275,28 @@ Protocols::InteractionModel::Status emAfReadOrWriteAttribute(const EmberAfAttrib return Protocols::InteractionModel::Status::UnsupportedAttribute; } +namespace chip { +namespace app { + +EndpointComposition GetCompositionForEndpointIndex(uint16_t endpointIndex) +{ + return EndpointComposition::kFullFamily; +} + +} // namespace app +} // namespace chip + +EndpointId emberAfParentEndpointFromIndex(uint16_t index) +{ + return kInvalidEndpointId; +} + +CHIP_ERROR GetSemanticTagForEndpointAtIndex(EndpointId endpoint, size_t index, + Clusters::Descriptor::Structs::SemanticTagStruct::Type & tag) +{ + return CHIP_ERROR_NOT_FOUND; +} + void emberAfAttributeChanged(EndpointId endpoint, ClusterId clusterId, AttributeId attributeId, AttributesChangedListener * listener) { diff --git a/src/app/reporting/Engine.cpp b/src/app/reporting/Engine.cpp index 63d71bfc92db7a..e2691e519ac13d 100644 --- a/src/app/reporting/Engine.cpp +++ b/src/app/reporting/Engine.cpp @@ -51,7 +51,7 @@ using Protocols::InteractionModel::Status; Status EventPathValid(DataModel::Provider * model, const ConcreteEventPath & eventPath) { - if (!model->GetClusterInfo(eventPath).has_value()) + if (!model->GetServerClusterInfo(eventPath).has_value()) { return model->EndpointExists(eventPath.mEndpointId) ? Status::UnsupportedCluster : Status::UnsupportedEndpoint; } @@ -148,7 +148,7 @@ DataModel::ActionReturnStatus RetrieveClusterData(DataModel::Provider * dataMode readRequest.path = path; DataVersion version = 0; - if (std::optional clusterInfo = dataModel->GetClusterInfo(path); clusterInfo.has_value()) + if (std::optional clusterInfo = dataModel->GetServerClusterInfo(path); clusterInfo.has_value()) { version = clusterInfo->dataVersion; } @@ -208,7 +208,7 @@ DataModel::ActionReturnStatus RetrieveClusterData(DataModel::Provider * dataMode bool IsClusterDataVersionEqualTo(DataModel::Provider * dataModel, const ConcreteClusterPath & path, DataVersion dataVersion) { - std::optional info = dataModel->GetClusterInfo(path); + std::optional info = dataModel->GetServerClusterInfo(path); if (!info.has_value()) { return false; diff --git a/src/app/tests/test-interaction-model-api.cpp b/src/app/tests/test-interaction-model-api.cpp index d263e251d2da7d..867d4c895ebf55 100644 --- a/src/app/tests/test-interaction-model-api.cpp +++ b/src/app/tests/test-interaction-model-api.cpp @@ -149,16 +149,21 @@ std::optional TestImCustomDataModel::Invoke(const InvokeRequ return std::make_optional(CHIP_ERROR_NOT_IMPLEMENTED); } -EndpointId TestImCustomDataModel::FirstEndpoint() +DataModel::EndpointEntry TestImCustomDataModel::FirstEndpoint() { return CodegenDataModelProviderInstance()->FirstEndpoint(); } -EndpointId TestImCustomDataModel::NextEndpoint(EndpointId before) +DataModel::EndpointEntry TestImCustomDataModel::NextEndpoint(EndpointId before) { return CodegenDataModelProviderInstance()->NextEndpoint(before); } +std::optional TestImCustomDataModel::GetEndpointInfo(EndpointId endpoint) +{ + return CodegenDataModelProviderInstance()->GetEndpointInfo(endpoint); +} + std::optional TestImCustomDataModel::FirstDeviceType(EndpointId endpoint) { return std::nullopt; @@ -170,19 +175,40 @@ std::optional TestImCustomDataModel::NextDeviceType( return std::nullopt; } -ClusterEntry TestImCustomDataModel::FirstCluster(EndpointId endpoint) +std::optional TestImCustomDataModel::GetFirstSemanticTag(EndpointId endpoint) +{ + return std::nullopt; +} + +std::optional TestImCustomDataModel::GetNextSemanticTag(EndpointId endpoint, + const SemanticTag & previous) +{ + return std::nullopt; +} + +ClusterEntry TestImCustomDataModel::FirstServerCluster(EndpointId endpoint) +{ + return CodegenDataModelProviderInstance()->FirstServerCluster(endpoint); +} + +ClusterEntry TestImCustomDataModel::NextServerCluster(const ConcreteClusterPath & before) +{ + return CodegenDataModelProviderInstance()->NextServerCluster(before); +} + +std::optional TestImCustomDataModel::GetServerClusterInfo(const ConcreteClusterPath & path) { - return CodegenDataModelProviderInstance()->FirstCluster(endpoint); + return CodegenDataModelProviderInstance()->GetServerClusterInfo(path); } -ClusterEntry TestImCustomDataModel::NextCluster(const ConcreteClusterPath & before) +ConcreteClusterPath TestImCustomDataModel::FirstClientCluster(EndpointId endpoint) { - return CodegenDataModelProviderInstance()->NextCluster(before); + return CodegenDataModelProviderInstance()->FirstClientCluster(endpoint); } -std::optional TestImCustomDataModel::GetClusterInfo(const ConcreteClusterPath & path) +ConcreteClusterPath TestImCustomDataModel::NextClientCluster(const ConcreteClusterPath & before) { - return CodegenDataModelProviderInstance()->GetClusterInfo(path); + return CodegenDataModelProviderInstance()->NextClientCluster(before); } AttributeEntry TestImCustomDataModel::FirstAttribute(const ConcreteClusterPath & cluster) diff --git a/src/app/tests/test-interaction-model-api.h b/src/app/tests/test-interaction-model-api.h index 0e0fd2c0e5b661..d382ccd8090a0a 100644 --- a/src/app/tests/test-interaction-model-api.h +++ b/src/app/tests/test-interaction-model-api.h @@ -110,14 +110,19 @@ class TestImCustomDataModel : public DataModel::Provider std::optional Invoke(const DataModel::InvokeRequest & request, chip::TLV::TLVReader & input_arguments, CommandHandler * handler) override; - EndpointId FirstEndpoint() override; - EndpointId NextEndpoint(EndpointId before) override; + DataModel::EndpointEntry FirstEndpoint() override; + DataModel::EndpointEntry NextEndpoint(EndpointId before) override; + std::optional GetEndpointInfo(EndpointId endpoint) override; std::optional FirstDeviceType(EndpointId endpoint) override; std::optional NextDeviceType(EndpointId endpoint, const DataModel::DeviceTypeEntry & previous) override; - DataModel::ClusterEntry FirstCluster(EndpointId endpoint) override; - DataModel::ClusterEntry NextCluster(const ConcreteClusterPath & before) override; - std::optional GetClusterInfo(const ConcreteClusterPath & path) override; + std::optional GetFirstSemanticTag(EndpointId endpoint) override; + std::optional GetNextSemanticTag(EndpointId endpoint, const SemanticTag & previous) override; + DataModel::ClusterEntry FirstServerCluster(EndpointId endpoint) override; + DataModel::ClusterEntry NextServerCluster(const ConcreteClusterPath & before) override; + std::optional GetServerClusterInfo(const ConcreteClusterPath & path) override; + ConcreteClusterPath FirstClientCluster(EndpointId endpoint) override; + ConcreteClusterPath NextClientCluster(const ConcreteClusterPath & before) override; DataModel::AttributeEntry FirstAttribute(const ConcreteClusterPath & cluster) override; DataModel::AttributeEntry NextAttribute(const ConcreteAttributePath & before) override; std::optional GetAttributeInfo(const ConcreteAttributePath & path) override; diff --git a/src/app/util/af-types.h b/src/app/util/af-types.h index 04275a2515c23c..e3559069ed9df3 100644 --- a/src/app/util/af-types.h +++ b/src/app/util/af-types.h @@ -120,6 +120,8 @@ struct EmberAfCluster uint16_t eventCount; bool IsServer() const { return (mask & CLUSTER_MASK_SERVER) != 0; } + + bool IsClient() const { return (mask & CLUSTER_MASK_CLIENT) != 0; } }; /** diff --git a/src/app/util/attribute-storage.cpp b/src/app/util/attribute-storage.cpp index 4d9cc2368f6900..3df2ba7c6676aa 100644 --- a/src/app/util/attribute-storage.cpp +++ b/src/app/util/attribute-storage.cpp @@ -1415,6 +1415,20 @@ bool IsTreeCompositionForEndpoint(EndpointId endpoint) return emAfEndpoints[index].bitmask.Has(EmberAfEndpointOptions::isTreeComposition); } +EndpointComposition GetCompositionForEndpointIndex(uint16_t endpointIndex) +{ + VerifyOrReturnValue(endpointIndex < ArraySize(emAfEndpoints), EndpointComposition::kInvalid); + if (emAfEndpoints[endpointIndex].bitmask.Has(EmberAfEndpointOptions::isFlatComposition)) + { + return EndpointComposition::kFullFamily; + } + if (emAfEndpoints[endpointIndex].bitmask.Has(EmberAfEndpointOptions::isTreeComposition)) + { + return EndpointComposition::kTree; + } + return EndpointComposition::kInvalid; +} + } // namespace app } // namespace chip diff --git a/src/app/util/attribute-storage.h b/src/app/util/attribute-storage.h index 711f6a7cff768d..6930db7a965ea2 100644 --- a/src/app/util/attribute-storage.h +++ b/src/app/util/attribute-storage.h @@ -378,5 +378,17 @@ bool IsFlatCompositionForEndpoint(EndpointId endpoint); */ bool IsTreeCompositionForEndpoint(EndpointId endpoint); +enum class EndpointComposition : uint8_t +{ + kFullFamily, + kTree, + kInvalid, +}; + +/** + * @brief Returns the composition for a given endpoint index + */ +EndpointComposition GetCompositionForEndpointIndex(uint16_t index); + } // namespace app } // namespace chip diff --git a/src/app/util/mock/MockNodeConfig.cpp b/src/app/util/mock/MockNodeConfig.cpp index c6572ed0aef075..bb919318e3cbb7 100644 --- a/src/app/util/mock/MockNodeConfig.cpp +++ b/src/app/util/mock/MockNodeConfig.cpp @@ -115,7 +115,7 @@ const T * findById(const std::vector & vector, decltype(std::declval().id) MockClusterConfig::MockClusterConfig(ClusterId aId, std::initializer_list aAttributes, std::initializer_list aEvents, std::initializer_list aAcceptedCommands, - std::initializer_list aGeneratedCommands) : + std::initializer_list aGeneratedCommands, BitMask side) : id(aId), attributes(aAttributes), events(aEvents), mEmberCluster{}, mAcceptedCommands(aAcceptedCommands), mGeneratedCommands(aGeneratedCommands) @@ -127,9 +127,17 @@ MockClusterConfig::MockClusterConfig(ClusterId aId, std::initializer_list(attributes.size()); - mEmberCluster.mask = CLUSTER_MASK_SERVER; mEmberCluster.eventCount = static_cast(mEmberEventList.size()); mEmberCluster.eventList = mEmberEventList.data(); @@ -177,9 +185,11 @@ const MockAttributeConfig * MockClusterConfig::attributeById(AttributeId attribu } MockEndpointConfig::MockEndpointConfig(EndpointId aId, std::initializer_list aClusters, - std::initializer_list aDeviceTypes) : + std::initializer_list aDeviceTypes, + std::initializer_list aTags, + app::EndpointComposition aComposition) : id(aId), - clusters(aClusters), mDeviceTypes(aDeviceTypes), mEmberEndpoint{} + composition(aComposition), clusters(aClusters), mDeviceTypes(aDeviceTypes), mSemanticTags(aTags), mEmberEndpoint{} { VerifyOrDie(aClusters.size() < UINT8_MAX); @@ -193,8 +203,8 @@ MockEndpointConfig::MockEndpointConfig(EndpointId aId, std::initializer_list #include +#include #include #include @@ -74,11 +75,18 @@ struct MockEventConfig const EventId id; }; +enum class MockClusterSide : uint8_t +{ + kServer = 0x1, + kClient = 0x2, +}; + struct MockClusterConfig { MockClusterConfig(ClusterId aId, std::initializer_list aAttributes = {}, std::initializer_list aEvents = {}, std::initializer_list aAcceptedCommands = {}, - std::initializer_list aGeneratedCommands = {}); + std::initializer_list aGeneratedCommands = {}, + BitMask side = BitMask().Set(MockClusterSide::kServer)); // Cluster-config is self-referential: mEmberCluster.attributes references mAttributeMetaData.data() MockClusterConfig(const MockClusterConfig & other); @@ -102,7 +110,9 @@ struct MockClusterConfig struct MockEndpointConfig { MockEndpointConfig(EndpointId aId, std::initializer_list aClusters = {}, - std::initializer_list aDeviceTypes = {}); + std::initializer_list aDeviceTypes = {}, + std::initializer_list aTags = {}, + app::EndpointComposition composition = app::EndpointComposition::kFullFamily); // Endpoint-config is self-referential: mEmberEndpoint.clusters references mEmberClusters.data() MockEndpointConfig(const MockEndpointConfig & other); @@ -115,12 +125,19 @@ struct MockEndpointConfig return Span(mDeviceTypes.data(), mDeviceTypes.size()); } + Span semanticTags() const + { + return Span(mSemanticTags.data(), mSemanticTags.size()); + } + const EndpointId id; + const app::EndpointComposition composition; const std::vector clusters; private: std::vector mEmberClusters; std::vector mDeviceTypes; + std::vector mSemanticTags; EmberAfEndpointType mEmberEndpoint; }; diff --git a/src/app/util/mock/attribute-storage.cpp b/src/app/util/mock/attribute-storage.cpp index 57f3d1e5216264..f41ba4de69fb3a 100644 --- a/src/app/util/mock/attribute-storage.cpp +++ b/src/app/util/mock/attribute-storage.cpp @@ -237,6 +237,39 @@ chip::EndpointId emberAfEndpointFromIndex(uint16_t index) return config.endpoints[index].id; } +namespace chip { +namespace app { + +EndpointComposition GetCompositionForEndpointIndex(uint16_t endpointIndex) +{ + return GetMockNodeConfig().endpoints[endpointIndex].composition; +} + +} // namespace app +} // namespace chip + +EndpointId emberAfParentEndpointFromIndex(uint16_t index) +{ + return kInvalidEndpointId; +} + +CHIP_ERROR GetSemanticTagForEndpointAtIndex(EndpointId endpoint, size_t index, + Clusters::Descriptor::Structs::SemanticTagStruct::Type & tag) +{ + auto ep = GetMockNodeConfig().endpointById(endpoint); + + if (ep) + { + auto semanticTags = ep->semanticTags(); + if (index < semanticTags.size()) + { + tag = semanticTags[index]; + return CHIP_NO_ERROR; + } + } + return CHIP_ERROR_NOT_FOUND; +} + chip::Optional emberAfGetNthClusterId(chip::EndpointId endpointId, uint8_t n, bool server) { VerifyOrReturnValue(server, NullOptional); // only server clusters supported diff --git a/src/controller/tests/data_model/DataModelFixtures.cpp b/src/controller/tests/data_model/DataModelFixtures.cpp index 6f42c38a7789e4..7ef9975bdfddcd 100644 --- a/src/controller/tests/data_model/DataModelFixtures.cpp +++ b/src/controller/tests/data_model/DataModelFixtures.cpp @@ -474,16 +474,21 @@ std::optional CustomDataModel::Invoke(const InvokeRequest & return std::nullopt; // handler status is set by the dispatch } -EndpointId CustomDataModel::FirstEndpoint() +DataModel::EndpointEntry CustomDataModel::FirstEndpoint() { return CodegenDataModelProviderInstance()->FirstEndpoint(); } -EndpointId CustomDataModel::NextEndpoint(EndpointId before) +DataModel::EndpointEntry CustomDataModel::NextEndpoint(EndpointId before) { return CodegenDataModelProviderInstance()->NextEndpoint(before); } +std::optional CustomDataModel::GetEndpointInfo(EndpointId endpoint) +{ + return CodegenDataModelProviderInstance()->GetEndpointInfo(endpoint); +} + std::optional CustomDataModel::FirstDeviceType(EndpointId endpoint) { return std::nullopt; @@ -495,19 +500,40 @@ std::optional CustomDataModel::NextDeviceType(Endpoi return std::nullopt; } -ClusterEntry CustomDataModel::FirstCluster(EndpointId endpoint) +std::optional CustomDataModel::GetFirstSemanticTag(EndpointId endpoint) +{ + return std::nullopt; +} + +std::optional CustomDataModel::GetNextSemanticTag(EndpointId endpoint, + const SemanticTag & previous) +{ + return std::nullopt; +} + +ClusterEntry CustomDataModel::FirstServerCluster(EndpointId endpoint) +{ + return CodegenDataModelProviderInstance()->FirstServerCluster(endpoint); +} + +ClusterEntry CustomDataModel::NextServerCluster(const ConcreteClusterPath & before) +{ + return CodegenDataModelProviderInstance()->NextServerCluster(before); +} + +std::optional CustomDataModel::GetServerClusterInfo(const ConcreteClusterPath & path) { - return CodegenDataModelProviderInstance()->FirstCluster(endpoint); + return CodegenDataModelProviderInstance()->GetServerClusterInfo(path); } -ClusterEntry CustomDataModel::NextCluster(const ConcreteClusterPath & before) +ConcreteClusterPath CustomDataModel::FirstClientCluster(EndpointId endpoint) { - return CodegenDataModelProviderInstance()->NextCluster(before); + return CodegenDataModelProviderInstance()->FirstClientCluster(endpoint); } -std::optional CustomDataModel::GetClusterInfo(const ConcreteClusterPath & path) +ConcreteClusterPath CustomDataModel::NextClientCluster(const ConcreteClusterPath & before) { - return CodegenDataModelProviderInstance()->GetClusterInfo(path); + return CodegenDataModelProviderInstance()->NextClientCluster(before); } AttributeEntry CustomDataModel::FirstAttribute(const ConcreteClusterPath & cluster) diff --git a/src/controller/tests/data_model/DataModelFixtures.h b/src/controller/tests/data_model/DataModelFixtures.h index e9b32aead650ee..c8136751c87ea1 100644 --- a/src/controller/tests/data_model/DataModelFixtures.h +++ b/src/controller/tests/data_model/DataModelFixtures.h @@ -122,14 +122,19 @@ class CustomDataModel : public DataModel::Provider std::optional Invoke(const DataModel::InvokeRequest & request, chip::TLV::TLVReader & input_arguments, CommandHandler * handler) override; - EndpointId FirstEndpoint() override; - EndpointId NextEndpoint(EndpointId before) override; + DataModel::EndpointEntry FirstEndpoint() override; + DataModel::EndpointEntry NextEndpoint(EndpointId before) override; + std::optional GetEndpointInfo(EndpointId endpoint) override; std::optional FirstDeviceType(EndpointId endpoint) override; std::optional NextDeviceType(EndpointId endpoint, const DataModel::DeviceTypeEntry & previous) override; - DataModel::ClusterEntry FirstCluster(EndpointId endpoint) override; - DataModel::ClusterEntry NextCluster(const ConcreteClusterPath & before) override; - std::optional GetClusterInfo(const ConcreteClusterPath & path) override; + std::optional GetFirstSemanticTag(EndpointId endpoint) override; + std::optional GetNextSemanticTag(EndpointId endpoint, const SemanticTag & previous) override; + DataModel::ClusterEntry FirstServerCluster(EndpointId endpoint) override; + DataModel::ClusterEntry NextServerCluster(const ConcreteClusterPath & before) override; + std::optional GetServerClusterInfo(const ConcreteClusterPath & path) override; + ConcreteClusterPath FirstClientCluster(EndpointId endpoint) override; + ConcreteClusterPath NextClientCluster(const ConcreteClusterPath & before) override; DataModel::AttributeEntry FirstAttribute(const ConcreteClusterPath & cluster) override; DataModel::AttributeEntry NextAttribute(const ConcreteAttributePath & before) override; std::optional GetAttributeInfo(const ConcreteAttributePath & path) override;