From a609e596cfbe2133f6d2448489d60524efd49dd3 Mon Sep 17 00:00:00 2001 From: Terence Hampson Date: Fri, 16 Feb 2024 13:36:29 -0500 Subject: [PATCH 001/385] Add nlfaultinjection version of the all clusters app (#32179) --- integrations/docker/images/chip-cert-bins/Dockerfile | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/integrations/docker/images/chip-cert-bins/Dockerfile b/integrations/docker/images/chip-cert-bins/Dockerfile index 553b3d65718e16..33662e66d3a9ba 100644 --- a/integrations/docker/images/chip-cert-bins/Dockerfile +++ b/integrations/docker/images/chip-cert-bins/Dockerfile @@ -180,6 +180,7 @@ RUN case ${TARGETPLATFORM} in \ --target linux-x64-shell-ipv6only-platform-mdns \ --target linux-x64-chip-cert-ipv6only-platform-mdns \ --target linux-x64-all-clusters-ipv6only \ + --target linux-x64-all-clusters-ipv6only-nlfaultinject \ --target linux-x64-all-clusters-minimal-ipv6only \ --target linux-x64-bridge-ipv6only \ --target linux-x64-tv-app-ipv6only \ @@ -198,6 +199,7 @@ RUN case ${TARGETPLATFORM} in \ && mv out/linux-x64-shell-ipv6only-platform-mdns/chip-shell out/chip-shell \ && mv out/linux-x64-chip-cert-ipv6only-platform-mdns/chip-cert out/chip-cert \ && mv out/linux-x64-all-clusters-ipv6only/chip-all-clusters-app out/chip-all-clusters-app \ + && mv out/linux-x64-all-clusters-ipv6only-nlfaultinject/chip-all-clusters-app out/chip-all-clusters-app-nlfaultinject \ && mv out/linux-x64-all-clusters-minimal-ipv6only/chip-all-clusters-minimal-app out/chip-all-clusters-minimal-app \ && mv out/linux-x64-bridge-ipv6only/chip-bridge-app out/chip-bridge-app \ && mv out/linux-x64-tv-app-ipv6only/chip-tv-app out/chip-tv-app \ @@ -220,6 +222,7 @@ RUN case ${TARGETPLATFORM} in \ --target linux-arm64-shell-ipv6only-platform-mdns \ --target linux-arm64-chip-cert-ipv6only-platform-mdns \ --target linux-arm64-all-clusters-ipv6only \ + --target linux-arm64-all-clusters-ipv6only-nlfaultinject \ --target linux-arm64-all-clusters-minimal-ipv6only \ --target linux-arm64-bridge-ipv6only \ --target linux-arm64-tv-app-ipv6only \ @@ -238,6 +241,7 @@ RUN case ${TARGETPLATFORM} in \ && mv out/linux-arm64-shell-ipv6only-platform-mdns/chip-shell out/chip-shell \ && mv out/linux-arm64-chip-cert-ipv6only-platform-mdns/chip-cert out/chip-cert \ && mv out/linux-arm64-all-clusters-ipv6only/chip-all-clusters-app out/chip-all-clusters-app \ + && mv out/linux-arm64-all-clusters-ipv6only-nlfaultinject/chip-all-clusters-app out/chip-all-clusters-app-nlfaultinject \ && mv out/linux-arm64-all-clusters-minimal-ipv6only/chip-all-clusters-minimal-app out/chip-all-clusters-minimal-app \ && mv out/linux-arm64-bridge-ipv6only/chip-bridge-app out/chip-bridge-app \ && mv out/linux-arm64-tv-app-ipv6only/chip-tv-app out/chip-tv-app \ @@ -269,6 +273,7 @@ COPY --from=chip-build-cert-bins /root/connectedhomeip/out/chip-tool chip-tool COPY --from=chip-build-cert-bins /root/connectedhomeip/out/chip-shell chip-shell COPY --from=chip-build-cert-bins /root/connectedhomeip/out/chip-cert chip-cert COPY --from=chip-build-cert-bins /root/connectedhomeip/out/chip-all-clusters-app chip-all-clusters-app +COPY --from=chip-build-cert-bins /root/connectedhomeip/out/chip-all-clusters-app-nlfaultinject chip-all-clusters-app-nlfaultinject COPY --from=chip-build-cert-bins /root/connectedhomeip/out/chip-all-clusters-minimal-app chip-all-clusters-minimal-app COPY --from=chip-build-cert-bins /root/connectedhomeip/out/chip-lighting-app chip-lighting-app COPY --from=chip-build-cert-bins /root/connectedhomeip/out/chip-tv-casting-app chip-tv-casting-app From d8f53c80d297aedd1b73042be430ee26fd2fd2d8 Mon Sep 17 00:00:00 2001 From: C Freeman Date: Fri, 16 Feb 2024 13:39:18 -0500 Subject: [PATCH 002/385] TC-ACE-2.1/2.2: Remove workaround for fixed scraper bug (#32158) Test: Manually verified the python code gets the correct value from the spec XML now. TC-ACE-2.1 and 2.2 pass. --- src/python_testing/spec_parsing_support.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/python_testing/spec_parsing_support.py b/src/python_testing/spec_parsing_support.py index 3a784178cdb880..3d6cedfb4da8bf 100644 --- a/src/python_testing/spec_parsing_support.py +++ b/src/python_testing/spec_parsing_support.py @@ -512,12 +512,6 @@ def remove_problem(location: typing.Union[CommandPathLocation, FeaturePathLocati 0x05: XmlAttribute(name='SupportedTemperatureLevels', datatype='list', conformance=feature(0x02, 'TL'), read_access=view, write_access=none, write_optional=False), } - # Workaround for incorrect parsing of access control cluster. - # Remove this workaround when https://github.com/csa-data-model/projects/issues/397 is fixed. - acl_id = Clusters.AccessControl.id - clusters[acl_id].attributes[Clusters.AccessControl.Attributes.Acl.attribute_id].write_access = Clusters.AccessControl.Enums.AccessControlEntryPrivilegeEnum.kAdminister - clusters[acl_id].attributes[Clusters.AccessControl.Attributes.Extension.attribute_id].write_access = Clusters.AccessControl.Enums.AccessControlEntryPrivilegeEnum.kAdminister - check_clusters_for_unknown_commands(clusters, problems) return clusters, problems From 39b2382c32129e52ecf394dd487063c7b93f01a5 Mon Sep 17 00:00:00 2001 From: adabreuti <76965454+adabreuti@users.noreply.github.com> Date: Fri, 16 Feb 2024 13:06:21 -0600 Subject: [PATCH 003/385] SHA-256 Stream Clear API to call lower level mbedtls free (#31607) * Update MBEDTLS SHA-256 Clear to call lower level HW implementation * Enable Power maangement for SHA-256 HW accel on TI platforms * Revert "Enable Power maangement for SHA-256 HW accel on TI platforms" This reverts commit db270a368b2c36fb5ddfbbdedc9c733e66d960d0. --- src/crypto/CHIPCryptoPALmbedTLS.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/crypto/CHIPCryptoPALmbedTLS.cpp b/src/crypto/CHIPCryptoPALmbedTLS.cpp index d7e0dee28edea6..4df0ce97e30989 100644 --- a/src/crypto/CHIPCryptoPALmbedTLS.cpp +++ b/src/crypto/CHIPCryptoPALmbedTLS.cpp @@ -199,8 +199,6 @@ Hash_SHA256_stream::Hash_SHA256_stream() Hash_SHA256_stream::~Hash_SHA256_stream() { - mbedtls_sha256_context * context = to_inner_hash_sha256_context(&mContext); - mbedtls_sha256_free(context); Clear(); } @@ -272,6 +270,9 @@ CHIP_ERROR Hash_SHA256_stream::Finish(MutableByteSpan & out_buffer) void Hash_SHA256_stream::Clear() { + mbedtls_sha256_context * context = to_inner_hash_sha256_context(&mContext); + mbedtls_sha256_free(context); + mbedtls_platform_zeroize(this, sizeof(*this)); } From 573511d733210bb253d9c2014d79a02b7a5671a4 Mon Sep 17 00:00:00 2001 From: Matthew Swartwout Date: Fri, 16 Feb 2024 11:17:32 -0800 Subject: [PATCH 004/385] Delete Concrete(Read|Data)AttributePath equality operator (#32131) * Delete Concrete(Read|Data)AttributePath equality operator Right now these default to using the ConcreteAttributePath equality operator, which is misleading because it will return true for objects which are not actually equal. Replace this with the MatchesConcreteAttributePath function. A new equality operator for these classes will be introduced in a follow-up PR. I'm introducing this change separately to ensure that CI catches any current usage of the equality operator. * Restyled by clang-format * Add unit tests * Restyled by clang-format --------- Co-authored-by: Restyled.io --- src/app/ConcreteAttributePath.h | 10 +++ src/app/ReadClient.cpp | 5 +- src/app/tests/BUILD.gn | 1 + src/app/tests/TestConcreteAttributePath.cpp | 94 +++++++++++++++++++++ 4 files changed, 107 insertions(+), 3 deletions(-) create mode 100644 src/app/tests/TestConcreteAttributePath.cpp diff --git a/src/app/ConcreteAttributePath.h b/src/app/ConcreteAttributePath.h index 076575dcafa2a1..253b590ef90739 100644 --- a/src/app/ConcreteAttributePath.h +++ b/src/app/ConcreteAttributePath.h @@ -87,6 +87,10 @@ struct ConcreteReadAttributePath : public ConcreteAttributePath mListIndex.SetValue(aListIndex); } + bool operator==(const ConcreteReadAttributePath & aOther) const = delete; + bool operator!=(const ConcreteReadAttributePath & aOther) const = delete; + bool operator<(const ConcreteReadAttributePath & aOther) const = delete; + Optional mListIndex; }; @@ -138,6 +142,12 @@ struct ConcreteDataAttributePath : public ConcreteAttributePath ChipLogValueMEI(mClusterId), ChipLogValueMEI(mAttributeId)); } + bool MatchesConcreteAttributePath(const ConcreteAttributePath & aOther) { return ConcreteAttributePath::operator==(aOther); } + + bool operator==(const ConcreteDataAttributePath & aOther) const = delete; + bool operator!=(const ConcreteDataAttributePath & aOther) const = delete; + bool operator<(const ConcreteDataAttributePath & aOther) const = delete; + // // This index is only valid if `mListOp` is set to a list item operation, i.e // ReplaceItem, DeleteItem or AppendItem. Otherwise, it is to be ignored. diff --git a/src/app/ReadClient.cpp b/src/app/ReadClient.cpp index 4a123fe01b6291..57ef57362a25fa 100644 --- a/src/app/ReadClient.cpp +++ b/src/app/ReadClient.cpp @@ -799,9 +799,8 @@ CHIP_ERROR ReadClient::ProcessAttributeReportIBs(TLV::TLVReader & aAttributeRepo attributePath.mListOp = ConcreteDataAttributePath::ListOperation::ReplaceAll; } - if (attributePath == - ConcreteDataAttributePath(kRootEndpointId, Clusters::IcdManagement::Id, - Clusters::IcdManagement::Attributes::OperatingMode::Id)) + if (attributePath.MatchesConcreteAttributePath(ConcreteAttributePath( + kRootEndpointId, Clusters::IcdManagement::Id, Clusters::IcdManagement::Attributes::OperatingMode::Id))) { PeerType peerType; TLV::TLVReader operatingModeTlvReader; diff --git a/src/app/tests/BUILD.gn b/src/app/tests/BUILD.gn index be78dd8ade9e54..e4ab60329f218e 100644 --- a/src/app/tests/BUILD.gn +++ b/src/app/tests/BUILD.gn @@ -135,6 +135,7 @@ chip_test_suite_using_nltest("tests") { "TestClusterInfo.cpp", "TestCommandInteraction.cpp", "TestCommandPathParams.cpp", + "TestConcreteAttributePath.cpp", "TestDataModelSerialization.cpp", "TestDefaultOTARequestorStorage.cpp", "TestEventLoggingNoUTCTime.cpp", diff --git a/src/app/tests/TestConcreteAttributePath.cpp b/src/app/tests/TestConcreteAttributePath.cpp new file mode 100644 index 00000000000000..6e3451be26a78f --- /dev/null +++ b/src/app/tests/TestConcreteAttributePath.cpp @@ -0,0 +1,94 @@ +/* + * + * Copyright (c) 2024 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 +#include +#include + +using namespace chip; +using namespace chip::app; + +namespace { + +void TestConcreteAttributePathEqualityDefaultConstructor(nlTestSuite * aSuite, void * aContext) +{ + ConcreteAttributePath path_one; + ConcreteAttributePath path_two; + NL_TEST_ASSERT(aSuite, path_one == path_two); +} + +void TestConcreteAttributePathEquality(nlTestSuite * aSuite, void * aContext) +{ + ConcreteAttributePath path_one(/*aEndpointId=*/1, /*aClusterId=*/2, /*aAttributeId=*/3); + ConcreteAttributePath path_two(/*aEndpointId=*/1, /*aClusterId=*/2, /*aAttributeId=*/3); + NL_TEST_ASSERT(aSuite, path_one == path_two); +} + +void TestConcreteAttributePathInequalityDifferentAttributeId(nlTestSuite * aSuite, void * aContext) +{ + ConcreteAttributePath path_one(/*aEndpointId=*/1, /*aClusterId=*/2, /*aAttributeId=*/3); + ConcreteAttributePath path_two(/*aEndpointId=*/1, /*aClusterId=*/2, /*aAttributeId=*/4); + NL_TEST_ASSERT(aSuite, path_one != path_two); +} + +void TestConcreteDataAttributePathMatchesConcreteAttributePathEquality(nlTestSuite * aSuite, void * aContext) +{ + ConcreteAttributePath path(/*aEndpointId=*/1, /*aClusterId=*/2, /*aAttributeId=*/3); + ConcreteDataAttributePath data_path(/*aEndpointId=*/1, /*aClusterId=*/2, /*aAttributeId=*/3); + ConcreteDataAttributePath data_path_with_version(/*aEndpointId=*/1, /*aClusterId=*/2, /*aAttributeId=*/3, + /*aDataVersion=*/MakeOptional(4U)); + ConcreteDataAttributePath data_path_with_list(/*aEndpointId=*/1, /*aClusterId=*/2, /*aAttributeId=*/3, + /*aListOp=*/ConcreteDataAttributePath::ListOperation::ReplaceAll, + /*aListIndex=*/5U); + + NL_TEST_ASSERT(aSuite, data_path.MatchesConcreteAttributePath(path)); + NL_TEST_ASSERT(aSuite, data_path_with_version.MatchesConcreteAttributePath(path)); + NL_TEST_ASSERT(aSuite, data_path_with_list.MatchesConcreteAttributePath(path)); +} + +void TestConcreteDataAttributePathMatchesConcreteAttributePathInequality(nlTestSuite * aSuite, void * aContext) +{ + ConcreteAttributePath path(/*aEndpointId=*/1, /*aClusterId=*/2, /*aAttributeId=*/3); + ConcreteDataAttributePath data_path(/*aEndpointId=*/1, /*aClusterId=*/2, /*aAttributeId=*/4); + + NL_TEST_ASSERT(aSuite, !data_path.MatchesConcreteAttributePath(path)); +} + +const nlTest sTests[] = { + NL_TEST_DEF("TestConcreteAttributePathEqualityDefaultConstructor", TestConcreteAttributePathEqualityDefaultConstructor), + NL_TEST_DEF("TestConcreteAttributePathEquality", TestConcreteAttributePathEquality), + NL_TEST_DEF("TestConcreteAttributePathInequalityDifferentAttributeId", TestConcreteAttributePathInequalityDifferentAttributeId), + NL_TEST_DEF("TestConcreteDataAttributePathMatchesConcreteAttributePathEquality", + TestConcreteDataAttributePathMatchesConcreteAttributePathEquality), + NL_TEST_DEF("TestConcreteDataAttributePathMatchesConcreteAttributePathInequality", + TestConcreteDataAttributePathMatchesConcreteAttributePathInequality), + NL_TEST_SENTINEL() +}; + +} // anonymous namespace + +int TestConcreteAttributePath() +{ + nlTestSuite theSuite = { "ConcreteAttributePath", &sTests[0], nullptr, nullptr }; + + nlTestRunner(&theSuite, nullptr); + + return (nlTestRunnerStats(&theSuite)); +} + +CHIP_REGISTER_TEST_SUITE(TestConcreteAttributePath) From 2d3a221ecaba843986fcc00e480001d5f85a378b Mon Sep 17 00:00:00 2001 From: lpbeliveau-silabs <112982107+lpbeliveau-silabs@users.noreply.github.com> Date: Fri, 16 Feb 2024 16:22:43 -0500 Subject: [PATCH 005/385] Split overloaded steps 1b and 2d in 2_6 and added fabric removal for TH2 and TH3 at the end (#32177) --- .../suites/certification/Test_TC_S_2_6.yaml | 56 ++++++++++++++++--- 1 file changed, 47 insertions(+), 9 deletions(-) diff --git a/src/app/tests/suites/certification/Test_TC_S_2_6.yaml b/src/app/tests/suites/certification/Test_TC_S_2_6.yaml index 4c81d96190abfc..c3b5b6561bfd57 100644 --- a/src/app/tests/suites/certification/Test_TC_S_2_6.yaml +++ b/src/app/tests/suites/certification/Test_TC_S_2_6.yaml @@ -101,7 +101,7 @@ tests: CHIP:TOO: } disabled: true - - label: "Step 1b: Repeat Step 1a with TH2 and TH3." + - label: "Step 1b: Repeat Step 1a with TH2." PICS: S.S.C03.Rsp verification: | ./chip-tool scenesmanagement remove-all-scenes 0x0000 2 1 --commissioner-name beta @@ -116,7 +116,11 @@ tests: [1700826575.191974][15971:15973] CHIP:TOO: status: 0 [1700826575.191985][15971:15973] CHIP:TOO: groupID: 0 [1700826575.191995][15971:15973] CHIP:TOO: } + disabled: true + - label: "Step 1C: Repeat Step 1a with TH3." + PICS: S.S.C03.Rsp + verification: | ./chip-tool scenesmanagement remove-all-scenes 0x0000 3 1 --commissioner-name gamma Verify the RemoveAllScenesResponse with following fields: @@ -282,10 +286,10 @@ tests: [1701242801.625919][7636:7638] CHIP:TOO: RemainingCapacity: 7 [1701242801.625930][7636:7638] CHIP:TOO: FabricIndex: 2 [1701242801.625941][7636:7638] CHIP:TOO: } + disabled: true - - TH3: - + - label: "Step 2e: Repeat Step 2b and 2c with TH3." + verification: | Please use Interactive mode to Verify the subscription of an event Here the command to enter interactive mode:-- ./chip-tool interactive start @@ -966,11 +970,11 @@ tests: disabled: true - label: - Verify that the DUT sends a report data to TH2 for FabricSceneInfo - after the MinIntervalFloor time; store the RemainingCapacity field - from this fabric’s entry reported in FabricSceneInfo into - Remaining2ndCapacity; verify Remaining2ndCapacity equals - (MaxRemainingCapacity). + "Step 10b: Verify that the DUT sends a report data to TH2 for + FabricSceneInfo after the MinIntervalFloor time; store the + RemainingCapacity field from this fabric’s entry reported in + FabricSceneInfo into Remaining2ndCapacity; verify Remaining2ndCapacity + equals (MaxRemainingCapacity)." verification: | ./chip-tool scenesmanagement subscribe fabric-scene-info 100 200 2 1 --commissioner-name beta @@ -989,3 +993,37 @@ tests: [1705915866.717640][21433:21435] CHIP:TOO: } disabled: true + + - label: + "Step 11a: TH1 removes the TH2 fabric by sending the RemoveFabric + command to the DUT with the FabricIndex set to th2FabricIndex" + verification: | + ./chip-tool operationalcredentials remove-fabric th2FabricIndex 1 0 + + On TH1(chip-tool) verify the success with the nocresponse with statuscode is success(0) + + [1784416866.004187][21433:21435] CHIP:DMG: Received Command Response Data, Endpoint=0 Cluster=0x0000_003E Command=0x0000_0008 + [1784416866.004214][21433:21435] CHIP:TOO: Endpoint: 0 Cluster: 0x0000_003E Command 0x0000_0008 + [1784416866.004236][21433:21435] CHIP:TOO: NOCResponse: { + [1784416866.004250][21433:21435] CHIP:TOO: statusCode: 0 + [1784416866.004255][21433:21435] CHIP:TOO: fabricIndex: th2FabricIndex + [1784416866.004259][21433:21435] CHIP:TOO: } + [1784416866.004270][21433:21435] CHIP:DMG: ICR moving to [AwaitingDe] + disabled: true + + - label: + "Step 11b: TH1 removes the TH3 fabric by sending the RemoveFabric + command to the DUT with the FabricIndex set to th3FabricIndex" + verification: | + ./chip-tool operationalcredentials remove-fabric th3FabricIndex 1 0 + + On TH1(chip-tool) verify the success with the nocresponse with statuscode is success(0) + + [1784416866.004187][21433:21435] CHIP:DMG: Received Command Response Data, Endpoint=0 Cluster=0x0000_003E Command=0x0000_0008 + [1784416866.004214][21433:21435] CHIP:TOO: Endpoint: 0 Cluster: 0x0000_003E Command 0x0000_0008 + [1784416866.004236][21433:21435] CHIP:TOO: NOCResponse: { + [1784416866.004250][21433:21435] CHIP:TOO: statusCode: 0 + [1784416866.004255][21433:21435] CHIP:TOO: fabricIndex: th3FabricIndex + [1784416866.004259][21433:21435] CHIP:TOO: } + [1784416866.004270][21433:21435] CHIP:DMG: ICR moving to [AwaitingDe] + disabled: true From f7494fa3aaf220964d606f6e61a6132270cf4549 Mon Sep 17 00:00:00 2001 From: C Freeman Date: Fri, 16 Feb 2024 16:22:49 -0500 Subject: [PATCH 006/385] TC-IDM-10.2: Work around conformance for color control (#32157) Some attributes are using a non-standard conformance marker in the spec. For now, treat all these as optional and default to the color control cluster tests to properly verify these values. Test: Tested against the example lighting app. The app still HAS conformance issues, but these particular attribues are no longer listed as problems. --- src/python_testing/spec_parsing_support.py | 27 ++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/python_testing/spec_parsing_support.py b/src/python_testing/spec_parsing_support.py index 3d6cedfb4da8bf..9b65df0d0dcab5 100644 --- a/src/python_testing/spec_parsing_support.py +++ b/src/python_testing/spec_parsing_support.py @@ -496,6 +496,33 @@ def remove_problem(location: typing.Union[CommandPathLocation, FeaturePathLocati clusters[id] = new # TODO: All these fixups should be removed BEFORE SVE if at all possible + # Workaround for Color Control cluster - the spec uses a non-standard conformance. Set all to optional now, will need + # to implement either arithmetic conformance handling (once spec changes land here) or specific test + # https://github.com/CHIP-Specifications/connectedhomeip-spec/pull/7808 for spec changes. + # see 3.2.8. Defined Primaries Information Attribute Set, affects Primary<#>X/Y/Intensity attributes. + cc_id = Clusters.ColorControl.id + cc_attr = Clusters.ColorControl.Attributes + affected_attributes = [cc_attr.Primary1X, + cc_attr.Primary1Y, + cc_attr.Primary1Intensity, + cc_attr.Primary2X, + cc_attr.Primary2Y, + cc_attr.Primary2Intensity, + cc_attr.Primary3X, + cc_attr.Primary3Y, + cc_attr.Primary3Intensity, + cc_attr.Primary4X, + cc_attr.Primary4Y, + cc_attr.Primary4Intensity, + cc_attr.Primary5X, + cc_attr.Primary5Y, + cc_attr.Primary5Intensity, + cc_attr.Primary6X, + cc_attr.Primary6Y, + cc_attr.Primary6Intensity, + ] + for a in affected_attributes: + clusters[cc_id].attributes[a.attribute_id].conformance = optional() # Workaround for temp control cluster - this is parsed incorrectly in the DM XML and is missing all its attributes # Remove this workaround when https://github.com/csa-data-model/projects/issues/330 is fixed From 02cc3cb4d48d1a1adada88fa0dcb97a8a9536a56 Mon Sep 17 00:00:00 2001 From: adabreuti <76965454+adabreuti@users.noreply.github.com> Date: Fri, 16 Feb 2024 15:58:41 -0600 Subject: [PATCH 007/385] [TI] Protect AES Crypto Driver access for Matter (#32180) * Update TI AES HW Implementation to protect resource access * Enable AES HW Accel * Restyled by clang-format --------- Co-authored-by: Restyled.io --- src/platform/cc13xx_26xx/cc13x4_26x4/crypto/aes_alt.c | 7 ++++++- .../cc13x4_26x4/crypto/cc13x4_26x4-mbedtls-config.h | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/platform/cc13xx_26xx/cc13x4_26x4/crypto/aes_alt.c b/src/platform/cc13xx_26xx/cc13x4_26x4/crypto/aes_alt.c index b6b790489a9916..91e9004dffdbac 100644 --- a/src/platform/cc13xx_26xx/cc13x4_26x4/crypto/aes_alt.c +++ b/src/platform/cc13xx_26xx/cc13x4_26x4/crypto/aes_alt.c @@ -26,6 +26,7 @@ #include #include +#include /* * number of active contexts, used for power on/off of the crypto core @@ -111,8 +112,11 @@ int mbedtls_aes_setkey_dec(mbedtls_aes_context * ctx, const unsigned char * key, int mbedtls_aes_crypt_ecb(mbedtls_aes_context * ctx, int mode, const unsigned char input[16], unsigned char output[16]) { int statusCrypto; + uint32_t key; AESECB_Operation operationOneStepEncrypt; + key = HwiP_disable(); + /* run it through the authentication + encryption, pass the ccmLVal = 2 */ AESECB_Operation_init(&operationOneStepEncrypt); @@ -125,9 +129,10 @@ int mbedtls_aes_crypt_ecb(mbedtls_aes_context * ctx, int mode, const unsigned ch if (CryptoKey_STATUS_SUCCESS != statusCrypto) { + HwiP_restore(key); return MBEDTLS_ERR_AES_HW_ACCEL_FAILED; } - + HwiP_restore(key); return 0; } #endif diff --git a/src/platform/cc13xx_26xx/cc13x4_26x4/crypto/cc13x4_26x4-mbedtls-config.h b/src/platform/cc13xx_26xx/cc13x4_26x4/crypto/cc13x4_26x4-mbedtls-config.h index 2ac87444764fd6..ce09760f8bf3dc 100644 --- a/src/platform/cc13xx_26xx/cc13x4_26x4/crypto/cc13x4_26x4-mbedtls-config.h +++ b/src/platform/cc13xx_26xx/cc13x4_26x4/crypto/cc13x4_26x4-mbedtls-config.h @@ -38,7 +38,7 @@ /* Enable Hardware Acceleration */ -// #define MBEDTLS_AES_ALT +#define MBEDTLS_AES_ALT // #define MBEDTLS_ECDH_COMPUTE_SHARED_ALT // #define MBEDTLS_ECDH_GEN_PUBLIC_ALT #define MBEDTLS_ECDSA_SIGN_ALT From 13f3e0525b88af723586770e4e93bb42dd42535b Mon Sep 17 00:00:00 2001 From: Tennessee Carmel-Veilleux Date: Fri, 16 Feb 2024 17:15:00 -0500 Subject: [PATCH 008/385] Introduce TC-CNET-4.4 automation (#32176) - Automate TC-CNET-4.4 per test plan. Testing done: - Ran against ESP32 and succeeded. Co-authored-by: cecille --- src/python_testing/TC_CNET_4_4.py | 132 ++++++++++++++++++++++++++++++ 1 file changed, 132 insertions(+) create mode 100644 src/python_testing/TC_CNET_4_4.py diff --git a/src/python_testing/TC_CNET_4_4.py b/src/python_testing/TC_CNET_4_4.py new file mode 100644 index 00000000000000..12407e6c5fd6b0 --- /dev/null +++ b/src/python_testing/TC_CNET_4_4.py @@ -0,0 +1,132 @@ +# +# Copyright (c) 2024 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. +# + +import logging +import random +import string +from typing import Optional + +import chip.clusters as Clusters +from chip.clusters.Types import NullValue +from matter_testing_support import MatterBaseTest, TestStep, async_test_body, default_matter_test_main, type_matches +from mobly import asserts + + +class TC_CNET_4_4(MatterBaseTest): + def steps_TC_CNET_4_4(self): + return [TestStep("precondition", "TH is commissioned", is_commissioning=True), + TestStep(1, 'TH reads from the DUT the Network Commissioning Cluster FeatureMap. If the FeatureMap does not include the WI flag (bit 0), skip the remaining steps in this test case'), + TestStep(2, 'TH reads from the DUT the SupportedWifiBands attribute and saves as supported_wifi_bands'), + TestStep(3, 'TH reads from the DUT the Networks attribute.'), + TestStep(4, 'TH sends ScanNetworks command to the DUT with the SSID field set to null and Breadcrumb field set to 1'), + TestStep(5, 'TH reads from the DUT the Breadcrumb attribute from the General Commissioning Cluster'), + TestStep(6, 'TH sends ScanNetworks Command to the DUT with SSID field set to known_ssid and Breadcrumb field set to 2'), + TestStep(7, 'TH reads Breadcrumb attribute from the General Commissioning Cluster'), + TestStep(8, 'TH sends ScanNetworks Command to the DUT with SSID field set to a string of 31 random alphabetical characters and Breadcrumb field set to 2')] + + def def_TC_CNET_4_4(self): + return '[TC-CNET-4.4] [Wi-Fi] Verification for ScanNetworks command [DUT-Server]' + + def pics_TC_CNET_4_4(self): + return ['CNET.S'] + + @async_test_body + async def test_TC_CNET_4_4(self): + # Commissioning is already done + self.step("precondition") + + cnet = Clusters.NetworkCommissioning + attr = cnet.Attributes + + self.step(1) + feature_map = await self.read_single_attribute_check_success(cluster=cnet, attribute=attr.FeatureMap) + if not (feature_map & cnet.Bitmaps.Feature.kWiFiNetworkInterface): + logging.info('Device does not support WiFi on endpoint, skipping remaining steps') + self.skip_all_remaining_steps(2) + return + + self.step(2) + supported_wifi_bands = await self.read_single_attribute_check_success(cluster=cnet, attribute=attr.SupportedWiFiBands) + + self.step(3) + networks = await self.read_single_attribute_check_success(cluster=cnet, attribute=attr.Networks) + connected = [network for network in networks if network.connected is True] + asserts.assert_greater_equal(len(connected), 1, "Did not find any connected networks on a commissioned device") + known_ssid = connected[0].networkID + + async def scan_and_check(ssid_to_scan: Optional[bytes], breadcrumb: int, expect_results: bool = True): + all_security = 0 + for security_bitmask in cnet.Bitmaps.WiFiSecurityBitmap: + all_security |= security_bitmask + + ssid = ssid_to_scan if ssid_to_scan is not None else NullValue + cmd = cnet.Commands.ScanNetworks(ssid=ssid, breadcrumb=breadcrumb) + scan_results = await self.send_single_cmd(cmd=cmd) + asserts.assert_true(type_matches(scan_results, cnet.Commands.ScanNetworksResponse), + "Unexpected value returned from scan network") + logging.info(f"Scan results: {scan_results}") + + if scan_results.debugText: + debug_text_len = len(scan_results.debug_text) + asserts.assert_less_equal(debug_text_len, 512, f"DebugText length {debug_text_len} was out of range") + + if expect_results: + asserts.assert_equal(scan_results.networkingStatus, cnet.Enums.NetworkCommissioningStatusEnum.kSuccess, + f"ScanNetworks was expected to have succeeded, got {scan_results.networkingStatus} instead") + asserts.assert_greater_equal(len(scan_results.wiFiScanResults), 1, "No responses returned from ScanNetwork command") + else: + asserts.assert_equal(scan_results.networkingStatus, cnet.Enums.NetworkCommissioningStatusEnum.kNetworkNotFound, + f"ScanNetworks was expected to received NetworkNotFound(5), got {scan_results.networkingStatus} instead") + return + + for network in scan_results.wiFiScanResults: + asserts.assert_true((network.security & ~all_security) == 0, "Unexpected bitmap in the security field") + asserts.assert_less_equal(len(network.ssid), 32, f"Returned SSID {network.ssid} is too long") + if ssid_to_scan is not None: + asserts.assert_equal(network.ssid, ssid_to_scan, "Unexpected SSID returned in directed scan") + asserts.assert_true(type_matches(network.bssid, bytes), "Incorrect type for BSSID") + asserts.assert_equal(len(network.bssid), 6, "Unexpected length of BSSID") + # TODO: this is inherited from the old test plan, but we should match the channel to the supported band. This range is unreasonably large. + asserts.assert_less_equal(network.channel, 65535, "Unexpected channel value") + if network.wiFiBand: + asserts.assert_true(network.wiFiBand in supported_wifi_bands, + "Listed wiFiBand is not in supported_wifi_bands") + if network.rssi: + asserts.assert_greater_equal(network.rssi, -120, "RSSI out of range") + asserts.assert_less_equal(network.rssi, 0, "RSSI out of range") + + self.step(4) + await scan_and_check(ssid_to_scan=None, breadcrumb=1, expect_results=True) + + self.step(5) + breadcrumb = await self.read_single_attribute_check_success(cluster=Clusters.GeneralCommissioning, attribute=Clusters.GeneralCommissioning.Attributes.Breadcrumb, endpoint=0) + asserts.assert_equal(breadcrumb, 1, "Incorrect breadcrumb value") + + self.step(6) + await scan_and_check(ssid_to_scan=known_ssid, breadcrumb=2, expect_results=True) + + self.step(7) + breadcrumb = await self.read_single_attribute_check_success(cluster=Clusters.GeneralCommissioning, attribute=Clusters.GeneralCommissioning.Attributes.Breadcrumb, endpoint=0) + asserts.assert_equal(breadcrumb, 2, "Incorrect breadcrumb value") + + self.step(8) + random_ssid = ''.join(random.choice(string.ascii_letters) for _ in range(31)).encode("utf-8") + await scan_and_check(ssid_to_scan=random_ssid, breadcrumb=2, expect_results=False) + + +if __name__ == "__main__": + default_matter_test_main() From 8937d2739f670479122d2404f2d5aae367ae6b4d Mon Sep 17 00:00:00 2001 From: Tennessee Carmel-Veilleux Date: Fri, 16 Feb 2024 18:12:22 -0500 Subject: [PATCH 009/385] Fix NetworkCommissioning post-review from #32156 (#32172) * Fix NetworkCommissioning post-review from #32156 - Found a regression on Thread scanning. - Changed some ConstraintError to InvalidCommand where more applicable. - Removed an update of cluster state on fail safe expiry. Testing done: - Retested on Wi-Fi - Testing on Thread as well * Re-notify errors on empty network at fail-safe expiry * Fix MobileDeviceTest * Fix Cirque tests --- .../network-commissioning.cpp | 23 +++++++++++-------- .../test_scripts/network_commissioning.py | 8 +++---- 2 files changed, 18 insertions(+), 13 deletions(-) diff --git a/src/app/clusters/network-commissioning/network-commissioning.cpp b/src/app/clusters/network-commissioning/network-commissioning.cpp index cb847a13867d5d..8212ea9f8008dc 100644 --- a/src/app/clusters/network-commissioning/network-commissioning.cpp +++ b/src/app/clusters/network-commissioning/network-commissioning.cpp @@ -477,7 +477,7 @@ void Instance::HandleScanNetworks(HandlerContext & ctx, const Commands::ScanNetw } if (ssid.size() > DeviceLayer::Internal::kMaxWiFiSSIDLength) { - // This should not happen, it means it's a broken driver. + // Clients should never use too large a SSID. ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Protocols::InteractionModel::Status::ConstraintError); SetLastNetworkingStatusValue(MakeNullable(Status::kUnknownError)); return; @@ -491,10 +491,10 @@ void Instance::HandleScanNetworks(HandlerContext & ctx, const Commands::ScanNetw } else if (mFeatureFlags.Has(Feature::kThreadNetworkInterface)) { - // Not allowed to populate SSID for Thread. - if (!req.ssid.HasValue()) + // SSID present on Thread violates the `[WI]` conformance. + if (req.ssid.HasValue()) { - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Protocols::InteractionModel::Status::ConstraintError); + ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Protocols::InteractionModel::Status::InvalidCommand); return; } @@ -559,7 +559,7 @@ void Instance::HandleAddOrUpdateWiFiNetwork(HandlerContext & ctx, const Commands return; } #endif // CHIP_DEVICE_CONFIG_ENABLE_WIFI_PDC - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Protocols::InteractionModel::Status::ConstraintError); + ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Protocols::InteractionModel::Status::InvalidCommand); return; } @@ -1202,11 +1202,16 @@ void Instance::OnFailSafeTimerExpired() mpWirelessDriver->RevertConfiguration(); mAsyncCommandHandle.Release(); - // Reset state on failsafe expiry. + // Mark the network list changed since `mpWirelessDriver->RevertConfiguration()` may have updated it. ReportNetworksListChanged(); - SetLastNetworkId(ByteSpan{}); - SetLastConnectErrorValue(NullNullable); - SetLastNetworkingStatusValue(NullNullable); + + // If no networks are left, clear-out errors; + if (mpBaseDriver && (CountAndRelease(mpBaseDriver->GetNetworks()) == 0)) + { + SetLastNetworkId(ByteSpan{}); + SetLastConnectErrorValue(NullNullable); + SetLastNetworkingStatusValue(NullNullable); + } } CHIP_ERROR Instance::EnumerateAcceptedCommands(const ConcreteClusterPath & cluster, CommandIdCallback callback, void * context) diff --git a/src/controller/python/test/test_scripts/network_commissioning.py b/src/controller/python/test/test_scripts/network_commissioning.py index 72635677be9c9d..8ecbd59f78393b 100644 --- a/src/controller/python/test/test_scripts/network_commissioning.py +++ b/src/controller/python/test/test_scripts/network_commissioning.py @@ -149,9 +149,9 @@ async def test_wifi(self, endpointId): # Scan networks logger.info("Scan networks") - req = Clusters.NetworkCommissioning.Commands.ScanNetworks( - ssid=b'', breadcrumb=self.with_breadcrumb()) + req = Clusters.NetworkCommissioning.Commands.ScanNetworks(breadcrumb=self.with_breadcrumb()) interactionTimeoutMs = self._devCtrl.ComputeRoundTripTimeout(self._nodeid, upperLayerProcessingTimeoutMs=30000) + logger.info(f"Request: {req}") res = await self._devCtrl.SendCommand( nodeid=self._nodeid, endpoint=endpointId, @@ -309,8 +309,8 @@ async def test_thread(self, endpointId): # Scan networks logger.info("Scan networks") - req = Clusters.NetworkCommissioning.Commands.ScanNetworks( - ssid=b'', breadcrumb=self.with_breadcrumb()) + req = Clusters.NetworkCommissioning.Commands.ScanNetworks(breadcrumb=self.with_breadcrumb()) + logger.info(f"Request: {req}") interactionTimeoutMs = self._devCtrl.ComputeRoundTripTimeout(self._nodeid, upperLayerProcessingTimeoutMs=30000) res = await self._devCtrl.SendCommand(nodeid=self._nodeid, endpoint=endpointId, From 977d90e1cde27669c1a4671dbb43d2c5762bccae Mon Sep 17 00:00:00 2001 From: lpbeliveau-silabs <112982107+lpbeliveau-silabs@users.noreply.github.com> Date: Fri, 16 Feb 2024 18:15:45 -0500 Subject: [PATCH 010/385] Fixed the differences with the VS Documents (#32183) --- .../suites/certification/Test_TC_S_2_2.yaml | 54 +--- .../suites/certification/Test_TC_S_2_3.yaml | 77 +++--- .../suites/certification/Test_TC_S_2_5.yaml | 4 +- .../suites/certification/Test_TC_S_2_6.yaml | 257 ++++++++++++++---- 4 files changed, 247 insertions(+), 145 deletions(-) diff --git a/src/app/tests/suites/certification/Test_TC_S_2_2.yaml b/src/app/tests/suites/certification/Test_TC_S_2_2.yaml index b27d4bfd333cee..02407f8807d993 100644 --- a/src/app/tests/suites/certification/Test_TC_S_2_2.yaml +++ b/src/app/tests/suites/certification/Test_TC_S_2_2.yaml @@ -643,48 +643,18 @@ tests: to 60 000 000 (60 000s) and a set of extension fields appropriate to AC1." verification: | - ./chip-tool scenes add-scene 0x0001 1 60000000 "Test Name" '[{"clusterId": value, "attributeValueList":[{"attributeId": value, "attributeValue": value}]}' nodeId endpointId - - Note: The number of ExtensionFieldSets, the value of clusterId of each ExtensionFieldSet, the number of attributes in attributeValueList and their values varies for each application - - Verify the "status is success" on the TH(Chip-tool) Log and below is the sample log provided for the raspi platform: - [1670970505.887060][5742:5744] CHIP:DMG: InvokeResponseMessage = - [1670970505.887118][5742:5744] CHIP:DMG: { - [1670970505.887172][5742:5744] CHIP:DMG: suppressResponse = false, - [1670970505.887231][5742:5744] CHIP:DMG: InvokeResponseIBs = - [1670970505.887307][5742:5744] CHIP:DMG: [ - [1670970505.887366][5742:5744] CHIP:DMG: InvokeResponseIB = - [1670970505.887444][5742:5744] CHIP:DMG: { - [1670970505.887507][5742:5744] CHIP:DMG: CommandDataIB = - [1670970505.887576][5742:5744] CHIP:DMG: { - [1670970505.887713][5742:5744] CHIP:DMG: CommandPathIB = - [1670970505.887804][5742:5744] CHIP:DMG: { - [1670970505.887940][5742:5744] CHIP:DMG: EndpointId = 0x1, - [1670970505.888093][5742:5744] CHIP:DMG: ClusterId = 0x5, - [1670970505.888242][5742:5744] CHIP:DMG: CommandId = 0x0, - [1670970505.888385][5742:5744] CHIP:DMG: }, - [1670970505.888692][5742:5744] CHIP:DMG: - [1670970505.888769][5742:5744] CHIP:DMG: CommandFields = - [1670970505.888852][5742:5744] CHIP:DMG: { - [1670970505.889030][5742:5744] CHIP:DMG: 0x0 = 0, - [1670970505.889183][5742:5744] CHIP:DMG: 0x1 = 1, - [1670970505.889406][5742:5744] CHIP:DMG: 0x2 = 1, - [1670970505.889515][5742:5744] CHIP:DMG: }, - [1670970505.889603][5742:5744] CHIP:DMG: }, - [1670970505.889684][5742:5744] CHIP:DMG: - [1670970505.889745][5742:5744] CHIP:DMG: }, - [1670970505.889821][5742:5744] CHIP:DMG: - [1670970505.889878][5742:5744] CHIP:DMG: ], - [1670970505.889953][5742:5744] CHIP:DMG: - [1670970505.890009][5742:5744] CHIP:DMG: InteractionModelRevision = 1 - [1670970505.890066][5742:5744] CHIP:DMG: }, - [1670970505.890212][5742:5744] CHIP:DMG: Received Command Response Data, Endpoint=1 Cluster=0x0000_0005 Command=0x0000_0000 - [1670970505.890328][5742:5744] CHIP:TOO: Endpoint: 1 Cluster: 0x0000_0005 Command 0x0000_0000 - [1670970505.890458][5742:5744] CHIP:TOO: AddSceneResponse: { - [1670970505.890551][5742:5744] CHIP:TOO: status: 0 - [1670970505.890608][5742:5744] CHIP:TOO: groupId: 1 - [1670970505.890717][5742:5744] CHIP:TOO: sceneId: 1 - [1670970505.890774][5742:5744] CHIP:TOO: } + ./chip-tool scenesmanagement add-scene 0x0001 0x01 60000000 "scene name" '[{"clusterID": "0x0300", "attributeValueList":[{"attributeID": "0x4001", "attributeValue": "0x01"}]}]' 1 1 + + Verify DUT sends a AddSceneResponse command to TH with the Status field set to 0x00 (SUCCESS), the GroupID field set to G1 and the SceneID field set to 0x01 on the TH(Chip-tool) Log and below is the sample log provided for the raspi platform: + + [1706763610.675038][4232:4234] CHIP:DMG: }, + [1706763610.675108][4232:4234] CHIP:DMG: Received Command Response Data, Endpoint=1 Cluster=0x0000_0062 Command=0x0000_0000 + [1706763610.675134][4232:4234] CHIP:TOO: Endpoint: 1 Cluster: 0x0000_0062 Command 0x0000_0000 + [1706763610.675187][4232:4234] CHIP:TOO: AddSceneResponse: { + [1706763610.675215][4232:4234] CHIP:TOO: status: 0 + [1706763610.675229][4232:4234] CHIP:TOO: groupID: 1 + [1706763610.675244][4232:4234] CHIP:TOO: sceneID: 1 + [1706763610.675258][4232:4234] CHIP:TOO: } cluster: "LogCommands" command: "UserPrompt" PICS: PICS_SKIP_SAMPLE_APP diff --git a/src/app/tests/suites/certification/Test_TC_S_2_3.yaml b/src/app/tests/suites/certification/Test_TC_S_2_3.yaml index eeeabe22dc4f4c..859204e549f7b2 100644 --- a/src/app/tests/suites/certification/Test_TC_S_2_3.yaml +++ b/src/app/tests/suites/certification/Test_TC_S_2_3.yaml @@ -376,50 +376,39 @@ tests: set to G1 and the SceneID field set to 0x01." PICS: S.S.C01.Rsp && PICS_SKIP_SAMPLE_APP verification: | - ./chip-tool scenesmanagement view-scene GroupId SceneId Node-Id EndpointId - - Note: The number of ExtensionFieldSets, the value of clusterId of each ExtensionFieldSet, the number of attributes in attributeValueList and their values varies for each application - - Verify that the extension fields in the log match the ones expected in the following log: - [1705680224.968551][5827:5829] CHIP:DMG: Received Command Response Data, Endpoint=1 Cluster=0x0000_0062 Command=0x0000_0001 - [1705680224.968559][5827:5829] CHIP:TOO: Endpoint: 1 Cluster: 0x0000_0062 Command 0x0000_0001 - CHIP:TOO: ViewSceneResponse: { - CHIP:TOO: status: 0 - CHIP:TOO: groupID: 1 - CHIP:TOO: sceneID: 1 - CHIP:TOO: transitionTime: 1000 - CHIP:TOO: sceneName: - CHIP:TOO: extensionFieldSets: 3 entries - CHIP:TOO: [1]: { - CHIP:TOO: ClusterID: XX - CHIP:TOO: AttributeValueList: X entries - CHIP:TOO: [1]: { - CHIP:TOO: AttributeID: XX - CHIP:TOO: AttributeValue:XX - CHIP:TOO: } - CHIP:TOO: } - CHIP:TOO: [2]: { - CHIP:TOO: ClusterID: XX - CHIP:TOO: AttributeValueList: X entries - CHIP:TOO: [1]: { - CHIP:TOO: AttributeID: XX - CHIP:TOO: AttributeValue: XX - CHIP:TOO: } - CHIP:TOO: } - CHIP:TOO: [3]: { - CHIP:TOO: ClusterID: XX - CHIP:TOO: AttributeValueList: XX entries - CHIP:TOO: [X]: { - CHIP:TOO: AttributeID: XX - CHIP:TOO: AttributeValue: XX - CHIP:TOO: } - ... - CHIP:TOO: [X]: { - CHIP:TOO: AttributeID: XX - CHIP:TOO: AttributeValue: XX - CHIP:TOO: } - CHIP:TOO: } - CHIP:TOO: } + ./chip-tool scenesmanagement view-scene 0x0101 0x01 1 1 + + Verify DUT sends a ViewSceneResponse command to TH with the Status field set to 0x00 (SUCCESS), the GroupID field set to G1, the SceneID field set to 0x01, the TransitionTime field set to 1000 and a set of extension fields appropriate to AC1 on the TH(Chip-tool) Log and below is the sample log provided for the raspi platform: + + + NOTE: The values below are expected to match the values from the specific AC tested + + [1708071897.294470][7731:7733] CHIP:DMG: Received Command Response Data, Endpoint=1 Cluster=0x0000_0062 Command=0x0000_0001 + [1708071897.294486][7731:7733] CHIP:TOO: Endpoint: 1 Cluster: 0x0000_0062 Command 0x0000_0001 + [1708071897.294520][7731:7733] CHIP:TOO: ViewSceneResponse: { + [1708071897.294527][7731:7733] CHIP:TOO: status: 0 + [1708071897.294530][7731:7733] CHIP:TOO: groupID: 257 + [1708071897.294533][7731:7733] CHIP:TOO: sceneID: 1 + [1708071897.294536][7731:7733] CHIP:TOO: transitionTime: 1000 + [1708071897.294540][7731:7733] CHIP:TOO: sceneName: scene name + [1708071897.294554][7731:7733] CHIP:TOO: extensionFieldSets: 2 entries + [1708071897.294569][7731:7733] CHIP:TOO: [1]: { + [1708071897.294574][7731:7733] CHIP:TOO: ClusterID: 6 + [1708071897.294580][7731:7733] CHIP:TOO: AttributeValueList: 1 entries + [1708071897.294589][7731:7733] CHIP:TOO: [1]: { + [1708071897.294593][7731:7733] CHIP:TOO: AttributeID: 1 + [1708071897.294596][7731:7733] CHIP:TOO: AttributeValue: 1 + [1708071897.294599][7731:7733] CHIP:TOO: } + [1708071897.294603][7731:7733] CHIP:TOO: } + [1708071897.294611][7731:7733] CHIP:TOO: [2]: { + [1708071897.294615][7731:7733] CHIP:TOO: ClusterID: 8 + [1708071897.294621][7731:7733] CHIP:TOO: AttributeValueList: 1 entries + [1708071897.294628][7731:7733] CHIP:TOO: [1]: { + [1708071897.294633][7731:7733] CHIP:TOO: AttributeID: 0 + [1708071897.294636][7731:7733] CHIP:TOO: AttributeValue: 100 + [1708071897.294639][7731:7733] CHIP:TOO: } + [1708071897.294643][7731:7733] CHIP:TOO: } + [1708071897.294647][7731:7733] CHIP:TOO: } cluster: "LogCommands" command: "UserPrompt" arguments: diff --git a/src/app/tests/suites/certification/Test_TC_S_2_5.yaml b/src/app/tests/suites/certification/Test_TC_S_2_5.yaml index e1624bf79d7e64..e0a2998e06d965 100644 --- a/src/app/tests/suites/certification/Test_TC_S_2_5.yaml +++ b/src/app/tests/suites/certification/Test_TC_S_2_5.yaml @@ -250,7 +250,7 @@ tests: to 20000 (20s) and no extension field sets." PICS: S.S.C00.Rsp verification: | - scenesmanagement add-scene 0x0001 0x01 20 scene1 [] 1 1 + ./chip-tool scenesmanagement add-scene 0x0001 0x01 20000 scene1 [] 1 1 Verify the AddSceneResponse with following fields: Status is SUCCESS @@ -412,7 +412,7 @@ tests: field sets. If RemainingCapacity is 0, continue to Step 8a." PICS: S.S.C00.Rsp verification: | - ./chip-tool scenesmanagement add-scene 0x0001 0x03 20 scene1 [] 1 1 + ./chip-tool scenesmanagement add-scene 0x0001 0x03 20000 scene1 [] 1 1 Verify the AddSceneResponse with following fields: Status is SUCCESS diff --git a/src/app/tests/suites/certification/Test_TC_S_2_6.yaml b/src/app/tests/suites/certification/Test_TC_S_2_6.yaml index c3b5b6561bfd57..2c8d0ce4e5a820 100644 --- a/src/app/tests/suites/certification/Test_TC_S_2_6.yaml +++ b/src/app/tests/suites/certification/Test_TC_S_2_6.yaml @@ -94,11 +94,15 @@ tests: verification: | ./chip-tool scenesmanagement remove-all-scenes 0x0000 1 1 - CHIP:TOO: Endpoint: 1 Cluster: 0x0000_0005 Command 0x0000_0003 - CHIP:TOO: RemoveAllScenesResponse: { - CHIP:TOO: status: 0 - CHIP:TOO: groupID: 0 - CHIP:TOO: } + Verify the RemoveAllScenesResponse with following fields: + Status is SUCCESS + Group ID is 0x0000 on the TH(Chip-tool) log and below is the sample log provided for the raspi platform: + + [1701173905.688536][36687:36689] CHIP:TOO: Endpoint: 1 Cluster: 0x0000_0062 Command 0x0000_0003 + [1701173905.688553][36687:36689] CHIP:TOO: RemoveAllScenesResponse: { + [1701173905.688558][36687:36689] CHIP:TOO: status: 0 + [1701173905.688561][36687:36689] CHIP:TOO: groupID: 0 + [1701173905.688563][36687:36689] CHIP:TOO: } disabled: true - label: "Step 1b: Repeat Step 1a with TH2." @@ -354,7 +358,7 @@ tests: set to 20000 (20s) and no extension field sets." PICS: S.S.C00.Rsp verification: | - ./chip-tool scenesmanagement add-scene 0x0000 0x01 20 scene1 [] 1 1 + ./chip-tool scenesmanagement add-scene 0x0000 0x01 20000 scene1 [] 1 1 Verify the AddSceneResponse with following fields: Status is SUCCESS @@ -377,7 +381,7 @@ tests: FabricSceneInfo into Remaining1stCapacity; verify Remaining1stCapacity equals (MaxRemainingCapacity-1)." verification: | - ./chip-tool scenesmanagement subscribe fabric-scene-info 100 200 1 1 + ./chipt-tool scenesmanagement subscribe fabric-scene-info 100 200 1 1 Verify the DUT sends a report data to TH1 for FabricSceneInfo after the MinIntervalFloor time; store the RemainingCapacity field from this fabric’s entry reported in FabricSceneInfo into Remaining1stCapacity and is equals to (MaxRemainingCapacity-1) on the TH (Chip-tool) and below is the sample log provided for the raspi platform: @@ -439,34 +443,137 @@ tests: verification: | ./chip-tool scenesmanagement add-scene 0x0000 0x02 20000 scene2 [] 1 1 - CHIP:TOO: Endpoint: 1 Cluster: 0x0000_0005 Command 0x0000_0000 - CHIP:TOO: AddSceneResponse: { - CHIP:TOO: status: 0 - CHIP:TOO: groupID: 0 - CHIP:TOO: sceneID: 2 - CHIP:TOO: } + Verify the AddSceneResponse with following fields: + Status is SUCCESS + Group ID is 0x0000 + SceneID field set to 0x02 on the TH1(Chip-tool) log and below is the sample log provided for the raspi platform: + + [1700827508.579671][16026:16028] CHIP:DMG: Received Command Response Data, Endpoint=1 Cluster=0x0000_0062 Command=0x0000_0000 + [1700827508.579675][16026:16028] CHIP:TOO: Endpoint: 1 Cluster: 0x0000_0062 Command 0x0000_0000 + [1700827508.579684][16026:16028] CHIP:TOO: AddSceneResponse: { + [1700827508.579688][16026:16028] CHIP:TOO: status: 0 + [1700827508.579691][16026:16028] CHIP:TOO: groupID: 0 + [1700827508.579694][16026:16028] CHIP:TOO: sceneID: 2 + [1700827508.579697][16026:16028] CHIP:TOO: } + + + ./chip-tool scenesmanagement subscribe fabric-scene-info 100 200 1 1 + Verify the DUT sends a report data messages after the MinIntervalFloor time to TH1 for RemainingCapacity field in FabricSceneInfo for that fabric with updated valueon the TH1 (Chip-tool) and below is the sample log provided for the raspi platform: + [1701243677.717829][7642:7644] CHIP:DMG: ReportDataMessage = + [1701243677.717834][7642:7644] CHIP:DMG: { + [1701243677.717839][7642:7644] CHIP:DMG: SubscriptionId = 0xbbe8695b, + [1701243677.717844][7642:7644] CHIP:DMG: AttributeReportIBs = + [1701243677.717854][7642:7644] CHIP:DMG: [ + [1701243677.717858][7642:7644] CHIP:DMG: AttributeReportIB = + [1701243677.717866][7642:7644] CHIP:DMG: { + [1701243677.717870][7642:7644] CHIP:DMG: AttributeDataIB = + [1701243677.717875][7642:7644] CHIP:DMG: { + [1701243677.717881][7642:7644] CHIP:DMG: DataVersion = 0x4daee689, + [1701243677.717886][7642:7644] CHIP:DMG: AttributePathIB = + [1701243677.717893][7642:7644] CHIP:DMG: { + [1701243677.717899][7642:7644] CHIP:DMG: Endpoint = 0x1, + [1701243677.717906][7642:7644] CHIP:DMG: Cluster = 0x62, + [1701243677.717912][7642:7644] CHIP:DMG: Attribute = 0x0000_0002, + [1701243677.717917][7642:7644] CHIP:DMG: } + [1701243677.717924][7642:7644] CHIP:DMG: + [1701243677.717929][7642:7644] CHIP:DMG: Data = [ + [1701243677.717935][7642:7644] CHIP:DMG: + [1701243677.717941][7642:7644] CHIP:DMG: { + [1701243677.717948][7642:7644] CHIP:DMG: 0x0 = 2, + [1701243677.717954][7642:7644] CHIP:DMG: 0x1 = 0, + [1701243677.717960][7642:7644] CHIP:DMG: 0x2 = 0, + [1701243677.717967][7642:7644] CHIP:DMG: 0x3 = false, + [1701243677.717973][7642:7644] CHIP:DMG: 0x4 = 5, + [1701243677.717979][7642:7644] CHIP:DMG: 0xfe = 1, + [1701243677.717986][7642:7644] CHIP:DMG: }, + [1701243677.717991][7642:7644] CHIP:DMG: ], + [1701243677.717996][7642:7644] CHIP:DMG: }, + [1701243677.718006][7642:7644] CHIP:DMG: + [1701243677.718010][7642:7644] CHIP:DMG: }, + [1701243677.718020][7642:7644] CHIP:DMG: + [1701243677.718024][7642:7644] CHIP:DMG: ], + [1701243677.718034][7642:7644] CHIP:DMG: + [1701243677.718037][7642:7644] CHIP:DMG: InteractionModelRevision = 11 + [1701243677.718040][7642:7644] CHIP:DMG: } + [1701243677.718133][7642:7644] CHIP:TOO: Endpoint: 1 Cluster: 0x0000_0062 Attribute 0x0000_0002 DataVersion: 1303307913 + [1701243677.718146][7642:7644] CHIP:TOO: FabricSceneInfo: 1 entries + [1701243677.718154][7642:7644] CHIP:TOO: [1]: { + [1701243677.718157][7642:7644] CHIP:TOO: SceneCount: 2 + [1701243677.718160][7642:7644] CHIP:TOO: CurrentScene: 0 + [1701243677.718162][7642:7644] CHIP:TOO: CurrentGroup: 0 + [1701243677.718165][7642:7644] CHIP:TOO: SceneValid: FALSE + [1701243677.718168][7642:7644] CHIP:TOO: RemainingCapacity: 5 + [1701243677.718170][7642:7644] CHIP:TOO: FabricIndex: 1 + [1701243677.718173][7642:7644] CHIP:TOO: } . . . - ./chip-tool scenesmanagement add-scene 0x0000 0x07 20000 scene2 [] 1 1 - - CHIP:TOO: Endpoint: 1 Cluster: 0x0000_0005 Command 0x0000_0000 - CHIP:TOO: AddSceneResponse: { - CHIP:TOO: status: 0 - CHIP:TOO: groupID: 0 - CHIP:TOO: sceneID: 7 - CHIP:TOO: } - - You should see the following data in the next report: - CHIP:TOO: FabricSceneInfo: 1 entries - CHIP:TOO: [1]: { - CHIP:TOO: SceneCount: 7 - CHIP:TOO: CurrentScene: 0 - CHIP:TOO: CurrentGroup: 0 - CHIP:TOO: SceneValid: FALSE - CHIP:TOO: RemainingCapacity: 0 - CHIP:TOO: FabricIndex: 1 - CHIP:TOO: } + ./chip-tool scenesmanagement add-scene 0x0000 0x07 20000 scene8 [] 1 1 + + Verify the AddSceneResponse with following fields: + Status is SUCCESS + Group ID is 0x0000 + SceneID field set to 0x07 on the TH(Chip-tool) log and below is the sample log provided for the raspi platform: + + [1700827941.415335][16068:16070] CHIP:DMG: }, + [1700827941.415392][16068:16070] CHIP:DMG: Received Command Response Data, Endpoint=1 Cluster=0x0000_0062 Command=0x0000_0000 + [1700827941.415406][16068:16070] CHIP:TOO: Endpoint: 1 Cluster: 0x0000_0062 Command 0x0000_0000 + [1700827941.415462][16068:16070] CHIP:TOO: AddSceneResponse: { + [1700827941.415477][16068:16070] CHIP:TOO: status: 0 + [1700827941.415488][16068:16070] CHIP:TOO: groupID: 0 + [1700827941.415498][16068:16070] CHIP:TOO: sceneID: 7 + [1700827941.415508][16068:16070] CHIP:TOO: } + + ./chip-tool scenesmanagement subscribe fabric-scene-info 100 200 1 1 + + Verify the DUT sends a report data messages after the MinIntervalFloor time to TH1 for RemainingCapacity field in FabricSceneInfo for that fabric with updated valueon the TH1 (Chip-tool) and below is the sample log provided for the raspi platform: + + [1701244322.682421][7642:7644] CHIP:DMG: ReportDataMessage = + [1701244322.682435][7642:7644] CHIP:DMG: { + [1701244322.682447][7642:7644] CHIP:DMG: SubscriptionId = 0xbbe8695b, + [1701244322.682458][7642:7644] CHIP:DMG: AttributeReportIBs = + [1701244322.682484][7642:7644] CHIP:DMG: [ + [1701244322.682495][7642:7644] CHIP:DMG: AttributeReportIB = + [1701244322.682518][7642:7644] CHIP:DMG: { + [1701244322.682528][7642:7644] CHIP:DMG: AttributeDataIB = + [1701244322.682542][7642:7644] CHIP:DMG: { + [1701244322.682555][7642:7644] CHIP:DMG: DataVersion = 0x4daee697, + [1701244322.682566][7642:7644] CHIP:DMG: AttributePathIB = + [1701244322.682579][7642:7644] CHIP:DMG: { + [1701244322.682592][7642:7644] CHIP:DMG: Endpoint = 0x1, + [1701244322.682605][7642:7644] CHIP:DMG: Cluster = 0x62, + [1701244322.682619][7642:7644] CHIP:DMG: Attribute = 0x0000_0002, + [1701244322.682631][7642:7644] CHIP:DMG: } + [1701244322.682647][7642:7644] CHIP:DMG: + [1701244322.682659][7642:7644] CHIP:DMG: Data = [ + [1701244322.682672][7642:7644] CHIP:DMG: + [1701244322.682687][7642:7644] CHIP:DMG: { + [1701244322.682701][7642:7644] CHIP:DMG: 0x0 = 7, + [1701244322.682715][7642:7644] CHIP:DMG: 0x1 = 0, + [1701244322.682729][7642:7644] CHIP:DMG: 0x2 = 0, + [1701244322.682742][7642:7644] CHIP:DMG: 0x3 = false, + [1701244322.682756][7642:7644] CHIP:DMG: 0x4 = 0, + [1701244322.682770][7642:7644] CHIP:DMG: 0xfe = 1, + [1701244322.682784][7642:7644] CHIP:DMG: }, + [1701244322.682807][7642:7644] CHIP:DMG: ], + [1701244322.682818][7642:7644] CHIP:DMG: }, + [1701244322.682843][7642:7644] CHIP:DMG: + [1701244322.682853][7642:7644] CHIP:DMG: }, + [1701244322.682876][7642:7644] CHIP:DMG: + [1701244322.682887][7642:7644] CHIP:DMG: ], + [1701244322.682908][7642:7644] CHIP:DMG: + [1701244322.682919][7642:7644] CHIP:DMG: InteractionModelRevision = 11 + [1701244322.682930][7642:7644] CHIP:DMG: } + [1701244322.683149][7642:7644] CHIP:TOO: Endpoint: 1 Cluster: 0x0000_0062 Attribute 0x0000_0002 DataVersion: 1303307927 + [1701244322.683191][7642:7644] CHIP:TOO: FabricSceneInfo: 1 entries + [1701244322.683224][7642:7644] CHIP:TOO: [1]: { + [1701244322.683236][7642:7644] CHIP:TOO: SceneCount: 7 + [1701244322.683247][7642:7644] CHIP:TOO: CurrentScene: 0 + [1701244322.683258][7642:7644] CHIP:TOO: CurrentGroup: 0 + [1701244322.683269][7642:7644] CHIP:TOO: SceneValid: FALSE + [1701244322.683282][7642:7644] CHIP:TOO: RemainingCapacity: 0 + [1701244322.683293][7642:7644] CHIP:TOO: FabricIndex: 1 + [1701244322.683304][7642:7644] CHIP:TOO: } disabled: true - label: @@ -476,7 +583,7 @@ tests: field sets." PICS: S.S.C00.Rsp verification: | - ./chip-tool scenesmanagement add-scene 0x0000 0x08 0x0014 scene9 [] 1 1 + ./chip-tool scenesmanagement add-scene 0x0000 0x08 20000 scene9 [] 1 1 Verify the AddSceneResponse with following fields: Status is RESOURCE_EXHAUSTED(0x89) on the TH1(Chip-tool) log and below is the sample log provided for the raspi platform: @@ -578,7 +685,7 @@ tests: [1700829509.052521][16198:16200] CHIP:TOO: sceneID: 8 [1700829509.052532][16198:16200] CHIP:TOO: } - ./chip-tool scenesmanagement subscribe fabric-scene-info 100 200 2 1 --commissioner-name beta + ./chip-tool scenesmanagement subscribe fabric-scene-info 100 200 2 1 --commissioner-name beta Verify the DUT sends a report data messages after the MinIntervalFloor time to TH2 for RemainingCapacity field in FabricSceneInfo for that fabric with updated value(decreasing to 0) on the TH2 (Chip-tool) and below is the sample log provided for the raspi platform: @@ -629,7 +736,6 @@ tests: [1701245132.870584][7824:7826] CHIP:TOO: FabricIndex: 2 [1701245132.870594][7824:7826] CHIP:TOO: } - ./chip-tool scenesmanagement subscribe fabric-scene-info 100 200 3 1 --commissioner-name gamma Verify that the DUT sends report data messages after the MinIntervalFloor time to TH3 for RemainingCapacity field in FabricSceneInfo for that fabric with updated value (decreasing to SceneTableSize - (2 * MaxRemainingCapacity)) on the TH2 (Chip-tool) and below is the sample log provided for the raspi platform: @@ -658,7 +764,7 @@ tests: [1705916737.108102][21608:21610] CHIP:DMG: 0x1 = 0, [1705916737.108106][21608:21610] CHIP:DMG: 0x2 = 0, [1705916737.108109][21608:21610] CHIP:DMG: 0x3 = false, - [1705916737.108113][21608:21610] CHIP:DMG: 0x4 = 7, + [1705916737.108113][21608:21610] CHIP:DMG: 0x4 = 2, [1705916737.108117][21608:21610] CHIP:DMG: 0xfe = 3, [1705916737.108120][21608:21610] CHIP:DMG: }, [1705916737.108123][21608:21610] CHIP:DMG: ], @@ -715,10 +821,10 @@ tests: [1705915133.114065][21363:21365] CHIP:TOO: AddSceneResponse: { [1705915133.114081][21363:21365] CHIP:TOO: status: 0 [1705915133.114092][21363:21365] CHIP:TOO: groupID: 0 - [1705915133.114103][21363:21365] CHIP:TOO: sceneID: 1 + [1705915133.114103][21363:21365] CHIP:TOO: sceneID: 2 [1705915133.114113][21363:21365] CHIP:TOO: } - ./chip-tool scenesmanagement subscribe fabric-scene-info 100 200 3 1 --commissioner-name gamma + scenesmanagement subscribe fabric-scene-info 100 200 3 1 --commissioner-name gamma Verify that the DUT sends report data messages after the MinIntervalFloor time to TH3 for RemainingCapacity field in FabricSceneInfo for that fabric with updated value on the TH3(Chip-tool) log and below is the sample log provided for the raspi platform: @@ -770,7 +876,7 @@ tests: [1705915183.312690][21363:21365] CHIP:TOO: } - ./chip-tool scenesmanagement add-scene 0x0000 0x03 0x0014 scene2 [] 3 1 --commissioner-name gamma + scenesmanagement add-scene 0x0000 0x03 0x0014 scene2 [] 3 1 --commissioner-name gamma Verify the AddSceneResponse with following fields: Status is SUCCESS @@ -786,7 +892,6 @@ tests: [1705915237.987161][21363:21365] CHIP:TOO: sceneID: 3 [1705915237.987171][21363:21365] CHIP:TOO: } - ./chip-tool scenesmanagement subscribe fabric-scene-info 100 200 3 1 --commissioner-name gamma Verify that the DUT sends report data messages after the MinIntervalFloor time to TH3 for RemainingCapacity field in FabricSceneInfo for that fabric with updated value((decreasing to 0)) on the TH3(Chip-tool) log and below is the sample log provided for the raspi platform: @@ -837,6 +942,7 @@ tests: [1705915281.586073][21387:21389] CHIP:TOO: RemainingCapacity: 0 [1705915281.586084][21387:21389] CHIP:TOO: FabricIndex: 3 [1705915281.586095][21387:21389] CHIP:TOO: } + disabled: true - label: @@ -845,7 +951,7 @@ tests: set to 20000 20s and no extension field sets." PICS: S.S.C00.Rsp verification: | - ./chip-tool scenesmanagement add-scene 0x0000 0x01 0x0014 scene [] 3 1 --commissioner-name gamma + ./chipt-tool scenesmanagement add-scene 0x0000 0x01 20000 scene [] 3 1 --commissioner-name gamma Verify the AddSceneResponse with following fields: Status is RESOURCE_EXHAUSTED(0x89) on the TH3(Chip-tool) log and below is the sample log provided for the raspi platform: @@ -865,7 +971,7 @@ tests: set to 0x0000, the SceneID field set to 0x01." PICS: S.S.C04.Rsp verification: | - ./chip-tool scenesmanagement store-scene 0x0000 0x01 3 1 --commissioner-name gamma + ./chipt-tool scenesmanagement store-scene 0x0000 0x01 3 1 --commissioner-name gamma Verify the StoreSceneResponse with following fields: Status is RESOURCE_EXHAUSTED(0x89) on the TH3(Chip-tool) log and below is the sample log provided for the raspi platform: @@ -887,7 +993,7 @@ tests: to 0x0000 and the scene identifier to field set to 0xFE." PICS: S.S.C40.Rsp verification: | - ./chip-tool scenesmanagement copy-scene 0x00 0x0000 0x02 0x0000 0x00 3 1 --commissioner-name gamma + ./chipt-tool scenesmanagement copy-scene 0x00 0x0000 0x02 0x0000 0x00 3 1 --commissioner-name gamma Verify the CopySceneResponse with following fields: Status is RESOURCE_EXHAUSTED(0x89) on the TH(Chip-tool) log and below is the sample log provided for the raspi platform: @@ -907,7 +1013,7 @@ tests: field set to 0x0000." PICS: S.S.C03.Rsp verification: | - ./chip-tool scenesmanagement remove-all-scenes 0x0000 1 1 + ./chipt-tool scenesmanagement remove-all-scenes 0x0000 1 1 Verify the RemoveAllScenesResponse with following fields: Status is SUCCESS @@ -932,21 +1038,58 @@ tests: should send 'empty' report data since there is no update for this attribute for TH2)." verification: | - ./chip-tool scenesmanagement subscribe fabric-scene-info 100 200 1 1 + ./chipt-tool scenesmanagement subscribe fabric-scene-info 100 200 1 1 Verify that the DUT sends a report data to TH1 for FabricSceneInfo after the MinIntervalFloor time; store the RemainingCapacity field from this fabric’s entry the reported in FabricSceneInfo into Remaining1stCapacity; verify Remaining1stCapacity equals (MaxRemainingCapacity) on TH1(Chip-tool) log and below is the sample log provided for the raspi platform: - [1705915725.959835][21417:21419] CHIP:DMG: } - [1705915725.959889][21417:21419] CHIP:TOO: Endpoint: 1 Cluster: 0x0000_0062 Attribute 0x0000_0002 DataVersion: 2122634911 - [1705915725.959913][21417:21419] CHIP:TOO: FabricSceneInfo: 1 entries - [1705915725.959926][21417:21419] CHIP:TOO: [1]: { - [1705915725.959929][21417:21419] CHIP:TOO: SceneCount: 0 - [1705915725.959931][21417:21419] CHIP:TOO: CurrentScene: 0 - [1705915725.959935][21417:21419] CHIP:TOO: CurrentGroup: 0 - [1705915725.959939][21417:21419] CHIP:TOO: SceneValid: FALSE - [1705915725.959943][21417:21419] CHIP:TOO: RemainingCapacity: 7 - [1705915725.959945][21417:21419] CHIP:TOO: FabricIndex: 1 - [1705915725.959948][21417:21419] CHIP:TOO: } + [1707984148.067226][18155:18157] CHIP:DMG: ReportDataMessage = + [1707984148.067240][18155:18157] CHIP:DMG: { + [1707984148.067250][18155:18157] CHIP:DMG: SubscriptionId = 0x53cf322d, + [1707984148.067258][18155:18157] CHIP:DMG: AttributeReportIBs = + [1707984148.067280][18155:18157] CHIP:DMG: [ + [1707984148.067295][18155:18157] CHIP:DMG: AttributeReportIB = + [1707984148.067320][18155:18157] CHIP:DMG: { + [1707984148.067331][18155:18157] CHIP:DMG: AttributeDataIB = + [1707984148.067343][18155:18157] CHIP:DMG: { + [1707984148.067355][18155:18157] CHIP:DMG: DataVersion = 0xc9875f20, + [1707984148.067367][18155:18157] CHIP:DMG: AttributePathIB = + [1707984148.067381][18155:18157] CHIP:DMG: { + [1707984148.067397][18155:18157] CHIP:DMG: Endpoint = 0x1, + [1707984148.067411][18155:18157] CHIP:DMG: Cluster = 0x62, + [1707984148.067431][18155:18157] CHIP:DMG: Attribute = 0x0000_0002, + [1707984148.067443][18155:18157] CHIP:DMG: } + [1707984148.067462][18155:18157] CHIP:DMG: + [1707984148.067474][18155:18157] CHIP:DMG: Data = [ + [1707984148.067488][18155:18157] CHIP:DMG: + [1707984148.067502][18155:18157] CHIP:DMG: { + [1707984148.067516][18155:18157] CHIP:DMG: 0x0 = 0, + [1707984148.067531][18155:18157] CHIP:DMG: 0x1 = 0, + [1707984148.067545][18155:18157] CHIP:DMG: 0x2 = 0, + [1707984148.067561][18155:18157] CHIP:DMG: 0x3 = false, + [1707984148.067575][18155:18157] CHIP:DMG: 0x4 = 7, + [1707984148.067589][18155:18157] CHIP:DMG: 0xfe = 1, + [1707984148.067603][18155:18157] CHIP:DMG: }, + [1707984148.067618][18155:18157] CHIP:DMG: ], + [1707984148.067629][18155:18157] CHIP:DMG: }, + [1707984148.067654][18155:18157] CHIP:DMG: + [1707984148.067664][18155:18157] CHIP:DMG: }, + [1707984148.067687][18155:18157] CHIP:DMG: + [1707984148.067696][18155:18157] CHIP:DMG: ], + [1707984148.067722][18155:18157] CHIP:DMG: + [1707984148.067733][18155:18157] CHIP:DMG: InteractionModelRevision = 11 + [1707984148.067744][18155:18157] CHIP:DMG: } + [1707984148.067925][18155:18157] CHIP:TOO: Endpoint: 1 Cluster: 0x0000_0062 Attribute 0x0000_0002 DataVersion: 3381092128 + [1707984148.067967][18155:18157] CHIP:TOO: FabricSceneInfo: 1 entries + [1707984148.067999][18155:18157] CHIP:TOO: [1]: { + [1707984148.068011][18155:18157] CHIP:TOO: SceneCount: 0 + [1707984148.068023][18155:18157] CHIP:TOO: CurrentScene: 0 + [1707984148.068033][18155:18157] CHIP:TOO: CurrentGroup: 0 + [1707984148.068045][18155:18157] CHIP:TOO: SceneValid: FALSE + [1707984148.068057][18155:18157] CHIP:TOO: RemainingCapacity: 7 + [1707984148.068068][18155:18157] CHIP:TOO: FabricIndex: 1 + [1707984148.068079][18155:18157] CHIP:TOO: } + + Verify that the DUT does not send report data to TH2 for FabricSceneInfo after the MinIntervalFloor time with updated value (it should send 'empty' report data since there is no update for this attribute for TH2). disabled: true - label: @@ -954,7 +1097,7 @@ tests: field set to 0x0000." PICS: S.S.C03.Rsp verification: | - ./chip-tool scenesmanagement remove-all-scenes 0x0000 2 1 --commissioner-name beta + ./chipt-tool scenesmanagement remove-all-scenes 0x0000 2 1 --commissioner-name beta Verify the RemoveAllScenesResponse with following fields: Status is SUCCESS From 116c28fb52228ccaeb96d985f5a4609e23db6a9f Mon Sep 17 00:00:00 2001 From: yunhanw-google Date: Fri, 16 Feb 2024 20:16:18 -0800 Subject: [PATCH 011/385] fix report status in android (#32167) --- src/controller/java/AndroidCallbacks.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/controller/java/AndroidCallbacks.cpp b/src/controller/java/AndroidCallbacks.cpp index cc6107cae3a431..eb6e8b1a5f255b 100644 --- a/src/controller/java/AndroidCallbacks.cpp +++ b/src/controller/java/AndroidCallbacks.cpp @@ -281,9 +281,8 @@ void ReportCallback::OnAttributeData(const app::ConcreteDataAttributePath & aPat jobject wrapperCallback = mWrapperCallbackRef.ObjectRef(); jobject nodeState = GetNodeStateObj(env, mNodeStateClassSignature, wrapperCallback); - if (aStatus.IsFailure()) + { - ChipLogError(Controller, "Receive bad status %s", ErrorStr(aStatus.ToChipError())); // Add Attribute Status to wrapperCallback jmethodID addAttributeStatusMethod = nullptr; err = JniReferences::GetInstance().FindMethod(env, nodeState, "addAttributeStatus", "(IJJILjava/lang/Integer;)V", @@ -305,8 +304,10 @@ void ReportCallback::OnAttributeData(const app::ConcreteDataAttributePath & aPat static_cast(aPath.mClusterId), static_cast(aPath.mAttributeId), static_cast(aStatus.mStatus), jClusterState); VerifyOrReturn(!env->ExceptionCheck(), env->ExceptionDescribe()); - return; } + + VerifyOrReturn(aStatus.IsSuccess(), ChipLogError(Controller, "Receive bad status %s", ErrorStr(aStatus.ToChipError())); + aPath.LogPath()); VerifyOrReturn(apData != nullptr, ChipLogError(Controller, "Receive empty apData"); aPath.LogPath()); TLV::TLVReader readerForJavaTLV; @@ -415,9 +416,8 @@ void ReportCallback::OnEventData(const app::EventHeader & aEventHeader, TLV::TLV ChipLogError(Controller, "mReportCallbackRef is not valid in %s", __func__)); jobject wrapperCallback = mWrapperCallbackRef.ObjectRef(); jobject nodeState = GetNodeStateObj(env, mNodeStateClassSignature, wrapperCallback); - if (apStatus != nullptr && apStatus->IsFailure()) + if (apStatus != nullptr) { - ChipLogError(Controller, "Receive bad status %s", ErrorStr(apStatus->ToChipError())); // Add Event Status to NodeState jmethodID addEventStatusMethod; err = JniReferences::GetInstance().FindMethod(env, nodeState, "addEventStatus", "(IJJILjava/lang/Integer;)V", From 1da449efc6738ee5e5dc1ab9a45433d109837b31 Mon Sep 17 00:00:00 2001 From: Justin Wood Date: Fri, 16 Feb 2024 20:25:05 -0800 Subject: [PATCH 012/385] Implement time sync for darwin (#32185) * Implement time sync for darwin * Restyled by whitespace * Restyled by clang-format * Fixing format string * Restyled by clang-format --------- Co-authored-by: Restyled.io --- src/darwin/Framework/CHIP/MTRConversion.h | 12 + src/darwin/Framework/CHIP/MTRConversion.mm | 33 ++- src/darwin/Framework/CHIP/MTRDevice.mm | 244 ++++++++++++++++++++- 3 files changed, 283 insertions(+), 6 deletions(-) diff --git a/src/darwin/Framework/CHIP/MTRConversion.h b/src/darwin/Framework/CHIP/MTRConversion.h index 543d80968566c6..b14f4c240f9f67 100644 --- a/src/darwin/Framework/CHIP/MTRConversion.h +++ b/src/darwin/Framework/CHIP/MTRConversion.h @@ -46,6 +46,18 @@ inline NSDate * MatterEpochSecondsAsDate(uint32_t matterEpochSeconds) */ bool DateToMatterEpochSeconds(NSDate * date, uint32_t & epoch); +/** + * Returns whether the conversion could be performed. Will return false if the + * passed-in date is our of the range representable as a Matter epoch-s value. + */ +bool DateToMatterEpochMilliseconds(NSDate * date, uint64_t & matterEpochMilliseconds); + +/** + * Returns whether the conversion could be performed. Will return false if the + * passed-in date is our of the range representable as a Matter epoch-s value. + */ +bool DateToMatterEpochMicroseconds(NSDate * date, uint64_t & matterEpochMicroseconds); + /** * Utilities for converting between NSSet and chip::CATValues. */ diff --git a/src/darwin/Framework/CHIP/MTRConversion.mm b/src/darwin/Framework/CHIP/MTRConversion.mm index c6ba6ec52fbf32..5e657b9330a8e5 100644 --- a/src/darwin/Framework/CHIP/MTRConversion.mm +++ b/src/darwin/Framework/CHIP/MTRConversion.mm @@ -63,18 +63,41 @@ CHIP_ERROR SetToCATValues(NSSet * catSet, chip::CATValues & values) bool DateToMatterEpochSeconds(NSDate * date, uint32_t & matterEpochSeconds) { - auto timeSinceUnixEpoch = date.timeIntervalSince1970; - if (timeSinceUnixEpoch < static_cast(chip::kChipEpochSecondsSinceUnixEpoch)) { - // This is a pre-Matter-epoch time, and cannot be represented in epoch-s. + uint64_t matterEpochMicroseconds = 0; + if (!DateToMatterEpochMicroseconds(date, matterEpochMicroseconds)) { + // Could not convert time return false; } - auto timeSinceMatterEpoch = timeSinceUnixEpoch - chip::kChipEpochSecondsSinceUnixEpoch; + uint64_t timeSinceMatterEpoch = matterEpochMicroseconds / chip::kMicrosecondsPerSecond; if (timeSinceMatterEpoch > UINT32_MAX) { // Too far into the future. return false; } - matterEpochSeconds = static_cast(timeSinceMatterEpoch); return true; } + +bool DateToMatterEpochMilliseconds(NSDate * date, uint64_t & matterEpochMilliseconds) +{ + uint64_t matterEpochMicroseconds = 0; + if (!DateToMatterEpochMicroseconds(date, matterEpochMicroseconds)) { + // Could not convert time + return false; + } + + matterEpochMilliseconds = matterEpochMicroseconds / chip::kMicrosecondsPerMillisecond; + return true; +} + +bool DateToMatterEpochMicroseconds(NSDate * date, uint64_t & matterEpochMicroseconds) +{ + uint64_t timeSinceUnixEpoch = static_cast(date.timeIntervalSince1970 * chip::kMicrosecondsPerSecond); + if (timeSinceUnixEpoch < chip::kChipEpochUsSinceUnixEpoch) { + // This is a pre-Matter-epoch time, and cannot be represented as an epoch time value. + return false; + } + + matterEpochMicroseconds = timeSinceUnixEpoch - chip::kChipEpochUsSinceUnixEpoch; + return true; +} diff --git a/src/darwin/Framework/CHIP/MTRDevice.mm b/src/darwin/Framework/CHIP/MTRDevice.mm index 2307a25d22361f..1b42caecf80c76 100644 --- a/src/darwin/Framework/CHIP/MTRDevice.mm +++ b/src/darwin/Framework/CHIP/MTRDevice.mm @@ -20,11 +20,13 @@ #import "MTRAsyncWorkQueue.h" #import "MTRAttributeSpecifiedCheck.h" +#import "MTRBaseClusters.h" #import "MTRBaseDevice_Internal.h" #import "MTRBaseSubscriptionCallback.h" #import "MTRCluster.h" #import "MTRClusterConstants.h" #import "MTRCommandTimedCheck.h" +#import "MTRConversion.h" #import "MTRDefines_Internal.h" #import "MTRDeviceController_Internal.h" #import "MTRDevice_Internal.h" @@ -143,6 +145,9 @@ typedef NS_ENUM(NSUInteger, MTRDeviceWorkItemDuplicateTypeID) { @interface MTRDevice () @property (nonatomic, readonly) os_unfair_lock lock; // protects the caches and device state +// protects against concurrent time updates by guarding timeUpdateScheduled flag which manages time updates scheduling, +// and protects device calls to setUTCTime and setDSTOffset +@property (nonatomic, readonly) os_unfair_lock timeSyncLock; @property (nonatomic) chip::FabricIndex fabricIndex; @property (nonatomic) MTRWeakReference> * weakDelegate; @property (nonatomic) dispatch_queue_t delegateQueue; @@ -190,6 +195,8 @@ @interface MTRDevice () @property (nonatomic) BOOL expirationCheckScheduled; +@property (nonatomic) BOOL timeUpdateScheduled; + @property (nonatomic) NSDate * estimatedStartTimeFromGeneralDiagnosticsUpTime; @property (nonatomic) NSMutableDictionary * temporaryMetaDataCache; @@ -224,6 +231,7 @@ - (instancetype)initWithNodeID:(NSNumber *)nodeID controller:(MTRDeviceControlle { if (self = [super init]) { _lock = OS_UNFAIR_LOCK_INIT; + _timeSyncLock = OS_UNFAIR_LOCK_INIT; _nodeID = [nodeID copy]; _fabricIndex = controller.fabricIndex; _deviceController = controller; @@ -249,6 +257,226 @@ + (MTRDevice *)deviceWithNodeID:(NSNumber *)nodeID controller:(MTRDeviceControll return [controller deviceForNodeID:nodeID]; } +#pragma mark - Time Synchronization + +- (void)_setTimeOnDevice +{ + NSDate * now = [NSDate date]; + // If no date available, error + if (!now) { + MTR_LOG_ERROR("%@ Could not retrieve current date. Unable to setUTCTime on endpoints.", self); + return; + } + + NSTimeZone * localTimeZone = [NSTimeZone localTimeZone]; + BOOL setDST = TRUE; + if (!localTimeZone) { + MTR_LOG_ERROR("%@ Could not retrieve local time zone. Unable to setDSTOffset on endpoints.", self); + setDST = FALSE; + } + + uint64_t matterEpochTimeMicroseconds = 0; + uint64_t nextDSTInMatterEpochTimeMicroseconds = 0; + if (!DateToMatterEpochMicroseconds(now, matterEpochTimeMicroseconds)) { + MTR_LOG_ERROR("%@ Could not convert NSDate (%@) to Matter Epoch Time. Unable to setUTCTime on endpoints.", self, now); + return; + } + + int32_t dstOffset = 0; + if (setDST) { + NSTimeInterval dstOffsetAsInterval = [localTimeZone daylightSavingTimeOffsetForDate:now]; + dstOffset = int32_t(dstOffsetAsInterval); + + // Calculate time to next DST. This is needed when we set the current DST. + NSDate * nextDSTTransitionDate = [localTimeZone nextDaylightSavingTimeTransition]; + if (!DateToMatterEpochMicroseconds(nextDSTTransitionDate, nextDSTInMatterEpochTimeMicroseconds)) { + MTR_LOG_ERROR("%@ Could not convert NSDate (%@) to Matter Epoch Time. Unable to setDSTOffset on endpoints.", self, nextDSTTransitionDate); + setDST = FALSE; + } + } + + // Set Time on each Endpoint with a Time Synchronization Cluster Server + NSArray * endpointsToSync = [self _endpointsWithTimeSyncClusterServer]; + for (NSNumber * endpoint in endpointsToSync) { + MTR_LOG_DEBUG("%@ Setting Time on Endpoint %@", self, endpoint); + [self _setUTCTime:matterEpochTimeMicroseconds withGranularity:MTRTimeSynchronizationGranularityMicrosecondsGranularity forEndpoint:endpoint]; + if (setDST) { + [self _setDSTOffset:dstOffset validStarting:0 validUntil:nextDSTInMatterEpochTimeMicroseconds forEndpoint:endpoint]; + } + } +} + +- (void)_scheduleNextUpdate:(UInt64)nextUpdateInSeconds +{ + MTRWeakReference * weakSelf = [MTRWeakReference weakReferenceWithObject:self]; + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t) (nextUpdateInSeconds * NSEC_PER_SEC)), self.queue, ^{ + MTR_LOG_DEBUG("%@ Timer expired, start Device Time Update", self); + MTRDevice * strongSelf = weakSelf.strongObject; + if (strongSelf) { + [strongSelf _performScheduledTimeUpdate]; + } else { + MTR_LOG_DEBUG("%@ MTRDevice no longer valid. No Timer Scheduled will be scheduled for a Device Time Update.", self); + return; + } + }); + self.timeUpdateScheduled = YES; + MTR_LOG_DEBUG("%@ Timer Scheduled for next Device Time Update, in %llu seconds", self, nextUpdateInSeconds); +} + +// Time Updates are a day apart (this can be changed in the future) +#define MTR_DEVICE_TIME_UPDATE_DEFAULT_WAIT_TIME_SEC (24 * 60 * 60) +// assume lock is held +- (void)_updateDeviceTimeAndScheduleNextUpdate +{ + os_unfair_lock_assert_owner(&self->_timeSyncLock); + if (self.timeUpdateScheduled) { + MTR_LOG_DEBUG("%@ Device Time Update already scheduled", self); + return; + } + + [self _setTimeOnDevice]; + [self _scheduleNextUpdate:MTR_DEVICE_TIME_UPDATE_DEFAULT_WAIT_TIME_SEC]; +} + +- (void)_performScheduledTimeUpdate +{ + os_unfair_lock_lock(&self->_timeSyncLock); + // Device needs to still be reachable + if (self.state != MTRDeviceStateReachable) { + MTR_LOG_DEBUG("%@ Device is not reachable, canceling Device Time Updates.", self); + os_unfair_lock_unlock(&self->_timeSyncLock); + return; + } + // Device must not be invalidated + if (!self.timeUpdateScheduled) { + MTR_LOG_DEBUG("%@ Device Time Update is no longer scheduled, MTRDevice may have been invalidated.", self); + os_unfair_lock_unlock(&self->_timeSyncLock); + return; + } + self.timeUpdateScheduled = NO; + [self _updateDeviceTimeAndScheduleNextUpdate]; + os_unfair_lock_unlock(&self->_timeSyncLock); +} + +- (NSArray *)_endpointsWithTimeSyncClusterServer +{ + auto partsList = [self readAttributeWithEndpointID:@(0) clusterID:@(MTRClusterIDTypeDescriptorID) attributeID:@(MTRAttributeIDTypeClusterDescriptorAttributePartsListID) params:nil]; + NSMutableArray * endpointsOnDevice = [self arrayOfNumbersFromAttributeValue:partsList]; + if (!endpointsOnDevice) { + endpointsOnDevice = [[NSMutableArray alloc] init]; + } + // Add Root node! + [endpointsOnDevice addObject:@(0)]; + + NSMutableArray * endpointsWithTimeSyncCluster = [[NSMutableArray alloc] init]; + for (NSNumber * endpoint in endpointsOnDevice) { + // Get list of server clusters on endpoint + auto clusterList = [self readAttributeWithEndpointID:endpoint clusterID:@(MTRClusterIDTypeDescriptorID) attributeID:@(MTRAttributeIDTypeClusterDescriptorAttributeServerListID) params:nil]; + NSArray * clusterArray = [self arrayOfNumbersFromAttributeValue:clusterList]; + + if (clusterArray && [clusterArray containsObject:@(MTRClusterIDTypeTimeSynchronizationID)]) { + [endpointsWithTimeSyncCluster addObject:endpoint]; + } + } + MTR_LOG_DEBUG("%@ Device has following endpoints with Time Sync Cluster Server: %@", self, endpointsWithTimeSyncCluster); + return endpointsWithTimeSyncCluster; +} + +- (void)_setUTCTime:(UInt64)matterEpochTime withGranularity:(uint8_t)granularity forEndpoint:(NSNumber *)endpoint +{ + MTR_LOG_DEBUG(" %@ _setUTCTime with matterEpochTime: %llu, endpoint %@", self, matterEpochTime, endpoint); + MTRTimeSynchronizationClusterSetUTCTimeParams * params = [[MTRTimeSynchronizationClusterSetUTCTimeParams + alloc] init]; + params.utcTime = @(matterEpochTime); + params.granularity = @(granularity); + auto setUTCTimeResponseHandler = ^(id _Nullable response, NSError * _Nullable error) { + if (error) { + MTR_LOG_ERROR("%@ _setUTCTime failed on endpoint %@, with parameters %@, error: %@", self, endpoint, params, error); + } + }; + + [self _invokeKnownCommandWithEndpointID:endpoint + clusterID:@(MTRClusterIDTypeTimeSynchronizationID) + commandID:@(MTRCommandIDTypeClusterTimeSynchronizationCommandSetUTCTimeID) + commandPayload:params + expectedValues:nil + expectedValueInterval:nil + timedInvokeTimeout:nil + serverSideProcessingTimeout:params.serverSideProcessingTimeout + responseClass:nil + queue:self.queue + completion:setUTCTimeResponseHandler]; +} + +- (void)_setDSTOffset:(int32_t)dstOffset validStarting:(uint64_t)validStarting validUntil:(uint64_t)validUntil forEndpoint:(NSNumber *)endpoint +{ + MTR_LOG_DEBUG("%@ _setDSTOffset with offset: %d, validStarting: %llu, validUntil: %llu, endpoint %@", + self, + dstOffset, validStarting, validUntil, endpoint); + + MTRTimeSynchronizationClusterSetDSTOffsetParams * params = [[MTRTimeSynchronizationClusterSetDSTOffsetParams + alloc] init]; + MTRTimeSynchronizationClusterDSTOffsetStruct * dstOffsetStruct = [[MTRTimeSynchronizationClusterDSTOffsetStruct alloc] init]; + dstOffsetStruct.offset = @(dstOffset); + dstOffsetStruct.validStarting = @(validStarting); + dstOffsetStruct.validUntil = @(validUntil); + params.dstOffset = @[ dstOffsetStruct ]; + + auto setDSTOffsetResponseHandler = ^(id _Nullable response, NSError * _Nullable error) { + if (error) { + MTR_LOG_ERROR("%@ _setDSTOffset failed on endpoint %@, with parameters %@, error: %@", self, endpoint, params, error); + } + }; + + [self _invokeKnownCommandWithEndpointID:endpoint + clusterID:@(MTRClusterIDTypeTimeSynchronizationID) + commandID:@(MTRCommandIDTypeClusterTimeSynchronizationCommandSetDSTOffsetID) + commandPayload:params + expectedValues:nil + expectedValueInterval:nil + timedInvokeTimeout:nil + serverSideProcessingTimeout:params.serverSideProcessingTimeout + responseClass:nil + queue:self.queue + completion:setDSTOffsetResponseHandler]; +} + +- (NSMutableArray *)arrayOfNumbersFromAttributeValue:(NSDictionary *)dataDictionary +{ + if (![MTRArrayValueType isEqual:dataDictionary[MTRTypeKey]]) { + return nil; + } + + id value = dataDictionary[MTRValueKey]; + if (![value isKindOfClass:NSArray.class]) { + return nil; + } + + NSArray * valueArray = value; + __auto_type outputArray = [NSMutableArray arrayWithCapacity:valueArray.count]; + + for (id item in valueArray) { + if (![item isKindOfClass:NSDictionary.class]) { + return nil; + } + + NSDictionary * itemDictionary = item; + id data = itemDictionary[MTRDataKey]; + if (![data isKindOfClass:NSDictionary.class]) { + return nil; + } + + NSDictionary * dataDictionary = data; + id dataType = dataDictionary[MTRTypeKey]; + id dataValue = dataDictionary[MTRValueKey]; + if (![dataType isKindOfClass:NSString.class] || ![dataValue isKindOfClass:NSNumber.class]) { + return nil; + } + [outputArray addObject:dataValue]; + } + return outputArray; +} + #pragma mark Subscription and delegate handling // subscription intervals are in seconds @@ -287,6 +515,10 @@ - (void)invalidate [_asyncWorkQueue invalidate]; + os_unfair_lock_lock(&self->_timeSyncLock); + _timeUpdateScheduled = NO; + os_unfair_lock_unlock(&self->_timeSyncLock); + os_unfair_lock_lock(&self->_lock); _state = MTRDeviceStateUnknown; @@ -370,6 +602,8 @@ - (void)_changeState:(MTRDeviceState)state } } +// First Time Sync happens 2 minutes after reachability (this can be changed in the future) +#define MTR_DEVICE_TIME_UPDATE_INITIAL_WAIT_TIME_SEC (60 * 2) - (void)_handleSubscriptionEstablished { os_unfair_lock_lock(&self->_lock); @@ -380,6 +614,14 @@ - (void)_handleSubscriptionEstablished [self _changeState:MTRDeviceStateReachable]; os_unfair_lock_unlock(&self->_lock); + + os_unfair_lock_lock(&self->_timeSyncLock); + + if (!self.timeUpdateScheduled) { + [self _scheduleNextUpdate:MTR_DEVICE_TIME_UPDATE_INITIAL_WAIT_TIME_SEC]; + } + + os_unfair_lock_unlock(&self->_timeSyncLock); } - (void)_handleSubscriptionError:(NSError *)error @@ -893,7 +1135,7 @@ - (void)_setupSubscription return; } - MTR_LOG_DEFAULT("%@ Subscribe with data version list size %lu, reduced by %lu", self, dataVersions.count, dataVersionFilterListSizeReduction); + MTR_LOG_DEFAULT("%@ Subscribe with data version list size %lu, reduced by %lu", self, (unsigned long) dataVersions.count, (unsigned long) dataVersionFilterListSizeReduction); // Callback and ClusterStateCache and ReadClient will be deleted // when OnDone is called. From 663de6553fd73414b79f965180c4247556c37966 Mon Sep 17 00:00:00 2001 From: Andrei Litvin Date: Fri, 16 Feb 2024 23:27:10 -0500 Subject: [PATCH 013/385] Update `data_model` scraped XML version to latest spec and scraper (#32170) * Ran scraper 1.2.4 on the latest spec version * Add in-progress scraping * Remove odd comment parts from NetworkCommissioningCluster.xml * Removed old files, re-generated new ones * Remove comments again * Remove the cluster suffix in names of clusters * Fix parsing error * Fix direction logic * Fix direction key --- data_model/README.md | 2 +- data_model/clusters/ACL-Cluster.xml | 25 +- data_model/clusters/AccountLogin.xml | 33 +- .../clusters/AdminCommissioningCluster.xml | 19 +- data_model/clusters/AirQuality.xml | 5 + data_model/clusters/AlarmBase.xml | 9 +- data_model/clusters/ApplicationBasic.xml | 5 + data_model/clusters/ApplicationLauncher.xml | 12 +- data_model/clusters/AudioOutput.xml | 9 +- data_model/clusters/BallastConfiguration.xml | 5 + .../clusters/BasicInformationCluster.xml | 61 +-- data_model/clusters/Binding-Cluster.xml | 5 + data_model/clusters/BooleanState.xml | 5 + .../clusters/BooleanStateConfiguration.xml | 9 +- data_model/clusters/Channel.xml | 284 ++++++++++++- data_model/clusters/ColorControl.xml | 119 +++--- data_model/clusters/ContentAppObserver.xml | 8 +- data_model/clusters/ContentControl.xml | 36 +- data_model/clusters/ContentLauncher.xml | 91 ++++- .../clusters/DemandResponseLoadControl.xml | 103 ++++- data_model/clusters/Descriptor-Cluster.xml | 5 + .../clusters/DeviceEnergyManagement.xml | 21 +- data_model/clusters/DiagnosticLogsCluster.xml | 18 +- data_model/clusters/DiagnosticsEthernet.xml | 5 +- data_model/clusters/DiagnosticsGeneral.xml | 74 ++-- data_model/clusters/DiagnosticsSoftware.xml | 24 +- data_model/clusters/DiagnosticsThread.xml | 28 +- data_model/clusters/DiagnosticsWiFi.xml | 13 +- data_model/clusters/DishwasherAlarm.xml | 5 + data_model/clusters/DoorLock.xml | 263 ++++++++++--- data_model/clusters/EVSE-Attributes.xml | 45 --- data_model/clusters/EVSE-Classification.xml | 45 --- data_model/clusters/EVSE-ClusterID.xml | 45 --- data_model/clusters/EVSE-Commands.xml | 45 --- data_model/clusters/EVSE-DataTypes.xml | 45 --- data_model/clusters/EVSE-Definitions.xml | 45 --- data_model/clusters/EVSE-Dependencies.xml | 45 --- data_model/clusters/EVSE-Events.xml | 45 --- data_model/clusters/EVSE-Features.xml | 45 --- data_model/clusters/EVSE-RevisionHistory.xml | 45 --- .../clusters/ElectricalEnergyMeasurement.xml | 59 ++- .../clusters/ElectricalPowerMeasurement.xml | 67 ++++ data_model/clusters/EnergyCalendar.xml | 5 + data_model/clusters/EnergyEVSE.xml | 20 +- data_model/clusters/EnergyPreference.xml | 5 + data_model/clusters/EnergyPrice.xml | 9 +- data_model/clusters/FanControl.xml | 7 +- data_model/clusters/FlowMeasurement.xml | 5 + .../clusters/GeneralCommissioningCluster.xml | 5 +- .../clusters/Group-Key-Management-Cluster.xml | 52 +-- data_model/clusters/Groups.xml | 21 +- data_model/clusters/ICDManagement.xml | 51 ++- data_model/clusters/Identify.xml | 9 +- .../clusters/IlluminanceMeasurement.xml | 5 + data_model/clusters/KeypadInput.xml | 8 +- ...ml => Label-Cluster-FixedLabelCluster.xml} | 5 + ...bel.xml => Label-Cluster-LabelCluster.xml} | 5 + ...xml => Label-Cluster-UserLabelCluster.xml} | 5 + data_model/clusters/LaundryDryerControls.xml | 3 + data_model/clusters/LaundryWasherControls.xml | 3 + data_model/clusters/LevelControl.xml | 21 +- .../clusters/LocalizationConfiguration.xml | 13 +- .../clusters/LocalizationTimeFormat.xml | 6 +- data_model/clusters/LocalizationUnit.xml | 3 + data_model/clusters/LowPower.xml | 7 +- data_model/clusters/MediaInput.xml | 13 +- data_model/clusters/MediaPlayback.xml | 251 +++++++++++- data_model/clusters/Messages.xml | 11 +- data_model/clusters/MicrowaveOvenControl.xml | 11 +- data_model/clusters/ModeBase.xml | 5 +- data_model/clusters/ModeSelect.xml | 5 +- .../clusters/Mode_DeviceEnergyManagement.xml | 5 + data_model/clusters/Mode_Dishwasher.xml | 5 + data_model/clusters/Mode_EVSE.xml | 5 + data_model/clusters/Mode_LaundryWasher.xml | 5 + data_model/clusters/Mode_MicrowaveOven.xml | 11 +- data_model/clusters/Mode_Oven.xml | 5 + data_model/clusters/Mode_RVCClean.xml | 5 + data_model/clusters/Mode_RVCRun.xml | 5 + data_model/clusters/Mode_Refrigerator.xml | 5 + data_model/clusters/Mode_WaterHeater.xml | 5 + .../clusters/NetworkCommissioningCluster.xml | 177 ++++++--- .../clusters/NetworkIdentityManagement.xml | 11 +- data_model/clusters/OTAProvider.xml | 52 +-- data_model/clusters/OTARequestor.xml | 24 +- data_model/clusters/OTASoftwareUpdate.xml | 2 - data_model/clusters/OccupancySensing.xml | 5 + data_model/clusters/OnOff.xml | 17 +- .../clusters/OperationalCredentialCluster.xml | 79 ++-- data_model/clusters/OperationalState.xml | 50 +++ data_model/clusters/OperationalState_Oven.xml | 5 + data_model/clusters/OperationalState_RVC.xml | 25 +- data_model/clusters/PowerSourceCluster.xml | 44 ++- .../PowerSourceConfigurationCluster.xml | 5 +- data_model/clusters/PowerTopology.xml | 5 + data_model/clusters/PressureMeasurement.xml | 5 + .../clusters/PumpConfigurationControl.xml | 204 +++++++++- data_model/clusters/RefrigeratorAlarm.xml | 8 +- data_model/clusters/ResourceMonitoring.xml | 4 +- data_model/clusters/Scenes.xml | 37 +- data_model/clusters/SmokeCOAlarm.xml | 7 +- data_model/clusters/Switch.xml | 3 + data_model/clusters/TargetNavigator.xml | 29 +- data_model/clusters/TemperatureControl.xml | 56 ++- .../clusters/TemperatureMeasurement.xml | 5 + data_model/clusters/Thermostat.xml | 372 +++++++++++++++++- .../ThermostatUserInterfaceConfiguration.xml | 3 + .../ThreadBorderRouterDiagnostics.xml | 11 +- data_model/clusters/TimeSync.xml | 36 +- .../clusters/ValveConfigurationControl.xml | 9 +- data_model/clusters/WakeOnLAN.xml | 7 +- .../clusters/WaterContentMeasurement.xml | 5 + data_model/clusters/WaterHeaterManagement.xml | 9 +- data_model/clusters/WiFiNetworkManagement.xml | 10 +- data_model/clusters/WindowCovering.xml | 19 +- ...xml => bridge-clusters-ActionsCluster.xml} | 52 +-- ...-BridgedDeviceBasicInformationCluster.xml} | 10 +- data_model/clusters/energy_management.xml | 2 + .../clusters/network_infrastructure.xml | 2 +- data_model/device_types/BaseDeviceType.xml | 19 - data_model/device_types/Cooktop.xml | 3 - .../DeviceEnergyManagement.xml} | 80 +--- data_model/device_types/EVSE.xml | 22 -- data_model/device_types/Thermostat.xml | 4 +- data_model/scraper_version | 2 +- data_model/spec_sha | 2 +- scripts/spec_xml/generate_spec_xml.py | 2 +- src/python_testing/spec_parsing_support.py | 3 + 128 files changed, 2824 insertions(+), 1221 deletions(-) delete mode 100644 data_model/clusters/EVSE-Attributes.xml delete mode 100644 data_model/clusters/EVSE-Classification.xml delete mode 100644 data_model/clusters/EVSE-ClusterID.xml delete mode 100644 data_model/clusters/EVSE-Commands.xml delete mode 100644 data_model/clusters/EVSE-DataTypes.xml delete mode 100644 data_model/clusters/EVSE-Definitions.xml delete mode 100644 data_model/clusters/EVSE-Dependencies.xml delete mode 100644 data_model/clusters/EVSE-Events.xml delete mode 100644 data_model/clusters/EVSE-Features.xml delete mode 100644 data_model/clusters/EVSE-RevisionHistory.xml rename data_model/clusters/{Label-Cluster-FixedLabel.xml => Label-Cluster-FixedLabelCluster.xml} (96%) rename data_model/clusters/{Label-Cluster-Label.xml => Label-Cluster-LabelCluster.xml} (96%) rename data_model/clusters/{Label-Cluster-UserLabel.xml => Label-Cluster-UserLabelCluster.xml} (96%) rename data_model/clusters/{bridge-clusters-Actions.xml => bridge-clusters-ActionsCluster.xml} (87%) rename data_model/clusters/{bridge-clusters-BridgedDeviceBasicInformation.xml => bridge-clusters-BridgedDeviceBasicInformationCluster.xml} (95%) rename data_model/{clusters/Timer.xml => device_types/DeviceEnergyManagement.xml} (55%) diff --git a/data_model/README.md b/data_model/README.md index 36f38cae0ff1f8..a26b1c4ff65558 100644 --- a/data_model/README.md +++ b/data_model/README.md @@ -17,7 +17,7 @@ update the spec XML files, however this is not done automatically. You will require access to the following tools locally: - `scraper`. A binary copy generally available - [here](https://github.com/csa-data-model/projects/tree/main/DM-Editor/bin/1.2.0/scrape) + [here](https://github.com/csa-data-model/projects/tree/main/DM-Editor/bin/scrape) - Specification repository checkout from https://github.com/CHIP-Specifications/connectedhomeip-spec diff --git a/data_model/clusters/ACL-Cluster.xml b/data_model/clusters/ACL-Cluster.xml index 9ef2f500e96e01..b965eb84234e0d 100644 --- a/data_model/clusters/ACL-Cluster.xml +++ b/data_model/clusters/ACL-Cluster.xml @@ -55,10 +55,13 @@ Connectivity Standards Alliance 508 Second Street, Suite 206 Davis, CA 95616, USA --> - + + + + @@ -112,25 +115,27 @@ Davis, CA 95616, USA - + + - + - + + - + - + - + @@ -150,12 +155,14 @@ Davis, CA 95616, USA - + + - + + diff --git a/data_model/clusters/AccountLogin.xml b/data_model/clusters/AccountLogin.xml index 91f675eaba693b..db87d05dc74902 100644 --- a/data_model/clusters/AccountLogin.xml +++ b/data_model/clusters/AccountLogin.xml @@ -54,14 +54,20 @@ This notice and disclaimer must be included on all copies of this document. Connectivity Standards Alliance 508 Second Street, Suite 206 Davis, CA 95616, USA + +:xrefstyle: basic --> - + + + + + - + @@ -70,14 +76,14 @@ Davis, CA 95616, USA - + - + @@ -86,12 +92,27 @@ Davis, CA 95616, USA - + + + + - + + + + + + + + + + + + + \ No newline at end of file diff --git a/data_model/clusters/AdminCommissioningCluster.xml b/data_model/clusters/AdminCommissioningCluster.xml index b94b25ec5520c2..eea41bc65b6e2c 100644 --- a/data_model/clusters/AdminCommissioningCluster.xml +++ b/data_model/clusters/AdminCommissioningCluster.xml @@ -1,7 +1,5 @@ + + + diff --git a/data_model/clusters/AlarmBase.xml b/data_model/clusters/AlarmBase.xml index 9ba73c14ab6e63..f4ffc6344a8b90 100644 --- a/data_model/clusters/AlarmBase.xml +++ b/data_model/clusters/AlarmBase.xml @@ -54,11 +54,16 @@ This notice and disclaimer must be included on all copies of this document. Connectivity Standards Alliance 508 Second Street, Suite 206 Davis, CA 95616, USA + +:xrefstyle: basic --> + + + @@ -91,7 +96,7 @@ Davis, CA 95616, USA - + @@ -100,7 +105,7 @@ Davis, CA 95616, USA - + diff --git a/data_model/clusters/ApplicationBasic.xml b/data_model/clusters/ApplicationBasic.xml index 086839a2338cfc..fa197a8d1e5cca 100644 --- a/data_model/clusters/ApplicationBasic.xml +++ b/data_model/clusters/ApplicationBasic.xml @@ -54,11 +54,16 @@ This notice and disclaimer must be included on all copies of this document. Connectivity Standards Alliance 508 Second Street, Suite 206 Davis, CA 95616, USA + +:xrefstyle: basic --> + + + diff --git a/data_model/clusters/ApplicationLauncher.xml b/data_model/clusters/ApplicationLauncher.xml index 5d716981a55d38..6b84436e73d42d 100644 --- a/data_model/clusters/ApplicationLauncher.xml +++ b/data_model/clusters/ApplicationLauncher.xml @@ -54,11 +54,16 @@ This notice and disclaimer must be included on all copies of this document. Connectivity Standards Alliance 508 Second Street, Suite 206 Davis, CA 95616, USA + +:xrefstyle: basic --> + + + @@ -111,7 +116,7 @@ Davis, CA 95616, USA - + @@ -124,7 +129,7 @@ Davis, CA 95616, USA - + @@ -134,7 +139,7 @@ Davis, CA 95616, USA - + @@ -145,7 +150,6 @@ Davis, CA 95616, USA - diff --git a/data_model/clusters/AudioOutput.xml b/data_model/clusters/AudioOutput.xml index 176e75b16c19c9..468ba2750152a6 100644 --- a/data_model/clusters/AudioOutput.xml +++ b/data_model/clusters/AudioOutput.xml @@ -54,11 +54,16 @@ This notice and disclaimer must be included on all copies of this document. Connectivity Standards Alliance 508 Second Street, Suite 206 Davis, CA 95616, USA + +:xrefstyle: basic --> + + + @@ -111,14 +116,14 @@ Davis, CA 95616, USA - + - + diff --git a/data_model/clusters/BallastConfiguration.xml b/data_model/clusters/BallastConfiguration.xml index 416b8cd7014beb..f25bef22cb4b6c 100644 --- a/data_model/clusters/BallastConfiguration.xml +++ b/data_model/clusters/BallastConfiguration.xml @@ -54,6 +54,8 @@ This notice and disclaimer must be included on all copies of this document. Connectivity Standards Alliance 508 Second Street, Suite 206 Davis, CA 95616, USA + +:xrefstyle: basic --> @@ -62,6 +64,9 @@ Davis, CA 95616, USA + + + diff --git a/data_model/clusters/BasicInformationCluster.xml b/data_model/clusters/BasicInformationCluster.xml index 87fa765f65b2f5..82b9283b0d21d6 100644 --- a/data_model/clusters/BasicInformationCluster.xml +++ b/data_model/clusters/BasicInformationCluster.xml @@ -59,8 +59,11 @@ Davis, CA 95616, USA - + + + + @@ -175,50 +178,50 @@ Davis, CA 95616, USA - + - + - + - + - + - + - + - + - + - + - + @@ -226,41 +229,41 @@ Davis, CA 95616, USA - + - + - + - + - + - + - + - + - + - + - + - + @@ -271,11 +274,11 @@ Davis, CA 95616, USA - + - + @@ -293,6 +296,12 @@ Davis, CA 95616, USA + + + + + + diff --git a/data_model/clusters/Binding-Cluster.xml b/data_model/clusters/Binding-Cluster.xml index 95f68f1d6ff995..eca291a7d895ff 100644 --- a/data_model/clusters/Binding-Cluster.xml +++ b/data_model/clusters/Binding-Cluster.xml @@ -54,11 +54,16 @@ This notice and disclaimer must be included on all copies of this document. Connectivity Standards Alliance 508 Second Street, Suite 206 Davis, CA 95616, USA + +:xrefstyle: basic --> + + + diff --git a/data_model/clusters/BooleanState.xml b/data_model/clusters/BooleanState.xml index 5b298075fbaefc..9205310c58f2be 100644 --- a/data_model/clusters/BooleanState.xml +++ b/data_model/clusters/BooleanState.xml @@ -54,11 +54,16 @@ This notice and disclaimer must be included on all copies of this document. Connectivity Standards Alliance 508 Second Street, Suite 206 Davis, CA 95616, USA + +:xrefstyle: basic --> + + + diff --git a/data_model/clusters/BooleanStateConfiguration.xml b/data_model/clusters/BooleanStateConfiguration.xml index 160cb7fadb7a93..dc17f93a7295f0 100644 --- a/data_model/clusters/BooleanStateConfiguration.xml +++ b/data_model/clusters/BooleanStateConfiguration.xml @@ -54,11 +54,16 @@ This notice and disclaimer must be included on all copies of this document. Connectivity Standards Alliance 508 Second Street, Suite 206 Davis, CA 95616, USA + +:xrefstyle: basic --> + + + @@ -164,7 +169,7 @@ Davis, CA 95616, USA - + @@ -173,7 +178,7 @@ Davis, CA 95616, USA - + diff --git a/data_model/clusters/Channel.xml b/data_model/clusters/Channel.xml index 9ace62ca720a53..1809f5262e7166 100644 --- a/data_model/clusters/Channel.xml +++ b/data_model/clusters/Channel.xml @@ -54,11 +54,17 @@ This notice and disclaimer must be included on all copies of this document. Connectivity Standards Alliance 508 Second Street, Suite 206 Davis, CA 95616, USA + +:xrefstyle: basic --> - + + + + + @@ -67,8 +73,28 @@ Davis, CA 95616, USA + + + + + + + + + + + + + + + + + + + + @@ -85,6 +111,17 @@ Davis, CA 95616, USA + + + + + + + + + + + @@ -101,6 +138,22 @@ Davis, CA 95616, USA + + + + + + + + + + + + + + + + @@ -117,6 +170,132 @@ Davis, CA 95616, USA + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -142,7 +321,7 @@ Davis, CA 95616, USA - + @@ -155,7 +334,6 @@ Davis, CA 95616, USA - @@ -170,7 +348,7 @@ Davis, CA 95616, USA - + @@ -180,12 +358,108 @@ Davis, CA 95616, USA - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/data_model/clusters/ColorControl.xml b/data_model/clusters/ColorControl.xml index c0b0655261b10b..b913009f852761 100644 --- a/data_model/clusters/ColorControl.xml +++ b/data_model/clusters/ColorControl.xml @@ -54,6 +54,8 @@ This notice and disclaimer must be included on all copies of this document. Connectivity Standards Alliance 508 Second Street, Suite 206 Davis, CA 95616, USA + +:xrefstyle: basic --> @@ -64,6 +66,9 @@ Davis, CA 95616, USA + + + @@ -123,19 +128,19 @@ Davis, CA 95616, USA - + - + - + - + - + @@ -158,13 +163,13 @@ Davis, CA 95616, USA - + - + - + @@ -356,16 +361,16 @@ Davis, CA 95616, USA - + - + - + - + @@ -434,7 +439,7 @@ Davis, CA 95616, USA - + @@ -449,7 +454,7 @@ Davis, CA 95616, USA - + @@ -460,16 +465,16 @@ Davis, CA 95616, USA - + - + - + - + @@ -489,23 +494,23 @@ Davis, CA 95616, USA - + - + - + - + - + @@ -524,23 +529,23 @@ Davis, CA 95616, USA - + - + - + - + - + @@ -562,7 +567,7 @@ Davis, CA 95616, USA - + @@ -584,23 +589,23 @@ Davis, CA 95616, USA - + - + - + - + - + @@ -619,23 +624,23 @@ Davis, CA 95616, USA - + - + - + - + - + @@ -657,7 +662,7 @@ Davis, CA 95616, USA - + @@ -683,7 +688,7 @@ Davis, CA 95616, USA - + @@ -709,7 +714,7 @@ Davis, CA 95616, USA - + @@ -729,7 +734,7 @@ Davis, CA 95616, USA - + @@ -753,7 +758,7 @@ Davis, CA 95616, USA - + @@ -775,7 +780,7 @@ Davis, CA 95616, USA - + @@ -800,7 +805,7 @@ Davis, CA 95616, USA - + @@ -821,7 +826,7 @@ Davis, CA 95616, USA - + @@ -846,7 +851,7 @@ Davis, CA 95616, USA - + @@ -871,7 +876,7 @@ Davis, CA 95616, USA - + @@ -899,13 +904,13 @@ Davis, CA 95616, USA - + - + - + @@ -914,10 +919,10 @@ Davis, CA 95616, USA - + - + @@ -939,7 +944,7 @@ Davis, CA 95616, USA - + @@ -957,7 +962,7 @@ Davis, CA 95616, USA - + @@ -986,7 +991,7 @@ Davis, CA 95616, USA - + diff --git a/data_model/clusters/ContentAppObserver.xml b/data_model/clusters/ContentAppObserver.xml index b426daa5ec3379..184cce14924cda 100644 --- a/data_model/clusters/ContentAppObserver.xml +++ b/data_model/clusters/ContentAppObserver.xml @@ -54,11 +54,16 @@ This notice and disclaimer must be included on all copies of this document. Connectivity Standards Alliance 508 Second Street, Suite 206 Davis, CA 95616, USA + +:xrefstyle: basic --> + + + @@ -71,7 +76,7 @@ Davis, CA 95616, USA - + @@ -84,7 +89,6 @@ Davis, CA 95616, USA - diff --git a/data_model/clusters/ContentControl.xml b/data_model/clusters/ContentControl.xml index b51bdff9397448..14996a7c28011a 100644 --- a/data_model/clusters/ContentControl.xml +++ b/data_model/clusters/ContentControl.xml @@ -59,6 +59,9 @@ Davis, CA 95616, USA + + + @@ -255,7 +258,7 @@ Davis, CA 95616, USA - + @@ -269,14 +272,13 @@ Davis, CA 95616, USA - + - @@ -285,15 +287,15 @@ Davis, CA 95616, USA - + - + - + @@ -307,7 +309,7 @@ Davis, CA 95616, USA - + @@ -317,19 +319,19 @@ Davis, CA 95616, USA - + - + - + @@ -339,7 +341,7 @@ Davis, CA 95616, USA - + @@ -349,7 +351,7 @@ Davis, CA 95616, USA - + @@ -359,7 +361,7 @@ Davis, CA 95616, USA - + @@ -369,7 +371,7 @@ Davis, CA 95616, USA - + @@ -379,7 +381,7 @@ Davis, CA 95616, USA - + @@ -389,7 +391,7 @@ Davis, CA 95616, USA - + @@ -398,7 +400,7 @@ Davis, CA 95616, USA - + diff --git a/data_model/clusters/ContentLauncher.xml b/data_model/clusters/ContentLauncher.xml index 2c310c6f2ccb3d..b8f80de2e51ea7 100644 --- a/data_model/clusters/ContentLauncher.xml +++ b/data_model/clusters/ContentLauncher.xml @@ -54,11 +54,17 @@ This notice and disclaimer must be included on all copies of this document. Connectivity Standards Alliance 508 Second Street, Suite 206 Davis, CA 95616, USA + +:xrefstyle: basic --> - + + + + + @@ -67,6 +73,15 @@ Davis, CA 95616, USA + + + + + + + + + @@ -119,12 +134,21 @@ Davis, CA 95616, USA - + + + + + + + + + + @@ -136,6 +160,16 @@ Davis, CA 95616, USA + + + + + + + + + + @@ -206,6 +240,27 @@ Davis, CA 95616, USA + + + + + + + + + + + + + + + + + + + + + @@ -220,6 +275,23 @@ Davis, CA 95616, USA + + + + + + + + + + + + + + + + + @@ -242,7 +314,7 @@ Davis, CA 95616, USA - + @@ -258,8 +330,15 @@ Davis, CA 95616, USA + + + + + + + - + @@ -273,9 +352,11 @@ Davis, CA 95616, USA + + + - diff --git a/data_model/clusters/DemandResponseLoadControl.xml b/data_model/clusters/DemandResponseLoadControl.xml index a5322bfb4f7206..206201b347612c 100644 --- a/data_model/clusters/DemandResponseLoadControl.xml +++ b/data_model/clusters/DemandResponseLoadControl.xml @@ -55,13 +55,16 @@ Connectivity Standards Alliance 508 Second Street, Suite 206 Davis, CA 95616, USA --> - + + + + @@ -192,6 +195,59 @@ Davis, CA 95616, USA + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -222,6 +278,41 @@ Davis, CA 95616, USA + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -361,14 +452,14 @@ Davis, CA 95616, USA - + - + @@ -376,14 +467,14 @@ Davis, CA 95616, USA - + - + @@ -394,7 +485,7 @@ Davis, CA 95616, USA - + diff --git a/data_model/clusters/Descriptor-Cluster.xml b/data_model/clusters/Descriptor-Cluster.xml index 9944d8a3f6ea4c..1b17fb4fdfdaea 100644 --- a/data_model/clusters/Descriptor-Cluster.xml +++ b/data_model/clusters/Descriptor-Cluster.xml @@ -54,12 +54,17 @@ This notice and disclaimer must be included on all copies of this document. Connectivity Standards Alliance 508 Second Street, Suite 206 Davis, CA 95616, USA + +:xrefstyle: basic --> + + + diff --git a/data_model/clusters/DeviceEnergyManagement.xml b/data_model/clusters/DeviceEnergyManagement.xml index 21f74a737d52cb..e493c5b332182e 100644 --- a/data_model/clusters/DeviceEnergyManagement.xml +++ b/data_model/clusters/DeviceEnergyManagement.xml @@ -54,6 +54,8 @@ This notice and disclaimer must be included on all copies of this document. Connectivity Standards Alliance 508 Second Street, Suite 206 Davis, CA 95616, USA + +:xrefstyle: basic --> @@ -61,6 +63,9 @@ Davis, CA 95616, USA + + + + @@ -487,13 +492,13 @@ Davis, CA 95616, USA - + - + @@ -507,7 +512,7 @@ Davis, CA 95616, USA - + @@ -521,13 +526,13 @@ Davis, CA 95616, USA - + - + @@ -545,7 +550,7 @@ Davis, CA 95616, USA - + @@ -560,7 +565,7 @@ Davis, CA 95616, USA - + diff --git a/data_model/clusters/DiagnosticLogsCluster.xml b/data_model/clusters/DiagnosticLogsCluster.xml index 14f995ca1855a6..5b67564b18f298 100644 --- a/data_model/clusters/DiagnosticLogsCluster.xml +++ b/data_model/clusters/DiagnosticLogsCluster.xml @@ -1,7 +1,5 @@ - + + + + @@ -138,11 +139,11 @@ Davis, CA 95616, USA - + - + @@ -221,7 +222,7 @@ Davis, CA 95616, USA - + diff --git a/data_model/clusters/DishwasherAlarm.xml b/data_model/clusters/DishwasherAlarm.xml index 7fda78ad163116..b3b67e2bffb500 100644 --- a/data_model/clusters/DishwasherAlarm.xml +++ b/data_model/clusters/DishwasherAlarm.xml @@ -54,11 +54,16 @@ This notice and disclaimer must be included on all copies of this document. Connectivity Standards Alliance + 508 Second Street, Suite 206 + Davis, CA 95616, USA + +:xrefstyle: short --> + + + diff --git a/data_model/clusters/DoorLock.xml b/data_model/clusters/DoorLock.xml index 4f84afca85ff1e..6284b973eb63e1 100644 --- a/data_model/clusters/DoorLock.xml +++ b/data_model/clusters/DoorLock.xml @@ -54,8 +54,10 @@ This notice and disclaimer must be included on all copies of this document. Connectivity Standards Alliance 508 Second Street, Suite 206 Davis, CA 95616, USA + +:xrefstyle: basic --> - + @@ -64,7 +66,11 @@ Davis, CA 95616, USA + + + + @@ -98,14 +104,19 @@ Davis, CA 95616, USA - - - - - - - - + + + + + + + + + + + + + @@ -119,6 +130,14 @@ Davis, CA 95616, USA + + + + + + + + @@ -201,6 +220,23 @@ Davis, CA 95616, USA + + + + + + + + + + + + + + + @@ -334,6 +370,21 @@ Davis, CA 95616, USA + + + + + + + + + + + + + + + @@ -482,6 +533,11 @@ Davis, CA 95616, USA + + + + + @@ -1053,9 +1109,84 @@ Davis, CA 95616, USA + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + @@ -1067,7 +1198,7 @@ Davis, CA 95616, USA - + @@ -1079,11 +1210,11 @@ Davis, CA 95616, USA - + - + @@ -1098,7 +1229,7 @@ Davis, CA 95616, USA - + @@ -1109,7 +1240,6 @@ Davis, CA 95616, USA - @@ -1138,7 +1268,7 @@ Davis, CA 95616, USA - + @@ -1165,7 +1295,7 @@ Davis, CA 95616, USA - + @@ -1181,7 +1311,6 @@ Davis, CA 95616, USA - @@ -1209,7 +1338,7 @@ Davis, CA 95616, USA - + @@ -1225,7 +1354,7 @@ Davis, CA 95616, USA - + @@ -1236,7 +1365,7 @@ Davis, CA 95616, USA - + @@ -1259,7 +1388,7 @@ Davis, CA 95616, USA - + @@ -1279,7 +1408,6 @@ Davis, CA 95616, USA - @@ -1293,7 +1421,7 @@ Davis, CA 95616, USA - + @@ -1326,7 +1454,7 @@ Davis, CA 95616, USA - + @@ -1341,7 +1469,6 @@ Davis, CA 95616, USA - @@ -1377,7 +1504,7 @@ Davis, CA 95616, USA - + @@ -1392,7 +1519,7 @@ Davis, CA 95616, USA - + @@ -1412,7 +1539,7 @@ Davis, CA 95616, USA - + @@ -1427,7 +1554,6 @@ Davis, CA 95616, USA - @@ -1450,7 +1576,7 @@ Davis, CA 95616, USA - + @@ -1465,7 +1591,7 @@ Davis, CA 95616, USA - + @@ -1484,7 +1610,7 @@ Davis, CA 95616, USA - + @@ -1495,7 +1621,6 @@ Davis, CA 95616, USA - @@ -1520,7 +1645,7 @@ Davis, CA 95616, USA - + @@ -1531,7 +1656,7 @@ Davis, CA 95616, USA - + @@ -1553,7 +1678,7 @@ Davis, CA 95616, USA - + @@ -1573,7 +1698,6 @@ Davis, CA 95616, USA - @@ -1587,7 +1711,7 @@ Davis, CA 95616, USA - + @@ -1615,7 +1739,7 @@ Davis, CA 95616, USA - + @@ -1631,7 +1755,6 @@ Davis, CA 95616, USA - @@ -1659,7 +1782,7 @@ Davis, CA 95616, USA - + @@ -1675,7 +1798,7 @@ Davis, CA 95616, USA - + @@ -1686,7 +1809,7 @@ Davis, CA 95616, USA - + @@ -1731,7 +1854,7 @@ Davis, CA 95616, USA - + @@ -1742,7 +1865,6 @@ Davis, CA 95616, USA - @@ -1792,7 +1914,7 @@ Davis, CA 95616, USA - + @@ -1844,7 +1966,7 @@ Davis, CA 95616, USA - + @@ -1885,7 +2007,6 @@ Davis, CA 95616, USA - @@ -1904,7 +2025,7 @@ Davis, CA 95616, USA - + @@ -1914,7 +2035,6 @@ Davis, CA 95616, USA - @@ -1939,8 +2059,15 @@ Davis, CA 95616, USA + + + + + + + - + @@ -1951,7 +2078,7 @@ Davis, CA 95616, USA - + @@ -1965,6 +2092,36 @@ Davis, CA 95616, USA + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/data_model/clusters/EVSE-Attributes.xml b/data_model/clusters/EVSE-Attributes.xml deleted file mode 100644 index 2d492a27c4c0a1..00000000000000 --- a/data_model/clusters/EVSE-Attributes.xml +++ /dev/null @@ -1,45 +0,0 @@ - - - \ No newline at end of file diff --git a/data_model/clusters/EVSE-Classification.xml b/data_model/clusters/EVSE-Classification.xml deleted file mode 100644 index 22df357be3e9d0..00000000000000 --- a/data_model/clusters/EVSE-Classification.xml +++ /dev/null @@ -1,45 +0,0 @@ - - - \ No newline at end of file diff --git a/data_model/clusters/EVSE-ClusterID.xml b/data_model/clusters/EVSE-ClusterID.xml deleted file mode 100644 index 6f84afeb8d04bc..00000000000000 --- a/data_model/clusters/EVSE-ClusterID.xml +++ /dev/null @@ -1,45 +0,0 @@ - - - \ No newline at end of file diff --git a/data_model/clusters/EVSE-Commands.xml b/data_model/clusters/EVSE-Commands.xml deleted file mode 100644 index 030565e20f8f96..00000000000000 --- a/data_model/clusters/EVSE-Commands.xml +++ /dev/null @@ -1,45 +0,0 @@ - - - \ No newline at end of file diff --git a/data_model/clusters/EVSE-DataTypes.xml b/data_model/clusters/EVSE-DataTypes.xml deleted file mode 100644 index 790d66143c7025..00000000000000 --- a/data_model/clusters/EVSE-DataTypes.xml +++ /dev/null @@ -1,45 +0,0 @@ - - - \ No newline at end of file diff --git a/data_model/clusters/EVSE-Definitions.xml b/data_model/clusters/EVSE-Definitions.xml deleted file mode 100644 index 7ff6135a3d2976..00000000000000 --- a/data_model/clusters/EVSE-Definitions.xml +++ /dev/null @@ -1,45 +0,0 @@ - - - \ No newline at end of file diff --git a/data_model/clusters/EVSE-Dependencies.xml b/data_model/clusters/EVSE-Dependencies.xml deleted file mode 100644 index a87cb67a4623ae..00000000000000 --- a/data_model/clusters/EVSE-Dependencies.xml +++ /dev/null @@ -1,45 +0,0 @@ - - - \ No newline at end of file diff --git a/data_model/clusters/EVSE-Events.xml b/data_model/clusters/EVSE-Events.xml deleted file mode 100644 index 51401775a6fe59..00000000000000 --- a/data_model/clusters/EVSE-Events.xml +++ /dev/null @@ -1,45 +0,0 @@ - - - \ No newline at end of file diff --git a/data_model/clusters/EVSE-Features.xml b/data_model/clusters/EVSE-Features.xml deleted file mode 100644 index a8b48a53b401e9..00000000000000 --- a/data_model/clusters/EVSE-Features.xml +++ /dev/null @@ -1,45 +0,0 @@ - - - \ No newline at end of file diff --git a/data_model/clusters/EVSE-RevisionHistory.xml b/data_model/clusters/EVSE-RevisionHistory.xml deleted file mode 100644 index 89ca30f749e5e1..00000000000000 --- a/data_model/clusters/EVSE-RevisionHistory.xml +++ /dev/null @@ -1,45 +0,0 @@ - - - \ No newline at end of file diff --git a/data_model/clusters/ElectricalEnergyMeasurement.xml b/data_model/clusters/ElectricalEnergyMeasurement.xml index c6bf8e73863c41..98020764397116 100644 --- a/data_model/clusters/ElectricalEnergyMeasurement.xml +++ b/data_model/clusters/ElectricalEnergyMeasurement.xml @@ -54,11 +54,16 @@ This notice and disclaimer must be included on all copies of this document. Connectivity Standards Alliance 508 Second Street, Suite 206 Davis, CA 95616, USA + +:xrefstyle: basic --> + + + @@ -74,7 +79,59 @@ Davis, CA 95616, USA - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/data_model/clusters/ElectricalPowerMeasurement.xml b/data_model/clusters/ElectricalPowerMeasurement.xml index aa5baeaf368cbb..c695e8db031790 100644 --- a/data_model/clusters/ElectricalPowerMeasurement.xml +++ b/data_model/clusters/ElectricalPowerMeasurement.xml @@ -54,11 +54,16 @@ This notice and disclaimer must be included on all copies of this document. Connectivity Standards Alliance 508 Second Street, Suite 206 Davis, CA 95616, USA + +:xrefstyle: basic --> + + + @@ -95,6 +100,68 @@ Davis, CA 95616, USA + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/data_model/clusters/EnergyCalendar.xml b/data_model/clusters/EnergyCalendar.xml index a21845d92c47c4..8d3f1b343bb4a7 100644 --- a/data_model/clusters/EnergyCalendar.xml +++ b/data_model/clusters/EnergyCalendar.xml @@ -54,6 +54,8 @@ This notice and disclaimer must be included on all copies of this document. Connectivity Standards Alliance 508 Second Street, Suite 206 Davis, CA 95616, USA + +:xrefstyle: short --> @@ -61,6 +63,9 @@ Davis, CA 95616, USA + + + diff --git a/data_model/clusters/EnergyEVSE.xml b/data_model/clusters/EnergyEVSE.xml index f59d41807d43e6..fa15692e78896d 100644 --- a/data_model/clusters/EnergyEVSE.xml +++ b/data_model/clusters/EnergyEVSE.xml @@ -54,12 +54,17 @@ This notice and disclaimer must be included on all copies of this document. Connectivity Standards Alliance 508 Second Street, Suite 206 Davis, CA 95616, USA + +:xrefstyle: basic --> + + + @@ -395,7 +400,6 @@ Davis, CA 95616, USA - @@ -405,11 +409,11 @@ Davis, CA 95616, USA - + - + @@ -425,7 +429,7 @@ Davis, CA 95616, USA - + @@ -439,11 +443,11 @@ Davis, CA 95616, USA - + - + @@ -454,13 +458,13 @@ Davis, CA 95616, USA - + - + diff --git a/data_model/clusters/EnergyPreference.xml b/data_model/clusters/EnergyPreference.xml index 7156be8eafe025..c3676520ed6d01 100644 --- a/data_model/clusters/EnergyPreference.xml +++ b/data_model/clusters/EnergyPreference.xml @@ -54,11 +54,16 @@ This notice and disclaimer must be included on all copies of this document. Connectivity Standards Alliance 508 Second Street, Suite 206 Davis, CA 95616, USA + +:xrefstyle: basic --> + + + diff --git a/data_model/clusters/EnergyPrice.xml b/data_model/clusters/EnergyPrice.xml index 23072a6a99ead5..1683fe1bbc13cf 100644 --- a/data_model/clusters/EnergyPrice.xml +++ b/data_model/clusters/EnergyPrice.xml @@ -54,6 +54,8 @@ This notice and disclaimer must be included on all copies of this document. Connectivity Standards Alliance 508 Second Street, Suite 206 Davis, CA 95616, USA + +:xrefstyle: short --> @@ -62,6 +64,9 @@ Davis, CA 95616, USA + + + @@ -173,7 +178,7 @@ Davis, CA 95616, USA - + @@ -188,7 +193,7 @@ Davis, CA 95616, USA - + diff --git a/data_model/clusters/FanControl.xml b/data_model/clusters/FanControl.xml index acf1d59e54d91e..756a7bd27466b3 100644 --- a/data_model/clusters/FanControl.xml +++ b/data_model/clusters/FanControl.xml @@ -54,6 +54,8 @@ This notice and disclaimer must be included on all copies of this document. Connectivity Standards Alliance 508 Second Street, Suite 206 Davis, CA 95616, USA + +:xrefstyle: short --> @@ -62,6 +64,9 @@ Davis, CA 95616, USA + + + @@ -277,7 +282,7 @@ Davis, CA 95616, USA - + diff --git a/data_model/clusters/FlowMeasurement.xml b/data_model/clusters/FlowMeasurement.xml index 66ad022c2c64ef..29f9d9d7ae58f9 100644 --- a/data_model/clusters/FlowMeasurement.xml +++ b/data_model/clusters/FlowMeasurement.xml @@ -54,6 +54,8 @@ This notice and disclaimer must be included on all copies of this document. Connectivity Standards Alliance 508 Second Street, Suite 206 Davis, CA 95616, USA + +:xrefstyle: basic --> @@ -61,6 +63,9 @@ Davis, CA 95616, USA + + + diff --git a/data_model/clusters/GeneralCommissioningCluster.xml b/data_model/clusters/GeneralCommissioningCluster.xml index a25cdfc6ac934e..635a6635990654 100644 --- a/data_model/clusters/GeneralCommissioningCluster.xml +++ b/data_model/clusters/GeneralCommissioningCluster.xml @@ -1,7 +1,5 @@ - + + + + @@ -86,21 +89,22 @@ Davis, CA 95616, USA - + - + + - + - + - + - + @@ -117,35 +121,35 @@ Davis, CA 95616, USA - + - + - + - + - + - + - + - + - + @@ -160,13 +164,15 @@ Davis, CA 95616, USA - + + - + + @@ -184,14 +190,14 @@ Davis, CA 95616, USA - + - + @@ -199,20 +205,19 @@ Davis, CA 95616, USA - - + - + @@ -220,7 +225,6 @@ Davis, CA 95616, USA - diff --git a/data_model/clusters/Groups.xml b/data_model/clusters/Groups.xml index 175c9caf26a435..72902e878cbe9f 100644 --- a/data_model/clusters/Groups.xml +++ b/data_model/clusters/Groups.xml @@ -54,6 +54,8 @@ This notice and disclaimer must be included on all copies of this document. Connectivity Standards Alliance 508 Second Street, Suite 206 Davis, CA 95616, USA + +:xrefstyle: basic --> @@ -62,6 +64,9 @@ Davis, CA 95616, USA + + + @@ -84,7 +89,7 @@ Davis, CA 95616, USA - + @@ -97,7 +102,6 @@ Davis, CA 95616, USA - @@ -108,7 +112,7 @@ Davis, CA 95616, USA - + @@ -117,7 +121,6 @@ Davis, CA 95616, USA - @@ -132,7 +135,7 @@ Davis, CA 95616, USA - + @@ -143,7 +146,6 @@ Davis, CA 95616, USA - @@ -156,7 +158,7 @@ Davis, CA 95616, USA - + @@ -165,7 +167,6 @@ Davis, CA 95616, USA - @@ -176,11 +177,11 @@ Davis, CA 95616, USA - + - + diff --git a/data_model/clusters/ICDManagement.xml b/data_model/clusters/ICDManagement.xml index 3cc6c9bfab4416..2a770a4f97f2b4 100644 --- a/data_model/clusters/ICDManagement.xml +++ b/data_model/clusters/ICDManagement.xml @@ -54,21 +54,41 @@ This notice and disclaimer must be included on all copies of this document. Connectivity Standards Alliance 508 Second Street, Suite 206 Davis, CA 95616, USA + +// Update Name --> - + + + + + - + + + + + + + + + + + + + + + @@ -133,9 +153,28 @@ Davis, CA 95616, USA + + + + + + + + + + + + + + + + + + + - + @@ -156,7 +195,6 @@ Davis, CA 95616, USA - @@ -164,7 +202,7 @@ Davis, CA 95616, USA - + @@ -177,7 +215,7 @@ Davis, CA 95616, USA - + @@ -190,7 +228,6 @@ Davis, CA 95616, USA - diff --git a/data_model/clusters/Identify.xml b/data_model/clusters/Identify.xml index 379e684e51297d..1cdc33aa0df727 100644 --- a/data_model/clusters/Identify.xml +++ b/data_model/clusters/Identify.xml @@ -54,6 +54,8 @@ This notice and disclaimer must be included on all copies of this document. Connectivity Standards Alliance 508 Second Street, Suite 206 Davis, CA 95616, USA + +:xrefstyle: basic --> @@ -62,6 +64,9 @@ Davis, CA 95616, USA + + + @@ -127,14 +132,14 @@ Davis, CA 95616, USA - + - + diff --git a/data_model/clusters/IlluminanceMeasurement.xml b/data_model/clusters/IlluminanceMeasurement.xml index c9be9fa6879293..c39daa0e6bdc4d 100644 --- a/data_model/clusters/IlluminanceMeasurement.xml +++ b/data_model/clusters/IlluminanceMeasurement.xml @@ -54,6 +54,8 @@ This notice and disclaimer must be included on all copies of this document. Connectivity Standards Alliance 508 Second Street, Suite 206 Davis, CA 95616, USA + +:xrefstyle: basic --> @@ -61,6 +63,9 @@ Davis, CA 95616, USA + + + diff --git a/data_model/clusters/KeypadInput.xml b/data_model/clusters/KeypadInput.xml index f0459e6b1bff1a..4cfb509b06d0be 100644 --- a/data_model/clusters/KeypadInput.xml +++ b/data_model/clusters/KeypadInput.xml @@ -54,11 +54,16 @@ This notice and disclaimer must be included on all copies of this document. Connectivity Standards Alliance 508 Second Street, Suite 206 Davis, CA 95616, USA + +:xrefstyle: basic --> + + + @@ -345,7 +350,7 @@ Davis, CA 95616, USA - + @@ -353,7 +358,6 @@ Davis, CA 95616, USA - diff --git a/data_model/clusters/Label-Cluster-FixedLabel.xml b/data_model/clusters/Label-Cluster-FixedLabelCluster.xml similarity index 96% rename from data_model/clusters/Label-Cluster-FixedLabel.xml rename to data_model/clusters/Label-Cluster-FixedLabelCluster.xml index 558664a5d69f72..e73bfc274a9da4 100644 --- a/data_model/clusters/Label-Cluster-FixedLabel.xml +++ b/data_model/clusters/Label-Cluster-FixedLabelCluster.xml @@ -54,11 +54,16 @@ This notice and disclaimer must be included on all copies of this document. Connectivity Standards Alliance 508 Second Street, Suite 206 Davis, CA 95616, USA + +:xrefstyle: basic --> + + + diff --git a/data_model/clusters/Label-Cluster-Label.xml b/data_model/clusters/Label-Cluster-LabelCluster.xml similarity index 96% rename from data_model/clusters/Label-Cluster-Label.xml rename to data_model/clusters/Label-Cluster-LabelCluster.xml index ee64da775b05cd..f107a0a7b3f12b 100644 --- a/data_model/clusters/Label-Cluster-Label.xml +++ b/data_model/clusters/Label-Cluster-LabelCluster.xml @@ -54,11 +54,16 @@ This notice and disclaimer must be included on all copies of this document. Connectivity Standards Alliance 508 Second Street, Suite 206 Davis, CA 95616, USA + +:xrefstyle: basic --> + + + diff --git a/data_model/clusters/Label-Cluster-UserLabel.xml b/data_model/clusters/Label-Cluster-UserLabelCluster.xml similarity index 96% rename from data_model/clusters/Label-Cluster-UserLabel.xml rename to data_model/clusters/Label-Cluster-UserLabelCluster.xml index bca4b1453f22de..f7e809ab785c00 100644 --- a/data_model/clusters/Label-Cluster-UserLabel.xml +++ b/data_model/clusters/Label-Cluster-UserLabelCluster.xml @@ -54,11 +54,16 @@ This notice and disclaimer must be included on all copies of this document. Connectivity Standards Alliance 508 Second Street, Suite 206 Davis, CA 95616, USA + +:xrefstyle: basic --> + + + diff --git a/data_model/clusters/LaundryDryerControls.xml b/data_model/clusters/LaundryDryerControls.xml index 461f08666093b8..a3f7b911fc9e9c 100644 --- a/data_model/clusters/LaundryDryerControls.xml +++ b/data_model/clusters/LaundryDryerControls.xml @@ -59,6 +59,9 @@ Davis, CA 95616, USA + + + diff --git a/data_model/clusters/LaundryWasherControls.xml b/data_model/clusters/LaundryWasherControls.xml index 5a9d108ccc1b01..16879842721473 100644 --- a/data_model/clusters/LaundryWasherControls.xml +++ b/data_model/clusters/LaundryWasherControls.xml @@ -59,6 +59,9 @@ Davis, CA 95616, USA + + + diff --git a/data_model/clusters/LevelControl.xml b/data_model/clusters/LevelControl.xml index 8a348a2dc05cbd..6b2b3cace52ec3 100644 --- a/data_model/clusters/LevelControl.xml +++ b/data_model/clusters/LevelControl.xml @@ -54,6 +54,8 @@ This notice and disclaimer must be included on all copies of this document. Connectivity Standards Alliance 508 Second Street, Suite 206 Davis, CA 95616, USA + +:xrefstyle: basic --> @@ -65,6 +67,7 @@ Davis, CA 95616, USA + @@ -210,7 +213,7 @@ Davis, CA 95616, USA - + @@ -230,7 +233,7 @@ Davis, CA 95616, USA - + @@ -250,7 +253,7 @@ Davis, CA 95616, USA - + @@ -273,7 +276,7 @@ Davis, CA 95616, USA - + @@ -285,23 +288,23 @@ Davis, CA 95616, USA - + - + - + - + - + diff --git a/data_model/clusters/LocalizationConfiguration.xml b/data_model/clusters/LocalizationConfiguration.xml index b264698b6d5393..f3c2d5b2d7662b 100644 --- a/data_model/clusters/LocalizationConfiguration.xml +++ b/data_model/clusters/LocalizationConfiguration.xml @@ -59,18 +59,25 @@ Davis, CA 95616, USA + + + - + - + - + + + + + \ No newline at end of file diff --git a/data_model/clusters/LocalizationTimeFormat.xml b/data_model/clusters/LocalizationTimeFormat.xml index 204f145f9c8b07..fb8ceea3ee17a8 100644 --- a/data_model/clusters/LocalizationTimeFormat.xml +++ b/data_model/clusters/LocalizationTimeFormat.xml @@ -59,6 +59,9 @@ Davis, CA 95616, USA + + + @@ -132,7 +135,8 @@ Davis, CA 95616, USA - + + diff --git a/data_model/clusters/LocalizationUnit.xml b/data_model/clusters/LocalizationUnit.xml index 24c54638b4ffd7..be7ea6a0aa2d78 100644 --- a/data_model/clusters/LocalizationUnit.xml +++ b/data_model/clusters/LocalizationUnit.xml @@ -59,6 +59,9 @@ Davis, CA 95616, USA + + + diff --git a/data_model/clusters/LowPower.xml b/data_model/clusters/LowPower.xml index f8ee432eef58a7..4c228d3154dfa1 100644 --- a/data_model/clusters/LowPower.xml +++ b/data_model/clusters/LowPower.xml @@ -54,14 +54,19 @@ This notice and disclaimer must be included on all copies of this document. Connectivity Standards Alliance 508 Second Street, Suite 206 Davis, CA 95616, USA + +:xrefstyle: basic --> + + + - + diff --git a/data_model/clusters/MediaInput.xml b/data_model/clusters/MediaInput.xml index 9ca0f351d1f59f..b7d9d2ef017035 100644 --- a/data_model/clusters/MediaInput.xml +++ b/data_model/clusters/MediaInput.xml @@ -54,11 +54,16 @@ This notice and disclaimer must be included on all copies of this document. Connectivity Standards Alliance 508 Second Street, Suite 206 Davis, CA 95616, USA + +:xrefstyle: basic --> + + + @@ -132,22 +137,22 @@ Davis, CA 95616, USA - + - + - + - + diff --git a/data_model/clusters/MediaPlayback.xml b/data_model/clusters/MediaPlayback.xml index f2cdf5c4a7c851..0a457a446208dd 100644 --- a/data_model/clusters/MediaPlayback.xml +++ b/data_model/clusters/MediaPlayback.xml @@ -54,11 +54,17 @@ This notice and disclaimer must be included on all copies of this document. Connectivity Standards Alliance 508 Second Street, Suite 206 Davis, CA 95616, USA + +:xrefstyle: basic --> - + + + + + @@ -67,8 +73,73 @@ Davis, CA 95616, USA + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -118,6 +189,30 @@ Davis, CA 95616, USA + + + + + + + + + + + + + + + + + + + + + + + + @@ -172,52 +267,96 @@ Davis, CA 95616, USA + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + - + - + - + + + + + + - + + + + + + - + - + @@ -225,7 +364,6 @@ Davis, CA 95616, USA - @@ -235,7 +373,7 @@ Davis, CA 95616, USA - + @@ -244,5 +382,92 @@ Davis, CA 95616, USA + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/data_model/clusters/Messages.xml b/data_model/clusters/Messages.xml index 9dd223d9a63f46..cea28ac15f54c9 100644 --- a/data_model/clusters/Messages.xml +++ b/data_model/clusters/Messages.xml @@ -55,6 +55,8 @@ Connectivity Standards Alliance + 508 Second Street, Suite 206 + Davis, CA 95616, USA +:xrefstyle: short + Copyright (C) Connectivity Standards Alliance (2021). All rights reserved. This information within this document is the property of the Connectivity Standards Alliance and its use and disclosure are restricted. @@ -91,6 +93,8 @@ are made. Connectivity Standards Alliance 508 Second Street, Suite 206 Davis, CA 95616, USA + +:xrefstyle: basic --> @@ -98,6 +102,9 @@ Davis, CA 95616, USA + + + @@ -245,7 +252,7 @@ Davis, CA 95616, USA - + @@ -275,7 +282,7 @@ Davis, CA 95616, USA - + diff --git a/data_model/clusters/MicrowaveOvenControl.xml b/data_model/clusters/MicrowaveOvenControl.xml index c95d713714854f..d7c6f72f740d3d 100644 --- a/data_model/clusters/MicrowaveOvenControl.xml +++ b/data_model/clusters/MicrowaveOvenControl.xml @@ -54,11 +54,16 @@ This notice and disclaimer must be included on all copies of this document. Connectivity Standards Alliance 508 Second Street, Suite 206 Davis, CA 95616, USA + +:xrefstyle: basic --> + + + @@ -114,7 +119,7 @@ Davis, CA 95616, USA - + @@ -139,7 +144,7 @@ Davis, CA 95616, USA - + @@ -166,7 +171,7 @@ Davis, CA 95616, USA - + diff --git a/data_model/clusters/ModeBase.xml b/data_model/clusters/ModeBase.xml index 5774a7fec0c5a5..2a11f85d343b39 100644 --- a/data_model/clusters/ModeBase.xml +++ b/data_model/clusters/ModeBase.xml @@ -61,6 +61,9 @@ Davis, CA 95616, USA + + + @@ -122,7 +125,7 @@ Require at least one standard mode tag. Define reserved ranges for base/derived - + diff --git a/data_model/clusters/ModeSelect.xml b/data_model/clusters/ModeSelect.xml index 19fe502c1fcfe2..a30a5b9bf8eca5 100644 --- a/data_model/clusters/ModeSelect.xml +++ b/data_model/clusters/ModeSelect.xml @@ -60,6 +60,9 @@ Davis, CA 95616, USA + + + @@ -133,7 +136,7 @@ Davis, CA 95616, USA - + diff --git a/data_model/clusters/Mode_DeviceEnergyManagement.xml b/data_model/clusters/Mode_DeviceEnergyManagement.xml index 4181b9b60ead42..592c7d4290a342 100644 --- a/data_model/clusters/Mode_DeviceEnergyManagement.xml +++ b/data_model/clusters/Mode_DeviceEnergyManagement.xml @@ -54,11 +54,16 @@ This notice and disclaimer must be included on all copies of this document. Connectivity Standards Alliance 508 Second Street, Suite 206 Davis, CA 95616, USA + +:xrefstyle: basic --> + + + diff --git a/data_model/clusters/Mode_Dishwasher.xml b/data_model/clusters/Mode_Dishwasher.xml index 22d0fab7897696..4ff6e78714f648 100644 --- a/data_model/clusters/Mode_Dishwasher.xml +++ b/data_model/clusters/Mode_Dishwasher.xml @@ -54,12 +54,17 @@ This notice and disclaimer must be included on all copies of this document. Connectivity Standards Alliance 508 Second Street, Suite 206 Davis, CA 95616, USA + +:xrefstyle: basic --> + + + diff --git a/data_model/clusters/Mode_EVSE.xml b/data_model/clusters/Mode_EVSE.xml index 2a600e3e381325..de88cb3717c8bf 100644 --- a/data_model/clusters/Mode_EVSE.xml +++ b/data_model/clusters/Mode_EVSE.xml @@ -54,10 +54,15 @@ This notice and disclaimer must be included on all copies of this document. Connectivity Standards Alliance 508 Second Street, Suite 206 Davis, CA 95616, USA + +:xrefstyle: basic --> + + + \ No newline at end of file diff --git a/data_model/clusters/Mode_LaundryWasher.xml b/data_model/clusters/Mode_LaundryWasher.xml index e89778fa9ea579..c59b2c3fef9051 100644 --- a/data_model/clusters/Mode_LaundryWasher.xml +++ b/data_model/clusters/Mode_LaundryWasher.xml @@ -54,12 +54,17 @@ This notice and disclaimer must be included on all copies of this document. Connectivity Standards Alliance 508 Second Street, Suite 206 Davis, CA 95616, USA + +:xrefstyle: basic --> + + + diff --git a/data_model/clusters/Mode_MicrowaveOven.xml b/data_model/clusters/Mode_MicrowaveOven.xml index cd98c189c12844..6e8a129444b9fd 100644 --- a/data_model/clusters/Mode_MicrowaveOven.xml +++ b/data_model/clusters/Mode_MicrowaveOven.xml @@ -54,11 +54,16 @@ This notice and disclaimer must be included on all copies of this document. Connectivity Standards Alliance 508 Second Street, Suite 206 Davis, CA 95616, USA + +:xrefstyle: basic --> + + + @@ -75,12 +80,10 @@ Davis, CA 95616, USA - - + - - + diff --git a/data_model/clusters/Mode_Oven.xml b/data_model/clusters/Mode_Oven.xml index 56a369dd425572..f6c7111bb844cd 100644 --- a/data_model/clusters/Mode_Oven.xml +++ b/data_model/clusters/Mode_Oven.xml @@ -54,10 +54,15 @@ This notice and disclaimer must be included on all copies of this document. Connectivity Standards Alliance 508 Second Street, Suite 206 Davis, CA 95616, USA + +:xrefstyle: basic --> + + + \ No newline at end of file diff --git a/data_model/clusters/Mode_RVCClean.xml b/data_model/clusters/Mode_RVCClean.xml index 64118517a03c1b..d1b2272fc7e756 100644 --- a/data_model/clusters/Mode_RVCClean.xml +++ b/data_model/clusters/Mode_RVCClean.xml @@ -54,12 +54,17 @@ This notice and disclaimer must be included on all copies of this document. Connectivity Standards Alliance 508 Second Street, Suite 206 Davis, CA 95616, USA + +:xrefstyle: basic --> + + + diff --git a/data_model/clusters/Mode_RVCRun.xml b/data_model/clusters/Mode_RVCRun.xml index 8f49741f7cfeb8..8e19b45a8385fc 100644 --- a/data_model/clusters/Mode_RVCRun.xml +++ b/data_model/clusters/Mode_RVCRun.xml @@ -54,12 +54,17 @@ This notice and disclaimer must be included on all copies of this document. Connectivity Standards Alliance 508 Second Street, Suite 206 Davis, CA 95616, USA + +:xrefstyle: basic --> + + + diff --git a/data_model/clusters/Mode_Refrigerator.xml b/data_model/clusters/Mode_Refrigerator.xml index cf6a65721e0efd..d51e30b68d1320 100644 --- a/data_model/clusters/Mode_Refrigerator.xml +++ b/data_model/clusters/Mode_Refrigerator.xml @@ -54,12 +54,17 @@ This notice and disclaimer must be included on all copies of this document. Connectivity Standards Alliance 508 Second Street, Suite 206 Davis, CA 95616, USA + +:xrefstyle: basic --> + + + diff --git a/data_model/clusters/Mode_WaterHeater.xml b/data_model/clusters/Mode_WaterHeater.xml index 69fba08b940293..56f1a1e9a66951 100644 --- a/data_model/clusters/Mode_WaterHeater.xml +++ b/data_model/clusters/Mode_WaterHeater.xml @@ -54,10 +54,15 @@ This notice and disclaimer must be included on all copies of this document. Connectivity Standards Alliance 508 Second Street, Suite 206 Davis, CA 95616, USA + +:xrefstyle: basic --> + + + \ No newline at end of file diff --git a/data_model/clusters/NetworkCommissioningCluster.xml b/data_model/clusters/NetworkCommissioningCluster.xml index 0153146c149d26..86c7a01ce9f951 100644 --- a/data_model/clusters/NetworkCommissioningCluster.xml +++ b/data_model/clusters/NetworkCommissioningCluster.xml @@ -1,7 +1,5 @@ - + + + + @@ -73,6 +76,11 @@ Davis, CA 95616, USA + + + + + @@ -169,15 +177,34 @@ Davis, CA 95616, USA + + + - + - + + + + + + + + + + + + + + + + + @@ -191,11 +218,11 @@ Davis, CA 95616, USA - + - + @@ -229,17 +256,17 @@ Davis, CA 95616, USA - + - + - + - + @@ -265,10 +292,11 @@ Davis, CA 95616, USA - + + - + @@ -302,24 +330,25 @@ Davis, CA 95616, USA - + - + - + + - + @@ -337,7 +366,7 @@ Davis, CA 95616, USA - + @@ -345,19 +374,18 @@ Davis, CA 95616, USA - + - + - @@ -368,54 +396,68 @@ Davis, CA 95616, USA - + - + - + + - + + - + - + - + - + - + + + + + + + + + + + + + - + - + - + - + @@ -423,16 +465,15 @@ Davis, CA 95616, USA - + - + - @@ -443,16 +484,28 @@ Davis, CA 95616, USA - + - + - + + + + + + + + + + + + + - + @@ -460,16 +513,15 @@ Davis, CA 95616, USA - + - + - @@ -479,7 +531,7 @@ Davis, CA 95616, USA - + @@ -487,7 +539,7 @@ Davis, CA 95616, USA - + @@ -495,9 +547,9 @@ Davis, CA 95616, USA - + - + @@ -507,5 +559,32 @@ Davis, CA 95616, USA + + + + + + + + + + + + + + + + + + + + + + + + + + + - \ No newline at end of file + diff --git a/data_model/clusters/NetworkIdentityManagement.xml b/data_model/clusters/NetworkIdentityManagement.xml index 08bee6af5871ff..8769b68583e4b9 100644 --- a/data_model/clusters/NetworkIdentityManagement.xml +++ b/data_model/clusters/NetworkIdentityManagement.xml @@ -54,11 +54,16 @@ This notice and disclaimer must be included on all copies of this document. Connectivity Standards Alliance 508 Second Street, Suite 206 Davis, CA 95616, USA + +:xrefstyle: basic --> + + + @@ -119,7 +124,7 @@ Davis, CA 95616, USA - + @@ -130,7 +135,7 @@ Davis, CA 95616, USA - + @@ -141,7 +146,7 @@ Davis, CA 95616, USA - + diff --git a/data_model/clusters/OTAProvider.xml b/data_model/clusters/OTAProvider.xml index 73157662cd6f6e..baf3996d3b911f 100644 --- a/data_model/clusters/OTAProvider.xml +++ b/data_model/clusters/OTAProvider.xml @@ -1,7 +1,5 @@ @@ -62,6 +64,9 @@ Davis, CA 95616, USA + + + diff --git a/data_model/clusters/OnOff.xml b/data_model/clusters/OnOff.xml index 0d64837ea57fbb..0b1e32af50cddb 100644 --- a/data_model/clusters/OnOff.xml +++ b/data_model/clusters/OnOff.xml @@ -54,6 +54,8 @@ This notice and disclaimer must be included on all copies of this document. Connectivity Standards Alliance 508 Second Street, Suite 206 Davis, CA 95616, USA + +:xrefstyle: basic --> @@ -64,6 +66,9 @@ Davis, CA 95616, USA + + + @@ -171,11 +176,11 @@ Davis, CA 95616, USA - + - + @@ -183,7 +188,7 @@ Davis, CA 95616, USA - + @@ -191,7 +196,7 @@ Davis, CA 95616, USA - + @@ -205,13 +210,13 @@ Davis, CA 95616, USA - + - + diff --git a/data_model/clusters/OperationalCredentialCluster.xml b/data_model/clusters/OperationalCredentialCluster.xml index ec523ba33671d1..1a2becd5c478a2 100644 --- a/data_model/clusters/OperationalCredentialCluster.xml +++ b/data_model/clusters/OperationalCredentialCluster.xml @@ -1,7 +1,5 @@ - + + + + @@ -98,10 +99,10 @@ Davis, CA 95616, USA - + - + @@ -115,11 +116,11 @@ Davis, CA 95616, USA - + - + - + @@ -136,32 +137,34 @@ Davis, CA 95616, USA - + - + - + - + - + + - + - + + - + @@ -175,10 +178,14 @@ Davis, CA 95616, USA - + + + + + @@ -186,7 +193,7 @@ Davis, CA 95616, USA - + @@ -195,7 +202,6 @@ Davis, CA 95616, USA - @@ -206,7 +212,7 @@ Davis, CA 95616, USA - + @@ -215,14 +221,13 @@ Davis, CA 95616, USA - - + @@ -234,7 +239,6 @@ Davis, CA 95616, USA - @@ -245,29 +249,29 @@ Davis, CA 95616, USA - + - + - + - + - + - + - + - + - + @@ -280,7 +284,6 @@ Davis, CA 95616, USA - @@ -294,7 +297,7 @@ Davis, CA 95616, USA - + @@ -302,7 +305,7 @@ Davis, CA 95616, USA - + @@ -310,12 +313,12 @@ Davis, CA 95616, USA - + - + - + diff --git a/data_model/clusters/OperationalState.xml b/data_model/clusters/OperationalState.xml index dcb5753b2c1998..0062b38b4b3981 100644 --- a/data_model/clusters/OperationalState.xml +++ b/data_model/clusters/OperationalState.xml @@ -60,6 +60,9 @@ Davis, CA 95616, USA + + + @@ -143,6 +146,53 @@ Davis, CA 95616, USA + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/data_model/clusters/OperationalState_Oven.xml b/data_model/clusters/OperationalState_Oven.xml index 947e93f8ec2348..c44ac37b7ccac9 100644 --- a/data_model/clusters/OperationalState_Oven.xml +++ b/data_model/clusters/OperationalState_Oven.xml @@ -54,10 +54,15 @@ This notice and disclaimer must be included on all copies of this document. Connectivity Standards Alliance + 508 Second Street, Suite 206 + Davis, CA 95616, USA + +:xrefstyle: basic --> + + + \ No newline at end of file diff --git a/data_model/clusters/OperationalState_RVC.xml b/data_model/clusters/OperationalState_RVC.xml index bc4e5505e45d6d..6426e2639a7b83 100644 --- a/data_model/clusters/OperationalState_RVC.xml +++ b/data_model/clusters/OperationalState_RVC.xml @@ -54,32 +54,29 @@ This notice and disclaimer must be included on all copies of this document. Connectivity Standards Alliance + 508 Second Street, Suite 206 + Davis, CA 95616, USA + +:xrefstyle: basic --> + + + - - - - - + + - - + - - - - - - - + + + diff --git a/data_model/clusters/PowerSourceCluster.xml b/data_model/clusters/PowerSourceCluster.xml index 16d6f0ac98cad5..ffd628de6686b8 100644 --- a/data_model/clusters/PowerSourceCluster.xml +++ b/data_model/clusters/PowerSourceCluster.xml @@ -61,6 +61,9 @@ Davis, CA 95616, USA + + + @@ -911,13 +914,13 @@ Davis, CA 95616, USA - + - + @@ -928,12 +931,14 @@ Davis, CA 95616, USA + + - + @@ -944,9 +949,10 @@ Davis, CA 95616, USA + - + @@ -957,13 +963,15 @@ Davis, CA 95616, USA - + + - + - + + - + @@ -971,13 +979,15 @@ Davis, CA 95616, USA - + + - + - + + - + @@ -985,13 +995,15 @@ Davis, CA 95616, USA - + + - + - + + - + diff --git a/data_model/clusters/PowerSourceConfigurationCluster.xml b/data_model/clusters/PowerSourceConfigurationCluster.xml index 5548bf6ad8e6b5..11e3bd47dd9186 100644 --- a/data_model/clusters/PowerSourceConfigurationCluster.xml +++ b/data_model/clusters/PowerSourceConfigurationCluster.xml @@ -59,10 +59,13 @@ Davis, CA 95616, USA + + + - + diff --git a/data_model/clusters/PowerTopology.xml b/data_model/clusters/PowerTopology.xml index c8d90baeeded19..d8c8a50d22a3a6 100644 --- a/data_model/clusters/PowerTopology.xml +++ b/data_model/clusters/PowerTopology.xml @@ -54,11 +54,16 @@ This notice and disclaimer must be included on all copies of this document. Connectivity Standards Alliance 508 Second Street, Suite 206 Davis, CA 95616, USA + +:xrefstyle: short --> + + + diff --git a/data_model/clusters/PressureMeasurement.xml b/data_model/clusters/PressureMeasurement.xml index 70093485639090..d9c4a4584404fe 100644 --- a/data_model/clusters/PressureMeasurement.xml +++ b/data_model/clusters/PressureMeasurement.xml @@ -54,6 +54,8 @@ This notice and disclaimer must be included on all copies of this document. Connectivity Standards Alliance 508 Second Street, Suite 206 Davis, CA 95616, USA + +:xrefstyle: basic --> @@ -61,6 +63,9 @@ Davis, CA 95616, USA + + + diff --git a/data_model/clusters/PumpConfigurationControl.xml b/data_model/clusters/PumpConfigurationControl.xml index f3fc98a52cee9e..cfd2971a395ecb 100644 --- a/data_model/clusters/PumpConfigurationControl.xml +++ b/data_model/clusters/PumpConfigurationControl.xml @@ -62,6 +62,9 @@ Davis, CA 95616, USA + + + @@ -169,7 +172,206 @@ Davis, CA 95616, USA - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/data_model/clusters/RefrigeratorAlarm.xml b/data_model/clusters/RefrigeratorAlarm.xml index c987c3860a4f52..caad94da1f6fad 100644 --- a/data_model/clusters/RefrigeratorAlarm.xml +++ b/data_model/clusters/RefrigeratorAlarm.xml @@ -54,11 +54,16 @@ This notice and disclaimer must be included on all copies of this document. Connectivity Standards Alliance 508 Second Street, Suite 206 Davis, CA 95616, USA + +:xrefstyle: short --> + + + @@ -73,8 +78,7 @@ Davis, CA 95616, USA - - + diff --git a/data_model/clusters/ResourceMonitoring.xml b/data_model/clusters/ResourceMonitoring.xml index 17fc7554ac41f0..6b0e8f3a203ded 100644 --- a/data_model/clusters/ResourceMonitoring.xml +++ b/data_model/clusters/ResourceMonitoring.xml @@ -54,6 +54,8 @@ This notice and disclaimer must be included on all copies of this document. Connectivity Standards Alliance 508 Second Street, Suite 206 Davis, CA 95616, USA + +:xrefstyle: basic --> @@ -164,7 +166,7 @@ Davis, CA 95616, USA - + diff --git a/data_model/clusters/Scenes.xml b/data_model/clusters/Scenes.xml index 0c4347c4e8be8a..5d9be300d1abbc 100644 --- a/data_model/clusters/Scenes.xml +++ b/data_model/clusters/Scenes.xml @@ -54,11 +54,16 @@ This notice and disclaimer must be included on all copies of this document. Connectivity Standards Alliance 508 Second Street, Suite 206 Davis, CA 95616, USA + +:xrefstyle: basic --> + + + @@ -116,17 +121,14 @@ Davis, CA 95616, USA - - - @@ -177,7 +179,7 @@ Davis, CA 95616, USA - + @@ -189,7 +191,7 @@ Davis, CA 95616, USA - + @@ -202,7 +204,6 @@ Davis, CA 95616, USA - @@ -216,7 +217,7 @@ Davis, CA 95616, USA - + @@ -228,7 +229,6 @@ Davis, CA 95616, USA - @@ -242,7 +242,7 @@ Davis, CA 95616, USA - + @@ -251,7 +251,7 @@ Davis, CA 95616, USA - + @@ -263,7 +263,6 @@ Davis, CA 95616, USA - @@ -277,7 +276,7 @@ Davis, CA 95616, USA - + @@ -285,7 +284,6 @@ Davis, CA 95616, USA - @@ -295,7 +293,7 @@ Davis, CA 95616, USA - + @@ -307,7 +305,6 @@ Davis, CA 95616, USA - @@ -321,7 +318,7 @@ Davis, CA 95616, USA - + @@ -337,7 +334,7 @@ Davis, CA 95616, USA - + @@ -345,7 +342,6 @@ Davis, CA 95616, USA - @@ -362,7 +358,7 @@ Davis, CA 95616, USA - + @@ -383,9 +379,8 @@ Davis, CA 95616, USA - - + diff --git a/data_model/clusters/SmokeCOAlarm.xml b/data_model/clusters/SmokeCOAlarm.xml index 0db5c78f4e947f..d3d35f13f15f25 100644 --- a/data_model/clusters/SmokeCOAlarm.xml +++ b/data_model/clusters/SmokeCOAlarm.xml @@ -54,11 +54,16 @@ This notice and disclaimer must be included on all copies of this document. Connectivity Standards Alliance 508 Second Street, Suite 206 Davis, CA 95616, USA + +:xrefstyle: basic --> + + + @@ -226,7 +231,7 @@ Davis, CA 95616, USA - + diff --git a/data_model/clusters/Switch.xml b/data_model/clusters/Switch.xml index 30602c35bf794f..e7170049ac051f 100644 --- a/data_model/clusters/Switch.xml +++ b/data_model/clusters/Switch.xml @@ -59,6 +59,9 @@ Davis, CA 95616, USA + + + diff --git a/data_model/clusters/TargetNavigator.xml b/data_model/clusters/TargetNavigator.xml index 343f1427176e41..cfb3a0c17a6f99 100644 --- a/data_model/clusters/TargetNavigator.xml +++ b/data_model/clusters/TargetNavigator.xml @@ -54,11 +54,17 @@ This notice and disclaimer must be included on all copies of this document. Connectivity Standards Alliance 508 Second Street, Suite 206 Davis, CA 95616, USA + +:xrefstyle: basic --> - + + + + + @@ -95,7 +101,7 @@ Davis, CA 95616, USA - + @@ -106,7 +112,6 @@ Davis, CA 95616, USA - @@ -116,4 +121,22 @@ Davis, CA 95616, USA + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/data_model/clusters/TemperatureControl.xml b/data_model/clusters/TemperatureControl.xml index f457238bab1d8a..70fc100d83bbab 100644 --- a/data_model/clusters/TemperatureControl.xml +++ b/data_model/clusters/TemperatureControl.xml @@ -59,6 +59,9 @@ Davis, CA 95616, USA + + + @@ -73,9 +76,58 @@ Davis, CA 95616, USA - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + diff --git a/data_model/clusters/TemperatureMeasurement.xml b/data_model/clusters/TemperatureMeasurement.xml index e1603fd3358bc3..540af82bcedd18 100644 --- a/data_model/clusters/TemperatureMeasurement.xml +++ b/data_model/clusters/TemperatureMeasurement.xml @@ -54,6 +54,8 @@ This notice and disclaimer must be included on all copies of this document. Connectivity Standards Alliance 508 Second Street, Suite 206 Davis, CA 95616, USA + +:xrefstyle: basic --> @@ -62,6 +64,9 @@ Davis, CA 95616, USA + + + diff --git a/data_model/clusters/Thermostat.xml b/data_model/clusters/Thermostat.xml index 400d55a048a116..756e27940c2cba 100644 --- a/data_model/clusters/Thermostat.xml +++ b/data_model/clusters/Thermostat.xml @@ -55,7 +55,7 @@ Connectivity Standards Alliance 508 Second Street, Suite 206 Davis, CA 95616, USA --> - + @@ -63,7 +63,11 @@ Davis, CA 95616, USA + + + + @@ -102,6 +106,17 @@ Davis, CA 95616, USA + + + + + + + + + + + @@ -212,13 +227,36 @@ Davis, CA 95616, USA + + + + + + + + + + + + + + + + + + + + - + + + + @@ -297,7 +335,7 @@ Davis, CA 95616, USA - + @@ -372,6 +410,14 @@ Davis, CA 95616, USA + + + + + + + + @@ -451,6 +497,149 @@ Davis, CA 95616, USA + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -823,9 +1012,110 @@ Davis, CA 95616, USA + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + @@ -837,7 +1127,6 @@ Davis, CA 95616, USA - @@ -858,7 +1147,7 @@ Davis, CA 95616, USA - + @@ -881,9 +1170,8 @@ Davis, CA 95616, USA - - + @@ -909,7 +1197,7 @@ Davis, CA 95616, USA - + @@ -923,17 +1211,79 @@ Davis, CA 95616, USA - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/data_model/clusters/ThermostatUserInterfaceConfiguration.xml b/data_model/clusters/ThermostatUserInterfaceConfiguration.xml index 6c8d1d920e6ef7..63fdba001c67a9 100644 --- a/data_model/clusters/ThermostatUserInterfaceConfiguration.xml +++ b/data_model/clusters/ThermostatUserInterfaceConfiguration.xml @@ -60,6 +60,9 @@ Davis, CA 95616, USA + + + diff --git a/data_model/clusters/ThreadBorderRouterDiagnostics.xml b/data_model/clusters/ThreadBorderRouterDiagnostics.xml index 29b5da9b8511f0..5527c486a0cc51 100644 --- a/data_model/clusters/ThreadBorderRouterDiagnostics.xml +++ b/data_model/clusters/ThreadBorderRouterDiagnostics.xml @@ -54,19 +54,23 @@ This notice and disclaimer must be included on all copies of this document. Connectivity Standards Alliance 508 Second Street, Suite 206 Davis, CA 95616, USA + +:xrefstyle: basic --> + + + - + - @@ -75,12 +79,11 @@ Davis, CA 95616, USA - + - diff --git a/data_model/clusters/TimeSync.xml b/data_model/clusters/TimeSync.xml index 096e0ff2798261..99ec173bc7e6e1 100644 --- a/data_model/clusters/TimeSync.xml +++ b/data_model/clusters/TimeSync.xml @@ -1,7 +1,5 @@ + + + @@ -112,19 +116,19 @@ Davis, CA 95616, USA - + - + - + - + @@ -133,22 +137,22 @@ Davis, CA 95616, USA - + - + - + - + - + - + @@ -178,9 +182,9 @@ Davis, CA 95616, USA - + - + @@ -192,10 +196,6 @@ Davis, CA 95616, USA - - - - \ No newline at end of file diff --git a/data_model/clusters/ValveConfigurationControl.xml b/data_model/clusters/ValveConfigurationControl.xml index 32620ad9cce97d..548fed7d7357c2 100644 --- a/data_model/clusters/ValveConfigurationControl.xml +++ b/data_model/clusters/ValveConfigurationControl.xml @@ -54,11 +54,16 @@ This notice and disclaimer must be included on all copies of this document. Connectivity Standards Alliance 508 Second Street, Suite 206 Davis, CA 95616, USA + +:xrefstyle: basic --> + + + @@ -171,7 +176,7 @@ Davis, CA 95616, USA - + @@ -186,7 +191,7 @@ Davis, CA 95616, USA - + diff --git a/data_model/clusters/WakeOnLAN.xml b/data_model/clusters/WakeOnLAN.xml index 799c92a03fd9b8..deb5af5a75ac7d 100644 --- a/data_model/clusters/WakeOnLAN.xml +++ b/data_model/clusters/WakeOnLAN.xml @@ -54,11 +54,16 @@ This notice and disclaimer must be included on all copies of this document. Connectivity Standards Alliance 508 Second Street, Suite 206 Davis, CA 95616, USA + +:xrefstyle: basic --> - + + + + diff --git a/data_model/clusters/WaterContentMeasurement.xml b/data_model/clusters/WaterContentMeasurement.xml index 8b1ff6a9a049bc..85d44793c93ae4 100644 --- a/data_model/clusters/WaterContentMeasurement.xml +++ b/data_model/clusters/WaterContentMeasurement.xml @@ -54,6 +54,8 @@ This notice and disclaimer must be included on all copies of this document. Connectivity Standards Alliance 508 Second Street, Suite 206 Davis, CA 95616, USA + +:xrefstyle: basic --> @@ -61,6 +63,9 @@ Davis, CA 95616, USA + + + diff --git a/data_model/clusters/WaterHeaterManagement.xml b/data_model/clusters/WaterHeaterManagement.xml index 073da0094b0b4b..4b6368555bf1d6 100644 --- a/data_model/clusters/WaterHeaterManagement.xml +++ b/data_model/clusters/WaterHeaterManagement.xml @@ -54,11 +54,16 @@ This notice and disclaimer must be included on all copies of this document. Connectivity Standards Alliance 508 Second Street, Suite 206 Davis, CA 95616, USA + +:xrefstyle: basic --> + + + @@ -129,7 +134,7 @@ Davis, CA 95616, USA - + @@ -151,7 +156,7 @@ Davis, CA 95616, USA - + diff --git a/data_model/clusters/WiFiNetworkManagement.xml b/data_model/clusters/WiFiNetworkManagement.xml index 6308eca7e4b184..fbb7a84a4e17b2 100644 --- a/data_model/clusters/WiFiNetworkManagement.xml +++ b/data_model/clusters/WiFiNetworkManagement.xml @@ -54,11 +54,16 @@ This notice and disclaimer must be included on all copies of this document. Connectivity Standards Alliance 508 Second Street, Suite 206 Davis, CA 95616, USA + +:xrefstyle: basic --> - + + + + @@ -69,12 +74,11 @@ Davis, CA 95616, USA - + - diff --git a/data_model/clusters/WindowCovering.xml b/data_model/clusters/WindowCovering.xml index 3ee6d43ded8bce..7b0afd461fcb96 100644 --- a/data_model/clusters/WindowCovering.xml +++ b/data_model/clusters/WindowCovering.xml @@ -54,6 +54,8 @@ This notice and disclaimer must be included on all copies of this document. Connectivity Standards Alliance 508 Second Street, Suite 206 Davis, CA 95616, USA + +:xrefstyle: basic --> @@ -63,6 +65,9 @@ Davis, CA 95616, USA + + + @@ -608,19 +613,19 @@ Davis, CA 95616, USA - + - + - + - + @@ -633,7 +638,7 @@ Davis, CA 95616, USA - + @@ -655,7 +660,7 @@ Davis, CA 95616, USA - + @@ -668,7 +673,7 @@ Davis, CA 95616, USA - + diff --git a/data_model/clusters/bridge-clusters-Actions.xml b/data_model/clusters/bridge-clusters-ActionsCluster.xml similarity index 87% rename from data_model/clusters/bridge-clusters-Actions.xml rename to data_model/clusters/bridge-clusters-ActionsCluster.xml index 51f7ee79bb4bad..e02b12e43d64a4 100644 --- a/data_model/clusters/bridge-clusters-Actions.xml +++ b/data_model/clusters/bridge-clusters-ActionsCluster.xml @@ -54,11 +54,16 @@ This notice and disclaimer must be included on all copies of this document. Connectivity Standards Alliance 508 Second Street, Suite 206 Davis, CA 95616, USA + +:sectnums: --> + + + @@ -159,7 +164,7 @@ Davis, CA 95616, USA - + @@ -181,7 +186,7 @@ Davis, CA 95616, USA - + @@ -189,32 +194,35 @@ Davis, CA 95616, USA - + + - + - + + - + - + + - + - + - + - + @@ -223,7 +231,7 @@ Davis, CA 95616, USA - + @@ -235,7 +243,7 @@ Davis, CA 95616, USA - + @@ -244,7 +252,7 @@ Davis, CA 95616, USA - + @@ -256,7 +264,7 @@ Davis, CA 95616, USA - + @@ -265,7 +273,7 @@ Davis, CA 95616, USA - + @@ -274,7 +282,7 @@ Davis, CA 95616, USA - + @@ -286,7 +294,7 @@ Davis, CA 95616, USA - + @@ -295,7 +303,7 @@ Davis, CA 95616, USA - + @@ -304,7 +312,7 @@ Davis, CA 95616, USA - + @@ -316,7 +324,7 @@ Davis, CA 95616, USA - + @@ -325,7 +333,7 @@ Davis, CA 95616, USA - + diff --git a/data_model/clusters/bridge-clusters-BridgedDeviceBasicInformation.xml b/data_model/clusters/bridge-clusters-BridgedDeviceBasicInformationCluster.xml similarity index 95% rename from data_model/clusters/bridge-clusters-BridgedDeviceBasicInformation.xml rename to data_model/clusters/bridge-clusters-BridgedDeviceBasicInformationCluster.xml index 5c4bd86b9ab7e4..1dd336ef3656a3 100644 --- a/data_model/clusters/bridge-clusters-BridgedDeviceBasicInformation.xml +++ b/data_model/clusters/bridge-clusters-BridgedDeviceBasicInformationCluster.xml @@ -54,13 +54,18 @@ This notice and disclaimer must be included on all copies of this document. Connectivity Standards Alliance 508 Second Street, Suite 206 Davis, CA 95616, USA + +:sectnums: --> - + + + + @@ -129,6 +134,9 @@ Davis, CA 95616, USA + + + diff --git a/data_model/clusters/energy_management.xml b/data_model/clusters/energy_management.xml index 792560796cdd4d..93858d1d1b3c89 100644 --- a/data_model/clusters/energy_management.xml +++ b/data_model/clusters/energy_management.xml @@ -54,5 +54,7 @@ This notice and disclaimer must be included on all copies of this document. Connectivity Standards Alliance 508 Second Street, Suite 206 Davis, CA 95616, USA + +:toc: --> \ No newline at end of file diff --git a/data_model/clusters/network_infrastructure.xml b/data_model/clusters/network_infrastructure.xml index 181ee350003454..7e75cc0af8229f 100644 --- a/data_model/clusters/network_infrastructure.xml +++ b/data_model/clusters/network_infrastructure.xml @@ -59,4 +59,4 @@ Connectivity Standards Alliance 508 Second Street, Suite 206 Davis, CA 95616, USA --> - \ No newline at end of file + diff --git a/data_model/device_types/BaseDeviceType.xml b/data_model/device_types/BaseDeviceType.xml index a92816ac49d6e1..22cec956aa6061 100644 --- a/data_model/device_types/BaseDeviceType.xml +++ b/data_model/device_types/BaseDeviceType.xml @@ -62,23 +62,4 @@ Davis, CA 95616, USA - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/data_model/device_types/Cooktop.xml b/data_model/device_types/Cooktop.xml index 233c72ed37590a..ea94653008d25a 100644 --- a/data_model/device_types/Cooktop.xml +++ b/data_model/device_types/Cooktop.xml @@ -71,9 +71,6 @@ Davis, CA 95616, USA - - - diff --git a/data_model/clusters/Timer.xml b/data_model/device_types/DeviceEnergyManagement.xml similarity index 55% rename from data_model/clusters/Timer.xml rename to data_model/device_types/DeviceEnergyManagement.xml index ad0d864f016e92..9d993a9454ea15 100644 --- a/data_model/clusters/Timer.xml +++ b/data_model/device_types/DeviceEnergyManagement.xml @@ -55,77 +55,17 @@ Connectivity Standards Alliance 508 Second Street, Suite 206 Davis, CA 95616, USA --> - + - + - - - - - - - - - - - - - - - - - - - - - - - - - + + + - - - - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file + + + \ No newline at end of file diff --git a/data_model/device_types/EVSE.xml b/data_model/device_types/EVSE.xml index f15b1db770b454..9e6ce7be28f301 100644 --- a/data_model/device_types/EVSE.xml +++ b/data_model/device_types/EVSE.xml @@ -65,28 +65,6 @@ Davis, CA 95616, USA - - - - - - - - - - - - - - - - - - - - - - diff --git a/data_model/device_types/Thermostat.xml b/data_model/device_types/Thermostat.xml index fc154468e97c5f..cbdedb7c039ed5 100644 --- a/data_model/device_types/Thermostat.xml +++ b/data_model/device_types/Thermostat.xml @@ -82,13 +82,13 @@ Davis, CA 95616, USA - + - + diff --git a/data_model/scraper_version b/data_model/scraper_version index 0495c4a88caed0..e8ea05db81420d 100644 --- a/data_model/scraper_version +++ b/data_model/scraper_version @@ -1 +1 @@ -1.2.3 +1.2.4 diff --git a/data_model/spec_sha b/data_model/spec_sha index ec683a1872fc3e..97f7f06deb9fe9 100644 --- a/data_model/spec_sha +++ b/data_model/spec_sha @@ -1 +1 @@ -72ce960f71810d6ca96125aea54e4fb0a9631e34 +b0310bae0264a29665f23a8f3d4dc4f742be6075 diff --git a/scripts/spec_xml/generate_spec_xml.py b/scripts/spec_xml/generate_spec_xml.py index f4f30d060096a0..016f92d4b5759a 100755 --- a/scripts/spec_xml/generate_spec_xml.py +++ b/scripts/spec_xml/generate_spec_xml.py @@ -79,7 +79,7 @@ def scrape_clusters(scraper, spec_root, output_dir, dry_run): def scrape_cluster(filename: str) -> None: xml_path = get_xml_path(filename, clusters_output_dir) - cmd = [scraper, 'cluster', '-i', filename, '-o', xml_path, '-nd'] + cmd = [scraper, 'cluster', '-i', filename, '-o', xml_path, '-nd', '--define', 'in-progress'] if dry_run: print(cmd) else: diff --git a/src/python_testing/spec_parsing_support.py b/src/python_testing/spec_parsing_support.py index 9b65df0d0dcab5..6a9d1f87ae3442 100644 --- a/src/python_testing/spec_parsing_support.py +++ b/src/python_testing/spec_parsing_support.py @@ -354,6 +354,9 @@ def get_command_type(self, element: ElementTree.Element) -> CommandType: return CommandType.GENERATED if element.attrib['direction'].lower() == 'commandtoclient': return CommandType.UNKNOWN + if element.attrib['direction'].lower() == 'commandtoserver': + return CommandType.ACCEPTED + raise Exception(f"Unknown direction: {element.attrib['direction']}") except KeyError: return CommandType.ACCEPTED From c13b324a3b9dcd3b278015c03c33ceab5fbd1a30 Mon Sep 17 00:00:00 2001 From: Erwin Pan Date: Sat, 17 Feb 2024 13:10:39 +0800 Subject: [PATCH 014/385] [Chef] fix air quality sensor build broken (#32191) * [Chef] fix air quality senesor build broken * Restyled by clang-format --------- Co-authored-by: Restyled.io --- examples/chef/common/chef-air-quality.h | 12 ++++++------ .../chef/common/chef-concentration-measurement.h | 13 +++++++------ 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/examples/chef/common/chef-air-quality.h b/examples/chef/common/chef-air-quality.h index 2eaf3ef28fdf66..e7589488d41d74 100644 --- a/examples/chef/common/chef-air-quality.h +++ b/examples/chef/common/chef-air-quality.h @@ -22,10 +22,10 @@ #include #ifdef MATTER_DM_PLUGIN_AIR_QUALITY_SERVER -Protocols::InteractionModel::Status chefAirQualityWriteCallback(chip::EndpointId endpoint, chip::ClusterId clusterId, - const EmberAfAttributeMetadata * attributeMetadata, - uint8_t * buffer); -Protocols::InteractionModel::Status chefAirQualityReadCallback(chip::EndpointId endpoint, chip::ClusterId clusterId, - const EmberAfAttributeMetadata * attributeMetadata, uint8_t * buffer, - uint16_t maxReadLength); +chip::Protocols::InteractionModel::Status chefAirQualityWriteCallback(chip::EndpointId endpoint, chip::ClusterId clusterId, + const EmberAfAttributeMetadata * attributeMetadata, + uint8_t * buffer); +chip::Protocols::InteractionModel::Status chefAirQualityReadCallback(chip::EndpointId endpoint, chip::ClusterId clusterId, + const EmberAfAttributeMetadata * attributeMetadata, + uint8_t * buffer, uint16_t maxReadLength); #endif diff --git a/examples/chef/common/chef-concentration-measurement.h b/examples/chef/common/chef-concentration-measurement.h index 9b8fc571872c6b..887df7d943ee08 100644 --- a/examples/chef/common/chef-concentration-measurement.h +++ b/examples/chef/common/chef-concentration-measurement.h @@ -31,10 +31,11 @@ defined(MATTER_DM_PLUGIN_PM10_CONCENTRATION_MEASUREMENT_SERVER) || \ defined(MATTER_DM_PLUGIN_TOTAL_VOLATILE_ORGANIC_COMPOUNDS_CONCENTRATION_MEASUREMENT_SERVER) || \ defined(MATTER_DM_PLUGIN_RADON_CONCENTRATION_MEASUREMENT_SERVER) -Protocols::InteractionModel::Status chefConcentrationMeasurementWriteCallback(chip::EndpointId endpoint, chip::ClusterId clusterId, - const EmberAfAttributeMetadata * attributeMetadata, - uint8_t * buffer); -Protocols::InteractionModel::Status chefConcentrationMeasurementReadCallback(chip::EndpointId endpoint, chip::ClusterId clusterId, - const EmberAfAttributeMetadata * attributeMetadata, - uint8_t * buffer, uint16_t maxReadLength); +chip::Protocols::InteractionModel::Status +chefConcentrationMeasurementWriteCallback(chip::EndpointId endpoint, chip::ClusterId clusterId, + const EmberAfAttributeMetadata * attributeMetadata, uint8_t * buffer); +chip::Protocols::InteractionModel::Status +chefConcentrationMeasurementReadCallback(chip::EndpointId endpoint, chip::ClusterId clusterId, + const EmberAfAttributeMetadata * attributeMetadata, uint8_t * buffer, + uint16_t maxReadLength); #endif From 2f2c4f1e311c9c35912e21156f816837986bc857 Mon Sep 17 00:00:00 2001 From: Jeff Tung <100387939+jtung-apple@users.noreply.github.com> Date: Fri, 16 Feb 2024 23:57:19 -0800 Subject: [PATCH 015/385] [Darwin] MTRDevice attribute cache persistent storage local test facility (#32181) * [Darwin] MTRDevice attribute cache persistent storage local test facility * Fix header scope * Fix CI compilation issue * Added MTR_PER_CONTROLLER_STORAGE_ENABLED check to fix darwin CI * Fix for the previous fix - now double tested --- src/darwin/Framework/CHIP/MTRBaseDevice.mm | 2 +- .../Framework/CHIP/MTRDeviceController.mm | 22 +++- .../MTRDeviceControllerLocalTestStorage.h | 37 +++++++ .../MTRDeviceControllerLocalTestStorage.m | 97 +++++++++++++++++ .../Framework/CHIPTests/MTRDeviceTests.m | 101 +++++++++++++++--- .../CHIPTests/MTRPerControllerStorageTests.m | 23 +--- .../TestHelpers/MTRTestDeclarations.h | 60 +++++++++++ .../Matter.xcodeproj/project.pbxproj | 17 +-- 8 files changed, 313 insertions(+), 46 deletions(-) create mode 100644 src/darwin/Framework/CHIP/MTRDeviceControllerLocalTestStorage.h create mode 100644 src/darwin/Framework/CHIP/MTRDeviceControllerLocalTestStorage.m create mode 100644 src/darwin/Framework/CHIPTests/TestHelpers/MTRTestDeclarations.h diff --git a/src/darwin/Framework/CHIP/MTRBaseDevice.mm b/src/darwin/Framework/CHIP/MTRBaseDevice.mm index 00f65b25dc000b..2a981cdd860fff 100644 --- a/src/darwin/Framework/CHIP/MTRBaseDevice.mm +++ b/src/darwin/Framework/CHIP/MTRBaseDevice.mm @@ -1976,7 +1976,6 @@ - (void)failSubscribers:(dispatch_queue_t)queue completion:(void (^)(void))compl MTR_LOG_DEBUG("Causing failure in subscribers on purpose"); CauseReadClientFailure(self.deviceController, self.nodeID, queue, completion); } -#endif // The following method is for unit testing purpose only + (id)CHIPEncodeAndDecodeNSObject:(id)object @@ -2018,6 +2017,7 @@ + (id)CHIPEncodeAndDecodeNSObject:(id)object } return decodedData.GetDecodedObject(); } +#endif - (void)readEventsWithEndpointID:(NSNumber * _Nullable)endpointID clusterID:(NSNumber * _Nullable)clusterID diff --git a/src/darwin/Framework/CHIP/MTRDeviceController.mm b/src/darwin/Framework/CHIP/MTRDeviceController.mm index 64d70ce647cdb7..edd521845b2415 100644 --- a/src/darwin/Framework/CHIP/MTRDeviceController.mm +++ b/src/darwin/Framework/CHIP/MTRDeviceController.mm @@ -32,6 +32,7 @@ #import "MTRConversion.h" #import "MTRDeviceControllerDelegateBridge.h" #import "MTRDeviceControllerFactory_Internal.h" +#import "MTRDeviceControllerLocalTestStorage.h" #import "MTRDeviceControllerStartupParams.h" #import "MTRDeviceControllerStartupParams_Internal.h" #import "MTRDevice_Internal.h" @@ -173,12 +174,31 @@ - (instancetype)initWithFactory:(MTRDeviceControllerFactory *)factory return nil; } + id storageDelegateToUse = storageDelegate; +#if MTR_PER_CONTROLLER_STORAGE_ENABLED + if (MTRDeviceControllerLocalTestStorage.localTestStorageEnabled) { + storageDelegateToUse = [[MTRDeviceControllerLocalTestStorage alloc] initWithPassThroughStorage:storageDelegate]; + } +#endif // MTR_PER_CONTROLLER_STORAGE_ENABLED _controllerDataStore = [[MTRDeviceControllerDataStore alloc] initWithController:self - storageDelegate:storageDelegate + storageDelegate:storageDelegateToUse storageDelegateQueue:storageDelegateQueue]; if (_controllerDataStore == nil) { return nil; } + } else { +#if MTR_PER_CONTROLLER_STORAGE_ENABLED + if (MTRDeviceControllerLocalTestStorage.localTestStorageEnabled) { + dispatch_queue_t localTestStorageQueue = dispatch_queue_create("org.csa-iot.matter.framework.devicecontroller.localteststorage", DISPATCH_QUEUE_SERIAL_WITH_AUTORELEASE_POOL); + MTRDeviceControllerLocalTestStorage * localTestStorage = [[MTRDeviceControllerLocalTestStorage alloc] initWithPassThroughStorage:nil]; + _controllerDataStore = [[MTRDeviceControllerDataStore alloc] initWithController:self + storageDelegate:localTestStorage + storageDelegateQueue:localTestStorageQueue]; + if (_controllerDataStore == nil) { + return nil; + } + } +#endif // MTR_PER_CONTROLLER_STORAGE_ENABLED } // Ensure the otaProviderDelegate, if any, is valid. diff --git a/src/darwin/Framework/CHIP/MTRDeviceControllerLocalTestStorage.h b/src/darwin/Framework/CHIP/MTRDeviceControllerLocalTestStorage.h new file mode 100644 index 00000000000000..915834ecabd35c --- /dev/null +++ b/src/darwin/Framework/CHIP/MTRDeviceControllerLocalTestStorage.h @@ -0,0 +1,37 @@ +// +/** + * Copyright (c) 2023 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import +#import + +#if MTR_PER_CONTROLLER_STORAGE_ENABLED + +NS_ASSUME_NONNULL_BEGIN + +MTR_EXTERN @interface MTRDeviceControllerLocalTestStorage : NSObject + +// Setting this variable only affects subsequent MTRDeviceController initializations +@property (class, nonatomic, assign) BOOL localTestStorageEnabled; + +// This storage persists items to NSUserDefaults for MTRStorageSharingTypeNotShared data. Items with other sharing types will be droppped, or stored/fetched with the "passthrough storage" if one is specified. +- (instancetype)initWithPassThroughStorage:(id _Nullable)passThroughStorage; + +@end + +NS_ASSUME_NONNULL_END + +#endif // MTR_PER_CONTROLLER_STORAGE_ENABLED diff --git a/src/darwin/Framework/CHIP/MTRDeviceControllerLocalTestStorage.m b/src/darwin/Framework/CHIP/MTRDeviceControllerLocalTestStorage.m new file mode 100644 index 00000000000000..4d52e4bf18afb6 --- /dev/null +++ b/src/darwin/Framework/CHIP/MTRDeviceControllerLocalTestStorage.m @@ -0,0 +1,97 @@ +// +/** + * Copyright (c) 2023 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "MTRDeviceControllerLocalTestStorage.h" + +#if MTR_PER_CONTROLLER_STORAGE_ENABLED + +static NSString * const kLocalTestUserDefaultDomain = @"org.csa-iot.matter.darwintest"; +static NSString * const kLocalTestUserDefaultEnabledKey = @"enableTestStorage"; + +@implementation MTRDeviceControllerLocalTestStorage { + id _passThroughStorage; +} + ++ (BOOL)localTestStorageEnabled +{ + NSUserDefaults * defaults = [[NSUserDefaults alloc] initWithSuiteName:kLocalTestUserDefaultDomain]; + return [defaults boolForKey:kLocalTestUserDefaultEnabledKey]; +} + ++ (void)setLocalTestStorageEnabled:(BOOL)localTestStorageEnabled +{ + NSUserDefaults * defaults = [[NSUserDefaults alloc] initWithSuiteName:kLocalTestUserDefaultDomain]; + [defaults setBool:localTestStorageEnabled forKey:kLocalTestUserDefaultEnabledKey]; +} + +- (instancetype)initWithPassThroughStorage:(id)passThroughStorage +{ + if (self = [super init]) { + _passThroughStorage = passThroughStorage; + } + return self; +} + +- (nullable id)controller:(MTRDeviceController *)controller + valueForKey:(NSString *)key + securityLevel:(MTRStorageSecurityLevel)securityLevel + sharingType:(MTRStorageSharingType)sharingType +{ + if (sharingType == MTRStorageSharingTypeNotShared) { + NSUserDefaults * defaults = [[NSUserDefaults alloc] initWithSuiteName:kLocalTestUserDefaultDomain]; + NSData * storedData = [defaults dataForKey:key]; + NSError * error; + id value = [NSKeyedUnarchiver unarchivedObjectOfClasses:MTRDeviceControllerStorageClasses() fromData:storedData error:&error]; + return value; + } else { + return [_passThroughStorage controller:controller valueForKey:key securityLevel:securityLevel sharingType:sharingType]; + } +} + +- (BOOL)controller:(MTRDeviceController *)controller + storeValue:(id)value + forKey:(NSString *)key + securityLevel:(MTRStorageSecurityLevel)securityLevel + sharingType:(MTRStorageSharingType)sharingType +{ + if (sharingType == MTRStorageSharingTypeNotShared) { + NSError * error; + NSData * data = [NSKeyedArchiver archivedDataWithRootObject:value requiringSecureCoding:YES error:&error]; + NSUserDefaults * defaults = [[NSUserDefaults alloc] initWithSuiteName:kLocalTestUserDefaultDomain]; + [defaults setObject:data forKey:key]; + return YES; + } else { + return [_passThroughStorage controller:controller storeValue:value forKey:key securityLevel:securityLevel sharingType:sharingType]; + } +} + +- (BOOL)controller:(MTRDeviceController *)controller + removeValueForKey:(NSString *)key + securityLevel:(MTRStorageSecurityLevel)securityLevel + sharingType:(MTRStorageSharingType)sharingType +{ + if (sharingType == MTRStorageSharingTypeNotShared) { + NSUserDefaults * defaults = [[NSUserDefaults alloc] initWithSuiteName:kLocalTestUserDefaultDomain]; + [defaults removeObjectForKey:key]; + return YES; + } else { + return [_passThroughStorage controller:controller removeValueForKey:key securityLevel:securityLevel sharingType:sharingType]; + } +} +@end + +#endif // MTR_PER_CONTROLLER_STORAGE_ENABLED diff --git a/src/darwin/Framework/CHIPTests/MTRDeviceTests.m b/src/darwin/Framework/CHIPTests/MTRDeviceTests.m index 66bca12cc47bfd..e4628bd475b5ae 100644 --- a/src/darwin/Framework/CHIPTests/MTRDeviceTests.m +++ b/src/darwin/Framework/CHIPTests/MTRDeviceTests.m @@ -25,8 +25,10 @@ #import #import "MTRCommandPayloadExtensions_Internal.h" +#import "MTRDeviceControllerLocalTestStorage.h" #import "MTRDeviceTestDelegate.h" #import "MTRErrorTestUtils.h" +#import "MTRTestDeclarations.h" #import "MTRTestKeys.h" #import "MTRTestResetCommissioneeHelper.h" #import "MTRTestStorage.h" @@ -74,19 +76,6 @@ static void WaitForCommissionee(XCTestExpectation * expectation) return mConnectedDevice; } -#ifdef DEBUG -@interface MTRBaseDevice (Test) -- (void)failSubscribers:(dispatch_queue_t)queue completion:(void (^)(void))completion; - -// Test function for whitebox testing -+ (id)CHIPEncodeAndDecodeNSObject:(id)object; -@end - -@interface MTRDevice (Test) -- (void)unitTestInjectEventReport:(NSArray *> *)eventReport; -@end -#endif - @interface MTRDeviceTestDeviceControllerDelegate : NSObject @property (nonatomic, strong) XCTestExpectation * expectation; @end @@ -129,10 +118,19 @@ @interface MTRDeviceTests : XCTestCase @implementation MTRDeviceTests +#if MTR_PER_CONTROLLER_STORAGE_ENABLED +static BOOL slocalTestStorageEnabledBeforeUnitTest; +#endif // MTR_PER_CONTROLLER_STORAGE_ENABLED + + (void)setUp { XCTestExpectation * pairingExpectation = [[XCTestExpectation alloc] initWithDescription:@"Pairing Complete"]; +#if MTR_PER_CONTROLLER_STORAGE_ENABLED + slocalTestStorageEnabledBeforeUnitTest = MTRDeviceControllerLocalTestStorage.localTestStorageEnabled; + MTRDeviceControllerLocalTestStorage.localTestStorageEnabled = YES; +#endif // MTR_PER_CONTROLLER_STORAGE_ENABLED + __auto_type * factory = [MTRDeviceControllerFactory sharedInstance]; XCTAssertNotNil(factory); @@ -182,6 +180,14 @@ + (void)tearDown { ResetCommissionee(GetConnectedDevice(), dispatch_get_main_queue(), nil, kTimeoutInSeconds); +#if MTR_PER_CONTROLLER_STORAGE_ENABLED + // Restore testing setting to previous state, and remove all persisted attributes + MTRDeviceControllerLocalTestStorage.localTestStorageEnabled = slocalTestStorageEnabledBeforeUnitTest; + [sController.controllerDataStore clearAllStoredAttributes]; + NSArray * storedAttributesAfterClear = [sController.controllerDataStore getStoredAttributesForNodeID:@(kDeviceId)]; + XCTAssertEqual(storedAttributesAfterClear.count, 0); +#endif // MTR_PER_CONTROLLER_STORAGE_ENABLED + MTRDeviceController * controller = sController; XCTAssertNotNil(controller); [controller shutdown]; @@ -1236,7 +1242,7 @@ - (void)test015_FailedSubscribeWithQueueAcrossShutdown __auto_type * params = [[MTRSubscribeParams alloc] init]; params.resubscribeAutomatically = NO; params.replaceExistingSubscriptions = NO; // Not strictly needed, but checking that doing this does not - // affect this subscription erroring out correctly. + // affect this subscription erroring out correctly. [device subscribeWithQueue:queue minInterval:1 maxInterval:2 @@ -1344,6 +1350,11 @@ - (void)test016_FailedSubscribeWithCacheReadDuringFailure - (void)test017_TestMTRDeviceBasics { + // Ensure the test starts with clean slate, even with MTRDeviceControllerLocalTestStorage enabled + [sController.controllerDataStore clearAllStoredAttributes]; + NSArray * storedAttributesAfterClear = [sController.controllerDataStore getStoredAttributesForNodeID:@(kDeviceId)]; + XCTAssertEqual(storedAttributesAfterClear.count, 0); + __auto_type * device = [MTRDevice deviceWithNodeID:kDeviceId deviceController:sController]; dispatch_queue_t queue = dispatch_get_main_queue(); @@ -1526,6 +1537,7 @@ - (void)test017_TestMTRDeviceBasics // Resubscription test setup XCTestExpectation * subscriptionDroppedExpectation = [self expectationWithDescription:@"Subscription has dropped"]; + delegate.onNotReachable = ^() { [subscriptionDroppedExpectation fulfill]; }; @@ -1600,7 +1612,7 @@ - (void)test018_SubscriptionErrorWhenNotResubscribing MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(1) maxInterval:@(10)]; params.resubscribeAutomatically = NO; params.replaceExistingSubscriptions = NO; // Not strictly needed, but checking that doing this does not - // affect this subscription erroring out correctly. + // affect this subscription erroring out correctly. __block BOOL subscriptionEstablished = NO; [device subscribeToAttributesWithEndpointID:@1 clusterID:@6 @@ -2826,6 +2838,65 @@ - (void)test030_DeviceAndClusterProperties XCTAssertEqualObjects(cluster.endpointID, @(0)); } +#if MTR_PER_CONTROLLER_STORAGE_ENABLED +- (void)test031_MTRDeviceAttributeCacheLocalTestStorage +{ + dispatch_queue_t queue = dispatch_get_main_queue(); + + // First start with clean slate and + __auto_type * device = [MTRDevice deviceWithNodeID:@(kDeviceId) controller:sController]; + [sController removeDevice:device]; + [sController.controllerDataStore clearAllStoredAttributes]; + NSArray * storedAttributesAfterClear = [sController.controllerDataStore getStoredAttributesForNodeID:@(kDeviceId)]; + XCTAssertEqual(storedAttributesAfterClear.count, 0); + + // Now recreate device and get subscription primed + device = [MTRDevice deviceWithNodeID:@(kDeviceId) controller:sController]; + XCTestExpectation * gotReportsExpectation = [self expectationWithDescription:@"Attribute and Event reports have been received"]; + __auto_type * delegate = [[MTRDeviceTestDelegate alloc] init]; + __weak __auto_type weakDelegate = delegate; + delegate.onReportEnd = ^{ + [gotReportsExpectation fulfill]; + __strong __auto_type strongDelegate = weakDelegate; + strongDelegate.onReportEnd = nil; + }; + [device setDelegate:delegate queue:queue]; + + [self waitForExpectations:@[ gotReportsExpectation ] timeout:60]; + + NSUInteger attributesReportedWithFirstSubscription = [device unitTestAttributesReportedSinceLastCheck]; + + NSArray * dataStoreValuesAfterFirstSubscription = [sController.controllerDataStore getStoredAttributesForNodeID:@(kDeviceId)]; + XCTAssertTrue(dataStoreValuesAfterFirstSubscription.count > 0); + + // Now remove device, resubscribe, and see that it succeeds + [sController removeDevice:device]; + device = [MTRDevice deviceWithNodeID:@(kDeviceId) controller:sController]; + + XCTestExpectation * resubGotReportsExpectation = [self expectationWithDescription:@"Attribute and Event reports have been received for resubscription"]; + delegate.onReportEnd = ^{ + [resubGotReportsExpectation fulfill]; + __strong __auto_type strongDelegate = weakDelegate; + strongDelegate.onReportEnd = nil; + }; + [device setDelegate:delegate queue:queue]; + + [self waitForExpectations:@[ resubGotReportsExpectation ] timeout:60]; + + NSUInteger attributesReportedWithSecondSubscription = [device unitTestAttributesReportedSinceLastCheck]; + + XCTAssertTrue(attributesReportedWithSecondSubscription < attributesReportedWithFirstSubscription); + + // 1) MTRDevice actually gets some attributes reported more than once + // 2) Some attributes do change on resubscribe + // * With all-clusts-app as of 2024-02-10, out of 1287 persisted attributes, still 450 attributes were reported with filter + // And so conservatively, assert that data version filters save at least 300 entries. + NSArray * dataStoreValuesAfterSecondSubscription = [sController.controllerDataStore getStoredAttributesForNodeID:@(kDeviceId)]; + NSUInteger storedAttributeCountDifferenceFromMTRDeviceReport = dataStoreValuesAfterSecondSubscription.count - attributesReportedWithSecondSubscription; + XCTAssertTrue(storedAttributeCountDifferenceFromMTRDeviceReport > 300); +} +#endif // MTR_PER_CONTROLLER_STORAGE_ENABLED + @end @interface MTRDeviceEncoderTests : XCTestCase diff --git a/src/darwin/Framework/CHIPTests/MTRPerControllerStorageTests.m b/src/darwin/Framework/CHIPTests/MTRPerControllerStorageTests.m index 661dbadb9ac445..38795bcc8cef87 100644 --- a/src/darwin/Framework/CHIPTests/MTRPerControllerStorageTests.m +++ b/src/darwin/Framework/CHIPTests/MTRPerControllerStorageTests.m @@ -22,6 +22,7 @@ #import "MTRDeviceTestDelegate.h" #import "MTRErrorTestUtils.h" #import "MTRFabricInfoChecker.h" +#import "MTRTestDeclarations.h" #import "MTRTestKeys.h" #import "MTRTestPerControllerStorage.h" #import "MTRTestResetCommissioneeHelper.h" @@ -33,28 +34,6 @@ static NSString * kOnboardingPayload = @"MT:-24J0AFN00KA0648G00"; static const uint16_t kTestVendorId = 0xFFF1u; -#ifdef DEBUG -// MTRDeviceControllerDataStore.h includes C++ header, and so we need to declare the methods separately -@protocol MTRDeviceControllerDataStoreAttributeStoreMethods -- (nullable NSArray *)getStoredAttributesForNodeID:(NSNumber *)nodeID; -- (void)storeAttributeValues:(NSArray *)dataValues forNodeID:(NSNumber *)nodeID; -- (void)clearStoredAttributesForNodeID:(NSNumber *)nodeID; -- (void)clearAllStoredAttributes; -@end - -// Declare internal methods for testing -@interface MTRDeviceController (Test) -+ (void)forceLocalhostAdvertisingOnly; -- (void)removeDevice:(MTRDevice *)device; -@property (nonatomic, readonly, nullable) id controllerDataStore; -@end - -@interface MTRDevice (Test) -- (BOOL)_attributeDataValue:(NSDictionary *)one isEqualToDataValue:(NSDictionary *)theOther; -- (NSUInteger)unitTestAttributesReportedSinceLastCheck; -@end -#endif // DEBUG - @interface MTRPerControllerStorageTestsControllerDelegate : NSObject @property (nonatomic, strong) XCTestExpectation * expectation; @property (nonatomic, strong) NSNumber * deviceID; diff --git a/src/darwin/Framework/CHIPTests/TestHelpers/MTRTestDeclarations.h b/src/darwin/Framework/CHIPTests/TestHelpers/MTRTestDeclarations.h new file mode 100644 index 00000000000000..5b77d0ec06aad7 --- /dev/null +++ b/src/darwin/Framework/CHIPTests/TestHelpers/MTRTestDeclarations.h @@ -0,0 +1,60 @@ +// +/** + * Copyright (c) 2023 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +#pragma mark - Declarations for internal methods + +// MTRDeviceControllerDataStore.h includes C++ header, and so we need to declare the methods separately +@protocol MTRDeviceControllerDataStoreAttributeStoreMethods +- (nullable NSArray *)getStoredAttributesForNodeID:(NSNumber *)nodeID; +- (void)storeAttributeValues:(NSArray *)dataValues forNodeID:(NSNumber *)nodeID; +- (void)clearStoredAttributesForNodeID:(NSNumber *)nodeID; +- (void)clearAllStoredAttributes; +@end + +// Declare internal methods for testing +@interface MTRDeviceController (Test) ++ (void)forceLocalhostAdvertisingOnly; +- (void)removeDevice:(MTRDevice *)device; +@property (nonatomic, readonly, nullable) id controllerDataStore; +@end + +@interface MTRDevice (Test) +- (BOOL)_attributeDataValue:(NSDictionary *)one isEqualToDataValue:(NSDictionary *)theOther; +@end + +#pragma mark - Declarations for items compiled only for DEBUG configuration + +#ifdef DEBUG +@interface MTRBaseDevice (TestDebug) +- (void)failSubscribers:(dispatch_queue_t)queue completion:(void (^)(void))completion; + +// Test function for whitebox testing ++ (id)CHIPEncodeAndDecodeNSObject:(id)object; +@end + +@interface MTRDevice (TestDebug) +- (void)unitTestInjectEventReport:(NSArray *> *)eventReport; +- (NSUInteger)unitTestAttributesReportedSinceLastCheck; +@end +#endif + +NS_ASSUME_NONNULL_END diff --git a/src/darwin/Framework/Matter.xcodeproj/project.pbxproj b/src/darwin/Framework/Matter.xcodeproj/project.pbxproj index 5e227bc7a8d2b2..a49b33fa3a1ea4 100644 --- a/src/darwin/Framework/Matter.xcodeproj/project.pbxproj +++ b/src/darwin/Framework/Matter.xcodeproj/project.pbxproj @@ -240,6 +240,8 @@ 5ACDDD7D27CD16D200EFD68A /* MTRClusterStateCacheContainer.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5ACDDD7C27CD16D200EFD68A /* MTRClusterStateCacheContainer.mm */; }; 5ACDDD7E27CD3F3A00EFD68A /* MTRClusterStateCacheContainer_Internal.h in Headers */ = {isa = PBXBuildFile; fileRef = 5ACDDD7B27CD14AF00EFD68A /* MTRClusterStateCacheContainer_Internal.h */; }; 5AE6D4E427A99041001F2493 /* MTRDeviceTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 5AE6D4E327A99041001F2493 /* MTRDeviceTests.m */; }; + 75139A6F2B7FE5E900E3A919 /* MTRDeviceControllerLocalTestStorage.m in Sources */ = {isa = PBXBuildFile; fileRef = 75139A6E2B7FE5E900E3A919 /* MTRDeviceControllerLocalTestStorage.m */; }; + 75139A702B7FE68C00E3A919 /* MTRDeviceControllerLocalTestStorage.h in Headers */ = {isa = PBXBuildFile; fileRef = 75139A6D2B7FE5D600E3A919 /* MTRDeviceControllerLocalTestStorage.h */; settings = {ATTRIBUTES = (Private, ); }; }; 7534F12828BFF20300390851 /* MTRDeviceAttestationDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = 7534F12628BFF20300390851 /* MTRDeviceAttestationDelegate.mm */; }; 7534F12928BFF20300390851 /* MTRDeviceAttestationDelegate_Internal.h in Headers */ = {isa = PBXBuildFile; fileRef = 7534F12728BFF20300390851 /* MTRDeviceAttestationDelegate_Internal.h */; }; 754F3DF427FBB94B00E60580 /* MTREventTLVValueDecoder_Internal.h in Headers */ = {isa = PBXBuildFile; fileRef = 754F3DF327FBB94B00E60580 /* MTREventTLVValueDecoder_Internal.h */; }; @@ -633,6 +635,9 @@ 5ACDDD7B27CD14AF00EFD68A /* MTRClusterStateCacheContainer_Internal.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MTRClusterStateCacheContainer_Internal.h; sourceTree = ""; }; 5ACDDD7C27CD16D200EFD68A /* MTRClusterStateCacheContainer.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = MTRClusterStateCacheContainer.mm; sourceTree = ""; }; 5AE6D4E327A99041001F2493 /* MTRDeviceTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MTRDeviceTests.m; sourceTree = ""; }; + 75139A6C2B7FE19100E3A919 /* MTRTestDeclarations.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MTRTestDeclarations.h; sourceTree = ""; }; + 75139A6D2B7FE5D600E3A919 /* MTRDeviceControllerLocalTestStorage.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MTRDeviceControllerLocalTestStorage.h; sourceTree = ""; }; + 75139A6E2B7FE5E900E3A919 /* MTRDeviceControllerLocalTestStorage.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MTRDeviceControllerLocalTestStorage.m; sourceTree = ""; }; 7534F12628BFF20300390851 /* MTRDeviceAttestationDelegate.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MTRDeviceAttestationDelegate.mm; sourceTree = ""; }; 7534F12728BFF20300390851 /* MTRDeviceAttestationDelegate_Internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MTRDeviceAttestationDelegate_Internal.h; sourceTree = ""; }; 754F3DF327FBB94B00E60580 /* MTREventTLVValueDecoder_Internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MTREventTLVValueDecoder_Internal.h; sourceTree = ""; }; @@ -792,9 +797,6 @@ 039145E02993102B00257B3E /* main.mm */, 03F430A52994100000166449 /* controller */, 039547092992DB02006D42A8 /* editline */, - 039546AD2991E193006D42A8 /* log */, - 039546B12991E194006D42A8 /* system */, - 039546A72991E185006D42A8 /* delay */, 039546A22991E132006D42A8 /* interaction_model */, 039546972991DFC4006D42A8 /* lib_json */, 039546872991C400006D42A8 /* chip-tool */, @@ -815,7 +817,6 @@ 03FB93DA2A46200A0048CB35 /* discover */, 037C3D7C2991BD4F00B7EEE2 /* pairing */, 037C3D852991BD4F00B7EEE2 /* clusters */, - 037C3D8B2991BD4F00B7EEE2 /* tests */, 037C3D8D2991BD4F00B7EEE2 /* provider */, 037C3D932991BD4F00B7EEE2 /* payload */, 037C3D972991BD4F00B7EEE2 /* storage */, @@ -1105,6 +1106,7 @@ 51C984602A61CE2A00B0AD9A /* MTRFabricInfoChecker.m */, 75B0D01C2B71B46F002074DD /* MTRDeviceTestDelegate.h */, 75B0D01D2B71B47F002074DD /* MTRDeviceTestDelegate.m */, + 75139A6C2B7FE19100E3A919 /* MTRTestDeclarations.h */, ); path = TestHelpers; sourceTree = ""; @@ -1238,6 +1240,8 @@ 5136661228067D550025EDAE /* MTRDeviceControllerFactory.h */, 5136661128067D540025EDAE /* MTRDeviceControllerFactory_Internal.h */, 5136661028067D540025EDAE /* MTRDeviceControllerFactory.mm */, + 75139A6D2B7FE5D600E3A919 /* MTRDeviceControllerLocalTestStorage.h */, + 75139A6E2B7FE5E900E3A919 /* MTRDeviceControllerLocalTestStorage.m */, 5A6FEC8D27B5624E00F25F42 /* MTRDeviceControllerOverXPC.h */, 5A830D6B27CFCF590053B85D /* MTRDeviceControllerOverXPC_Internal.h */, 5A6FEC8F27B563D900F25F42 /* MTRDeviceControllerOverXPC.mm */, @@ -1555,6 +1559,7 @@ 1EC4CE6425CC276600D7304F /* MTRBaseClusters.h in Headers */, 3D843712294977000070D20A /* MTRCallbackBridgeBase.h in Headers */, 3DECCB742934C21B00585AEC /* MTRDefines.h in Headers */, + 75139A702B7FE68C00E3A919 /* MTRDeviceControllerLocalTestStorage.h in Headers */, 2C5EEEF6268A85C400CAE3D3 /* MTRDeviceConnectionBridge.h in Headers */, 2C8C8FC0253E0C2100797F05 /* MTRPersistentStorageDelegateBridge.h in Headers */, 51FE72352ACDB40000437032 /* MTRCommandPayloads_Internal.h in Headers */, @@ -1753,7 +1758,6 @@ B45373EF2A9FEBFE00807602 /* ops-raw-skt.c in Sources */, 516411332B6BF77700E67C05 /* MTRServerAccessControl.mm in Sources */, 037C3DD52991C2E200B7EEE2 /* CHIPCommandBridge.mm in Sources */, - 039546BC2991E1CB006D42A8 /* LogCommands.cpp in Sources */, 516411312B6BF70300E67C05 /* DataModelHandler.cpp in Sources */, B45373E12A9FEB7F00807602 /* ops-h1.c in Sources */, B45373EB2A9FEBDB00807602 /* ops-listen.c in Sources */, @@ -1766,13 +1770,11 @@ B45373E62A9FEBA400807602 /* header.c in Sources */, B45374002A9FEC4F00807602 /* unix-init.c in Sources */, B45373DF2A9FEB6F00807602 /* system.c in Sources */, - 039546BD2991E1CB006D42A8 /* SystemCommands.cpp in Sources */, B45373FC2A9FEC4F00807602 /* unix-caps.c in Sources */, B4E262162AA0CF1C00DBA5BC /* RemoteDataModelLogger.mm in Sources */, B45373ED2A9FEBEC00807602 /* ops-pipe.c in Sources */, B45373C02A9FEA9100807602 /* output.c in Sources */, 0395470F2992DB37006D42A8 /* complete.c in Sources */, - 039546BE2991E1CB006D42A8 /* DelayCommands.cpp in Sources */, B4E2621B2AA0D02000DBA5BC /* SleepCommand.mm in Sources */, B45373FF2A9FEC4F00807602 /* unix-misc.c in Sources */, B45373D92A9FEB3800807602 /* poll.c in Sources */, @@ -1840,6 +1842,7 @@ 75B765C32A1D82D30014719B /* MTRAttributeSpecifiedCheck.mm in Sources */, AF5F90FF2878D351005503FA /* MTROTAProviderDelegateBridge.mm in Sources */, 516415FF2B6B132200D5CE11 /* DataModelHandler.cpp in Sources */, + 75139A6F2B7FE5E900E3A919 /* MTRDeviceControllerLocalTestStorage.m in Sources */, 51E95DFC2A78443C00A434F0 /* MTRSessionResumptionStorageBridge.mm in Sources */, 514C79ED2B62ADCD00DD6D7B /* ember-compatibility-functions.cpp in Sources */, 7534F12828BFF20300390851 /* MTRDeviceAttestationDelegate.mm in Sources */, From acedec197c61d8b2b2bbe55fac16faf8a73b190e Mon Sep 17 00:00:00 2001 From: Hasty Granbery Date: Sun, 18 Feb 2024 04:45:59 +0900 Subject: [PATCH 016/385] Power Topology: add test scripts (#32114) * Initial XML for Power Topology cluster * Regen * Restyled really wants newlines at the end of every JSON file * Rename LeafTopology to TreeTopology * [Feature] Power Topology server & all-clusters-app stub * Make endpointId a constructor arg for PowerTopologyDelegate * Change PowerTopologyDelegate to not return std::vectors * Remove unneeded entries in attributeAccessInterfaceAttributes for Power Topology cluster * Typo in python/chip/clusters/__init__.py * Format zcl.json * Add DynamicPowerFlow feature to PowerTopology stub * Add Power Topology to client * Set CI PICS values * Python test script for Power Topology * Linted python script * Add Power Topology python script test * Add PWRTL_1_1 to ciTests.json * Restyled * Regen * Format PICS.yaml --- .github/workflows/tests.yaml | 1 + src/app/tests/suites/certification/PICS.yaml | 33 +++++ .../certification/Test_TC_PWRTL_1_1.yaml | 119 ++++++++++++++++++ .../tests/suites/certification/ci-pics-values | 12 ++ src/app/tests/suites/ciTests.json | 1 + src/app/tests/suites/manualTests.json | 2 + src/app/zap_cluster_list.json | 2 +- src/python_testing/TC_PWRTL_2_1.py | 69 ++++++++++ 8 files changed, 238 insertions(+), 1 deletion(-) create mode 100644 src/app/tests/suites/certification/Test_TC_PWRTL_1_1.yaml create mode 100644 src/python_testing/TC_PWRTL_2_1.py diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index 05d2670edd665e..f083cd70bccd7c 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yaml @@ -502,6 +502,7 @@ jobs: scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --app out/linux-x64-all-clusters-ipv6only-no-ble-no-wifi-tsan-clang-test/chip-all-clusters-app --factoryreset --app-args "--discriminator 1234 --KVS kvs1 --trace-to json:out/trace_data/app-{SCRIPT_BASE_NAME}.json" --script "src/python_testing/TC_IDM_1_2.py" --script-args "--storage-path admin_storage.json --commissioning-method on-network --discriminator 1234 --passcode 20202021 --trace-to json:out/trace_data/test-{SCRIPT_BASE_NAME}.json --trace-to perfetto:out/trace_data/test-{SCRIPT_BASE_NAME}.perfetto"' scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --app out/linux-x64-all-clusters-ipv6only-no-ble-no-wifi-tsan-clang-test/chip-all-clusters-app --factoryreset --app-args "--discriminator 1234 --KVS kvs1 --trace-to json:out/trace_data/app-{SCRIPT_BASE_NAME}.json --enable-key 000102030405060708090a0b0c0d0e0f" --script "src/python_testing/TC_IDM_1_4.py" --script-args "--hex-arg PIXIT.DGGEN.TEST_EVENT_TRIGGER_KEY:000102030405060708090a0b0c0d0e0f --storage-path admin_storage.json --commissioning-method on-network --discriminator 1234 --passcode 20202021 --trace-to json:out/trace_data/test-{SCRIPT_BASE_NAME}.json --trace-to perfetto:out/trace_data/test-{SCRIPT_BASE_NAME}.perfetto"' scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --app out/linux-x64-all-clusters-ipv6only-no-ble-no-wifi-tsan-clang-test/chip-all-clusters-app --factoryreset --app-args "--discriminator 1234 --KVS kvs1 --trace-to json:out/trace_data/app-{SCRIPT_BASE_NAME}.json" --script "src/python_testing/TC_IDM_4_2.py" --script-args "--storage-path admin_storage.json --commissioning-method on-network --discriminator 1234 --passcode 20202021 --trace-to json:out/trace_data/test-{SCRIPT_BASE_NAME}.json --trace-to perfetto:out/trace_data/test-{SCRIPT_BASE_NAME}.perfetto"' + scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --app out/linux-x64-all-clusters-ipv6only-no-ble-no-wifi-tsan-clang-test/chip-all-clusters-app --factoryreset --app-args "--discriminator 1234 --KVS kvs1 --trace-to json:out/trace_data/app-{SCRIPT_BASE_NAME}.json" --script "src/python_testing/TC_PWRTL_2_1.py" --script-args "--storage-path admin_storage.json --commissioning-method on-network --discriminator 1234 --passcode 20202021 --trace-to json:out/trace_data/test-{SCRIPT_BASE_NAME}.json --trace-to perfetto:out/trace_data/test-{SCRIPT_BASE_NAME}.perfetto"' scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --app out/linux-x64-all-clusters-ipv6only-no-ble-no-wifi-tsan-clang-test/chip-all-clusters-app --factoryreset --app-args "--discriminator 1234 --KVS kvs1 --trace-to json:out/trace_data/app-{SCRIPT_BASE_NAME}.json" --script "src/python_testing/TC_RR_1_1.py" --script-args "--storage-path admin_storage.json --commissioning-method on-network --discriminator 1234 --passcode 20202021 --trace-to json:out/trace_data/test-{SCRIPT_BASE_NAME}.json --trace-to perfetto:out/trace_data/test-{SCRIPT_BASE_NAME}.perfetto"' scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --app out/linux-x64-all-clusters-ipv6only-no-ble-no-wifi-tsan-clang-test/chip-all-clusters-app --factoryreset --app-args "--discriminator 1234 --KVS kvs1 --trace-to json:out/trace_data/app-{SCRIPT_BASE_NAME}.json" --script "src/python_testing/TC_RVCCLEANM_1_2.py" --script-args "--int-arg PIXIT_ENDPOINT:1 --storage-path admin_storage.json --commissioning-method on-network --discriminator 1234 --passcode 20202021 --trace-to json:out/trace_data/test-{SCRIPT_BASE_NAME}.json --trace-to perfetto:out/trace_data/test-{SCRIPT_BASE_NAME}.perfetto"' scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --app out/linux-x64-all-clusters-ipv6only-no-ble-no-wifi-tsan-clang-test/chip-all-clusters-app --factoryreset --app-args "--discriminator 1234 --KVS kvs1 --trace-to json:out/trace_data/app-{SCRIPT_BASE_NAME}.json" --script "src/python_testing/TC_RVCRUNM_1_2.py" --script-args "--int-arg PIXIT_ENDPOINT:1 --storage-path admin_storage.json --commissioning-method on-network --discriminator 1234 --passcode 20202021 --trace-to json:out/trace_data/test-{SCRIPT_BASE_NAME}.json --trace-to perfetto:out/trace_data/test-{SCRIPT_BASE_NAME}.perfetto"' diff --git a/src/app/tests/suites/certification/PICS.yaml b/src/app/tests/suites/certification/PICS.yaml index 068db7f0dfe525..49554c37f4e3b6 100644 --- a/src/app/tests/suites/certification/PICS.yaml +++ b/src/app/tests/suites/certification/PICS.yaml @@ -10160,3 +10160,36 @@ PICS: - label: "Can the mode change be manually controlled?" id: EEVSEM.S.M.CAN_MANUALLY_CONTROLLED + + # + # Power Topology Cluster + # + - label: "Does the device implement the Power Topology Cluster as a server?" + id: PWRTL.S + + # Features + + - label: + "Does the associated endpoint provide or consume power for the entire + node?" + id: PWRTL.S.F00 + + - label: + "Does the associated endpoint provide or consume power for itself and + its child endpoints?" + id: PWRTL.S.F01 + + - label: + "Does the associated endpoint provide or consume power for a provided + set of endpoints?" + id: PWRTL.S.F02 + + - label: "Can the provided set of endpoints change?" + id: PWRTL.S.F03 + + #Server attributes + - label: "Does the device implement the AvailableEndpoints attribute?" + id: PWRTL.S.A0000 + + - label: "Does the device implement the ActiveEndpoints attribute?" + id: PWRTL.S.A0001 diff --git a/src/app/tests/suites/certification/Test_TC_PWRTL_1_1.yaml b/src/app/tests/suites/certification/Test_TC_PWRTL_1_1.yaml new file mode 100644 index 00000000000000..cfe6fd860be240 --- /dev/null +++ b/src/app/tests/suites/certification/Test_TC_PWRTL_1_1.yaml @@ -0,0 +1,119 @@ +# Copyright (c) 2021 Project CHIP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# Auto-generated scripts for harness use only, please review before automation. The endpoints and cluster names are currently set to default + +name: 44.1.1. [TC-PWRTL-1.1] Global Attributes with DUT as Server + +PICS: + - PWRTL.S + +config: + nodeId: 0x12344321 + cluster: "Power Topology" + endpoint: 1 + +tests: + - label: "Step 1: Wait for the commissioned device to be retrieved" + cluster: "DelayCommands" + command: "WaitForCommissionee" + arguments: + values: + - name: "nodeId" + value: nodeId + + - label: "Step 2: TH reads the ClusterRevision from DUT" + command: "readAttribute" + attribute: "ClusterRevision" + response: + value: 1 + constraints: + type: int16u + + - label: + "Step 3a: Given PWRTL.S.F00(Node) ensure featuremap has the correct + bit set" + PICS: PWRTL.S.F00 + command: "readAttribute" + attribute: "FeatureMap" + response: + constraints: + type: bitmap32 + hasMasksSet: [0x1] + hasMasksClear: [0x2, 0x4, 0x8] + + - label: + "Step 3b: Given PWRTL.S.F01(Leaf) ensure featuremap has the correct + bit set" + PICS: PWRTL.S.F01 + command: "readAttribute" + attribute: "FeatureMap" + response: + constraints: + type: bitmap32 + hasMasksSet: [0x2] + hasMasksClear: [0x1, 0x4, 0x8] + + - label: + "Step 3c: Given PWRTL.S.F02(Set) ensure featuremap has the correct bit + set" + PICS: PWRTL.S.F02 + command: "readAttribute" + attribute: "FeatureMap" + response: + constraints: + type: bitmap32 + hasMasksSet: [0x4] + hasMasksClear: [0x1, 0x2] + + - label: + "Step 3d: Given PWRTL.S.F03(Dynamic Power Flow) ensure featuremap has + the correct bit set" + PICS: PWRTL.S.F03 + command: "readAttribute" + attribute: "FeatureMap" + response: + constraints: + type: bitmap32 + hasMasksSet: [0x4, 0x8] + + - label: "Step 4a: TH reads AttributeList from DUT" + PICS: "!PICS_SF_SET && !PICS_SF_DYPF" + command: "readAttribute" + attribute: "AttributeList" + response: + constraints: + type: list + contains: [] + + - label: + "Step 4b: TH reads feature dependent attribute(AvailableEndpoints) + AttributeList from DUT" + PICS: "PICS_SF_SET && !PICS_SF_DYPF" + command: "readAttribute" + attribute: "AttributeList" + response: + constraints: + type: list + contains: [0] + + - label: + "Step 4c: TH reads feature dependent attribute(ActiveEndpoints) + AttributeList from DUT" + PICS: "PICS_SF_SET && PICS_SF_DYPF" + command: "readAttribute" + attribute: "AttributeList" + response: + constraints: + type: list + contains: [0, 1] diff --git a/src/app/tests/suites/certification/ci-pics-values b/src/app/tests/suites/certification/ci-pics-values index c710f846f0a13a..f200ad302931ff 100644 --- a/src/app/tests/suites/certification/ci-pics-values +++ b/src/app/tests/suites/certification/ci-pics-values @@ -2939,3 +2939,15 @@ DEMM.S.C01.Tx=1 #Manual controllable DEMM.S.M.CAN_TEST_MODE_FAILURE=1 DEMM.S.M.CAN_MANUALLY_CONTROLLED=1 + +#Power Topology Cluster +# Server +PWRTL.S=1 +PWRTL.S.A0000=1 +PWRTL.S.A0001=1 + +#Features +PWRTL.S.F00=0 +PWRTL.S.F01=0 +PWRTL.S.F02=1 +PWRTL.S.F03=1 \ No newline at end of file diff --git a/src/app/tests/suites/ciTests.json b/src/app/tests/suites/ciTests.json index ee6b5436451a6f..26efd799ad7efd 100644 --- a/src/app/tests/suites/ciTests.json +++ b/src/app/tests/suites/ciTests.json @@ -191,6 +191,7 @@ "Test_TC_OO_2_4" ], "PowerSource": ["Test_TC_PS_1_1", "Test_TC_PS_2_1"], + "PowerTopology": ["Test_TC_PWRTL_1_1"], "PressureMeasurement": [ "Test_TC_PRS_1_1", "Test_TC_PRS_2_1", diff --git a/src/app/tests/suites/manualTests.json b/src/app/tests/suites/manualTests.json index 774b3d8dce35f3..d199a682492150 100644 --- a/src/app/tests/suites/manualTests.json +++ b/src/app/tests/suites/manualTests.json @@ -311,6 +311,7 @@ "AccessControlEnforcement": [], "OvenMode": ["Test_TC_OTCCM_1_1", "Test_TC_OTCCM_1_2"], "EnergyEVSE": ["Test_TC_EEVSE_1_1", "Test_TC_EEVSE_2_1"], + "PowerTopology": ["Test_TC_PWRTL_1_1"], "collection": [ "DeviceDiscovery", "Groups", @@ -338,6 +339,7 @@ "ModeSelect", "OTASoftwareUpdate", "PowerSourceConfiguration", + "PowerTopology", "PressureMeasurement", "SecureChannel", "SoftwareDiagnostics", diff --git a/src/app/zap_cluster_list.json b/src/app/zap_cluster_list.json index b3993634639869..56adf0a1126f95 100644 --- a/src/app/zap_cluster_list.json +++ b/src/app/zap_cluster_list.json @@ -68,7 +68,6 @@ "MESSAGES_CLUSTER": [], "MODE_SELECT_CLUSTER": [], "NETWORK_COMMISSIONING_CLUSTER": [], - "POWER_TOPOLOGY_CLUSTER": [], "SAMPLE_MEI_CLUSTER": [], "NITROGEN_DIOXIDE_CONCENTRATION_MEASUREMENT_CLUSTER": [], "OCCUPANCY_SENSING_CLUSTER": ["occupancy-sensor-server"], @@ -91,6 +90,7 @@ "POWER_PROFILE_CLUSTER": [], "POWER_SOURCE_CLUSTER": [], "POWER_SOURCE_CONFIGURATION_CLUSTER": [], + "POWER_TOPOLOGY_CLUSTER": [], "PRESSURE_MEASUREMENT_CLUSTER": [], "PROXY_CONFIGURATION_CLUSTER": [], "PROXY_DISCOVERY_CLUSTER": [], diff --git a/src/python_testing/TC_PWRTL_2_1.py b/src/python_testing/TC_PWRTL_2_1.py new file mode 100644 index 00000000000000..bd839cd5f072f4 --- /dev/null +++ b/src/python_testing/TC_PWRTL_2_1.py @@ -0,0 +1,69 @@ +# +# Copyright (c) 2024 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. +# + +import logging + +import chip.clusters as Clusters +from chip.clusters.Types import NullValue +from matter_testing_support import MatterBaseTest, async_test_body, default_matter_test_main +from mobly import asserts + + +class TC_PWRTL_2_1(MatterBaseTest): + + def pics_TC_PWRTL_2_1(self) -> list[str]: + return ["PWRTL.S"] + + @async_test_body + async def test_TC_PWRTL_2_1(self): + + attributes = Clusters.PowerTopology.Attributes + + endpoint = self.user_params.get("endpoint", 1) + + self.print_step(1, "Commissioning, already done") + + if not self.check_pics("PWRTL.S.A0000"): + logging.info("Test skipped because PICS PWRTL.S.A0000 is not set") + return + + self.print_step(2, "Read AvailableAttributes attribute") + available_endpoints = await self.read_single_attribute_check_success(endpoint=endpoint, cluster=Clusters.Objects.PowerTopology, attribute=attributes.AvailableEndpoints) + + if available_endpoints == NullValue: + logging.info("AvailableEndpoints is null") + else: + logging.info("AvailableEndpoints: %s" % (available_endpoints)) + + asserts.assert_less_equal(len(available_endpoints), 21, + "AvailableEndpoints length %d must be less than 21!" % len(available_endpoints)) + + if not self.check_pics("PWRTL.S.A0001"): + logging.info("Test skipped because PICS PWRTL.S.A0001 is not set") + return + + self.print_step(3, "Read ActiveEndpoints attribute") + active_endpoints = await self.read_single_attribute_check_success(endpoint=endpoint, cluster=Clusters.Objects.PowerTopology, attribute=attributes.ActiveEndpoints) + logging.info("ActiveEndpoints: %s" % (active_endpoints)) + + if available_endpoints == NullValue: + asserts.assert_true(active_endpoints == NullValue, + "ActiveEndpoints should be null when AvailableEndpoints is null: %s" % active_endpoints) + + +if __name__ == "__main__": + default_matter_test_main() From dbc6ed396be4b99faa5ea064e13e33c80e1ded4b Mon Sep 17 00:00:00 2001 From: yunhanw-google Date: Sun, 18 Feb 2024 02:10:50 -0800 Subject: [PATCH 017/385] [Android]Pass write response status from jni to application (#32164) --- .../clusterclient/BasicClientFragment.kt | 5 +- .../OtaProviderClientFragment.kt | 9 +- .../clusterclient/WildcardFragment.kt | 5 +- .../pairing/PairOnNetworkLongImReadCommand.kt | 9 +- .../PairOnNetworkLongImWriteCommand.kt | 8 +- kotlin-detect-config.yaml | 4 +- .../generators/java/ChipClusters_java.jinja | 12 ++- .../several_clusters/java/ChipClusters.java | 12 ++- src/controller/java/AndroidCallbacks.cpp | 22 +++-- src/controller/java/BUILD.gn | 2 + .../chip/devicecontroller/ChipClusters.java | 12 ++- .../devicecontroller/StatusException.java | 34 ++++++++ .../WriteAttributesCallback.java | 4 +- .../WriteAttributesCallbackJni.java | 12 ++- .../chip/devicecontroller/model/Status.java | 80 +++++++++++++++-- .../matter/controller/MatterControllerImpl.kt | 8 +- .../controller/WriteAttributesCallback.kt | 4 +- .../controller/WriteAttributesCallbackJni.kt | 12 ++- .../src/matter/controller/model/States.kt | 2 - .../src/matter/controller/model/Status.kt | 86 +++++++++++++++++++ .../python/chip/interaction_model/__init__.py | 1 + .../interaction_model/StatusCodeList.h | 5 +- 22 files changed, 296 insertions(+), 52 deletions(-) create mode 100644 src/controller/java/src/chip/devicecontroller/StatusException.java create mode 100644 src/controller/java/src/matter/controller/model/Status.kt diff --git a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/BasicClientFragment.kt b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/BasicClientFragment.kt index 0662ec08dc2146..f38cacbd259073 100644 --- a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/BasicClientFragment.kt +++ b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/BasicClientFragment.kt @@ -17,6 +17,7 @@ import chip.devicecontroller.model.AttributeWriteRequest import chip.devicecontroller.model.ChipAttributePath import chip.devicecontroller.model.ChipEventPath import chip.devicecontroller.model.NodeState +import chip.devicecontroller.model.Status import com.google.chip.chiptool.ChipClient import com.google.chip.chiptool.GenericChipDeviceListener import com.google.chip.chiptool.R @@ -191,8 +192,8 @@ class BasicClientFragment : Fragment() { Log.e(TAG, "Write ${attribute.name} failure", ex) } - override fun onResponse(attributePath: ChipAttributePath?) { - showMessage("Write ${attribute.name} success") + override fun onResponse(attributePath: ChipAttributePath, status: Status) { + showMessage("Write ${attribute.name} response: $status") } }, devicePtr, diff --git a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/OtaProviderClientFragment.kt b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/OtaProviderClientFragment.kt index 87735856fa4844..c27159193ed2dc 100644 --- a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/OtaProviderClientFragment.kt +++ b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/OtaProviderClientFragment.kt @@ -32,6 +32,7 @@ import chip.devicecontroller.model.AttributeWriteRequest import chip.devicecontroller.model.ChipAttributePath import chip.devicecontroller.model.ChipEventPath import chip.devicecontroller.model.NodeState +import chip.devicecontroller.model.Status import com.google.chip.chiptool.ChipClient import com.google.chip.chiptool.GenericChipDeviceListener import com.google.chip.chiptool.R @@ -223,9 +224,9 @@ class OtaProviderClientFragment : Fragment() { showMessage("Error : ${e.toString()}") } - override fun onResponse(attributePath: ChipAttributePath?) { + override fun onResponse(attributePath: ChipAttributePath, status: Status) { Log.d(TAG, "onResponse") - showMessage("write Success") + showMessage("$attributePath : Write response: $status") } }, ChipClient.getConnectedDevicePointer(requireContext(), addressUpdateFragment.deviceId), @@ -350,9 +351,9 @@ class OtaProviderClientFragment : Fragment() { showMessage("error : ${e.toString()}") } - override fun onResponse(attributePath: ChipAttributePath?) { + override fun onResponse(attributePath: ChipAttributePath, status: Status) { Log.d(TAG, "onResponse") - showMessage("write success") + showMessage("$attributePath : Write response: $status") } }, ChipClient.getConnectedDevicePointer(requireContext(), addressUpdateFragment.deviceId), diff --git a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/WildcardFragment.kt b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/WildcardFragment.kt index 1978951e02e210..af119581a7047f 100644 --- a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/WildcardFragment.kt +++ b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/WildcardFragment.kt @@ -27,6 +27,7 @@ import chip.devicecontroller.model.ChipEventPath import chip.devicecontroller.model.ChipPathId import chip.devicecontroller.model.InvokeElement import chip.devicecontroller.model.NodeState +import chip.devicecontroller.model.Status import com.google.chip.chiptool.ChipClient import com.google.chip.chiptool.R import com.google.chip.chiptool.databinding.WildcardFragmentBinding @@ -92,8 +93,8 @@ class WildcardFragment : Fragment() { Log.e(TAG, "Report error for $attributePath: $ex") } - override fun onResponse(attributePath: ChipAttributePath?) { - val text = "$attributePath : Write Success" + override fun onResponse(attributePath: ChipAttributePath, status: Status) { + val text = "$attributePath : Write response: $status" requireActivity().runOnUiThread { binding.outputTv.text = text } } diff --git a/examples/java-matter-controller/java/src/com/matter/controller/commands/pairing/PairOnNetworkLongImReadCommand.kt b/examples/java-matter-controller/java/src/com/matter/controller/commands/pairing/PairOnNetworkLongImReadCommand.kt index e0a95d584130eb..1758fbd868fbfb 100644 --- a/examples/java-matter-controller/java/src/com/matter/controller/commands/pairing/PairOnNetworkLongImReadCommand.kt +++ b/examples/java-matter-controller/java/src/com/matter/controller/commands/pairing/PairOnNetworkLongImReadCommand.kt @@ -67,13 +67,12 @@ class PairOnNetworkLongImReadCommand( } fun checkUnitTestClusterGeneralStatus(status: Status): Boolean = - (status.getStatus() == CLUSTER_ID_TEST_GENERAL_ERROR_STATUS) && - !status.getClusterStatus().isPresent() + (status.getStatus() == Status.Code.InvalidDataType) && !status.getClusterStatus().isPresent() fun checkUnitTestClusterClusterStatus(status: Status): Boolean = - (status.getStatus() == CLUSTER_ID_TEST_CLUSTER_ERROR_STATUS) && + (status.getStatus() == Status.Code.Failure) && status.getClusterStatus().isPresent() && - status.getClusterStatus().get() == CLUSTER_ID_TEST_CLUSTER_ERROR_CLUSTER_STATUS + (status.getClusterStatus().get() == CLUSTER_ID_TEST_CLUSTER_ERROR_CLUSTER_STATUS) private fun validateResponse(nodeState: NodeState) { val endpointZero = @@ -243,8 +242,6 @@ class PairOnNetworkLongImReadCommand( private const val CLUSTER_ID_BASIC_VERSION = 0L private const val CLUSTER_ID_TEST_GENERAL_ERROR_BOOLEAN = 0x0031L private const val CLUSTER_ID_TEST_CLUSTER_ERROR_BOOLEAN = 0x0032L - private const val CLUSTER_ID_TEST_GENERAL_ERROR_STATUS = 0x8d - private const val CLUSTER_ID_TEST_CLUSTER_ERROR_STATUS = 1 private const val CLUSTER_ID_TEST_CLUSTER_ERROR_CLUSTER_STATUS = 17 } } diff --git a/examples/java-matter-controller/java/src/com/matter/controller/commands/pairing/PairOnNetworkLongImWriteCommand.kt b/examples/java-matter-controller/java/src/com/matter/controller/commands/pairing/PairOnNetworkLongImWriteCommand.kt index 3e90935d22268e..fdb74c5d065b5c 100644 --- a/examples/java-matter-controller/java/src/com/matter/controller/commands/pairing/PairOnNetworkLongImWriteCommand.kt +++ b/examples/java-matter-controller/java/src/com/matter/controller/commands/pairing/PairOnNetworkLongImWriteCommand.kt @@ -22,6 +22,7 @@ import chip.devicecontroller.GetConnectedDeviceCallbackJni.GetConnectedDeviceCal import chip.devicecontroller.WriteAttributesCallback import chip.devicecontroller.model.AttributeWriteRequest import chip.devicecontroller.model.ChipAttributePath +import chip.devicecontroller.model.Status import com.matter.controller.commands.common.CredentialsIssuer import java.util.logging.Level import java.util.logging.Logger @@ -51,11 +52,8 @@ class PairOnNetworkLongImWriteCommand( setFailure("write failure") } - override fun onResponse(attributePath: ChipAttributePath?) { - logger.log(Level.INFO, "Write receive OnResponse on ") - if (attributePath != null) { - logger.log(Level.INFO, attributePath.toString()) - } + override fun onResponse(attributePath: ChipAttributePath, status: Status) { + logger.log(Level.INFO, "$attributePath : Write response: $status") setSuccess() } } diff --git a/kotlin-detect-config.yaml b/kotlin-detect-config.yaml index 6de03b283f7065..2ad54a05d6c483 100644 --- a/kotlin-detect-config.yaml +++ b/kotlin-detect-config.yaml @@ -36,8 +36,8 @@ style: - "**/src/controller/java/src/matter/tlv/types.kt" - "**/src/controller/java/src/matter/tlv/utils.kt" - "**/src/controller/java/src/matter/tlv/values.kt" - - "**/src/controller/java/src/chip/WildcardImport - examples/android/CHIPTest/app/src/androidTest/java/com/tcl/chip/chiptest/ExampleInstrumentedTest.kt" + - "**/src/controller/java/src/matter/tlv/values.kt" + - "**/src/controller/java/src/matter/controller/model/Status.kt" - "**/src/controller/java/tests/chip/devicecontroller/cluster/ChipClusterEventStructTest.kt" - "**/src/controller/java/tests/chip/devicecontroller/cluster/ChipClusterStructTest.kt" - "**/src/controller/java/tests/matter/jsontlv/JsonToTlvToJsonTest.kt" diff --git a/scripts/py_matter_idl/matter_idl/generators/java/ChipClusters_java.jinja b/scripts/py_matter_idl/matter_idl/generators/java/ChipClusters_java.jinja index ba0abf5976f49c..6c8ad742068684 100644 --- a/scripts/py_matter_idl/matter_idl/generators/java/ChipClusters_java.jinja +++ b/scripts/py_matter_idl/matter_idl/generators/java/ChipClusters_java.jinja @@ -102,6 +102,7 @@ import chip.devicecontroller.model.ClusterState; import chip.devicecontroller.model.EndpointState; import chip.devicecontroller.model.InvokeElement; import chip.devicecontroller.model.NodeState; +import chip.devicecontroller.model.Status; import javax.annotation.Nullable; import java.util.ArrayList; @@ -318,8 +319,15 @@ public class ChipClusters { } @Override - public void onResponse(ChipAttributePath attributePath) { - callback.onSuccess(); + public void onResponse(ChipAttributePath attributePath, Status status) { + if (status.getStatus() == Status.Code.Success) + { + callback.onSuccess(); + } + else + { + callback.onError(new StatusException(status.getStatus())); + } } @Override diff --git a/scripts/py_matter_idl/matter_idl/tests/outputs/several_clusters/java/ChipClusters.java b/scripts/py_matter_idl/matter_idl/tests/outputs/several_clusters/java/ChipClusters.java index 9b6287a9a954ae..37c5c031b5c5ae 100644 --- a/scripts/py_matter_idl/matter_idl/tests/outputs/several_clusters/java/ChipClusters.java +++ b/scripts/py_matter_idl/matter_idl/tests/outputs/several_clusters/java/ChipClusters.java @@ -25,6 +25,7 @@ import chip.devicecontroller.model.EndpointState; import chip.devicecontroller.model.InvokeElement; import chip.devicecontroller.model.NodeState; +import chip.devicecontroller.model.Status; import javax.annotation.Nullable; import java.util.ArrayList; @@ -241,8 +242,15 @@ static class WriteAttributesCallbackImpl implements WriteAttributesCallback { } @Override - public void onResponse(ChipAttributePath attributePath) { - callback.onSuccess(); + public void onResponse(ChipAttributePath attributePath, Status status) { + if (status.getStatus() == Status.Code.Success) + { + callback.onSuccess(); + } + else + { + callback.onError(new StatusException(status.getStatus())); + } } @Override diff --git a/src/controller/java/AndroidCallbacks.cpp b/src/controller/java/AndroidCallbacks.cpp index eb6e8b1a5f255b..eb1584b531e292 100644 --- a/src/controller/java/AndroidCallbacks.cpp +++ b/src/controller/java/AndroidCallbacks.cpp @@ -669,23 +669,27 @@ void WriteAttributesCallback::OnResponse(const app::WriteClient * apWriteClient, JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread(); VerifyOrReturn(env != nullptr, ChipLogError(Controller, "Could not get JNIEnv for current thread")); JniLocalReferenceScope scope(env); - - if (aStatus.mStatus != Protocols::InteractionModel::Status::Success) - { - ReportError(&aPath, aStatus.mStatus); - return; - } - jmethodID onResponseMethod; VerifyOrReturn(mWrapperCallbackRef.HasValidObjectRef(), ChipLogError(Controller, "mWrapperCallbackRef is not valid in %s", __func__)); jobject wrapperCallback = mWrapperCallbackRef.ObjectRef(); - err = JniReferences::GetInstance().FindMethod(env, wrapperCallback, "onResponse", "(IJJ)V", &onResponseMethod); + err = JniReferences::GetInstance().FindMethod(env, wrapperCallback, "onResponse", "(IJJILjava/lang/Integer;)V", + &onResponseMethod); VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Controller, "Unable to find onError method: %s", ErrorStr(err))); + jobject jClusterState = nullptr; + if (aStatus.mClusterStatus.HasValue()) + { + err = JniReferences::GetInstance().CreateBoxedObject( + "java/lang/Integer", "(I)V", static_cast(aStatus.mClusterStatus.Value()), jClusterState); + VerifyOrReturn(err == CHIP_NO_ERROR, + ChipLogError(Controller, "Could not CreateBoxedObject with error %" CHIP_ERROR_FORMAT, err.Format())); + } + DeviceLayer::StackUnlock unlock; env->CallVoidMethod(wrapperCallback, onResponseMethod, static_cast(aPath.mEndpointId), - static_cast(aPath.mClusterId), static_cast(aPath.mAttributeId)); + static_cast(aPath.mClusterId), static_cast(aPath.mAttributeId), aStatus.mStatus, + jClusterState); VerifyOrReturn(!env->ExceptionCheck(), env->ExceptionDescribe()); } diff --git a/src/controller/java/BUILD.gn b/src/controller/java/BUILD.gn index b2ec93cb67f160..bf41b962b4cc3d 100644 --- a/src/controller/java/BUILD.gn +++ b/src/controller/java/BUILD.gn @@ -391,6 +391,7 @@ kotlin_library("kotlin_matter_controller") { "src/matter/controller/WriteAttributesCallbackJni.kt", "src/matter/controller/model/Paths.kt", "src/matter/controller/model/States.kt", + "src/matter/controller/model/Status.kt", ] sources += matter_structs_sources @@ -477,6 +478,7 @@ android_library("java") { "src/chip/devicecontroller/ReportCallback.java", "src/chip/devicecontroller/ReportCallbackJni.java", "src/chip/devicecontroller/ResubscriptionAttemptCallback.java", + "src/chip/devicecontroller/StatusException.java", "src/chip/devicecontroller/SubscriptionEstablishedCallback.java", "src/chip/devicecontroller/ThreadScanResult.java", "src/chip/devicecontroller/UnpairDeviceCallback.java", diff --git a/src/controller/java/generated/java/chip/devicecontroller/ChipClusters.java b/src/controller/java/generated/java/chip/devicecontroller/ChipClusters.java index 6e479c5f37094c..fcc9154511d2b7 100644 --- a/src/controller/java/generated/java/chip/devicecontroller/ChipClusters.java +++ b/src/controller/java/generated/java/chip/devicecontroller/ChipClusters.java @@ -25,6 +25,7 @@ import chip.devicecontroller.model.EndpointState; import chip.devicecontroller.model.InvokeElement; import chip.devicecontroller.model.NodeState; +import chip.devicecontroller.model.Status; import javax.annotation.Nullable; import java.util.ArrayList; @@ -241,8 +242,15 @@ static class WriteAttributesCallbackImpl implements WriteAttributesCallback { } @Override - public void onResponse(ChipAttributePath attributePath) { - callback.onSuccess(); + public void onResponse(ChipAttributePath attributePath, Status status) { + if (status.getStatus() == Status.Code.Success) + { + callback.onSuccess(); + } + else + { + callback.onError(new StatusException(status.getStatus())); + } } @Override diff --git a/src/controller/java/src/chip/devicecontroller/StatusException.java b/src/controller/java/src/chip/devicecontroller/StatusException.java new file mode 100644 index 00000000000000..6a97e5b0e19aeb --- /dev/null +++ b/src/controller/java/src/chip/devicecontroller/StatusException.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2024 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. + * + */ +package chip.devicecontroller; + +import chip.devicecontroller.model.Status; + +/** Exception class holding error codes defined by Interaction Model */ +public class StatusException extends Exception { + private static final long serialVersionUID = 1L; + + public Status.Code code = Status.Code.Success; + + public StatusException() {} + + public StatusException(Status.Code code) { + super(String.format("CHIP IM status error: %s", code.name())); + this.code = code; + } +} diff --git a/src/controller/java/src/chip/devicecontroller/WriteAttributesCallback.java b/src/controller/java/src/chip/devicecontroller/WriteAttributesCallback.java index 4e469ab0e58245..477f133c81a9c4 100644 --- a/src/controller/java/src/chip/devicecontroller/WriteAttributesCallback.java +++ b/src/controller/java/src/chip/devicecontroller/WriteAttributesCallback.java @@ -18,6 +18,7 @@ package chip.devicecontroller; import chip.devicecontroller.model.ChipAttributePath; +import chip.devicecontroller.model.Status; import javax.annotation.Nullable; /** An interface for receiving write response. */ @@ -40,8 +41,9 @@ public interface WriteAttributesCallback { * path. * * @param attributePath The attribute path field in write response. + * @param status The status field in write response. */ - void onResponse(ChipAttributePath attributePath); + void onResponse(ChipAttributePath attributePath, Status status); default void onDone() {} } diff --git a/src/controller/java/src/chip/devicecontroller/WriteAttributesCallbackJni.java b/src/controller/java/src/chip/devicecontroller/WriteAttributesCallbackJni.java index fd7f8066c80a73..7b95b30759222f 100644 --- a/src/controller/java/src/chip/devicecontroller/WriteAttributesCallbackJni.java +++ b/src/controller/java/src/chip/devicecontroller/WriteAttributesCallbackJni.java @@ -18,6 +18,8 @@ package chip.devicecontroller; import chip.devicecontroller.model.ChipAttributePath; +import chip.devicecontroller.model.Status; +import javax.annotation.Nullable; /** JNI wrapper callback class for {@link WriteAttributesCallback}. */ public final class WriteAttributesCallbackJni { @@ -45,9 +47,15 @@ private void onError( e); } - private void onResponse(int endpointId, long clusterId, long attributeId) { + private void onResponse( + int endpointId, + long clusterId, + long attributeId, + int status, + @Nullable Integer clusterStatus) { wrappedWriteAttributesCallback.onResponse( - ChipAttributePath.newInstance(endpointId, clusterId, attributeId)); + ChipAttributePath.newInstance(endpointId, clusterId, attributeId), + Status.newInstance(status, clusterStatus)); } private void onDone() { diff --git a/src/controller/java/src/chip/devicecontroller/model/Status.java b/src/controller/java/src/chip/devicecontroller/model/Status.java index c367535f5e8578..d859fae9f189e0 100644 --- a/src/controller/java/src/chip/devicecontroller/model/Status.java +++ b/src/controller/java/src/chip/devicecontroller/model/Status.java @@ -21,17 +21,87 @@ import java.util.Locale; import java.util.Optional; +/** Class for Interaction Model Status * */ public final class Status { - private Integer status; + public enum Code { + Success(0x0), + Failure(0x01), + InvalidSusbscription(0x7d), + UnsupportedAccess(0x7e), + UnsupportedEndPoint(0x7f), + InvalidAction(0x80), + UnsupportedCommand(0x81), + Deprecated82(0x82), + Deprecated83(0x83), + Deprecated84(0x84), + InvalidCommand(0x85), + UnsupportedAttribute(0x86), + ConstraintError(0x87), + UnsupportedWrite(0x88), + ResourceExhausted(0x89), + Deprecated8a(0x8a), + NotFound(0x8b), + UnreportableAttribute(0x8c), + InvalidDataType(0x8d), + Deprecated8e(0x8e), + UnsupportedRead(0x8f), + Deprecated90(0x90), + Deprecated91(0x91), + DataVersionMismatch(0x92), + Deprecated93(0x93), + Timeout(0x94), + Reserved95(0x95), + Reserved96(0x96), + Reserved97(0x97), + Reserved98(0x98), + Reserved99(0x99), + Reserved9a(0x9a), + Busy(0x9c), + Deprecatedc0(0xc0), + Deprecatedc1(0xc1), + Deprecatedc2(0xc2), + UnsupportedCluster(0xc3), + Deprecatedc4(0xc4), + NoUpstreamSubsricption(0xc5), + NeedTimedInteraction(0xc6), + UnsupportedEvent(0xc7), + PathExhausted(0xc8), + TimedRequestMismatch(0xc9), + FailsafeRequired(0xca), + InvalidInState(0xcb), + NoCommandResponse(0xcc), + WriteIgnored(0xf0); + + private int id = 0; + + Code(int id) { + this.id = id; + } + + public int getId() { + return id; + } + + public static Code fromId(int id) { + for (Code type : values()) { + if (type.getId() == id) { + return type; + } + } + return null; + } + } + + private Code status = Code.Success; private Optional clusterStatus; private Status(int status, Optional clusterStatus) { - this.status = status; + this.status = Code.fromId(status); this.clusterStatus = clusterStatus; } // Getters - public Integer getStatus() { + public Code getStatus() { return status; } @@ -43,7 +113,7 @@ public String toString() { return String.format( Locale.ENGLISH, "status %s, clusterStatus %s", - String.valueOf(status), + status.name(), clusterStatus.isPresent() ? String.valueOf(clusterStatus.get()) : "None"); } @@ -51,7 +121,7 @@ public static Status newInstance(int status) { return new Status(status, Optional.empty()); } - static Status newInstance(int status, Integer clusterStatus) { + public static Status newInstance(int status, Integer clusterStatus) { return new Status(status, Optional.ofNullable(clusterStatus)); } } diff --git a/src/controller/java/src/matter/controller/MatterControllerImpl.kt b/src/controller/java/src/matter/controller/MatterControllerImpl.kt index 202d97a99e1ad0..6ae71f33a0faac 100644 --- a/src/controller/java/src/matter/controller/MatterControllerImpl.kt +++ b/src/controller/java/src/matter/controller/MatterControllerImpl.kt @@ -36,6 +36,7 @@ import matter.controller.model.AttributePath import matter.controller.model.EventPath import matter.controller.model.EventState import matter.controller.model.NodeState +import matter.controller.model.Status /** Controller to interact with the CHIP device. */ class MatterControllerImpl(params: ControllerParams) : MatterController { @@ -340,8 +341,11 @@ class MatterControllerImpl(params: ControllerParams) : MatterController { return suspendCancellableCoroutine { continuation -> val writeCallback = object : WriteAttributesCallback { - override fun onResponse(attributePath: AttributePath) { - logger.log(Level.INFO, "write success for attributePath:%s", attributePath.toString()) + override fun onResponse(attributePath: AttributePath, status: Status) { + logger.log( + Level.INFO, + "Receive write response for attributePath: ${attributePath} and status ${status}" + ) } override fun onError(attributePath: AttributePath?, ex: Exception) { diff --git a/src/controller/java/src/matter/controller/WriteAttributesCallback.kt b/src/controller/java/src/matter/controller/WriteAttributesCallback.kt index b4a3f112a02f83..6b1b3f7056f71e 100644 --- a/src/controller/java/src/matter/controller/WriteAttributesCallback.kt +++ b/src/controller/java/src/matter/controller/WriteAttributesCallback.kt @@ -18,6 +18,7 @@ package matter.controller import matter.controller.model.AttributePath +import matter.controller.model.Status /** An interface for receiving write response. */ interface WriteAttributesCallback { @@ -38,8 +39,9 @@ interface WriteAttributesCallback { * path. * * @param attributePath The attribute path field in write response. + * @param status The attribute status field in write response. */ - fun onResponse(attributePath: AttributePath) + fun onResponse(attributePath: AttributePath, status: Status) fun onDone() {} } diff --git a/src/controller/java/src/matter/controller/WriteAttributesCallbackJni.kt b/src/controller/java/src/matter/controller/WriteAttributesCallbackJni.kt index bd0bad3e228dda..fe52a329ff3078 100644 --- a/src/controller/java/src/matter/controller/WriteAttributesCallbackJni.kt +++ b/src/controller/java/src/matter/controller/WriteAttributesCallbackJni.kt @@ -18,6 +18,7 @@ package matter.controller import matter.controller.model.AttributePath +import matter.controller.model.Status /** JNI wrapper callback class for [WriteAttributesCallback]. */ class WriteAttributesCallbackJni( @@ -53,9 +54,16 @@ class WriteAttributesCallbackJni( ) } - private fun onResponse(endpointId: Int, clusterId: Long, attributeId: Long) { + private fun onResponse( + endpointId: Int, + clusterId: Long, + attributeId: Long, + status: Int, + clusterStatus: Int? + ) { wrappedWriteAttributesCallback.onResponse( - AttributePath(endpointId.toUShort(), clusterId.toUInt(), attributeId.toUInt()) + AttributePath(endpointId.toUShort(), clusterId.toUInt(), attributeId.toUInt()), + Status(status, clusterStatus) ) } diff --git a/src/controller/java/src/matter/controller/model/States.kt b/src/controller/java/src/matter/controller/model/States.kt index c913b37b9986f4..e7799f1f5a64e1 100644 --- a/src/controller/java/src/matter/controller/model/States.kt +++ b/src/controller/java/src/matter/controller/model/States.kt @@ -273,5 +273,3 @@ data class EventState( return null } } - -data class Status(val status: Int, val clusterStatus: Int?) diff --git a/src/controller/java/src/matter/controller/model/Status.kt b/src/controller/java/src/matter/controller/model/Status.kt new file mode 100644 index 00000000000000..fa12f0b1cb25a5 --- /dev/null +++ b/src/controller/java/src/matter/controller/model/Status.kt @@ -0,0 +1,86 @@ +/* + * 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. + * + */ +package matter.controller.model + +/** + * Represents information about a node, including data on all available endpoints. + * + * @param endpoints A mapping of endpoint IDs with the associated cluster data. + */ +data class Status(val status: Int, val clusterStatus: Int?) { + enum class Code(val id: Int) { + SUCCESS(0X0), + FAILURE(0X01), + INVALID_SUSBSCRIPTION(0X7D), + UNSUPPORTED_ACCESS(0X7E), + UNSUPPORTED_ENDPOINT(0X7F), + INVALID_ACTION(0X80), + UNSUPPORTED_COMMAND(0X81), + DEPRECATED82(0X82), + DEPRECATED83(0X83), + DEPRECATED84(0X84), + INVALID_COMMAND(0X85), + UNSUPPORTED_ATTRIBUTE(0X86), + CONSTRAINT_ERROR(0X87), + UNSUPPORTED_WRITE(0X88), + RESOURCE_EXHAUSTED(0X89), + DEPRECATED8A(0X8A), + NOT_FOUND(0X8B), + UNREPORTABLE_ATTRIBUTE(0X8C), + INVALID_DATATYPE(0X8D), + DEPRECATED8E(0X8E), + UNSUPPORTED_READ(0X8F), + DEPRECATED90(0X90), + DEPRECATED91(0X91), + DATA_VERSION_MISMATCH(0X92), + DEPRECATED93(0X93), + TIMEOUT(0X94), + RESERVED95(0X95), + RESERVED96(0X96), + RESERVED97(0X97), + RESERVED98(0X98), + RESERVED99(0X99), + RESERVED9A(0X9A), + BUSY(0X9C), + DEPRECATEDC0(0XC0), + DEPRECATEDC1(0XC1), + DEPRECATEDC2(0XC2), + UNSUPPORTED_CLUSTER(0XC3), + DEPRECATEDC4(0XC4), + NO_UPSTREAM_SUBSRICPTION(0XC5), + NEEDS_TIMED_INTERACTION(0XC6), + UNSUPPORTED_EVENT(0XC7), + PATH_EXHAUSTED(0XC8), + TIMED_REQUEST_MISMATCH(0XC9), + FAILSAFE_REQUIRED(0XCA), + INVALID_IN_STATE(0XCB), + NO_COMMAND_RESPONSE(0XCC), + WRITE_IGNORED(0XF0) + } + + fun getCode(): Code? { + for (code in Code.values()) { + if (code.id == status) { + return code + } + } + return null + } + + override fun toString(): String = "$status/$clusterStatus/" +} diff --git a/src/controller/python/chip/interaction_model/__init__.py b/src/controller/python/chip/interaction_model/__init__.py index 61faa7f7d5d741..ec100846b085a5 100644 --- a/src/controller/python/chip/interaction_model/__init__.py +++ b/src/controller/python/chip/interaction_model/__init__.py @@ -86,6 +86,7 @@ class Status(enum.IntEnum): FailsafeRequired = 0xca InvalidInState = 0xcb NoCommandResponse = 0xcc + WriteIgnored = 0xf0 class InteractionModelError(ChipStackException): diff --git a/src/protocols/interaction_model/StatusCodeList.h b/src/protocols/interaction_model/StatusCodeList.h index 3b79e4a698b7b5..5538478d76ce52 100644 --- a/src/protocols/interaction_model/StatusCodeList.h +++ b/src/protocols/interaction_model/StatusCodeList.h @@ -22,7 +22,10 @@ * include this file, then undefine the macro. */ -/// WARNING: If you touch this list, please also update src/controller/python/chip/interaction_model/__init__.py +/// WARNING: If you touch this list, +/// please update src/controller/python/chip/interaction_model/__init__.py +/// please update src/controller/java/src/chip/devicecontroller/model/Status.java +/// please update src/controller/java/src/matter/controller/model/Status.kt // clang-format off CHIP_IM_STATUS_CODE(Success , SUCCESS , 0x0) From c4688b86cdb9345e4c4f12f8086b08ee237de555 Mon Sep 17 00:00:00 2001 From: yunhanw-google Date: Sun, 18 Feb 2024 20:03:58 -0800 Subject: [PATCH 018/385] [Android]rename MatterController-JNI.cpp to MatterInteractionClient-JNI.cpp (#32161) --- src/controller/java/BUILD.gn | 2 +- ...MatterController-JNI.cpp => MatterInteractionClient-JNI.cpp} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename src/controller/java/{MatterController-JNI.cpp => MatterInteractionClient-JNI.cpp} (100%) diff --git a/src/controller/java/BUILD.gn b/src/controller/java/BUILD.gn index bf41b962b4cc3d..678a03a6bf63bc 100644 --- a/src/controller/java/BUILD.gn +++ b/src/controller/java/BUILD.gn @@ -67,7 +67,7 @@ shared_library("jni") { "DeviceAttestationDelegateBridge.h", "GroupDeviceProxy.h", "MatterCallbacks-JNI.cpp", - "MatterController-JNI.cpp", + "MatterInteractionClient-JNI.cpp", ] deps = [ diff --git a/src/controller/java/MatterController-JNI.cpp b/src/controller/java/MatterInteractionClient-JNI.cpp similarity index 100% rename from src/controller/java/MatterController-JNI.cpp rename to src/controller/java/MatterInteractionClient-JNI.cpp From 11ea4316f3e5a60f8d34fcad8deeb154803498a8 Mon Sep 17 00:00:00 2001 From: Kamil Kasperczyk <66371704+kkasperczyk-no@users.noreply.github.com> Date: Mon, 19 Feb 2024 09:11:59 +0100 Subject: [PATCH 019/385] [nrfconnect] Added port for lit-icd-app example. (#32196) Implemented nrfconnect port for the lit-icd-app example. --- examples/lit-icd-app/nrfconnect/.gitignore | 1 + .../lit-icd-app/nrfconnect/CMakeLists.txt | 66 +++ examples/lit-icd-app/nrfconnect/Kconfig | 41 ++ examples/lit-icd-app/nrfconnect/README.md | 401 ++++++++++++++ .../boards/nrf52840dk_nrf52840.overlay | 54 ++ .../boards/nrf5340dk_nrf5340_cpuapp.overlay | 45 ++ .../boards/nrf52840dk_nrf52840.overlay | 21 + .../nrf52840dk_nrf52840_release.overlay | 21 + .../boards/nrf5340dk_nrf5340_cpuapp.overlay | 20 + .../nrf5340dk_nrf5340_cpuapp_release.overlay | 21 + .../nrfconnect/child_image/mcuboot/prj.conf | 30 ++ .../child_image/mcuboot/prj_release.conf | 30 ++ .../child_image/multiprotocol_rpmsg/prj.conf | 25 + .../multiprotocol_rpmsg/prj_no_dfu.conf | 25 + .../multiprotocol_rpmsg/prj_release.conf | 25 + .../nrf52840dk_nrf52840/pm_static_dfu.yml | 42 ++ .../pm_static_dfu.yml | 56 ++ .../lit-icd-app/nrfconnect/main/AppTask.cpp | 502 ++++++++++++++++++ .../nrfconnect/main/include/AppConfig.h | 33 ++ .../nrfconnect/main/include/AppEvent.h | 72 +++ .../nrfconnect/main/include/AppTask.h | 74 +++ .../main/include/CHIPProjectConfig.h | 28 + examples/lit-icd-app/nrfconnect/main/main.cpp | 33 ++ examples/lit-icd-app/nrfconnect/prj.conf | 46 ++ .../lit-icd-app/nrfconnect/prj_no_dfu.conf | 48 ++ .../lit-icd-app/nrfconnect/prj_release.conf | 60 +++ .../nrfconnect/third_party/connectedhomeip | 1 + 27 files changed, 1821 insertions(+) create mode 100644 examples/lit-icd-app/nrfconnect/.gitignore create mode 100644 examples/lit-icd-app/nrfconnect/CMakeLists.txt create mode 100644 examples/lit-icd-app/nrfconnect/Kconfig create mode 100644 examples/lit-icd-app/nrfconnect/README.md create mode 100644 examples/lit-icd-app/nrfconnect/boards/nrf52840dk_nrf52840.overlay create mode 100644 examples/lit-icd-app/nrfconnect/boards/nrf5340dk_nrf5340_cpuapp.overlay create mode 100644 examples/lit-icd-app/nrfconnect/child_image/mcuboot/boards/nrf52840dk_nrf52840.overlay create mode 100644 examples/lit-icd-app/nrfconnect/child_image/mcuboot/boards/nrf52840dk_nrf52840_release.overlay create mode 100644 examples/lit-icd-app/nrfconnect/child_image/mcuboot/boards/nrf5340dk_nrf5340_cpuapp.overlay create mode 100644 examples/lit-icd-app/nrfconnect/child_image/mcuboot/boards/nrf5340dk_nrf5340_cpuapp_release.overlay create mode 100644 examples/lit-icd-app/nrfconnect/child_image/mcuboot/prj.conf create mode 100644 examples/lit-icd-app/nrfconnect/child_image/mcuboot/prj_release.conf create mode 100644 examples/lit-icd-app/nrfconnect/child_image/multiprotocol_rpmsg/prj.conf create mode 100644 examples/lit-icd-app/nrfconnect/child_image/multiprotocol_rpmsg/prj_no_dfu.conf create mode 100644 examples/lit-icd-app/nrfconnect/child_image/multiprotocol_rpmsg/prj_release.conf create mode 100644 examples/lit-icd-app/nrfconnect/configuration/nrf52840dk_nrf52840/pm_static_dfu.yml create mode 100644 examples/lit-icd-app/nrfconnect/configuration/nrf5340dk_nrf5340_cpuapp/pm_static_dfu.yml create mode 100644 examples/lit-icd-app/nrfconnect/main/AppTask.cpp create mode 100644 examples/lit-icd-app/nrfconnect/main/include/AppConfig.h create mode 100644 examples/lit-icd-app/nrfconnect/main/include/AppEvent.h create mode 100644 examples/lit-icd-app/nrfconnect/main/include/AppTask.h create mode 100644 examples/lit-icd-app/nrfconnect/main/include/CHIPProjectConfig.h create mode 100644 examples/lit-icd-app/nrfconnect/main/main.cpp create mode 100644 examples/lit-icd-app/nrfconnect/prj.conf create mode 100644 examples/lit-icd-app/nrfconnect/prj_no_dfu.conf create mode 100644 examples/lit-icd-app/nrfconnect/prj_release.conf create mode 120000 examples/lit-icd-app/nrfconnect/third_party/connectedhomeip diff --git a/examples/lit-icd-app/nrfconnect/.gitignore b/examples/lit-icd-app/nrfconnect/.gitignore new file mode 100644 index 00000000000000..84c048a73cc2e5 --- /dev/null +++ b/examples/lit-icd-app/nrfconnect/.gitignore @@ -0,0 +1 @@ +/build/ diff --git a/examples/lit-icd-app/nrfconnect/CMakeLists.txt b/examples/lit-icd-app/nrfconnect/CMakeLists.txt new file mode 100644 index 00000000000000..a9b921016670e7 --- /dev/null +++ b/examples/lit-icd-app/nrfconnect/CMakeLists.txt @@ -0,0 +1,66 @@ +# +# Copyright (c) 2024 Project CHIP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +cmake_minimum_required(VERSION 3.13.1) + +get_filename_component(CHIP_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/third_party/connectedhomeip REALPATH) +get_filename_component(NRFCONNECT_COMMON ${CHIP_ROOT}/examples/platform/nrfconnect REALPATH) +get_filename_component(GEN_DIR ${CHIP_ROOT}/zzz_generated/ REALPATH) + +include(${CHIP_ROOT}/config/nrfconnect/app/check-nrfconnect-version.cmake) + +# Set Kconfig root files that will be processed as a first Kconfig for used child images. +set(mcuboot_KCONFIG_ROOT ${CHIP_ROOT}/config/nrfconnect/chip-module/Kconfig.mcuboot.root) +set(multiprotocol_rpmsg_KCONFIG_ROOT ${CHIP_ROOT}/config/nrfconnect/chip-module/Kconfig.multiprotocol_rpmsg.root) + +if(NOT CONF_FILE STREQUAL "prj_no_dfu.conf") + set(PM_STATIC_YML_FILE ${CMAKE_CURRENT_SOURCE_DIR}/configuration/${BOARD}/pm_static_dfu.yml) +endif() + +list(APPEND ZEPHYR_EXTRA_MODULES ${CHIP_ROOT}/config/nrfconnect/chip-module) +find_package(Zephyr HINTS $ENV{ZEPHYR_BASE}) + +# -Wmaybe-uninitialized has too many false positives, including on std::optional +# and chip::Optional. Make it nonfatal. +# +# See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80635 +target_compile_options(app PRIVATE -Werror -Wno-error=maybe-uninitialized) + +project(chip-nrfconnect-lit-icd-app-example) + +include(${CHIP_ROOT}/config/nrfconnect/app/enable-gnu-std.cmake) +include(${CHIP_ROOT}/config/nrfconnect/app/flashing.cmake) +include(${CHIP_ROOT}/src/app/chip_data_model.cmake) + +target_include_directories(app PRIVATE + main/include + ${GEN_DIR}/app-common + ${GEN_DIR}/lit-icd-app + ${NRFCONNECT_COMMON}/util/include + ${NRFCONNECT_COMMON}/app/include) + +target_sources(app PRIVATE + main/AppTask.cpp + main/main.cpp + ${NRFCONNECT_COMMON}/util/LEDWidget.cpp) + +chip_configure_data_model(app + INCLUDE_SERVER + ZAP_FILE ${CMAKE_CURRENT_SOURCE_DIR}/../lit-icd-common/lit-icd-server-app.zap +) + +if(CONFIG_CHIP_OTA_REQUESTOR) + target_sources(app PRIVATE ${NRFCONNECT_COMMON}/util/OTAUtil.cpp) +endif() diff --git a/examples/lit-icd-app/nrfconnect/Kconfig b/examples/lit-icd-app/nrfconnect/Kconfig new file mode 100644 index 00000000000000..4d9501ac5cab90 --- /dev/null +++ b/examples/lit-icd-app/nrfconnect/Kconfig @@ -0,0 +1,41 @@ +# +# Copyright (c) 2024 Project CHIP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +mainmenu "Matter nRF Connect LIT ICD Example Application" + +config STATE_LEDS + bool "Use LEDs to indicate the device state" + default y + help + Use LEDs to render the current state of the device such as the progress of commissioning of + the device into a network or the factory reset initiation. Note that setting this option to + 'n' does not disable the LED indicating the state of the simulated bolt. + +# Sample configuration used for Thread networking +if NET_L2_OPENTHREAD + +choice OPENTHREAD_NORDIC_LIBRARY_CONFIGURATION + default OPENTHREAD_NORDIC_LIBRARY_MTD +endchoice + +choice OPENTHREAD_DEVICE_TYPE + default OPENTHREAD_MTD +endchoice + +endif # NET_L2_OPENTHREAD + +rsource "../../../config/nrfconnect/chip-module/Kconfig.features" +rsource "../../../config/nrfconnect/chip-module/Kconfig.defaults" +source "Kconfig.zephyr" diff --git a/examples/lit-icd-app/nrfconnect/README.md b/examples/lit-icd-app/nrfconnect/README.md new file mode 100644 index 00000000000000..704950fdcac63e --- /dev/null +++ b/examples/lit-icd-app/nrfconnect/README.md @@ -0,0 +1,401 @@ +# Matter nRF Connect LIT ICD Example Application + +The nRF Connect LIT ICD Example allows to test the device that utilizes Long +Idle Time feature from the Intermittently Connected Device Management cluster. +It uses buttons to change the device states and LEDs to show the state of these +changes. You can use this example as a reference for creating your own +application. + +Nordic Semiconductor logo +nRF52840 DK + +The example is based on +[Matter](https://github.com/project-chip/connectedhomeip) and Nordic +Semiconductor's nRF Connect SDK, and was created to facilitate testing and +certification of a Matter device communicating over a low-power, 802.15.4 Thread +network. + +The example behaves as a Matter accessory, that is a device that can be paired +into an existing Matter network and can be controlled by this network. + +
+ +## Overview + +This example is running on the nRF Connect platform, which is based on Nordic +Semiconductor's +[nRF Connect SDK](https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/index.html) +and [Zephyr RTOS](https://zephyrproject.org/). Visit Matter's +[nRF Connect platform overview](../../../docs/guides/nrfconnect_platform_overview.md) +to read more about the platform structure and dependencies. + +By default, the Matter accessory device has IPv6 networking disabled. You must +pair it with the Matter controller over Bluetooth® LE to get the configuration +from the controller to use the device within a Thread network. You have to make +the device discoverable manually (for security reasons). See +[Bluetooth LE advertising](#bluetooth-le-advertising) to learn how to do this. +The controller must get the commissioning information from the Matter accessory +device and provision the device into the network. + +The sample uses buttons for changing the device states, and LEDs to show the +state of these changes. + +### Bluetooth LE advertising + +In this example, to commission the device onto a Matter network, it must be +discoverable over Bluetooth LE. For security reasons, you must start Bluetooth +LE advertising manually after powering up the device by pressing **Button 4**. + +### Bluetooth LE rendezvous + +In this example, the commissioning procedure is done over Bluetooth LE between a +Matter device and the Matter controller, where the controller has the +commissioner role. + +To start the rendezvous, the controller must get the commissioning information +from the Matter device. The data payload is encoded within a QR code, printed to +the UART console, and shared using an NFC tag. The emulation of the NFC tag +emulation starts automatically when Bluetooth LE advertising is started and +stays enabled until Bluetooth LE advertising timeout expires. + +#### Thread provisioning + +The provisioning operation, which is the Last part of the rendezvous procedure, +involves sending the Thread network credentials from the Matter controller to +the Matter device. As a result, the device joins the Thread network and can +communicate with other devices in the network. + +### Device Firmware Upgrade + +The example supports over-the-air (OTA) device firmware upgrade (DFU) using +Matter OTA mechanism, which is enabled by default. + +The +[MCUboot](https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/mcuboot/index.html) +bootloader solution is used to replace the old firmware image with the new one. + +#### Matter Over-the-Air Update + +The Matter over-the-air update distinguishes two types of nodes: OTA Provider +and OTA Requestor. + +An OTA Provider is a node that hosts a new firmware image and is able to respond +on an OTA Requestor's queries regarding availability of new firmware images or +requests to start sending the update packages. + +An OTA Requestor is a node that wants to download a new firmware image and sends +requests to an OTA Provider to start the update process. + +#### Bootloader + +MCUboot is a secure bootloader used for swapping firmware images of different +versions and generating proper build output files that can be used in the device +firmware upgrade process. + +The bootloader solution requires an area of flash memory to swap application +images during the firmware upgrade. Nordic Semiconductor devices use an external +memory chip for this purpose. The memory chip communicates with the +microcontroller through the QSPI bus. + +See the +[Building with Device Firmware Upgrade support](#building-with-device-firmware-upgrade-support) +section to learn how to change MCUboot and flash configuration in this example. + +
+ +## Requirements + +The application requires a specific revision of the nRF Connect SDK to work +correctly. See [Setting up the environment](#setting-up-the-environment) for +more information. + +### Supported devices + +The example supports building and running on the following devices: + +| Hardware platform | Build target | Platform image | +| ----------------------------------------------------------------------------------------- | -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ | +| [nRF52840 DK](https://www.nordicsemi.com/Software-and-Tools/Development-Kits/nRF52840-DK) | `nrf52840dk_nrf52840` |
nRF52840 DKnRF52840 DK
| +| [nRF5340 DK](https://www.nordicsemi.com/Software-and-Tools/Development-Kits/nRF5340-DK) | `nrf5340dk_nrf5340_cpuapp` |
nRF5340 DKnRF5340 DK
| + +
+ +## Device UI + +This section lists the User Interface elements that you can use to control and +monitor the state of the device. These correspond to PCB components on the +platform image. + +**LED 1** shows the overall state of the device and its connectivity. The +following states are possible: + +- _Short Flash On (50 ms on/950 ms off)_ — The device is in the + unprovisioned (unpaired) state and is waiting for a commissioning + application to connect. + +- _Rapid Even Flashing (100 ms on/100 ms off)_ — The device is in the + unprovisioned state and a commissioning application is connected through + Bluetooth LE. + +- _Short Flash Off (950ms on/50ms off)_ — The device is fully + provisioned, but does not yet have full connectivity for Thread network. + +- _Solid On_ — The device is fully provisioned. + +**LED 2** is used for the Identify feature purpose. The LED starts blinking +evenly (500 ms on/500 ms off) when the Identify command of the Identify cluster +is received on the endpoint 1. The command’s argument can be used to specify the +duration of the effect. + +**Button 1** Pressing the button for more than 3 s initiates the factory reset +of the device. Releasing the button within the 3-second window cancels the +factory reset procedure. + +**Button 3** Represents the User Active Mode Trigger feature from the +Intermittently Connected Devices Management cluster. Pressing it puts the ICD +device in the active mode and makes it responsive. + +**Button 4** Starts the NFC tag emulation, enables Bluetooth LE advertising for +the predefined period of time (15 minutes by default), and makes the device +discoverable over Bluetooth LE. This button is used during the commissioning +procedure. + +**SEGGER J-Link USB port** can be used to get logs from the device or +communicate with it using the +[command line interface](../../../docs/guides/nrfconnect_examples_cli.md). + +**NFC port with antenna attached** can be used to start the +[rendezvous](#bluetooth-le-rendezvous) by providing the commissioning +information from the Matter device in a data payload that can be shared using +NFC. + +
+ +## Setting up the environment + +Before building the example, check out the Matter repository and sync submodules +using the following command: + + $ python3 scripts/checkout_submodules.py --shallow --platform nrfconnect + +> **Note**: +> +> For Linux operating system install +> [SEGGER J-Link Software](https://www.segger.com/downloads/jlink/#J-LinkSoftwareAndDocumentationPack). + +### Install Command Line Tools + +With admin permissions enabled, download and install the +[nRF Command Line Tools](https://www.nordicsemi.com/Products/Development-tools/nrf-command-line-tools). + +### Install Toolchain Manager + +Toolchain Manager is available from +[nRF Connect for Desktop](https://www.nordicsemi.com/Products/Development-tools/nrf-connect-for-desktop), +a cross-platform tool that provides different applications that simplify +installing the nRF Connect SDK. Both the tool and the application are available +for Windows, Linux, and macOS. + +To install the Toolchain Manager app, complete the following steps: + +1. [Download nRF Connect for Desktop](https://www.nordicsemi.com/Products/Development-tools/nrf-connect-for-desktop/download#infotabs) + for your operating system. + +2. Install and run the tool on your machine. + +3. In the **APPS** section, click **Install** button on the Toolchain Manager + tab. + +### Install nRF Connect SDK + +Complete the following steps to install the nRF Connect SDK: + +1. Open Toolchain Manager in nRF Connect for Desktop. + +2. Click the **Install** button next to the + [recommended](../../../config/nrfconnect/.nrfconnect-recommended-revision) + version of the nRF Connect SDK. + +3. A pop-up window will inform you about the current installation directory. If + you want to change the directory, click the **Change directory** button. + Otherwise, click the **Continue installation** button. + +4. When the nRF Connect SDK is installed on your machine, the **Install** + button changes to the **Open VS Code** button. + +5. Click the dropdown menu next to the **Open VS Code** button for the + installed nRF Connect SDK version, and select **Open terminal**. + +6. Make sure that the nRF Connect SDK version is compatible with the Matter SDK + version: + + ``` + $ cd {connectedhomeip directory} + $ python3 scripts/setup/nrfconnect/update_ncs.py --update + ``` + +Now you can proceed with the [Building](#building) instruction. + +
+ +## Building + +Complete the following steps to build the sample: + +1. Navigate to the example's directory: + + $ cd examples/lit-icd-app/nrfconnect + +2. Run the following command to build the example, with _build-target_ replaced + with the build target name of the Nordic Semiconductor's kit you own, for + example `nrf52840dk_nrf52840`: + + $ west build -b build-target + + You only need to specify the build target on the first build. See + [Requirements](#requirements) for the build target names of compatible kits. + +The output `zephyr.hex` file will be available in the `build/zephyr/` directory. + +### Removing build artifacts + +If you're planning to build the example for a different kit or make changes to +the configuration, remove all build artifacts before building. To do so, use the +following command: + + $ rm -r build + +### Building with release configuration + +To build the example with release configuration that disables the diagnostic +features like logs and command-line interface, run the following command: + + $ west build -b build-target -- -DCONF_FILE=prj_release.conf + +Remember to replace _build-target_ with the build target name of the Nordic +Semiconductor's kit you own. + +### Building with Device Firmware Upgrade support + +Support for DFU using Matter OTA is enabled by default. + +To completely disable support for DFU, run the following command with +_build-target_ replaced with the build target name of the Nordic Semiconductor +kit you are using (for example `nrf52840dk_nrf52840`): + + $ west build -b build-target -- -DCONF_FILE=prj_no_dfu.conf + +> **Note**: +> +> There are two types of Device Firmware Upgrade modes: single-image DFU and +> multi-image DFU. Single-image mode supports upgrading only one firmware image, +> the application image, and should be used for single-core nRF52840 DK devices. +> Multi-image mode allows to upgrade more firmware images and is suitable for +> upgrading the application core and network core firmware in two-core nRF5340 +> DK devices. + +#### Changing bootloader configuration + +To change the default MCUboot configuration, edit the `prj.conf` file located in +the `child_image/mcuboot` directory. + +Make sure to keep the configuration consistent with changes made to the +application configuration. This is necessary for the configuration to work, as +the bootloader image is a separate application from the user application and it +has its own configuration file. + +#### Changing flash memory settings + +In the default configuration, the MCUboot uses the +[Partition Manager](https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/scripts/partition_manager/partition_manager.html#partition-manager) +to configure flash partitions used for the bootloader application image slot +purposes. You can change these settings by defining +[static partitions](https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/scripts/partition_manager/partition_manager.html#ug-pm-static). +This example uses this option to define using an external flash. + +To modify the flash settings of your board (that is, your _build-target_, for +example `nrf52840dk_nrf52840`), edit the `pm_static_dfu.yml` file located in the +`configuration/build-target/` directory. + +
+ +## Configuring the example + +The Zephyr ecosystem is based on Kconfig files and the settings can be modified +using the menuconfig utility. + +To open the menuconfig utility, run the following command from the example +directory: + + $ west build -b build-target -t menuconfig + +Remember to replace _build-target_ with the build target name of the Nordic +Semiconductor's kit you own. + +Changes done with menuconfig will be lost if the `build` directory is deleted. +To make them persistent, save the configuration options in the `prj.conf` file. + +### Example build types + +The example uses different configuration files depending on the supported +features. Configuration files are provided for different build types and they +are located in the application root directory. + +The `prj.conf` file represents a debug build type. Other build types are covered +by dedicated files with the build type added as a suffix to the prj part, as per +the following list. For example, the release build type file name is +`prj_release.conf`. If a board has other configuration files, for example +associated with partition layout or child image configuration, these follow the +same pattern. + +Before you start testing the application, you can select one of the build types +supported by the sample. This sample supports the following build types, +depending on the selected board: + +- debug -- Debug version of the application - can be used to enable additional + features for verifying the application behavior, such as logs or + command-line shell. +- release -- Release version of the application - can be used to enable only + the necessary application functionalities to optimize its performance. +- no_dfu -- Debug version of the application without Device Firmware Upgrade + feature support. + +For more information, see the +[Configuring nRF Connect SDK examples](../../../docs/guides/nrfconnect_examples_configuration.md) +page. + +
+ +## Flashing and debugging + +To flash the application to the device, use the west tool and run the following +command from the example directory: + + $ west flash --erase + +If you have multiple development kits connected, west will prompt you to pick +the correct one. + +To debug the application on target, run the following command from the example +directory: + + $ west debug + +
+ +## Testing the example + +Check the [CLI tutorial](../../../docs/guides/nrfconnect_examples_cli.md) to +learn how to use command-line interface of the application. + +### Testing using Linux CHIPTool + +Read the [CHIP Tool user guide](../../../docs/guides/chip_tool_guide.md) to see +how to use [CHIP Tool for Linux or mac OS](../../chip-tool/README.md) to +commission and control the application within a Matter-enabled Thread network. + +### Testing Device Firmware Upgrade + +Read the +[DFU tutorial](../../../docs/guides/nrfconnect_examples_software_update.md) to +see how to upgrade your device firmware. diff --git a/examples/lit-icd-app/nrfconnect/boards/nrf52840dk_nrf52840.overlay b/examples/lit-icd-app/nrfconnect/boards/nrf52840dk_nrf52840.overlay new file mode 100644 index 00000000000000..7babe0424821ba --- /dev/null +++ b/examples/lit-icd-app/nrfconnect/boards/nrf52840dk_nrf52840.overlay @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2024 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/ { + chosen { + nordic,pm-ext-flash = &mx25r64; + }; + + /* + * In some default configurations within the nRF Connect SDK, + * e.g. on nRF52840, the chosen zephyr,entropy node is &cryptocell. + * This devicetree overlay ensures that default is overridden wherever it + * is set, as this application uses the RNG node for entropy exclusively. + */ + chosen { + zephyr,entropy = &rng; + }; +}; + +/* Disable unused peripherals to reduce power consumption */ +&adc { + status = "disabled"; +}; +&uart1 { + status = "disabled"; +}; +&i2c0 { + status = "disabled"; +}; +&pwm0 { + status = "disabled"; +}; +&spi1 { + status = "disabled"; +}; +&spi3 { + status = "disabled"; +}; +&usbd { + status = "disabled"; +}; diff --git a/examples/lit-icd-app/nrfconnect/boards/nrf5340dk_nrf5340_cpuapp.overlay b/examples/lit-icd-app/nrfconnect/boards/nrf5340dk_nrf5340_cpuapp.overlay new file mode 100644 index 00000000000000..12155ffcd1f509 --- /dev/null +++ b/examples/lit-icd-app/nrfconnect/boards/nrf5340dk_nrf5340_cpuapp.overlay @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2024 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +/ { + chosen { + nordic,pm-ext-flash = &mx25r64; + }; +}; + +/* Set IPC thread priority to the highest value to not collide with other threads. */ +&ipc0 { + zephyr,priority = <0 PRIO_COOP>; +}; + +/* Disable unused peripherals to reduce power consumption */ +&adc { + status = "disabled"; +}; +&i2c1 { + status = "disabled"; +}; +&pwm0 { + status = "disabled"; +}; +&spi2 { + status = "disabled"; +}; +&usbd { + status = "disabled"; +}; diff --git a/examples/lit-icd-app/nrfconnect/child_image/mcuboot/boards/nrf52840dk_nrf52840.overlay b/examples/lit-icd-app/nrfconnect/child_image/mcuboot/boards/nrf52840dk_nrf52840.overlay new file mode 100644 index 00000000000000..9f9128c6beff60 --- /dev/null +++ b/examples/lit-icd-app/nrfconnect/child_image/mcuboot/boards/nrf52840dk_nrf52840.overlay @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2024 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/ { + chosen { + nordic,pm-ext-flash = &mx25r64; + }; +}; diff --git a/examples/lit-icd-app/nrfconnect/child_image/mcuboot/boards/nrf52840dk_nrf52840_release.overlay b/examples/lit-icd-app/nrfconnect/child_image/mcuboot/boards/nrf52840dk_nrf52840_release.overlay new file mode 100644 index 00000000000000..9f9128c6beff60 --- /dev/null +++ b/examples/lit-icd-app/nrfconnect/child_image/mcuboot/boards/nrf52840dk_nrf52840_release.overlay @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2024 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/ { + chosen { + nordic,pm-ext-flash = &mx25r64; + }; +}; diff --git a/examples/lit-icd-app/nrfconnect/child_image/mcuboot/boards/nrf5340dk_nrf5340_cpuapp.overlay b/examples/lit-icd-app/nrfconnect/child_image/mcuboot/boards/nrf5340dk_nrf5340_cpuapp.overlay new file mode 100644 index 00000000000000..50069180506973 --- /dev/null +++ b/examples/lit-icd-app/nrfconnect/child_image/mcuboot/boards/nrf5340dk_nrf5340_cpuapp.overlay @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2024 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/ { + chosen { + nordic,pm-ext-flash = &mx25r64; + }; +}; diff --git a/examples/lit-icd-app/nrfconnect/child_image/mcuboot/boards/nrf5340dk_nrf5340_cpuapp_release.overlay b/examples/lit-icd-app/nrfconnect/child_image/mcuboot/boards/nrf5340dk_nrf5340_cpuapp_release.overlay new file mode 100644 index 00000000000000..9f9128c6beff60 --- /dev/null +++ b/examples/lit-icd-app/nrfconnect/child_image/mcuboot/boards/nrf5340dk_nrf5340_cpuapp_release.overlay @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2024 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/ { + chosen { + nordic,pm-ext-flash = &mx25r64; + }; +}; diff --git a/examples/lit-icd-app/nrfconnect/child_image/mcuboot/prj.conf b/examples/lit-icd-app/nrfconnect/child_image/mcuboot/prj.conf new file mode 100644 index 00000000000000..3f43b733b4bb96 --- /dev/null +++ b/examples/lit-icd-app/nrfconnect/child_image/mcuboot/prj.conf @@ -0,0 +1,30 @@ +# +# Copyright (c) 2024 Project CHIP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# This target uses Kconfig.mcuboot.defaults to set options common for all +# samples using mcuboot. This file should contain only options specific for this sample +# mcuboot configuration or overrides of default values. + +CONFIG_MBEDTLS_CFG_FILE="mcuboot-mbedtls-cfg.h" + +# Bootloader size optimization +# Disable not used modules that cannot be set in Kconfig.mcuboot.defaults due to overriding +# in board files. +CONFIG_CONSOLE=n +CONFIG_SERIAL=n +CONFIG_UART_CONSOLE=n +CONFIG_USE_SEGGER_RTT=n +CONFIG_GPIO=n diff --git a/examples/lit-icd-app/nrfconnect/child_image/mcuboot/prj_release.conf b/examples/lit-icd-app/nrfconnect/child_image/mcuboot/prj_release.conf new file mode 100644 index 00000000000000..3f43b733b4bb96 --- /dev/null +++ b/examples/lit-icd-app/nrfconnect/child_image/mcuboot/prj_release.conf @@ -0,0 +1,30 @@ +# +# Copyright (c) 2024 Project CHIP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# This target uses Kconfig.mcuboot.defaults to set options common for all +# samples using mcuboot. This file should contain only options specific for this sample +# mcuboot configuration or overrides of default values. + +CONFIG_MBEDTLS_CFG_FILE="mcuboot-mbedtls-cfg.h" + +# Bootloader size optimization +# Disable not used modules that cannot be set in Kconfig.mcuboot.defaults due to overriding +# in board files. +CONFIG_CONSOLE=n +CONFIG_SERIAL=n +CONFIG_UART_CONSOLE=n +CONFIG_USE_SEGGER_RTT=n +CONFIG_GPIO=n diff --git a/examples/lit-icd-app/nrfconnect/child_image/multiprotocol_rpmsg/prj.conf b/examples/lit-icd-app/nrfconnect/child_image/multiprotocol_rpmsg/prj.conf new file mode 100644 index 00000000000000..48deaa9fa18135 --- /dev/null +++ b/examples/lit-icd-app/nrfconnect/child_image/multiprotocol_rpmsg/prj.conf @@ -0,0 +1,25 @@ +# +# Copyright (c) 2024 Project CHIP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# This target uses Kconfig.multiprotocol_rpmsg.defaults to set options common for all +# samples using multiprotocol_rpmsg. This file should contain only options specific for this sample +# multiprotocol_rpmsg configuration or overrides of default values. + +# Disable not used modules that cannot be set in Kconfig.multiprotocol_rpmsg.defaults due to overriding +# in board files. + +CONFIG_SERIAL=n +CONFIG_UART_CONSOLE=n diff --git a/examples/lit-icd-app/nrfconnect/child_image/multiprotocol_rpmsg/prj_no_dfu.conf b/examples/lit-icd-app/nrfconnect/child_image/multiprotocol_rpmsg/prj_no_dfu.conf new file mode 100644 index 00000000000000..48deaa9fa18135 --- /dev/null +++ b/examples/lit-icd-app/nrfconnect/child_image/multiprotocol_rpmsg/prj_no_dfu.conf @@ -0,0 +1,25 @@ +# +# Copyright (c) 2024 Project CHIP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# This target uses Kconfig.multiprotocol_rpmsg.defaults to set options common for all +# samples using multiprotocol_rpmsg. This file should contain only options specific for this sample +# multiprotocol_rpmsg configuration or overrides of default values. + +# Disable not used modules that cannot be set in Kconfig.multiprotocol_rpmsg.defaults due to overriding +# in board files. + +CONFIG_SERIAL=n +CONFIG_UART_CONSOLE=n diff --git a/examples/lit-icd-app/nrfconnect/child_image/multiprotocol_rpmsg/prj_release.conf b/examples/lit-icd-app/nrfconnect/child_image/multiprotocol_rpmsg/prj_release.conf new file mode 100644 index 00000000000000..48deaa9fa18135 --- /dev/null +++ b/examples/lit-icd-app/nrfconnect/child_image/multiprotocol_rpmsg/prj_release.conf @@ -0,0 +1,25 @@ +# +# Copyright (c) 2024 Project CHIP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# This target uses Kconfig.multiprotocol_rpmsg.defaults to set options common for all +# samples using multiprotocol_rpmsg. This file should contain only options specific for this sample +# multiprotocol_rpmsg configuration or overrides of default values. + +# Disable not used modules that cannot be set in Kconfig.multiprotocol_rpmsg.defaults due to overriding +# in board files. + +CONFIG_SERIAL=n +CONFIG_UART_CONSOLE=n diff --git a/examples/lit-icd-app/nrfconnect/configuration/nrf52840dk_nrf52840/pm_static_dfu.yml b/examples/lit-icd-app/nrfconnect/configuration/nrf52840dk_nrf52840/pm_static_dfu.yml new file mode 100644 index 00000000000000..ce42b39e55ee87 --- /dev/null +++ b/examples/lit-icd-app/nrfconnect/configuration/nrf52840dk_nrf52840/pm_static_dfu.yml @@ -0,0 +1,42 @@ +mcuboot: + address: 0x0 + size: 0x7000 + region: flash_primary +mcuboot_pad: + address: 0x7000 + size: 0x200 +app: + address: 0x7200 + size: 0xf3e00 +mcuboot_primary: + orig_span: &id001 + - mcuboot_pad + - app + span: *id001 + address: 0x7000 + size: 0xf4000 + region: flash_primary +mcuboot_primary_app: + orig_span: &id002 + - app + span: *id002 + address: 0x7200 + size: 0xf3e00 +factory_data: + address: 0xfb000 + size: 0x1000 + region: flash_primary +settings_storage: + address: 0xfc000 + size: 0x4000 + region: flash_primary +mcuboot_secondary: + address: 0x0 + size: 0xf4000 + device: MX25R64 + region: external_flash +external_flash: + address: 0xf4000 + size: 0x70c000 + device: MX25R64 + region: external_flash diff --git a/examples/lit-icd-app/nrfconnect/configuration/nrf5340dk_nrf5340_cpuapp/pm_static_dfu.yml b/examples/lit-icd-app/nrfconnect/configuration/nrf5340dk_nrf5340_cpuapp/pm_static_dfu.yml new file mode 100644 index 00000000000000..10e8680c363a53 --- /dev/null +++ b/examples/lit-icd-app/nrfconnect/configuration/nrf5340dk_nrf5340_cpuapp/pm_static_dfu.yml @@ -0,0 +1,56 @@ +mcuboot: + address: 0x0 + size: 0x8000 + region: flash_primary +mcuboot_pad: + address: 0x8000 + size: 0x200 +app: + address: 0x8200 + size: 0xf2e00 +mcuboot_primary: + orig_span: &id001 + - mcuboot_pad + - app + span: *id001 + address: 0x8000 + size: 0xf3000 + region: flash_primary +mcuboot_primary_app: + orig_span: &id002 + - app + span: *id002 + address: 0x8200 + size: 0xf2e00 +factory_data: + address: 0xfb000 + size: 0x1000 + region: flash_primary +settings_storage: + address: 0xfc000 + size: 0x4000 + region: flash_primary +mcuboot_primary_1: + address: 0x0 + size: 0x40000 + device: flash_ctrl + region: ram_flash +mcuboot_secondary: + address: 0x0 + size: 0xf3000 + device: MX25R64 + region: external_flash +mcuboot_secondary_1: + address: 0xf3000 + size: 0x40000 + device: MX25R64 + region: external_flash +external_flash: + address: 0x133000 + size: 0x6CD000 + device: MX25R64 + region: external_flash +pcd_sram: + address: 0x20000000 + size: 0x2000 + region: sram_primary diff --git a/examples/lit-icd-app/nrfconnect/main/AppTask.cpp b/examples/lit-icd-app/nrfconnect/main/AppTask.cpp new file mode 100644 index 00000000000000..50622d0c88b96e --- /dev/null +++ b/examples/lit-icd-app/nrfconnect/main/AppTask.cpp @@ -0,0 +1,502 @@ +/* + * Copyright (c) 2024 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 "AppTask.h" +#include "AppConfig.h" +#include "AppEvent.h" +#include "FabricTableDelegate.h" +#include "LEDUtil.h" + +#include + +#include +#include + +#include +#include +#include +#include + +#include +#include + +#if CONFIG_CHIP_OTA_REQUESTOR +#include "OTAUtil.h" +#endif + +#include +#include +#include + +LOG_MODULE_DECLARE(app, CONFIG_CHIP_APP_LOG_LEVEL); + +using namespace ::chip; +using namespace ::chip::app; +using namespace ::chip::Credentials; +using namespace ::chip::DeviceLayer; + +namespace { +constexpr uint32_t kFactoryResetTriggerTimeout = 3000; +constexpr uint32_t kFactoryResetCancelWindowTimeout = 3000; +constexpr size_t kAppEventQueueSize = 10; +constexpr EndpointId kIdentifyEndpointId = 1; + +// NOTE! This key is for test/certification only and should not be available in production devices! +// If CONFIG_CHIP_FACTORY_DATA is enabled, this value is read from the factory data. +uint8_t sTestEventTriggerEnableKey[TestEventTriggerDelegate::kEnableKeyLength] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff }; + +K_MSGQ_DEFINE(sAppEventQueue, sizeof(AppEvent), kAppEventQueueSize, alignof(AppEvent)); +k_timer sFunctionTimer; + +chip::DeviceLayer::DeviceInfoProviderImpl gExampleDeviceInfoProvider; + +Identify sIdentify = { kIdentifyEndpointId, AppTask::IdentifyStartHandler, AppTask::IdentifyStopHandler, + Clusters::Identify::IdentifyTypeEnum::kVisibleIndicator }; + +LEDWidget sStatusLED; +LEDWidget sIdentifyLED; +FactoryResetLEDsWrapper<2> sFactoryResetLEDs{ { FACTORY_RESET_SIGNAL_LED, FACTORY_RESET_SIGNAL_LED1 } }; + +bool sIsNetworkProvisioned = false; +bool sIsNetworkEnabled = false; +bool sHaveBLEConnections = false; + +} // namespace + +namespace LedConsts { +constexpr uint32_t kBlinkRate_ms{ 500 }; +constexpr uint32_t kIdentifyBlinkRate_ms{ 500 }; +namespace StatusLed { +namespace Unprovisioned { +constexpr uint32_t kOn_ms{ 100 }; +constexpr uint32_t kOff_ms{ kOn_ms }; +} // namespace Unprovisioned +namespace Provisioned { +constexpr uint32_t kOn_ms{ 50 }; +constexpr uint32_t kOff_ms{ 950 }; +} // namespace Provisioned + +} // namespace StatusLed +} // namespace LedConsts + +CHIP_ERROR AppTask::Init() +{ + // Initialize CHIP stack + LOG_INF("Init CHIP stack"); + + CHIP_ERROR err = chip::Platform::MemoryInit(); + if (err != CHIP_NO_ERROR) + { + LOG_ERR("Platform::MemoryInit() failed"); + return err; + } + + err = PlatformMgr().InitChipStack(); + if (err != CHIP_NO_ERROR) + { + LOG_ERR("PlatformMgr().InitChipStack() failed"); + return err; + } + +#if defined(CONFIG_NET_L2_OPENTHREAD) + err = ThreadStackMgr().InitThreadStack(); + if (err != CHIP_NO_ERROR) + { + LOG_ERR("ThreadStackMgr().InitThreadStack() failed"); + return err; + } + +#ifdef CONFIG_OPENTHREAD_MTD_SED + err = ConnectivityMgr().SetThreadDeviceType(ConnectivityManager::kThreadDeviceType_SleepyEndDevice); +#else + err = ConnectivityMgr().SetThreadDeviceType(ConnectivityManager::kThreadDeviceType_MinimalEndDevice); +#endif + if (err != CHIP_NO_ERROR) + { + LOG_ERR("ConnectivityMgr().SetThreadDeviceType() failed"); + return err; + } +#else + return CHIP_ERROR_INTERNAL; +#endif // CONFIG_NET_L2_OPENTHREAD + + // Initialize LEDs + LEDWidget::InitGpio(); + LEDWidget::SetStateUpdateCallback(LEDStateUpdateHandler); + + sStatusLED.Init(SYSTEM_STATE_LED); + sIdentifyLED.Init(IDENTIFY_STATE_LED); + sIdentifyLED.Set(false); + + UpdateStatusLED(); + + // Initialize buttons + auto ret = dk_buttons_init(ButtonEventHandler); + if (ret) + { + LOG_ERR("dk_buttons_init() failed"); + return chip::System::MapErrorZephyr(ret); + } + + // Initialize timer user data + k_timer_init(&sFunctionTimer, &AppTask::FunctionTimerTimeoutCallback, nullptr); + k_timer_user_data_set(&sFunctionTimer, this); + +#ifdef CONFIG_CHIP_OTA_REQUESTOR + /* OTA image confirmation must be done before the factory data init. */ + OtaConfirmNewImage(); +#endif + + // Initialize CHIP server +#if CONFIG_CHIP_FACTORY_DATA + ReturnErrorOnFailure(mFactoryDataProvider.Init()); + SetDeviceInstanceInfoProvider(&mFactoryDataProvider); + SetDeviceAttestationCredentialsProvider(&mFactoryDataProvider); + SetCommissionableDataProvider(&mFactoryDataProvider); + // Read EnableKey from the factory data. + MutableByteSpan enableKey(sTestEventTriggerEnableKey); + err = mFactoryDataProvider.GetEnableKey(enableKey); + if (err != CHIP_NO_ERROR) + { + LOG_ERR("mFactoryDataProvider.GetEnableKey() failed. Could not delegate a test event trigger"); + memset(sTestEventTriggerEnableKey, 0, sizeof(sTestEventTriggerEnableKey)); + } +#else + SetDeviceInstanceInfoProvider(&DeviceInstanceInfoProviderMgrImpl()); + SetDeviceAttestationCredentialsProvider(Examples::GetExampleDACProvider()); +#endif + + static CommonCaseDeviceServerInitParams initParams; + static SimpleTestEventTriggerDelegate sTestEventTriggerDelegate{}; + static OTATestEventTriggerHandler sOtaTestEventTriggerHandler{}; + VerifyOrDie(sTestEventTriggerDelegate.Init(ByteSpan(sTestEventTriggerEnableKey)) == CHIP_NO_ERROR); + VerifyOrDie(sTestEventTriggerDelegate.AddHandler(&sOtaTestEventTriggerHandler) == CHIP_NO_ERROR); + (void) initParams.InitializeStaticResourcesBeforeServerInit(); + initParams.testEventTriggerDelegate = &sTestEventTriggerDelegate; + ReturnErrorOnFailure(chip::Server::GetInstance().Init(initParams)); + AppFabricTableDelegate::Init(); + + gExampleDeviceInfoProvider.SetStorageDelegate(&Server::GetInstance().GetPersistentStorage()); + chip::DeviceLayer::SetDeviceInfoProvider(&gExampleDeviceInfoProvider); + ConfigurationMgr().LogDeviceConfig(); + PrintOnboardingCodes(chip::RendezvousInformationFlag(chip::RendezvousInformationFlag::kBLE)); + + // Add CHIP event handler and start CHIP thread. + // Note that all the initialization code should happen prior to this point to avoid data races + // between the main and the CHIP threads + PlatformMgr().AddEventHandler(ChipEventHandler, 0); + err = PlatformMgr().StartEventLoopTask(); + if (err != CHIP_NO_ERROR) + { + LOG_ERR("PlatformMgr().StartEventLoopTask() failed"); + } + + return err; +} + +CHIP_ERROR AppTask::StartApp() +{ + ReturnErrorOnFailure(Init()); + + AppEvent event{}; + + while (true) + { + k_msgq_get(&sAppEventQueue, &event, K_FOREVER); + DispatchEvent(event); + } + + return CHIP_NO_ERROR; +} + +void AppTask::IdentifyStartHandler(Identify *) +{ + AppEvent event; + event.Type = AppEventType::IdentifyStart; + event.Handler = [](const AppEvent &) { sIdentifyLED.Blink(LedConsts::kIdentifyBlinkRate_ms); }; + PostEvent(event); +} + +void AppTask::IdentifyStopHandler(Identify *) +{ + AppEvent event; + event.Type = AppEventType::IdentifyStop; + event.Handler = [](const AppEvent &) { sIdentifyLED.Set(false); }; + PostEvent(event); +} + +void AppTask::ButtonEventHandler(uint32_t buttonState, uint32_t hasChanged) +{ + AppEvent button_event; + button_event.Type = AppEventType::Button; + + if (BLE_ADVERTISEMENT_START_BUTTON_MASK & buttonState & hasChanged) + { + button_event.ButtonEvent.PinNo = BLE_ADVERTISEMENT_START_BUTTON; + button_event.ButtonEvent.Action = static_cast(AppEventType::ButtonPushed); + button_event.Handler = StartBLEAdvertisementHandler; + PostEvent(button_event); + } + + if (FUNCTION_BUTTON_MASK & hasChanged) + { + button_event.ButtonEvent.PinNo = FUNCTION_BUTTON; + button_event.ButtonEvent.Action = + static_cast((FUNCTION_BUTTON_MASK & buttonState) ? AppEventType::ButtonPushed : AppEventType::ButtonReleased); + button_event.Handler = FunctionHandler; + PostEvent(button_event); + } + + if (ICD_UAT_BUTTON_MASK & hasChanged) + { + button_event.ButtonEvent.PinNo = ICD_UAT_BUTTON; + button_event.ButtonEvent.Action = static_cast(AppEventType::ButtonPushed); + button_event.Handler = IcdUatEventHandler; + PostEvent(button_event); + } +} + +void AppTask::IcdUatEventHandler(const AppEvent &) +{ + Server::GetInstance().GetICDManager().UpdateOperationState(ICDManager::OperationalState::ActiveMode); +} + +void AppTask::FunctionTimerTimeoutCallback(k_timer * timer) +{ + if (!timer) + { + return; + } + + AppEvent event; + event.Type = AppEventType::Timer; + event.TimerEvent.Context = k_timer_user_data_get(timer); + event.Handler = FunctionTimerEventHandler; + PostEvent(event); +} + +void AppTask::FunctionTimerEventHandler(const AppEvent & event) +{ + if (event.Type != AppEventType::Timer || !Instance().mFunctionTimerActive) + { + return; + } + + // If we reached here, the button was held past kFactoryResetTriggerTimeout, initiate factory reset + if (Instance().mFunction == FunctionEvent::SoftwareUpdate) + { + LOG_INF("Factory Reset Triggered. Release button within %ums to cancel.", kFactoryResetTriggerTimeout); + + // Start timer for kFactoryResetCancelWindowTimeout to allow user to cancel, if required. + Instance().StartTimer(kFactoryResetCancelWindowTimeout); + Instance().mFunction = FunctionEvent::FactoryReset; + + // Turn off all LEDs before starting blink to make sure blink is coordinated. + sStatusLED.Set(false); + sFactoryResetLEDs.Set(false); + + sStatusLED.Blink(LedConsts::kBlinkRate_ms); + sFactoryResetLEDs.Blink(LedConsts::kBlinkRate_ms); + } + else if (Instance().mFunction == FunctionEvent::FactoryReset) + { + // Actually trigger Factory Reset + Instance().mFunction = FunctionEvent::NoneSelected; + chip::Server::GetInstance().ScheduleFactoryReset(); + } + else if (Instance().mFunction == FunctionEvent::AdvertisingStart) + { + // The button was held past kAdvertisingTriggerTimeout, start BLE advertisement if we have 2 buttons UI + StartBLEAdvertisementHandler(event); + } +} + +void AppTask::FunctionHandler(const AppEvent & event) +{ + if (event.ButtonEvent.PinNo != FUNCTION_BUTTON) + return; + + // To trigger software update: press the FUNCTION_BUTTON button briefly (< FACTORY_RESET_TRIGGER_TIMEOUT) + // To initiate factory reset: press the FUNCTION_BUTTON for FACTORY_RESET_TRIGGER_TIMEOUT + FACTORY_RESET_CANCEL_WINDOW_TIMEOUT + // All LEDs start blinking after FACTORY_RESET_TRIGGER_TIMEOUT to signal factory reset has been initiated. + // To cancel factory reset: release the FUNCTION_BUTTON once all LEDs start blinking within the + // FACTORY_RESET_CANCEL_WINDOW_TIMEOUT + if (event.ButtonEvent.Action == static_cast(AppEventType::ButtonPushed)) + { + if (!Instance().mFunctionTimerActive && Instance().mFunction == FunctionEvent::NoneSelected) + { + Instance().StartTimer(kFactoryResetTriggerTimeout); + + Instance().mFunction = FunctionEvent::SoftwareUpdate; + } + } + else + { + // If the button was released before factory reset got initiated, trigger a software update. + if (Instance().mFunctionTimerActive && Instance().mFunction == FunctionEvent::SoftwareUpdate) + { + Instance().CancelTimer(); + Instance().mFunction = FunctionEvent::NoneSelected; + } + else if (Instance().mFunctionTimerActive && Instance().mFunction == FunctionEvent::FactoryReset) + { + sFactoryResetLEDs.Set(false); + UpdateStatusLED(); + Instance().CancelTimer(); + Instance().mFunction = FunctionEvent::NoneSelected; + LOG_INF("Factory Reset has been Canceled"); + } + } +} + +void AppTask::StartBLEAdvertisementHandler(const AppEvent &) +{ + if (Server::GetInstance().GetFabricTable().FabricCount() != 0) + { + LOG_INF("Matter service BLE advertising not started - device is already commissioned"); + return; + } + + if (ConnectivityMgr().IsBLEAdvertisingEnabled()) + { + LOG_INF("BLE advertising is already enabled"); + return; + } + + if (Server::GetInstance().GetCommissioningWindowManager().OpenBasicCommissioningWindow() != CHIP_NO_ERROR) + { + LOG_ERR("OpenBasicCommissioningWindow() failed"); + } +} + +void AppTask::UpdateLedStateEventHandler(const AppEvent & event) +{ + if (event.Type == AppEventType::UpdateLedState) + { + event.UpdateLedStateEvent.LedWidget->UpdateState(); + } +} + +void AppTask::LEDStateUpdateHandler(LEDWidget & ledWidget) +{ + AppEvent event; + event.Type = AppEventType::UpdateLedState; + event.Handler = UpdateLedStateEventHandler; + event.UpdateLedStateEvent.LedWidget = &ledWidget; + PostEvent(event); +} + +void AppTask::UpdateStatusLED() +{ +#ifdef CONFIG_STATE_LEDS + // Update the status LED. + // + // If IPv6 network and service provisioned, keep the LED On constantly. + // + // If the system has BLE connection(s) until the stage above, THEN blink the LED at an even + // rate of 100ms. + // + // Otherwise, blink the LED for a very short time. + if (sIsNetworkProvisioned && sIsNetworkEnabled) + { + sStatusLED.Set(true); + } + else if (sHaveBLEConnections) + { + sStatusLED.Blink(LedConsts::StatusLed::Unprovisioned::kOn_ms, LedConsts::StatusLed::Unprovisioned::kOff_ms); + } + else + { + sStatusLED.Blink(LedConsts::StatusLed::Provisioned::kOn_ms, LedConsts::StatusLed::Provisioned::kOff_ms); + } +#endif +} + +void AppTask::ChipEventHandler(const ChipDeviceEvent * event, intptr_t /* arg */) +{ + switch (event->Type) + { + case DeviceEventType::kCHIPoBLEAdvertisingChange: +#ifdef CONFIG_CHIP_NFC_COMMISSIONING + if (event->CHIPoBLEAdvertisingChange.Result == kActivity_Started) + { + if (NFCMgr().IsTagEmulationStarted()) + { + LOG_INF("NFC Tag emulation is already started"); + } + else + { + ShareQRCodeOverNFC(chip::RendezvousInformationFlags(chip::RendezvousInformationFlag::kBLE)); + } + } + else if (event->CHIPoBLEAdvertisingChange.Result == kActivity_Stopped) + { + NFCMgr().StopTagEmulation(); + } +#endif + sHaveBLEConnections = ConnectivityMgr().NumBLEConnections() != 0; + UpdateStatusLED(); + break; +#if defined(CONFIG_NET_L2_OPENTHREAD) + case DeviceEventType::kDnssdInitialized: +#if CONFIG_CHIP_OTA_REQUESTOR + InitBasicOTARequestor(); +#endif // CONFIG_CHIP_OTA_REQUESTOR + break; + case DeviceEventType::kThreadStateChange: + sIsNetworkProvisioned = ConnectivityMgr().IsThreadProvisioned(); + sIsNetworkEnabled = ConnectivityMgr().IsThreadEnabled(); + UpdateStatusLED(); + break; +#endif // CONFIG_NET_L2_OPENTHREAD + default: + break; + } +} + +void AppTask::CancelTimer() +{ + k_timer_stop(&sFunctionTimer); + Instance().mFunctionTimerActive = false; +} + +void AppTask::StartTimer(uint32_t aTimeoutInMs) +{ + k_timer_start(&sFunctionTimer, K_MSEC(aTimeoutInMs), K_NO_WAIT); + Instance().mFunctionTimerActive = true; +} + +void AppTask::PostEvent(const AppEvent & event) +{ + if (k_msgq_put(&sAppEventQueue, &event, K_NO_WAIT) != 0) + { + LOG_INF("Failed to post event to app task event queue"); + } +} + +void AppTask::DispatchEvent(const AppEvent & event) +{ + if (event.Handler) + { + event.Handler(event); + } + else + { + LOG_INF("Event received with no handler. Dropping event."); + } +} diff --git a/examples/lit-icd-app/nrfconnect/main/include/AppConfig.h b/examples/lit-icd-app/nrfconnect/main/include/AppConfig.h new file mode 100644 index 00000000000000..26f63f5ec1fa06 --- /dev/null +++ b/examples/lit-icd-app/nrfconnect/main/include/AppConfig.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2024 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 "BoardUtil.h" + +// ---- LIT ICD Application example config ---- + +#define FUNCTION_BUTTON DK_BTN1 +#define FUNCTION_BUTTON_MASK DK_BTN1_MSK +#define ICD_UAT_BUTTON DK_BTN3 +#define ICD_UAT_BUTTON_MASK DK_BTN3_MSK +#define BLE_ADVERTISEMENT_START_BUTTON DK_BTN4 +#define BLE_ADVERTISEMENT_START_BUTTON_MASK DK_BTN4_MSK +#define SYSTEM_STATE_LED DK_LED1 +#define IDENTIFY_STATE_LED DK_LED2 +#define FACTORY_RESET_SIGNAL_LED DK_LED3 +#define FACTORY_RESET_SIGNAL_LED1 DK_LED4 diff --git a/examples/lit-icd-app/nrfconnect/main/include/AppEvent.h b/examples/lit-icd-app/nrfconnect/main/include/AppEvent.h new file mode 100644 index 00000000000000..27ae7408f52e08 --- /dev/null +++ b/examples/lit-icd-app/nrfconnect/main/include/AppEvent.h @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2024 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 "EventTypes.h" + +class LEDWidget; + +enum class AppEventType : uint8_t +{ + None = 0, + Button, + ButtonPushed, + ButtonReleased, + Timer, + UpdateLedState, + IdentifyStart, + IdentifyStop, +}; + +enum class FunctionEvent : uint8_t +{ + NoneSelected = 0, + SoftwareUpdate = 0, + FactoryReset, + AdvertisingStart +}; + +struct AppEvent +{ + union + { + struct + { + uint8_t PinNo; + uint8_t Action; + } ButtonEvent; + struct + { + void * Context; + } TimerEvent; + struct + { + uint8_t Action; + int32_t Actor; + } LockEvent; + struct + { + LEDWidget * LedWidget; + } UpdateLedStateEvent; + }; + + AppEventType Type{ AppEventType::None }; + EventHandler Handler; +}; diff --git a/examples/lit-icd-app/nrfconnect/main/include/AppTask.h b/examples/lit-icd-app/nrfconnect/main/include/AppTask.h new file mode 100644 index 00000000000000..f1513b2d1e75cb --- /dev/null +++ b/examples/lit-icd-app/nrfconnect/main/include/AppTask.h @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2024 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 "AppEvent.h" +#include "LEDWidget.h" + +#if CONFIG_CHIP_FACTORY_DATA +#include +#else +#include +#endif + +struct k_timer; +struct Identify; + +class AppTask +{ +public: + static AppTask & Instance(void) + { + static AppTask sAppTask; + return sAppTask; + }; + CHIP_ERROR StartApp(); + + static void IdentifyStartHandler(Identify *); + static void IdentifyStopHandler(Identify *); + + static void PostEvent(const AppEvent & event); + +private: + CHIP_ERROR Init(); + + static void CancelTimer(); + static void StartTimer(uint32_t timeoutInMs); + + static void DispatchEvent(const AppEvent & event); + static void FunctionTimerEventHandler(const AppEvent & event); + static void FunctionHandler(const AppEvent & event); + static void StartBLEAdvertisementHandler(const AppEvent & event); + static void IcdUatEventHandler(const AppEvent & event); + static void UpdateLedStateEventHandler(const AppEvent & event); + + static void ChipEventHandler(const chip::DeviceLayer::ChipDeviceEvent * event, intptr_t arg); + static void ButtonEventHandler(uint32_t buttonState, uint32_t hasChanged); + static void LEDStateUpdateHandler(LEDWidget & ledWidget); + static void FunctionTimerTimeoutCallback(k_timer * timer); + static void UpdateStatusLED(); + + FunctionEvent mFunction = FunctionEvent::NoneSelected; + bool mFunctionTimerActive = false; + +#if CONFIG_CHIP_FACTORY_DATA + chip::DeviceLayer::FactoryDataProvider mFactoryDataProvider; +#endif +}; diff --git a/examples/lit-icd-app/nrfconnect/main/include/CHIPProjectConfig.h b/examples/lit-icd-app/nrfconnect/main/include/CHIPProjectConfig.h new file mode 100644 index 00000000000000..4baa186190f638 --- /dev/null +++ b/examples/lit-icd-app/nrfconnect/main/include/CHIPProjectConfig.h @@ -0,0 +1,28 @@ +/* + * + * Copyright (c) 2020 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. + */ + +/** + * @file + * Example project configuration file for CHIP. + * + * This is a place to put application or project-specific overrides + * to the default configuration values for general CHIP features. + * + */ + +#pragma once diff --git a/examples/lit-icd-app/nrfconnect/main/main.cpp b/examples/lit-icd-app/nrfconnect/main/main.cpp new file mode 100644 index 00000000000000..0f9b0451e4284d --- /dev/null +++ b/examples/lit-icd-app/nrfconnect/main/main.cpp @@ -0,0 +1,33 @@ +/* + * + * Copyright (c) 2024 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 "AppTask.h" + +#include + +LOG_MODULE_REGISTER(app, CONFIG_CHIP_APP_LOG_LEVEL); + +using namespace ::chip; + +int main() +{ + CHIP_ERROR err = AppTask::Instance().StartApp(); + + LOG_ERR("Exited with code %" CHIP_ERROR_FORMAT, err.Format()); + return err == CHIP_NO_ERROR ? EXIT_SUCCESS : EXIT_FAILURE; +} diff --git a/examples/lit-icd-app/nrfconnect/prj.conf b/examples/lit-icd-app/nrfconnect/prj.conf new file mode 100644 index 00000000000000..950be7c8c394e4 --- /dev/null +++ b/examples/lit-icd-app/nrfconnect/prj.conf @@ -0,0 +1,46 @@ +# +# Copyright (c) 2024 Project CHIP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# This sample uses Kconfig.defaults to set options common for all +# samples. This file should contain only options specific for this sample +# or overrides of default values. + +# Enable CHIP +CONFIG_CHIP=y +CONFIG_CHIP_PROJECT_CONFIG="main/include/CHIPProjectConfig.h" +CONFIG_STD_CPP17=y + +# Add support for LEDs and buttons on Nordic development kits +CONFIG_DK_LIBRARY=y + +# Bluetooth Low Energy configuration +CONFIG_BT_DEVICE_NAME="MatterLIT" + +# Other settings +CONFIG_THREAD_NAME=y +CONFIG_MPU_STACK_GUARD=y +CONFIG_RESET_ON_FATAL_ERROR=n + +# Reduce application size +CONFIG_USE_SEGGER_RTT=n + +# Enable Factory Data feature +CONFIG_CHIP_FACTORY_DATA=y +CONFIG_CHIP_FACTORY_DATA_BUILD=y + +# Enable LIT ICD configuration +CONFIG_CHIP_ENABLE_ICD_SUPPORT=y +CONFIG_CHIP_ICD_LIT_SUPPORT=y diff --git a/examples/lit-icd-app/nrfconnect/prj_no_dfu.conf b/examples/lit-icd-app/nrfconnect/prj_no_dfu.conf new file mode 100644 index 00000000000000..00607e349a31ab --- /dev/null +++ b/examples/lit-icd-app/nrfconnect/prj_no_dfu.conf @@ -0,0 +1,48 @@ +# +# Copyright (c) 2024 Project CHIP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# This sample uses Kconfig.defaults to set options common for all +# samples. This file should contain only options specific for this sample +# or overrides of default values. + +# Enable CHIP +CONFIG_CHIP=y +CONFIG_CHIP_PROJECT_CONFIG="main/include/CHIPProjectConfig.h" +CONFIG_STD_CPP17=y + +# Add support for LEDs and buttons on Nordic development kits +CONFIG_DK_LIBRARY=y + +# Bluetooth Low Energy configuration +CONFIG_BT_DEVICE_NAME="MatterLIT" + +# Other settings +CONFIG_THREAD_NAME=y +CONFIG_MPU_STACK_GUARD=y +CONFIG_RESET_ON_FATAL_ERROR=n + +# Reduce application size +CONFIG_USE_SEGGER_RTT=n + +# Disable Matter OTA DFU +CONFIG_CHIP_OTA_REQUESTOR=n + +# Disable QSPI NOR +CONFIG_CHIP_QSPI_NOR=n + +# Enable LIT ICD configuration +CONFIG_CHIP_ENABLE_ICD_SUPPORT=y +CONFIG_CHIP_ICD_LIT_SUPPORT=y diff --git a/examples/lit-icd-app/nrfconnect/prj_release.conf b/examples/lit-icd-app/nrfconnect/prj_release.conf new file mode 100644 index 00000000000000..61b6b3dfc6f8f8 --- /dev/null +++ b/examples/lit-icd-app/nrfconnect/prj_release.conf @@ -0,0 +1,60 @@ +# +# Copyright (c) 2024 Project CHIP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# This sample uses Kconfig.defaults to set options common for all +# samples. This file should contain only options specific for this sample +# or overrides of default values. + +# Enable CHIP +CONFIG_CHIP=y +CONFIG_CHIP_PROJECT_CONFIG="main/include/CHIPProjectConfig.h" +CONFIG_STD_CPP17=y + +# Add support for LEDs and buttons on Nordic development kits +CONFIG_DK_LIBRARY=y + +# Bluetooth Low Energy configuration +CONFIG_BT_DEVICE_NAME="MatterLIT" + +# Enable system reset on fatal error +CONFIG_RESET_ON_FATAL_ERROR=y + +# Suspend devices when the CPU goes into sleep +CONFIG_PM_DEVICE=y + +# Disable all debug features +CONFIG_USE_SEGGER_RTT=n +CONFIG_SHELL=n +CONFIG_OPENTHREAD_SHELL=n +CONFIG_CONSOLE=n +CONFIG_UART_CONSOLE=n +CONFIG_SERIAL=n +CONFIG_LOG=n +CONFIG_LOG_MODE_MINIMAL=n +CONFIG_ASSERT_VERBOSE=n +CONFIG_ASSERT_NO_FILE_INFO=y +CONFIG_PRINTK=n +CONFIG_PRINTK_SYNC=n +CONFIG_THREAD_NAME=n +CONFIG_BOOT_BANNER=n + +# Enable Factory Data feature +CONFIG_CHIP_FACTORY_DATA=y +CONFIG_CHIP_FACTORY_DATA_BUILD=y + +# Enable LIT ICD configuration +CONFIG_CHIP_ENABLE_ICD_SUPPORT=y +CONFIG_CHIP_ICD_LIT_SUPPORT=y diff --git a/examples/lit-icd-app/nrfconnect/third_party/connectedhomeip b/examples/lit-icd-app/nrfconnect/third_party/connectedhomeip new file mode 120000 index 00000000000000..c866b86874994d --- /dev/null +++ b/examples/lit-icd-app/nrfconnect/third_party/connectedhomeip @@ -0,0 +1 @@ +../../../.. \ No newline at end of file From 1fd60e56f67a077b933e140f1917c36480b31812 Mon Sep 17 00:00:00 2001 From: Justin Wood Date: Mon, 19 Feb 2024 09:22:23 -0800 Subject: [PATCH 020/385] Update cherry-picks.yaml --- .github/workflows/cherry-picks.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/cherry-picks.yaml b/.github/workflows/cherry-picks.yaml index 6d9b5339b40b9e..a062aa5fcf9b87 100644 --- a/.github/workflows/cherry-picks.yaml +++ b/.github/workflows/cherry-picks.yaml @@ -14,7 +14,6 @@ jobs: (github.event.pull_request.merged == true) && ( (contains(github.event.pull_request.labels.*.name, 'sve')) - || (contains(github.event.pull_request.labels.*.name, 'spec')) || (contains(github.event.pull_request.labels.*.name, 'request sve')) || (contains(github.event.pull_request.labels.*.name, 'cert blocker')) ) @@ -27,11 +26,12 @@ jobs: uses: carloscastrojumo/github-cherry-pick-action@v1.0.9 with: token: ${{ secrets.MATTER_PAT }} - branch: sve-2 + branch: 1.3-sve labels: | sve cherry pick reviewers: | woody-apple andy31415 + raju-apple env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} From f5b7a1d54497e9f9838d1b9b590b20334260aa12 Mon Sep 17 00:00:00 2001 From: Arkadiusz Bokowy Date: Mon, 19 Feb 2024 18:27:57 +0100 Subject: [PATCH 021/385] [Linux] Fix BLE infinite advertising (#32093) * [Linux] Fix BLE infinite advertising According to BlueZ documentation, discoverable timeout of 0 should disable the timeout. However, due to a bug, setting timeout to 0 stops advertising immediately after sending ADV frame. * Add comments for commented-out properties * Add comments to D-Bus interfaces which are owned by us * Update the comment so it will be easier to understand the meaning --- .../Linux/bluez/BluezAdvertisement.cpp | 2 +- src/platform/Linux/dbus/bluez/DbusBluez.xml | 42 +++++++++++++++++-- 2 files changed, 40 insertions(+), 4 deletions(-) diff --git a/src/platform/Linux/bluez/BluezAdvertisement.cpp b/src/platform/Linux/bluez/BluezAdvertisement.cpp index db74da8bec1ec4..1b95aae41a4f11 100644 --- a/src/platform/Linux/bluez/BluezAdvertisement.cpp +++ b/src/platform/Linux/bluez/BluezAdvertisement.cpp @@ -65,7 +65,7 @@ BluezLEAdvertisement1 * BluezAdvertisement::CreateLEAdvertisement() // Bluez to set "BR/EDR Not Supported" flag. Bluez doesn't provide API to do that explicitly // and the flag is necessary to force using LE transport. bluez_leadvertisement1_set_discoverable(adv, TRUE); - bluez_leadvertisement1_set_discoverable_timeout(adv, 0 /* infinite */); + // empty discoverable timeout for infinite discoverability // empty includes bluez_leadvertisement1_set_local_name(adv, mAdvName); diff --git a/src/platform/Linux/dbus/bluez/DbusBluez.xml b/src/platform/Linux/dbus/bluez/DbusBluez.xml index 00887dc5e147a9..0a42da708d50a9 100644 --- a/src/platform/Linux/dbus/bluez/DbusBluez.xml +++ b/src/platform/Linux/dbus/bluez/DbusBluez.xml @@ -108,6 +108,10 @@ + @@ -115,6 +119,10 @@ + @@ -152,6 +160,10 @@ + @@ -172,6 +184,10 @@ + @@ -183,13 +199,33 @@ + - - - + + + From d2ed79c086f62e6355c38eb9ce99bd1d28bbb4a5 Mon Sep 17 00:00:00 2001 From: Vivien Nicolas Date: Mon, 19 Feb 2024 18:29:12 +0100 Subject: [PATCH 022/385] [DiagnosticLogs] When the size of the logs for the target intent is 0, the server returns Exhausted instead of NoLogs (#32205) --- .../diagnostic-logs-server/diagnostic-logs-server.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/app/clusters/diagnostic-logs-server/diagnostic-logs-server.cpp b/src/app/clusters/diagnostic-logs-server/diagnostic-logs-server.cpp index 95d9a332819ae3..83beb46484bb71 100644 --- a/src/app/clusters/diagnostic-logs-server/diagnostic-logs-server.cpp +++ b/src/app/clusters/diagnostic-logs-server/diagnostic-logs-server.cpp @@ -115,6 +115,9 @@ void DiagnosticLogsServer::HandleLogRequestForResponsePayload(CommandHandler * c Optional timeStamp; Optional timeSinceBoot; + auto size = delegate->GetSizeForIntent(intent); + VerifyOrReturn(size != 0, AddResponse(commandObj, path, StatusEnum::kNoLogs)); + auto err = delegate->GetLogForIntent(intent, logContent, timeStamp, timeSinceBoot); VerifyOrReturn(CHIP_ERROR_NOT_FOUND != err, AddResponse(commandObj, path, StatusEnum::kNoLogs)); VerifyOrReturn(CHIP_NO_ERROR == err, AddResponse(commandObj, path, StatusEnum::kDenied)); @@ -136,10 +139,13 @@ void DiagnosticLogsServer::HandleLogRequestForBdx(CommandHandler * commandObj, c auto * delegate = GetDiagnosticLogsProviderDelegate(path.mEndpointId); VerifyOrReturn(nullptr != delegate, AddResponse(commandObj, path, StatusEnum::kNoLogs)); + auto size = delegate->GetSizeForIntent(intent); + // In the case where the size is 0 sets the Status field of the RetrieveLogsResponse to NoLogs and do not start a BDX session. + VerifyOrReturn(size != 0, HandleLogRequestForResponsePayload(commandObj, path, intent, StatusEnum::kNoLogs)); + // In the case where the Node is able to fit the entirety of the requested logs within the LogContent field, the Status field of // the RetrieveLogsResponse SHALL be set to Exhausted and a BDX session SHALL NOT be initiated. - VerifyOrReturn(delegate->GetSizeForIntent(intent) > kMaxLogContentSize, - HandleLogRequestForResponsePayload(commandObj, path, intent, StatusEnum::kExhausted)); + VerifyOrReturn(size > kMaxLogContentSize, HandleLogRequestForResponsePayload(commandObj, path, intent, StatusEnum::kExhausted)); // If the RequestedProtocol is set to BDX and either the Node does not support BDX or it is not possible for the Node // to establish a BDX session, then the Node SHALL utilize the LogContent field of the RetrieveLogsResponse command From a5be64326e57636795d2cef5390832708097075a Mon Sep 17 00:00:00 2001 From: Vivien Nicolas Date: Mon, 19 Feb 2024 18:29:26 +0100 Subject: [PATCH 023/385] [DiagnosticLogs] When the size of the TransferFileDesignator is 0, the server should returns CONSTRAINT_ERROR (#32207) --- .../clusters/diagnostic-logs-server/diagnostic-logs-server.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/app/clusters/diagnostic-logs-server/diagnostic-logs-server.cpp b/src/app/clusters/diagnostic-logs-server/diagnostic-logs-server.cpp index 83beb46484bb71..7b1b036ee4857b 100644 --- a/src/app/clusters/diagnostic-logs-server/diagnostic-logs-server.cpp +++ b/src/app/clusters/diagnostic-logs-server/diagnostic-logs-server.cpp @@ -132,6 +132,8 @@ void DiagnosticLogsServer::HandleLogRequestForBdx(CommandHandler * commandObj, c // INVALID_COMMAND. VerifyOrReturn(transferFileDesignator.HasValue(), commandObj->AddStatus(path, Status::InvalidCommand)); + VerifyOrReturn(transferFileDesignator.Value().size() > 0, commandObj->AddStatus(path, Status::ConstraintError)); + VerifyOrReturn(transferFileDesignator.Value().size() <= kMaxFileDesignatorLen, commandObj->AddStatus(path, Status::ConstraintError)); From 73d827cada19badc12f7e849fb08dd44860ad6ac Mon Sep 17 00:00:00 2001 From: Arkadiusz Bokowy Date: Mon, 19 Feb 2024 18:34:33 +0100 Subject: [PATCH 024/385] [Linux] Lock CHIP stack before calling WiFi diagnostic delegate (#32137) * Get rid of static functions by wrapping glib callbacks with lambda * Get rid of the rest of static functions * Keep sWiFiIfName as an instance member * Lock CHIP stack before calling WiFi diagnostic delegate * Do not use sInstance internally in ConnectivityManagerImpl * Fix signatures for properties-changed and scan-done callbacks * Keep all members of ConnectivityManagerImpl as instance members * Fix freeing char objects allocated by glib * Restyled by clang-format * Fix compilation warnings --------- Co-authored-by: Restyled.io --- .../Linux/ConnectivityManagerImpl.cpp | 200 +++++++++++------- src/platform/Linux/ConnectivityManagerImpl.h | 56 ++--- src/platform/Linux/PlatformManagerImpl.cpp | 4 +- 3 files changed, 152 insertions(+), 108 deletions(-) diff --git a/src/platform/Linux/ConnectivityManagerImpl.cpp b/src/platform/Linux/ConnectivityManagerImpl.cpp index d03cefef4f0ef7..eef7ce883f0042 100644 --- a/src/platform/Linux/ConnectivityManagerImpl.cpp +++ b/src/platform/Linux/ConnectivityManagerImpl.cpp @@ -98,15 +98,6 @@ namespace DeviceLayer { ConnectivityManagerImpl ConnectivityManagerImpl::sInstance; -#if CHIP_DEVICE_CONFIG_ENABLE_WIFI -char ConnectivityManagerImpl::sWiFiIfName[]; -#endif - -WiFiDriver::ScanCallback * ConnectivityManagerImpl::mpScanCallback; -NetworkCommissioning::Internal::WirelessDriver::ConnectCallback * ConnectivityManagerImpl::mpConnectCallback; -uint8_t ConnectivityManagerImpl::sInterestedSSID[Internal::kMaxWiFiSSIDLength]; -uint8_t ConnectivityManagerImpl::sInterestedSSIDLen; - CHIP_ERROR ConnectivityManagerImpl::_Init() { #if CHIP_DEVICE_CONFIG_ENABLE_WPA @@ -166,12 +157,6 @@ void ConnectivityManagerImpl::_OnPlatformEvent(const ChipDeviceEvent * event) #if CHIP_DEVICE_CONFIG_ENABLE_WPA -bool ConnectivityManagerImpl::mAssociationStarted = false; -BitFlags::ConnectivityFlags> - ConnectivityManagerImpl::mConnectivityFlag; -struct GDBusWpaSupplicant ConnectivityManagerImpl::mWpaSupplicant; -std::mutex ConnectivityManagerImpl::mWpaSupplicantMutex; - ConnectivityManager::WiFiStationMode ConnectivityManagerImpl::_GetWiFiStationMode() { if (mWiFiStationMode != kWiFiStationMode_ApplicationControlled) @@ -313,7 +298,7 @@ CHIP_ERROR ConnectivityManagerImpl::_SetWiFiAPMode(WiFiAPMode val) ChipLogProgress(DeviceLayer, "WiFi AP mode change: %s -> %s", WiFiAPModeToStr(mWiFiAPMode), WiFiAPModeToStr(val)); mWiFiAPMode = val; - DeviceLayer::SystemLayer().ScheduleWork(DriveAPState, nullptr); + DeviceLayer::SystemLayer().ScheduleLambda([this] { DriveAPState(); }); } exit: @@ -326,7 +311,7 @@ void ConnectivityManagerImpl::_DemandStartWiFiAP() { ChipLogProgress(DeviceLayer, "wpa_supplicant: Demand start WiFi AP"); mLastAPDemandTime = System::SystemClock().GetMonotonicTimestamp(); - DeviceLayer::SystemLayer().ScheduleWork(DriveAPState, nullptr); + DeviceLayer::SystemLayer().ScheduleLambda([this] { DriveAPState(); }); } else { @@ -340,7 +325,7 @@ void ConnectivityManagerImpl::_StopOnDemandWiFiAP() { ChipLogProgress(DeviceLayer, "wpa_supplicant: Demand stop WiFi AP"); mLastAPDemandTime = System::Clock::kZero; - DeviceLayer::SystemLayer().ScheduleWork(DriveAPState, nullptr); + DeviceLayer::SystemLayer().ScheduleLambda([this] { DriveAPState(); }); } else { @@ -362,7 +347,7 @@ void ConnectivityManagerImpl::_MaintainOnDemandWiFiAP() void ConnectivityManagerImpl::_SetWiFiAPIdleTimeout(System::Clock::Timeout val) { mWiFiAPIdleTimeout = val; - DeviceLayer::SystemLayer().ScheduleWork(DriveAPState, nullptr); + DeviceLayer::SystemLayer().ScheduleLambda([this] { DriveAPState(); }); } void ConnectivityManagerImpl::UpdateNetworkStatus() @@ -391,12 +376,11 @@ void ConnectivityManagerImpl::UpdateNetworkStatus() MakeOptional(GetDisconnectReason())); } -void ConnectivityManagerImpl::_OnWpaPropertiesChanged(WpaFiW1Wpa_supplicant1Interface * proxy, GVariant * changed_properties, - const gchar * const * invalidated_properties, gpointer user_data) +void ConnectivityManagerImpl::_OnWpaPropertiesChanged(WpaFiW1Wpa_supplicant1Interface * proxy, GVariant * changedProperties) { std::lock_guard lock(mWpaSupplicantMutex); - if (g_variant_n_children(changed_properties) > 0) + if (g_variant_n_children(changedProperties) > 0) { GAutoPtr iter; const gchar * key; @@ -404,7 +388,7 @@ void ConnectivityManagerImpl::_OnWpaPropertiesChanged(WpaFiW1Wpa_supplicant1Inte WiFiDiagnosticsDelegate * delegate = GetDiagnosticDataProvider().GetWiFiDiagnosticsDelegate(); - g_variant_get(changed_properties, "a{sv}", &MakeUniquePointerReceiver(iter).Get()); + g_variant_get(changedProperties, "a{sv}", &MakeUniquePointerReceiver(iter).Get()); while (g_variant_iter_loop(iter.get(), "{&sv}", &key, &value)) { @@ -424,6 +408,7 @@ void ConnectivityManagerImpl::_OnWpaPropertiesChanged(WpaFiW1Wpa_supplicant1Inte if (delegate) { + chip::DeviceLayer::StackLock stackLock; delegate->OnDisconnectionDetected(reason); delegate->OnConnectionStatusChanged(static_cast(ConnectionStatusEnum::kConnected)); } @@ -453,7 +438,7 @@ void ConnectivityManagerImpl::_OnWpaPropertiesChanged(WpaFiW1Wpa_supplicant1Inte break; } - DeviceLayer::SystemLayer().ScheduleLambda([reason]() { + DeviceLayer::SystemLayer().ScheduleLambda([this, reason]() { if (mpConnectCallback != nullptr) { mpConnectCallback->OnResult(NetworkCommissioning::Status::kUnknownError, CharSpan(), reason); @@ -463,6 +448,7 @@ void ConnectivityManagerImpl::_OnWpaPropertiesChanged(WpaFiW1Wpa_supplicant1Inte if (delegate) { + chip::DeviceLayer::StackLock stackLock; delegate->OnAssociationFailureDetected(associationFailureCause, status); } } @@ -475,6 +461,7 @@ void ConnectivityManagerImpl::_OnWpaPropertiesChanged(WpaFiW1Wpa_supplicant1Inte { if (delegate) { + chip::DeviceLayer::StackLock stackLock; delegate->OnConnectionStatusChanged(static_cast(ConnectionStatusEnum::kNotConnected)); } @@ -484,7 +471,7 @@ void ConnectivityManagerImpl::_OnWpaPropertiesChanged(WpaFiW1Wpa_supplicant1Inte { if (mAssociationStarted) { - DeviceLayer::SystemLayer().ScheduleLambda([]() { + DeviceLayer::SystemLayer().ScheduleLambda([this]() { if (mpConnectCallback != nullptr) { mpConnectCallback->OnResult(NetworkCommissioning::Status::kSuccess, CharSpan(), 0); @@ -500,7 +487,7 @@ void ConnectivityManagerImpl::_OnWpaPropertiesChanged(WpaFiW1Wpa_supplicant1Inte } } -void ConnectivityManagerImpl::_OnWpaInterfaceProxyReady(GObject * source_object, GAsyncResult * res, gpointer user_data) +void ConnectivityManagerImpl::_OnWpaInterfaceProxyReady(GObject * sourceObject, GAsyncResult * res) { // When creating D-Bus proxy object, the thread default context must be initialized. Otherwise, // all D-Bus signals will be delivered to the GLib global default main context. @@ -525,8 +512,17 @@ void ConnectivityManagerImpl::_OnWpaInterfaceProxyReady(GObject * source_object, mWpaSupplicant.state = GDBusWpaSupplicant::WPA_INTERFACE_CONNECTED; ChipLogProgress(DeviceLayer, "wpa_supplicant: connected to wpa_supplicant interface proxy"); - g_signal_connect(mWpaSupplicant.iface, "properties-changed", G_CALLBACK(_OnWpaPropertiesChanged), NULL); - g_signal_connect(mWpaSupplicant.iface, "scan-done", G_CALLBACK(_OnWpaInterfaceScanDone), NULL); + g_signal_connect( + mWpaSupplicant.iface, "properties-changed", + G_CALLBACK(+[](WpaFiW1Wpa_supplicant1Interface * proxy, GVariant * properties, ConnectivityManagerImpl * self) { + return self->_OnWpaPropertiesChanged(proxy, properties); + }), + this); + g_signal_connect(mWpaSupplicant.iface, "scan-done", + G_CALLBACK(+[](WpaFiW1Wpa_supplicant1Interface * proxy, gboolean success, ConnectivityManagerImpl * self) { + return self->_OnWpaInterfaceScanDone(proxy, success); + }), + this); } else { @@ -537,7 +533,7 @@ void ConnectivityManagerImpl::_OnWpaInterfaceProxyReady(GObject * source_object, } // We need to stop auto scan or it will block our network scan. - DeviceLayer::SystemLayer().ScheduleLambda([]() { + DeviceLayer::SystemLayer().ScheduleLambda([this]() { CHIP_ERROR errInner = StopAutoScan(); if (errInner != CHIP_NO_ERROR) { @@ -546,7 +542,7 @@ void ConnectivityManagerImpl::_OnWpaInterfaceProxyReady(GObject * source_object, }); } -void ConnectivityManagerImpl::_OnWpaBssProxyReady(GObject * source_object, GAsyncResult * res, gpointer user_data) +void ConnectivityManagerImpl::_OnWpaBssProxyReady(GObject * sourceObject, GAsyncResult * res) { // When creating D-Bus proxy object, the thread default context must be initialized. Otherwise, // all D-Bus signals will be delivered to the GLib global default main context. @@ -577,7 +573,7 @@ void ConnectivityManagerImpl::_OnWpaBssProxyReady(GObject * source_object, GAsyn } } -void ConnectivityManagerImpl::_OnWpaInterfaceReady(GObject * source_object, GAsyncResult * res, gpointer user_data) +void ConnectivityManagerImpl::_OnWpaInterfaceReady(GObject * sourceObject, GAsyncResult * res) { // When creating D-Bus proxy object, the thread default context must be initialized. Otherwise, // all D-Bus signals will be delivered to the GLib global default main context. @@ -594,12 +590,21 @@ void ConnectivityManagerImpl::_OnWpaInterfaceReady(GObject * source_object, GAsy mWpaSupplicant.state = GDBusWpaSupplicant::WPA_GOT_INTERFACE_PATH; ChipLogProgress(DeviceLayer, "wpa_supplicant: WiFi interface: %s", mWpaSupplicant.interfacePath); - wpa_fi_w1_wpa_supplicant1_interface_proxy_new_for_bus(G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE, kWpaSupplicantServiceName, - mWpaSupplicant.interfacePath, nullptr, _OnWpaInterfaceProxyReady, - nullptr); - - wpa_fi_w1_wpa_supplicant1_bss_proxy_new_for_bus(G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE, kWpaSupplicantServiceName, - mWpaSupplicant.interfacePath, nullptr, _OnWpaBssProxyReady, nullptr); + wpa_fi_w1_wpa_supplicant1_interface_proxy_new_for_bus( + G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE, kWpaSupplicantServiceName, mWpaSupplicant.interfacePath, nullptr, + reinterpret_cast( + +[](GObject * sourceObject_, GAsyncResult * res_, ConnectivityManagerImpl * self) { + return self->_OnWpaInterfaceProxyReady(sourceObject_, res_); + }), + this); + + wpa_fi_w1_wpa_supplicant1_bss_proxy_new_for_bus( + G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE, kWpaSupplicantServiceName, mWpaSupplicant.interfacePath, nullptr, + reinterpret_cast( + +[](GObject * sourceObject_, GAsyncResult * res_, ConnectivityManagerImpl * self) { + return self->_OnWpaBssProxyReady(sourceObject_, res_); + }), + this); } else { @@ -626,12 +631,21 @@ void ConnectivityManagerImpl::_OnWpaInterfaceReady(GObject * source_object, GAsy Platform::CopyString(sWiFiIfName, CHIP_DEVICE_CONFIG_WIFI_STATION_IF_NAME); - wpa_fi_w1_wpa_supplicant1_interface_proxy_new_for_bus(G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE, - kWpaSupplicantServiceName, mWpaSupplicant.interfacePath, nullptr, - _OnWpaInterfaceProxyReady, nullptr); - - wpa_fi_w1_wpa_supplicant1_bss_proxy_new_for_bus(G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE, kWpaSupplicantServiceName, - mWpaSupplicant.interfacePath, nullptr, _OnWpaBssProxyReady, nullptr); + wpa_fi_w1_wpa_supplicant1_interface_proxy_new_for_bus( + G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE, kWpaSupplicantServiceName, mWpaSupplicant.interfacePath, nullptr, + reinterpret_cast( + +[](GObject * sourceObject_, GAsyncResult * res_, ConnectivityManagerImpl * self) { + return self->_OnWpaInterfaceProxyReady(sourceObject_, res_); + }), + this); + + wpa_fi_w1_wpa_supplicant1_bss_proxy_new_for_bus( + G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE, kWpaSupplicantServiceName, mWpaSupplicant.interfacePath, nullptr, + reinterpret_cast( + +[](GObject * sourceObject_, GAsyncResult * res_, ConnectivityManagerImpl * self) { + return self->_OnWpaBssProxyReady(sourceObject_, res_); + }), + this); } else { @@ -649,8 +663,7 @@ void ConnectivityManagerImpl::_OnWpaInterfaceReady(GObject * source_object, GAsy } } -void ConnectivityManagerImpl::_OnWpaInterfaceAdded(WpaFiW1Wpa_supplicant1 * proxy, const gchar * path, GVariant * properties, - gpointer user_data) +void ConnectivityManagerImpl::_OnWpaInterfaceAdded(WpaFiW1Wpa_supplicant1 * proxy, const char * path, GVariant * properties) { // When creating D-Bus proxy object, the thread default context must be initialized. Otherwise, // all D-Bus signals will be delivered to the GLib global default main context. @@ -669,17 +682,25 @@ void ConnectivityManagerImpl::_OnWpaInterfaceAdded(WpaFiW1Wpa_supplicant1 * prox mWpaSupplicant.state = GDBusWpaSupplicant::WPA_GOT_INTERFACE_PATH; ChipLogProgress(DeviceLayer, "wpa_supplicant: WiFi interface added: %s", mWpaSupplicant.interfacePath); - wpa_fi_w1_wpa_supplicant1_interface_proxy_new_for_bus(G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE, kWpaSupplicantServiceName, - mWpaSupplicant.interfacePath, nullptr, _OnWpaInterfaceProxyReady, - nullptr); - - wpa_fi_w1_wpa_supplicant1_bss_proxy_new_for_bus(G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE, kWpaSupplicantServiceName, - mWpaSupplicant.interfacePath, nullptr, _OnWpaBssProxyReady, nullptr); + wpa_fi_w1_wpa_supplicant1_interface_proxy_new_for_bus( + G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE, kWpaSupplicantServiceName, mWpaSupplicant.interfacePath, nullptr, + reinterpret_cast( + +[](GObject * sourceObject_, GAsyncResult * res_, ConnectivityManagerImpl * self) { + return self->_OnWpaInterfaceProxyReady(sourceObject_, res_); + }), + this); + + wpa_fi_w1_wpa_supplicant1_bss_proxy_new_for_bus( + G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE, kWpaSupplicantServiceName, mWpaSupplicant.interfacePath, nullptr, + reinterpret_cast( + +[](GObject * sourceObject_, GAsyncResult * res_, ConnectivityManagerImpl * self) { + return self->_OnWpaBssProxyReady(sourceObject_, res_); + }), + this); } } -void ConnectivityManagerImpl::_OnWpaInterfaceRemoved(WpaFiW1Wpa_supplicant1 * proxy, const gchar * path, GVariant * properties, - gpointer user_data) +void ConnectivityManagerImpl::_OnWpaInterfaceRemoved(WpaFiW1Wpa_supplicant1 * proxy, const char * path, GVariant * properties) { std::lock_guard lock(mWpaSupplicantMutex); @@ -716,7 +737,7 @@ void ConnectivityManagerImpl::_OnWpaInterfaceRemoved(WpaFiW1Wpa_supplicant1 * pr } } -void ConnectivityManagerImpl::_OnWpaProxyReady(GObject * source_object, GAsyncResult * res, gpointer user_data) +void ConnectivityManagerImpl::_OnWpaProxyReady(GObject * sourceObject, GAsyncResult * res) { // When creating D-Bus proxy object, the thread default context must be initialized. Otherwise, // all D-Bus signals will be delivered to the GLib global default main context. @@ -732,11 +753,24 @@ void ConnectivityManagerImpl::_OnWpaProxyReady(GObject * source_object, GAsyncRe mWpaSupplicant.state = GDBusWpaSupplicant::WPA_CONNECTED; ChipLogProgress(DeviceLayer, "wpa_supplicant: connected to wpa_supplicant proxy"); - g_signal_connect(mWpaSupplicant.proxy, "interface-added", G_CALLBACK(_OnWpaInterfaceAdded), NULL); - - g_signal_connect(mWpaSupplicant.proxy, "interface-removed", G_CALLBACK(_OnWpaInterfaceRemoved), NULL); - - wpa_fi_w1_wpa_supplicant1_call_get_interface(mWpaSupplicant.proxy, sWiFiIfName, nullptr, _OnWpaInterfaceReady, nullptr); + g_signal_connect( + mWpaSupplicant.proxy, "interface-added", + G_CALLBACK(+[](WpaFiW1Wpa_supplicant1 * proxy, const char * path, GVariant * properties, + ConnectivityManagerImpl * self) { return self->_OnWpaInterfaceAdded(proxy, path, properties); }), + this); + g_signal_connect( + mWpaSupplicant.proxy, "interface-removed", + G_CALLBACK(+[](WpaFiW1Wpa_supplicant1 * proxy, const char * path, GVariant * properties, + ConnectivityManagerImpl * self) { return self->_OnWpaInterfaceRemoved(proxy, path, properties); }), + this); + + wpa_fi_w1_wpa_supplicant1_call_get_interface( + mWpaSupplicant.proxy, sWiFiIfName, nullptr, + reinterpret_cast( + +[](GObject * sourceObject_, GAsyncResult * res_, ConnectivityManagerImpl * self) { + return self->_OnWpaInterfaceReady(sourceObject_, res_); + }), + this); } else { @@ -753,7 +787,8 @@ void ConnectivityManagerImpl::StartWiFiManagement() mConnectivityFlag.ClearAll(); mWpaSupplicant = GDBusWpaSupplicant{}; - CHIP_ERROR err = PlatformMgrImpl().GLibMatterContextInvokeSync(_StartWiFiManagement, this); + CHIP_ERROR err = PlatformMgrImpl().GLibMatterContextInvokeSync( + +[](ConnectivityManagerImpl * self) { return self->_StartWiFiManagement(); }, this); VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(DeviceLayer, "Failed to start WiFi management")); } @@ -829,7 +864,7 @@ void ConnectivityManagerImpl::DriveAPState() // Compute the amount of idle time before the AP should be deactivated and // arm a timer to fire at that time. System::Clock::Timeout apTimeout = (mLastAPDemandTime + mWiFiAPIdleTimeout) - now; - err = DeviceLayer::SystemLayer().StartTimer(apTimeout, DriveAPState, nullptr); + err = DeviceLayer::SystemLayer().StartTimer(apTimeout, DriveAPState, this); SuccessOrExit(err); ChipLogProgress(DeviceLayer, "Next WiFi AP timeout in %" PRIu32 " s", std::chrono::duration_cast(apTimeout).count()); @@ -916,7 +951,7 @@ CHIP_ERROR ConnectivityManagerImpl::ConfigureWiFiAP() // Clean up current network if exists if (mWpaSupplicant.networkPath) { - g_object_unref(mWpaSupplicant.networkPath); + g_free(mWpaSupplicant.networkPath); mWpaSupplicant.networkPath = nullptr; } @@ -956,7 +991,7 @@ CHIP_ERROR ConnectivityManagerImpl::ConfigureWiFiAP() if (mWpaSupplicant.networkPath) { - g_object_unref(mWpaSupplicant.networkPath); + g_free(mWpaSupplicant.networkPath); mWpaSupplicant.networkPath = nullptr; } @@ -977,7 +1012,7 @@ void ConnectivityManagerImpl::ChangeWiFiAPState(WiFiAPState newState) void ConnectivityManagerImpl::DriveAPState(::chip::System::Layer * aLayer, void * aAppState) { - sInstance.DriveAPState(); + reinterpret_cast(aAppState)->DriveAPState(); } CHIP_ERROR @@ -1030,8 +1065,14 @@ ConnectivityManagerImpl::_ConnectWiFiNetworkAsync(GVariant * args, wpa_fi_w1_wpa_supplicant1_interface_call_disconnect_sync(mWpaSupplicant.iface, nullptr, nullptr); ChipLogProgress(DeviceLayer, "wpa_supplicant: added network: %s", mWpaSupplicant.networkPath); - wpa_fi_w1_wpa_supplicant1_interface_call_select_network(mWpaSupplicant.iface, mWpaSupplicant.networkPath, nullptr, - _ConnectWiFiNetworkAsyncCallback, this); + wpa_fi_w1_wpa_supplicant1_interface_call_select_network( + mWpaSupplicant.iface, mWpaSupplicant.networkPath, nullptr, + reinterpret_cast( + +[](GObject * sourceObject_, GAsyncResult * res_, ConnectivityManagerImpl * self) { + return self->_ConnectWiFiNetworkAsyncCallback(sourceObject_, res_); + }), + this); + mpConnectCallback = apCallback; } else @@ -1040,7 +1081,7 @@ ConnectivityManagerImpl::_ConnectWiFiNetworkAsync(GVariant * args, if (mWpaSupplicant.networkPath) { - g_object_unref(mWpaSupplicant.networkPath); + g_free(mWpaSupplicant.networkPath); mWpaSupplicant.networkPath = nullptr; } @@ -1191,9 +1232,8 @@ CHIP_ERROR ConnectivityManagerImpl::ConnectWiFiNetworkWithPDCAsync( } #endif // CHIP_DEVICE_CONFIG_ENABLE_WIFI_PDC -void ConnectivityManagerImpl::_ConnectWiFiNetworkAsyncCallback(GObject * source_object, GAsyncResult * res, gpointer user_data) +void ConnectivityManagerImpl::_ConnectWiFiNetworkAsyncCallback(GObject * sourceObject, GAsyncResult * res) { - ConnectivityManagerImpl * this_ = reinterpret_cast(user_data); GAutoPtr err; std::lock_guard lock(mWpaSupplicantMutex); @@ -1204,12 +1244,12 @@ void ConnectivityManagerImpl::_ConnectWiFiNetworkAsyncCallback(GObject * source_ if (!result) { ChipLogError(DeviceLayer, "Failed to perform connect network: %s", err == nullptr ? "unknown error" : err->message); - DeviceLayer::SystemLayer().ScheduleLambda([this_]() { + DeviceLayer::SystemLayer().ScheduleLambda([this]() { if (mpConnectCallback != nullptr) { // TODO(#14175): Replace this with actual thread attach result. - this_->mpConnectCallback->OnResult(NetworkCommissioning::Status::kUnknownError, CharSpan(), 0); - this_->mpConnectCallback = nullptr; + mpConnectCallback->OnResult(NetworkCommissioning::Status::kUnknownError, CharSpan(), 0); + mpConnectCallback = nullptr; } mpConnectCallback = nullptr; }); @@ -1796,7 +1836,7 @@ bool ConnectivityManagerImpl::_GetBssInfo(const gchar * bssPath, NetworkCommissi return true; } -void ConnectivityManagerImpl::_OnWpaInterfaceScanDone(GObject * source_object, GAsyncResult * res, gpointer user_data) +void ConnectivityManagerImpl::_OnWpaInterfaceScanDone(WpaFiW1Wpa_supplicant1Interface * proxy, gboolean success) { std::lock_guard lock(mWpaSupplicantMutex); @@ -1806,7 +1846,7 @@ void ConnectivityManagerImpl::_OnWpaInterfaceScanDone(GObject * source_object, G if (bsss == nullptr) { ChipLogProgress(DeviceLayer, "wpa_supplicant: no network found"); - DeviceLayer::SystemLayer().ScheduleLambda([]() { + DeviceLayer::SystemLayer().ScheduleLambda([this]() { if (mpScanCallback != nullptr) { mpScanCallback->OnFinished(Status::kSuccess, CharSpan(), nullptr); @@ -1833,7 +1873,7 @@ void ConnectivityManagerImpl::_OnWpaInterfaceScanDone(GObject * source_object, G } } - DeviceLayer::SystemLayer().ScheduleLambda([networkScanned]() { + DeviceLayer::SystemLayer().ScheduleLambda([this, networkScanned]() { // Note: We cannot post a event in ScheduleLambda since std::vector is not trivial copiable. This results in the use of // const_cast but should be fine for almost all cases, since we actually handled the ownership of this element to this // lambda. @@ -1850,15 +1890,19 @@ void ConnectivityManagerImpl::_OnWpaInterfaceScanDone(GObject * source_object, G g_strfreev(oldBsss); } -CHIP_ERROR ConnectivityManagerImpl::_StartWiFiManagement(ConnectivityManagerImpl * self) +CHIP_ERROR ConnectivityManagerImpl::_StartWiFiManagement() { // When creating D-Bus proxy object, the thread default context must be initialized. Otherwise, // all D-Bus signals will be delivered to the GLib global default main context. VerifyOrDie(g_main_context_get_thread_default() != nullptr); ChipLogProgress(DeviceLayer, "wpa_supplicant: Start WiFi management"); - wpa_fi_w1_wpa_supplicant1_proxy_new_for_bus(G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE, kWpaSupplicantServiceName, - kWpaSupplicantObjectPath, nullptr, self->_OnWpaProxyReady, nullptr); + wpa_fi_w1_wpa_supplicant1_proxy_new_for_bus( + G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE, kWpaSupplicantServiceName, kWpaSupplicantObjectPath, nullptr, + reinterpret_cast(+[](GObject * sourceObject_, GAsyncResult * res_, ConnectivityManagerImpl * self) { + return self->_OnWpaProxyReady(sourceObject_, res_); + }), + this); return CHIP_NO_ERROR; } diff --git a/src/platform/Linux/ConnectivityManagerImpl.h b/src/platform/Linux/ConnectivityManagerImpl.h index 930b84fb4d455b..26d6172ad438eb 100644 --- a/src/platform/Linux/ConnectivityManagerImpl.h +++ b/src/platform/Linux/ConnectivityManagerImpl.h @@ -155,14 +155,14 @@ class ConnectivityManagerImpl final : public ConnectivityManager, CHIP_ERROR _ConnectWiFiNetworkAsync(GVariant * networkArgs, NetworkCommissioning::Internal::WirelessDriver::ConnectCallback * connectCallback) CHIP_REQUIRES(mWpaSupplicantMutex); - static void _ConnectWiFiNetworkAsyncCallback(GObject * source_object, GAsyncResult * res, gpointer user_data); + void _ConnectWiFiNetworkAsyncCallback(GObject * sourceObject, GAsyncResult * res); #endif public: const char * GetEthernetIfName() { return (mEthIfName[0] == '\0') ? nullptr : mEthIfName; } #if CHIP_DEVICE_CONFIG_ENABLE_WIFI - static const char * GetWiFiIfName() { return (sWiFiIfName[0] == '\0') ? nullptr : sWiFiIfName; } + const char * GetWiFiIfName() { return (sWiFiIfName[0] == '\0') ? nullptr : sWiFiIfName; } #endif private: @@ -205,29 +205,27 @@ class ConnectivityManagerImpl final : public ConnectivityManager, System::Clock::Timeout _GetWiFiAPIdleTimeout(); void _SetWiFiAPIdleTimeout(System::Clock::Timeout val); void UpdateNetworkStatus(); - static CHIP_ERROR StopAutoScan(); - - static void _OnWpaProxyReady(GObject * source_object, GAsyncResult * res, gpointer user_data); - static void _OnWpaInterfaceRemoved(WpaFiW1Wpa_supplicant1 * proxy, const gchar * path, GVariant * properties, - gpointer user_data); - static void _OnWpaInterfaceAdded(WpaFiW1Wpa_supplicant1 * proxy, const gchar * path, GVariant * properties, gpointer user_data); - static void _OnWpaPropertiesChanged(WpaFiW1Wpa_supplicant1Interface * proxy, GVariant * changed_properties, - const gchar * const * invalidated_properties, gpointer user_data); - static void _OnWpaInterfaceReady(GObject * source_object, GAsyncResult * res, gpointer user_data); - static void _OnWpaInterfaceProxyReady(GObject * source_object, GAsyncResult * res, gpointer user_data); - static void _OnWpaBssProxyReady(GObject * source_object, GAsyncResult * res, gpointer user_data); - static void _OnWpaInterfaceScanDone(GObject * source_object, GAsyncResult * res, gpointer user_data); - - static bool _GetBssInfo(const gchar * bssPath, NetworkCommissioning::WiFiScanResponse & result); - - static CHIP_ERROR _StartWiFiManagement(ConnectivityManagerImpl * self); - - static bool mAssociationStarted; - static BitFlags mConnectivityFlag; - static GDBusWpaSupplicant mWpaSupplicant CHIP_GUARDED_BY(mWpaSupplicantMutex); + CHIP_ERROR StopAutoScan(); + + void _OnWpaProxyReady(GObject * sourceObject, GAsyncResult * res); + void _OnWpaInterfaceRemoved(WpaFiW1Wpa_supplicant1 * proxy, const char * path, GVariant * properties); + void _OnWpaInterfaceAdded(WpaFiW1Wpa_supplicant1 * proxy, const char * path, GVariant * properties); + void _OnWpaPropertiesChanged(WpaFiW1Wpa_supplicant1Interface * proxy, GVariant * properties); + void _OnWpaInterfaceScanDone(WpaFiW1Wpa_supplicant1Interface * proxy, gboolean success); + void _OnWpaInterfaceReady(GObject * sourceObject, GAsyncResult * res); + void _OnWpaInterfaceProxyReady(GObject * sourceObject, GAsyncResult * res); + void _OnWpaBssProxyReady(GObject * sourceObject, GAsyncResult * res); + + bool _GetBssInfo(const gchar * bssPath, NetworkCommissioning::WiFiScanResponse & result); + + CHIP_ERROR _StartWiFiManagement(); + + bool mAssociationStarted = false; + BitFlags mConnectivityFlag; + GDBusWpaSupplicant mWpaSupplicant CHIP_GUARDED_BY(mWpaSupplicantMutex); // Access to mWpaSupplicant has to be protected by a mutex because it is accessed from // the CHIP event loop thread and dedicated D-Bus thread started by platform manager. - static std::mutex mWpaSupplicantMutex; + std::mutex mWpaSupplicantMutex; NetworkCommissioning::Internal::BaseDriver::NetworkStatusChangeCallback * mpStatusChangeCallback = nullptr; #endif @@ -262,13 +260,15 @@ class ConnectivityManagerImpl final : public ConnectivityManager, #endif #if CHIP_DEVICE_CONFIG_ENABLE_WIFI - static char sWiFiIfName[IFNAMSIZ]; + char sWiFiIfName[IFNAMSIZ]; #endif - static uint8_t sInterestedSSID[Internal::kMaxWiFiSSIDLength]; - static uint8_t sInterestedSSIDLen; - static NetworkCommissioning::WiFiDriver::ScanCallback * mpScanCallback; - static NetworkCommissioning::Internal::WirelessDriver::ConnectCallback * mpConnectCallback; +#if CHIP_DEVICE_CONFIG_ENABLE_WPA + uint8_t sInterestedSSID[Internal::kMaxWiFiSSIDLength]; + uint8_t sInterestedSSIDLen; +#endif + NetworkCommissioning::WiFiDriver::ScanCallback * mpScanCallback; + NetworkCommissioning::Internal::WirelessDriver::ConnectCallback * mpConnectCallback; }; #if CHIP_DEVICE_CONFIG_ENABLE_WPA diff --git a/src/platform/Linux/PlatformManagerImpl.cpp b/src/platform/Linux/PlatformManagerImpl.cpp index 0098eb01ae96eb..401d72bbe413bd 100644 --- a/src/platform/Linux/PlatformManagerImpl.cpp +++ b/src/platform/Linux/PlatformManagerImpl.cpp @@ -108,13 +108,13 @@ gboolean WiFiIPChangeListener(GIOChannel * ch, GIOCondition /* condition */, voi continue; } - if (ConnectivityManagerImpl::GetWiFiIfName() == nullptr) + if (ConnectivityMgrImpl().GetWiFiIfName() == nullptr) { ChipLogDetail(DeviceLayer, "No wifi interface name. Ignoring IP update event."); continue; } - if (strcmp(name, ConnectivityManagerImpl::GetWiFiIfName()) != 0) + if (strcmp(name, ConnectivityMgrImpl().GetWiFiIfName()) != 0) { continue; } From 70e08ecf85298034e8592842442fb648b53f37e9 Mon Sep 17 00:00:00 2001 From: simonhmorris1 <112178216+simonhmorris1@users.noreply.github.com> Date: Mon, 19 Feb 2024 22:48:23 +0000 Subject: [PATCH 025/385] Update TC-DD-3.2/3.6/3.8 Non-Concurrent(#31751) (#31760) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Update TC-DD-3.2/3.6/3.8 Non-Concurrent(#31751) * Restyled by whitespace * Restyled by prettier-yaml * Update src/app/tests/suites/certification/Test_TC_DD_3_8.yaml Co-authored-by: Damian Królik <66667989+Damian-Nordic@users.noreply.github.com> --------- Co-authored-by: Restyled.io Co-authored-by: Damian Królik <66667989+Damian-Nordic@users.noreply.github.com> --- .../suites/certification/Test_TC_DD_3_2.yaml | 481 ++++++++++-------- .../suites/certification/Test_TC_DD_3_6.yaml | 108 ++-- .../suites/certification/Test_TC_DD_3_8.yaml | 44 +- 3 files changed, 361 insertions(+), 272 deletions(-) diff --git a/src/app/tests/suites/certification/Test_TC_DD_3_2.yaml b/src/app/tests/suites/certification/Test_TC_DD_3_2.yaml index 4814d35ee82829..514d9375b11251 100644 --- a/src/app/tests/suites/certification/Test_TC_DD_3_2.yaml +++ b/src/app/tests/suites/certification/Test_TC_DD_3_2.yaml @@ -37,9 +37,10 @@ tests: verification: | Verify in DUT(ALL-CLUSTER-APP) start BLE Advertising by specific DUT implementation - Verify in TH (CHIP-TOOL) start commissioning process(need to obtain the Thread dataset first) + Verify in TH (CHIP-TOOL) start commissioning process (either Thread or WiFi) ./chip-tool pairing ble-thread 1 hex:0e080000000000010000000300000f35060004001fffe0020811111111222222220708fd27e57b1b1e22d9051000112233445566778899aabbccddeeff030e4f70656e54687265616444656d6f01021234041061e1206d2c2b46e079eb775f41fc72190c0402a0fff8 20202021 3840 + ./chip-tool pairing ble-wifi 20202021 3840 disabled: true - label: @@ -51,6 +52,38 @@ tests: CHIP:SC: Received PBKDF param response disabled: true + - label: + "Step 2a: Commissioner reads General Commissioning cluster attribute + SupportsConcurrentConnection" + verification: | + Verify in TH(CHIP-TOOL) + CHIP:DMG: AttributeReportIB = + CHIP:DMG: { + CHIP:DMG: AttributeDataIB = + CHIP:DMG: { + CHIP:DMG: DataVersion = 0xb0556660, + CHIP:DMG: AttributePathIB = + CHIP:DMG: { + CHIP:DMG: Endpoint = 0x0, + CHIP:DMG: Cluster = 0x30, + CHIP:DMG: Attribute = 0x0000_0004, + CHIP:DMG: } + CHIP:DMG: + CHIP:DMG: Data = false, + CHIP:DMG: }, + CHIP:DMG: + CHIP:DMG: }, + CHIP:DMG: + CHIP:DMG: ], + CHIP:DMG: + CHIP:DMG: SuppressResponse = true, + CHIP:DMG: InteractionModelRevision = 11 + CHIP:DMG: } + CHIP:CTL: ----- NetworkCommissioning Features: has WiFi. endpointid = 0 + CHIP:SVR: OnReadCommissioningInfo - vendorId=0xFFF1 productId=0x8001 + CHIP:CTL: Successfully finished commissioning step 'ReadCommissioningInfo2' + disabled: true + - label: "Step 3: Commissioner SHALL re-arm Fail-safe timer on Commissionee within 60s (the autonomously Fail-safe timer length set by @@ -76,63 +109,68 @@ tests: OperationalCSRRequest command" verification: | Verify in TH(CHIP-TOOL) - - CHIP:CTL: Sending CSR request to 0xffffa4001730 device + CHIP:CTL: Sending CSR request to 0xffff7fe56480 device CHIP:DMG: ICR moving to [AddingComm] CHIP:DMG: ICR moving to [AddedComma] - CHIP:IN: Prepared secure message 0xffffb9ba6db8 to 0x0000000000000001 (1) of type 0x8 and protocolId (0, 1) on exchange 45042i with MessageCounter:12011388. - CHIP:IN: Sending encrypted msg 0xffffb9ba6db8 with MessageCounter:12011388 to 0x0000000000000001 (1) at monotonic time: 304120 msec - CHIP:DMG: ICR moving to [CommandSen] + CHIP:EM: <<< [E:11057i S:28473 M:98750543] (S) Msg TX to 0:FFFFFFFB00000000 [0000] [BLE] --- Type 0001:08 (IM:InvokeCommandRequest) + CHIP:DMG: ICR moving to [AwaitingRe] CHIP:CTL: Sent CSR request, waiting for the CSR CHIP:DMG: ICR moving to [AwaitingDe] + CHIP:DL: Long dispatch time: 118 ms, for event type 16389 CHIP:DL: HandlePlatformSpecificBLEEvent 16387 - CHIP:DL: Indication received, conn = 0xffffb0044210 + CHIP:DL: Indication received, conn = 0xffff81218b30 CHIP:DL: HandlePlatformSpecificBLEEvent 16389 - CHIP:DL: Indication received, conn = 0xffffb0044210 + CHIP:DL: Indication received, conn = 0xffff81218b30 CHIP:DL: HandlePlatformSpecificBLEEvent 16389 - CHIP:EM: Received message of type 0x9 with protocolId (0, 1) and MessageCounter:8508040 on exchange 45042i - CHIP:EM: Found matching exchange: 45042i, Delegate: 0xffffb0040000 + CHIP:EM: >>> [E:11057i S:28473 M:31913565] (S) Msg RX from 0:FFFFFFFB00000000 [0000] --- Type 0001:09 (IM:InvokeCommandResponse) + CHIP:EM: Found matching exchange: 11057i, Delegate: 0xffff78c217c8 CHIP:DMG: ICR moving to [ResponseRe] CHIP:DMG: InvokeResponseMessage = CHIP:DMG: { - CHIP:DMG: suppressResponse = false, - CHIP:DMG: InvokeResponseIBs = - CHIP:DMG: [ - CHIP:DMG: InvokeResponseIB = - CHIP:DMG: { - CHIP:DMG: CommandDataIB = - CHIP:DMG: { - CHIP:DMG: CommandPathIB = - CHIP:DMG: { - CHIP:DMG: EndpointId = 0x0, - CHIP:DMG: ClusterId = 0x3e, - CHIP:DMG: CommandId = 0x5, - CHIP:DMG: }, + CHIP:DMG: suppressResponse = false, + CHIP:DMG: InvokeResponseIBs = + CHIP:DMG: [ + CHIP:DMG: InvokeResponseIB = + CHIP:DMG: { + CHIP:DMG: CommandDataIB = + CHIP:DMG: { + CHIP:DMG: CommandPathIB = + CHIP:DMG: { + CHIP:DMG: EndpointId = 0x0, + CHIP:DMG: ClusterId = 0x3e, + CHIP:DMG: CommandId = 0x5, + CHIP:DMG: }, CHIP:DMG: - CHIP:DMG: CommandData = - CHIP:DMG: { - CHIP:DMG: 0x0 = [ - CHIP:DMG: 0x15, 0x30, 0x1, 0xcd, 0x30, 0x81, 0xca, 0x30, 0x70, 0x2, 0x1, 0x0, 0x30, 0xe, 0x31, 0xc, 0x30, 0xa, 0x6, 0x3, 0x55, 0x4, 0xa, 0xc, 0x3, 0x43, 0x53, 0x52, 0x30, 0x59, 0x30, 0x13, 0x6, 0x7, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x2, 0x1, 0x6, 0x8, 0x2a, 0x86 - CHIP:DMG: ] - CHIP:DMG: 0x1 = [ - CHIP:DMG: 0xea, 0xd6, 0x96, 0x53, 0x4d, 0x46, 0x1d, 0xd6, 0xcc, 0x7f, 0x25, 0x50, 0x80, 0x4c, 0x2a, 0xe9, 0xc8, 0xb8, 0x1b, 0x34, 0xca, 0x98, 0x38, 0x42, 0x74, 0xc2, 0x13, 0xf4, 0x10, 0x4d, 0xa2, 0x44, 0x38, 0x98, 0x28, 0xb6, 0xb1, 0x94, 0x6b, 0xd, 0x29, 0x1b - CHIP:DMG: ] - CHIP:DMG: }, - CHIP:DMG: }, + CHIP:DMG: CommandFields = + CHIP:DMG: { + CHIP:DMG: 0x0 = [ + CHIP:DMG: 0x15, 0x30, 0x01, 0xca, 0x30, 0x81, 0xc7, 0x30, 0x70, 0x02, 0x01, 0x00, 0x30, 0x0e, 0x31, 0x0c, 0x30, 0x0a, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x03, 0x43, 0x53, 0x52, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0xf1, 0xa2, 0x66, 0x01, 0xf7, 0xec, 0x41, 0x11, 0x82, 0x3f, 0xf6, 0x8f, 0x94, 0xe6, 0xeb, 0xe6, 0x6e, 0x6b, 0xbb, 0x2b, 0xad, 0x19, 0x7e, 0xb8, 0x11, 0xbb, 0xc8, 0xc8, 0xf8, 0x59, 0x73, 0x10, 0xd7, 0xff, 0x61, 0x01, 0x0e, 0x7d, 0x50, 0x6e, 0x9d, 0x66, 0xd3, 0x89, 0x83, 0x84, 0xfe, 0xe0, 0xee, 0x7b, 0xbf, 0xaa, 0xa6, 0x3c, 0x60, 0x0a, 0x8e, 0xda, 0xb1, 0xfc, 0xa4, 0xf5, 0xf2, 0xcb, 0xa0, 0x00, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x03, 0x47, 0x00, 0x30, 0x44, 0x02, 0x20, 0x23, 0x94, 0xd8, 0xc4, 0x00, 0x9a, 0xec, 0x9c, 0x0e, 0x11, 0x26, 0x7f, 0x9e, 0xea, 0x7b, 0xe3, 0x83, 0xde, 0xf8, 0xd3, 0xd3, 0xe7, 0x31, 0xeb, 0x3c, 0xf5, 0x73, 0x65, 0xcd, 0xd8, 0xc0, 0x48, 0x02, 0x20, 0x63, 0x5a, 0x67, 0x85, 0x71, 0xa9, 0x50, 0x30, 0x8e, 0x4c, 0x00, 0x0e, 0x65, 0x1e, 0x59, 0x53, 0x85, 0xb2, 0x6f, 0x5a, 0x01, 0x46, 0xda, 0xb5, 0x27, 0xea, 0x6b, 0x5c, 0x8a, 0x82, 0x48, 0x5e, 0x30, 0x02, 0x20, 0x08, 0x9b, 0x9c, 0xe3, 0xa4, 0xfd, 0xdb, 0xc5, 0xbd, 0x78, 0x36, 0x7c, 0x47, 0xd9, 0xaf, 0x57, 0x22, 0x5a, 0x70, 0xa8, 0x14, 0x86, 0xdd, 0xea, 0x1b, 0x44, 0x80, 0xbd, 0x39, 0x4f, 0xca, 0x76, 0x18, + CHIP:DMG: ] (242 bytes) + CHIP:DMG: 0x1 = [ + CHIP:DMG: 0xc1, 0xa1, 0xf7, 0xba, 0xe4, 0x5f, 0xd5, 0x62, 0x06, 0xb9, 0xe7, 0xf3, 0x64, 0x47, 0x36, 0x6f, 0xcb, 0xf5, 0x74, 0x97, 0x61, 0xf1, 0x54, 0xbc, 0x9a, 0x6c, 0x1b, 0x60, 0xa7, 0xf0, 0xb6, 0x5e, 0x9b, 0x05, 0x06, 0xd8, 0x9f, 0x0e, 0x47, 0xd9, 0x3a, 0xbf, 0x8d, 0x71, 0x61, 0xd4, 0xcf, 0xee, 0x38, 0x64, 0x0d, 0xc0, 0xf8, 0x44, 0xe7, 0x77, 0x08, 0x7d, 0x6b, 0x20, 0x1e, 0x40, 0x1f, 0x94, + CHIP:DMG: ] (64 bytes) + CHIP:DMG: }, + CHIP:DMG: }, CHIP:DMG: - CHIP:DMG: }, + CHIP:DMG: }, CHIP:DMG: - CHIP:DMG: ], + CHIP:DMG: ], CHIP:DMG: - CHIP:DMG: InteractionModelRevision = 1 + CHIP:DMG: InteractionModelRevision = 11 CHIP:DMG: }, CHIP:DMG: Received Command Response Data, Endpoint=0 Cluster=0x0000_003E Command=0x0000_0005 CHIP:CTL: Received certificate signing request from the device + CHIP:CTL: Successfully finished commissioning step 'SendOpCertSigningRequest' + CHIP:CTL: Commissioning stage next step: 'SendOpCertSigningRequest' -> 'ValidateCSR' + CHIP:CTL: Performing next commissioning step 'ValidateCSR' + CHIP:CTL: Successfully finished commissioning step 'ValidateCSR' + CHIP:CTL: Commissioning stage next step: 'ValidateCSR' -> 'GenerateNOCChain' + CHIP:CTL: Performing next commissioning step 'GenerateNOCChain' CHIP:CTL: Getting certificate chain for the device from the issuer CHIP:CTL: Verifying Certificate Signing Request CHIP:CTL: Generating NOC CHIP:CTL: Providing certificate chain to the commissioner - CHIP:CTL: Received callback from the CA for NOC Chain generation. Status ../../src/controller/ExampleOperationalCredentialsIssuer.cpp:225: Success + CHIP:CTL: Received callback from the CA for NOC Chain generation. Status src/controller/ExampleOperationalCredentialsIssuer.cpp:395: Success disabled: true - label: @@ -141,49 +179,48 @@ tests: verification: | Verify in TH(CHIP-TOOL) - [1651218829.220063][3273:3278] CHIP:CTL: Sending root certificate to the device - [1651218829.220201][3273:3278] CHIP:DMG: ICR moving to [AddingComm] - [1651218829.222415][3273:3278] CHIP:DMG: ICR moving to [AddedComma] - [1651218829.222549][3273:3278] CHIP:IN: Prepared secure message 0xffffb9ba6b98 to 0x0000000000000001 (1) of type 0x8 and protocolId (0, 1) on exchange 45043i with MessageCounter:12011389. - [1651218829.222616][3273:3278] CHIP:IN: Sending encrypted msg 0xffffb9ba6b98 with MessageCounter:12011389 to 0x0000000000000001 (1) at monotonic time: 305872 msec - [1651218829.222746][3273:3278] CHIP:DMG: ICR moving to [CommandSen] - [1651218829.222789][3273:3278] CHIP:CTL: Sent root certificate to the device - [1651218829.223121][3273:3278] CHIP:DMG: ICR moving to [AwaitingDe] - [1651218829.306861][3273:3278] CHIP:DL: HandlePlatformSpecificBLEEvent 16387 - [1651218829.404144][3273:3278] CHIP:DL: HandlePlatformSpecificBLEEvent 16387 - [1651218829.454121][3273:3276] CHIP:DL: Indication received, conn = 0xffffb0044210 - [1651218829.454352][3273:3278] CHIP:DL: HandlePlatformSpecificBLEEvent 16389 - CHIP:EM: Received message of type 0x9 with protocolId (0, 1) and MessageCounter:8508041 on exchange 45043i - CHIP:EM: Found matching exchange: 45043i, Delegate: 0xffffa400def0 + CHIP:CTL: Sending root certificate to the device + CHIP:DMG: ICR moving to [AddingComm] + CHIP:DMG: ICR moving to [AddedComma] + CHIP:EM: <<< [E:11058i S:28473 M:98750544] (S) Msg TX to 0:FFFFFFFB00000000 [0000] [BLE] --- Type 0001:08 (IM:InvokeCommandRequest) + CHIP:DMG: ICR moving to [AwaitingRe] + CHIP:CTL: Sent root certificate to the device + CHIP:DMG: ICR moving to [AwaitingDe] + CHIP:DL: HandlePlatformSpecificBLEEvent 16387 + CHIP:DL: HandlePlatformSpecificBLEEvent 16387 + CHIP:DL: Indication received, conn = 0xffff81218b30 + CHIP:DL: HandlePlatformSpecificBLEEvent 16389 + CHIP:EM: >>> [E:11058i S:28473 M:31913566] (S) Msg RX from 0:FFFFFFFB00000000 [0000] --- Type 0001:09 (IM:InvokeCommandResponse) + CHIP:EM: Found matching exchange: 11058i, Delegate: 0xffff78c20b88 CHIP:DMG: ICR moving to [ResponseRe] CHIP:DMG: InvokeResponseMessage = CHIP:DMG: { - CHIP:DMG: suppressResponse = false, - CHIP:DMG: InvokeResponseIBs = - CHIP:DMG: [ - CHIP:DMG: InvokeResponseIB = - CHIP:DMG: { - CHIP:DMG: CommandStatusIB = - CHIP:DMG: { - CHIP:DMG: CommandPathIB = - CHIP:DMG: { - CHIP:DMG: EndpointId = 0x0, - CHIP:DMG: ClusterId = 0x3e, - CHIP:DMG: CommandId = 0xb, - CHIP:DMG: }, + CHIP:DMG: suppressResponse = false, + CHIP:DMG: InvokeResponseIBs = + CHIP:DMG: [ + CHIP:DMG: InvokeResponseIB = + CHIP:DMG: { + CHIP:DMG: CommandStatusIB = + CHIP:DMG: { + CHIP:DMG: CommandPathIB = + CHIP:DMG: { + CHIP:DMG: EndpointId = 0x0, + CHIP:DMG: ClusterId = 0x3e, + CHIP:DMG: CommandId = 0xb, + CHIP:DMG: }, CHIP:DMG: - CHIP:DMG: StatusIB = - CHIP:DMG: { - CHIP:DMG: status = 0x0, - CHIP:DMG: }, + CHIP:DMG: StatusIB = + CHIP:DMG: { + CHIP:DMG: status = 0x00 (SUCCESS), + CHIP:DMG: }, CHIP:DMG: - CHIP:DMG: }, + CHIP:DMG: }, CHIP:DMG: - CHIP:DMG: }, + CHIP:DMG: }, CHIP:DMG: - CHIP:DMG: ], + CHIP:DMG: ], CHIP:DMG: - CHIP:DMG: InteractionModelRevision = 1 + CHIP:DMG: InteractionModelRevision = 11 CHIP:DMG: }, CHIP:DMG: Received Command Response Status for Endpoint=0 Cluster=0x0000_003E Command=0x0000_000B Status=0x0 CHIP:CTL: Device confirmed that it has received the root certificate @@ -195,54 +232,53 @@ tests: verification: | Verify in TH(CHIP-TOOL) - [1651218829.457248][3273:3278] CHIP:CTL: Sending operational certificate chain to the device - [1651218829.457372][3273:3278] CHIP:DMG: ICR moving to [AddingComm] - [1651218829.460013][3273:3278] CHIP:DMG: ICR moving to [AddedComma] - [1651218829.460273][3273:3278] CHIP:IN: Prepared secure message 0xffffb9ba7828 to 0x0000000000000001 (1) of type 0x8 and protocolId (0, 1) on exchange 45044i with MessageCounter:12011390. - [1651218829.460374][3273:3278] CHIP:IN: Sending encrypted msg 0xffffb9ba7828 with MessageCounter:12011390 to 0x0000000000000001 (1) at monotonic time: 306110 msec - [1651218829.460602][3273:3278] CHIP:DMG: ICR moving to [CommandSen] - [1651218829.460684][3273:3278] CHIP:CTL: Sent operational certificate to the device - [1651218829.460778][3273:3278] CHIP:DMG: ICR moving to [AwaitingDe] - [1651218829.550574][3273:3278] CHIP:DL: HandlePlatformSpecificBLEEvent 16387 - [1651218829.648065][3273:3278] CHIP:DL: HandlePlatformSpecificBLEEvent 16387 - [1651218829.745594][3273:3278] CHIP:DL: HandlePlatformSpecificBLEEvent 16387 - [1651218833.988087][3273:3276] CHIP:DL: Indication received, conn = 0xffffb0044210 - [1651218833.988336][3273:3278] CHIP:DL: HandlePlatformSpecificBLEEvent 16389 - [1651218833.988598][3273:3278] CHIP:EM: Received message of type 0x9 with protocolId (0, 1) and MessageCounter:8508042 on exchange 45044i - CHIP:EM: Found matching exchange: 45044i, Delegate: 0xffffb0040000 + CHIP:CTL: Performing next commissioning step 'SendNOC' + CHIP:DMG: ICR moving to [AddingComm] + CHIP:DMG: ICR moving to [AddedComma] + CHIP:EM: <<< [E:11059i S:28473 M:98750545] (S) Msg TX to 0:FFFFFFFB00000000 [0000] [BLE] --- Type 0001:08 (IM:InvokeCommandRequest) + CHIP:DMG: ICR moving to [AwaitingRe] + CHIP:CTL: Sent operational certificate to the device + CHIP:DMG: ICR moving to [AwaitingDe] + CHIP:DL: HandlePlatformSpecificBLEEvent 16387 + CHIP:DL: HandlePlatformSpecificBLEEvent 16387 + CHIP:DL: HandlePlatformSpecificBLEEvent 16387 + CHIP:DL: Indication received, conn = 0xffff81218b30 + CHIP:DL: HandlePlatformSpecificBLEEvent 16389 + CHIP:EM: >>> [E:11059i S:28473 M:31913567] (S) Msg RX from 0:FFFFFFFB00000000 [0000] --- Type 0001:09 (IM:InvokeCommandResponse) + CHIP:EM: Found matching exchange: 11059i, Delegate: 0xffff78c209c8 CHIP:DMG: ICR moving to [ResponseRe] CHIP:DMG: InvokeResponseMessage = CHIP:DMG: { - CHIP:DMG: suppressResponse = false, - CHIP:DMG: InvokeResponseIBs = - CHIP:DMG: [ - CHIP:DMG: InvokeResponseIB = - CHIP:DMG: { - CHIP:DMG: CommandDataIB = - CHIP:DMG: { - CHIP:DMG: CommandPathIB = - CHIP:DMG: { - CHIP:DMG: EndpointId = 0x0, - CHIP:DMG: ClusterId = 0x3e, - CHIP:DMG: CommandId = 0x8, - CHIP:DMG: }, + CHIP:DMG: suppressResponse = false, + CHIP:DMG: InvokeResponseIBs = + CHIP:DMG: [ + CHIP:DMG: InvokeResponseIB = + CHIP:DMG: { + CHIP:DMG: CommandDataIB = + CHIP:DMG: { + CHIP:DMG: CommandPathIB = + CHIP:DMG: { + CHIP:DMG: EndpointId = 0x0, + CHIP:DMG: ClusterId = 0x3e, + CHIP:DMG: CommandId = 0x8, + CHIP:DMG: }, CHIP:DMG: - CHIP:DMG: CommandData = - CHIP:DMG: { - CHIP:DMG: 0x0 = 0, - CHIP:DMG: 0x1 = 1, - CHIP:DMG: }, - CHIP:DMG: }, + CHIP:DMG: CommandFields = + CHIP:DMG: { + CHIP:DMG: 0x0 = 0, + CHIP:DMG: 0x1 = 1, + CHIP:DMG: }, + CHIP:DMG: }, CHIP:DMG: - CHIP:DMG: }, + CHIP:DMG: }, CHIP:DMG: - CHIP:DMG: ], + CHIP:DMG: ], CHIP:DMG: - CHIP:DMG: InteractionModelRevision = 1 + CHIP:DMG: InteractionModelRevision = 11 CHIP:DMG: }, CHIP:DMG: Received Command Response Data, Endpoint=0 Cluster=0x0000_003E Command=0x0000_0008 CHIP:CTL: Device returned status 0 on receiving the NOC - CHIP:CTL: Operational credentials provisioned on device 0xffffa4001730 + CHIP:CTL: Operational credentials provisioned on device 0xffff7fe56480 disabled: true - label: @@ -251,50 +287,49 @@ tests: verification: | Verify in TH(CHIP-TOOL) - [1651218833.995054][3273:3278] CHIP:CTL: Adding thread network - [1651218833.995176][3273:3278] CHIP:DMG: ICR moving to [AddingComm] - [1651218833.995253][3273:3278] CHIP:DMG: ICR moving to [AddedComma] - [1651218833.995431][3273:3278] CHIP:IN: Prepared secure message 0xffffb9ba7848 to 0x0000000000000001 (1) of type 0x8 and protocolId (0, 1) on exchange 45045i with MessageCounter:12011391. - [1651218833.995523][3273:3278] CHIP:IN: Sending encrypted msg 0xffffb9ba7848 with MessageCounter:12011391 to 0x0000000000000001 (1) at monotonic time: 310645 msec - [1651218833.995723][3273:3278] CHIP:DMG: ICR moving to [CommandSen] - [1651218833.995823][3273:3278] CHIP:DMG: ICR moving to [AwaitingDe] - [1651218834.084548][3273:3278] CHIP:DL: HandlePlatformSpecificBLEEvent 16387 - [1651218834.134690][3273:3276] CHIP:DL: Indication received, conn = 0xffffb0044210 - [1651218834.134918][3273:3278] CHIP:DL: HandlePlatformSpecificBLEEvent 16389 - CHIP:EM: Received message of type 0x9 with protocolId (0, 1) and MessageCounter:8508043 on exchange 45045i - CHIP:EM: Found matching exchange: 45045i, Delegate: 0xffffa400def0 + CHIP:CTL: Performing next commissioning step 'WiFiNetworkSetup' + CHIP:DMG: ICR moving to [AddingComm] + CHIP:DMG: ICR moving to [AddedComma] + CHIP:EM: <<< [E:11060i S:28473 M:98750546] (S) Msg TX to 0:FFFFFFFB00000000 [0000] [BLE] --- Type 0001:08 (IM:InvokeCommandRequest) + CHIP:DMG: ICR moving to [AwaitingRe] + CHIP:DMG: ICR moving to [AwaitingDe] + CHIP:DL: HandlePlatformSpecificBLEEvent 16387 + CHIP:DL: Indication received, conn = 0xffff81218b30 + CHIP:DL: HandlePlatformSpecificBLEEvent 16389 + CHIP:EM: >>> [E:11060i S:28473 M:31913568] (S) Msg RX from 0:FFFFFFFB00000000 [0000] --- Type 0001:09 (IM:InvokeCommandResponse) + CHIP:EM: Found matching exchange: 11060i, Delegate: 0xffff78c20808 CHIP:DMG: ICR moving to [ResponseRe] CHIP:DMG: InvokeResponseMessage = CHIP:DMG: { - CHIP:DMG: suppressResponse = false, - CHIP:DMG: InvokeResponseIBs = - CHIP:DMG: [ - CHIP:DMG: InvokeResponseIB = - CHIP:DMG: { - CHIP:DMG: CommandDataIB = - CHIP:DMG: { - CHIP:DMG: CommandPathIB = - CHIP:DMG: { - CHIP:DMG: EndpointId = 0x0, - CHIP:DMG: ClusterId = 0x31, - CHIP:DMG: CommandId = 0x5, - CHIP:DMG: }, + CHIP:DMG: suppressResponse = false, + CHIP:DMG: InvokeResponseIBs = + CHIP:DMG: [ + CHIP:DMG: InvokeResponseIB = + CHIP:DMG: { + CHIP:DMG: CommandDataIB = + CHIP:DMG: { + CHIP:DMG: CommandPathIB = + CHIP:DMG: { + CHIP:DMG: EndpointId = 0x0, + CHIP:DMG: ClusterId = 0x31, + CHIP:DMG: CommandId = 0x5, + CHIP:DMG: }, CHIP:DMG: - CHIP:DMG: CommandData = - CHIP:DMG: { - CHIP:DMG: 0x0 = 0, - CHIP:DMG: 0x1 = "", - CHIP:DMG: }, - CHIP:DMG: }, + CHIP:DMG: CommandFields = + CHIP:DMG: { + CHIP:DMG: 0x0 = 0, + CHIP:DMG: 0x2 = 0, + CHIP:DMG: }, + CHIP:DMG: }, CHIP:DMG: - CHIP:DMG: }, + CHIP:DMG: }, CHIP:DMG: - CHIP:DMG: ], + CHIP:DMG: ], CHIP:DMG: - CHIP:DMG: InteractionModelRevision = 1 + CHIP:DMG: InteractionModelRevision = 11 CHIP:DMG: }, CHIP:DMG: Received Command Response Data, Endpoint=0 Cluster=0x0000_0031 Command=0x0000_0005 - CHIP:CTL: Received NetworkConfig response + CHIP:CTL: Received NetworkConfig response, networkingStatus=0 disabled: true - label: @@ -303,118 +338,124 @@ tests: verification: | Verify in TH(CHIP-TOOL) - [1651218834.137891][3273:3278] CHIP:CTL: Enabling thread network - [1651218834.138014][3273:3278] CHIP:DMG: ICR moving to [AddingComm] - [1651218834.138086][3273:3278] CHIP:DMG: ICR moving to [AddedComma] - [1651218834.138236][3273:3278] CHIP:IN: Prepared secure message 0xffffb9ba7938 to 0x0000000000000001 (1) of type 0x8 and protocolId (0, 1) on exchange 45046i with MessageCounter:12011392. - [1651218834.138325][3273:3278] CHIP:IN: Sending encrypted msg 0xffffb9ba7938 with MessageCounter:12011392 to 0x0000000000000001 (1) at monotonic time: 310788 msec - [1651218834.138522][3273:3278] CHIP:DMG: ICR moving to [CommandSen] - [1651218834.138628][3273:3278] CHIP:DMG: ICR moving to [AwaitingDe] - [1651218834.231701][3273:3278] CHIP:DL: HandlePlatformSpecificBLEEvent 16387 - [1651218834.426948][3273:3276] CHIP:DL: Indication received, conn = 0xffffb0044210 - [1651218834.427186][3273:3278] CHIP:DL: HandlePlatformSpecificBLEEvent 16389 - [1651218834.427443][3273:3278] CHIP:EM: Received message of type 0x9 with protocolId (0, 1) and MessageCounter:8508044 on exchange 45046i - CHIP:EM: Found matching exchange: 45046i, Delegate: 0xffffb0040000 + CHIP:CTL: SendCommand kWiFiNetworkEnable, supportsConcurrentConnection=0 + CHIP:DMG: ICR moving to [AddingComm] + CHIP:DMG: ICR moving to [AddedComma] + CHIP:EM: <<< [E:11062i S:28473 M:98750548] (S) Msg TX to 0:FFFFFFFB00000000 [0000] [BLE] --- Type 0001:08 (IM:InvokeCommandRequest) + CHIP:DMG: ICR moving to [AwaitingRe] + CHIP:DMG: ICR moving to [AwaitingDe] + CHIP:DL: HandlePlatformSpecificBLEEvent 16387 + CHIP:DL: Indication received, conn = 0xffff81218b30 + CHIP:DL: HandlePlatformSpecificBLEEvent 16389 + CHIP:EM: >>> [E:11062i S:28473 M:31913570] (S) Msg RX from 0:FFFFFFFB00000000 [0000] --- Type 0001:09 (IM:InvokeCommandResponse) + CHIP:EM: Found matching exchange: 11062i, Delegate: 0xffff78c20488 CHIP:DMG: ICR moving to [ResponseRe] CHIP:DMG: InvokeResponseMessage = CHIP:DMG: { - CHIP:DMG: suppressResponse = false, - CHIP:DMG: InvokeResponseIBs = - CHIP:DMG: [ - CHIP:DMG: InvokeResponseIB = - CHIP:DMG: { - CHIP:DMG: CommandDataIB = - CHIP:DMG: { - CHIP:DMG: CommandPathIB = - CHIP:DMG: { - CHIP:DMG: EndpointId = 0x0, - CHIP:DMG: ClusterId = 0x31, - CHIP:DMG: CommandId = 0x7, - CHIP:DMG: }, + CHIP:DMG: suppressResponse = false, + CHIP:DMG: InvokeResponseIBs = + CHIP:DMG: [ + CHIP:DMG: InvokeResponseIB = + CHIP:DMG: { + CHIP:DMG: CommandDataIB = + CHIP:DMG: { + CHIP:DMG: CommandPathIB = + CHIP:DMG: { + CHIP:DMG: EndpointId = 0x0, + CHIP:DMG: ClusterId = 0x31, + CHIP:DMG: CommandId = 0x7, + CHIP:DMG: }, CHIP:DMG: - CHIP:DMG: CommandData = - CHIP:DMG: { - CHIP:DMG: 0x0 = 0, - CHIP:DMG: 0x1 = "", - CHIP:DMG: 0x2 = 0, - CHIP:DMG: }, - CHIP:DMG: }, + CHIP:DMG: CommandFields = + CHIP:DMG: { + CHIP:DMG: 0x0 = 0, + CHIP:DMG: 0x2 = NULL + CHIP:DMG: }, + CHIP:DMG: }, CHIP:DMG: - CHIP:DMG: }, + CHIP:DMG: }, CHIP:DMG: - CHIP:DMG: ], + CHIP:DMG: ], CHIP:DMG: - CHIP:DMG: InteractionModelRevision = 1 + CHIP:DMG: InteractionModelRevision = 11 CHIP:DMG: }, CHIP:DMG: Received Command Response Data, Endpoint=0 Cluster=0x0000_0031 Command=0x0000_0007 - CHIP:CTL: Received ConnectNetwork response + CHIP:CTL: Received ConnectNetwork response, networkingStatus=0 disabled: true - label: "Step 10: Commissioning channel between the Commissioner and - Commissionee is terminated." + Commissionee is closed." + verification: | + Cannot be verified in TH(CHIP-TOOL) + disabled: true + + - label: "Step 11: Commissionee starts the operational channel." verification: | - 1. Terminate the connection between the Commissionee and the Commissioner. (i.e. remove network access or terminate commissioning process) + Verify in TH(CHIP-TOOL) + + Inferred by successful completion of Step 12 disabled: true - label: - "Step 11: Commissioner starts discovery of DUT using Operational + "Step 12: Commissioner starts discovery of DUT using Operational Discovery" verification: | Verify in TH(CHIP-TOOL) - CHIP:DL: Avahi resolve found - CHIP:DIS: Node ID resolved for 0x0000000000000001 - CHIP:DIS: Addr 0: [fd11:22::9d96:8fcf:10cf:799e]:5540 - CHIP:CTL: OperationalDiscoveryComplete for device ID 0x0000000000000001 + CHIP:CTL: Performing next commissioning step 'FindOperational' + CHIP:IN: Expiring all sessions for node <00000000000007CE, 1>!! + CHIP:CSM: FindOrEstablishSession: PeerId = [1:00000000000007CE] + CHIP:CSM: FindOrEstablishSession: No existing OperationalSessionSetup instance found + CHIP:DIS: OperationalSessionSetup[1:00000000000007CE]: State change 1 --> 2 + CHIP:DMG: ICR moving to [AwaitingDe] + CHIP:DIS: Checking node lookup status after 200 ms + CHIP:DL: HandlePlatformSpecificBLEEvent 16387 + CHIP:DIS: UDP:[fe80::e65f:1ff:fec2:47af%eth0]:5540: new best score: 7 + CHIP:DIS: Lookup clearing interface for non LL address + CHIP:DIS: UDP:172.16.62.113%eth0:5540: new best score: 2 + CHIP:DIS: Checking node lookup status after 7151 ms + CHIP:DIS: OperationalSessionSetup[1:00000000000007CE]: Updating device address to UDP:[fe80::e65f:1ff:fec2:47af%eth0]:5540 while in state 2 + CHIP:DIS: OperationalSessionSetup[1:00000000000007CE]: State change 2 --> 3 + CHIP:IN: SecureSession[0xffff7902f2c0]: Allocated Type:2 LSID:28474 disabled: true - label: - "Step 12: Commissioner opens a CASE session with DUT over operational + "Step 13: Commissioner opens a CASE session with DUT over operational network" verification: | Verify in TH(CHIP-TOOL) CHIP:SC: Sent Sigma1 msg - CHIP:CTL: Address resolved for node: 0x0000000000000001 - CHIP:EM: Received message of type 0x31 with protocolId (0, 0) and MessageCounter:1066460336 on exchange 45047i - CHIP:EM: Found matching exchange: 45047i, Delegate: 0xffffa400f7f8 - CHIP:EM: Rxd Ack; Removing MessageCounter:2352378411 from Retrans Table on exchange 45047i - CHIP:EM: Removed CHIP MessageCounter:2352378411 from RetransTable on exchange 45047i + CHIP:DIS: OperationalSessionSetup[1:00000000000007CE]: State change 3 --> 4 + CHIP:EM: Retransmitting MessageCounter:226454874 on exchange 11063i Send Cnt 1 + CHIP:EM: Retransmitting MessageCounter:226454874 on exchange 11063i Send Cnt 2 + CHIP:EM: Retransmitting MessageCounter:226454874 on exchange 11063i Send Cnt 3 + CHIP:EM: >>> [E:11063i S:0 M:192590746 (Ack:226454874)] (U) Msg RX from 0:0000000000000000 [0000] --- Type 0000:31 (SecureChannel:CASE_Sigma2) + CHIP:EM: Found matching exchange: 11063i, Delegate: 0xffff78207b08 + CHIP:EM: Rxd Ack; Removing MessageCounter:226454874 from Retrans Table on exchange 11063i CHIP:SC: Received Sigma2 msg - CHIP:SC: Peer assigned session session ID 2 - CHIP:SC: The device does not support GetClock_RealTimeMS() API. This will eventually result in CASE session setup failures. - CHIP:IN: Generating compressed fabric ID using uncompressed fabric ID 0x0000000000000001 and root pubkey - CHIP:IN: 0x04, 0x6e, 0x3e, 0x58, 0x9d, 0x08, 0xd6, 0xae, - CHIP:IN: 0xe9, 0xff, 0x9b, 0x8f, 0xba, 0x6f, 0x57, 0x73, - CHIP:IN: 0x21, 0xc4, 0xe2, 0x7b, 0x09, 0xe4, 0x24, 0x7f, - CHIP:IN: 0x55, 0x44, 0x3b, 0xf2, 0x7c, 0x13, 0x45, 0x3b, - CHIP:IN: 0x82, 0xa8, 0x42, 0x96, 0xb4, 0x36, 0x78, 0x20, - CHIP:IN: 0xa1, 0x37, 0x69, 0xf0, 0x20, 0xc9, 0x20, 0x7e, - CHIP:IN: 0x66, 0x45, 0x84, 0x53, 0x1b, 0x3e, 0xd2, 0x61, - CHIP:IN: 0xb6, 0x89, 0x27, 0xfd, 0xe8, 0x23, 0x69, 0x6d, - CHIP:IN: 0x93, - CHIP:IN: Generated compressed fabric ID - CHIP:IN: 0xa3, 0x54, 0xab, 0x2a, 0xa2, 0x1f, 0x8e, 0x48, + CHIP:SC: Peer assigned session session ID 24240 CHIP:SC: Found MRP parameters in the message CHIP:SC: Sending Sigma3 - CHIP:EM: Piggybacking Ack for MessageCounter:1066460336 on exchange: 45047i - CHIP:IN: Prepared unauthenticated message 0xaaaad7ce1bf8 to 0x0000000000000000 (0) of type 0x32 and protocolId (0, 0) on exchange 45047i with MessageCounter:2352378412. - CHIP:IN: Sending unauthenticated msg 0xaaaad7ce1bf8 with MessageCounter:2352378412 to 0x0000000000000000 at monotonic time: 315803 msec + CHIP:EM: <<< [E:11063i S:0 M:226454875 (Ack:192590746)] (U) Msg TX to 0:0000000000000000 [0000] [UDP:[fe80::e65f:1ff:fec2:47af%eth0]:5540] --- Type 0000:32 (SecureChannel:CASE_Sigma3) CHIP:SC: Sent Sigma3 msg - CHIP:EM: Received message of type 0x40 with protocolId (0, 0) and MessageCounter:1066460337 on exchange 45047i - CHIP:EM: Found matching exchange: 45047i, Delegate: 0xffffa400f7f8 - CHIP:EM: Rxd Ack; Removing MessageCounter:2352378412 from Retrans Table on exchange 45047i - CHIP:EM: Removed CHIP MessageCounter:2352378412 from RetransTable on exchange 45047i + CHIP:EM: >>> [E:11063i S:0 M:192590747 (Ack:226454875)] (U) Msg RX from 0:0000000000000000 [0000] --- Type 0000:40 (SecureChannel:StatusReport) + CHIP:EM: Found matching exchange: 11063i, Delegate: 0xffff78207b08 + CHIP:EM: Rxd Ack; Removing MessageCounter:226454875 from Retrans Table on exchange 11063i CHIP:SC: Success status report received. Session was established - CHIP:IN: New secure session created for device 0x0000000000000001, LSID:2 PSID:2! + CHIP:SC: SecureSession[0xffff7902f2c0, LSID:28474]: State change 'kEstablishing' --> 'kActive' + CHIP:IN: SecureSession[0xffff7902f2c0]: Activated - Type:2 LSID:28474 + CHIP:IN: New secure session activated for device <00000000000007CE, 1>, LSID:28474 PSID:24240! + CHIP:DIS: OperationalSessionSetup[1:00000000000007CE]: State change 4 --> 5 + CHIP:CTL: Successfully finished commissioning step 'FindOperational' disabled: true - - label: "Step 13: Commissioner sends CommissioningComplete command" + - label: "Step 14: Commissioner sends CommissioningComplete command" verification: | Verify in TH(CHIP-TOOL) - CHIP:CTL: Received CommissioningComplete response - CHIP:CTL: Rendezvous cleanup - CHIP:TOO: Device commissioning completed with success + CHIP:DMG: Received Command Response Data, Endpoint=0 Cluster=0x0000_0030 Command=0x0000_0005 + CHIP:CTL: Received CommissioningComplete response, errorCode=0 + CHIP:CTL: Successfully finished commissioning step 'SendComplete' disabled: true diff --git a/src/app/tests/suites/certification/Test_TC_DD_3_6.yaml b/src/app/tests/suites/certification/Test_TC_DD_3_6.yaml index 674808bfabb520..ad24d09cbbb9f8 100644 --- a/src/app/tests/suites/certification/Test_TC_DD_3_6.yaml +++ b/src/app/tests/suites/certification/Test_TC_DD_3_6.yaml @@ -28,6 +28,7 @@ tests: - label: "Note" verification: | Chip-tool command used below are an example to verify the DUT as commissioner test cases. For certification test, we expect DUT should have a capability or way to run the equivalent command. + Test Harness is a Commissionee device that is not connected to an operational network (i.e. Wi-Fi, or Ethernet) and is configured as a Non-concurrent device. disabled: true - label: "Preconditions" @@ -50,9 +51,11 @@ tests: verification: | Verify in TH (ALL-CLUSTER-APP) start BLE Advertising by specific DUT implementation - Verify in DUT(CHIP-TOOL) start commissioning process(need to obtain the Thread dataset first) + Verify in DUT(CHIP-TOOL) start commissioning process (either Thread or WiFi) ./chip-tool pairing ble-thread 1 hex:0e080000000000010000000300000f35060004001fffe0020811111111222222220708fd27e57b1b1e22d9051000112233445566778899aabbccddeeff030e4f70656e54687265616444656d6f01021234041061e1206d2c2b46e079eb775f41fc72190c0402a0fff8 20202021 3840 + ./chip-tool pairing ble-wifi 20202021 3840 + disabled: true - label: @@ -64,6 +67,30 @@ tests: CHIP:SC: Received PBKDF param response disabled: true + - label: + "Step 3a: Commissioner reads commissioning information, including + SupportsConcurrentConnection attribute from General Commissioining + Cluster" + verification: | + Verify in TH that SupportsConcurrentConnection is false + + CHIP:IM: Received Read request + CHIP:DMG: ReadRequestMessage = + CHIP:DMG: { + CHIP:DMG: AttributePathIBs = + CHIP:DMG: [ + CHIP:DMG: AttributePathIB = + CHIP:DMG: { + CHIP:DMG: Endpoint = 0x0, + CHIP:DMG: Cluster = 0x30, + CHIP:DMG: Attribute = 0x0000_0004, + CHIP:DMG: } + CHIP:DMG: + CHIP:DMG: isFabricFiltered = false, + CHIP:DMG: InteractionModelRevision = 11 + CHIP:DMG: }, + disabled: true + - label: "Step 4: Commissioner SHALL re-arm Fail-safe timer on Commissionee within 60s (the autonomously Fail-safe timer length set by @@ -370,15 +397,9 @@ tests: - label: "Step 11: Commissioning channel between the Commissioner and - Commissionee is terminated." + Commissionee is closed, operational channel started." verification: | - Verify the channel was terminated on DUT as commissioner side: - [1651271753284] [23287:743790] CHIP: [CTL] Received CommissioningComplete response - [1651271753284] [23287:743790] CHIP: [CTL] Successfully finished commissioning step 'SendComplete' - [1651271753284] [23287:743790] CHIP: [CTL] Commissioning stage next step: 'SendComplete' -> 'Cleanup' - [1651271753284] [23287:743790] CHIP: [CTL] Performing next commissioning step 'Cleanup' - [1651271753284] [23287:743790] CHIP: [CTL] Successfully finished commissioning step 'Cleanup' - [1651271753284] [23287:743790] CHIP: [TOO] Device commissioning completed with success + Inferred by successful completion of Step 12 disabled: true - label: @@ -387,10 +408,21 @@ tests: verification: | Verify in DUT as commissioner side - CHIP:DL: Avahi resolve found - CHIP:DIS: Node ID resolved for 0x0000000000000001 - CHIP:DIS: Addr 0: [fd11:22::9d96:8fcf:10cf:799e]:5540 - CHIP:CTL: OperationalDiscoveryComplete for device ID 0x0000000000000001 + CHIP:CTL: Performing next commissioning step 'FindOperational' + CHIP:IN: Expiring all sessions for node <00000000000007CE, 1>!! + CHIP:CSM: FindOrEstablishSession: PeerId = [1:00000000000007CE] + CHIP:CSM: FindOrEstablishSession: No existing OperationalSessionSetup instance found + CHIP:DIS: OperationalSessionSetup[1:00000000000007CE]: State change 1 --> 2 + CHIP:DMG: ICR moving to [AwaitingDe] + CHIP:DIS: Checking node lookup status after 200 ms + CHIP:DL: HandlePlatformSpecificBLEEvent 16387 + CHIP:DIS: UDP:[fe80::e65f:1ff:fec2:47af%eth0]:5540: new best score: 7 + CHIP:DIS: Lookup clearing interface for non LL address + CHIP:DIS: UDP:172.16.62.113%eth0:5540: new best score: 2 + CHIP:DIS: Checking node lookup status after 7151 ms + CHIP:DIS: OperationalSessionSetup[1:00000000000007CE]: Updating device address to UDP:[fe80::e65f:1ff:fec2:47af%eth0]:5540 while in state 2 + CHIP:DIS: OperationalSessionSetup[1:00000000000007CE]: State change 2 --> 3 + CHIP:IN: SecureSession[0xffff7902f2c0]: Allocated Type:2 LSID:28474 disabled: true - label: @@ -400,45 +432,35 @@ tests: Verify in DUT as commissioner side CHIP:SC: Sent Sigma1 msg - CHIP:CTL: Address resolved for node: 0x0000000000000001 - CHIP:EM: Received message of type 0x31 with protocolId (0, 0) and MessageCounter:1066460336 on exchange 45047i - CHIP:EM: Found matching exchange: 45047i, Delegate: 0xffffa400f7f8 - CHIP:EM: Rxd Ack; Removing MessageCounter:2352378411 from Retrans Table on exchange 45047i - CHIP:EM: Removed CHIP MessageCounter:2352378411 from RetransTable on exchange 45047i + CHIP:DIS: OperationalSessionSetup[1:00000000000007CE]: State change 3 --> 4 + CHIP:EM: Retransmitting MessageCounter:226454874 on exchange 11063i Send Cnt 1 + CHIP:EM: Retransmitting MessageCounter:226454874 on exchange 11063i Send Cnt 2 + CHIP:EM: Retransmitting MessageCounter:226454874 on exchange 11063i Send Cnt 3 + CHIP:EM: >>> [E:11063i S:0 M:192590746 (Ack:226454874)] (U) Msg RX from 0:0000000000000000 [0000] --- Type 0000:31 (SecureChannel:CASE_Sigma2) + CHIP:EM: Found matching exchange: 11063i, Delegate: 0xffff78207b08 + CHIP:EM: Rxd Ack; Removing MessageCounter:226454874 from Retrans Table on exchange 11063i CHIP:SC: Received Sigma2 msg - CHIP:SC: Peer assigned session session ID 2 - CHIP:SC: The device does not support GetClock_RealTimeMS() API. This will eventually result in CASE session setup failures. - CHIP:IN: Generating compressed fabric ID using uncompressed fabric ID 0x0000000000000001 and root pubkey - CHIP:IN: 0x04, 0x6e, 0x3e, 0x58, 0x9d, 0x08, 0xd6, 0xae, - CHIP:IN: 0xe9, 0xff, 0x9b, 0x8f, 0xba, 0x6f, 0x57, 0x73, - CHIP:IN: 0x21, 0xc4, 0xe2, 0x7b, 0x09, 0xe4, 0x24, 0x7f, - CHIP:IN: 0x55, 0x44, 0x3b, 0xf2, 0x7c, 0x13, 0x45, 0x3b, - CHIP:IN: 0x82, 0xa8, 0x42, 0x96, 0xb4, 0x36, 0x78, 0x20, - CHIP:IN: 0xa1, 0x37, 0x69, 0xf0, 0x20, 0xc9, 0x20, 0x7e, - CHIP:IN: 0x66, 0x45, 0x84, 0x53, 0x1b, 0x3e, 0xd2, 0x61, - CHIP:IN: 0xb6, 0x89, 0x27, 0xfd, 0xe8, 0x23, 0x69, 0x6d, - CHIP:IN: 0x93, - CHIP:IN: Generated compressed fabric ID - CHIP:IN: 0xa3, 0x54, 0xab, 0x2a, 0xa2, 0x1f, 0x8e, 0x48, + CHIP:SC: Peer assigned session session ID 24240 CHIP:SC: Found MRP parameters in the message CHIP:SC: Sending Sigma3 - CHIP:EM: Piggybacking Ack for MessageCounter:1066460336 on exchange: 45047i - CHIP:IN: Prepared unauthenticated message 0xaaaad7ce1bf8 to 0x0000000000000000 (0) of type 0x32 and protocolId (0, 0) on exchange 45047i with MessageCounter:2352378412. - CHIP:IN: Sending unauthenticated msg 0xaaaad7ce1bf8 with MessageCounter:2352378412 to 0x0000000000000000 at monotonic time: 315803 msec + CHIP:EM: <<< [E:11063i S:0 M:226454875 (Ack:192590746)] (U) Msg TX to 0:0000000000000000 [0000] [UDP:[fe80::e65f:1ff:fec2:47af%eth0]:5540] --- Type 0000:32 (SecureChannel:CASE_Sigma3) CHIP:SC: Sent Sigma3 msg - CHIP:EM: Received message of type 0x40 with protocolId (0, 0) and MessageCounter:1066460337 on exchange 45047i - CHIP:EM: Found matching exchange: 45047i, Delegate: 0xffffa400f7f8 - CHIP:EM: Rxd Ack; Removing MessageCounter:2352378412 from Retrans Table on exchange 45047i - CHIP:EM: Removed CHIP MessageCounter:2352378412 from RetransTable on exchange 45047i + CHIP:EM: >>> [E:11063i S:0 M:192590747 (Ack:226454875)] (U) Msg RX from 0:0000000000000000 [0000] --- Type 0000:40 (SecureChannel:StatusReport) + CHIP:EM: Found matching exchange: 11063i, Delegate: 0xffff78207b08 + CHIP:EM: Rxd Ack; Removing MessageCounter:226454875 from Retrans Table on exchange 11063i CHIP:SC: Success status report received. Session was established - CHIP:IN: New secure session created for device 0x0000000000000001, LSID:2 PSID:2! + CHIP:SC: SecureSession[0xffff7902f2c0, LSID:28474]: State change 'kEstablishing' --> 'kActive' + CHIP:IN: SecureSession[0xffff7902f2c0]: Activated - Type:2 LSID:28474 + CHIP:IN: New secure session activated for device <00000000000007CE, 1>, LSID:28474 PSID:24240! + CHIP:DIS: OperationalSessionSetup[1:00000000000007CE]: State change 4 --> 5 + CHIP:CTL: Successfully finished commissioning step 'FindOperational' disabled: true disabled: true - label: "Step 14: Commissioner sends CommissioningComplete command" verification: | Verify in DUT as commissioner side - CHIP:CTL: Received CommissioningComplete response - CHIP:CTL: Rendezvous cleanup - CHIP:TOO: Device commissioning completed with success + CHIP:DMG: Received Command Response Data, Endpoint=0 Cluster=0x0000_0030 Command=0x0000_0005 + CHIP:CTL: Received CommissioningComplete response, errorCode=0 + CHIP:CTL: Successfully finished commissioning step 'SendComplete' disabled: true diff --git a/src/app/tests/suites/certification/Test_TC_DD_3_8.yaml b/src/app/tests/suites/certification/Test_TC_DD_3_8.yaml index 8410f4c0aab5eb..e9f48c1652e4a0 100644 --- a/src/app/tests/suites/certification/Test_TC_DD_3_8.yaml +++ b/src/app/tests/suites/certification/Test_TC_DD_3_8.yaml @@ -29,6 +29,7 @@ tests: - label: "Note" verification: | Chip-tool command used below are an example to verify the DUT as commissioner test cases. For certification test, we expect DUT should have a capability or way to run the equivalent command. + Test Harness is a Commissionee device that is not connected to an operational network (i.e. Wi-Fi, or Ethernet) and is configured as a Non-concurrent device. disabled: true - label: "Preconditions" @@ -50,9 +51,10 @@ tests: verification: | Verify in TH as server side: start BLE Advertising by specific DUT implementation - Verify in DUT as client side: start commissioning process(need to obtain the Thread dataset first) + Verify in DUT as client side: start commissioning process (either Thread or WiFi) ./chip-tool pairing ble-thread 1 hex:0e080000000000010000000300000f35060004001fffe0020811111111222222220708fd27e57b1b1e22d9051000112233445566778899aabbccddeeff030e4f70656e54687265616444656d6f01021234041061e1206d2c2b46e079eb775f41fc72190c0402a0fff8 20202021 3840 + ./chip-tool pairing ble-wifi 20202021 3840 disabled: true - label: @@ -64,6 +66,30 @@ tests: CHIP:SC: Received PBKDF param response disabled: true + - label: + "Step 3a: Commissioner reads commissioning information, including + SupportsConcurrentConnection attribute from General Commissioning + Cluster" + verification: | + Verify in TH that SupportsConcurrentConnection is false + + CHIP:IM: Received Read request + CHIP:DMG: ReadRequestMessage = + CHIP:DMG: { + CHIP:DMG: AttributePathIBs = + CHIP:DMG: [ + CHIP:DMG: AttributePathIB = + CHIP:DMG: { + CHIP:DMG: Endpoint = 0x0, + CHIP:DMG: Cluster = 0x30, + CHIP:DMG: Attribute = 0x0000_0004, + CHIP:DMG: } + CHIP:DMG: + CHIP:DMG: isFabricFiltered = false, + CHIP:DMG: InteractionModelRevision = 11 + CHIP:DMG: }, + disabled: true + - label: "Step 4: Commissioner SHALL re-arm Fail-safe timer on Commissionee within 60s (the autonomously Fail-safe timer length set by @@ -372,18 +398,18 @@ tests: "Step 11: Commissioning channel between the Commissioner and Commissionee is terminated." verification: | - 1. Verify the channel was terminated on DUT=chip-tool - [1651271753284] [23287:743790] CHIP: [CTL] Received CommissioningComplete response - [1651271753284] [23287:743790] CHIP: [CTL] Successfully finished commissioning step 'SendComplete' - [1651271753284] [23287:743790] CHIP: [CTL] Commissioning stage next step: 'SendComplete' -> 'Cleanup' - [1651271753284] [23287:743790] CHIP: [CTL] Performing next commissioning step 'Cleanup' - [1651271753284] [23287:743790] CHIP: [CTL] Successfully finished commissioning step 'Cleanup' - [1651271753284] [23287:743790] CHIP: [TOO] Device commissioning completed with success + Verify in TH + + CHIP:SVR: Received kCloseAllBleConnections:32777 + CHIP:IN: Clearing BLE pending packets. + CHIP:BLE: Releasing end point's BLE connection back to application. + CHIP:BLE: Got notification regarding chip connection closure + CHIP:DL: wpa_supplicant: Start WiFi management disabled: true - label: "Step 12: Reboot TH and prepare for commissioning" verification: | - 1. Using TH=all-clusters-app, exit the app, re-launch app + 1. Using TH=all-clusters-app in non-concurrent mode, exit the app, re-launch app disabled: true - label: From 165da4691f114766262f54fcde093de655cec918 Mon Sep 17 00:00:00 2001 From: Shubham Patil Date: Tue, 20 Feb 2024 09:20:59 +0530 Subject: [PATCH 026/385] [ESP32] Read core dump from flash, for diagnostic crash logs (#32192) * [ESP32] Read core dump from flash, for diagnostic crash logs * Restyled by clang-format * Restyled by prettier-markdown * add espcoredump to .wordlist * Add some null checks and init the struct members --------- Co-authored-by: Restyled.io --- .github/.wordlist.txt | 3 +- .../esp32/README.md | 32 ++- .../esp32/main/CMakeLists.txt | 4 +- ...diagnostic-logs-provider-delegate-impl.cpp | 242 ++++++++++++++---- .../esp32/main/diagnostic_logs/crash.log | 21 -- .../diagnostic-logs-provider-delegate-impl.h | 54 +++- .../esp32/partitions.csv | 5 +- .../esp32/sdkconfig.defaults | 3 + 8 files changed, 286 insertions(+), 78 deletions(-) delete mode 100644 examples/temperature-measurement-app/esp32/main/diagnostic_logs/crash.log diff --git a/.github/.wordlist.txt b/.github/.wordlist.txt index 58a06086679e06..155e909a43f526 100644 --- a/.github/.wordlist.txt +++ b/.github/.wordlist.txt @@ -523,6 +523,7 @@ epochStartTime eq errorValue esd +espcoredump ESPPORT Espressif esptool @@ -1621,4 +1622,4 @@ zephyrproject zhengyaohan Zigbee zigbeealliance -zigbeethread \ No newline at end of file +zigbeethread diff --git a/examples/temperature-measurement-app/esp32/README.md b/examples/temperature-measurement-app/esp32/README.md index 18d07ff639b06a..99347fc6ead9f4 100644 --- a/examples/temperature-measurement-app/esp32/README.md +++ b/examples/temperature-measurement-app/esp32/README.md @@ -51,9 +51,39 @@ chip-tool pairing ble-wifi 1 SSID PASSPHRASE 20202021 3840 chip-tool diagnosticlogs retrieve-logs-request 0 0 1 0 # Read network diagnostic using BDX protocol -chip-tool diagnosticlogs retrieve-logs-request 1 0 1 0 --TransferFileDesignator network-diag.log +chip-tool interactive start +> diagnosticlogs retrieve-logs-request 1 1 1 0 --TransferFileDesignator network-diag.log +# Retrieve crash over BDX +> diagnosticlogs retrieve-logs-request 1 1 1 0 --TransferFileDesignator crash.bin ``` +esp-idf supports storing and retrieving +[core dump in flash](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/core_dump.html#core-dump-to-flash). + +To support that, application needs to add core dump partition's entry in +[partitons.csv](partitions.csv#7) and we need to enable few menuconfig options. + +``` +CONFIG_ESP32_ENABLE_COREDUMP_TO_FLASH=y +CONFIG_ESP32_COREDUMP_DATA_FORMAT_ELF=y +``` + +This example's partition table and sdkconfig.default are already modified + +- Retrieve the core dump using diagnostic logs cluster + + ``` + # Read crash logs over BDX + chip-tool interactive start + > diagnosticlogs retrieve-logs-request 1 1 1 0 --TransferFileDesignator crash.bin + ``` + +- Decode the crash logs, using espcoredump.py + ``` + espcoredump.py --chip (CHIP) info_corefile --core /tmp/crash.bin \ + --core-format elf build/chip-temperature-measurement-app.elf + ``` + ## Optimization Optimization related to WiFi, BLuetooth, Asserts etc are the part of this diff --git a/examples/temperature-measurement-app/esp32/main/CMakeLists.txt b/examples/temperature-measurement-app/esp32/main/CMakeLists.txt index 8953d34869b76a..062266652dc303 100644 --- a/examples/temperature-measurement-app/esp32/main/CMakeLists.txt +++ b/examples/temperature-measurement-app/esp32/main/CMakeLists.txt @@ -55,7 +55,7 @@ set(SRC_DIRS_LIST "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/providers" ) -set(PRIV_REQUIRES_LIST chip QRCode bt nvs_flash) +set(PRIV_REQUIRES_LIST chip QRCode bt nvs_flash bootloader_support espcoredump) if (CONFIG_ENABLE_PW_RPC) # Append additional directories for RPC build @@ -83,7 +83,7 @@ endif (CONFIG_ENABLE_PW_RPC) idf_component_register(PRIV_INCLUDE_DIRS ${PRIV_INCLUDE_DIRS_LIST} SRC_DIRS ${SRC_DIRS_LIST} PRIV_REQUIRES ${PRIV_REQUIRES_LIST} - EMBED_FILES diagnostic_logs/end_user_support.log diagnostic_logs/network_diag.log diagnostic_logs/crash.log) + EMBED_FILES diagnostic_logs/end_user_support.log diagnostic_logs/network_diag.log) include("${CHIP_ROOT}/build/chip/esp32/esp32_codegen.cmake") chip_app_component_codegen("${CHIP_ROOT}/examples/temperature-measurement-app/temperature-measurement-common/temperature-measurement.matter") diff --git a/examples/temperature-measurement-app/esp32/main/diagnostic-logs-provider-delegate-impl.cpp b/examples/temperature-measurement-app/esp32/main/diagnostic-logs-provider-delegate-impl.cpp index 4bef0fbd86cc19..5034e3f928788f 100644 --- a/examples/temperature-measurement-app/esp32/main/diagnostic-logs-provider-delegate-impl.cpp +++ b/examples/temperature-measurement-app/esp32/main/diagnostic-logs-provider-delegate-impl.cpp @@ -19,10 +19,19 @@ #include #include +#if defined(CONFIG_ESP_COREDUMP_ENABLE_TO_FLASH) && defined(CONFIG_ESP_COREDUMP_DATA_FORMAT_ELF) +#include +#include +// Its a bit hackish but we need this in order to pull in the sizeof(core_dump_header_t) +// we can even use the static 20 but, what if that gets chagned? +#include "../include_core_dump/esp_core_dump_types.h" +#endif // defined(CONFIG_ESP_COREDUMP_ENABLE_TO_FLASH) && defined(CONFIG_ESP_COREDUMP_DATA_FORMAT_ELF) + using namespace chip; using namespace chip::app::Clusters::DiagnosticLogs; LogProvider LogProvider::sInstance; +LogProvider::CrashLogContext LogProvider::sCrashLogContext; namespace { bool IsValidIntent(IntentEnum intent) @@ -30,24 +39,21 @@ bool IsValidIntent(IntentEnum intent) return intent != IntentEnum::kUnknownEnumValue; } -// end_user_support.log, network_diag.log, and crash.log files are embedded in the firmware +// end_user_support.log and network_diag.log files are embedded in the firmware extern const uint8_t endUserSupportLogStart[] asm("_binary_end_user_support_log_start"); extern const uint8_t endUserSupportLogEnd[] asm("_binary_end_user_support_log_end"); extern const uint8_t networkDiagnosticLogStart[] asm("_binary_network_diag_log_start"); extern const uint8_t networkDiagnosticLogEnd[] asm("_binary_network_diag_log_end"); - -extern const uint8_t crashLogStart[] asm("_binary_crash_log_start"); -extern const uint8_t crashLogEnd[] asm("_binary_crash_log_end"); } // namespace LogProvider::~LogProvider() { - for (auto sessionSpan : mSessionSpanMap) + for (auto sessionSpan : mSessionContextMap) { Platform::MemoryFree(sessionSpan.second); } - mSessionSpanMap.clear(); + mSessionContextMap.clear(); } CHIP_ERROR LogProvider::GetLogForIntent(IntentEnum intent, MutableByteSpan & outBuffer, Optional & outTimeStamp, @@ -69,93 +75,233 @@ CHIP_ERROR LogProvider::GetLogForIntent(IntentEnum intent, MutableByteSpan & out return CHIP_NO_ERROR; } -const uint8_t * LogProvider::GetDataStartForIntent(IntentEnum intent) +size_t LogProvider::GetSizeForIntent(IntentEnum intent) { switch (intent) { case IntentEnum::kEndUserSupport: - return &endUserSupportLogStart[0]; + return static_cast(endUserSupportLogEnd - endUserSupportLogStart); case IntentEnum::kNetworkDiag: - return &networkDiagnosticLogStart[0]; + return static_cast(networkDiagnosticLogEnd - networkDiagnosticLogStart); case IntentEnum::kCrashLogs: - return &crashLogStart[0]; + return GetCrashSize(); default: - return nullptr; + return 0; } } -size_t LogProvider::GetSizeForIntent(IntentEnum intent) +size_t LogProvider::GetCrashSize() { + size_t outSize = 0; + +#if defined(CONFIG_ESP_COREDUMP_ENABLE_TO_FLASH) && defined(CONFIG_ESP_COREDUMP_DATA_FORMAT_ELF) + size_t unusedOutAddr; + esp_err_t esp_err = esp_core_dump_image_get(&unusedOutAddr, &outSize); + VerifyOrReturnValue(esp_err == ESP_OK, 0, ChipLogError(DeviceLayer, "Failed to get core dump image, esp_err:%d", esp_err)); +#endif // defined(CONFIG_ESP_COREDUMP_ENABLE_TO_FLASH) && defined(CONFIG_ESP_COREDUMP_DATA_FORMAT_ELF) + + return outSize; +} + +CHIP_ERROR LogProvider::MapCrashPartition(CrashLogContext * context) +{ +#if defined(CONFIG_ESP_COREDUMP_ENABLE_TO_FLASH) && defined(CONFIG_ESP_COREDUMP_DATA_FORMAT_ELF) + size_t outAddr, outSize; + esp_err_t esp_err = esp_core_dump_image_get(&outAddr, &outSize); + VerifyOrReturnError(esp_err == ESP_OK, CHIP_ERROR(ChipError::Range::kPlatform, esp_err), + ChipLogError(DeviceLayer, "Failed to get core dump image, esp_err:%d", esp_err)); + + /* map the full core dump parition, including the checksum. */ + esp_err = spi_flash_mmap(outAddr, outSize, SPI_FLASH_MMAP_DATA, &context->mappedAddress, &context->mappedHandle); + VerifyOrReturnError(esp_err == ESP_OK, CHIP_ERROR(ChipError::Range::kPlatform, esp_err), + ChipLogError(DeviceLayer, "Failed to mmap the crash partition, esp_err:%d", esp_err)); + + context->crashSize = static_cast(outSize); + return CHIP_NO_ERROR; +#else + return CHIP_ERROR_NOT_FOUND; +#endif // defined(CONFIG_ESP_COREDUMP_ENABLE_TO_FLASH) && defined(CONFIG_ESP_COREDUMP_DATA_FORMAT_ELF) +} + +CHIP_ERROR LogProvider::PrepareLogContextForIntent(LogContext * context, IntentEnum intent) +{ + context->intent = intent; + switch (intent) { + case IntentEnum::kEndUserSupport: { + context->EndUserSupport.span = + ByteSpan(&endUserSupportLogStart[0], static_cast(endUserSupportLogEnd - endUserSupportLogStart)); + } + break; + + case IntentEnum::kNetworkDiag: { + context->NetworkDiag.span = + ByteSpan(&networkDiagnosticLogStart[0], static_cast(networkDiagnosticLogEnd - networkDiagnosticLogStart)); + } + break; + + case IntentEnum::kCrashLogs: { +#if defined(CONFIG_ESP_COREDUMP_ENABLE_TO_FLASH) && defined(CONFIG_ESP_COREDUMP_DATA_FORMAT_ELF) + sCrashLogContext.Reset(); + context->Crash.logContext = &sCrashLogContext; + + CHIP_ERROR err = MapCrashPartition(context->Crash.logContext); + VerifyOrReturnError(err == CHIP_NO_ERROR, err, context->Crash.logContext = nullptr); + + context->Crash.logContext->readOffset = sizeof(core_dump_header_t); + context->Crash.logContext->isMapped = true; +#else + return CHIP_ERROR_NOT_FOUND; +#endif // defined(CONFIG_ESP_COREDUMP_ENABLE_TO_FLASH) && defined(CONFIG_ESP_COREDUMP_DATA_FORMAT_ELF) + } + break; + + default: + return CHIP_ERROR_INVALID_ARGUMENT; + } + + return CHIP_NO_ERROR; +} + +void LogProvider::CleanupLogContextForIntent(LogContext * context) +{ + switch (context->intent) + { case IntentEnum::kEndUserSupport: - return static_cast(endUserSupportLogEnd - endUserSupportLogStart); + break; + case IntentEnum::kNetworkDiag: - return static_cast(networkDiagnosticLogEnd - networkDiagnosticLogStart); - case IntentEnum::kCrashLogs: - return static_cast(crashLogEnd - crashLogStart); + break; + + case IntentEnum::kCrashLogs: { +#if defined(CONFIG_ESP_COREDUMP_ENABLE_TO_FLASH) && defined(CONFIG_ESP_COREDUMP_DATA_FORMAT_ELF) + CrashLogContext * logContext = context->Crash.logContext; + spi_flash_munmap(logContext->mappedHandle); + logContext->Reset(); +#endif // defined(CONFIG_ESP_COREDUMP_ENABLE_TO_FLASH) && defined(CONFIG_ESP_COREDUMP_DATA_FORMAT_ELF) + } + break; + default: - return 0; + break; } } +CHIP_ERROR LogProvider::GetDataForIntent(LogContext * context, MutableByteSpan & outBuffer, bool & outIsEndOfLog) +{ + switch (context->intent) + { + case IntentEnum::kEndUserSupport: { + auto dataSize = context->EndUserSupport.span.size(); + auto count = std::min(dataSize, outBuffer.size()); + + VerifyOrReturnError(CanCastTo(count), CHIP_ERROR_INVALID_ARGUMENT, outBuffer.reduce_size(0)); + ReturnErrorOnFailure(CopySpanToMutableSpan(ByteSpan(context->EndUserSupport.span.data(), count), outBuffer)); + + outIsEndOfLog = dataSize == count; + if (!outIsEndOfLog) + { + // reduce the span after reading count bytes + context->EndUserSupport.span = context->EndUserSupport.span.SubSpan(count); + } + } + break; + + case IntentEnum::kNetworkDiag: { + auto dataSize = context->NetworkDiag.span.size(); + auto count = std::min(dataSize, outBuffer.size()); + + VerifyOrReturnError(CanCastTo(count), CHIP_ERROR_INVALID_ARGUMENT, outBuffer.reduce_size(0)); + ReturnErrorOnFailure(CopySpanToMutableSpan(ByteSpan(context->NetworkDiag.span.data(), count), outBuffer)); + + outIsEndOfLog = dataSize == count; + if (!outIsEndOfLog) + { + // reduce the span after reading count bytes + context->NetworkDiag.span = context->NetworkDiag.span.SubSpan(count); + } + } + break; + + case IntentEnum::kCrashLogs: { +#if defined(CONFIG_ESP_COREDUMP_ENABLE_TO_FLASH) && defined(CONFIG_ESP_COREDUMP_DATA_FORMAT_ELF) + CrashLogContext * logContext = context->Crash.logContext; + size_t dataSize = logContext->crashSize - logContext->readOffset; + auto count = std::min(dataSize, outBuffer.size()); + + VerifyOrReturnError(CanCastTo(count), CHIP_ERROR_INVALID_ARGUMENT, outBuffer.reduce_size(0)); + + const uint8_t * readAddr = reinterpret_cast(logContext->mappedAddress) + logContext->readOffset; + memcpy(outBuffer.data(), readAddr, count); + outBuffer.reduce_size(count); + + logContext->readOffset += count; + outIsEndOfLog = dataSize == count; +#else + outBuffer.reduce_size(0); + return CHIP_ERROR_NOT_FOUND; +#endif // defined(CONFIG_ESP_COREDUMP_ENABLE_TO_FLASH) && defined(CONFIG_ESP_COREDUMP_DATA_FORMAT_ELF) + } + break; + + default: + return CHIP_ERROR_INVALID_ARGUMENT; + } + + return CHIP_NO_ERROR; +} + CHIP_ERROR LogProvider::StartLogCollection(IntentEnum intent, LogSessionHandle & outHandle, Optional & outTimeStamp, Optional & outTimeSinceBoot) { VerifyOrReturnValue(IsValidIntent(intent), CHIP_ERROR_INVALID_ARGUMENT); - const uint8_t * dataStart = GetDataStartForIntent(intent); - VerifyOrReturnError(dataStart, CHIP_ERROR_NOT_FOUND); - - size_t dataSize = GetSizeForIntent(intent); - VerifyOrReturnError(dataSize, CHIP_ERROR_NOT_FOUND); + // In case of crash logs we can only mmap at max once, so check before doing anything + if (intent == IntentEnum::kCrashLogs) + { + VerifyOrReturnError(sCrashLogContext.isMapped == false, CHIP_ERROR_INCORRECT_STATE, + ChipLogError(DeviceLayer, "Crash partition already mapped")); + } - ByteSpan * span = reinterpret_cast(Platform::MemoryCalloc(1, sizeof(ByteSpan))); - VerifyOrReturnValue(span, CHIP_ERROR_NO_MEMORY); + LogContext * context = reinterpret_cast(Platform::MemoryCalloc(1, sizeof(LogContext))); + VerifyOrReturnValue(context != nullptr, CHIP_ERROR_NO_MEMORY); - *span = ByteSpan(dataStart, dataSize); + CHIP_ERROR err = PrepareLogContextForIntent(context, intent); + VerifyOrReturnError(err == CHIP_NO_ERROR, err, Platform::MemoryFree(context)); mLogSessionHandle++; // If the session handle rolls over to UINT16_MAX which is invalid, reset to 0. VerifyOrDo(mLogSessionHandle != kInvalidLogSessionHandle, mLogSessionHandle = 0); - outHandle = mLogSessionHandle; - mSessionSpanMap[mLogSessionHandle] = span; + outHandle = mLogSessionHandle; + mSessionContextMap[mLogSessionHandle] = context; + return CHIP_NO_ERROR; } CHIP_ERROR LogProvider::EndLogCollection(LogSessionHandle sessionHandle) { VerifyOrReturnValue(sessionHandle != kInvalidLogSessionHandle, CHIP_ERROR_INVALID_ARGUMENT); - VerifyOrReturnValue(mSessionSpanMap.count(sessionHandle), CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrReturnValue(mSessionContextMap.count(sessionHandle), CHIP_ERROR_INVALID_ARGUMENT); - ByteSpan * span = mSessionSpanMap[sessionHandle]; - mSessionSpanMap.erase(sessionHandle); + LogContext * context = mSessionContextMap[sessionHandle]; + VerifyOrReturnError(context, CHIP_ERROR_INCORRECT_STATE); + + CleanupLogContextForIntent(context); + Platform::MemoryFree(context); + mSessionContextMap.erase(sessionHandle); - Platform::MemoryFree(span); return CHIP_NO_ERROR; } CHIP_ERROR LogProvider::CollectLog(LogSessionHandle sessionHandle, MutableByteSpan & outBuffer, bool & outIsEndOfLog) { VerifyOrReturnValue(sessionHandle != kInvalidLogSessionHandle, CHIP_ERROR_INVALID_ARGUMENT); - VerifyOrReturnValue(mSessionSpanMap.count(sessionHandle), CHIP_ERROR_INVALID_ARGUMENT); - - ByteSpan * span = mSessionSpanMap[sessionHandle]; - auto dataSize = span->size(); - auto count = std::min(dataSize, outBuffer.size()); - - VerifyOrReturnError(CanCastTo(count), CHIP_ERROR_INVALID_ARGUMENT, outBuffer.reduce_size(0)); - - ReturnErrorOnFailure(CopySpanToMutableSpan(ByteSpan(span->data(), count), outBuffer)); + VerifyOrReturnValue(mSessionContextMap.count(sessionHandle), CHIP_ERROR_INVALID_ARGUMENT); - outIsEndOfLog = dataSize == count; + LogContext * context = mSessionContextMap[sessionHandle]; + VerifyOrReturnError(context, CHIP_ERROR_INCORRECT_STATE); - if (!outIsEndOfLog) - { - // reduce the span after reading count bytes - *span = span->SubSpan(count); - } - - return CHIP_NO_ERROR; + return GetDataForIntent(context, outBuffer, outIsEndOfLog); } diff --git a/examples/temperature-measurement-app/esp32/main/diagnostic_logs/crash.log b/examples/temperature-measurement-app/esp32/main/diagnostic_logs/crash.log deleted file mode 100644 index 04089de8ce7afd..00000000000000 --- a/examples/temperature-measurement-app/esp32/main/diagnostic_logs/crash.log +++ /dev/null @@ -1,21 +0,0 @@ -W (5047Guru Meditation Error: Core 0 panic'ed (LoadProhibited). Exception was unhandled. - -Core 0 register dump: -PC : 0x4009579a PS : 0x00060c33 A0 : 0x800941e1 A1 : 0x3fff3630 -0x4009579a: uxListRemove at /opt/espressif/esp-idf/components/freertos/FreeRTOS-Kernel/list.c:195 - -A2 : 0x00000006 A3 : 0x00060c20 A4 : 0x00000000 A5 : 0x00060c23 -A6 : 0xb33fffff A7 : 0xb33fffff A8 : 0x800950f0 A9 : 0x3fff3600 -A10 : 0x00000001 A11 : 0x000000fe A12 : 0x00000000 A13 : 0x00000000 -A14 : 0x00000000 A15 : 0x00000000 SAR : 0x0000000a EXCCAUSE: 0x0000001c -EXCVADDR: 0x00000016 LBEG : 0x4000c2e0 LEND : 0x4000c2f6 LCOUNT : 0xffffffff -0x4000c2e0: memcpy in ROM -0x4000c2f6: memcpy in ROM - -Backtrace: 0x40095797:0x3fff3630 0x400941de:0x3fff3650 0x40154b39:0x3fff3670 0x40154b53:0x3fff3690 0x4013e20d:0x3fff36b0 0x40094fa6:0x3fff36d0 -0x40095797: uxListRemove at /opt/espressif/esp-idf/components/freertos/FreeRTOS-Kernel/list.c:202 -0x400941de: vTaskDelete at /opt/espressif/esp-idf/components/freertos/FreeRTOS-Kernel/tasks.c:1434 (discriminator 4) -0x40154b39: esp_nimble_disable at /opt/espressif/esp-idf/components/bt/host/nimble/nimble/porting/npl/freertos/src/nimble_port_freertos.c:55 -0x40154b53: nimble_port_freertos_deinit at /opt/espressif/esp-idf/components/bt/host/nimble/nimble/porting/npl/freertos/src/nimble_port_freertos.c:80 -0x4013e20d: chip::DeviceLayer::Internal::BLEManagerImpl::bleprph_host_task(void*) at /home/smart/projects/smp_matter/build/esp-idf/chip/../../../../../../../opt/espressif/esp-matter/connectedhomeip/connectedhomeip/config/esp32/third_party/connectedhomeip/src/platform/ESP32/nimble/BLEManagerImpl.cpp:864 -0x40094fa6: vPortTaskWrapper at /opt/espressif/esp-idf/components/freertos/FreeRTOS-Kernel/portable/xtensa/port.c:162 diff --git a/examples/temperature-measurement-app/esp32/main/include/diagnostic-logs-provider-delegate-impl.h b/examples/temperature-measurement-app/esp32/main/include/diagnostic-logs-provider-delegate-impl.h index d47dccafa6079d..c3d1bd389fb39b 100644 --- a/examples/temperature-measurement-app/esp32/main/include/diagnostic-logs-provider-delegate-impl.h +++ b/examples/temperature-measurement-app/esp32/main/include/diagnostic-logs-provider-delegate-impl.h @@ -20,6 +20,7 @@ #include #include +#include namespace chip { namespace app { @@ -54,12 +55,59 @@ class LogProvider : public DiagnosticLogsProviderDelegate LogProvider(const LogProvider &) = delete; LogProvider & operator=(const LogProvider &) = delete; - // This tracks the ByteSpan for each session - std::map mSessionSpanMap; + struct CrashLogContext + { + spi_flash_mmap_handle_t mappedHandle = 0; + const void * mappedAddress = nullptr; + uint32_t crashSize = 0; + uint32_t readOffset = 0; + bool isMapped = 0; + + void Reset() + { + this->mappedHandle = 0; + this->mappedAddress = nullptr; + this->crashSize = 0; + this->readOffset = 0; + this->isMapped = 0; + } + }; + + static CrashLogContext sCrashLogContext; + + struct LogContext + { + IntentEnum intent; + union + { + struct + { + ByteSpan span; + } EndUserSupport; + struct + { + ByteSpan span; + } NetworkDiag; + struct + { + // TODO: This be a ref counted, so that we can serve parallel queries for crash logs + CrashLogContext * logContext; + } Crash; + }; + }; + + // This tracks the ByteSpan for each session, need to change this to void * + std::map mSessionContextMap; LogSessionHandle mLogSessionHandle = kInvalidLogSessionHandle; - const uint8_t * GetDataStartForIntent(IntentEnum intent); + // Helpers for Retrieving Core Dump from flash + size_t GetCrashSize(); + CHIP_ERROR MapCrashPartition(CrashLogContext * crashLogContext); + + CHIP_ERROR PrepareLogContextForIntent(LogContext * context, IntentEnum intent); + void CleanupLogContextForIntent(LogContext * contex); + CHIP_ERROR GetDataForIntent(LogContext * context, MutableByteSpan & outBuffer, bool & outIsEndOfLog); }; } // namespace DiagnosticLogs diff --git a/examples/temperature-measurement-app/esp32/partitions.csv b/examples/temperature-measurement-app/esp32/partitions.csv index 8b0928187b8708..35c776d19e80fa 100644 --- a/examples/temperature-measurement-app/esp32/partitions.csv +++ b/examples/temperature-measurement-app/esp32/partitions.csv @@ -2,5 +2,6 @@ # Note: if you have increased the bootloader size, make sure to update the offsets to avoid overlap nvs, data, nvs, , 0xC000, phy_init, data, phy, , 0x1000, -# Factory partition size about 1.9MB -factory, app, factory, , 1920K, +# Factory partition size about 1.5MB +factory, app, factory, , 1536K, +coredump, data, coredump,, 64K diff --git a/examples/temperature-measurement-app/esp32/sdkconfig.defaults b/examples/temperature-measurement-app/esp32/sdkconfig.defaults index 6d3243cabfeb8c..3dcab272b297db 100644 --- a/examples/temperature-measurement-app/esp32/sdkconfig.defaults +++ b/examples/temperature-measurement-app/esp32/sdkconfig.defaults @@ -99,3 +99,6 @@ CONFIG_LWIP_IPV6_NUM_ADDRESSES=6 # Enable the diagnostic logs transfer over BDX protocol CONFIG_CHIP_ENABLE_BDX_LOG_TRANSFER=y + +CONFIG_ESP32_ENABLE_COREDUMP_TO_FLASH=y +CONFIG_ESP32_COREDUMP_DATA_FORMAT_ELF=y From 6b27278831f83c2bd151df8d948ab6c604a06b96 Mon Sep 17 00:00:00 2001 From: joonhaengHeo <85541460+joonhaengHeo@users.noreply.github.com> Date: Tue, 20 Feb 2024 16:29:08 +0900 Subject: [PATCH 027/385] Fix Android interaction tool crash (#32197) --- .../clusterinteraction/ClusterDetailFragment.kt | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/clusterinteraction/ClusterDetailFragment.kt b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/clusterinteraction/ClusterDetailFragment.kt index 50c33bd35c60ba..eb14eee23770bd 100644 --- a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/clusterinteraction/ClusterDetailFragment.kt +++ b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/clusterinteraction/ClusterDetailFragment.kt @@ -199,10 +199,19 @@ class ClusterDetailFragment : Fragment() { private fun castStringToType(data: String, type: Class<*>, underlyingType: Class<*>): Any? { return when (type) { - Int::class.java -> data.toInt() - Boolean::class.java -> data.toBoolean() + Int::class.java, + java.lang.Integer::class.java -> data.toInt() + Boolean::class.java, + java.lang.Boolean::class.java -> data.toBoolean() ByteArray::class.java -> data.encodeToByteArray() - Long::class.java -> data.toLong() + Long::class.java, + java.lang.Long::class.java -> data.toLong() + Short::class.java, + java.lang.Short::class.java -> data.toShort() + Double::class.java, + java.lang.Double::class.java -> data.toDouble() + Float::class.java, + java.lang.Float::class.java -> data.toFloat() Optional::class.java -> if (data.isEmpty()) Optional.empty() else Optional.of(castStringToType(data, underlyingType, underlyingType)!!) From a3d0a86a204cc970c4e37307b5ae71043129125f Mon Sep 17 00:00:00 2001 From: Andrei Litvin Date: Tue, 20 Feb 2024 04:56:48 -0500 Subject: [PATCH 028/385] Add more files to be managed and known by GN (#32140) * A first attempt at cleanup: moved ObjectList.h and some renames * Another rename pass * Final rename pass * Restyle * Fix typo in include * Fix typo and include dependencies * Remove handled files from linter check * Added 3 more mock files to be tracked by gn * Added some comments about layering issues and added EventManagement.h since that seems safe * Added more headers that are safe and restyle * Spell out what we could not add in IM because broken dependencies * Also track AppDelegate * Update the comments to not trigger the very basic linter we have * Fix typo * Restyle * Pull linkedlist into support rather than separate source set --- .github/workflows/lint.yml | 14 -------- src/app/AttributePathExpandIterator.cpp | 2 +- src/app/AttributePathExpandIterator.h | 4 +-- src/app/BUILD.gn | 26 +++++++++++++++ src/app/EventLoggingTypes.h | 10 +++--- src/app/EventManagement.cpp | 2 +- src/app/EventManagement.h | 4 +-- src/app/InteractionModelEngine.cpp | 32 ++++++++++--------- src/app/InteractionModelEngine.h | 26 +++++++-------- src/app/ReadHandler.cpp | 2 +- src/app/ReadHandler.h | 14 ++++---- src/app/SubscriptionResumptionStorage.h | 12 +++---- src/app/common/BUILD.gn | 2 ++ src/app/data-model/BUILD.gn | 2 +- src/app/reporting/Engine.cpp | 2 +- src/app/reporting/Engine.h | 2 +- src/app/server/BUILD.gn | 1 + .../tests/TestAttributePathExpandIterator.cpp | 24 +++++++------- src/app/tests/TestEventLogging.cpp | 8 ++--- src/app/tests/TestEventLoggingNoUTCTime.cpp | 8 ++--- .../tests/TestFabricScopedEventLogging.cpp | 8 ++--- src/app/tests/TestInteractionModelEngine.cpp | 12 +++---- src/app/util/BUILD.gn | 8 +++++ src/app/util/mock/BUILD.gn | 3 ++ src/lib/support/BUILD.gn | 1 + .../ObjectList.h => lib/support/LinkedList.h} | 7 ++-- 26 files changed, 132 insertions(+), 104 deletions(-) rename src/{app/ObjectList.h => lib/support/LinkedList.h} (90%) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 189f63837c841e..d811fe05fa888f 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -93,35 +93,25 @@ jobs: --known-failure app/AttributeAccessInterface.h \ --known-failure app/AttributeAccessToken.h \ --known-failure app/att-storage.h \ - --known-failure app/BufferedReadCallback.h \ --known-failure app/CommandHandler.h \ --known-failure app/CommandHandlerInterface.h \ - --known-failure app/CommandPathParams.h \ - --known-failure app/CommandPathRegistry.h \ - --known-failure app/CommandResponseSender.h \ --known-failure app/CommandSender.h \ --known-failure app/CommandSenderLegacyCallback.h \ --known-failure app/CompatEnumNames.h \ - --known-failure app/ConcreteAttributePath.h \ - --known-failure app/ConcreteCommandPath.h \ --known-failure app/data-model/ListLargeSystemExtensions.h \ --known-failure app/EventHeader.h \ --known-failure app/EventLoggingDelegate.h \ --known-failure app/EventLogging.h \ --known-failure app/EventLoggingTypes.h \ - --known-failure app/EventManagement.h \ --known-failure app/InteractionModelHelper.h \ - --known-failure app/ObjectList.h \ --known-failure app/ReadClient.h \ --known-failure app/ReadHandler.h \ --known-failure app/ReadPrepareParams.h \ --known-failure app/reporting/tests/MockReportScheduler.cpp \ --known-failure app/reporting/tests/MockReportScheduler.h \ - --known-failure app/server/AppDelegate.h \ --known-failure app/TestEventTriggerDelegate.h \ --known-failure app/util/af.h \ --known-failure app/util/af-types.h \ - --known-failure app/util/attribute-metadata.h \ --known-failure app/util/attribute-storage.cpp \ --known-failure app/util/attribute-storage.h \ --known-failure app/util/attribute-storage-null-handling.h \ @@ -141,11 +131,7 @@ jobs: --known-failure app/util/im-client-callbacks.h \ --known-failure app/util/MatterCallbacks.h \ --known-failure app/util/message.cpp \ - --known-failure app/util/mock/Constants.h \ - --known-failure app/util/mock/Functions.h \ - --known-failure app/util/mock/MockNodeConfig.h \ --known-failure app/util/odd-sized-integers.h \ - --known-failure app/util/types_stub.h \ --known-failure app/util/util.cpp \ --known-failure app/util/util.h \ --known-failure app/WriteClient.h \ diff --git a/src/app/AttributePathExpandIterator.cpp b/src/app/AttributePathExpandIterator.cpp index 5c1bb50c179f47..784499a41c4d74 100644 --- a/src/app/AttributePathExpandIterator.cpp +++ b/src/app/AttributePathExpandIterator.cpp @@ -52,7 +52,7 @@ extern bool emberAfEndpointIndexIsEnabled(uint16_t index); namespace chip { namespace app { -AttributePathExpandIterator::AttributePathExpandIterator(ObjectList * aAttributePath) +AttributePathExpandIterator::AttributePathExpandIterator(SingleLinkedListNode * aAttributePath) { mpAttributePath = aAttributePath; diff --git a/src/app/AttributePathExpandIterator.h b/src/app/AttributePathExpandIterator.h index dbf8382014ce9c..f11e6793822f84 100644 --- a/src/app/AttributePathExpandIterator.h +++ b/src/app/AttributePathExpandIterator.h @@ -69,7 +69,7 @@ namespace app { class AttributePathExpandIterator { public: - AttributePathExpandIterator(ObjectList * aAttributePath); + AttributePathExpandIterator(SingleLinkedListNode * aAttributePath); /** * Proceed the iterator to the next attribute path in the given cluster info. @@ -105,7 +105,7 @@ class AttributePathExpandIterator inline bool Valid() const { return mpAttributePath != nullptr; } private: - ObjectList * mpAttributePath; + SingleLinkedListNode * mpAttributePath; ConcreteAttributePath mOutputPath; diff --git a/src/app/BUILD.gn b/src/app/BUILD.gn index c0f30493824f3a..3dfbbbffe56daf 100644 --- a/src/app/BUILD.gn +++ b/src/app/BUILD.gn @@ -87,7 +87,11 @@ source_set("revision_info") { source_set("paths") { sources = [ "AttributePathParams.h", + "CommandPathParams.h", + "CommandPathRegistry.h", + "ConcreteAttributePath.h", "ConcreteClusterPath.h", + "ConcreteCommandPath.h", "ConcreteEventPath.h", "DataVersionFilter.h", "EventPathParams.h", @@ -96,6 +100,7 @@ source_set("paths") { # This source sets also depends on basic-types.h that is not in any dependency we can use public_deps = [ ":app_config", + "${chip_root}/src/app/util:types", "${chip_root}/src/lib/core", "${chip_root}/src/lib/core:types", ] @@ -222,12 +227,14 @@ static_library("app") { "CommandHandler.cpp", "CommandResponseHelper.h", "CommandResponseSender.cpp", + "CommandResponseSender.h", "CommandSender.cpp", "DefaultAttributePersistenceProvider.cpp", "DefaultAttributePersistenceProvider.h", "DeferredAttributePersistenceProvider.cpp", "DeferredAttributePersistenceProvider.h", "EventManagement.cpp", + "EventManagement.h", "FailSafeContext.cpp", "FailSafeContext.h", "OTAUserConsentCommon.h", @@ -242,6 +249,21 @@ static_library("app") { "TimerDelegates.h", "WriteClient.cpp", "WriteHandler.cpp", + + # TODO: the following items cannot be included due to interaction-model circularity + # (app depending on im and im including these headers): + # Name with _ so that linter does not recognize it + # "CommandHandler._h" + # "CommandSender._h", + # "ReadClient._h", + # "ReadHandler._h", + # "WriteClient._h", + # "WriteHandler._h" + + # TODO: the following items cannot be included due to platform includes not being + # able to depend on src/app + # Name with _ so that linter does not recognize it + # "_AttributeAccessInterface._h", ] public_deps = [ @@ -261,9 +283,13 @@ static_library("app") { if (chip_enable_read_client) { sources += [ "BufferedReadCallback.cpp", + "BufferedReadCallback.h", "ClusterStateCache.cpp", "ClusterStateCache.h", "ReadClient.cpp", + + # TODO: cannot include "ReadClient._h" because interaction-model backreference + # Name with _ so that linter does not recognize it ] } diff --git a/src/app/EventLoggingTypes.h b/src/app/EventLoggingTypes.h index 35fd37a25045ca..04a843ebcfbd60 100644 --- a/src/app/EventLoggingTypes.h +++ b/src/app/EventLoggingTypes.h @@ -19,11 +19,11 @@ #include #include -#include #include #include #include #include +#include #include inline constexpr size_t kNumPriorityLevel = 3; @@ -151,10 +151,10 @@ struct EventLoadOutContext EventNumber mStartingEventNumber = 0; Timestamp mPreviousTime; Timestamp mCurrentTime; - EventNumber mCurrentEventNumber = 0; - size_t mEventCount = 0; - const ObjectList * mpInterestedEventPaths = nullptr; - bool mFirst = true; + EventNumber mCurrentEventNumber = 0; + size_t mEventCount = 0; + const SingleLinkedListNode * mpInterestedEventPaths = nullptr; + bool mFirst = true; Access::SubjectDescriptor mSubjectDescriptor; }; } // namespace app diff --git a/src/app/EventManagement.cpp b/src/app/EventManagement.cpp index aa3abd67f828d8..8e6d53c24c9636 100644 --- a/src/app/EventManagement.cpp +++ b/src/app/EventManagement.cpp @@ -639,7 +639,7 @@ CHIP_ERROR EventManagement::CopyEventsSince(const TLVReader & aReader, size_t aD return err; } -CHIP_ERROR EventManagement::FetchEventsSince(TLVWriter & aWriter, const ObjectList * apEventPathList, +CHIP_ERROR EventManagement::FetchEventsSince(TLVWriter & aWriter, const SingleLinkedListNode * apEventPathList, EventNumber & aEventMin, size_t & aEventCount, const Access::SubjectDescriptor & aSubjectDescriptor) { diff --git a/src/app/EventManagement.h b/src/app/EventManagement.h index 228c26cca94a68..950efdc2bae867 100644 --- a/src/app/EventManagement.h +++ b/src/app/EventManagement.h @@ -31,10 +31,10 @@ #include #include #include -#include #include #include #include +#include #include #include #include @@ -359,7 +359,7 @@ class EventManagement * available. * */ - CHIP_ERROR FetchEventsSince(chip::TLV::TLVWriter & aWriter, const ObjectList * apEventPathList, + CHIP_ERROR FetchEventsSince(chip::TLV::TLVWriter & aWriter, const SingleLinkedListNode * apEventPathList, EventNumber & aEventMin, size_t & aEventCount, const Access::SubjectDescriptor & aSubjectDescriptor); /** diff --git a/src/app/InteractionModelEngine.cpp b/src/app/InteractionModelEngine.cpp index ddc8a984f16b72..8e4b5a80e3df7d 100644 --- a/src/app/InteractionModelEngine.cpp +++ b/src/app/InteractionModelEngine.cpp @@ -450,7 +450,7 @@ CHIP_ERROR InteractionModelEngine::ParseAttributePaths(const Access::SubjectDesc // This avoids the 'parse all paths' approach that is employed in ReadHandler since we want to // avoid allocating out of the path store during this minimal initial processing stage. // - ObjectList paramsList; + SingleLinkedListNode paramsList; ReturnErrorOnFailure(path.Init(pathReader)); ReturnErrorOnFailure(path.ParsePath(paramsList.mValue)); @@ -1513,12 +1513,12 @@ bool InteractionModelEngine::HasConflictWriteRequests(const WriteHandler * apWri return false; } -void InteractionModelEngine::ReleaseAttributePathList(ObjectList *& aAttributePathList) +void InteractionModelEngine::ReleaseAttributePathList(SingleLinkedListNode *& aAttributePathList) { ReleasePool(aAttributePathList, mAttributePathPool); } -CHIP_ERROR InteractionModelEngine::PushFrontAttributePathList(ObjectList *& aAttributePathList, +CHIP_ERROR InteractionModelEngine::PushFrontAttributePathList(SingleLinkedListNode *& aAttributePathList, AttributePathParams & aAttributePath) { CHIP_ERROR err = PushFront(aAttributePathList, aAttributePath, mAttributePathPool); @@ -1530,10 +1530,10 @@ CHIP_ERROR InteractionModelEngine::PushFrontAttributePathList(ObjectList *& aAttributePaths) +void InteractionModelEngine::RemoveDuplicateConcreteAttributePath(SingleLinkedListNode *& aAttributePaths) { - ObjectList * prev = nullptr; - auto * path1 = aAttributePaths; + SingleLinkedListNode * prev = nullptr; + auto * path1 = aAttributePaths; while (path1 != nullptr) { @@ -1585,12 +1585,12 @@ void InteractionModelEngine::RemoveDuplicateConcreteAttributePath(ObjectList *& aEventPathList) +void InteractionModelEngine::ReleaseEventPathList(SingleLinkedListNode *& aEventPathList) { ReleasePool(aEventPathList, mEventPathPool); } -CHIP_ERROR InteractionModelEngine::PushFrontEventPathParamsList(ObjectList *& aEventPathList, +CHIP_ERROR InteractionModelEngine::PushFrontEventPathParamsList(SingleLinkedListNode *& aEventPathList, EventPathParams & aEventPath) { CHIP_ERROR err = PushFront(aEventPathList, aEventPath, mEventPathPool); @@ -1602,12 +1602,12 @@ CHIP_ERROR InteractionModelEngine::PushFrontEventPathParamsList(ObjectList *& aDataVersionFilterList) +void InteractionModelEngine::ReleaseDataVersionFilterList(SingleLinkedListNode *& aDataVersionFilterList) { ReleasePool(aDataVersionFilterList, mDataVersionFilterPool); } -CHIP_ERROR InteractionModelEngine::PushFrontDataVersionFilterList(ObjectList *& aDataVersionFilterList, +CHIP_ERROR InteractionModelEngine::PushFrontDataVersionFilterList(SingleLinkedListNode *& aDataVersionFilterList, DataVersionFilter & aDataVersionFilter) { CHIP_ERROR err = PushFront(aDataVersionFilterList, aDataVersionFilter, mDataVersionFilterPool); @@ -1620,12 +1620,13 @@ CHIP_ERROR InteractionModelEngine::PushFrontDataVersionFilterList(ObjectList -void InteractionModelEngine::ReleasePool(ObjectList *& aObjectList, ObjectPool, N> & aObjectPool) +void InteractionModelEngine::ReleasePool(SingleLinkedListNode *& aObjectList, + ObjectPool, N> & aObjectPool) { - ObjectList * current = aObjectList; + SingleLinkedListNode * current = aObjectList; while (current != nullptr) { - ObjectList * nextObject = current->mpNext; + SingleLinkedListNode * nextObject = current->mpNext; aObjectPool.ReleaseObject(current); current = nextObject; } @@ -1634,9 +1635,10 @@ void InteractionModelEngine::ReleasePool(ObjectList *& aObjectList, ObjectPoo } template -CHIP_ERROR InteractionModelEngine::PushFront(ObjectList *& aObjectList, T & aData, ObjectPool, N> & aObjectPool) +CHIP_ERROR InteractionModelEngine::PushFront(SingleLinkedListNode *& aObjectList, T & aData, + ObjectPool, N> & aObjectPool) { - ObjectList * object = aObjectPool.CreateObject(); + SingleLinkedListNode * object = aObjectPool.CreateObject(); if (object == nullptr) { return CHIP_ERROR_NO_MEMORY; diff --git a/src/app/InteractionModelEngine.h b/src/app/InteractionModelEngine.h index b222087867380f..1c05767299dfbb 100644 --- a/src/app/InteractionModelEngine.h +++ b/src/app/InteractionModelEngine.h @@ -38,7 +38,6 @@ #include #include #include -#include #include #include #include @@ -54,6 +53,7 @@ #include #include #include +#include #include #include #include @@ -187,22 +187,22 @@ class InteractionModelEngine : public Messaging::UnsolicitedMessageHandler, reporting::ReportScheduler * GetReportScheduler() { return mReportScheduler; } - void ReleaseAttributePathList(ObjectList *& aAttributePathList); + void ReleaseAttributePathList(SingleLinkedListNode *& aAttributePathList); - CHIP_ERROR PushFrontAttributePathList(ObjectList *& aAttributePathList, + CHIP_ERROR PushFrontAttributePathList(SingleLinkedListNode *& aAttributePathList, AttributePathParams & aAttributePath); // If a concrete path indicates an attribute that is also referenced by a wildcard path in the request, // the path SHALL be removed from the list. - void RemoveDuplicateConcreteAttributePath(ObjectList *& aAttributePaths); + void RemoveDuplicateConcreteAttributePath(SingleLinkedListNode *& aAttributePaths); - void ReleaseEventPathList(ObjectList *& aEventPathList); + void ReleaseEventPathList(SingleLinkedListNode *& aEventPathList); - CHIP_ERROR PushFrontEventPathParamsList(ObjectList *& aEventPathList, EventPathParams & aEventPath); + CHIP_ERROR PushFrontEventPathParamsList(SingleLinkedListNode *& aEventPathList, EventPathParams & aEventPath); - void ReleaseDataVersionFilterList(ObjectList *& aDataVersionFilterList); + void ReleaseDataVersionFilterList(SingleLinkedListNode *& aDataVersionFilterList); - CHIP_ERROR PushFrontDataVersionFilterList(ObjectList *& aDataVersionFilterList, + CHIP_ERROR PushFrontDataVersionFilterList(SingleLinkedListNode *& aDataVersionFilterList, DataVersionFilter & aDataVersionFilter); CHIP_ERROR RegisterCommandHandler(CommandHandlerInterface * handler); @@ -576,9 +576,9 @@ class InteractionModelEngine : public Messaging::UnsolicitedMessageHandler, static void ResumeSubscriptionsTimerCallback(System::Layer * apSystemLayer, void * apAppState); template - void ReleasePool(ObjectList *& aObjectList, ObjectPool, N> & aObjectPool); + void ReleasePool(SingleLinkedListNode *& aObjectList, ObjectPool, N> & aObjectPool); template - CHIP_ERROR PushFront(ObjectList *& aObjectList, T & aData, ObjectPool, N> & aObjectPool); + CHIP_ERROR PushFront(SingleLinkedListNode *& aObjectList, T & aData, ObjectPool, N> & aObjectPool); Messaging::ExchangeManager * mpExchangeMgr = nullptr; @@ -606,13 +606,13 @@ class InteractionModelEngine : public Messaging::UnsolicitedMessageHandler, "CHIP_IM_MAX_NUM_READS is too small to match the requirements of spec 8.5.1"); #endif - ObjectPool, + ObjectPool, CHIP_IM_SERVER_MAX_NUM_PATH_GROUPS_FOR_READS + CHIP_IM_SERVER_MAX_NUM_PATH_GROUPS_FOR_SUBSCRIPTIONS> mAttributePathPool; - ObjectPool, + ObjectPool, CHIP_IM_SERVER_MAX_NUM_PATH_GROUPS_FOR_READS + CHIP_IM_SERVER_MAX_NUM_PATH_GROUPS_FOR_SUBSCRIPTIONS> mEventPathPool; - ObjectPool, + ObjectPool, CHIP_IM_SERVER_MAX_NUM_PATH_GROUPS_FOR_READS + CHIP_IM_SERVER_MAX_NUM_PATH_GROUPS_FOR_SUBSCRIPTIONS> mDataVersionFilterPool; diff --git a/src/app/ReadHandler.cpp b/src/app/ReadHandler.cpp index b5fc34484ea8ff..63da2a53aa7470 100644 --- a/src/app/ReadHandler.cpp +++ b/src/app/ReadHandler.cpp @@ -134,7 +134,7 @@ void ReadHandler::OnSubscriptionResumed(const SessionHandle & sessionHandle, MoveToState(HandlerState::CanStartReporting); - ObjectList * attributePath = mpAttributePathList; + SingleLinkedListNode * attributePath = mpAttributePathList; while (attributePath) { mManagementCallback.GetInteractionModelEngine()->GetReportingEngine().SetDirty(attributePath->mValue); diff --git a/src/app/ReadHandler.h b/src/app/ReadHandler.h index 71070c357147df..c597bac8a58d70 100644 --- a/src/app/ReadHandler.h +++ b/src/app/ReadHandler.h @@ -36,7 +36,6 @@ #include #include #include -#include #include #include #include @@ -45,6 +44,7 @@ #include #include #include +#include #include #include #include @@ -224,9 +224,9 @@ class ReadHandler : public Messaging::ExchangeDelegate ReadHandler(ManagementCallback & apCallback, Observer * observer); #endif - const ObjectList * GetAttributePathList() const { return mpAttributePathList; } - const ObjectList * GetEventPathList() const { return mpEventPathList; } - const ObjectList * GetDataVersionFilterList() const { return mpDataVersionFilterList; } + const SingleLinkedListNode * GetAttributePathList() const { return mpAttributePathList; } + const SingleLinkedListNode * GetEventPathList() const { return mpEventPathList; } + const SingleLinkedListNode * GetDataVersionFilterList() const { return mpDataVersionFilterList; } void GetReportingIntervals(uint16_t & aMinInterval, uint16_t & aMaxInterval) const { @@ -550,9 +550,9 @@ class ReadHandler : public Messaging::ExchangeDelegate Messaging::ExchangeManager * mExchangeMgr = nullptr; #endif // CHIP_CONFIG_UNSAFE_SUBSCRIPTION_EXCHANGE_MANAGER_USE - ObjectList * mpAttributePathList = nullptr; - ObjectList * mpEventPathList = nullptr; - ObjectList * mpDataVersionFilterList = nullptr; + SingleLinkedListNode * mpAttributePathList = nullptr; + SingleLinkedListNode * mpEventPathList = nullptr; + SingleLinkedListNode * mpDataVersionFilterList = nullptr; ManagementCallback & mManagementCallback; diff --git a/src/app/SubscriptionResumptionStorage.h b/src/app/SubscriptionResumptionStorage.h index 316adc3bd3c2e3..19342599f36bbc 100644 --- a/src/app/SubscriptionResumptionStorage.h +++ b/src/app/SubscriptionResumptionStorage.h @@ -78,15 +78,15 @@ class SubscriptionResumptionStorage bool mFabricFiltered; Platform::ScopedMemoryBufferWithSize mAttributePaths; Platform::ScopedMemoryBufferWithSize mEventPaths; - CHIP_ERROR SetAttributePaths(const ObjectList * pAttributePathList) + CHIP_ERROR SetAttributePaths(const SingleLinkedListNode * pAttributePathList) { mAttributePaths.Free(); if (!pAttributePathList) { return CHIP_NO_ERROR; } - const ObjectList * attributePath = pAttributePathList; - size_t attributePathCount = 0; + const SingleLinkedListNode * attributePath = pAttributePathList; + size_t attributePathCount = 0; while (attributePath) { attributePathCount++; @@ -103,15 +103,15 @@ class SubscriptionResumptionStorage } return CHIP_NO_ERROR; } - CHIP_ERROR SetEventPaths(const ObjectList * pEventPathList) + CHIP_ERROR SetEventPaths(const SingleLinkedListNode * pEventPathList) { mEventPaths.Free(); if (!pEventPathList) { return CHIP_NO_ERROR; } - const ObjectList * eventPath = pEventPathList; - size_t eventPathCount = 0; + const SingleLinkedListNode * eventPath = pEventPathList; + size_t eventPathCount = 0; while (eventPath) { eventPathCount++; diff --git a/src/app/common/BUILD.gn b/src/app/common/BUILD.gn index 193d4c362e537e..1af268a477efaf 100644 --- a/src/app/common/BUILD.gn +++ b/src/app/common/BUILD.gn @@ -27,7 +27,9 @@ static_library("cluster-objects") { ] public_deps = [ + "${chip_root}/src/app:paths", "${chip_root}/src/app/data-model", + "${chip_root}/src/app/util:types", "${chip_root}/src/lib/core", "${chip_root}/src/lib/support", "${chip_root}/src/protocols/interaction_model", diff --git a/src/app/data-model/BUILD.gn b/src/app/data-model/BUILD.gn index 49a49033f0e9f2..9b04882a60ec9c 100644 --- a/src/app/data-model/BUILD.gn +++ b/src/app/data-model/BUILD.gn @@ -37,8 +37,8 @@ source_set("data-model") { # of this, in part due to zap-generated code dependency. # # - app/util/attribute-storage-null-handling.h - # - app/ConcreteAttributePath.h # + "${chip_root}/src/app:paths", "${chip_root}/src/app/common:enums", "${chip_root}/src/lib/core", "${chip_root}/src/lib/support", diff --git a/src/app/reporting/Engine.cpp b/src/app/reporting/Engine.cpp index 80dec7ed6d3cd1..2dd730c358fe0a 100644 --- a/src/app/reporting/Engine.cpp +++ b/src/app/reporting/Engine.cpp @@ -58,7 +58,7 @@ void Engine::Shutdown() mGlobalDirtySet.ReleaseAll(); } -bool Engine::IsClusterDataVersionMatch(const ObjectList * aDataVersionFilterList, +bool Engine::IsClusterDataVersionMatch(const SingleLinkedListNode * aDataVersionFilterList, const ConcreteReadAttributePath & aPath) { bool existPathMatch = false; diff --git a/src/app/reporting/Engine.h b/src/app/reporting/Engine.h index 47483d9096bfec..fccf9e08ab020f 100644 --- a/src/app/reporting/Engine.h +++ b/src/app/reporting/Engine.h @@ -179,7 +179,7 @@ class Engine // of those will fail to match. This function should return false if either nothing in the list matches the given // endpoint+cluster in the path or there is an entry in the list that matches the endpoint+cluster in the path but does not // match the current data version of that cluster. - bool IsClusterDataVersionMatch(const ObjectList * aDataVersionFilterList, + bool IsClusterDataVersionMatch(const SingleLinkedListNode * aDataVersionFilterList, const ConcreteReadAttributePath & aPath); /** diff --git a/src/app/server/BUILD.gn b/src/app/server/BUILD.gn index 4d63afda77ad42..7c661464bbaea3 100644 --- a/src/app/server/BUILD.gn +++ b/src/app/server/BUILD.gn @@ -30,6 +30,7 @@ static_library("server") { sources = [ "AclStorage.cpp", "AclStorage.h", + "AppDelegate.h", "CommissioningModeProvider.h", "CommissioningWindowManager.cpp", "CommissioningWindowManager.h", diff --git a/src/app/tests/TestAttributePathExpandIterator.cpp b/src/app/tests/TestAttributePathExpandIterator.cpp index d4da4fc95a2b8c..e5505320193b81 100644 --- a/src/app/tests/TestAttributePathExpandIterator.cpp +++ b/src/app/tests/TestAttributePathExpandIterator.cpp @@ -20,12 +20,12 @@ #include #include #include -#include #include #include #include #include #include +#include #include #include @@ -41,7 +41,7 @@ using P = app::ConcreteAttributePath; void TestAllWildcard(nlTestSuite * apSuite, void * apContext) { - app::ObjectList clusInfo; + SingleLinkedListNode clusInfo; app::ConcreteAttributePath path; P paths[] = { @@ -144,7 +144,7 @@ void TestAllWildcard(nlTestSuite * apSuite, void * apContext) void TestWildcardEndpoint(nlTestSuite * apSuite, void * apContext) { - app::ObjectList clusInfo; + SingleLinkedListNode clusInfo; clusInfo.mValue.mClusterId = Test::MockClusterId(3); clusInfo.mValue.mAttributeId = Test::MockAttributeId(3); @@ -167,7 +167,7 @@ void TestWildcardEndpoint(nlTestSuite * apSuite, void * apContext) void TestWildcardCluster(nlTestSuite * apSuite, void * apContext) { - app::ObjectList clusInfo; + SingleLinkedListNode clusInfo; clusInfo.mValue.mEndpointId = Test::kMockEndpoint3; clusInfo.mValue.mAttributeId = app::Clusters::Globals::Attributes::ClusterRevision::Id; @@ -193,7 +193,7 @@ void TestWildcardCluster(nlTestSuite * apSuite, void * apContext) void TestWildcardClusterGlobalAttributeNotInMetadata(nlTestSuite * apSuite, void * apContext) { - app::ObjectList clusInfo; + SingleLinkedListNode clusInfo; clusInfo.mValue.mEndpointId = Test::kMockEndpoint3; clusInfo.mValue.mAttributeId = app::Clusters::Globals::Attributes::AttributeList::Id; @@ -219,7 +219,7 @@ void TestWildcardClusterGlobalAttributeNotInMetadata(nlTestSuite * apSuite, void void TestWildcardAttribute(nlTestSuite * apSuite, void * apContext) { - app::ObjectList clusInfo; + SingleLinkedListNode clusInfo; clusInfo.mValue.mEndpointId = Test::kMockEndpoint2; clusInfo.mValue.mClusterId = Test::MockClusterId(3); @@ -252,7 +252,7 @@ void TestWildcardAttribute(nlTestSuite * apSuite, void * apContext) void TestNoWildcard(nlTestSuite * apSuite, void * apContext) { - app::ObjectList clusInfo; + SingleLinkedListNode clusInfo; clusInfo.mValue.mEndpointId = Test::kMockEndpoint2; clusInfo.mValue.mClusterId = Test::MockClusterId(3); clusInfo.mValue.mAttributeId = Test::MockAttributeId(3); @@ -277,21 +277,21 @@ void TestNoWildcard(nlTestSuite * apSuite, void * apContext) void TestMultipleClusInfo(nlTestSuite * apSuite, void * apContext) { - app::ObjectList clusInfo1; + SingleLinkedListNode clusInfo1; - app::ObjectList clusInfo2; + SingleLinkedListNode clusInfo2; clusInfo2.mValue.mClusterId = Test::MockClusterId(3); clusInfo2.mValue.mAttributeId = Test::MockAttributeId(3); - app::ObjectList clusInfo3; + SingleLinkedListNode clusInfo3; clusInfo3.mValue.mEndpointId = Test::kMockEndpoint3; clusInfo3.mValue.mAttributeId = app::Clusters::Globals::Attributes::ClusterRevision::Id; - app::ObjectList clusInfo4; + SingleLinkedListNode clusInfo4; clusInfo4.mValue.mEndpointId = Test::kMockEndpoint2; clusInfo4.mValue.mClusterId = Test::MockClusterId(3); - app::ObjectList clusInfo5; + SingleLinkedListNode clusInfo5; clusInfo5.mValue.mEndpointId = Test::kMockEndpoint2; clusInfo5.mValue.mClusterId = Test::MockClusterId(3); clusInfo5.mValue.mAttributeId = Test::MockAttributeId(3); diff --git a/src/app/tests/TestEventLogging.cpp b/src/app/tests/TestEventLogging.cpp index 08f950517acfde..baf43d6b398707 100644 --- a/src/app/tests/TestEventLogging.cpp +++ b/src/app/tests/TestEventLogging.cpp @@ -27,7 +27,6 @@ #include #include #include -#include #include #include #include @@ -37,6 +36,7 @@ #include #include #include +#include #include #include #include @@ -133,7 +133,7 @@ static void CheckLogState(nlTestSuite * apSuite, chip::app::EventManagement & aL } static void CheckLogReadOut(nlTestSuite * apSuite, chip::app::EventManagement & alogMgmt, chip::EventNumber startingEventNumber, - size_t expectedNumEvents, chip::app::ObjectList * clusterInfo) + size_t expectedNumEvents, chip::SingleLinkedListNode * clusterInfo) { CHIP_ERROR err; chip::TLV::TLVReader reader; @@ -236,7 +236,7 @@ static void CheckLogEventWithEvictToNextBuffer(nlTestSuite * apSuite, void * apC NL_TEST_ASSERT(apSuite, (eid4 + 1) == eid5); NL_TEST_ASSERT(apSuite, (eid5 + 1) == eid6); - chip::app::ObjectList paths[2]; + chip::SingleLinkedListNode paths[2]; paths[0].mValue.mEndpointId = kTestEndpointId1; paths[0].mValue.mClusterId = kLivenessClusterId; @@ -257,7 +257,7 @@ static void CheckLogEventWithEvictToNextBuffer(nlTestSuite * apSuite, void * apC // interested paths are path list, expect to retrieve all events for those interested paths CheckLogReadOut(apSuite, logMgmt, 0, 6, paths); - chip::app::ObjectList pathsWithWildcard[2]; + chip::SingleLinkedListNode pathsWithWildcard[2]; paths[0].mValue.mEndpointId = kTestEndpointId1; paths[0].mValue.mClusterId = kLivenessClusterId; diff --git a/src/app/tests/TestEventLoggingNoUTCTime.cpp b/src/app/tests/TestEventLoggingNoUTCTime.cpp index 43df98a790e2ba..8360f9a0813e98 100644 --- a/src/app/tests/TestEventLoggingNoUTCTime.cpp +++ b/src/app/tests/TestEventLoggingNoUTCTime.cpp @@ -26,7 +26,6 @@ #include #include #include -#include #include #include #include @@ -36,6 +35,7 @@ #include #include #include +#include #include #include #include @@ -177,7 +177,7 @@ static void CheckLogState(nlTestSuite * apSuite, chip::app::EventManagement & aL } static void CheckLogReadOut(nlTestSuite * apSuite, chip::app::EventManagement & alogMgmt, chip::EventNumber startingEventNumber, - size_t expectedNumEvents, chip::app::ObjectList * clusterInfo) + size_t expectedNumEvents, chip::SingleLinkedListNode * clusterInfo) { CHIP_ERROR err; chip::TLV::TLVReader reader; @@ -279,7 +279,7 @@ static void CheckLogEventWithEvictToNextBuffer(nlTestSuite * apSuite, void * apC NL_TEST_ASSERT(apSuite, (eid4 + 1) == eid5); NL_TEST_ASSERT(apSuite, (eid5 + 1) == eid6); - chip::app::ObjectList paths[2]; + chip::SingleLinkedListNode paths[2]; paths[0].mValue.mEndpointId = kTestEndpointId1; paths[0].mValue.mClusterId = kLivenessClusterId; @@ -300,7 +300,7 @@ static void CheckLogEventWithEvictToNextBuffer(nlTestSuite * apSuite, void * apC // interested paths are path list, expect to retrieve all events for those interested paths CheckLogReadOut(apSuite, logMgmt, 0, 6, paths); - chip::app::ObjectList pathsWithWildcard[2]; + chip::SingleLinkedListNode pathsWithWildcard[2]; paths[0].mValue.mEndpointId = kTestEndpointId1; paths[0].mValue.mClusterId = kLivenessClusterId; diff --git a/src/app/tests/TestFabricScopedEventLogging.cpp b/src/app/tests/TestFabricScopedEventLogging.cpp index f55ac63b687491..d016ad5183e1c0 100644 --- a/src/app/tests/TestFabricScopedEventLogging.cpp +++ b/src/app/tests/TestFabricScopedEventLogging.cpp @@ -27,7 +27,6 @@ #include #include #include -#include #include #include #include @@ -37,6 +36,7 @@ #include #include #include +#include #include #include #include @@ -137,7 +137,7 @@ static void CheckLogState(nlTestSuite * apSuite, chip::app::EventManagement & aL } static void CheckLogReadOut(nlTestSuite * apSuite, chip::app::EventManagement & alogMgmt, chip::EventNumber startingEventNumber, - size_t expectedNumEvents, chip::app::ObjectList * clusterInfo, + size_t expectedNumEvents, chip::SingleLinkedListNode * clusterInfo, const chip::Access::SubjectDescriptor & aSubjectDescriptor) { CHIP_ERROR err; @@ -220,7 +220,7 @@ static void CheckLogEventWithEvictToNextBuffer(nlTestSuite * apSuite, void * apC NL_TEST_ASSERT(apSuite, (eid2 + 1) == eid3); NL_TEST_ASSERT(apSuite, (eid3 + 1) == eid4); - chip::app::ObjectList paths[2]; + chip::SingleLinkedListNode paths[2]; paths[0].mValue.mEndpointId = kTestEndpointId1; paths[0].mValue.mClusterId = kLivenessClusterId; @@ -247,7 +247,7 @@ static void CheckLogEventWithEvictToNextBuffer(nlTestSuite * apSuite, void * apC CheckLogReadOut(apSuite, logMgmt, 0, 1, paths, descriptor); // Fabric event + wildcard test, only have one fabric-scoped event with fabric 2 - chip::app::ObjectList pathsWithWildcard[2]; + chip::SingleLinkedListNode pathsWithWildcard[2]; paths[0].mValue.mEndpointId = kTestEndpointId1; paths[0].mValue.mClusterId = kLivenessClusterId; diff --git a/src/app/tests/TestInteractionModelEngine.cpp b/src/app/tests/TestInteractionModelEngine.cpp index f4450635ac0b8f..fcdc7d53e1594f 100644 --- a/src/app/tests/TestInteractionModelEngine.cpp +++ b/src/app/tests/TestInteractionModelEngine.cpp @@ -52,13 +52,13 @@ class TestInteractionModelEngine #if CHIP_CONFIG_PERSIST_SUBSCRIPTIONS && CHIP_CONFIG_SUBSCRIPTION_TIMEOUT_RESUMPTION static void TestSubscriptionResumptionTimer(nlTestSuite * apSuite, void * apContext); #endif // CHIP_CONFIG_PERSIST_SUBSCRIPTIONS && CHIP_CONFIG_SUBSCRIPTION_TIMEOUT_RESUMPTION - static int GetAttributePathListLength(ObjectList * apattributePathParamsList); + static int GetAttributePathListLength(SingleLinkedListNode * apattributePathParamsList); }; -int TestInteractionModelEngine::GetAttributePathListLength(ObjectList * apAttributePathParamsList) +int TestInteractionModelEngine::GetAttributePathListLength(SingleLinkedListNode * apAttributePathParamsList) { - int length = 0; - ObjectList * runner = apAttributePathParamsList; + int length = 0; + SingleLinkedListNode * runner = apAttributePathParamsList; while (runner != nullptr) { runner = runner->mpNext; @@ -74,7 +74,7 @@ void TestInteractionModelEngine::TestAttributePathParamsPushRelease(nlTestSuite err = InteractionModelEngine::GetInstance()->Init(&ctx.GetExchangeManager(), &ctx.GetFabricTable(), app::reporting::GetDefaultReportScheduler()); NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); - ObjectList * attributePathParamsList = nullptr; + SingleLinkedListNode * attributePathParamsList = nullptr; AttributePathParams attributePathParams1; AttributePathParams attributePathParams2; AttributePathParams attributePathParams3; @@ -112,7 +112,7 @@ void TestInteractionModelEngine::TestRemoveDuplicateConcreteAttribute(nlTestSuit err = InteractionModelEngine::GetInstance()->Init(&ctx.GetExchangeManager(), &ctx.GetFabricTable(), app::reporting::GetDefaultReportScheduler()); NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); - ObjectList * attributePathParamsList = nullptr; + SingleLinkedListNode * attributePathParamsList = nullptr; AttributePathParams attributePathParams1; AttributePathParams attributePathParams2; AttributePathParams attributePathParams3; diff --git a/src/app/util/BUILD.gn b/src/app/util/BUILD.gn index 31d6b9e881956a..821ba51a9badcc 100644 --- a/src/app/util/BUILD.gn +++ b/src/app/util/BUILD.gn @@ -14,3 +14,11 @@ import("//build_overrides/chip.gni") import("${chip_root}/src/app/common_flags.gni") + +source_set("types") { + sources = [ + "attribute-metadata.h", + "basic-types.h", + "types_stub.h", + ] +} diff --git a/src/app/util/mock/BUILD.gn b/src/app/util/mock/BUILD.gn index 5918318107fd35..be56bc69032844 100644 --- a/src/app/util/mock/BUILD.gn +++ b/src/app/util/mock/BUILD.gn @@ -20,7 +20,10 @@ config("mock_include") { source_set("mock_ember") { sources = [ + "Constants.h", + "Functions.h", "MockNodeConfig.cpp", + "MockNodeConfig.h", "attribute-storage.cpp", ] diff --git a/src/lib/support/BUILD.gn b/src/lib/support/BUILD.gn index 2342b26ae66d70..02ca1eef593def 100644 --- a/src/lib/support/BUILD.gn +++ b/src/lib/support/BUILD.gn @@ -212,6 +212,7 @@ static_library("support") { "Iterators.h", "LambdaBridge.h", "LifetimePersistedCounter.h", + "LinkedList.h", "ObjectLifeCycle.h", "OwnerOf.h", "PersistedCounter.h", diff --git a/src/app/ObjectList.h b/src/lib/support/LinkedList.h similarity index 90% rename from src/app/ObjectList.h rename to src/lib/support/LinkedList.h index 416db0bb70a6b5..d830c2b3a23351 100644 --- a/src/app/ObjectList.h +++ b/src/lib/support/LinkedList.h @@ -22,13 +22,13 @@ #include namespace chip { -namespace app { +/// A very basic single-linked list template -struct ObjectList +struct SingleLinkedListNode { T mValue; - ObjectList * mpNext = nullptr; + SingleLinkedListNode * mpNext = nullptr; size_t Count() const { @@ -41,5 +41,4 @@ struct ObjectList } }; -} // namespace app } // namespace chip From 19c49a8699403ae0f2da2083ec506408b6a4ae31 Mon Sep 17 00:00:00 2001 From: William Date: Tue, 20 Feb 2024 13:34:07 +0000 Subject: [PATCH 029/385] Run RVC test against the RVC example app in CI. (#32079) * Run RVC test against the RVC example app in CI. * Restyled by gn * Added the RVC example app to the built examples. * Removed -app to make things consistent with other appliences. * Added missing copy instructons and fixed typos in the rvc app name. * Added the rvc-app pics values to the ci-pics-values since the tests are run against the rvc-app and there isn't currently a way to select a different YICS file when running the yaml tests. * Added missing PICS to the ci-pics-values. * Fixed typos in the tests workflow. * Update src/app/tests/suites/certification/ci-pics-values Co-authored-by: Petru Lauric <81822411+plauric@users.noreply.github.com> * Added 1 ms sleep after sending pipe commands form the test scripts. This removes the test flakyness in CI. * Restyled by autopep8 * Restyled by isort * Removed the RVC and MWO apps from the cirque tests as they are not needed following review comments. * Added todo with link to issue. --------- Co-authored-by: Restyled.io Co-authored-by: Petru Lauric <81822411+plauric@users.noreply.github.com> --- .github/workflows/darwin-tests.yaml | 2 + .github/workflows/tests.yaml | 18 +- BUILD.gn | 12 ++ .../docker/images/chip-cert-bins/Dockerfile | 4 + scripts/build/builders/host.py | 4 +- scripts/build/gn_gen_cirque.sh | 2 +- scripts/tests/chiptest/__init__.py | 2 + scripts/tests/chiptest/linux.py | 1 + scripts/tests/chiptest/test_definition.py | 6 +- scripts/tests/run_test_suite.py | 9 +- .../tests/suites/certification/ci-pics-values | 161 +++++++++++------- src/python_testing/TC_RVCCLEANM_2_1.py | 4 + src/python_testing/TC_RVCCLEANM_2_2.py | 5 + src/python_testing/TC_RVCOPSTATE_2_1.py | 4 + src/python_testing/TC_RVCOPSTATE_2_3.py | 3 + src/python_testing/TC_RVCOPSTATE_2_4.py | 4 + src/python_testing/TC_RVCRUNM_2_1.py | 4 + src/python_testing/TC_RVCRUNM_2_2.py | 5 + 18 files changed, 180 insertions(+), 70 deletions(-) diff --git a/.github/workflows/darwin-tests.yaml b/.github/workflows/darwin-tests.yaml index 05943be5b0e155..e6e14ec4929a11 100644 --- a/.github/workflows/darwin-tests.yaml +++ b/.github/workflows/darwin-tests.yaml @@ -100,6 +100,7 @@ jobs: --target darwin-x64-bridge-${BUILD_VARIANT} \ --target darwin-x64-lit-icd-${BUILD_VARIANT} \ --target darwin-x64-microwave-oven-${BUILD_VARIANT} \ + --target darwin-x64-rvc-${BUILD_VARIANT} \ build \ --copy-artifacts-to objdir-clone \ " @@ -120,6 +121,7 @@ jobs: --tv-app ./out/darwin-x64-tv-app-${BUILD_VARIANT}/chip-tv-app \ --bridge-app ./out/darwin-x64-bridge-${BUILD_VARIANT}/chip-bridge-app \ --microwave-oven-app ./out/darwin-x64-microwave-oven-${BUILD_VARIANT}/chip-microwave-oven-app \ + --rvc-app ./out/darwin-x64-rvc-${BUILD_VARIANT}/chip-rvc-app \ " - name: Run OTA Test run: | diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index f083cd70bccd7c..83d921c2fa4188 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yaml @@ -213,6 +213,7 @@ jobs: --target linux-x64-bridge-${BUILD_VARIANT} \ --target linux-x64-lit-icd-${BUILD_VARIANT} \ --target linux-x64-microwave-oven-${BUILD_VARIANT} \ + --target linux-x64-rvc-${BUILD_VARIANT} \ build \ --copy-artifacts-to objdir-clone \ " @@ -234,6 +235,7 @@ jobs: --bridge-app ./out/linux-x64-bridge-${BUILD_VARIANT}/chip-bridge-app \ --lit-icd-app ./out/linux-x64-lit-icd-${BUILD_VARIANT}/lit-icd-app \ --microwave-oven-app ./out/linux-x64-microwave-oven-${BUILD_VARIANT}/chip-microwave-oven-app \ + --rvc-app ./out/linux-x64-rvc-${BUILD_VARIANT}/chip-rvc-app \ " - name: Run purposeful failure tests using the python parser sending commands to chip-tool @@ -274,6 +276,7 @@ jobs: --bridge-app ./out/linux-x64-bridge-${BUILD_VARIANT}/chip-bridge-app \ --lit-icd-app ./out/linux-x64-lit-icd-${BUILD_VARIANT}/lit-icd-app \ --microwave-oven-app ./out/linux-x64-microwave-oven-${BUILD_VARIANT}/chip-microwave-oven-app \ + --rvc-app ./out/linux-x64-rvc-${BUILD_VARIANT}/chip-rvc-app \ " - name: Run Tests using chip-repl (including slow) if: github.event_name == 'push' @@ -292,6 +295,7 @@ jobs: --bridge-app ./out/linux-x64-bridge-${BUILD_VARIANT}/chip-bridge-app \ --lit-icd-app ./out/linux-x64-lit-icd-${BUILD_VARIANT}/lit-icd-app \ --microwave-oven-app ./out/linux-x64-microwave-oven-${BUILD_VARIANT}/chip-microwave-oven-app \ + --rvc-app ./out/linux-x64-rvc-${BUILD_VARIANT}/chip-rvc-app \ " - name: Uploading core files uses: actions/upload-artifact@v4 @@ -359,6 +363,7 @@ jobs: --target darwin-x64-bridge-${BUILD_VARIANT} \ --target darwin-x64-lit-icd-${BUILD_VARIANT} \ --target darwin-x64-microwave-oven-${BUILD_VARIANT} \ + --target darwin-x64-rvc-${BUILD_VARIANT} \ build \ --copy-artifacts-to objdir-clone \ " @@ -381,6 +386,7 @@ jobs: --bridge-app ./out/darwin-x64-bridge-${BUILD_VARIANT}/chip-bridge-app \ --lit-icd-app ./out/darwin-x64-lit-icd-${BUILD_VARIANT}/lit-icd-app \ --microwave-oven-app ./out/darwin-x64-microwave-oven-${BUILD_VARIANT}/chip-microwave-oven-app \ + --rvc-app ./out/darwin-x64-rvc-${BUILD_VARIANT}/chip-rvc-app \ " - name: Run purposeful failure tests using the python parser sending commands to chip-tool @@ -460,6 +466,7 @@ jobs: --target linux-x64-lit-icd-ipv6only-no-ble-no-wifi-tsan-clang-test \ --target linux-x64-energy-management-ipv6only-no-ble-no-wifi-tsan-clang-test \ --target linux-x64-microwave-oven-ipv6only-no-ble-no-wifi-tsan-clang-test \ + --target linux-x64-rvc-ipv6only-no-ble-no-wifi-tsan-clang-test \ --target linux-x64-python-bindings \ build \ --copy-artifacts-to objdir-clone \ @@ -504,8 +511,6 @@ jobs: scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --app out/linux-x64-all-clusters-ipv6only-no-ble-no-wifi-tsan-clang-test/chip-all-clusters-app --factoryreset --app-args "--discriminator 1234 --KVS kvs1 --trace-to json:out/trace_data/app-{SCRIPT_BASE_NAME}.json" --script "src/python_testing/TC_IDM_4_2.py" --script-args "--storage-path admin_storage.json --commissioning-method on-network --discriminator 1234 --passcode 20202021 --trace-to json:out/trace_data/test-{SCRIPT_BASE_NAME}.json --trace-to perfetto:out/trace_data/test-{SCRIPT_BASE_NAME}.perfetto"' scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --app out/linux-x64-all-clusters-ipv6only-no-ble-no-wifi-tsan-clang-test/chip-all-clusters-app --factoryreset --app-args "--discriminator 1234 --KVS kvs1 --trace-to json:out/trace_data/app-{SCRIPT_BASE_NAME}.json" --script "src/python_testing/TC_PWRTL_2_1.py" --script-args "--storage-path admin_storage.json --commissioning-method on-network --discriminator 1234 --passcode 20202021 --trace-to json:out/trace_data/test-{SCRIPT_BASE_NAME}.json --trace-to perfetto:out/trace_data/test-{SCRIPT_BASE_NAME}.perfetto"' scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --app out/linux-x64-all-clusters-ipv6only-no-ble-no-wifi-tsan-clang-test/chip-all-clusters-app --factoryreset --app-args "--discriminator 1234 --KVS kvs1 --trace-to json:out/trace_data/app-{SCRIPT_BASE_NAME}.json" --script "src/python_testing/TC_RR_1_1.py" --script-args "--storage-path admin_storage.json --commissioning-method on-network --discriminator 1234 --passcode 20202021 --trace-to json:out/trace_data/test-{SCRIPT_BASE_NAME}.json --trace-to perfetto:out/trace_data/test-{SCRIPT_BASE_NAME}.perfetto"' - scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --app out/linux-x64-all-clusters-ipv6only-no-ble-no-wifi-tsan-clang-test/chip-all-clusters-app --factoryreset --app-args "--discriminator 1234 --KVS kvs1 --trace-to json:out/trace_data/app-{SCRIPT_BASE_NAME}.json" --script "src/python_testing/TC_RVCCLEANM_1_2.py" --script-args "--int-arg PIXIT_ENDPOINT:1 --storage-path admin_storage.json --commissioning-method on-network --discriminator 1234 --passcode 20202021 --trace-to json:out/trace_data/test-{SCRIPT_BASE_NAME}.json --trace-to perfetto:out/trace_data/test-{SCRIPT_BASE_NAME}.perfetto"' - scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --app out/linux-x64-all-clusters-ipv6only-no-ble-no-wifi-tsan-clang-test/chip-all-clusters-app --factoryreset --app-args "--discriminator 1234 --KVS kvs1 --trace-to json:out/trace_data/app-{SCRIPT_BASE_NAME}.json" --script "src/python_testing/TC_RVCRUNM_1_2.py" --script-args "--int-arg PIXIT_ENDPOINT:1 --storage-path admin_storage.json --commissioning-method on-network --discriminator 1234 --passcode 20202021 --trace-to json:out/trace_data/test-{SCRIPT_BASE_NAME}.json --trace-to perfetto:out/trace_data/test-{SCRIPT_BASE_NAME}.perfetto"' scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --app out/linux-x64-all-clusters-ipv6only-no-ble-no-wifi-tsan-clang-test/chip-all-clusters-app --factoryreset --app-args "--discriminator 1234 --KVS kvs1 --trace-to json:out/trace_data/app-{SCRIPT_BASE_NAME}.json" --script "src/python_testing/TC_SC_3_6.py" --script-args "--storage-path admin_storage.json --commissioning-method on-network --discriminator 1234 --passcode 20202021 --trace-to json:out/trace_data/test-{SCRIPT_BASE_NAME}.json --trace-to perfetto:out/trace_data/test-{SCRIPT_BASE_NAME}.perfetto"' scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --app out/linux-x64-all-clusters-ipv6only-no-ble-no-wifi-tsan-clang-test/chip-all-clusters-app --factoryreset --app-args "--discriminator 1234 --KVS kvs1 --trace-to json:out/trace_data/app-{SCRIPT_BASE_NAME}.json" --script "src/python_testing/TC_TIMESYNC_2_1.py" --script-args "--storage-path admin_storage.json --commissioning-method on-network --discriminator 1234 --passcode 20202021 --PICS src/app/tests/suites/certification/ci-pics-values --trace-to json:out/trace_data/test-{SCRIPT_BASE_NAME}.json --trace-to perfetto:out/trace_data/test-{SCRIPT_BASE_NAME}.perfetto"' scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --app out/linux-x64-all-clusters-ipv6only-no-ble-no-wifi-tsan-clang-test/chip-all-clusters-app --factoryreset --app-args "--discriminator 1234 --KVS kvs1 --trace-to json:out/trace_data/app-{SCRIPT_BASE_NAME}.json" --script "src/python_testing/TC_TIMESYNC_2_10.py" --script-args "--storage-path admin_storage.json --commissioning-method on-network --discriminator 1234 --passcode 20202021 --PICS src/app/tests/suites/certification/ci-pics-values --trace-to json:out/trace_data/test-{SCRIPT_BASE_NAME}.json --trace-to perfetto:out/trace_data/test-{SCRIPT_BASE_NAME}.perfetto"' @@ -543,6 +548,15 @@ jobs: scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --app out/linux-x64-microwave-oven-ipv6only-no-ble-no-wifi-tsan-clang-test/chip-microwave-oven-app --factoryreset --app-args "--discriminator 1234 --KVS kvs1 --trace_file json:out/trace_data/app-{SCRIPT_BASE_NAME}.json" --script "src/python_testing/TC_MWOCTRL_2_3.py" --script-args "--storage-path admin_storage.json --commissioning-method on-network --discriminator 1234 --passcode 20202021 --trace-to json:out/trace_data/test-{SCRIPT_BASE_NAME}.json --trace-to perfetto:out/trace_data/test-{SCRIPT_BASE_NAME}.perfetto"' scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --app out/linux-x64-microwave-oven-ipv6only-no-ble-no-wifi-tsan-clang-test/chip-microwave-oven-app --factoryreset --app-args "--discriminator 1234 --KVS kvs1 --trace_file json:out/trace_data/app-{SCRIPT_BASE_NAME}.json" --script "src/python_testing/TC_MWOCTRL_2_4.py" --script-args "--storage-path admin_storage.json --commissioning-method on-network --discriminator 1234 --passcode 20202021 --trace-to json:out/trace_data/test-{SCRIPT_BASE_NAME}.json --trace-to perfetto:out/trace_data/test-{SCRIPT_BASE_NAME}.perfetto"' scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --app out/linux-x64-microwave-oven-ipv6only-no-ble-no-wifi-tsan-clang-test/chip-microwave-oven-app --factoryreset --app-args "--discriminator 1234 --KVS kvs1 --trace_file json:out/trace_data/app-{SCRIPT_BASE_NAME}.json" --script "src/python_testing/TC_MWOM_1_2.py" --script-args "--storage-path admin_storage.json --commissioning-method on-network --discriminator 1234 --passcode 20202021 --trace-to json:out/trace_data/test-{SCRIPT_BASE_NAME}.json --trace-to perfetto:out/trace_data/test-{SCRIPT_BASE_NAME}.perfetto"' + scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --app out/linux-x64-rvc-ipv6only-no-ble-no-wifi-tsan-clang-test/chip-rvc-app --factoryreset --app-args "--discriminator 1234 --KVS kvs1 --trace_file json:out/trace_data/app-{SCRIPT_BASE_NAME}.json" --script "src/python_testing/TC_RVCRUNM_1_2.py" --script-args "--storage-path admin_storage.json --commissioning-method on-network --discriminator 1234 --passcode 20202021 --PICS examples/rvc-app/rvc-common/pics/rvc-app-pics-values --endpoint 1 --trace-to json:out/trace_data/test-{SCRIPT_BASE_NAME}.json --trace-to perfetto:out/trace_data/test-{SCRIPT_BASE_NAME}.perfetto"' + scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --app out/linux-x64-rvc-ipv6only-no-ble-no-wifi-tsan-clang-test/chip-rvc-app --factoryreset --app-args "--discriminator 1234 --KVS kvs1 --trace_file json:out/trace_data/app-{SCRIPT_BASE_NAME}.json" --script "src/python_testing/TC_RVCRUNM_2_1.py" --script-args "--storage-path admin_storage.json --commissioning-method on-network --discriminator 1234 --passcode 20202021 --PICS examples/rvc-app/rvc-common/pics/rvc-app-pics-values --endpoint 1 --trace-to json:out/trace_data/test-{SCRIPT_BASE_NAME}.json --trace-to perfetto:out/trace_data/test-{SCRIPT_BASE_NAME}.perfetto --int-arg PIXIT.RVCRUNM.MODE_CHANGE_OK:0 PIXIT.RVCRUNM.MODE_CHANGE_FAIL:2"' + scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --app out/linux-x64-rvc-ipv6only-no-ble-no-wifi-tsan-clang-test/chip-rvc-app --factoryreset --app-args "--discriminator 1234 --KVS kvs1 --trace_file json:out/trace_data/app-{SCRIPT_BASE_NAME}.json" --script "src/python_testing/TC_RVCRUNM_2_2.py" --script-args "--storage-path admin_storage.json --commissioning-method on-network --discriminator 1234 --passcode 20202021 --PICS examples/rvc-app/rvc-common/pics/rvc-app-pics-values --endpoint 1 --trace-to json:out/trace_data/test-{SCRIPT_BASE_NAME}.json --trace-to perfetto:out/trace_data/test-{SCRIPT_BASE_NAME}.perfetto --int-arg PIXIT.RVCRUNM.MODE_A:1 PIXIT.RVCRUNM.MODE_B:2"' + scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --app out/linux-x64-rvc-ipv6only-no-ble-no-wifi-tsan-clang-test/chip-rvc-app --factoryreset --app-args "--discriminator 1234 --KVS kvs1 --trace_file json:out/trace_data/app-{SCRIPT_BASE_NAME}.json" --script "src/python_testing/TC_RVCCLEANM_1_2.py" --script-args "--storage-path admin_storage.json --commissioning-method on-network --discriminator 1234 --passcode 20202021 --PICS examples/rvc-app/rvc-common/pics/rvc-app-pics-values --endpoint 1 --trace-to json:out/trace_data/test-{SCRIPT_BASE_NAME}.json --trace-to perfetto:out/trace_data/test-{SCRIPT_BASE_NAME}.perfetto"' + scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --app out/linux-x64-rvc-ipv6only-no-ble-no-wifi-tsan-clang-test/chip-rvc-app --factoryreset --app-args "--discriminator 1234 --KVS kvs1 --trace_file json:out/trace_data/app-{SCRIPT_BASE_NAME}.json" --script "src/python_testing/TC_RVCCLEANM_2_1.py" --script-args "--storage-path admin_storage.json --commissioning-method on-network --discriminator 1234 --passcode 20202021 --PICS examples/rvc-app/rvc-common/pics/rvc-app-pics-values --endpoint 1 --trace-to json:out/trace_data/test-{SCRIPT_BASE_NAME}.json --trace-to perfetto:out/trace_data/test-{SCRIPT_BASE_NAME}.perfetto --int-arg PIXIT.RVCCLEANM.MODE_CHANGE_FAIL:1 PIXIT.RVCCLEANM.MODE_CHANGE_OK:2"' + scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --app out/linux-x64-rvc-ipv6only-no-ble-no-wifi-tsan-clang-test/chip-rvc-app --factoryreset --app-args "--discriminator 1234 --KVS kvs1 --trace_file json:out/trace_data/app-{SCRIPT_BASE_NAME}.json" --script "src/python_testing/TC_RVCCLEANM_2_2.py" --script-args "--storage-path admin_storage.json --commissioning-method on-network --discriminator 1234 --passcode 20202021 --PICS examples/rvc-app/rvc-common/pics/rvc-app-pics-values --endpoint 1 --trace-to json:out/trace_data/test-{SCRIPT_BASE_NAME}.json --trace-to perfetto:out/trace_data/test-{SCRIPT_BASE_NAME}.perfetto"' + scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --app out/linux-x64-rvc-ipv6only-no-ble-no-wifi-tsan-clang-test/chip-rvc-app --factoryreset --app-args "--discriminator 1234 --KVS kvs1 --trace_file json:out/trace_data/app-{SCRIPT_BASE_NAME}.json" --script "src/python_testing/TC_RVCOPSTATE_2_1.py" --script-args "--storage-path admin_storage.json --commissioning-method on-network --discriminator 1234 --passcode 20202021 --PICS examples/rvc-app/rvc-common/pics/rvc-app-pics-values --endpoint 1 --trace-to json:out/trace_data/test-{SCRIPT_BASE_NAME}.json --trace-to perfetto:out/trace_data/test-{SCRIPT_BASE_NAME}.perfetto"' + scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --app out/linux-x64-rvc-ipv6only-no-ble-no-wifi-tsan-clang-test/chip-rvc-app --factoryreset --app-args "--discriminator 1234 --KVS kvs1 --trace_file json:out/trace_data/app-{SCRIPT_BASE_NAME}.json" --script "src/python_testing/TC_RVCOPSTATE_2_3.py" --script-args "--storage-path admin_storage.json --commissioning-method on-network --discriminator 1234 --passcode 20202021 --PICS examples/rvc-app/rvc-common/pics/rvc-app-pics-values --endpoint 1 --trace-to json:out/trace_data/test-{SCRIPT_BASE_NAME}.json --trace-to perfetto:out/trace_data/test-{SCRIPT_BASE_NAME}.perfetto"' + scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --app out/linux-x64-rvc-ipv6only-no-ble-no-wifi-tsan-clang-test/chip-rvc-app --factoryreset --app-args "--discriminator 1234 --KVS kvs1 --trace_file json:out/trace_data/app-{SCRIPT_BASE_NAME}.json" --script "src/python_testing/TC_RVCOPSTATE_2_4.py" --script-args "--storage-path admin_storage.json --commissioning-method on-network --discriminator 1234 --passcode 20202021 --PICS examples/rvc-app/rvc-common/pics/rvc-app-pics-values --endpoint 1 --trace-to json:out/trace_data/test-{SCRIPT_BASE_NAME}.json --trace-to perfetto:out/trace_data/test-{SCRIPT_BASE_NAME}.perfetto"' - name: Uploading core files uses: actions/upload-artifact@v4 if: ${{ failure() && !env.ACT }} diff --git a/BUILD.gn b/BUILD.gn index 838ea743f348c8..a96f2a2e67265a 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -363,6 +363,10 @@ if (current_toolchain != "${dir_pw_toolchain}/default:default") { enable_linux_lit_icd_app_build = enable_default_builds && (host_os == "linux" || host_os == "mac") + # Build the Linux RVC app example. + enable_linux_rvc_app_build = + enable_default_builds && (host_os == "linux" || host_os == "mac") + # Build the cc13x2x7_26x2x7 lock app example. enable_cc13x2x7_26x2x7_lock_app_build = enable_ti_simplelink_builds @@ -744,6 +748,14 @@ if (current_toolchain != "${dir_pw_toolchain}/default:default") { extra_build_deps += [ ":genio_shell_app" ] } + if (enable_linux_rvc_app_build) { + group("linux_rvc_app") { + deps = [ "${chip_root}/examples/rvc-app/linux(${standalone_toolchain})" ] + } + + extra_build_deps += [ ":linux_rvc_app" ] + } + group("default") { deps = extra_build_deps + builds } diff --git a/integrations/docker/images/chip-cert-bins/Dockerfile b/integrations/docker/images/chip-cert-bins/Dockerfile index 33662e66d3a9ba..dff19ccd0137ef 100644 --- a/integrations/docker/images/chip-cert-bins/Dockerfile +++ b/integrations/docker/images/chip-cert-bins/Dockerfile @@ -194,6 +194,7 @@ RUN case ${TARGETPLATFORM} in \ --target linux-x64-lit-icd-ipv6only \ --target linux-x64-energy-management-ipv6only \ --target linux-x64-microwave-oven-ipv6only \ + --target linux-x64-rvc-ipv6only \ build \ && mv out/linux-x64-chip-tool-ipv6only-platform-mdns/chip-tool out/chip-tool \ && mv out/linux-x64-shell-ipv6only-platform-mdns/chip-shell out/chip-shell \ @@ -213,6 +214,7 @@ RUN case ${TARGETPLATFORM} in \ && mv out/linux-x64-lit-icd-ipv6only/lit-icd-app out/lit-icd-app \ && mv out/linux-x64-energy-management-ipv6only/chip-energy-management-app out/chip-energy-management-app \ && mv out/linux-x64-microwave-oven-ipv6only/chip-microwave-oven-app out/chip-microwave-oven-app \ + && mv out/linux-x64-rvc-ipv6only/chip-rvc-app out/chip-rvc-app \ ;; \ "linux/arm64")\ set -x \ @@ -255,6 +257,7 @@ RUN case ${TARGETPLATFORM} in \ && mv out/linux-arm64-lit-icd-ipv6only/lit-icd-app out/lit-icd-app \ && mv out/linux-arm64-energy-management-ipv6only/chip-energy-management-app out/chip-energy-management-app \ && mv out/linux-arm64-microwave-oven-ipv6only/chip-microwave-oven-app out/chip-microwave-oven-app \ + && mv out/linux-arm64-rvc-ipv6only/chip-rvc-app out/chip-rvc-app \ ;; \ *) ;; \ esac @@ -287,6 +290,7 @@ COPY --from=chip-build-cert-bins /root/connectedhomeip/out/chip-app1 chip-app1 COPY --from=chip-build-cert-bins /root/connectedhomeip/out/lit-icd-app lit-icd-app COPY --from=chip-build-cert-bins /root/connectedhomeip/out/chip-energy-management-app chip-energy-management-app COPY --from=chip-build-cert-bins /root/connectedhomeip/out/chip-microwave-oven-app chip-microwave-oven-app +COPY --from=chip-build-cert-bins /root/connectedhomeip/out/chip-rvc-app chip-rvc-app # Stage 3.1: Setup the Matter Python environment COPY --from=chip-build-cert-bins /root/connectedhomeip/out/python_lib python_lib diff --git a/scripts/build/builders/host.py b/scripts/build/builders/host.py index a6ad8f343e0b16..fcb609c70e941f 100644 --- a/scripts/build/builders/host.py +++ b/scripts/build/builders/host.py @@ -234,8 +234,8 @@ def OutputNames(self): yield 'refrigerator-app' yield 'refrigerator-app.map' elif self == HostApp.RVC: - yield 'rvc-app' - yield 'rvc-app.map' + yield 'chip-rvc-app' + yield 'chip-rvc-app.map' elif self == HostApp.AIR_PURIFIER: yield 'air-purifier-app' yield 'air-purifier-app.map' diff --git a/scripts/build/gn_gen_cirque.sh b/scripts/build/gn_gen_cirque.sh index a0713f571189ab..d6f6bd86905a0e 100755 --- a/scripts/build/gn_gen_cirque.sh +++ b/scripts/build/gn_gen_cirque.sh @@ -36,7 +36,7 @@ echo "Setup build environment" source "./scripts/activate.sh" echo "Build: GN configure" -gn --root="$CHIP_ROOT" gen --check --fail-on-unused-args out/debug --args='target_os="all"'"chip_build_tests=false chip_enable_wifi=false chip_im_force_fabric_quota_check=true enable_default_builds=false enable_host_gcc_build=true enable_standalone_chip_tool_build=true enable_linux_all_clusters_app_build=true enable_linux_lighting_app_build=true enable_microwave_oven_app_build=true enable_linux_lit_icd_app_build=true" +gn --root="$CHIP_ROOT" gen --check --fail-on-unused-args out/debug --args='target_os="all"'"chip_build_tests=false chip_enable_wifi=false chip_im_force_fabric_quota_check=true enable_default_builds=false enable_host_gcc_build=true enable_standalone_chip_tool_build=true enable_linux_all_clusters_app_build=true enable_linux_lighting_app_build=true enable_linux_lit_icd_app_build=true" echo "Build: Ninja build" time ninja -C out/debug all check diff --git a/scripts/tests/chiptest/__init__.py b/scripts/tests/chiptest/__init__.py index 505a5e163cc5c4..ecfd98be618480 100644 --- a/scripts/tests/chiptest/__init__.py +++ b/scripts/tests/chiptest/__init__.py @@ -313,6 +313,8 @@ def target_for_name(name: str): return TestTarget.LIT_ICD if name.startswith("Test_TC_MWOCTRL_") or name.startswith("Test_TC_MWOM_"): return TestTarget.MWO + if name.startswith("Test_TC_RVCRUNM_") or name.startswith("Test_TC_RVCCLEANM_") or name.startswith("Test_TC_RVCOPSTATE_"): + return TestTarget.RVC return TestTarget.ALL_CLUSTERS diff --git a/scripts/tests/chiptest/linux.py b/scripts/tests/chiptest/linux.py index 1d679ee236a3fd..3dbd851be26b47 100644 --- a/scripts/tests/chiptest/linux.py +++ b/scripts/tests/chiptest/linux.py @@ -183,6 +183,7 @@ def PathsWithNetworkNamespaces(paths: ApplicationPaths) -> ApplicationPaths: tv_app='ip netns exec app'.split() + paths.tv_app, lit_icd_app='ip netns exec app'.split() + paths.lit_icd_app, microwave_oven_app='ip netns exec app'.split() + paths.microwave_oven_app, + rvc_app='ip netns exec app'.split() + paths.rvc_app, bridge_app='ip netns exec app'.split() + paths.bridge_app, chip_repl_yaml_tester_cmd='ip netns exec tool'.split() + paths.chip_repl_yaml_tester_cmd, chip_tool_with_python_cmd='ip netns exec tool'.split() + paths.chip_tool_with_python_cmd, diff --git a/scripts/tests/chiptest/test_definition.py b/scripts/tests/chiptest/test_definition.py index 95f7a631928ba4..12c59cfad0cc41 100644 --- a/scripts/tests/chiptest/test_definition.py +++ b/scripts/tests/chiptest/test_definition.py @@ -176,6 +176,7 @@ class TestTarget(Enum): BRIDGE = auto() LIT_ICD = auto() MWO = auto() + RVC = auto() @dataclass @@ -191,10 +192,11 @@ class ApplicationPaths: microwave_oven_app: typing.List[str] chip_repl_yaml_tester_cmd: typing.List[str] chip_tool_with_python_cmd: typing.List[str] + rvc_app: typing.List[str] def items(self): return [self.chip_tool, self.all_clusters_app, self.lock_app, self.ota_provider_app, self.ota_requestor_app, - self.tv_app, self.bridge_app, self.lit_icd_app, self.microwave_oven_app, self.chip_repl_yaml_tester_cmd, self.chip_tool_with_python_cmd] + self.tv_app, self.bridge_app, self.lit_icd_app, self.microwave_oven_app, self.chip_repl_yaml_tester_cmd, self.chip_tool_with_python_cmd, self.rvc_app] @dataclass @@ -305,6 +307,8 @@ def Run(self, runner, apps_register, paths: ApplicationPaths, pics_file: str, target_app = paths.lit_icd_app elif self.target == TestTarget.MWO: target_app = paths.microwave_oven_app + elif self.target == TestTarget.RVC: + target_app = paths.rvc_app else: raise Exception("Unknown test target - " "don't know which application to run") diff --git a/scripts/tests/run_test_suite.py b/scripts/tests/run_test_suite.py index 9dbe01d9dbcfa0..2df88cd6740653 100755 --- a/scripts/tests/run_test_suite.py +++ b/scripts/tests/run_test_suite.py @@ -257,6 +257,9 @@ def cmd_list(context): @click.option( '--microwave-oven-app', help='what microwave oven app to use') +@click.option( + '--rvc-app', + help='what rvc app to use') @click.option( '--chip-repl-yaml-tester', help='what python script to use for running yaml tests using chip-repl as controller') @@ -288,7 +291,7 @@ def cmd_list(context): help='Number of tests that are expected to fail in each iteration. Overall test will pass if the number of failures matches this. Nonzero values require --keep-going') @click.pass_context def cmd_run(context, iterations, all_clusters_app, lock_app, ota_provider_app, ota_requestor_app, - tv_app, bridge_app, lit_icd_app, microwave_oven_app, chip_repl_yaml_tester, chip_tool_with_python, pics_file, keep_going, test_timeout_seconds, expected_failures): + tv_app, bridge_app, lit_icd_app, microwave_oven_app, rvc_app, chip_repl_yaml_tester, chip_tool_with_python, pics_file, keep_going, test_timeout_seconds, expected_failures): if expected_failures != 0 and not keep_going: logging.exception(f"'--expected-failures {expected_failures}' used without '--keep-going'") sys.exit(2) @@ -321,6 +324,9 @@ def cmd_run(context, iterations, all_clusters_app, lock_app, ota_provider_app, o if microwave_oven_app is None: microwave_oven_app = paths_finder.get('chip-microwave-oven-app') + if rvc_app is None: + rvc_app = paths_finder.get('chip-rvc-app') + if chip_repl_yaml_tester is None: chip_repl_yaml_tester = paths_finder.get('yamltest_with_chip_repl_tester.py') @@ -341,6 +347,7 @@ def cmd_run(context, iterations, all_clusters_app, lock_app, ota_provider_app, o bridge_app=[bridge_app], lit_icd_app=[lit_icd_app], microwave_oven_app=[microwave_oven_app], + rvc_app=[rvc_app], chip_repl_yaml_tester_cmd=['python3'] + [chip_repl_yaml_tester], chip_tool_with_python_cmd=['python3'] + [chip_tool_with_python], ) diff --git a/src/app/tests/suites/certification/ci-pics-values b/src/app/tests/suites/certification/ci-pics-values index f200ad302931ff..021f52e6547ec8 100644 --- a/src/app/tests/suites/certification/ci-pics-values +++ b/src/app/tests/suites/certification/ci-pics-values @@ -2477,97 +2477,132 @@ REFALM.S.E00=1 REFALM.S.C00.Rsp=1 REFALM.S.C01.Rsp=1 -# RVC CLEAN MODE CLUSTER - +# PICS for the RVC app +# These are required to be here because currently there isn't a way to select a different PICS +# file when running the yaml tests in CI RVCCLEANM.S=1 - -#Server RVCCLEANM.S.A0000=1 RVCCLEANM.S.A0001=1 - -#Feature -RVCCLEANM.S.F00=0 - -#commands RVCCLEANM.S.C00.Rsp=1 RVCCLEANM.S.C01.Tx=1 - +RVCCLEANM.S.F00=0 RVCCLEANM.S.M.CAN_TEST_MODE_FAILURE=1 -#PIXIT -PIXIT.RVCCLEANM.MODE_CHANGE_FAIL=1 -PIXIT.RVCCLEANM.MODE_CHANGE_OK=1 - -# RVC OPERATIONAL STATE CLUSTER RVCOPSTATE.S=1 -RVCOPSTATE.C=1 - -#ManuallyControlled -# These are the PICS supported by the all-clusters-app - -RVCOPSTATE.S.M.ST_STOPPED=1 -RVCOPSTATE.S.M.ST_RUNNING=1 -RVCOPSTATE.S.M.ST_PAUSED=1 -RVCOPSTATE.S.M.ST_ERROR=0 -RVCOPSTATE.S.M.ST_SEEKING_CHARGER=0 -RVCOPSTATE.S.M.ST_CHARGING=0 -RVCOPSTATE.S.M.ST_DOCKED=0 -RVCOPSTATE.S.M.ERR_NO_ERROR=1 -RVCOPSTATE.S.M.ERR_UNABLE_TO_START_OR_RESUME=0 -RVCOPSTATE.S.M.ERR_UNABLE_TO_COMPLETE_OPERATION=0 -RVCOPSTATE.S.M.ERR_COMMAND_INVALID_IN_STATE=0 -RVCOPSTATE.S.M.ERR_FAILED_TO_FIND_CHARGING_DOCK=0 -RVCOPSTATE.S.M.ERR_STUCK=0 -RVCOPSTATE.S.M.ERR_DUST_BIN_MISSING=0 -RVCOPSTATE.S.M.ERR_DUST_BIN_FULL=0 -RVCOPSTATE.S.M.ERR_WATER_TANK_EMPTY=0 -RVCOPSTATE.S.M.ERR_WATER_TANK_MISSING=0 -RVCOPSTATE.S.M.ERR_WATER_TANK_LID_OPEN=0 -RVCOPSTATE.S.M.ERR_MOP_CLEANING_PAD_MISSING=0 - -#Events -RVCOPSTATE.S.E00=1 -RVCOPSTATE.S.E01=1 - -#Server RVCOPSTATE.S.A0000=1 RVCOPSTATE.S.A0001=1 -RVCOPSTATE.S.A0002=1 +RVCOPSTATE.S.A0002=0 RVCOPSTATE.S.A0003=1 RVCOPSTATE.S.A0004=1 RVCOPSTATE.S.A0005=1 - -#Commands +RVCOPSTATE.S.E00=1 +RVCOPSTATE.S.E01=1 RVCOPSTATE.S.C00.Rsp=1 RVCOPSTATE.S.C01.Rsp=0 RVCOPSTATE.S.C02.Rsp=0 RVCOPSTATE.S.C03.Rsp=1 RVCOPSTATE.S.C04.Tx=1 RVCOPSTATE.S.C128.Rsp=1 -RVCOPSTATE.C.C00.Tx=1 -RVCOPSTATE.C.C01.Tx=1 -RVCOPSTATE.C.C02.Tx=1 -RVCOPSTATE.C.C04.Tx=1 - +RVCOPSTATE.S.M.ST_STOPPED=1 +RVCOPSTATE.S.M.ST_RUNNING=1 +RVCOPSTATE.S.M.ST_PAUSED=1 +RVCOPSTATE.S.M.ST_ERROR=1 +RVCOPSTATE.S.M.ST_SEEKING_CHARGER=1 +RVCOPSTATE.S.M.ST_CHARGING=1 +RVCOPSTATE.S.M.ST_DOCKED=1 +RVCOPSTATE.S.M.ERR_NO_ERROR=1 +RVCOPSTATE.S.M.ERR_UNABLE_TO_START_OR_RESUME=1 +RVCOPSTATE.S.M.ERR_UNABLE_TO_COMPLETE_OPERATION=1 +RVCOPSTATE.S.M.ERR_COMMAND_INVALID_IN_STATE=1 +RVCOPSTATE.S.M.ERR_FAILED_TO_FIND_CHARGING_DOCK=1 +RVCOPSTATE.S.M.ERR_STUCK=1 +RVCOPSTATE.S.M.ERR_DUST_BIN_MISSING=1 +RVCOPSTATE.S.M.ERR_DUST_BIN_FULL=1 +RVCOPSTATE.S.M.ERR_WATER_TANK_EMPTY=1 +RVCOPSTATE.S.M.ERR_WATER_TANK_MISSING=1 +RVCOPSTATE.S.M.ERR_WATER_TANK_LID_OPEN=1 +RVCOPSTATE.S.M.ERR_MOP_CLEANING_PAD_MISSING=1 +RVCOPSTATE.C=0 +RVCOPSTATE.C.C00.Tx=0 +RVCOPSTATE.C.C01.Tx=0 +RVCOPSTATE.C.C02.Tx=0 +RVCOPSTATE.C.C04.Tx=0 -# RVC RUN MODE CLUSTER RVCRUNM.S=1 -RVCRUNM.S.F00=0 - -#Server RVCRUNM.S.A0000=1 RVCRUNM.S.A0001=1 - -#Commands RVCRUNM.S.C00.Rsp=1 RVCRUNM.S.C01.Tx=1 - +RVCRUNM.S.F00=0 RVCRUNM.S.M.CAN_TEST_MODE_FAILURE=1 RVCRUNM.S.M.CAN_MANUALLY_CONTROLLED=1 -#PIXIT -PIXIT.RVCRUNM.MODE_CHANGE_FAIL=1 -PIXIT.RVCRUNM.MODE_CHANGE_OK=1 +# These are useless as these values are set where the python tests are run. +# They are only here because a list test wants then to be. +PIXIT.RVCCLEANM.MODE_CHANGE_FAIL=0 +PIXIT.RVCCLEANM.MODE_CHANGE_OK=0 +PIXIT.RVCRUNM.MODE_CHANGE_FAIL=0 +PIXIT.RVCRUNM.MODE_CHANGE_OK=0 + +# These are the RVC PICS for the all-clustrs-app. +# These PICS are commented out because the yaml tests are being run against the rvc-app. +# RVCCLEANM.S=1 +# RVCCLEANM.S.A0000=1 +# RVCCLEANM.S.A0001=1 +# RVCCLEANM.S.F00=0 +# RVCCLEANM.S.C00.Rsp=1 +# RVCCLEANM.S.C01.Tx=1 +# RVCCLEANM.S.M.CAN_TEST_MODE_FAILURE=1 + +# RVCOPSTATE.S=1 +# RVCOPSTATE.C=1 +# RVCOPSTATE.S.M.ST_STOPPED=1 +# RVCOPSTATE.S.M.ST_RUNNING=1 +# RVCOPSTATE.S.M.ST_PAUSED=1 +# RVCOPSTATE.S.M.ST_ERROR=0 +# RVCOPSTATE.S.M.ST_SEEKING_CHARGER=0 +# RVCOPSTATE.S.M.ST_CHARGING=0 +# RVCOPSTATE.S.M.ST_DOCKED=0 +# RVCOPSTATE.S.M.ERR_NO_ERROR=1 +# RVCOPSTATE.S.M.ERR_UNABLE_TO_START_OR_RESUME=0 +# RVCOPSTATE.S.M.ERR_UNABLE_TO_COMPLETE_OPERATION=0 +# RVCOPSTATE.S.M.ERR_COMMAND_INVALID_IN_STATE=0 +# RVCOPSTATE.S.M.ERR_FAILED_TO_FIND_CHARGING_DOCK=0 +# RVCOPSTATE.S.M.ERR_STUCK=0 +# RVCOPSTATE.S.M.ERR_DUST_BIN_MISSING=0 +# RVCOPSTATE.S.M.ERR_DUST_BIN_FULL=0 +# RVCOPSTATE.S.M.ERR_WATER_TANK_EMPTY=0 +# RVCOPSTATE.S.M.ERR_WATER_TANK_MISSING=0 +# RVCOPSTATE.S.M.ERR_WATER_TANK_LID_OPEN=0 +# RVCOPSTATE.S.M.ERR_MOP_CLEANING_PAD_MISSING=0 +# RVCOPSTATE.S.E00=1 +# RVCOPSTATE.S.E01=1 +# RVCOPSTATE.S.A0000=1 +# RVCOPSTATE.S.A0001=1 +# RVCOPSTATE.S.A0002=1 +# RVCOPSTATE.S.A0003=1 +# RVCOPSTATE.S.A0004=1 +# RVCOPSTATE.S.A0005=1 +# RVCOPSTATE.S.C00.Rsp=1 +# RVCOPSTATE.S.C01.Rsp=0 +# RVCOPSTATE.S.C02.Rsp=0 +# RVCOPSTATE.S.C03.Rsp=1 +# RVCOPSTATE.S.C04.Tx=1 +# RVCOPSTATE.S.C128.Rsp=1 +# RVCOPSTATE.C.C00.Tx=1 +# RVCOPSTATE.C.C01.Tx=1 +# RVCOPSTATE.C.C02.Tx=1 +# RVCOPSTATE.C.C04.Tx=1 + +# RVCRUNM.S=1 +# RVCRUNM.S.F00=0 +# RVCRUNM.S.A0000=1 +# RVCRUNM.S.A0001=1 +# RVCRUNM.S.C00.Rsp=1 +# RVCRUNM.S.C01.Tx=1 +# RVCRUNM.S.M.CAN_TEST_MODE_FAILURE=1 +# RVCRUNM.S.M.CAN_MANUALLY_CONTROLLED=1 + #Refrigerator and Temperature Controlled Cabinet Mode Cluster(TCCM) diff --git a/src/python_testing/TC_RVCCLEANM_2_1.py b/src/python_testing/TC_RVCCLEANM_2_1.py index d000f0d5af697d..6ef91d89a06729 100644 --- a/src/python_testing/TC_RVCCLEANM_2_1.py +++ b/src/python_testing/TC_RVCCLEANM_2_1.py @@ -16,6 +16,7 @@ # import logging +from time import sleep import chip.clusters as Clusters from matter_testing_support import MatterBaseTest, async_test_body, default_matter_test_main, type_matches @@ -56,6 +57,9 @@ async def send_run_change_to_mode_cmd(self, newMode) -> Clusters.Objects.RvcRunM def write_to_app_pipe(self, command): with open(self.app_pipe, "w") as app_pipe: app_pipe.write(command + "\n") + # Delay for pipe command to be processed (otherwise tests are flaky) + # TODO(#31239): centralize pipe write logic and remove the need of sleep + sleep(0.001) def pics_TC_RVCCLEANM_2_1(self) -> list[str]: return ["RVCCLEANM.S"] diff --git a/src/python_testing/TC_RVCCLEANM_2_2.py b/src/python_testing/TC_RVCCLEANM_2_2.py index ae5c268d7a9668..7e1fa6aaf2667e 100644 --- a/src/python_testing/TC_RVCCLEANM_2_2.py +++ b/src/python_testing/TC_RVCCLEANM_2_2.py @@ -15,6 +15,8 @@ # limitations under the License. # +from time import sleep + import chip.clusters as Clusters from matter_testing_support import MatterBaseTest, async_test_body, default_matter_test_main from mobly import asserts @@ -70,6 +72,9 @@ def pics_TC_RVCCLEANM_2_2(self) -> list[str]: def write_to_app_pipe(self, command): with open(self.app_pipe, "w") as app_pipe: app_pipe.write(command + "\n") + # Delay for pipe command to be processed (otherwise tests are flaky) + # TODO(#31239): centralize pipe write logic and remove the need of sleep + sleep(0.001) @async_test_body async def test_TC_RVCCLEANM_2_2(self): diff --git a/src/python_testing/TC_RVCOPSTATE_2_1.py b/src/python_testing/TC_RVCOPSTATE_2_1.py index b0d753ad216164..e9dd4659059fa0 100644 --- a/src/python_testing/TC_RVCOPSTATE_2_1.py +++ b/src/python_testing/TC_RVCOPSTATE_2_1.py @@ -16,6 +16,7 @@ # import logging +from time import sleep import chip.clusters as Clusters from chip.clusters.Types import NullValue @@ -63,6 +64,9 @@ async def send_pause_cmd(self) -> Clusters.Objects.RvcOperationalState.Commands. def write_to_app_pipe(self, command): with open(self.app_pipe, "w") as app_pipe: app_pipe.write(command + "\n") + # Allow some time for the command to take effect. + # This removes the test flakyness which is very annoying for everyone in CI. + sleep(0.001) def TC_RVCOPSTATE_2_1(self) -> list[str]: return ["RVCOPSTATE.S"] diff --git a/src/python_testing/TC_RVCOPSTATE_2_3.py b/src/python_testing/TC_RVCOPSTATE_2_3.py index 4d275ac5adc5b9..aa755315fb7d46 100644 --- a/src/python_testing/TC_RVCOPSTATE_2_3.py +++ b/src/python_testing/TC_RVCOPSTATE_2_3.py @@ -130,6 +130,9 @@ async def send_run_change_to_mode_cmd(self, new_mode) -> Clusters.Objects.RvcRun def write_to_app_pipe(self, command): with open(self.app_pipe, "w") as app_pipe: app_pipe.write(command + "\n") + # Delay for pipe command to be processed (otherwise tests are flaky) + # TODO(#31239): centralize pipe write logic and remove the need of sleep + sleep(0.001) # Prints the instruction and waits for a user input to continue def print_instruction(self, step_number, instruction): diff --git a/src/python_testing/TC_RVCOPSTATE_2_4.py b/src/python_testing/TC_RVCOPSTATE_2_4.py index 3314eaade876bb..7352fbd089f172 100644 --- a/src/python_testing/TC_RVCOPSTATE_2_4.py +++ b/src/python_testing/TC_RVCOPSTATE_2_4.py @@ -16,6 +16,7 @@ # import logging +from time import sleep import chip.clusters as Clusters from matter_testing_support import MatterBaseTest, async_test_body, default_matter_test_main, type_matches @@ -81,6 +82,9 @@ async def send_run_change_to_mode_cmd(self, new_mode): def write_to_app_pipe(self, command): with open(self.app_pipe, "w") as app_pipe: app_pipe.write(command + "\n") + # Delay for pipe command to be processed (otherwise tests are flaky) + # TODO(#31239): centralize pipe write logic and remove the need of sleep + sleep(0.001) def pics_TC_RVCOPSTATE_2_4(self) -> list[str]: return ["RVCOPSTATE.S"] diff --git a/src/python_testing/TC_RVCRUNM_2_1.py b/src/python_testing/TC_RVCRUNM_2_1.py index a9b4c44ba4f88c..1f3bccb528f137 100644 --- a/src/python_testing/TC_RVCRUNM_2_1.py +++ b/src/python_testing/TC_RVCRUNM_2_1.py @@ -16,6 +16,7 @@ # import logging +from time import sleep import chip.clusters as Clusters from matter_testing_support import MatterBaseTest, async_test_body, default_matter_test_main, type_matches @@ -51,6 +52,9 @@ async def send_change_to_mode_cmd(self, newMode) -> Clusters.Objects.RvcRunMode. def write_to_app_pipe(self, command): with open(self.app_pipe, "w") as app_pipe: app_pipe.write(command + "\n") + # Delay for pipe command to be processed (otherwise tests are flaky) + # TODO(#31239): centralize pipe write logic and remove the need of sleep + sleep(0.001) def pics_TC_RVCRUNM_2_1(self) -> list[str]: return ["RVCRUNM.S"] diff --git a/src/python_testing/TC_RVCRUNM_2_2.py b/src/python_testing/TC_RVCRUNM_2_2.py index 4868865c367d19..d85d1ae53cb928 100644 --- a/src/python_testing/TC_RVCRUNM_2_2.py +++ b/src/python_testing/TC_RVCRUNM_2_2.py @@ -15,6 +15,8 @@ # limitations under the License. # +from time import sleep + import chip.clusters as Clusters from matter_testing_support import MatterBaseTest, async_test_body, default_matter_test_main from mobly import asserts @@ -91,6 +93,9 @@ async def read_op_state_operational_state(self) -> Clusters.Objects.RvcOperation def write_to_app_pipe(self, command): with open(self.app_pipe, "w") as app_pipe: app_pipe.write(command + "\n") + # Delay for pipe command to be processed (otherwise tests are flaky) + # TODO(#31239): centralize pipe write logic and remove the need of sleep + sleep(0.001) def pics_TC_RVCRUNM_2_2(self) -> list[str]: return ["RVCRUNM.S"] From f7baa582598763a3ff0ebbcba2f418b502beae20 Mon Sep 17 00:00:00 2001 From: "tianfeng.yang" <130436698+tianfeng-yang@users.noreply.github.com> Date: Tue, 20 Feb 2024 22:41:17 +0800 Subject: [PATCH 030/385] Restore state before restart dnssd (#31985) * Restore state before restart dnssd * Needs to call Shutdown --- src/lib/dnssd/Discovery_ImplPlatform.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/lib/dnssd/Discovery_ImplPlatform.cpp b/src/lib/dnssd/Discovery_ImplPlatform.cpp index abbc4647ff3805..3369f8c00b3b3b 100644 --- a/src/lib/dnssd/Discovery_ImplPlatform.cpp +++ b/src/lib/dnssd/Discovery_ImplPlatform.cpp @@ -420,8 +420,13 @@ void DiscoveryImplPlatform::HandleDnssdInit(void * context, CHIP_ERROR initError void DiscoveryImplPlatform::HandleDnssdError(void * context, CHIP_ERROR error) { + DiscoveryImplPlatform * publisher = static_cast(context); + if (error == CHIP_ERROR_FORCED_RESET) { + // Restore dnssd state before restart, also needs to call ChipDnssdShutdown() + publisher->Shutdown(); + DeviceLayer::ChipDeviceEvent event; event.Type = DeviceLayer::DeviceEventType::kDnssdRestartNeeded; error = DeviceLayer::PlatformMgr().PostEvent(&event); From d09f68ef570ef68b178332cc18450e2f1935299a Mon Sep 17 00:00:00 2001 From: chrisdecenzo <61757564+chrisdecenzo@users.noreply.github.com> Date: Tue, 20 Feb 2024 06:53:35 -0800 Subject: [PATCH 031/385] Messages cluster sample app for android (#32162) * sample app for java * present and list messages * address feedback * Restyle [in-dev] Messages cluster sample app for android (#32163) * Restyled by whitespace * Restyled by google-java-format --------- Co-authored-by: Restyled.io * Restyled by google-java-format (#32195) Co-authored-by: Restyled.io * address feedback --------- Co-authored-by: restyled-io[bot] <32688539+restyled-io[bot]@users.noreply.github.com> Co-authored-by: Restyled.io --- .../tv/server/service/MatterServant.java | 3 + examples/tv-app/android/BUILD.gn | 6 + .../tv-app/android/java/ChannelManager.cpp | 20 +- .../java/ContentAppAttributeDelegate.cpp | 2 + .../java/ContentAppCommandDelegate.cpp | 2 + .../android/java/ContentLauncherManager.cpp | 11 + .../android/java/KeypadInputManager.cpp | 1 + examples/tv-app/android/java/LevelManager.cpp | 1 + .../tv-app/android/java/LowPowerManager.cpp | 1 + .../tv-app/android/java/MediaInputManager.cpp | 14 +- .../android/java/MediaPlaybackManager.cpp | 18 +- .../tv-app/android/java/MessagesManager.cpp | 454 ++++++++++++++++++ .../tv-app/android/java/MessagesManager.h | 63 +++ .../android/java/MyUserPrompter-JNI.cpp | 4 + examples/tv-app/android/java/OnOffManager.cpp | 1 + examples/tv-app/android/java/TVApp-JNI.cpp | 6 + .../tv-app/android/java/WakeOnLanManager.cpp | 1 + .../com/matter/tv/server/tvapp/Clusters.java | 2 +- .../com/matter/tv/server/tvapp/Message.java | 46 ++ .../server/tvapp/MessageResponseOption.java | 28 ++ .../tv/server/tvapp/MessagesManager.java | 36 ++ .../tv/server/tvapp/MessagesManagerStub.java | 82 ++++ .../src/com/matter/tv/server/tvapp/TvApp.java | 2 + 23 files changed, 799 insertions(+), 5 deletions(-) create mode 100644 examples/tv-app/android/java/MessagesManager.cpp create mode 100644 examples/tv-app/android/java/MessagesManager.h create mode 100644 examples/tv-app/android/java/src/com/matter/tv/server/tvapp/Message.java create mode 100644 examples/tv-app/android/java/src/com/matter/tv/server/tvapp/MessageResponseOption.java create mode 100644 examples/tv-app/android/java/src/com/matter/tv/server/tvapp/MessagesManager.java create mode 100644 examples/tv-app/android/java/src/com/matter/tv/server/tvapp/MessagesManagerStub.java diff --git a/examples/tv-app/android/App/platform-app/src/main/java/com/matter/tv/server/service/MatterServant.java b/examples/tv-app/android/App/platform-app/src/main/java/com/matter/tv/server/service/MatterServant.java index 79b02f01386769..540798aae913b7 100644 --- a/examples/tv-app/android/App/platform-app/src/main/java/com/matter/tv/server/service/MatterServant.java +++ b/examples/tv-app/android/App/platform-app/src/main/java/com/matter/tv/server/service/MatterServant.java @@ -41,6 +41,7 @@ import com.matter.tv.server.tvapp.LowPowerManagerStub; import com.matter.tv.server.tvapp.MediaInputManagerStub; import com.matter.tv.server.tvapp.MediaPlaybackManagerStub; +import com.matter.tv.server.tvapp.MessagesManagerStub; import com.matter.tv.server.tvapp.OnOffManagerStub; import com.matter.tv.server.tvapp.TvApp; import com.matter.tv.server.tvapp.WakeOnLanManagerStub; @@ -96,6 +97,8 @@ public void init(@NonNull Context context) { app.setMediaPlaybackManager(endpoint, new MediaPlaybackManagerStub(endpoint)); } else if (clusterId == Clusters.ClusterId_Channel) { app.setChannelManager(endpoint, new ChannelManagerStub(endpoint)); + } else if (clusterId == Clusters.ClusterId_Messaging) { + app.setMessagesManager(endpoint, new MessagesManagerStub(endpoint)); } else if (clusterId == Clusters.ClusterId_OnOff) { mOnOffEndpoint = endpoint; app.setOnOffManager(endpoint, new OnOffManagerStub(endpoint)); diff --git a/examples/tv-app/android/BUILD.gn b/examples/tv-app/android/BUILD.gn index 63de5a515b0754..47157a271edfe8 100644 --- a/examples/tv-app/android/BUILD.gn +++ b/examples/tv-app/android/BUILD.gn @@ -69,6 +69,8 @@ shared_library("jni") { "java/MediaInputManager.h", "java/MediaPlaybackManager.cpp", "java/MediaPlaybackManager.h", + "java/MessagesManager.cpp", + "java/MessagesManager.h", "java/MyUserPrompter-JNI.cpp", "java/MyUserPrompter-JNI.h", "java/MyUserPrompterResolver-JNI.cpp", @@ -143,6 +145,10 @@ android_library("java") { "java/src/com/matter/tv/server/tvapp/MediaPlaybackManagerStub.java", "java/src/com/matter/tv/server/tvapp/MediaPlaybackPosition.java", "java/src/com/matter/tv/server/tvapp/MediaTrack.java", + "java/src/com/matter/tv/server/tvapp/Message.java", + "java/src/com/matter/tv/server/tvapp/MessageResponseOption.java", + "java/src/com/matter/tv/server/tvapp/MessagesManager.java", + "java/src/com/matter/tv/server/tvapp/MessagesManagerStub.java", "java/src/com/matter/tv/server/tvapp/OnOffManager.java", "java/src/com/matter/tv/server/tvapp/OnOffManagerStub.java", "java/src/com/matter/tv/server/tvapp/TvApp.java", diff --git a/examples/tv-app/android/java/ChannelManager.cpp b/examples/tv-app/android/java/ChannelManager.cpp index 3c0efcab9f8cdc..c7067132e46e9d 100644 --- a/examples/tv-app/android/java/ChannelManager.cpp +++ b/examples/tv-app/android/java/ChannelManager.cpp @@ -57,6 +57,7 @@ void ChannelManager::NewManager(jint endpoint, jobject manager) CHIP_ERROR ChannelManager::HandleGetChannelList(AttributeValueEncoder & aEncoder) { + DeviceLayer::StackUnlock unlock; CHIP_ERROR err = CHIP_NO_ERROR; JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread(); VerifyOrReturnError(env != nullptr, CHIP_JNI_ERROR_NULL_OBJECT, ChipLogError(Zcl, "Could not get JNIEnv for current thread")); @@ -66,6 +67,8 @@ CHIP_ERROR ChannelManager::HandleGetChannelList(AttributeValueEncoder & aEncoder VerifyOrExit(mChannelManagerObject.HasValidObjectRef(), err = CHIP_ERROR_INCORRECT_STATE); VerifyOrExit(mGetChannelListMethod != nullptr, err = CHIP_ERROR_INCORRECT_STATE); + env->ExceptionClear(); + return aEncoder.EncodeList([this, env](const auto & encoder) -> CHIP_ERROR { jobjectArray channelInfoList = (jobjectArray) env->CallObjectMethod(mChannelManagerObject.ObjectRef(), mGetChannelListMethod); @@ -134,6 +137,7 @@ CHIP_ERROR ChannelManager::HandleGetChannelList(AttributeValueEncoder & aEncoder CHIP_ERROR ChannelManager::HandleGetLineup(AttributeValueEncoder & aEncoder) { + DeviceLayer::StackUnlock unlock; chip::app::Clusters::Channel::Structs::LineupInfoStruct::Type lineupInfo; CHIP_ERROR err = CHIP_NO_ERROR; JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread(); @@ -144,6 +148,8 @@ CHIP_ERROR ChannelManager::HandleGetLineup(AttributeValueEncoder & aEncoder) VerifyOrExit(mChannelManagerObject.HasValidObjectRef(), err = CHIP_ERROR_INCORRECT_STATE); VerifyOrExit(mGetLineupMethod != nullptr, err = CHIP_ERROR_INCORRECT_STATE); + env->ExceptionClear(); + { jobject channelLineupObject = env->CallObjectMethod(mChannelManagerObject.ObjectRef(), mGetLineupMethod); if (channelLineupObject != nullptr) @@ -197,6 +203,7 @@ CHIP_ERROR ChannelManager::HandleGetLineup(AttributeValueEncoder & aEncoder) CHIP_ERROR ChannelManager::HandleGetCurrentChannel(AttributeValueEncoder & aEncoder) { + DeviceLayer::StackUnlock unlock; chip::app::Clusters::Channel::Structs::ChannelInfoStruct::Type channelInfo; CHIP_ERROR err = CHIP_NO_ERROR; JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread(); @@ -207,6 +214,8 @@ CHIP_ERROR ChannelManager::HandleGetCurrentChannel(AttributeValueEncoder & aEnco VerifyOrExit(mChannelManagerObject.HasValidObjectRef(), err = CHIP_ERROR_INCORRECT_STATE); VerifyOrExit(mGetCurrentChannelMethod != nullptr, err = CHIP_ERROR_INCORRECT_STATE); + env->ExceptionClear(); + { jobject channelInfoObject = env->CallObjectMethod(mChannelManagerObject.ObjectRef(), mGetCurrentChannelMethod); if (channelInfoObject != nullptr) @@ -273,6 +282,7 @@ CHIP_ERROR ChannelManager::HandleGetCurrentChannel(AttributeValueEncoder & aEnco void ChannelManager::HandleChangeChannel(CommandResponseHelper & helper, const CharSpan & match) { + DeviceLayer::StackUnlock unlock; std::string name(match.data(), match.size()); JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread(); VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Could not get JNIEnv for current thread")); @@ -282,9 +292,10 @@ void ChannelManager::HandleChangeChannel(CommandResponseHelperExceptionClear(); + { UtfString jniname(env, name.c_str()); - env->ExceptionClear(); jobject channelObject = env->CallObjectMethod(mChannelManagerObject.ObjectRef(), mChangeChannelMethod, jniname.jniValue()); if (env->ExceptionCheck()) { @@ -319,6 +330,7 @@ void ChannelManager::HandleChangeChannel(CommandResponseHelper> & externalIdList, const chip::Optional & data) { + DeviceLayer::StackUnlock unlock; ProgramGuideResponseType response; CHIP_ERROR err = CHIP_NO_ERROR; JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread(); @@ -394,6 +408,8 @@ void ChannelManager::HandleGetProgramGuide( VerifyOrExit(mChannelManagerObject.HasValidObjectRef(), err = CHIP_ERROR_INCORRECT_STATE); VerifyOrExit(mGetProgramGuideMethod != nullptr, err = CHIP_ERROR_INCORRECT_STATE); + env->ExceptionClear(); + { // NOTE: this example app does not pass the Data, PageToken, ChannelsArray or ExternalIdList through to the Java layer UtfString jData(env, ""); @@ -591,6 +607,7 @@ bool ChannelManager::HandleRecordProgram(const chip::CharSpan & programIdentifie const DataModel::DecodableList & externalIdList, const chip::ByteSpan & data) { + DeviceLayer::StackUnlock unlock; jboolean ret = JNI_FALSE; JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread(); VerifyOrReturnValue(env != nullptr, false, ChipLogError(Zcl, "Could not get JNIEnv for current thread")); @@ -628,6 +645,7 @@ bool ChannelManager::HandleCancelRecordProgram(const chip::CharSpan & programIde const DataModel::DecodableList & externalIdList, const chip::ByteSpan & data) { + DeviceLayer::StackUnlock unlock; jboolean ret = JNI_FALSE; JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread(); VerifyOrReturnValue(env != nullptr, false, ChipLogError(Zcl, "Could not get JNIEnv for current thread")); diff --git a/examples/tv-app/android/java/ContentAppAttributeDelegate.cpp b/examples/tv-app/android/java/ContentAppAttributeDelegate.cpp index 84e7d9933ad022..00b4ca7a225b2c 100644 --- a/examples/tv-app/android/java/ContentAppAttributeDelegate.cpp +++ b/examples/tv-app/android/java/ContentAppAttributeDelegate.cpp @@ -28,6 +28,7 @@ #include #include #include +#include #include namespace chip { @@ -43,6 +44,7 @@ std::string ContentAppAttributeDelegate::Read(const chip::app::ConcreteReadAttri return ""; } + DeviceLayer::StackUnlock unlock; JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread(); ChipLogProgress(Zcl, "ContentAppAttributeDelegate::Read being called for endpoint %d cluster %d attribute %d", aPath.mEndpointId, aPath.mClusterId, aPath.mAttributeId); diff --git a/examples/tv-app/android/java/ContentAppCommandDelegate.cpp b/examples/tv-app/android/java/ContentAppCommandDelegate.cpp index 3963140d1b5e65..2e5dcbe0f3b5e1 100644 --- a/examples/tv-app/android/java/ContentAppCommandDelegate.cpp +++ b/examples/tv-app/android/java/ContentAppCommandDelegate.cpp @@ -31,6 +31,7 @@ #include #include #include +#include #include namespace chip { @@ -50,6 +51,7 @@ void ContentAppCommandDelegate::InvokeCommand(CommandHandlerInterface::HandlerCo { if (handlerContext.mRequestPath.mEndpointId >= FIXED_ENDPOINT_COUNT) { + DeviceLayer::StackUnlock unlock; TLV::TLVReader readerForJson; readerForJson.Init(handlerContext.mPayload); diff --git a/examples/tv-app/android/java/ContentLauncherManager.cpp b/examples/tv-app/android/java/ContentLauncherManager.cpp index caa14b04f9e938..f68e1131fa6fb8 100644 --- a/examples/tv-app/android/java/ContentLauncherManager.cpp +++ b/examples/tv-app/android/java/ContentLauncherManager.cpp @@ -51,6 +51,7 @@ void ContentLauncherManager::HandleLaunchContent(CommandResponseHelper playbackPreferences, bool useCurrentContext) { + DeviceLayer::StackUnlock unlock; Commands::LauncherResponse::Type response; CHIP_ERROR err = CHIP_NO_ERROR; JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread(); @@ -61,6 +62,7 @@ void ContentLauncherManager::HandleLaunchContent(CommandResponseHelperExceptionClear(); { UtfString jData(env, data); @@ -106,6 +108,7 @@ void ContentLauncherManager::HandleLaunchUrl(CommandResponseHelperExceptionClear(); + { UtfString jContentUrl(env, contentUrl); UtfString jDisplayString(env, displayString); @@ -160,6 +165,7 @@ void ContentLauncherManager::HandleLaunchUrl(CommandResponseHelper acceptedHeadersList; @@ -170,6 +176,8 @@ CHIP_ERROR ContentLauncherManager::HandleGetAcceptHeaderList(AttributeValueEncod VerifyOrExit(mContentLauncherManagerObject.HasValidObjectRef(), err = CHIP_ERROR_INCORRECT_STATE); VerifyOrExit(mGetAcceptHeaderMethod != nullptr, err = CHIP_ERROR_INCORRECT_STATE); + env->ExceptionClear(); + return aEncoder.EncodeList([this, env](const auto & encoder) -> CHIP_ERROR { jobjectArray acceptedHeadersArray = (jobjectArray) env->CallObjectMethod(mContentLauncherManagerObject.ObjectRef(), mGetAcceptHeaderMethod); @@ -203,6 +211,7 @@ CHIP_ERROR ContentLauncherManager::HandleGetAcceptHeaderList(AttributeValueEncod uint32_t ContentLauncherManager::HandleGetSupportedStreamingProtocols() { + DeviceLayer::StackUnlock unlock; CHIP_ERROR err = CHIP_NO_ERROR; JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread(); uint32_t supportedStreamingProtocols = 0; @@ -213,6 +222,8 @@ uint32_t ContentLauncherManager::HandleGetSupportedStreamingProtocols() VerifyOrExit(mContentLauncherManagerObject.HasValidObjectRef(), err = CHIP_ERROR_INCORRECT_STATE); VerifyOrExit(mGetSupportedStreamingProtocolsMethod != nullptr, err = CHIP_ERROR_INCORRECT_STATE); + env->ExceptionClear(); + { jlong jSupportedStreamingProtocols = env->CallLongMethod(mContentLauncherManagerObject.ObjectRef(), mGetSupportedStreamingProtocolsMethod); diff --git a/examples/tv-app/android/java/KeypadInputManager.cpp b/examples/tv-app/android/java/KeypadInputManager.cpp index a43a56cb860978..2382397fc351d9 100644 --- a/examples/tv-app/android/java/KeypadInputManager.cpp +++ b/examples/tv-app/android/java/KeypadInputManager.cpp @@ -44,6 +44,7 @@ void KeypadInputManager::NewManager(jint endpoint, jobject manager) void KeypadInputManager::HandleSendKey(CommandResponseHelper & helper, const CECKeyCodeEnum & keyCode) { + DeviceLayer::StackUnlock unlock; Commands::SendKeyResponse::Type response; jint ret = -1; diff --git a/examples/tv-app/android/java/LevelManager.cpp b/examples/tv-app/android/java/LevelManager.cpp index b79f150c7ae20e..f9be7578e830ab 100644 --- a/examples/tv-app/android/java/LevelManager.cpp +++ b/examples/tv-app/android/java/LevelManager.cpp @@ -112,6 +112,7 @@ CHIP_ERROR LevelManager::InitializeWithObjects(jobject managerObject) void LevelManager::HandleLevelChanged(uint8_t value) { + DeviceLayer::StackUnlock unlock; ChipLogProgress(Zcl, "LevelManager::HandleLevelChanged"); JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread(); diff --git a/examples/tv-app/android/java/LowPowerManager.cpp b/examples/tv-app/android/java/LowPowerManager.cpp index 12e234964d4c5e..5c6906fcd1d659 100644 --- a/examples/tv-app/android/java/LowPowerManager.cpp +++ b/examples/tv-app/android/java/LowPowerManager.cpp @@ -64,6 +64,7 @@ void LowPowerManager::InitializeWithObjects(jobject managerObject) bool LowPowerManager::HandleSleep() { + DeviceLayer::StackUnlock unlock; jboolean ret = JNI_FALSE; JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread(); JniLocalReferenceScope scope(env); diff --git a/examples/tv-app/android/java/MediaInputManager.cpp b/examples/tv-app/android/java/MediaInputManager.cpp index bbc575b6eab378..0f1c922243c2be 100644 --- a/examples/tv-app/android/java/MediaInputManager.cpp +++ b/examples/tv-app/android/java/MediaInputManager.cpp @@ -51,6 +51,7 @@ void MediaInputManager::NewManager(jint endpoint, jobject manager) CHIP_ERROR MediaInputManager::HandleGetInputList(chip::app::AttributeValueEncoder & aEncoder) { + DeviceLayer::StackUnlock unlock; CHIP_ERROR err = CHIP_NO_ERROR; JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread(); VerifyOrReturnError(env != nullptr, CHIP_JNI_ERROR_NO_ENV, ChipLogError(Zcl, "Could not get JNIEnv for current thread")); @@ -60,6 +61,8 @@ CHIP_ERROR MediaInputManager::HandleGetInputList(chip::app::AttributeValueEncode VerifyOrExit(mMediaInputManagerObject.HasValidObjectRef(), err = CHIP_ERROR_INCORRECT_STATE); VerifyOrExit(mGetInputListMethod != nullptr, err = CHIP_ERROR_INCORRECT_STATE); + env->ExceptionClear(); + return aEncoder.EncodeList([this, env](const auto & encoder) -> CHIP_ERROR { jobjectArray inputArray = (jobjectArray) env->CallObjectMethod(mMediaInputManagerObject.ObjectRef(), mGetInputListMethod); if (env->ExceptionCheck()) @@ -121,6 +124,7 @@ CHIP_ERROR MediaInputManager::HandleGetInputList(chip::app::AttributeValueEncode uint8_t MediaInputManager::HandleGetCurrentInput() { + DeviceLayer::StackUnlock unlock; CHIP_ERROR err = CHIP_NO_ERROR; jint index = -1; JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread(); @@ -130,7 +134,8 @@ uint8_t MediaInputManager::HandleGetCurrentInput() ChipLogProgress(Zcl, "Received MediaInputManager::HandleGetCurrentInput"); VerifyOrExit(mMediaInputManagerObject.HasValidObjectRef(), err = CHIP_ERROR_INCORRECT_STATE); VerifyOrExit(mGetCurrentInputMethod != nullptr, err = CHIP_ERROR_INCORRECT_STATE); - VerifyOrExit(env != NULL, err = CHIP_JNI_ERROR_NO_ENV); + + env->ExceptionClear(); { index = env->CallIntMethod(mMediaInputManagerObject.ObjectRef(), mGetCurrentInputMethod); @@ -154,6 +159,7 @@ uint8_t MediaInputManager::HandleGetCurrentInput() bool MediaInputManager::HandleSelectInput(const uint8_t index) { + DeviceLayer::StackUnlock unlock; jboolean ret = JNI_FALSE; JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread(); VerifyOrReturnValue(env != nullptr, false, ChipLogError(Zcl, "Could not get JNIEnv for current thread")); @@ -179,6 +185,7 @@ bool MediaInputManager::HandleSelectInput(const uint8_t index) bool MediaInputManager::HandleShowInputStatus() { + DeviceLayer::StackUnlock unlock; jboolean ret = JNI_FALSE; JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread(); VerifyOrReturnValue(env != nullptr, false, ChipLogError(Zcl, "Could not get JNIEnv for current thread")); @@ -204,6 +211,7 @@ bool MediaInputManager::HandleShowInputStatus() bool MediaInputManager::HandleHideInputStatus() { + DeviceLayer::StackUnlock unlock; jboolean ret = JNI_FALSE; JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread(); VerifyOrReturnValue(env != nullptr, false, ChipLogError(Zcl, "Could not get JNIEnv for current thread")); @@ -229,6 +237,7 @@ bool MediaInputManager::HandleHideInputStatus() bool MediaInputManager::HandleRenameInput(const uint8_t index, const chip::CharSpan & name) { + DeviceLayer::StackUnlock unlock; std::string inputname(name.data(), name.size()); jboolean ret = JNI_FALSE; JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread(); @@ -239,9 +248,10 @@ bool MediaInputManager::HandleRenameInput(const uint8_t index, const chip::CharS VerifyOrExit(mMediaInputManagerObject.HasValidObjectRef(), ChipLogError(Zcl, "mMediaInputManagerObject is not valid")); VerifyOrExit(mRenameInputMethod != nullptr, ChipLogError(Zcl, "mHideInputStatusMethod null")); + env->ExceptionClear(); + { UtfString jniInputname(env, inputname.data()); - env->ExceptionClear(); ret = env->CallBooleanMethod(mMediaInputManagerObject.ObjectRef(), mRenameInputMethod, static_cast(index), jniInputname.jniValue()); if (env->ExceptionCheck()) diff --git a/examples/tv-app/android/java/MediaPlaybackManager.cpp b/examples/tv-app/android/java/MediaPlaybackManager.cpp index 62abeb12ec30eb..667ab2ec41b382 100644 --- a/examples/tv-app/android/java/MediaPlaybackManager.cpp +++ b/examples/tv-app/android/java/MediaPlaybackManager.cpp @@ -97,6 +97,7 @@ CHIP_ERROR MediaPlaybackManager::HandleGetActiveAudioTrack(AttributeValueEncoder CHIP_ERROR MediaPlaybackManager::HandleGetActiveTrack(bool audio, AttributeValueEncoder & aEncoder) { + DeviceLayer::StackUnlock unlock; Structs::TrackStruct::Type response; Structs::TrackAttributesStruct::Type trackAttributes; response.trackAttributes = Nullable(trackAttributes); @@ -170,6 +171,7 @@ CHIP_ERROR MediaPlaybackManager::HandleGetAvailableAudioTracks(AttributeValueEnc CHIP_ERROR MediaPlaybackManager::HandleGetAvailableTracks(bool audio, AttributeValueEncoder & aEncoder) { + DeviceLayer::StackUnlock unlock; CHIP_ERROR err = CHIP_NO_ERROR; JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread(); VerifyOrReturnError(env != nullptr, CHIP_JNI_ERROR_NULL_OBJECT, ChipLogError(Zcl, "Could not get JNIEnv for current thread")); @@ -179,6 +181,8 @@ CHIP_ERROR MediaPlaybackManager::HandleGetAvailableTracks(bool audio, AttributeV VerifyOrExit(mMediaPlaybackManagerObject.HasValidObjectRef(), err = CHIP_ERROR_INCORRECT_STATE); VerifyOrExit(mGetAvailableTracksMethod != nullptr, err = CHIP_ERROR_INCORRECT_STATE); + env->ExceptionClear(); + return aEncoder.EncodeList([this, env, audio](const auto & encoder) -> CHIP_ERROR { jobjectArray trackList = (jobjectArray) env->CallObjectMethod(mMediaPlaybackManagerObject.ObjectRef(), mGetAvailableTracksMethod, static_cast(audio)); @@ -317,6 +321,7 @@ bool MediaPlaybackManager::HandleActivateAudioTrack(const chip::CharSpan & track bool MediaPlaybackManager::HandleActivateTrack(bool audio, const chip::CharSpan & trackId) { + DeviceLayer::StackUnlock unlock; std::string id(trackId.data(), trackId.size()); jint ret = -1; @@ -328,9 +333,11 @@ bool MediaPlaybackManager::HandleActivateTrack(bool audio, const chip::CharSpan ChipLogProgress(Zcl, "MediaPlaybackManager::HandleActivateAudioTrack"); VerifyOrExit(mMediaPlaybackManagerObject.HasValidObjectRef(), err = CHIP_ERROR_INCORRECT_STATE); VerifyOrExit(mActivateTrackMethod != nullptr, err = CHIP_ERROR_INCORRECT_STATE); + + env->ExceptionClear(); + { UtfString jniid(env, id.c_str()); - env->ExceptionClear(); ret = env->CallIntMethod(mMediaPlaybackManagerObject.ObjectRef(), mActivateTrackMethod, static_cast(audio), jniid.jniValue()); if (env->ExceptionCheck()) @@ -351,6 +358,7 @@ bool MediaPlaybackManager::HandleActivateTextTrack(const chip::CharSpan & trackI bool MediaPlaybackManager::HandleDeactivateTextTrack() { + DeviceLayer::StackUnlock unlock; jint ret = -1; CHIP_ERROR err = CHIP_NO_ERROR; JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread(); @@ -439,6 +447,7 @@ void MediaPlaybackManager::InitializeWithObjects(jobject managerObject) uint64_t MediaPlaybackManager::HandleMediaRequestGetAttribute(MediaPlaybackRequestAttribute attribute) { + DeviceLayer::StackUnlock unlock; uint64_t ret = std::numeric_limits::max(); jlong jAttributeValue = -1; CHIP_ERROR err = CHIP_NO_ERROR; @@ -450,6 +459,8 @@ uint64_t MediaPlaybackManager::HandleMediaRequestGetAttribute(MediaPlaybackReque VerifyOrExit(mMediaPlaybackManagerObject.HasValidObjectRef(), err = CHIP_ERROR_INCORRECT_STATE); VerifyOrExit(mGetAttributeMethod != nullptr, err = CHIP_ERROR_INCORRECT_STATE); + env->ExceptionClear(); + jAttributeValue = env->CallLongMethod(mMediaPlaybackManagerObject.ObjectRef(), mGetAttributeMethod, static_cast(attribute)); if (env->ExceptionCheck()) @@ -480,6 +491,7 @@ uint64_t MediaPlaybackManager::HandleMediaRequestGetAttribute(MediaPlaybackReque long MediaPlaybackManager::HandleMediaRequestGetLongAttribute(MediaPlaybackRequestAttribute attribute) { + DeviceLayer::StackUnlock unlock; long ret = 0; jlong jAttributeValue = -1; CHIP_ERROR err = CHIP_NO_ERROR; @@ -491,6 +503,8 @@ long MediaPlaybackManager::HandleMediaRequestGetLongAttribute(MediaPlaybackReque VerifyOrExit(mMediaPlaybackManagerObject.HasValidObjectRef(), err = CHIP_ERROR_INCORRECT_STATE); VerifyOrExit(mGetAttributeMethod != nullptr, err = CHIP_ERROR_INCORRECT_STATE); + env->ExceptionClear(); + jAttributeValue = env->CallLongMethod(mMediaPlaybackManagerObject.ObjectRef(), mGetAttributeMethod, static_cast(attribute)); if (env->ExceptionCheck()) @@ -516,6 +530,7 @@ Commands::PlaybackResponse::Type MediaPlaybackManager::HandleMediaRequest(MediaP uint64_t deltaPositionMilliseconds) { + DeviceLayer::StackUnlock unlock; Commands::PlaybackResponse::Type response; jint ret = -1; @@ -553,6 +568,7 @@ Commands::PlaybackResponse::Type MediaPlaybackManager::HandleMediaRequest(MediaP CHIP_ERROR MediaPlaybackManager::HandleGetSampledPosition(AttributeValueEncoder & aEncoder) { + DeviceLayer::StackUnlock unlock; Structs::PlaybackPositionStruct::Type response; response.updatedAt = 0; response.position = Nullable(0); diff --git a/examples/tv-app/android/java/MessagesManager.cpp b/examples/tv-app/android/java/MessagesManager.cpp new file mode 100644 index 00000000000000..9203d7b54510f5 --- /dev/null +++ b/examples/tv-app/android/java/MessagesManager.cpp @@ -0,0 +1,454 @@ +/** + * + * Copyright (c) 2024 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "MessagesManager.h" +#include "TvApp-JNI.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace chip; +using namespace chip::app; +using namespace chip::app::Clusters::Messages; +using namespace chip::Uint8; +using MessageResponseOption = chip::app::Clusters::Messages::Structs::MessageResponseOptionStruct::Type; + +/** @brief Messages Cluster Init + * + * This function is called when a specific cluster is initialized. It gives the + * application an opportunity to take care of cluster initialization procedures. + * It is called exactly once for each endpoint where cluster is present. + * + */ +void emberAfMessagesClusterInitCallback(EndpointId endpoint) +{ + ChipLogProgress(Zcl, "------------TV Android App: Messages::PostClusterInit"); + TvAppJNIMgr().PostClusterInit(chip::app::Clusters::Messages::Id, endpoint); +} + +void MessagesManager::NewManager(jint endpoint, jobject manager) +{ + ChipLogProgress(Zcl, "-----TV Android App: Messages::SetDefaultDelegate"); + MessagesManager * mgr = new MessagesManager(); + VerifyOrReturn(mgr != nullptr, ChipLogError(Zcl, "Failed to create MessagesManager")); + mgr->InitializeWithObjects(manager); + chip::app::Clusters::Messages::SetDefaultDelegate(static_cast(endpoint), mgr); +} + +void MessagesManager::InitializeWithObjects(jobject managerObject) +{ + JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread(); + VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Failed to GetEnvForCurrentThread for MessagesManager")); + + VerifyOrReturn(mMessagesManagerObject.Init(managerObject) == CHIP_NO_ERROR, + ChipLogError(Zcl, "Failed to init mMessagesManagerObject")); + + jclass managerClass = env->GetObjectClass(managerObject); + VerifyOrReturn(managerClass != nullptr, ChipLogError(Zcl, "Failed to get MessagesManager Java class")); + + mGetMessagesMethod = env->GetMethodID(managerClass, "getMessages", "()[Lcom/matter/tv/server/tvapp/Message;"); + if (mGetMessagesMethod == nullptr) + { + ChipLogError(Zcl, "Failed to access MessagesManager 'getMessages' method"); + env->ExceptionClear(); + } + + mPresentMessagesMethod = + env->GetMethodID(managerClass, "presentMessages", "(Ljava/lang/String;IIJILjava/lang/String;Ljava/util/HashMap;)Z"); + if (mPresentMessagesMethod == nullptr) + { + ChipLogError(Zcl, "Failed to access MessagesManager 'presentMessages' method"); + env->ExceptionClear(); + } + + mCancelMessagesMethod = env->GetMethodID(managerClass, "cancelMessage", "(Ljava/lang/String;)Z"); + if (mCancelMessagesMethod == nullptr) + { + ChipLogError(Zcl, "Failed to access MessagesManager 'cancelMessage' method"); + env->ExceptionClear(); + } +} + +uint32_t MessagesManager::GetFeatureMap(chip::EndpointId endpoint) +{ + if (endpoint >= MATTER_DM_CONTENT_LAUNCHER_CLUSTER_SERVER_ENDPOINT_COUNT) + { + return kEndpointFeatureMap; + } + + BitMask FeatureMap; + FeatureMap.Set(Feature::kReceivedConfirmation); + FeatureMap.Set(Feature::kConfirmationResponse); + FeatureMap.Set(Feature::kConfirmationReply); + FeatureMap.Set(Feature::kProtectedMessages); + + uint32_t featureMap = FeatureMap.Raw(); + // forcing to all features since this implementation supports all + // Attributes::FeatureMap::Get(endpoint, &featureMap); + return featureMap; +} + +CHIP_ERROR MessagesManager::HandleGetMessages(AttributeValueEncoder & aEncoder) +{ + DeviceLayer::StackUnlock unlock; + CHIP_ERROR err = CHIP_NO_ERROR; + JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread(); + VerifyOrReturnError(env != nullptr, CHIP_JNI_ERROR_NULL_OBJECT, ChipLogError(Zcl, "Could not get JNIEnv for current thread")); + JniLocalReferenceScope scope(env); + + env->ExceptionClear(); + + ChipLogProgress(Zcl, "Received MessagesManager::HandleGetMessages"); + VerifyOrExit(mMessagesManagerObject.HasValidObjectRef(), err = CHIP_ERROR_INCORRECT_STATE); + VerifyOrExit(mGetMessagesMethod != nullptr, err = CHIP_ERROR_INCORRECT_STATE); + + return aEncoder.EncodeList([this, env](const auto & encoder) -> CHIP_ERROR { + jobjectArray messagesList = + static_cast(env->CallObjectMethod(mMessagesManagerObject.ObjectRef(), mGetMessagesMethod)); + if (env->ExceptionCheck()) + { + ChipLogError(Zcl, "Java exception in MessagesManager::HandleGetMessages"); + env->ExceptionDescribe(); + env->ExceptionClear(); + return CHIP_ERROR_INCORRECT_STATE; + } + + jint length = env->GetArrayLength(messagesList); + + for (jint i = 0; i < length; i++) + { + std::vector options; + std::vector optionLabels; + uint8_t buf[kMessageIdLength]; + + chip::app::Clusters::Messages::Structs::MessageStruct::Type message; + jobject messageObject = env->GetObjectArrayElement(messagesList, i); + jclass messageClass = env->GetObjectClass(messageObject); + + jfieldID getMessageIdField = env->GetFieldID(messageClass, "messageId", "Ljava/lang/String;"); + jstring jmessageId = static_cast(env->GetObjectField(messageObject, getMessageIdField)); + JniUtfString messageId(env, jmessageId); + if (jmessageId != nullptr) + { + VerifyOrReturnValue(chip::Encoding::HexToBytes(messageId.charSpan().data(), messageId.charSpan().size(), buf, + sizeof(buf)) == sizeof(buf), + CHIP_ERROR_INVALID_ARGUMENT, ChipLogError(Zcl, "HexToBytes failed")); + message.messageID = ByteSpan(buf, sizeof(buf)); + } + + jfieldID getMessageTextField = env->GetFieldID(messageClass, "messageText", "Ljava/lang/String;"); + jstring jmessageText = static_cast(env->GetObjectField(messageObject, getMessageTextField)); + JniUtfString messageText(env, jmessageText); + if (jmessageText != nullptr) + { + message.messageText = messageText.charSpan(); + } + + jfieldID messageControlField = env->GetFieldID(messageClass, "messageControl", "I"); + jint jmessageControl = env->GetIntField(messageObject, messageControlField); + message.messageControl = static_cast>(static_cast(jmessageControl)); + + jfieldID priorityField = env->GetFieldID(messageClass, "priority", "I"); + jint jpriority = env->GetIntField(messageObject, priorityField); + if (jpriority >= 0) + { + message.priority = MessagePriorityEnum(static_cast(jpriority)); + } + + jfieldID startTimeField = env->GetFieldID(messageClass, "startTime", "J"); + jlong jstartTime = env->GetLongField(messageObject, startTimeField); + if (jstartTime >= 0) + { + message.startTime = DataModel::Nullable(static_cast(jstartTime)); + } + + jfieldID durationField = env->GetFieldID(messageClass, "duration", "I"); + jint jduration = env->GetIntField(messageObject, durationField); + if (jduration >= 0) + { + message.duration = DataModel::Nullable(static_cast(jduration)); + } + + jfieldID getResponseOptionsField = + env->GetFieldID(messageClass, "responseOptions", "[Lcom/matter/tv/server/tvapp/MessageResponseOption;"); + + jobjectArray responsesArray = static_cast(env->GetObjectField(messageObject, getResponseOptionsField)); + jint size = env->GetArrayLength(responsesArray); + if (size > 0) + { + for (jint j = 0; j < size; j++) + { + MessageResponseOption option; + + jobject responseOptionObject = env->GetObjectArrayElement(responsesArray, j); + jclass responseOptionClass = env->GetObjectClass(responseOptionObject); + + jfieldID idField = env->GetFieldID(responseOptionClass, "id", "J"); + jlong jid = env->GetLongField(responseOptionObject, idField); + option.messageResponseID = Optional(static_cast(jid)); + + jfieldID getLabelField = env->GetFieldID(responseOptionClass, "label", "Ljava/lang/String;"); + jstring jlabelText = static_cast(env->GetObjectField(responseOptionObject, getLabelField)); + VerifyOrReturnValue(jlabelText != nullptr, CHIP_ERROR_INVALID_ARGUMENT, ChipLogError(Zcl, "jlabelText null")); + JniUtfString * label = new JniUtfString(env, jlabelText); + VerifyOrReturnValue(label != nullptr, CHIP_ERROR_NO_MEMORY, ChipLogError(Zcl, "label null")); + + optionLabels.push_back(label); + + option.label = Optional(label->charSpan()); + + options.push_back(option); + } + + message.responses = Optional>( + DataModel::List(options.data(), options.size())); + } + ReturnErrorOnFailure(encoder.Encode(message)); + for (JniUtfString * optionLabel : optionLabels) + { + delete optionLabel; + } + } + + return CHIP_NO_ERROR; + }); + +exit: + if (err != CHIP_NO_ERROR) + { + ChipLogError(Zcl, "MessagesManager::HandleGetMessages status error: %s", err.AsString()); + } + return err; +} + +CHIP_ERROR MessagesManager::HandleGetActiveMessageIds(AttributeValueEncoder & aEncoder) +{ + DeviceLayer::StackUnlock unlock; + CHIP_ERROR err = CHIP_NO_ERROR; + JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread(); + VerifyOrReturnError(env != nullptr, CHIP_JNI_ERROR_NULL_OBJECT, ChipLogError(Zcl, "Could not get JNIEnv for current thread")); + JniLocalReferenceScope scope(env); + + ChipLogProgress(Zcl, "Received MessagesManager::HandleGetActiveMessageIds"); + VerifyOrExit(mMessagesManagerObject.HasValidObjectRef(), err = CHIP_ERROR_INCORRECT_STATE); + VerifyOrExit(mGetMessagesMethod != nullptr, err = CHIP_ERROR_INCORRECT_STATE); + + env->ExceptionClear(); + + return aEncoder.EncodeList([this, env](const auto & encoder) -> CHIP_ERROR { + jobjectArray messagesList = + static_cast(env->CallObjectMethod(mMessagesManagerObject.ObjectRef(), mGetMessagesMethod)); + if (env->ExceptionCheck()) + { + ChipLogError(Zcl, "Java exception in MessagesManager::HandleGetActiveMessageIds"); + env->ExceptionDescribe(); + env->ExceptionClear(); + return CHIP_ERROR_INCORRECT_STATE; + } + + jint length = env->GetArrayLength(messagesList); + + for (jint i = 0; i < length; i++) + { + jobject messageObject = env->GetObjectArrayElement(messagesList, i); + jclass messageClass = env->GetObjectClass(messageObject); + + jfieldID getMessageIdField = env->GetFieldID(messageClass, "messageId", "Ljava/lang/String;"); + jstring jmessageId = static_cast(env->GetObjectField(messageObject, getMessageIdField)); + JniUtfString messageId(env, jmessageId); + if (jmessageId != nullptr) + { + uint8_t buf[kMessageIdLength]; + VerifyOrReturnValue(chip::Encoding::HexToBytes(messageId.charSpan().data(), messageId.charSpan().size(), buf, + sizeof(buf)) == sizeof(buf), + CHIP_ERROR_INVALID_ARGUMENT, ChipLogError(Zcl, "HexToBytes failed")); + + ReturnErrorOnFailure(encoder.Encode(ByteSpan(buf, sizeof(buf)))); + } + } + + return CHIP_NO_ERROR; + }); + +exit: + if (err != CHIP_NO_ERROR) + { + ChipLogError(Zcl, "MessagesManager::HandleGetMessages status error: %s", err.AsString()); + } + + return err; +} + +CHIP_ERROR MessagesManager::HandlePresentMessagesRequest( + const ByteSpan & messageId, const MessagePriorityEnum & priority, const BitMask & messageControl, + const DataModel::Nullable & startTime, const DataModel::Nullable & duration, const CharSpan & messageText, + const Optional> & responses) +{ + DeviceLayer::StackUnlock unlock; + JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread(); + VerifyOrReturnError(env != nullptr, CHIP_JNI_ERROR_NULL_OBJECT, ChipLogError(Zcl, "Could not get JNIEnv for current thread")); + JniLocalReferenceScope scope(env); + + ChipLogProgress(Zcl, "Received MessagesManager::HandlePresentMessagesRequest"); + VerifyOrReturnError(mMessagesManagerObject.HasValidObjectRef(), CHIP_ERROR_INCORRECT_STATE, + ChipLogError(Zcl, "Invalid mMessagesManagerObject")); + VerifyOrReturnError(mPresentMessagesMethod != nullptr, CHIP_ERROR_INCORRECT_STATE, + ChipLogError(Zcl, "mPresentMessagesMethod null")); + + env->ExceptionClear(); + { + char hex_buf[(kMessageIdLength * 2) + 1]; + VerifyOrReturnError( + CHIP_NO_ERROR == + chip::Encoding::BytesToUppercaseHexString(messageId.data(), messageId.size(), hex_buf, sizeof(hex_buf)), + CHIP_ERROR_INCORRECT_STATE, ChipLogError(Zcl, "BytesToUppercaseHexString failed")); + + jstring jid = env->NewStringUTF(hex_buf); + if (jid == nullptr) + { + return CHIP_ERROR_INTERNAL; + } + + std::string smessageText(messageText.data(), messageText.size()); + jstring jmessageText = env->NewStringUTF(smessageText.c_str()); + if (jmessageText == nullptr) + { + return CHIP_ERROR_INTERNAL; + } + + jint jcontrol = static_cast(messageControl.Raw()); + jint jduration = -1; + if (!duration.IsNull()) + { + jduration = static_cast(duration.Value()); + } + jlong jstartTime = -1; + if (!startTime.IsNull()) + { + jstartTime = static_cast(startTime.Value()); + } + + jint jpriority = static_cast(priority); + + jclass hashMapClass = env->FindClass("java/util/HashMap"); + VerifyOrReturnError(hashMapClass != nullptr, CHIP_ERROR_INCORRECT_STATE, ChipLogError(Zcl, "Could not find class HashMap")); + jmethodID hashMapCtor = env->GetMethodID(hashMapClass, "", "()V"); + VerifyOrReturnError(hashMapCtor != nullptr, CHIP_ERROR_INCORRECT_STATE, + ChipLogError(Zcl, "Could not find HashMap constructor")); + jobject joptions = env->NewObject(hashMapClass, hashMapCtor); + VerifyOrReturnError(joptions != nullptr, CHIP_ERROR_INCORRECT_STATE, ChipLogError(Zcl, "Could not create HashMap")); + + if (responses.HasValue()) + { + jmethodID hashMapPut = + env->GetMethodID(hashMapClass, "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"); + VerifyOrReturnError(hashMapPut != nullptr, CHIP_ERROR_INCORRECT_STATE, ChipLogError(Zcl, "Could not find HashMap put")); + + jclass longClass = env->FindClass("java/lang/Long"); + VerifyOrReturnError(longClass != nullptr, CHIP_ERROR_INCORRECT_STATE, ChipLogError(Zcl, "Could not find class Long")); + jmethodID longCtor = env->GetMethodID(longClass, "", "(J)V"); + VerifyOrReturnError(longCtor != nullptr, CHIP_ERROR_INCORRECT_STATE, + ChipLogError(Zcl, "Could not find Long constructor")); + + auto iter = responses.Value().begin(); + while (iter.Next()) + { + auto & response = iter.GetValue(); + + std::string label(response.label.Value().data(), response.label.Value().size()); + jstring jlabel = env->NewStringUTF(label.c_str()); + if (jlabel == nullptr) + { + return CHIP_ERROR_INTERNAL; + } + + jobject jlong = env->NewObject(longClass, longCtor, response.messageResponseID.Value()); + VerifyOrReturnError(jlong != nullptr, CHIP_ERROR_INCORRECT_STATE, ChipLogError(Zcl, "Could not create Long")); + + // add to HashMap + env->CallObjectMethod(joptions, hashMapPut, jlong, jlabel); + if (env->ExceptionCheck()) + { + ChipLogError(DeviceLayer, "Java exception in MessagesManager::HandlePresentMessagesRequest"); + env->ExceptionDescribe(); + env->ExceptionClear(); + return CHIP_ERROR_INTERNAL; + } + } + } + + env->CallBooleanMethod(mMessagesManagerObject.ObjectRef(), mPresentMessagesMethod, jid, jpriority, jcontrol, jstartTime, + jduration, jmessageText, joptions); + if (env->ExceptionCheck()) + { + ChipLogError(DeviceLayer, "Java exception in MessagesManager::HandlePresentMessagesRequest"); + env->ExceptionDescribe(); + env->ExceptionClear(); + return CHIP_ERROR_INTERNAL; + } + } + return CHIP_NO_ERROR; +} + +CHIP_ERROR MessagesManager::HandleCancelMessagesRequest(const DataModel::DecodableList & messageIds) +{ + DeviceLayer::StackUnlock unlock; + JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread(); + VerifyOrReturnError(env != nullptr, CHIP_JNI_ERROR_NULL_OBJECT, ChipLogError(Zcl, "Could not get JNIEnv for current thread")); + JniLocalReferenceScope scope(env); + + ChipLogProgress(Zcl, "Received MessagesManager::HandleCancelMessagesRequest"); + VerifyOrReturnError(mMessagesManagerObject.HasValidObjectRef(), CHIP_ERROR_INCORRECT_STATE, + ChipLogError(Zcl, "Invalid mMessagesManagerObject")); + VerifyOrReturnError(mCancelMessagesMethod != nullptr, CHIP_ERROR_INCORRECT_STATE, + ChipLogError(Zcl, "mCancelMessagesMethod null")); + + env->ExceptionClear(); + + auto iter = messageIds.begin(); + while (iter.Next()) + { + auto & id = iter.GetValue(); + + char hex_buf[(kMessageIdLength * 2) + 1]; + VerifyOrReturnError(CHIP_NO_ERROR == + chip::Encoding::BytesToUppercaseHexString(id.data(), id.size(), hex_buf, sizeof(hex_buf)), + CHIP_ERROR_INCORRECT_STATE, ChipLogError(Zcl, "BytesToUppercaseHexString failed")); + + jstring jid = env->NewStringUTF(hex_buf); + if (jid == nullptr) + { + return CHIP_ERROR_INTERNAL; + } + + env->CallBooleanMethod(mMessagesManagerObject.ObjectRef(), mCancelMessagesMethod, jid); + if (env->ExceptionCheck()) + { + ChipLogError(DeviceLayer, "Java exception in MessagesManager::HandleCancelMessagesRequest"); + env->ExceptionDescribe(); + env->ExceptionClear(); + return CHIP_ERROR_INTERNAL; + } + } + return CHIP_NO_ERROR; +} diff --git a/examples/tv-app/android/java/MessagesManager.h b/examples/tv-app/android/java/MessagesManager.h new file mode 100644 index 00000000000000..563192a542bdf6 --- /dev/null +++ b/examples/tv-app/android/java/MessagesManager.h @@ -0,0 +1,63 @@ +/** + * + * Copyright (c) 2024 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include + +#include +#include + +#include +#include + +class MessagesManager : public chip::app::Clusters::Messages::Delegate +{ +public: + static void NewManager(jint endpoint, jobject manager); + void InitializeWithObjects(jobject managerObject); + + // Commands + CHIP_ERROR HandlePresentMessagesRequest( + const chip::ByteSpan & messageId, const chip::app::Clusters::Messages::MessagePriorityEnum & priority, + const chip::BitMask & messageControl, + const chip::app::DataModel::Nullable & startTime, const chip::app::DataModel::Nullable & duration, + const chip::CharSpan & messageText, + const chip::Optional< + chip::app::DataModel::DecodableList> & + responses) override; + CHIP_ERROR HandleCancelMessagesRequest(const chip::app::DataModel::DecodableList & messageIds) override; + + // Attributes + CHIP_ERROR HandleGetMessages(chip::app::AttributeValueEncoder & aEncoder) override; + CHIP_ERROR HandleGetActiveMessageIds(chip::app::AttributeValueEncoder & aEncoder) override; + + // Global Attributes + uint32_t GetFeatureMap(chip::EndpointId endpoint) override; + // uint16_t GetClusterRevision(chip::EndpointId endpoint) override; + +private: + chip::JniGlobalReference mMessagesManagerObject; + jmethodID mGetMessagesMethod = nullptr; + + jmethodID mPresentMessagesMethod = nullptr; + jmethodID mCancelMessagesMethod = nullptr; + + // TODO: set this based upon meta data from app + static constexpr uint32_t kEndpointFeatureMap = 15; + // static constexpr uint16_t kClusterRevision = 1; +}; diff --git a/examples/tv-app/android/java/MyUserPrompter-JNI.cpp b/examples/tv-app/android/java/MyUserPrompter-JNI.cpp index d2c83b28a1ce8f..82b06e210d7853 100644 --- a/examples/tv-app/android/java/MyUserPrompter-JNI.cpp +++ b/examples/tv-app/android/java/MyUserPrompter-JNI.cpp @@ -78,6 +78,7 @@ JNIMyUserPrompter::JNIMyUserPrompter(jobject provider) */ void JNIMyUserPrompter::PromptForCommissionOKPermission(uint16_t vendorId, uint16_t productId, const char * commissioneeName) { + DeviceLayer::StackUnlock unlock; CHIP_ERROR err = CHIP_NO_ERROR; JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread(); std::string stringCommissioneeName(commissioneeName); @@ -119,6 +120,7 @@ void JNIMyUserPrompter::PromptForCommissionOKPermission(uint16_t vendorId, uint1 void JNIMyUserPrompter::PromptForCommissionPasscode(uint16_t vendorId, uint16_t productId, const char * commissioneeName, uint16_t pairingHint, const char * pairingInstruction) { + DeviceLayer::StackUnlock unlock; CHIP_ERROR err = CHIP_NO_ERROR; JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread(); std::string stringCommissioneeName(commissioneeName); @@ -198,6 +200,7 @@ void JNIMyUserPrompter::PromptCommissioningStarted(uint16_t vendorId, uint16_t p */ void JNIMyUserPrompter::PromptCommissioningSucceeded(uint16_t vendorId, uint16_t productId, const char * commissioneeName) { + DeviceLayer::StackUnlock unlock; CHIP_ERROR err = CHIP_NO_ERROR; JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread(); std::string stringCommissioneeName(commissioneeName); @@ -234,6 +237,7 @@ void JNIMyUserPrompter::PromptCommissioningSucceeded(uint16_t vendorId, uint16_t */ void JNIMyUserPrompter::PromptCommissioningFailed(const char * commissioneeName, CHIP_ERROR error) { + DeviceLayer::StackUnlock unlock; CHIP_ERROR err = CHIP_NO_ERROR; JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread(); std::string stringCommissioneeName(commissioneeName); diff --git a/examples/tv-app/android/java/OnOffManager.cpp b/examples/tv-app/android/java/OnOffManager.cpp index 9a330754aa4a16..db694748e8a11b 100644 --- a/examples/tv-app/android/java/OnOffManager.cpp +++ b/examples/tv-app/android/java/OnOffManager.cpp @@ -113,6 +113,7 @@ CHIP_ERROR OnOffManager::InitializeWithObjects(jobject managerObject) void OnOffManager::HandleOnOffChanged(bool value) { + DeviceLayer::StackUnlock unlock; ChipLogProgress(Zcl, "OnOffManager::HandleOnOffChanged"); JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread(); diff --git a/examples/tv-app/android/java/TVApp-JNI.cpp b/examples/tv-app/android/java/TVApp-JNI.cpp index 6bbc35ed297415..72279c49dca9d7 100644 --- a/examples/tv-app/android/java/TVApp-JNI.cpp +++ b/examples/tv-app/android/java/TVApp-JNI.cpp @@ -27,6 +27,7 @@ #include "LowPowerManager.h" #include "MediaInputManager.h" #include "MediaPlaybackManager.h" +#include "MessagesManager.h" #include "MyUserPrompter-JNI.h" #include "OnOffManager.h" #include "WakeOnLanManager.h" @@ -137,6 +138,11 @@ JNI_METHOD(void, setMediaPlaybackManager)(JNIEnv *, jobject, jint endpoint, jobj MediaPlaybackManager::NewManager(endpoint, manager); } +JNI_METHOD(void, setMessagesManager)(JNIEnv *, jobject, jint endpoint, jobject manager) +{ + MessagesManager::NewManager(endpoint, manager); +} + JNI_METHOD(void, setChannelManager)(JNIEnv *, jobject, jint endpoint, jobject manager) { ChannelManager::NewManager(endpoint, manager); diff --git a/examples/tv-app/android/java/WakeOnLanManager.cpp b/examples/tv-app/android/java/WakeOnLanManager.cpp index 5a3093aca53332..a50ddca72bbb3e 100644 --- a/examples/tv-app/android/java/WakeOnLanManager.cpp +++ b/examples/tv-app/android/java/WakeOnLanManager.cpp @@ -51,6 +51,7 @@ void WakeOnLanManager::NewManager(jint endpoint, jobject manager) CHIP_ERROR WakeOnLanManager::HandleGetMacAddress(chip::app::AttributeValueEncoder & aEncoder) { + DeviceLayer::StackUnlock unlock; jobject javaMac; CHIP_ERROR err = CHIP_NO_ERROR; JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread(); diff --git a/examples/tv-app/android/java/src/com/matter/tv/server/tvapp/Clusters.java b/examples/tv-app/android/java/src/com/matter/tv/server/tvapp/Clusters.java index d699ca68ea6365..5928c1b10181c7 100644 --- a/examples/tv-app/android/java/src/com/matter/tv/server/tvapp/Clusters.java +++ b/examples/tv-app/android/java/src/com/matter/tv/server/tvapp/Clusters.java @@ -129,7 +129,7 @@ public class Clusters { public static final long ClusterId_ApplicationBasic = 0x0000050D; public static final long ClusterId_AccountLogin = 0x0000050E; public static final long ClusterId_TestCluster = 0xFFF1FC05; - public static final long ClusterId_Messaging = 0x00000703; + public static final long ClusterId_Messaging = 0x00000097; public static final long ClusterId_ApplianceIdentification = 0x00000B00; public static final long ClusterId_MeterIdentification = 0x00000B01; public static final long ClusterId_ApplianceEventsAndAlert = 0x00000B02; diff --git a/examples/tv-app/android/java/src/com/matter/tv/server/tvapp/Message.java b/examples/tv-app/android/java/src/com/matter/tv/server/tvapp/Message.java new file mode 100644 index 00000000000000..c194ffb44f9ee1 --- /dev/null +++ b/examples/tv-app/android/java/src/com/matter/tv/server/tvapp/Message.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2024 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. + * + */ +package com.matter.tv.server.tvapp; + +public class Message { + + public String messageId; + public int priority; + public int messageControl; + public long startTime; + public int duration; + public String messageText; + public MessageResponseOption responseOptions[]; + + public Message( + String messageId, + int priority, + int messageControl, + long startTime, + int duration, + String messageText, + MessageResponseOption responseOptions[]) { + this.messageId = messageId; + this.priority = priority; + this.messageControl = messageControl; + this.startTime = startTime; + this.duration = duration; + this.messageText = messageText; + this.responseOptions = responseOptions; + } +} diff --git a/examples/tv-app/android/java/src/com/matter/tv/server/tvapp/MessageResponseOption.java b/examples/tv-app/android/java/src/com/matter/tv/server/tvapp/MessageResponseOption.java new file mode 100644 index 00000000000000..5d8e77d1e91389 --- /dev/null +++ b/examples/tv-app/android/java/src/com/matter/tv/server/tvapp/MessageResponseOption.java @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2024 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. + * + */ +package com.matter.tv.server.tvapp; + +public class MessageResponseOption { + public long id = -1; + public String label = "na"; + + public MessageResponseOption(long id, String label) { + this.id = id; + this.label = label; + } +} diff --git a/examples/tv-app/android/java/src/com/matter/tv/server/tvapp/MessagesManager.java b/examples/tv-app/android/java/src/com/matter/tv/server/tvapp/MessagesManager.java new file mode 100644 index 00000000000000..0a5680866714c6 --- /dev/null +++ b/examples/tv-app/android/java/src/com/matter/tv/server/tvapp/MessagesManager.java @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2024 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. + * + */ +package com.matter.tv.server.tvapp; + +import java.util.HashMap; + +public interface MessagesManager { + + Message[] getMessages(); + + boolean presentMessages( + String messageId, + int priority, + int messageControl, + long startTime, + int duration, + String messageText, + HashMap responseOptions); + + boolean cancelMessage(String messageId); +} diff --git a/examples/tv-app/android/java/src/com/matter/tv/server/tvapp/MessagesManagerStub.java b/examples/tv-app/android/java/src/com/matter/tv/server/tvapp/MessagesManagerStub.java new file mode 100644 index 00000000000000..63fef69d35c936 --- /dev/null +++ b/examples/tv-app/android/java/src/com/matter/tv/server/tvapp/MessagesManagerStub.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2024 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. + * + */ +package com.matter.tv.server.tvapp; + +import android.util.Log; +import java.util.HashMap; +import java.util.Map; + +public class MessagesManagerStub implements MessagesManager { + private static final String TAG = MessagesManagerStub.class.getSimpleName(); + + private int endpoint = -1; + + private Map messages = new HashMap(); + + public MessagesManagerStub(int endpoint) { + this.endpoint = endpoint; + Log.d(TAG, "MessagesManagerStub: at " + this.endpoint); + + HashMap responseOptions = new HashMap(); + responseOptions.put(new Long(1), "Yes"); + responseOptions.put(new Long(2), "No"); + presentMessages( + "31323334353637383930313233343536", 1, 1, 30, 60, "TestMessage", responseOptions); + Log.d(TAG, "MessagesManagerStub: added dummy message"); + } + + @Override + public Message[] getMessages() { + Log.d(TAG, "getMessages: at " + this.endpoint); + return messages.values().toArray(new Message[0]); + } + + @Override + public boolean presentMessages( + String messageId, + int priority, + int messageControl, + long startTime, + int duration, + String messageText, + HashMap responseOptions) { + Log.d( + TAG, "presentMessages: at " + this.endpoint + " id:" + messageId + " text:" + messageText); + MessageResponseOption[] options = new MessageResponseOption[responseOptions.size()]; + int i = 0; + + for (Map.Entry set : responseOptions.entrySet()) { + Log.d(TAG, "presentMessages option: key:" + set.getKey() + " value:" + set.getValue()); + options[i] = new MessageResponseOption(set.getKey().longValue(), set.getValue()); + i++; + } + + messages.put( + messageId, + new Message( + messageId, priority, messageControl, startTime, duration, messageText, options)); + return true; + } + + @Override + public boolean cancelMessage(String messageId) { + Log.d(TAG, "cancelMessage: at " + this.endpoint + " messageId:" + messageId); + messages.remove(messageId); + return true; // per spec, succeed unless error + } +} diff --git a/examples/tv-app/android/java/src/com/matter/tv/server/tvapp/TvApp.java b/examples/tv-app/android/java/src/com/matter/tv/server/tvapp/TvApp.java index d8bb564370afa4..eaf207e45f3618 100644 --- a/examples/tv-app/android/java/src/com/matter/tv/server/tvapp/TvApp.java +++ b/examples/tv-app/android/java/src/com/matter/tv/server/tvapp/TvApp.java @@ -57,6 +57,8 @@ private void postClusterInit(long clusterId, int endpoint) { public native void setMediaPlaybackManager(int endpoint, MediaPlaybackManager manager); + public native void setMessagesManager(int endpoint, MessagesManager manager); + public native void setChannelManager(int endpoint, ChannelManager manager); public native void setOnOffManager(int endpoint, OnOffManager manager); From 65a86ee652ef39beef8370c41446b5a5b4bcc3eb Mon Sep 17 00:00:00 2001 From: Andrei Litvin Date: Tue, 20 Feb 2024 10:42:47 -0500 Subject: [PATCH 032/385] Bump cloudbuild image version to 36 (#32222) * Bump cloudbuild image version to 36 * Undo submodule update --------- Co-authored-by: Andrei Litvin --- integrations/cloudbuild/build-all.yaml | 6 +++--- integrations/cloudbuild/smoke-test.yaml | 14 +++++++------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/integrations/cloudbuild/build-all.yaml b/integrations/cloudbuild/build-all.yaml index 6590630957d902..cdefbcf1ddbe15 100644 --- a/integrations/cloudbuild/build-all.yaml +++ b/integrations/cloudbuild/build-all.yaml @@ -6,7 +6,7 @@ steps: - "--init" - "--recursive" id: Submodules - - name: "ghcr.io/project-chip/chip-build-vscode:35" + - name: "ghcr.io/project-chip/chip-build-vscode:36" env: - PW_ENVIRONMENT_ROOT=/pwenv args: @@ -21,7 +21,7 @@ steps: path: /pwenv timeout: 900s - - name: "ghcr.io/project-chip/chip-build-vscode:35" + - name: "ghcr.io/project-chip/chip-build-vscode:36" env: - PW_ENVIRONMENT_ROOT=/pwenv args: @@ -85,7 +85,7 @@ steps: --target k32w-shell build --create-archives /workspace/artifacts/ - - name: "ghcr.io/project-chip/chip-build-vscode:35" + - name: "ghcr.io/project-chip/chip-build-vscode:36" env: - PW_ENVIRONMENT_ROOT=/pwenv args: diff --git a/integrations/cloudbuild/smoke-test.yaml b/integrations/cloudbuild/smoke-test.yaml index f05bbd0e369d2d..87e22dbbea99d0 100644 --- a/integrations/cloudbuild/smoke-test.yaml +++ b/integrations/cloudbuild/smoke-test.yaml @@ -1,5 +1,5 @@ steps: - - name: "ghcr.io/project-chip/chip-build-vscode:35" + - name: "ghcr.io/project-chip/chip-build-vscode:36" entrypoint: "bash" args: - "-c" @@ -7,7 +7,7 @@ steps: git config --global --add safe.directory "*" git submodule update --init --recursive id: Submodules - - name: "ghcr.io/project-chip/chip-build-vscode:35" + - name: "ghcr.io/project-chip/chip-build-vscode:36" env: - PW_ENVIRONMENT_ROOT=/pwenv args: @@ -22,7 +22,7 @@ steps: path: /pwenv timeout: 900s - - name: "ghcr.io/project-chip/chip-build-vscode:35" + - name: "ghcr.io/project-chip/chip-build-vscode:36" id: ESP32 env: - PW_ENVIRONMENT_ROOT=/pwenv @@ -43,7 +43,7 @@ steps: volumes: - name: pwenv path: /pwenv - - name: "ghcr.io/project-chip/chip-build-vscode:35" + - name: "ghcr.io/project-chip/chip-build-vscode:36" id: NRFConnect env: - PW_ENVIRONMENT_ROOT=/pwenv @@ -64,7 +64,7 @@ steps: - name: pwenv path: /pwenv - - name: "ghcr.io/project-chip/chip-build-vscode:35" + - name: "ghcr.io/project-chip/chip-build-vscode:36" id: EFR32 env: - PW_ENVIRONMENT_ROOT=/pwenv @@ -86,7 +86,7 @@ steps: - name: pwenv path: /pwenv - - name: "ghcr.io/project-chip/chip-build-vscode:35" + - name: "ghcr.io/project-chip/chip-build-vscode:36" id: Linux env: - PW_ENVIRONMENT_ROOT=/pwenv @@ -139,7 +139,7 @@ steps: - name: pwenv path: /pwenv - - name: "ghcr.io/project-chip/chip-build-vscode:35" + - name: "ghcr.io/project-chip/chip-build-vscode:36" id: Android env: - PW_ENVIRONMENT_ROOT=/pwenv From 5569f26b64cbeba74e8c7140d96e2de55ae5b809 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 20 Feb 2024 10:44:05 -0500 Subject: [PATCH 033/385] Bump third_party/ot-br-posix/repo from `c5a7a35` to `9bdaa91` (#32200) Bumps [third_party/ot-br-posix/repo](https://github.com/openthread/ot-br-posix) from `c5a7a35` to `9bdaa91`. - [Release notes](https://github.com/openthread/ot-br-posix/releases) - [Commits](https://github.com/openthread/ot-br-posix/compare/c5a7a35e3bd2f3da8cce1e2e2a3bbe5cdeedb729...9bdaa9101663c2ce9016fb5e2b5010442b17ca26) --- updated-dependencies: - dependency-name: third_party/ot-br-posix/repo dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- third_party/ot-br-posix/repo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/third_party/ot-br-posix/repo b/third_party/ot-br-posix/repo index c5a7a35e3bd2f3..9bdaa9101663c2 160000 --- a/third_party/ot-br-posix/repo +++ b/third_party/ot-br-posix/repo @@ -1 +1 @@ -Subproject commit c5a7a35e3bd2f3da8cce1e2e2a3bbe5cdeedb729 +Subproject commit 9bdaa9101663c2ce9016fb5e2b5010442b17ca26 From 932db7f1eeb5e22a98845f34e02aad12aeeae27b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 20 Feb 2024 15:45:27 +0000 Subject: [PATCH 034/385] Bump third_party/mbedtls/repo from `ede909f` to `039c903` (#32202) Bumps [third_party/mbedtls/repo](https://github.com/ARMmbed/mbedtls) from `ede909f` to `039c903`. - [Release notes](https://github.com/ARMmbed/mbedtls/releases) - [Commits](https://github.com/ARMmbed/mbedtls/compare/ede909f99ab6e6a958a41e365251c2a1d2c4ed4d...039c903e7b2882af8e85ce5e090fd44e6a9d2289) --- updated-dependencies: - dependency-name: third_party/mbedtls/repo dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- third_party/mbedtls/repo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/third_party/mbedtls/repo b/third_party/mbedtls/repo index ede909f99ab6e6..039c903e7b2882 160000 --- a/third_party/mbedtls/repo +++ b/third_party/mbedtls/repo @@ -1 +1 @@ -Subproject commit ede909f99ab6e6a958a41e365251c2a1d2c4ed4d +Subproject commit 039c903e7b2882af8e85ce5e090fd44e6a9d2289 From 9fca5a71c1b11789035cd8dcd028a8eedb798d2f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 20 Feb 2024 15:45:37 +0000 Subject: [PATCH 035/385] Bump third_party/openthread/repo from `b212a0a` to `33574ad` (#32203) Bumps [third_party/openthread/repo](https://github.com/openthread/openthread) from `b212a0a` to `33574ad`. - [Release notes](https://github.com/openthread/openthread/releases) - [Commits](https://github.com/openthread/openthread/compare/b212a0a748070ccbda765c3ebed2aab8b6b08fce...33574ad4175ffb088bcca047f4c8d5fb240d1495) --- updated-dependencies: - dependency-name: third_party/openthread/repo dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- third_party/openthread/repo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/third_party/openthread/repo b/third_party/openthread/repo index b212a0a748070c..33574ad4175ffb 160000 --- a/third_party/openthread/repo +++ b/third_party/openthread/repo @@ -1 +1 @@ -Subproject commit b212a0a748070ccbda765c3ebed2aab8b6b08fce +Subproject commit 33574ad4175ffb088bcca047f4c8d5fb240d1495 From 02f5674e53f2711446ef7e07ea99308986d801b3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 20 Feb 2024 10:48:56 -0500 Subject: [PATCH 036/385] Bump third_party/libwebsockets/repo from `49bfef2` to `b71a662` (#32204) Bumps [third_party/libwebsockets/repo](https://github.com/warmcat/libwebsockets) from `49bfef2` to `b71a662`. - [Commits](https://github.com/warmcat/libwebsockets/compare/49bfef2ecd51b854b63e35d913849b6bb518a7f6...b71a6621b0b14bfc8fcbe804b036a9543af5e910) --- updated-dependencies: - dependency-name: third_party/libwebsockets/repo dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- third_party/libwebsockets/repo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/third_party/libwebsockets/repo b/third_party/libwebsockets/repo index 49bfef2ecd51b8..b71a6621b0b14b 160000 --- a/third_party/libwebsockets/repo +++ b/third_party/libwebsockets/repo @@ -1 +1 @@ -Subproject commit 49bfef2ecd51b854b63e35d913849b6bb518a7f6 +Subproject commit b71a6621b0b14bfc8fcbe804b036a9543af5e910 From a2e2c8a71818cdf4c0a3efc842bfe3f4457a056b Mon Sep 17 00:00:00 2001 From: Amine Alami <43780877+Alami-Amine@users.noreply.github.com> Date: Tue, 20 Feb 2024 17:06:06 +0100 Subject: [PATCH 037/385] [devcontainer] forcing devcontainer to execute docker build script using bash (#32193) --- .devcontainer/devcontainer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 94ad9314b9a56c..4d5be76434e8f8 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -14,7 +14,7 @@ "mounts": [ "source=/var/run/docker.sock,target=/var/run/docker.sock,type=bind" ], - "initializeCommand": ".devcontainer/build.sh --tag matter-dev-environment:local --version 22", + "initializeCommand": "bash .devcontainer/build.sh --tag matter-dev-environment:local --version 22", "image": "matter-dev-environment:local", "remoteUser": "vscode", "customizations": { From f67c1af64bd326cdb33db1902e74e6fe4b6845bb Mon Sep 17 00:00:00 2001 From: yunhanw-google Date: Tue, 20 Feb 2024 08:47:30 -0800 Subject: [PATCH 038/385] [Android]add missing stack unlock for onattribute and onevent callback for android IM (#32217) * add missing unlock for onattribute and onevent callback for android IM * Restyled by whitespace --------- Co-authored-by: Restyled.io --- src/controller/java/AndroidCallbacks.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/controller/java/AndroidCallbacks.cpp b/src/controller/java/AndroidCallbacks.cpp index eb1584b531e292..01ef820f82c6ed 100644 --- a/src/controller/java/AndroidCallbacks.cpp +++ b/src/controller/java/AndroidCallbacks.cpp @@ -138,7 +138,6 @@ jobject GetNodeStateObj(JNIEnv * env, const char * nodeStateClassSignature, jobj JniReferences::GetInstance().FindMethod(env, wrapperCallback, "getNodeState", nodeStateClassSignature, &getNodeStateMethod); VerifyOrReturnValue(err == CHIP_NO_ERROR, nullptr, ChipLogError(Controller, "Could not find getNodeState method")); - DeviceLayer::StackUnlock unlock; jobject ret = env->CallObjectMethod(wrapperCallback, getNodeStateMethod); VerifyOrReturnValue(!env->ExceptionCheck(), nullptr, env->ExceptionDescribe()); @@ -270,6 +269,7 @@ CHIP_ERROR ConvertReportTlvToJson(const uint32_t id, TLV::TLVReader & data, std: void ReportCallback::OnAttributeData(const app::ConcreteDataAttributePath & aPath, TLV::TLVReader * apData, const app::StatusIB & aStatus) { + DeviceLayer::StackUnlock unlock; CHIP_ERROR err = CHIP_NO_ERROR; JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread(); VerifyOrReturn(env != nullptr, ChipLogError(Controller, "Could not get JNIEnv for current thread")); @@ -408,6 +408,7 @@ void ReportCallback::UpdateClusterDataVersion() void ReportCallback::OnEventData(const app::EventHeader & aEventHeader, TLV::TLVReader * apData, const app::StatusIB * apStatus) { + DeviceLayer::StackUnlock unlock; CHIP_ERROR err = CHIP_NO_ERROR; JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread(); VerifyOrReturn(env != nullptr, ChipLogError(Controller, "Could not get JNIEnv for current thread")); @@ -642,7 +643,6 @@ void ReportCallback::ReportError(const app::ConcreteAttributePath * attributePat eventClusterId = static_cast(eventPath->mClusterId); eventId = static_cast(eventPath->mEventId); } - env->CallVoidMethod(wrapperCallback, onErrorMethod, isAttributePath, attributeEndpointId, attributeClusterId, attributeId, isEventPath, eventEndpointId, eventClusterId, eventId, exception); VerifyOrReturn(!env->ExceptionCheck(), env->ExceptionDescribe()); From 9c1101962b4ed672f13b704e01bb712bbb0f55fd Mon Sep 17 00:00:00 2001 From: Vivien Nicolas Date: Tue, 20 Feb 2024 18:27:52 +0100 Subject: [PATCH 039/385] [MatterYamlTests] Allow enum names in YAML instead of raw values (#32107) * [YAML] Allow the YAML tests to use the enum names instead of the raw value * Update the YAML tests * [MatterYamlTests] Get test_yaml_parser.py to be runned in CI * [MatterYamlTests] Add tests to test_yaml_parser.py * Update errors.py Co-authored-by: Boris Zbarsky --------- Co-authored-by: Boris Zbarsky --- scripts/py_matter_yamltests/BUILD.gn | 1 + .../matter_yamltests/errors.py | 42 ++++ .../matter_yamltests/parser.py | 179 +++++++++++++++-- .../py_matter_yamltests/test_yaml_parser.py | 180 ++++++++++++++++-- .../tests/suites/DL_UsersAndCredentials.yaml | 4 +- .../suites/TestAccessControlConstraints.yaml | 4 +- src/app/tests/suites/TestCluster.yaml | 4 +- src/app/tests/suites/TestDiagnosticLogs.yaml | 4 +- .../suites/certification/Test_TC_ACL_2_4.yaml | 4 +- .../suites/certification/Test_TC_ACL_2_9.yaml | 8 +- .../certification/Test_TC_DRLK_2_9.yaml | 2 +- .../suites/certification/Test_TC_ILL_2_1.yaml | 2 +- .../suites/certification/Test_TC_I_2_3.yaml | 2 +- .../certification/Test_TC_LTIME_3_1.yaml | 4 +- .../certification/Test_TC_LUNIT_3_1.yaml | 2 +- .../certification/Test_TC_TSTAT_2_1.yaml | 8 +- 16 files changed, 394 insertions(+), 56 deletions(-) diff --git a/scripts/py_matter_yamltests/BUILD.gn b/scripts/py_matter_yamltests/BUILD.gn index b886fb04132c37..f8fa027672b868 100644 --- a/scripts/py_matter_yamltests/BUILD.gn +++ b/scripts/py_matter_yamltests/BUILD.gn @@ -55,6 +55,7 @@ pw_python_package("matter_yamltests") { "test_pics_checker.py", "test_parser_builder.py", "test_pseudo_clusters.py", + "test_yaml_parser.py", "test_yaml_loader.py", ] diff --git a/scripts/py_matter_yamltests/matter_yamltests/errors.py b/scripts/py_matter_yamltests/matter_yamltests/errors.py index daa886573569c1..1f26ea4f8354bc 100644 --- a/scripts/py_matter_yamltests/matter_yamltests/errors.py +++ b/scripts/py_matter_yamltests/matter_yamltests/errors.py @@ -222,3 +222,45 @@ def __init__(self, content): self.tag_key_with_error(content, 'attribute') response = content.get('response') self.tag_key_with_error(response, 'saveAs') + + +class TestStepEnumError(TestStepError): + """ + Raise when an enum value or an enum name is not found in the definitions. + + Parameters: + - enum_name_or_value (str|int): The name (str) or value (int) of the enumeration in the step. + If a string is provided, it is considered the name of the enumeration; if an integer is provided, it is considered the value of the enumeration. + - enum_candidates (dict): A dictionary mapping enumeration names (as strings) to their corresponding values + (as integers). This dictionary represents all known values of the enumeration. + """ + + def __init__(self, enum_name_or_value, enum_candidates: dict): + if type(enum_name_or_value) is str: + message = f'Unknown enum name: "{enum_name_or_value}". The possible values are: "{enum_candidates}"' + + for enum_name in enum_candidates: + if enum_name.lower() == enum_name_or_value.lower(): + message = f'Unknown enum name: "{enum_name_or_value}". Did you mean "{enum_name}" ?' + break + + else: + message = f'Unknown enum value: "{enum_name_or_value}". The possible values are: "{enum_candidates}"' + + super().__init__(message) + + +class TestStepEnumSpecifierNotUnknownError(TestStepError): + """Raise when an enum value declared as unknown is in fact a known enum value from the definitions.""" + + def __init__(self, specified_value, enum_name): + message = f'The value "{specified_value}" is not unknown. It is the value of "{enum_name}"' + super().__init__(message) + + +class TestStepEnumSpecifierWrongError(TestStepError): + """Raise when an enum value is specified for a given enum name but it does not match the enum value from the definitions.""" + + def __init__(self, specified_value, enum_name, enum_value): + message = f'The value "{specified_value}" is not the value of "{enum_name}({enum_value})"' + super().__init__(message) diff --git a/scripts/py_matter_yamltests/matter_yamltests/parser.py b/scripts/py_matter_yamltests/matter_yamltests/parser.py index 16f98bcf96d800..cb0a89c6418756 100644 --- a/scripts/py_matter_yamltests/matter_yamltests/parser.py +++ b/scripts/py_matter_yamltests/matter_yamltests/parser.py @@ -15,6 +15,7 @@ import copy import logging +import re from dataclasses import dataclass, field from enum import Enum, auto from typing import Optional @@ -22,7 +23,8 @@ from . import fixes from .constraints import get_constraints, is_typed_constraint from .definitions import SpecDefinitions -from .errors import TestStepError, TestStepKeyError, TestStepValueNameError +from .errors import (TestStepEnumError, TestStepEnumSpecifierNotUnknownError, TestStepEnumSpecifierWrongError, TestStepError, + TestStepKeyError, TestStepValueNameError) from .pics_checker import PICSChecker from .yaml_loader import YamlLoader @@ -38,6 +40,9 @@ 'SubscribeAll', ] +# If True, enum values should use a valid name instead of a raw value +STRICT_ENUM_VALUE_CHECK = False + class UnknownPathQualifierError(TestStepError): """Raise when an attribute/command/event name is not found in the definitions.""" @@ -169,6 +174,99 @@ def _value_or_config(data, key, config): return data[key] if key in data else config.get(key) +class EnumType: + def __init__(self, enum: Enum): + self.type = enum.name + self.base_type = enum.base_type + + self._codes = {} + self.entries_by_name = {} + self.entries_by_code = {} + self._compute_entries(enum) + + def translate(self, key: str, value) -> int: + if self._codes.get(key) is not None and self._codes.get(key) == value: + return self._codes.get(key) + + if type(value) is str: + code = self._get_code_by_name(value) + else: + code = self._get_code_by_value(value) + + if code is None: + raise TestStepEnumError(value, self.entries_by_name) + + self._codes[key] = code + return code + + def _get_code_by_name(self, value): + # For readability the name could sometimes be written as "enum_name(enum_code)" instead of "enum_name" + # In this case the enum_code should be checked to ensure that it is correct, unless enum_name is UnknownEnumValue + # in which case only invalid enum_code are allowed. + specified_name, specified_code = self._extract_name_and_code(value) + if specified_name not in self.entries_by_name: + return None + + enum_code = self.entries_by_name.get(specified_name) + if specified_code is None or specified_code == enum_code: + return enum_code + + if specified_name != f'{self.type}.UnknownEnumValue': + raise TestStepEnumSpecifierWrongError( + specified_code, specified_name, enum_code) + + enum_name = self.entries_by_code.get(specified_code) + if enum_name: + raise TestStepEnumSpecifierNotUnknownError(value, enum_name) + + return specified_code + + def _get_code_by_value(self, value): + enum_name = self.entries_by_code.get(value) + if not enum_name: + return None + + if STRICT_ENUM_VALUE_CHECK: + raise TestStepEnumError(value, self.entries_by_name) + + return value + + def _compute_entries(self, enum: Enum): + enum_codes = [] + for enum_entry in enum.entries: + name = f'{self.type}.{enum_entry.name}' + code = enum_entry.code + + self.entries_by_name[name] = code + self.entries_by_code[code] = name + enum_codes.append(code) + + # search for the first invalid entry if any + max_code = 0xFF + 1 + if self.base_type == 'enum16': + max_code = 0xFFFF + 1 + + for code in range(0, max_code): + if code not in enum_codes: + name = f'{self.type}.UnknownEnumValue' + self.entries_by_name[name] = code + self.entries_by_code[code] = name + break + + def _extract_name_and_code(self, enum_name: str): + match = re.match(r"([\w.]+)(?:\((\w+)\))?", enum_name) + if match: + name = match.group(1) + code = int(match.group(2)) if match.group(2) else None + return name, code + + return None, None + + @staticmethod + def is_valid_type(target_type: str): + return target_type == 'enum8' or target_type == 'enum16' + + class _TestStepWithPlaceholders: '''A single YAML test parsed, as is, from YAML. @@ -441,7 +539,11 @@ def _as_mapping(self, definitions, cluster_name, target_name): element = definitions.get_type_by_name(cluster_name, target_name) if hasattr(element, 'base_type'): - target_name = element.base_type.lower() + if EnumType.is_valid_type(element.base_type): + target_name = EnumType(element) + else: + target_name = element.base_type + elif hasattr(element, 'fields'): target_name = {f.name: self._as_mapping( definitions, cluster_name, f.data_type.name) for f in element.fields} @@ -480,7 +582,11 @@ def _update_with_definition(self, container: dict, mapping_type): if key == 'value': value[key] = self._update_value_with_definition( - item_value, mapping) + value, + key, + item_value, + mapping + ) elif key == 'saveAs' and type(item_value) is str and item_value not in self._parsing_config_variable_storage: self._parsing_config_variable_storage[item_value] = None elif key == 'saveDataVersionAs' and type(item_value) is str and item_value not in self._parsing_config_variable_storage: @@ -491,37 +597,80 @@ def _update_with_definition(self, container: dict, mapping_type): # the the value type for the target field. if is_typed_constraint(constraint): value[key][constraint] = self._update_value_with_definition( - constraint_value, mapping) + item_value, + constraint, + constraint_value, + mapping + ) else: # This key, value pair does not rely on cluster specifications. pass - def _update_value_with_definition(self, value, mapping_type): + def _update_value_with_definition(self, container: dict, key: str, value, mapping_type): + """ + Processes a given value based on a specified mapping type and returns the updated value. + This method does not modify the container in place; rather, it returns a new value that should be + used to update or process further as necessary. + + The 'container' and 'key' parameters are primarily used for error tagging. If an error occurs + during the value processing, these parameters allow for the error to be precisely located and + reported, facilitating easier debugging and error tracking. + + Parameters: + - container (dict): A dictionary that serves as a context for the operation. It is used for error + tagging if processing fails, by associating errors with specific locations within the data structure. + - key (str): The key related to the value being processed. It is used alongside 'container' to tag + errors, enabling precise identification of the error source. + - value: The value to be processed according to the mapping type. + - mapping_type: Dictates the processing or mapping logic to be applied to 'value'. + + Returns: + The processed value, which is the result of applying the specified mapping type to the original 'value'. + This method does not update the 'container'; any necessary updates based on the processed value must + be handled outside this method. + + Raises: + - TestStepError: If an error occurs during the processing of the value. The error includes details + from the 'container' and 'key' to facilitate error tracing and debugging. + """ + if not mapping_type: return value if type(value) is dict: rv = {} - for key in value: + for item_key in value: # FabricIndex is a special case where the framework requires it to be passed even # if it is not part of the requested arguments per spec and not part of the XML # definition. - if key == 'FabricIndex' or key == 'fabricIndex': - rv[key] = value[key] # int64u + if item_key == 'FabricIndex' or item_key == 'fabricIndex': + rv[item_key] = value[item_key] # int64u else: - if not mapping_type.get(key): - raise TestStepKeyError(value, key) - mapping = mapping_type[key] - rv[key] = self._update_value_with_definition( - value[key], mapping) + if not mapping_type.get(item_key): + raise TestStepKeyError(value, item_key) + mapping = mapping_type[item_key] + rv[item_key] = self._update_value_with_definition( + value, + item_key, + value[item_key], + mapping + ) return rv + if type(value) is list: - return [self._update_value_with_definition(entry, mapping_type) for entry in value] + return [self._update_value_with_definition(container, key, entry, mapping_type) for entry in value] + # TODO currently unsure if the check of `value not in config` is sufficant. For # example let's say value = 'foo + 1' and map type is 'int64u', we would arguably do # the wrong thing below. if value is not None and value not in self._parsing_config_variable_storage: - if mapping_type == 'int64u' or mapping_type == 'int64s' or mapping_type == 'bitmap64' or mapping_type == 'epoch_us': + if type(mapping_type) is EnumType: + try: + value = mapping_type.translate(key, value) + except (TestStepEnumError, TestStepEnumSpecifierNotUnknownError, TestStepEnumSpecifierWrongError) as e: + e.tag_key_with_error(container, key) + raise e + elif mapping_type == 'int64u' or mapping_type == 'int64s' or mapping_type == 'bitmap64' or mapping_type == 'epoch_us': value = fixes.try_apply_float_to_integer_fix(value) value = fixes.try_apply_yaml_cpp_longlong_limitation_fix(value) value = fixes.try_apply_yaml_unrepresentable_integer_for_javascript_fixes( diff --git a/scripts/py_matter_yamltests/test_yaml_parser.py b/scripts/py_matter_yamltests/test_yaml_parser.py index 055f949773f9d3..27472572a96d6b 100644 --- a/scripts/py_matter_yamltests/test_yaml_parser.py +++ b/scripts/py_matter_yamltests/test_yaml_parser.py @@ -20,14 +20,22 @@ # is arguably better then no checks at all. import io -import tempfile import unittest +from unittest.mock import mock_open, patch from matter_yamltests.definitions import ParseSource, SpecDefinitions +from matter_yamltests.errors import TestStepEnumError, TestStepEnumSpecifierNotUnknownError, TestStepEnumSpecifierWrongError from matter_yamltests.parser import TestParser, TestParserConfig simple_test_description = ''' + + + + + + + @@ -36,8 +44,11 @@ Test 0x1234 - + test_enum + + + ''' @@ -52,43 +63,145 @@ tests: - label: "Send Test Command" command: "test" +''' + +enum_values_yaml = ''' +name: Test Enum Values + +config: + nodeId: 0x12344321 + cluster: "Test" + endpoint: 1 + +tests: + - label: "Read attribute test_enum Value" + command: "readAttribute" + attribute: "test_enum" + response: + value: 0 + + - label: "Read attribute test_enum Value" + command: "readAttribute" + attribute: "test_enum" + response: + value: TestEnum.A + + - label: "Read attribute test_enum Value" + command: "readAttribute" + attribute: "test_enum" + response: + value: TestEnum.A(0) + + - label: "Read attribute test_enum Value" + command: "readAttribute" + attribute: "test_enum" + response: + value: TestEnum.UnknownEnumValue + + - label: "Read attribute test_enum Value" + command: "readAttribute" + attribute: "test_enum" + response: + value: TestEnum.UnknownEnumValue(255) + + - label: "Write attribute test_enum Value" + command: "writeAttribute" + attribute: "test_enum" + arguments: + value: 0 + + - label: "Write attribute test_enum Value" + command: "writeAttribute" + attribute: "test_enum" + arguments: + value: TestEnum.A + + - label: "Write attribute test_enum Value" + command: "writeAttribute" + attribute: "test_enum" + arguments: + value: TestEnum.A(0) + + - label: "Write attribute test_enum Value" + command: "writeAttribute" + attribute: "test_enum" + arguments: + value: TestEnum.UnknownEnumValue + + - label: "Write attribute test_enum Value" + command: "writeAttribute" + attribute: "test_enum" + arguments: + value: TestEnum.UnknownEnumValue(255) +''' + +enum_value_read_response_wrong_code_yaml = ''' +tests: + - label: "Read attribute test_enum Value" + cluster: "Test" + command: "readAttribute" + attribute: "test_enum" + response: + value: 123 +''' + +enum_value_read_response_wrong_name_yaml = ''' +tests: + - label: "Read attribute test_enum Value" + cluster: "Test" + command: "readAttribute" + attribute: "test_enum" + response: + value: ThisIsWrong +''' - - label: "Send Test Not Handled Command" - command: "testNotHandled" +enum_value_read_response_wrong_code_specified_yaml = ''' +tests: + - label: "Read attribute test_enum Value" + cluster: "Test" + command: "readAttribute" + attribute: "test_enum" response: - error: INVALID_COMMAND + value: TestEnum.A(123) +''' - - label: "Send Test Specific Command" - command: "testSpecific" +enum_value_read_response_not_unknown_code_specified_yaml = ''' +tests: + - label: "Read attribute test_enum Value" + cluster: "Test" + command: "readAttribute" + attribute: "test_enum" response: - values: - - name: "returnValue" - value: 7 + value: TestEnum.UnknownEnumValue(0) ''' +def mock_open_with_parameter_content(content): + file_object = mock_open(read_data=content).return_value + file_object.__iter__.return_value = content.splitlines(True) + return file_object + + +@patch('builtins.open', new=mock_open_with_parameter_content) class TestYamlParser(unittest.TestCase): def setUp(self): self._definitions = SpecDefinitions( [ParseSource(source=io.StringIO(simple_test_description), name='simple_test_description')]) - self._temp_file = tempfile.NamedTemporaryFile(suffix='.yaml') - with open(self._temp_file.name, 'w') as f: - f.writelines(simple_test_yaml) def test_able_to_iterate_over_all_parsed_tests(self): # self._yaml_parser.tests implements `__next__`, which does value substitution. We are # simply ensure there is no exceptions raise. parser_config = TestParserConfig(None, self._definitions) - yaml_parser = TestParser(self._temp_file.name, parser_config) + yaml_parser = TestParser(simple_test_yaml, parser_config) count = 0 for idx, test_step in enumerate(yaml_parser.tests): count += 1 pass - self.assertEqual(count, 3) + self.assertEqual(count, 1) def test_config(self): parser_config = TestParserConfig(None, self._definitions) - yaml_parser = TestParser(self._temp_file.name, parser_config) + yaml_parser = TestParser(simple_test_yaml, parser_config) for idx, test_step in enumerate(yaml_parser.tests): self.assertEqual(test_step.node_id, 0x12344321) self.assertEqual(test_step.cluster, 'Test') @@ -99,7 +212,7 @@ def test_config_override(self): 'cluster': 'TestOverride', 'endpoint': 4} parser_config = TestParserConfig( None, self._definitions, config_override) - yaml_parser = TestParser(self._temp_file.name, parser_config) + yaml_parser = TestParser(simple_test_yaml, parser_config) for idx, test_step in enumerate(yaml_parser.tests): self.assertEqual(test_step.node_id, 12345) self.assertEqual(test_step.cluster, 'TestOverride') @@ -109,8 +222,37 @@ def test_config_override_unknown_field(self): config_override = {'unknown_field': 1} parser_config = TestParserConfig( None, self._definitions, config_override) - self.assertRaises(KeyError, TestParser, - self._temp_file.name, parser_config) + + yaml_parser = TestParser(simple_test_yaml, parser_config) + self.assertIsInstance(yaml_parser, TestParser) + + def test_config_valid_enum_values(self): + parser_config = TestParserConfig(None, self._definitions) + yaml_parser = TestParser(enum_values_yaml, parser_config) + self.assertIsInstance(yaml_parser, TestParser) + + for idx, test_step in enumerate(yaml_parser.tests): + pass + + def test_config_read_response_wrong_code(self): + parser_config = TestParserConfig(None, self._definitions) + self.assertRaises(TestStepEnumError, TestParser, + enum_value_read_response_wrong_code_yaml, parser_config) + + def test_config_read_response_wrong_name(self): + parser_config = TestParserConfig(None, self._definitions) + self.assertRaises(TestStepEnumError, TestParser, + enum_value_read_response_wrong_name_yaml, parser_config) + + def test_config_read_response_wrong_code_specified(self): + parser_config = TestParserConfig(None, self._definitions) + self.assertRaises(TestStepEnumSpecifierWrongError, TestParser, + enum_value_read_response_wrong_code_specified_yaml, parser_config) + + def test_config_read_response_not_unknown_code_specified(self): + parser_config = TestParserConfig(None, self._definitions) + self.assertRaises(TestStepEnumSpecifierNotUnknownError, TestParser, + enum_value_read_response_not_unknown_code_specified_yaml, parser_config) def main(): diff --git a/src/app/tests/suites/DL_UsersAndCredentials.yaml b/src/app/tests/suites/DL_UsersAndCredentials.yaml index 0a344d4883eba6..e86fbbe56dc053 100644 --- a/src/app/tests/suites/DL_UsersAndCredentials.yaml +++ b/src/app/tests/suites/DL_UsersAndCredentials.yaml @@ -562,7 +562,7 @@ tests: - name: "UserUniqueID" value: 0xBABA - name: "UserStatus" - value: 2 + value: UserStatusEnum.UnknownEnumValue(2) - name: "UserType" value: null - name: "CredentialRule" @@ -1031,7 +1031,7 @@ tests: - name: "UserIndex" value: null - name: "UserStatus" - value: 2 + value: UserStatusEnum.UnknownEnumValue(2) - name: "UserType" value: null response: diff --git a/src/app/tests/suites/TestAccessControlConstraints.yaml b/src/app/tests/suites/TestAccessControlConstraints.yaml index 82e66b8d347c10..1a54ea48f92365 100644 --- a/src/app/tests/suites/TestAccessControlConstraints.yaml +++ b/src/app/tests/suites/TestAccessControlConstraints.yaml @@ -130,7 +130,7 @@ tests: { FabricIndex: 0, Privilege: 3, - AuthMode: 4, # INVALID + AuthMode: AccessControlEntryAuthModeEnum.UnknownEnumValue, Subjects: [], Targets: null, }, @@ -231,7 +231,7 @@ tests: }, { FabricIndex: 0, - Privilege: 6, # INVALID + Privilege: AccessControlEntryPrivilegeEnum.UnknownEnumValue, AuthMode: 2, # CASE Subjects: null, Targets: null, diff --git a/src/app/tests/suites/TestCluster.yaml b/src/app/tests/suites/TestCluster.yaml index d51aea86b777f6..017d6ce6b6daf4 100644 --- a/src/app/tests/suites/TestCluster.yaml +++ b/src/app/tests/suites/TestCluster.yaml @@ -1066,7 +1066,7 @@ tests: - name: "arg1" value: 20003 - name: "arg2" - value: 101 + value: SimpleEnum.UnknownEnumValue response: # Attempting to echo back the invalid enum value should fail. error: FAILURE @@ -2814,7 +2814,7 @@ tests: command: "writeAttribute" attribute: "nullable_enum_attr" arguments: - value: 255 + value: SimpleEnum.UnknownEnumValue(255) response: error: CONSTRAINT_ERROR diff --git a/src/app/tests/suites/TestDiagnosticLogs.yaml b/src/app/tests/suites/TestDiagnosticLogs.yaml index 57ab8cb0fa04f8..2e512d962678c3 100644 --- a/src/app/tests/suites/TestDiagnosticLogs.yaml +++ b/src/app/tests/suites/TestDiagnosticLogs.yaml @@ -443,7 +443,7 @@ tests: arguments: values: - name: "Intent" - value: 128 # undefined value + value: IntentEnum.UnknownEnumValue(128) - name: "RequestedProtocol" value: 0 # ResponsePayload response: @@ -456,7 +456,7 @@ tests: - name: "Intent" value: 0 # EndUserSupport - name: "RequestedProtocol" - value: 128 # undefined value + value: TransferProtocolEnum.UnknownEnumValue(128) response: error: "INVALID_COMMAND" diff --git a/src/app/tests/suites/certification/Test_TC_ACL_2_4.yaml b/src/app/tests/suites/certification/Test_TC_ACL_2_4.yaml index bd173e7eb81427..12a6829c642048 100644 --- a/src/app/tests/suites/certification/Test_TC_ACL_2_4.yaml +++ b/src/app/tests/suites/certification/Test_TC_ACL_2_4.yaml @@ -1164,7 +1164,7 @@ tests: FabricIndex: CurrentFabricIndexValue, }, { - Privilege: 6, + Privilege: AccessControlEntryPrivilegeEnum.UnknownEnumValue, AuthMode: 2, Subjects: null, Targets: null, @@ -1192,7 +1192,7 @@ tests: }, { Privilege: 3, - AuthMode: 4, + AuthMode: AccessControlEntryAuthModeEnum.UnknownEnumValue, Subjects: null, Targets: null, FabricIndex: CurrentFabricIndexValue, diff --git a/src/app/tests/suites/certification/Test_TC_ACL_2_9.yaml b/src/app/tests/suites/certification/Test_TC_ACL_2_9.yaml index 22ce1c1451f5a4..d2db93f33b1cd8 100644 --- a/src/app/tests/suites/certification/Test_TC_ACL_2_9.yaml +++ b/src/app/tests/suites/certification/Test_TC_ACL_2_9.yaml @@ -66,8 +66,8 @@ tests: value: [ { - Privilege: "4", - AuthMode: "2", + Privilege: AccessControlEntryPrivilegeEnum.Manage, + AuthMode: AccessControlEntryAuthModeEnum.CASE, Subjects: [CommissionerNodeId], Targets: null, FabricIndex: CurrentFabricIndexValue, @@ -94,8 +94,8 @@ tests: value: [ { - Privilege: "5", - AuthMode: "2", + Privilege: AccessControlEntryPrivilegeEnum.Administer, + AuthMode: AccessControlEntryAuthModeEnum.CASE, Subjects: [CommissionerNodeId], Targets: null, FabricIndex: CurrentFabricIndexValue, diff --git a/src/app/tests/suites/certification/Test_TC_DRLK_2_9.yaml b/src/app/tests/suites/certification/Test_TC_DRLK_2_9.yaml index 9f2e34ea6d01ed..0c10f9fa7ba058 100644 --- a/src/app/tests/suites/certification/Test_TC_DRLK_2_9.yaml +++ b/src/app/tests/suites/certification/Test_TC_DRLK_2_9.yaml @@ -167,7 +167,7 @@ tests: - name: "UserIndex" value: null - name: "UserStatus" - value: 5 + value: UserStatusEnum.UnknownEnumValue(5) - name: "UserType" value: 10 response: diff --git a/src/app/tests/suites/certification/Test_TC_ILL_2_1.yaml b/src/app/tests/suites/certification/Test_TC_ILL_2_1.yaml index 6afdb920658f94..741fc878e8880f 100644 --- a/src/app/tests/suites/certification/Test_TC_ILL_2_1.yaml +++ b/src/app/tests/suites/certification/Test_TC_ILL_2_1.yaml @@ -86,4 +86,4 @@ tests: constraints: type: enum8 minValue: 0 - maxValue: 254 + maxValue: LightSensorTypeEnum.UnknownEnumValue(254) diff --git a/src/app/tests/suites/certification/Test_TC_I_2_3.yaml b/src/app/tests/suites/certification/Test_TC_I_2_3.yaml index 379ed424638c9b..343539ce69e624 100644 --- a/src/app/tests/suites/certification/Test_TC_I_2_3.yaml +++ b/src/app/tests/suites/certification/Test_TC_I_2_3.yaml @@ -237,7 +237,7 @@ tests: - name: "EffectIdentifier" value: 0 - name: "EffectVariant" - value: 66 + value: EffectVariantEnum.UnknownEnumValue(66) - label: "Check DUT executes a blink effect." cluster: "LogCommands" diff --git a/src/app/tests/suites/certification/Test_TC_LTIME_3_1.yaml b/src/app/tests/suites/certification/Test_TC_LTIME_3_1.yaml index ead4e9b246c853..b011a94ce9cef7 100644 --- a/src/app/tests/suites/certification/Test_TC_LTIME_3_1.yaml +++ b/src/app/tests/suites/certification/Test_TC_LTIME_3_1.yaml @@ -352,7 +352,7 @@ tests: command: "writeAttribute" attribute: "ActiveCalendarType" arguments: - value: 50 + value: CalendarTypeEnum.UnknownEnumValue(50) response: error: CONSTRAINT_ERROR @@ -361,6 +361,6 @@ tests: command: "writeAttribute" attribute: "HourFormat" arguments: - value: 5 + value: HourFormatEnum.UnknownEnumValue(5) response: error: CONSTRAINT_ERROR diff --git a/src/app/tests/suites/certification/Test_TC_LUNIT_3_1.yaml b/src/app/tests/suites/certification/Test_TC_LUNIT_3_1.yaml index a572f7e143dc43..b67c22a871ced9 100644 --- a/src/app/tests/suites/certification/Test_TC_LUNIT_3_1.yaml +++ b/src/app/tests/suites/certification/Test_TC_LUNIT_3_1.yaml @@ -94,6 +94,6 @@ tests: arguments: # Per spec, if [TEMP] feature is enabled, then this attribute can be # one of 0 (Farenheit), 1 (Celsius) or 2 (Kelvin) - value: 5 # INVALID + value: TempUnitEnum.UnknownEnumValue(5) response: error: CONSTRAINT_ERROR diff --git a/src/app/tests/suites/certification/Test_TC_TSTAT_2_1.yaml b/src/app/tests/suites/certification/Test_TC_TSTAT_2_1.yaml index 63aba52fe3f3f6..faf34fdea43e92 100644 --- a/src/app/tests/suites/certification/Test_TC_TSTAT_2_1.yaml +++ b/src/app/tests/suites/certification/Test_TC_TSTAT_2_1.yaml @@ -468,8 +468,12 @@ tests: response: constraints: type: enum8 - minValue: 0 - maxValue: 9 + anyOf: + [ + ThermostatRunningModeEnum.Off(0), + ThermostatRunningModeEnum.Cool(3), + ThermostatRunningModeEnum.Heat(4), + ] - label: "Step 27: TH reads the StartOfWeek attribute from the DUT" PICS: TSTAT.S.F03 From 6350333131ef0fb95d469a6987a34f0bbcc95b7e Mon Sep 17 00:00:00 2001 From: Junior Martinez <67972863+jmartinez-silabs@users.noreply.github.com> Date: Tue, 20 Feb 2024 16:10:07 -0500 Subject: [PATCH 040/385] [THREAD] Bring clear all Srp Client host and Services to the GenericThreadStackManagerImpl (#32215) * Bring the functionality to clear all Srp Client host and Services to the GenericThreadStackManagerImpl * Fix Tizen build * Update src/platform/Tizen/ThreadStackManagerImpl.cpp Co-authored-by: Arkadiusz Bokowy * Add method documentation and address comments * Restyled by whitespace --------- Co-authored-by: Arkadiusz Bokowy Co-authored-by: Restyled.io --- src/include/platform/ThreadStackManager.h | 35 +++++++++++++ src/platform/ESP32/ThreadStackManagerImpl.cpp | 24 +++++++++ src/platform/ESP32/ThreadStackManagerImpl.h | 11 ++++ .../GenericThreadStackManagerImpl_FreeRTOS.h | 8 +++ ...GenericThreadStackManagerImpl_FreeRTOS.hpp | 26 ++++++++++ .../CYW30739/ThreadStackManagerImpl.cpp | 23 ++++++++ .../CYW30739/ThreadStackManagerImpl.h | 8 +++ src/platform/Linux/ThreadStackManagerImpl.h | 5 ++ ...GenericThreadStackManagerImpl_OpenThread.h | 3 ++ ...nericThreadStackManagerImpl_OpenThread.hpp | 35 +++++++++++++ src/platform/Tizen/ThreadStackManagerImpl.cpp | 10 ++++ src/platform/Tizen/ThreadStackManagerImpl.h | 6 +++ .../Zephyr/ThreadStackManagerImpl.cpp | 16 ++++++ src/platform/Zephyr/ThreadStackManagerImpl.h | 8 +++ .../silabs/ConfigurationManagerImpl.cpp | 2 +- src/platform/silabs/ThreadStackManagerImpl.h | 11 ---- .../silabs/efr32/ThreadStackManagerImpl.cpp | 52 ------------------- .../telink/ThreadStackManagerImpl.cpp | 16 ++++++ src/platform/telink/ThreadStackManagerImpl.h | 8 +++ src/platform/webos/ThreadStackManagerImpl.h | 5 ++ 20 files changed, 248 insertions(+), 64 deletions(-) diff --git a/src/include/platform/ThreadStackManager.h b/src/include/platform/ThreadStackManager.h index 86d895ec1cfe52..cda3c7acdccbd5 100644 --- a/src/include/platform/ThreadStackManager.h +++ b/src/include/platform/ThreadStackManager.h @@ -121,6 +121,26 @@ class ThreadStackManager CHIP_ERROR RemoveSrpService(const char * aInstanceName, const char * aName); CHIP_ERROR InvalidateAllSrpServices(); ///< Mark all SRP services as invalid CHIP_ERROR RemoveInvalidSrpServices(); ///< Remove SRP services marked as invalid + + /* + * @brief Utility function to clear all thread SRP host and services established between the SRP server and client. + * It is expected that a transaction is done between the SRP server and client so the clear request is applied on both ends + * + * A generic implementation is provided in `GenericThreadStackManagerImpl_OpenThread` with the SoC OT stack + */ + CHIP_ERROR ClearAllSrpHostAndServices(); + + /* + * @brief Used to synchronize on the SRP server response confirming the clearing of the host and service entries + * Should be called in ClearAllSrpHostAndServices once the request is sent. + */ + void WaitOnSrpClearAllComplete(); + + /* + * @brief Notify that the SRP server confirmed the clearing of the host and service entries + * Should be called in the SRP Client set callback in the removal confirmation. + */ + void NotifySrpClearAllComplete(); CHIP_ERROR SetupSrpHost(const char * aHostName); CHIP_ERROR ClearSrpHost(const char * aHostName); CHIP_ERROR SetSrpDnsCallbacks(DnsAsyncReturnCallback aInitCallback, DnsAsyncReturnCallback aErrorCallback, void * aContext); @@ -289,6 +309,21 @@ inline CHIP_ERROR ThreadStackManager::RemoveInvalidSrpServices() return static_cast(this)->_RemoveInvalidSrpServices(); } +inline CHIP_ERROR ThreadStackManager::ClearAllSrpHostAndServices() +{ + return static_cast(this)->_ClearAllSrpHostAndServices(); +} + +inline void ThreadStackManager::WaitOnSrpClearAllComplete() +{ + return static_cast(this)->_WaitOnSrpClearAllComplete(); +} + +inline void ThreadStackManager::NotifySrpClearAllComplete() +{ + return static_cast(this)->_NotifySrpClearAllComplete(); +} + inline CHIP_ERROR ThreadStackManager::SetupSrpHost(const char * aHostName) { return static_cast(this)->_SetupSrpHost(aHostName); diff --git a/src/platform/ESP32/ThreadStackManagerImpl.cpp b/src/platform/ESP32/ThreadStackManagerImpl.cpp index eed07af6d68af1..0449607999668b 100644 --- a/src/platform/ESP32/ThreadStackManagerImpl.cpp +++ b/src/platform/ESP32/ThreadStackManagerImpl.cpp @@ -77,6 +77,30 @@ void ThreadStackManagerImpl::_UnlockThreadStack() esp_openthread_lock_release(); } +#if CHIP_DEVICE_CONFIG_ENABLE_THREAD_SRP_CLIENT +void ThreadStackManagerImpl::_WaitOnSrpClearAllComplete() +{ + // Only 1 task can be blocked on a srpClearAll request + if (mSrpClearAllRequester == nullptr) + { + mSrpClearAllRequester = xTaskGetCurrentTaskHandle(); + // Wait on OnSrpClientNotification which confirms the clearing is done. + // It will notify this current task with NotifySrpClearAllComplete. + // However, we won't wait more than 2s. + ulTaskNotifyTake(pdTRUE, pdMS_TO_TICKS(2000)); + mSrpClearAllRequester = nullptr; + } +} + +void ThreadStackManagerImpl::_NotifySrpClearAllComplete() +{ + if (mSrpClearAllRequester) + { + xTaskNotifyGive(mSrpClearAllRequester); + } +} +#endif // CHIP_DEVICE_CONFIG_ENABLE_THREAD_SRP_CLIENT + void ThreadStackManagerImpl::_ProcessThreadActivity() { // Intentionally empty. diff --git a/src/platform/ESP32/ThreadStackManagerImpl.h b/src/platform/ESP32/ThreadStackManagerImpl.h index 46795d658d6535..1287e7a5f3a1ba 100644 --- a/src/platform/ESP32/ThreadStackManagerImpl.h +++ b/src/platform/ESP32/ThreadStackManagerImpl.h @@ -68,10 +68,21 @@ class ThreadStackManagerImpl final : public ThreadStackManager, void _OnCHIPoBLEAdvertisingStart(); void _OnCHIPoBLEAdvertisingStop(); +#if CHIP_DEVICE_CONFIG_ENABLE_THREAD_SRP_CLIENT + void _WaitOnSrpClearAllComplete(); + void _NotifySrpClearAllComplete(); +#endif // CHIP_DEVICE_CONFIG_ENABLE_THREAD_SRP_CLIENT + // ===== Methods that override the GenericThreadStackMa + private: friend ThreadStackManager & ::chip::DeviceLayer::ThreadStackMgr(void); friend ThreadStackManagerImpl & ::chip::DeviceLayer::ThreadStackMgrImpl(void); static ThreadStackManagerImpl sInstance; + +#if CHIP_DEVICE_CONFIG_ENABLE_THREAD_SRP_CLIENT + TaskHandle_t mSrpClearAllRequester = nullptr; +#endif + ThreadStackManagerImpl() = default; }; diff --git a/src/platform/FreeRTOS/GenericThreadStackManagerImpl_FreeRTOS.h b/src/platform/FreeRTOS/GenericThreadStackManagerImpl_FreeRTOS.h index 870fcf2ed80657..059b701f6bda05 100644 --- a/src/platform/FreeRTOS/GenericThreadStackManagerImpl_FreeRTOS.h +++ b/src/platform/FreeRTOS/GenericThreadStackManagerImpl_FreeRTOS.h @@ -64,6 +64,10 @@ class GenericThreadStackManagerImpl_FreeRTOS bool _TryLockThreadStack(void); void _UnlockThreadStack(void); +#if CHIP_DEVICE_CONFIG_ENABLE_THREAD_SRP_CLIENT + void _WaitOnSrpClearAllComplete(); + void _NotifySrpClearAllComplete(); +#endif // CHIP_DEVICE_CONFIG_ENABLE_THREAD_SRP_CLIENT // ===== Members available to the implementation subclass. SemaphoreHandle_t mThreadStackLock; @@ -88,6 +92,10 @@ class GenericThreadStackManagerImpl_FreeRTOS #if defined(CHIP_CONFIG_FREERTOS_USE_STATIC_SEMAPHORE) && CHIP_CONFIG_FREERTOS_USE_STATIC_SEMAPHORE StaticSemaphore_t mThreadStackLockMutex; #endif + +#if CHIP_DEVICE_CONFIG_ENABLE_THREAD_SRP_CLIENT + TaskHandle_t mSrpClearAllRequester = nullptr; +#endif }; // Instruct the compiler to instantiate the template only when explicitly told to do so. diff --git a/src/platform/FreeRTOS/GenericThreadStackManagerImpl_FreeRTOS.hpp b/src/platform/FreeRTOS/GenericThreadStackManagerImpl_FreeRTOS.hpp index 4dbee81b23af01..9008258989375e 100644 --- a/src/platform/FreeRTOS/GenericThreadStackManagerImpl_FreeRTOS.hpp +++ b/src/platform/FreeRTOS/GenericThreadStackManagerImpl_FreeRTOS.hpp @@ -101,6 +101,32 @@ void GenericThreadStackManagerImpl_FreeRTOS::_UnlockThreadStack(void) xSemaphoreGive(mThreadStackLock); } +#if CHIP_DEVICE_CONFIG_ENABLE_THREAD_SRP_CLIENT +template +void GenericThreadStackManagerImpl_FreeRTOS::_WaitOnSrpClearAllComplete() +{ + // Only 1 task can be blocked on a srpClearAll request + if (mSrpClearAllRequester == nullptr) + { + mSrpClearAllRequester = xTaskGetCurrentTaskHandle(); + // Wait on OnSrpClientNotification which confirms the slearing is done. + // It will notify this current task with NotifySrpClearAllComplete. + // However, we won't wait more than 2s. + ulTaskNotifyTake(pdTRUE, pdMS_TO_TICKS(2000)); + mSrpClearAllRequester = nullptr; + } +} + +template +void GenericThreadStackManagerImpl_FreeRTOS::_NotifySrpClearAllComplete() +{ + if (mSrpClearAllRequester) + { + xTaskNotifyGive(mSrpClearAllRequester); + } +} +#endif // CHIP_DEVICE_CONFIG_ENABLE_THREAD_SRP_CLIENT + template void GenericThreadStackManagerImpl_FreeRTOS::SignalThreadActivityPending() { diff --git a/src/platform/Infineon/CYW30739/ThreadStackManagerImpl.cpp b/src/platform/Infineon/CYW30739/ThreadStackManagerImpl.cpp index f0393a795ef63a..21297d75cf5252 100644 --- a/src/platform/Infineon/CYW30739/ThreadStackManagerImpl.cpp +++ b/src/platform/Infineon/CYW30739/ThreadStackManagerImpl.cpp @@ -54,6 +54,14 @@ CHIP_ERROR ThreadStackManagerImpl::_InitThreadStack() VerifyOrExit(result == WICED_SUCCESS, err = CHIP_ERROR_INTERNAL); otSysInit(0, NULL); +#if CHIP_DEVICE_CONFIG_ENABLE_THREAD_SRP_CLIENT + mSrpClearAllSemaphore = wiced_rtos_create_mutex(); + VerifyOrExit(mSrpClearAllSemaphore != nullptr, err = CHIP_ERROR_NO_MEMORY); + + result = wiced_rtos_init_mutex(mSrpClearAllSemaphore); + VerifyOrExit(result == WICED_SUCCESS, err = CHIP_ERROR_INTERNAL); +#endif // CHIP_DEVICE_CONFIG_ENABLE_THREAD_SRP_CLIENT + err = GenericThreadStackManagerImpl_OpenThread::DoInit(NULL); exit: @@ -95,6 +103,21 @@ void ThreadStackManagerImpl::_UnlockThreadStack() VerifyOrReturn(result == WICED_SUCCESS || result == WICED_NOT_OWNED, ChipLogError(DeviceLayer, "%s %x", __func__, result)); } +#if CHIP_DEVICE_CONFIG_ENABLE_THREAD_SRP_CLIENT +void ThreadStackManagerImpl::_WaitOnSrpClearAllComplete() +{ + const wiced_result_t result = wiced_rtos_lock_mutex(mSrpClearAllSemaphore); + VerifyOrReturn(result == WICED_SUCCESS, ChipLogError(DeviceLayer, "%s %x", __func__, result)); +} + +void ThreadStackManagerImpl::_NotifySrpClearAllComplete() +{ + const wiced_result_t result = wiced_rtos_unlock_mutex(mSrpClearAllSemaphore); + VerifyOrReturn(result == WICED_SUCCESS || result == WICED_NOT_OWNED, ChipLogError(DeviceLayer, "%s %x", __func__, result)); +} +#endif // CHIP_DEVICE_CONFIG_ENABLE_THREAD_SRP_CLIENT +// ===== Methods that override the GenericThreadStackMa + void ThreadStackManagerImpl::ThreadTaskMain(void) { while (true) diff --git a/src/platform/Infineon/CYW30739/ThreadStackManagerImpl.h b/src/platform/Infineon/CYW30739/ThreadStackManagerImpl.h index cdb2cb8ee65fdc..5cd3fef1c60239 100644 --- a/src/platform/Infineon/CYW30739/ThreadStackManagerImpl.h +++ b/src/platform/Infineon/CYW30739/ThreadStackManagerImpl.h @@ -58,6 +58,11 @@ class ThreadStackManagerImpl final : public ThreadStackManager, bool _TryLockThreadStack(); void _UnlockThreadStack(); +#if CHIP_DEVICE_CONFIG_ENABLE_THREAD_SRP_CLIENT + void _WaitOnSrpClearAllComplete(); + void _NotifySrpClearAllComplete(); +#endif // CHIP_DEVICE_CONFIG_ENABLE_THREAD_SRP_CLIENT + // ===== Methods that override the GenericThreadStackMa private: // ===== Members for internal use by the following friends. @@ -67,6 +72,9 @@ class ThreadStackManagerImpl final : public ThreadStackManager, wiced_thread_t * mThread; EventFlags mEventFlags; wiced_mutex_t * mMutex; +#if CHIP_DEVICE_CONFIG_ENABLE_THREAD_SRP_CLIENT + wiced_mutex_t * mSrpClearAllSemaphore; +#endif // CHIP_DEVICE_CONFIG_ENABLE_THREAD_SRP_CLIENT static ThreadStackManagerImpl sInstance; // ===== Private members for use by this class only. diff --git a/src/platform/Linux/ThreadStackManagerImpl.h b/src/platform/Linux/ThreadStackManagerImpl.h index 977c6b94d0027f..e262837dd84c76 100755 --- a/src/platform/Linux/ThreadStackManagerImpl.h +++ b/src/platform/Linux/ThreadStackManagerImpl.h @@ -57,6 +57,11 @@ class ThreadStackManagerImpl : public ThreadStackManager bool _TryLockThreadStack() { return false; } // Intentionally left blank void _UnlockThreadStack() {} // Intentionally left blank +#if CHIP_DEVICE_CONFIG_ENABLE_THREAD_SRP_CLIENT + void _WaitOnSrpClearAllComplete() {} + void _NotifySrpClearAllComplete() {} +#endif // CHIP_DEVICE_CONFIG_ENABLE_THREAD_SRP_CLIENT + bool _HaveRouteToAddress(const Inet::IPAddress & destAddr); void _OnPlatformEvent(const ChipDeviceEvent * event); diff --git a/src/platform/OpenThread/GenericThreadStackManagerImpl_OpenThread.h b/src/platform/OpenThread/GenericThreadStackManagerImpl_OpenThread.h index 161c2b202a8310..8ce0805182dcaa 100644 --- a/src/platform/OpenThread/GenericThreadStackManagerImpl_OpenThread.h +++ b/src/platform/OpenThread/GenericThreadStackManagerImpl_OpenThread.h @@ -121,6 +121,7 @@ class GenericThreadStackManagerImpl_OpenThread CHIP_ERROR _RemoveSrpService(const char * aInstanceName, const char * aName); CHIP_ERROR _InvalidateAllSrpServices(); CHIP_ERROR _RemoveInvalidSrpServices(); + CHIP_ERROR _ClearAllSrpHostAndServices(); CHIP_ERROR _SetupSrpHost(const char * aHostName); CHIP_ERROR _ClearSrpHost(const char * aHostName); @@ -203,6 +204,8 @@ class GenericThreadStackManagerImpl_OpenThread SrpClient mSrpClient; + bool mIsSrpClearAllRequested = false; + static void OnSrpClientNotification(otError aError, const otSrpClientHostInfo * aHostInfo, const otSrpClientService * aServices, const otSrpClientService * aRemovedServices, void * aContext); static void OnSrpClientStateChange(const otSockAddr * aServerSockAddr, void * aContext); diff --git a/src/platform/OpenThread/GenericThreadStackManagerImpl_OpenThread.hpp b/src/platform/OpenThread/GenericThreadStackManagerImpl_OpenThread.hpp index acc0c78d0c8eb7..21c44dd00279e3 100644 --- a/src/platform/OpenThread/GenericThreadStackManagerImpl_OpenThread.hpp +++ b/src/platform/OpenThread/GenericThreadStackManagerImpl_OpenThread.hpp @@ -1307,6 +1307,12 @@ void GenericThreadStackManagerImpl_OpenThread::OnSrpClientNotificatio ThreadStackMgrImpl().mSrpClient.mIsInitialized = true; ThreadStackMgrImpl().mSrpClient.mInitializedCallback(ThreadStackMgrImpl().mSrpClient.mCallbackContext, CHIP_NO_ERROR); + + if (ThreadStackMgrImpl().mIsSrpClearAllRequested) + { + ThreadStackMgrImpl().NotifySrpClearAllComplete(); + ThreadStackMgrImpl().mIsSrpClearAllRequested = false; + } } } @@ -1618,6 +1624,35 @@ CHIP_ERROR GenericThreadStackManagerImpl_OpenThread::_RemoveInvalidSr return error; } +/* + * @brief This is a utility function to remove all Thread client srp host and services + * established between the device and the srp server (in most cases the OTBR). + * The calling task is blocked until OnSrpClientNotification which confims the client received the request. + * The blocking mechanism is defined by the platform implementation of `WaitOnSrpClearAllComplete` and `NotifySrpClearAllComplete` + * + * Note: This function is meant to be used during the factory reset sequence. + * + */ +template +CHIP_ERROR GenericThreadStackManagerImpl_OpenThread::_ClearAllSrpHostAndServices() +{ + CHIP_ERROR error = CHIP_NO_ERROR; + Impl()->LockThreadStack(); + if (!mIsSrpClearAllRequested) + { + error = + MapOpenThreadError(otSrpClientRemoveHostAndServices(mOTInst, true /*aRemoveKeyLease*/, true /*aSendUnregToServer*/)); + mIsSrpClearAllRequested = true; + Impl()->UnlockThreadStack(); + Impl()->WaitOnSrpClearAllComplete(); + } + else + { + Impl()->UnlockThreadStack(); + } + return error; +} + template CHIP_ERROR GenericThreadStackManagerImpl_OpenThread::_SetupSrpHost(const char * aHostName) { diff --git a/src/platform/Tizen/ThreadStackManagerImpl.cpp b/src/platform/Tizen/ThreadStackManagerImpl.cpp index 47a4548507e332..e6252d92926190 100644 --- a/src/platform/Tizen/ThreadStackManagerImpl.cpp +++ b/src/platform/Tizen/ThreadStackManagerImpl.cpp @@ -646,6 +646,16 @@ CHIP_ERROR ThreadStackManagerImpl::_RemoveInvalidSrpServices() return CHIP_NO_ERROR; } +CHIP_ERROR ThreadStackManagerImpl::_ClearAllSrpHostAndServices() +{ + for (auto it = mSrpClientServices.begin(); it != mSrpClientServices.end();) + { + ReturnErrorOnFailure(_RemoveSrpService(it->mInstanceName, it->mName)); + it = mSrpClientServices.erase(it); + } + return CHIP_NO_ERROR; +} + void ThreadStackManagerImpl::_ThreadIpAddressCb(int index, char * ipAddr, thread_ipaddr_type_e ipAddrType, void * userData) { VerifyOrReturn(ipAddr != nullptr, ChipLogError(DeviceLayer, "FAIL: Invalid argument: Thread ipAddr not found")); diff --git a/src/platform/Tizen/ThreadStackManagerImpl.h b/src/platform/Tizen/ThreadStackManagerImpl.h index 05b300f574114b..07092f43b320eb 100644 --- a/src/platform/Tizen/ThreadStackManagerImpl.h +++ b/src/platform/Tizen/ThreadStackManagerImpl.h @@ -57,6 +57,11 @@ class ThreadStackManagerImpl : public ThreadStackManager bool _TryLockThreadStack() { return false; } // Intentionally left blank void _UnlockThreadStack() {} // Intentionally left blank +#if CHIP_DEVICE_CONFIG_ENABLE_THREAD_SRP_CLIENT + void _WaitOnSrpClearAllComplete() {} + void _NotifySrpClearAllComplete() {} +#endif // CHIP_DEVICE_CONFIG_ENABLE_THREAD_SRP_CLIENT + bool _HaveRouteToAddress(const Inet::IPAddress & destAddr); void _OnPlatformEvent(const ChipDeviceEvent * event); @@ -115,6 +120,7 @@ class ThreadStackManagerImpl : public ThreadStackManager CHIP_ERROR _RemoveSrpService(const char * aInstanceName, const char * aName); CHIP_ERROR _InvalidateAllSrpServices(); CHIP_ERROR _RemoveInvalidSrpServices(); + CHIP_ERROR _ClearAllSrpHostAndServices(); CHIP_ERROR _SetupSrpHost(const char * aHostName); CHIP_ERROR _ClearSrpHost(const char * aHostName); CHIP_ERROR _SetSrpDnsCallbacks(DnsAsyncReturnCallback aInitCallback, DnsAsyncReturnCallback aErrorCallback, void * aContext); diff --git a/src/platform/Zephyr/ThreadStackManagerImpl.cpp b/src/platform/Zephyr/ThreadStackManagerImpl.cpp index 3cfcfe3b7888b2..95bdfc8ea7044a 100644 --- a/src/platform/Zephyr/ThreadStackManagerImpl.cpp +++ b/src/platform/Zephyr/ThreadStackManagerImpl.cpp @@ -66,6 +66,10 @@ CHIP_ERROR ThreadStackManagerImpl::_InitThreadStack() return MapOpenThreadError(otError); }); +#if CHIP_DEVICE_CONFIG_ENABLE_THREAD_SRP_CLIENT + k_sem_init(&mSrpClearAllSemaphore, 0, 1); +#endif // CHIP_DEVICE_CONFIG_ENABLE_THREAD_SRP_CLIENT + return CHIP_NO_ERROR; } @@ -85,5 +89,17 @@ void ThreadStackManagerImpl::_UnlockThreadStack() openthread_api_mutex_unlock(openthread_get_default_context()); } +#if CHIP_DEVICE_CONFIG_ENABLE_THREAD_SRP_CLIENT +void ThreadStackManagerImpl::_WaitOnSrpClearAllComplete() +{ + k_sem_take(&mSrpClearAllSemaphore, K_SECONDS(2)); +} + +void ThreadStackManagerImpl::_NotifySrpClearAllComplete() +{ + k_sem_give(&mSrpClearAllSemaphore); +} +#endif // CHIP_DEVICE_CONFIG_ENABLE_THREAD_SRP_CLIENT + } // namespace DeviceLayer } // namespace chip diff --git a/src/platform/Zephyr/ThreadStackManagerImpl.h b/src/platform/Zephyr/ThreadStackManagerImpl.h index c0c66b492c6b1d..ec9feb8b121d3e 100644 --- a/src/platform/Zephyr/ThreadStackManagerImpl.h +++ b/src/platform/Zephyr/ThreadStackManagerImpl.h @@ -71,6 +71,10 @@ class ThreadStackManagerImpl final : public ThreadStackManager, bool _TryLockThreadStack(); void _UnlockThreadStack(); +#if CHIP_DEVICE_CONFIG_ENABLE_THREAD_SRP_CLIENT + void _WaitOnSrpClearAllComplete(); + void _NotifySrpClearAllComplete(); +#endif // CHIP_DEVICE_CONFIG_ENABLE_THREAD_SRP_CLIENT // ===== Methods that override the GenericThreadStackManagerImpl_OpenThread abstract interface. void _ProcessThreadActivity() {} @@ -83,6 +87,10 @@ class ThreadStackManagerImpl final : public ThreadStackManager, friend ThreadStackManager & ::chip::DeviceLayer::ThreadStackMgr(void); friend ThreadStackManagerImpl & ::chip::DeviceLayer::ThreadStackMgrImpl(void); +#if CHIP_DEVICE_CONFIG_ENABLE_THREAD_SRP_CLIENT + k_sem mSrpClearAllSemaphore; +#endif // CHIP_DEVICE_CONFIG_ENABLE_THREAD_SRP_CLIENT + static ThreadStackManagerImpl sInstance; // ===== Private members for use by this class only. diff --git a/src/platform/silabs/ConfigurationManagerImpl.cpp b/src/platform/silabs/ConfigurationManagerImpl.cpp index a3e1778c11ac3f..8412075de3a914 100644 --- a/src/platform/silabs/ConfigurationManagerImpl.cpp +++ b/src/platform/silabs/ConfigurationManagerImpl.cpp @@ -272,7 +272,7 @@ void ConfigurationManagerImpl::DoFactoryReset(intptr_t arg) #if CHIP_DEVICE_CONFIG_ENABLE_THREAD #if CHIP_DEVICE_CONFIG_ENABLE_THREAD_SRP_CLIENT - ThreadStackMgrImpl().RemoveAllSrpServices(); + ThreadStackMgr().ClearAllSrpHostAndServices(); #endif // CHIP_DEVICE_CONFIG_ENABLE_THREAD_SRP_CLIENT ChipLogProgress(DeviceLayer, "Clearing Thread provision"); ThreadStackMgr().ErasePersistentInfo(); diff --git a/src/platform/silabs/ThreadStackManagerImpl.h b/src/platform/silabs/ThreadStackManagerImpl.h index b1436b3b75b27e..c56990fb0d3712 100644 --- a/src/platform/silabs/ThreadStackManagerImpl.h +++ b/src/platform/silabs/ThreadStackManagerImpl.h @@ -72,19 +72,11 @@ class ThreadStackManagerImpl final : public ThreadStackManager, using ThreadStackManager::InitThreadStack; CHIP_ERROR InitThreadStack(otInstance * otInst); -#if CHIP_DEVICE_CONFIG_ENABLE_THREAD_SRP_CLIENT - void RemoveAllSrpServices(); -#endif private: // ===== Methods that implement the ThreadStackManager abstract interface. CHIP_ERROR _InitThreadStack(void); -#if CHIP_DEVICE_CONFIG_ENABLE_THREAD_SRP_CLIENT - static void OnSrpClientRemoveCallback(otError aError, const otSrpClientHostInfo * aHostInfo, - const otSrpClientService * aServices, const otSrpClientService * aRemovedServices, - void * aContext); -#endif // ===== Members for internal use by the following friends. friend ThreadStackManager & ::chip::DeviceLayer::ThreadStackMgr(void); @@ -94,9 +86,6 @@ class ThreadStackManagerImpl final : public ThreadStackManager, static ThreadStackManagerImpl sInstance; static bool IsInitialized(); -#if CHIP_DEVICE_CONFIG_ENABLE_THREAD_SRP_CLIENT - TaskHandle_t srpRemoveRequester = nullptr; -#endif // ===== Private members for use by this class only. diff --git a/src/platform/silabs/efr32/ThreadStackManagerImpl.cpp b/src/platform/silabs/efr32/ThreadStackManagerImpl.cpp index c4556036034e78..83767f9a0e1fb8 100644 --- a/src/platform/silabs/efr32/ThreadStackManagerImpl.cpp +++ b/src/platform/silabs/efr32/ThreadStackManagerImpl.cpp @@ -66,58 +66,6 @@ bool ThreadStackManagerImpl::IsInitialized() return sInstance.mThreadStackLock != NULL; } -#if CHIP_DEVICE_CONFIG_ENABLE_THREAD_SRP_CLIENT -/* - * @brief Notifies `RemoveAllSrpServices` that the Srp Client removal has completed - * and unblock the calling task. - * - * No data is processed. - */ -void ThreadStackManagerImpl::OnSrpClientRemoveCallback(otError aError, const otSrpClientHostInfo * aHostInfo, - const otSrpClientService * aServices, - const otSrpClientService * aRemovedServices, void * aContext) -{ - if (ThreadStackMgrImpl().srpRemoveRequester) - { - xTaskNotifyGive(ThreadStackMgrImpl().srpRemoveRequester); - } -} - -/* - * @brief This is a utility function to remove all Thread client Srp services - * established between the device and the srp server (in most cases the OTBR). - * The calling task is blocked until OnSrpClientRemoveCallback. - * - * Note: This function is meant to be used during the factory reset sequence. - * It overrides the generic SrpClient callback `OnSrpClientNotification` with - * OnSrpClientRemoveCallback which doesn't process any of the callback data. - * - * If there is a usecase where this function would be needed in a non-Factory reset context, - * OnSrpClientRemoveCallback should be extended and tied back with the GenericThreadStackManagerImpl_OpenThread - * management of the srp clients. - */ -void ThreadStackManagerImpl::RemoveAllSrpServices() -{ - // This check ensure that only one srp services removal is running - if (ThreadStackMgrImpl().srpRemoveRequester == nullptr) - { - srpRemoveRequester = xTaskGetCurrentTaskHandle(); - otSrpClientSetCallback(OTInstance(), &OnSrpClientRemoveCallback, nullptr); - InvalidateAllSrpServices(); - if (RemoveInvalidSrpServices() == CHIP_NO_ERROR) - { - // Wait for the OnSrpClientRemoveCallback. - ulTaskNotifyTake(pdTRUE, pdMS_TO_TICKS(2000)); - } - else - { - ChipLogError(DeviceLayer, "Failed to remove srp services"); - } - ThreadStackMgrImpl().srpRemoveRequester = nullptr; - } -} -#endif // CHIP_DEVICE_CONFIG_ENABLE_THREAD_SRP_CLIENT - } // namespace DeviceLayer } // namespace chip diff --git a/src/platform/telink/ThreadStackManagerImpl.cpp b/src/platform/telink/ThreadStackManagerImpl.cpp index e66735b1de68f2..13ba8be424563b 100644 --- a/src/platform/telink/ThreadStackManagerImpl.cpp +++ b/src/platform/telink/ThreadStackManagerImpl.cpp @@ -68,6 +68,10 @@ CHIP_ERROR ThreadStackManagerImpl::_InitThreadStack() return MapOpenThreadError(otError); }); +#if CHIP_DEVICE_CONFIG_ENABLE_THREAD_SRP_CLIENT + k_sem_init(&mSrpClearAllSemaphore, 0, 1); +#endif // CHIP_DEVICE_CONFIG_ENABLE_THREAD_SRP_CLIENT + return CHIP_NO_ERROR; } @@ -87,6 +91,18 @@ void ThreadStackManagerImpl::_UnlockThreadStack() openthread_api_mutex_unlock(openthread_get_default_context()); } +#if CHIP_DEVICE_CONFIG_ENABLE_THREAD_SRP_CLIENT +void ThreadStackManagerImpl::_WaitOnSrpClearAllComplete() +{ + k_sem_take(&mSrpClearAllSemaphore, K_SECONDS(2)); +} + +void ThreadStackManagerImpl::_NotifySrpClearAllComplete() +{ + k_sem_give(&mSrpClearAllSemaphore); +} +#endif // CHIP_DEVICE_CONFIG_ENABLE_THREAD_SRP_CLIENT + CHIP_ERROR ThreadStackManagerImpl::_AttachToThreadNetwork(const Thread::OperationalDataset & dataset, NetworkCommissioning::Internal::WirelessDriver::ConnectCallback * callback) diff --git a/src/platform/telink/ThreadStackManagerImpl.h b/src/platform/telink/ThreadStackManagerImpl.h index d1040542f3c616..21db9972f62dec 100644 --- a/src/platform/telink/ThreadStackManagerImpl.h +++ b/src/platform/telink/ThreadStackManagerImpl.h @@ -74,6 +74,10 @@ class ThreadStackManagerImpl final : public ThreadStackManager, bool _TryLockThreadStack(); void _UnlockThreadStack(); +#if CHIP_DEVICE_CONFIG_ENABLE_THREAD_SRP_CLIENT + void _WaitOnSrpClearAllComplete(); + void _NotifySrpClearAllComplete(); +#endif // CHIP_DEVICE_CONFIG_ENABLE_THREAD_SRP_CLIENT // ===== Methods that override the GenericThreadStackManagerImpl_OpenThread abstract interface. void _ProcessThreadActivity() {} @@ -95,6 +99,10 @@ class ThreadStackManagerImpl final : public ThreadStackManager, bool mRadioBlocked; bool mReadyToAttach; +#if CHIP_DEVICE_CONFIG_ENABLE_THREAD_SRP_CLIENT + k_sem mSrpClearAllSemaphore; +#endif // CHIP_DEVICE_CONFIG_ENABLE_THREAD_SRP_CLIENT + NetworkCommissioning::ThreadDriver::ScanCallback * mpScanCallback; }; diff --git a/src/platform/webos/ThreadStackManagerImpl.h b/src/platform/webos/ThreadStackManagerImpl.h index 876c339cceb6ae..a21d4cbf551251 100644 --- a/src/platform/webos/ThreadStackManagerImpl.h +++ b/src/platform/webos/ThreadStackManagerImpl.h @@ -50,6 +50,11 @@ class ThreadStackManagerImpl : public ThreadStackManager bool _TryLockThreadStack() { return false; } // Intentionally left blank void _UnlockThreadStack() {} // Intentionally left blank +#if CHIP_DEVICE_CONFIG_ENABLE_THREAD_SRP_CLIENT + void _WaitOnSrpClearAllComplete() {} + void _NotifySrpClearAllComplete() {} +#endif // CHIP_DEVICE_CONFIG_ENABLE_THREAD_SRP_CLIENT + bool _HaveRouteToAddress(const Inet::IPAddress & destAddr); void _OnPlatformEvent(const ChipDeviceEvent * event); From b8de5cc5ea9b103fc2b1f9c4ac42cf41d7416e72 Mon Sep 17 00:00:00 2001 From: David Rempel <63119829+drempelg@users.noreply.github.com> Date: Tue, 20 Feb 2024 15:16:02 -0800 Subject: [PATCH 041/385] Feature/energypreferences (#30244) * Adding the Energy Preferences XML * Added just the xml and regenerated. No implementations yet as requested. * regen * put the cluster back into all-clusters after merge. * Apply suggestions from code review Added suggestions for ARRAY vs array Co-authored-by: Boris Zbarsky * regenerate * Finished up impl for energy-preferences * Added some error checking for features, and constraint checking. Also turned on the features in the all-clusters-app * Restyled by whitespace * Restyled by clang-format * Fixed copy paste bug * Removed some unecessary changes and a comment. * initialize the delegate pointer * Put the cluster back in the all-clusters app after the merge * Fixed minor issues from review * Restyled by whitespace * Addressing some review concerns * Some more comments resolved * Better documentation, a set of braces I missed last time around, and added an extra header include. * fix build error after merge * Restyled by whitespace * Restyled by clang-format * Update src/app/clusters/energy-preference-server/energy-preference-server.cpp Co-authored-by: Boris Zbarsky * Implement proposed API changes with clearer delineation of storage * Restyled by clang-format * Typo * Regen zap, update code to reflect the updated return from Feature::Get * ZAP regen, to fix merge errors * Apply suggestions from code review Co-authored-by: Boris Zbarsky * Address suggestion re: optionality conversion * Fix one more omission * another small fix * Fix up copyright headers * Restyled by clang-format * Reinitialize storage objects on every iteration * fix typo * Restyled by clang-format * Apply suggestions from code review Co-authored-by: Boris Zbarsky --------- Co-authored-by: Boris Zbarsky Co-authored-by: Restyled.io Co-authored-by: Robert Szewczyk --- .../all-clusters-app.matter | 48 ++++ .../all-clusters-common/all-clusters-app.zap | 186 ++++++++++++++ .../src/energy-preference-delegate.cpp | 137 ++++++++++ .../all-clusters-app/ameba/chip_main.cmake | 1 + .../esp32/main/CMakeLists.txt | 5 +- examples/all-clusters-app/linux/BUILD.gn | 1 + .../energy-preference-server.cpp | 235 ++++++++++++++++++ .../energy-preference-server.h | 107 ++++++++ src/app/common/templates/config-data.yaml | 1 + .../chip/energy-preference-cluster.xml | 1 + src/app/zap_cluster_list.json | 2 +- .../data_model/controller-clusters.matter | 2 +- 12 files changed, 723 insertions(+), 3 deletions(-) create mode 100644 examples/all-clusters-app/all-clusters-common/src/energy-preference-delegate.cpp create mode 100644 src/app/clusters/energy-preference-server/energy-preference-server.cpp create mode 100644 src/app/clusters/energy-preference-server/energy-preference-server.h diff --git a/examples/all-clusters-app/all-clusters-common/all-clusters-app.matter b/examples/all-clusters-app/all-clusters-common/all-clusters-app.matter index 62dc0d7d84c3fa..5a7b510b05b0c8 100644 --- a/examples/all-clusters-app/all-clusters-common/all-clusters-app.matter +++ b/examples/all-clusters-app/all-clusters-common/all-clusters-app.matter @@ -4455,6 +4455,40 @@ provisional cluster EnergyEvse = 153 { timed command ClearTargets(): DefaultSuccess = 7; } +/** This cluster provides an interface to specify preferences for how devices should consume energy. */ +provisional cluster EnergyPreference = 155 { + revision 1; + + enum EnergyPriorityEnum : enum8 { + kComfort = 0; + kSpeed = 1; + kEfficiency = 2; + kWaterConsumption = 3; + } + + bitmap Feature : bitmap32 { + kEnergyBalance = 0x1; + kLowPowerModeSensitivity = 0x2; + } + + struct BalanceStruct { + percent step = 0; + optional char_string<64> label = 1; + } + + readonly attribute optional BalanceStruct energyBalances[] = 0; + attribute optional int8u currentEnergyBalance = 1; + readonly attribute optional EnergyPriorityEnum energyPriorities[] = 2; + readonly attribute optional BalanceStruct lowPowerModeSensitivities[] = 3; + attribute optional int8u currentLowPowerModeSensitivity = 4; + 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; +} + /** The Power Topology Cluster provides a mechanism for expressing how power is flowing between endpoints. */ provisional cluster PowerTopology = 156 { revision 1; @@ -8361,6 +8395,20 @@ endpoint 1 { handle command ClearTargets; } + server cluster EnergyPreference { + callback attribute energyBalances; + ram attribute currentEnergyBalance; + callback attribute energyPriorities; + callback attribute lowPowerModeSensitivities; + ram attribute currentLowPowerModeSensitivity; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute eventList; + callback attribute attributeList; + ram attribute featureMap default = 3; + ram attribute clusterRevision default = 1; + } + server cluster PowerTopology { callback attribute availableEndpoints; callback attribute activeEndpoints; diff --git a/examples/all-clusters-app/all-clusters-common/all-clusters-app.zap b/examples/all-clusters-app/all-clusters-common/all-clusters-app.zap index 0a2a3faf1b37e8..21bcfee37b5e0d 100644 --- a/examples/all-clusters-app/all-clusters-common/all-clusters-app.zap +++ b/examples/all-clusters-app/all-clusters-common/all-clusters-app.zap @@ -14692,6 +14692,192 @@ } ] }, + { + "name": "Energy Preference", + "code": 155, + "mfgCode": null, + "define": "ENERGY_PREFERENCE_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "EnergyBalances", + "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 + }, + { + "name": "CurrentEnergyBalance", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "EnergyPriorities", + "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": "LowPowerModeSensitivities", + "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": "CurrentLowPowerModeSensitivity", + "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": "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": "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, + "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": "3", + "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": "Window Covering", "code": 258, diff --git a/examples/all-clusters-app/all-clusters-common/src/energy-preference-delegate.cpp b/examples/all-clusters-app/all-clusters-common/src/energy-preference-delegate.cpp new file mode 100644 index 00000000000000..cd9b47dd7979e6 --- /dev/null +++ b/examples/all-clusters-app/all-clusters-common/src/energy-preference-delegate.cpp @@ -0,0 +1,137 @@ +/* + * + * Copyright (c) 2024 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::Clusters::EnergyPreference; +using namespace chip::app::Clusters::EnergyPreference::Structs; + +static BalanceStruct::Type gsEnergyBalances[] = { + { .step = 0, .label = Optional("Efficient"_span) }, + { .step = 50, .label = Optional() }, + { .step = 100, .label = Optional("Comfort"_span) }, +}; + +static BalanceStruct::Type gsPowerBalances[] = { + { .step = 0, .label = Optional("1 Minute"_span) }, + { .step = 12, .label = Optional("5 Minutes"_span) }, + { .step = 24, .label = Optional("10 Minutes"_span) }, + { .step = 36, .label = Optional("15 Minutes"_span) }, + { .step = 48, .label = Optional("20 Minutes"_span) }, + { .step = 60, .label = Optional("25 Minutes"_span) }, + { .step = 70, .label = Optional("30 Minutes"_span) }, + { .step = 80, .label = Optional("60 Minutes"_span) }, + { .step = 90, .label = Optional("120 Minutes"_span) }, + { .step = 100, .label = Optional("Never"_span) }, +}; + +// assumes it'll be the only delegate for it's lifetime. +struct EPrefDelegate : public Delegate +{ + EPrefDelegate(); + virtual ~EPrefDelegate(); + + CHIP_ERROR GetEnergyBalanceAtIndex(chip::EndpointId aEndpoint, size_t aIndex, chip::Percent & aOutStep, + chip::Optional & aOutLabel) override; + CHIP_ERROR GetEnergyPriorityAtIndex(chip::EndpointId aEndpoint, size_t aIndex, EnergyPriorityEnum & priority) override; + CHIP_ERROR GetLowPowerModeSensitivityAtIndex(chip::EndpointId aEndpoint, size_t aIndex, chip::Percent & aOutStep, + chip::Optional & aOutLabel) override; + + size_t GetNumEnergyBalances(chip::EndpointId aEndpoint) override; + size_t GetNumLowPowerModeSensitivities(chip::EndpointId aEndpoint) override; +}; + +EPrefDelegate::EPrefDelegate() : Delegate() +{ + VerifyOrDie(GetDelegate() == nullptr); + SetDelegate(this); +} + +EPrefDelegate::~EPrefDelegate() +{ + VerifyOrDie(GetDelegate() == this); + SetDelegate(nullptr); +} + +size_t EPrefDelegate::GetNumEnergyBalances(chip::EndpointId aEndpoint) +{ + return (ArraySize(gsEnergyBalances)); +} + +size_t EPrefDelegate::GetNumLowPowerModeSensitivities(chip::EndpointId aEndpoint) +{ + return (ArraySize(gsEnergyBalances)); +} + +CHIP_ERROR +EPrefDelegate::GetEnergyBalanceAtIndex(chip::EndpointId aEndpoint, size_t aIndex, chip::Percent & aOutStep, + chip::Optional & aOutLabel) +{ + if (aIndex < GetNumEnergyBalances(aEndpoint)) + { + aOutStep = gsEnergyBalances[aIndex].step; + if (gsEnergyBalances[aIndex].label.HasValue()) + { + chip::CopyCharSpanToMutableCharSpan(gsEnergyBalances[aIndex].label.Value(), aOutLabel.Value()); + } + else + { + aOutLabel.ClearValue(); + } + return CHIP_NO_ERROR; + } + return CHIP_ERROR_NOT_FOUND; +} + +CHIP_ERROR +EPrefDelegate::GetEnergyPriorityAtIndex(chip::EndpointId aEndpoint, size_t aIndex, EnergyPriorityEnum & priority) +{ + static EnergyPriorityEnum priorities[] = { EnergyPriorityEnum::kEfficiency, EnergyPriorityEnum::kComfort }; + + if (aIndex < ArraySize(priorities)) + { + priority = priorities[aIndex]; + return CHIP_NO_ERROR; + } + + return CHIP_ERROR_NOT_FOUND; +} + +CHIP_ERROR +EPrefDelegate::GetLowPowerModeSensitivityAtIndex(chip::EndpointId aEndpoint, size_t aIndex, chip::Percent & aOutStep, + chip::Optional & aOutLabel) +{ + if (aIndex < GetNumLowPowerModeSensitivities(aEndpoint)) + { + aOutStep = gsPowerBalances[aIndex].step; + if (gsPowerBalances[aIndex].label.HasValue()) + { + chip::CopyCharSpanToMutableCharSpan(gsPowerBalances[aIndex].label.Value(), aOutLabel.Value()); + } + else + { + aOutLabel.ClearValue(); + } + return CHIP_NO_ERROR; + } + + return CHIP_ERROR_NOT_FOUND; +} + +static EPrefDelegate gsDelegate; diff --git a/examples/all-clusters-app/ameba/chip_main.cmake b/examples/all-clusters-app/ameba/chip_main.cmake index 0d8b99c117716e..c4572063508ac0 100755 --- a/examples/all-clusters-app/ameba/chip_main.cmake +++ b/examples/all-clusters-app/ameba/chip_main.cmake @@ -158,6 +158,7 @@ list( ${chip_dir}/examples/all-clusters-app/all-clusters-common/src/concentration-measurement-instances.cpp ${chip_dir}/examples/all-clusters-app/all-clusters-common/src/device-energy-management-stub.cpp ${chip_dir}/examples/all-clusters-app/all-clusters-common/src/energy-evse-stub.cpp + ${chip_dir}/examples/all-clusters-app/all-clusters-common/src/energy-preference-delegate.cpp ${chip_dir}/examples/all-clusters-app/all-clusters-common/src/fan-stub.cpp ${chip_dir}/examples/all-clusters-app/all-clusters-common/src/oven-modes.cpp ${chip_dir}/examples/all-clusters-app/all-clusters-common/src/laundry-washer-controls-delegate-impl.cpp diff --git a/examples/all-clusters-app/esp32/main/CMakeLists.txt b/examples/all-clusters-app/esp32/main/CMakeLists.txt index 238f0e899c340d..63851b1deeb611 100644 --- a/examples/all-clusters-app/esp32/main/CMakeLists.txt +++ b/examples/all-clusters-app/esp32/main/CMakeLists.txt @@ -96,8 +96,11 @@ set(SRC_DIRS_LIST "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/time-synchronization-server" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/valve-configuration-and-control-server" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/dishwasher-alarm-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/laundry-washer-controls-server" + "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/laundry-washer-controls-server" + "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/laundry-washer-controls-server" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/laundry-dryer-controls-server" + "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/all-clusters-app/all-clusters-common/src" + "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/energy-preference-server" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/electrical-energy-measurement-server" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/electrical-power-measurement-server" ) diff --git a/examples/all-clusters-app/linux/BUILD.gn b/examples/all-clusters-app/linux/BUILD.gn index 998f98a19cd3de..3d52ef748de90d 100644 --- a/examples/all-clusters-app/linux/BUILD.gn +++ b/examples/all-clusters-app/linux/BUILD.gn @@ -40,6 +40,7 @@ source_set("chip-all-clusters-common") { "${chip_root}/examples/all-clusters-app/all-clusters-common/src/electrical-energy-measurement-stub.cpp", "${chip_root}/examples/all-clusters-app/all-clusters-common/src/electrical-power-measurement-stub.cpp", "${chip_root}/examples/all-clusters-app/all-clusters-common/src/energy-evse-stub.cpp", + "${chip_root}/examples/all-clusters-app/all-clusters-common/src/energy-preference-delegate.cpp", "${chip_root}/examples/all-clusters-app/all-clusters-common/src/fan-stub.cpp", "${chip_root}/examples/all-clusters-app/all-clusters-common/src/laundry-dryer-controls-delegate-impl.cpp", "${chip_root}/examples/all-clusters-app/all-clusters-common/src/laundry-washer-controls-delegate-impl.cpp", diff --git a/src/app/clusters/energy-preference-server/energy-preference-server.cpp b/src/app/clusters/energy-preference-server/energy-preference-server.cpp new file mode 100644 index 00000000000000..7cb377a7221ba1 --- /dev/null +++ b/src/app/clusters/energy-preference-server/energy-preference-server.cpp @@ -0,0 +1,235 @@ +/** + * + * Copyright (c) 2024 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "energy-preference-server.h" + +#include // Needed for registerAttributeAccessOverride + +#include +#include +#include +#include +#include +#include +#include + +using namespace chip; +using namespace chip::app; +using namespace chip::app::Clusters; +using namespace chip::app::Clusters::EnergyPreference; +using namespace chip::app::Clusters::EnergyPreference::Structs; +using namespace chip::app::Clusters::EnergyPreference::Attributes; + +using Status = Protocols::InteractionModel::Status; + +namespace { + +class EnergyPrefAttrAccess : public AttributeAccessInterface +{ +public: + EnergyPrefAttrAccess() : AttributeAccessInterface(Optional::Missing(), EnergyPreference::Id) {} + + CHIP_ERROR Read(const ConcreteReadAttributePath & aPath, AttributeValueEncoder & aEncoder) override; +}; + +EnergyPrefAttrAccess gEnergyPrefAttrAccess; +Delegate * gsDelegate = nullptr; + +CHIP_ERROR EnergyPrefAttrAccess::Read(const ConcreteReadAttributePath & aPath, AttributeValueEncoder & aEncoder) +{ + VerifyOrDie(aPath.mClusterId == EnergyPreference::Id); + EndpointId endpoint = aPath.mEndpointId; + uint32_t ourFeatureMap = 0; + const bool featureMapIsGood = FeatureMap::Get(aPath.mEndpointId, &ourFeatureMap) == Status::Success; + const bool balanceSupported = featureMapIsGood && ((ourFeatureMap & to_underlying(Feature::kEnergyBalance)) != 0); + const bool lowPowerSupported = featureMapIsGood && ((ourFeatureMap & to_underlying(Feature::kLowPowerModeSensitivity)) != 0); + + switch (aPath.mAttributeId) + { + case EnergyBalances::Id: + if (!balanceSupported) + { + return CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute); + } + + if (gsDelegate != nullptr) + { + return aEncoder.EncodeList([endpoint](const auto & encoder) -> CHIP_ERROR { + size_t index = 0; + CHIP_ERROR err = CHIP_NO_ERROR; + do + { + Percent step; + char buffer[64]; + Optional label{ MutableCharSpan(buffer) }; + if ((err = gsDelegate->GetEnergyBalanceAtIndex(endpoint, index, step, label)) == CHIP_NO_ERROR) + { + BalanceStruct::Type balance = { step, + label.HasValue() ? Optional(label.Value()) + : Optional() }; + ReturnErrorOnFailure(encoder.Encode(balance)); + index++; + } + } while (err == CHIP_NO_ERROR); + + if (err == CHIP_ERROR_NOT_FOUND) + { + return CHIP_NO_ERROR; + } + return err; + }); + } + return CHIP_ERROR_INCORRECT_STATE; + case EnergyPriorities::Id: + if (balanceSupported == false) + { + return CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute); + } + + if (gsDelegate != nullptr) + { + return aEncoder.EncodeList([endpoint](const auto & encoder) -> CHIP_ERROR { + EnergyPriorityEnum priority; + size_t index = 0; + CHIP_ERROR err = CHIP_NO_ERROR; + while ((err = gsDelegate->GetEnergyPriorityAtIndex(endpoint, index, priority)) == CHIP_NO_ERROR) + { + ReturnErrorOnFailure(encoder.Encode(priority)); + index++; + } + if (err == CHIP_ERROR_NOT_FOUND) + { + return CHIP_NO_ERROR; + } + return err; + }); + } + return CHIP_ERROR_INCORRECT_STATE; + case LowPowerModeSensitivities::Id: + if (lowPowerSupported == false) + { + return CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute); + } + + if (gsDelegate != nullptr) + { + return aEncoder.EncodeList([endpoint](const auto & encoder) -> CHIP_ERROR { + size_t index = 0; + CHIP_ERROR err = CHIP_NO_ERROR; + do + { + Percent step; + char buffer[64]; + Optional label{ MutableCharSpan(buffer) }; + if ((err = gsDelegate->GetLowPowerModeSensitivityAtIndex(endpoint, index, step, label)) == CHIP_NO_ERROR) + { + BalanceStruct::Type balance = { step, + label.HasValue() ? Optional(label.Value()) + : Optional() }; + ReturnErrorOnFailure(encoder.Encode(balance)); + index++; + } + } while (err == CHIP_NO_ERROR); + if (err == CHIP_ERROR_NOT_FOUND) + { + return CHIP_NO_ERROR; + } + return err; + }); + } + return CHIP_ERROR_INCORRECT_STATE; + default: // return CHIP_NO_ERROR and just read from the attribute store in default + break; + } + + return CHIP_NO_ERROR; +} + +} // anonymous namespace + +namespace chip::app::Clusters::EnergyPreference { + +void SetDelegate(Delegate * aDelegate) +{ + gsDelegate = aDelegate; +} + +Delegate * GetDelegate() +{ + return gsDelegate; +} + +} // namespace chip::app::Clusters::EnergyPreference + +Status MatterEnergyPreferenceClusterServerPreAttributeChangedCallback(const ConcreteAttributePath & attributePath, + EmberAfAttributeType attributeType, uint16_t size, + uint8_t * value) +{ + EndpointId endpoint = attributePath.mEndpointId; + Delegate * delegate = GetDelegate(); + uint32_t ourFeatureMap; + const bool featureMapIsGood = FeatureMap::Get(attributePath.mEndpointId, &ourFeatureMap) == Status::Success; + const bool balanceSupported = featureMapIsGood && ((ourFeatureMap & to_underlying(Feature::kEnergyBalance)) != 0); + const bool lowPowerSupported = featureMapIsGood && ((ourFeatureMap & to_underlying(Feature::kLowPowerModeSensitivity)) != 0); + + if (delegate == nullptr) + { + return Status::UnsupportedWrite; + } + + switch (attributePath.mAttributeId) + { + case CurrentEnergyBalance::Id: { + if (balanceSupported == false) + { + return Status::UnsupportedAttribute; + } + + uint8_t index = Encoding::Get8(value); + size_t arraySize = delegate->GetNumEnergyBalances(endpoint); + if (index >= arraySize) + { + return Status::ConstraintError; + } + + return Status::Success; + } + + case CurrentLowPowerModeSensitivity::Id: { + if (lowPowerSupported == false) + { + return Status::UnsupportedAttribute; + } + + uint8_t index = Encoding::Get8(value); + size_t arraySize = delegate->GetNumLowPowerModeSensitivities(endpoint); + if (index >= arraySize) + { + return Status::ConstraintError; + } + + return Status::Success; + } + default: + return Status::Success; + } +} + +void MatterEnergyPreferencePluginServerInitCallback() +{ + registerAttributeAccessOverride(&gEnergyPrefAttrAccess); +} diff --git a/src/app/clusters/energy-preference-server/energy-preference-server.h b/src/app/clusters/energy-preference-server/energy-preference-server.h new file mode 100644 index 00000000000000..771057847e372a --- /dev/null +++ b/src/app/clusters/energy-preference-server/energy-preference-server.h @@ -0,0 +1,107 @@ +/** + * + * Copyright (c) 2024 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include + +#include +#include +#include +#include + +namespace chip::app::Clusters::EnergyPreference { + +struct Delegate +{ + // Note: This delegate does not handle the "Current Active" indexes attributes storage. + // eg: Current Energy Balance and Current Low Power Mode Sensitivity. These can be handled using + // ember built in storage, or via the external callbacks as desired by the implementer. + + virtual ~Delegate() {} + + /** + * Get an Energy Balance. + * + * The delegate method is called by the cluster to fill out the + * values for the list in EnergyBalances attribute. Storage for + * both aOutStep and aOutLabel is provided by the caller. + * + * @param aEndpoint The endpoint to query. + * @param aIndex The index of the balance, with 0 representing the first one. + * @param aOutStep The Step value from BalanceStruct + * + * @param aOutLabel The Label value from BalanceStruct. Storage is + * provided by the caller, and is large enough to accomodate the + * longest label (64 chars), on successful return the size of the span must be + * adjusted to reflect the length of the value, or ClearValue() called on the Optional to indicate there is no label. + * + * @return CHIP_ERROR_NOT_FOUND if the index is out of range. + */ + virtual CHIP_ERROR GetEnergyBalanceAtIndex(chip::EndpointId aEndpoint, size_t aIndex, chip::Percent & aOutStep, + chip::Optional & aOutLabel) = 0; + + /** + * Get an Energy Priority. + * @param aEndpoint The endpoint to query. + * @param aIndex The index of the priority, with 0 representing the first one. + * @param aOutPriority The EnergyPriorityEnum to copy the data into. + * @return CHIP_ERROR_NOT_FOUND if the index is out of range. + */ + virtual CHIP_ERROR GetEnergyPriorityAtIndex(chip::EndpointId aEndpoint, size_t aIndex, + chip::app::Clusters::EnergyPreference::EnergyPriorityEnum & aOutPriority) = 0; + + /** + * Get a Power Sensitity Balance Struct data at the specified index. + * + * The delegate method is called by the cluster to fill out the + * values for the list in LowPowerSensitivities attribute. Storage for + * both aOutStep and aOutLabel is provided by the caller. + * + * @param aEndpoint The endpoint to query. + * @param aIndex The index of the priority, with 0 representing the first one. + * @param aOutStep The Step value from BalanceStruct + * + * @param aOutLabel The Label value from BalanceStruct. Storage is + * provided by the caller, and is large enough to accomodate the + * longest label (64 chars), on successful return the size of the span must be + * adjusted to reflect the length of the value, or ClearValue() called on the Optional to indicate there is no label. + * + * @return CHIP_ERROR_NOT_FOUND if the index is out of range. + */ + virtual CHIP_ERROR GetLowPowerModeSensitivityAtIndex(chip::EndpointId aEndpoint, size_t aIndex, chip::Percent & aOutStep, + chip::Optional & aOutLabel) = 0; + + /** + * Get the number of energy balances this endpoint has. + * @param aEndpoint The endpoint to query. + * @return the number of balance structs in the list. + */ + virtual size_t GetNumEnergyBalances(chip::EndpointId aEndpoint) = 0; + + /** + * Get the number of low power mode sensitivities this endpoint has. + * @param aEndpoint The endpoint to query. + * @return the number of balance structs in the list. + */ + virtual size_t GetNumLowPowerModeSensitivities(chip::EndpointId aEndpoint) = 0; +}; + +void SetDelegate(Delegate * aDelegate); +Delegate * GetDelegate(); + +} // namespace chip::app::Clusters::EnergyPreference diff --git a/src/app/common/templates/config-data.yaml b/src/app/common/templates/config-data.yaml index 20677184632c6c..875cdbcdbd1514 100644 --- a/src/app/common/templates/config-data.yaml +++ b/src/app/common/templates/config-data.yaml @@ -84,5 +84,6 @@ ClustersWithPreAttributeChangeFunctions: - Mode Select - Fan Control - Thermostat + - Energy Preference - Laundry Washer Controls - Laundry Dryer Controls diff --git a/src/app/zap-templates/zcl/data-model/chip/energy-preference-cluster.xml b/src/app/zap-templates/zcl/data-model/chip/energy-preference-cluster.xml index ceff9846978e63..32893bd82a68e9 100644 --- a/src/app/zap-templates/zcl/data-model/chip/energy-preference-cluster.xml +++ b/src/app/zap-templates/zcl/data-model/chip/energy-preference-cluster.xml @@ -22,6 +22,7 @@ limitations under the License. true This cluster provides an interface to specify preferences for how devices should consume energy. + EnergyBalances diff --git a/src/app/zap_cluster_list.json b/src/app/zap_cluster_list.json index 56adf0a1126f95..2edfb272ad23e1 100644 --- a/src/app/zap_cluster_list.json +++ b/src/app/zap_cluster_list.json @@ -192,7 +192,7 @@ "ETHERNET_NETWORK_DIAGNOSTICS_CLUSTER": [ "ethernet-network-diagnostics-server" ], - "ENERGY_PREFERENCE_CLUSTER": [""], + "ENERGY_PREFERENCE_CLUSTER": ["energy-preference-server"], "FAN_CONTROL_CLUSTER": ["fan-control-server"], "FAULT_INJECTION_CLUSTER": ["fault-injection-server"], "FIXED_LABEL_CLUSTER": ["fixed-label-server"], diff --git a/src/controller/data_model/controller-clusters.matter b/src/controller/data_model/controller-clusters.matter index 89864630b8e85e..235366f4206e78 100644 --- a/src/controller/data_model/controller-clusters.matter +++ b/src/controller/data_model/controller-clusters.matter @@ -4978,7 +4978,7 @@ provisional cluster EnergyEvse = 153 { /** This cluster provides an interface to specify preferences for how devices should consume energy. */ provisional cluster EnergyPreference = 155 { - revision 1; // NOTE: Default/not specifically set + revision 1; enum EnergyPriorityEnum : enum8 { kComfort = 0; From 0c3f012c71cf3466ad5fe6d236b47e2bce914c7b Mon Sep 17 00:00:00 2001 From: Karsten Sperling <113487422+ksperling-apple@users.noreply.github.com> Date: Thu, 22 Feb 2024 01:58:17 +1300 Subject: [PATCH 042/385] Disable WiFi PDC support by default for 1.3 (#32234) Fixes #32169 --- src/platform/Darwin/CHIPDevicePlatformConfig.h | 1 - src/platform/Linux/CHIPDevicePlatformConfig.h | 1 - src/platform/Linux/NetworkCommissioningWiFiDriver.cpp | 2 +- 3 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/platform/Darwin/CHIPDevicePlatformConfig.h b/src/platform/Darwin/CHIPDevicePlatformConfig.h index 15fdaa476e3645..7a5140494c22dd 100644 --- a/src/platform/Darwin/CHIPDevicePlatformConfig.h +++ b/src/platform/Darwin/CHIPDevicePlatformConfig.h @@ -25,7 +25,6 @@ // ==================== Platform Adaptations ==================== -#define CHIP_DEVICE_CONFIG_ENABLE_WIFI_PDC 1 #define CHIP_DEVICE_CONFIG_ENABLE_WIFI_STATION 0 #define CHIP_DEVICE_CONFIG_ENABLE_WIFI_AP 0 diff --git a/src/platform/Linux/CHIPDevicePlatformConfig.h b/src/platform/Linux/CHIPDevicePlatformConfig.h index 70ed39d62899d5..530e2716308842 100644 --- a/src/platform/Linux/CHIPDevicePlatformConfig.h +++ b/src/platform/Linux/CHIPDevicePlatformConfig.h @@ -26,7 +26,6 @@ // ==================== Platform Adaptations ==================== #if CHIP_DEVICE_CONFIG_ENABLE_WIFI -#define CHIP_DEVICE_CONFIG_ENABLE_WIFI_PDC 1 #define CHIP_DEVICE_CONFIG_ENABLE_WIFI_STATION 1 #define CHIP_DEVICE_CONFIG_ENABLE_WIFI_AP 0 #else diff --git a/src/platform/Linux/NetworkCommissioningWiFiDriver.cpp b/src/platform/Linux/NetworkCommissioningWiFiDriver.cpp index 4b5b3c0b6b5e7d..16e4b7f0d7fbde 100644 --- a/src/platform/Linux/NetworkCommissioningWiFiDriver.cpp +++ b/src/platform/Linux/NetworkCommissioningWiFiDriver.cpp @@ -44,12 +44,12 @@ constexpr char kWiFiCredentialsKeyName[] = "wifi-pass"; constexpr char kWifiNetworkIdentityKeyName[] = "wifi-ni"; constexpr char kWifiClientIdentityKeyName[] = "wifi-ci"; constexpr char kWifiClientIdentityKeypairKeyName[] = "wifi-cik"; +#endif // CHIP_DEVICE_CONFIG_ENABLE_WIFI_PDC inline CHIP_ERROR IgnoreNotFound(CHIP_ERROR err) { return (err == CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND) ? CHIP_NO_ERROR : err; } -#endif // CHIP_DEVICE_CONFIG_ENABLE_WIFI_PDC } // namespace // NOTE: For WiFiDriver, we uses two network configs, one is mSavedNetwork, and another is mStagingNetwork, during init, it will From a64773a912e09f65cfe00f527dd8d85123c69c83 Mon Sep 17 00:00:00 2001 From: Matthew Swartwout Date: Wed, 21 Feb 2024 05:52:25 -0800 Subject: [PATCH 043/385] Initialize scalar members in TLVReader (#32129) * Initialize scalar members in TLVReader The documented return values for multiple TLVReader functions do match the actual return value for the uninitialize case. Explicitly initialize members with null/0 values to match the documentation. * Restyled by clang-format * Don't inline constructor * Restyled by clang-format --------- Co-authored-by: Restyled.io --- src/lib/core/TLVReader.cpp | 6 ++++++ src/lib/core/TLVReader.h | 2 ++ src/lib/core/tests/TestTLV.cpp | 23 +++++++++++++++++++++++ 3 files changed, 31 insertions(+) diff --git a/src/lib/core/TLVReader.cpp b/src/lib/core/TLVReader.cpp index abef9af1636ca5..8368b9fb0fac04 100644 --- a/src/lib/core/TLVReader.cpp +++ b/src/lib/core/TLVReader.cpp @@ -49,6 +49,12 @@ using namespace chip::Encoding; static const uint8_t sTagSizes[] = { 0, 1, 2, 4, 2, 4, 6, 8 }; +TLVReader::TLVReader() : + ImplicitProfileId(kProfileIdNotSpecified), AppData(nullptr), mElemLenOrVal(0), mBackingStore(nullptr), mReadPoint(nullptr), + mBufEnd(nullptr), mLenRead(0), mMaxLen(0), mContainerType(kTLVType_NotSpecified), mControlByte(kTLVControlByte_NotSpecified), + mContainerOpen(false) +{} + void TLVReader::Init(const uint8_t * data, size_t dataLen) { // TODO: Maybe we can just make mMaxLen and mLenRead size_t instead? diff --git a/src/lib/core/TLVReader.h b/src/lib/core/TLVReader.h index bfb6b47f14d3f4..e86812cc2dc16b 100644 --- a/src/lib/core/TLVReader.h +++ b/src/lib/core/TLVReader.h @@ -86,6 +86,8 @@ class DLL_EXPORT TLVReader friend class TLVUpdater; public: + TLVReader(); + /** * Initializes a TLVReader object from another TLVReader object. * diff --git a/src/lib/core/tests/TestTLV.cpp b/src/lib/core/tests/TestTLV.cpp index fce0a5d17ae484..f71bce13fbd70b 100644 --- a/src/lib/core/tests/TestTLV.cpp +++ b/src/lib/core/tests/TestTLV.cpp @@ -3832,6 +3832,27 @@ void TestTLVReader_SkipOverContainer(nlTestSuite * inSuite) ForEachElement(inSuite, reader, nullptr, TestTLVReader_SkipOverContainer_ProcessElement); } +/** + * Tests using an uninitialized TLVReader. + */ +void TestTLVReaderUninitialized(nlTestSuite * inSuite) +{ + TLVReader reader; + + NL_TEST_ASSERT(inSuite, reader.GetType() == kTLVType_NotSpecified); + NL_TEST_ASSERT(inSuite, reader.GetLength() == 0); + NL_TEST_ASSERT(inSuite, reader.GetControlByte() == kTLVControlByte_NotSpecified); + NL_TEST_ASSERT(inSuite, reader.GetContainerType() == kTLVType_NotSpecified); + NL_TEST_ASSERT(inSuite, reader.GetLengthRead() == 0); + NL_TEST_ASSERT(inSuite, reader.GetRemainingLength() == 0); + NL_TEST_ASSERT(inSuite, reader.GetTotalLength() == 0); + NL_TEST_ASSERT(inSuite, reader.GetBackingStore() == nullptr); + NL_TEST_ASSERT(inSuite, reader.IsElementDouble() == false); + NL_TEST_ASSERT(inSuite, reader.GetReadPoint() == nullptr); + NL_TEST_ASSERT(inSuite, reader.ImplicitProfileId == kProfileIdNotSpecified); + NL_TEST_ASSERT(inSuite, reader.AppData == nullptr); +} + /** * Test CHIP TLV Reader */ @@ -3852,6 +3873,8 @@ void CheckTLVReader(nlTestSuite * inSuite, void * inContext) TestTLVReader_NextOverContainer(inSuite); TestTLVReader_SkipOverContainer(inSuite); + + TestTLVReaderUninitialized(inSuite); } /** From e1a4a01ca6c5715153381449b6d73bece6995756 Mon Sep 17 00:00:00 2001 From: Arkadiusz Bokowy Date: Wed, 21 Feb 2024 17:35:34 +0100 Subject: [PATCH 044/385] Extend GAutoPtr to conventionally get receiver (#32115) * Extend GAutoPtr to conventionally get receiver * Replace explicit use of MakeUniquePointerReceiver with GetReceiver() * Replace g_clear_error with .reset() * Add missing GLibTypeDeleter.h dependency to Tizen platform --- src/platform/GLibTypeDeleter.h | 12 +++- .../Linux/ConnectivityManagerImpl.cpp | 55 ++++++++----------- src/platform/Linux/ThreadStackManagerImpl.cpp | 28 ++++------ src/platform/Linux/bluez/AdapterIterator.cpp | 2 +- .../Linux/bluez/BluezAdvertisement.cpp | 8 +-- src/platform/Linux/bluez/BluezConnection.cpp | 10 ++-- src/platform/Linux/bluez/BluezEndpoint.cpp | 15 +++-- .../Linux/bluez/ChipDeviceScanner.cpp | 15 ++--- src/platform/Tizen/BLEManagerImpl.cpp | 12 ++-- src/platform/Tizen/BUILD.gn | 1 + src/platform/Tizen/DnssdImpl.cpp | 10 ++-- src/platform/Tizen/WiFiManager.cpp | 10 ++-- 12 files changed, 84 insertions(+), 94 deletions(-) diff --git a/src/platform/GLibTypeDeleter.h b/src/platform/GLibTypeDeleter.h index e6d9bfd0d2c1ed..f217d559e9cc66 100644 --- a/src/platform/GLibTypeDeleter.h +++ b/src/platform/GLibTypeDeleter.h @@ -29,10 +29,10 @@ class UniquePointerReceiver { public: UniquePointerReceiver(std::unique_ptr & target) : mTarget(target) {} - ~UniquePointerReceiver() { mTarget.reset(mValue); } T *& Get() { return mValue; } + T ** operator&() { return &mValue; } private: std::unique_ptr & mTarget; @@ -151,6 +151,14 @@ struct GAutoPtrDeleter }; template -using GAutoPtr = std::unique_ptr::deleter>; +class GAutoPtr : public std::unique_ptr::deleter> +{ +public: + using deleter = typename GAutoPtrDeleter::deleter; + using std::unique_ptr::unique_ptr; + + // Convenience method to get a UniquePointerReceiver for this object. + UniquePointerReceiver GetReceiver() { return MakeUniquePointerReceiver(*this); } +}; } // namespace chip diff --git a/src/platform/Linux/ConnectivityManagerImpl.cpp b/src/platform/Linux/ConnectivityManagerImpl.cpp index eef7ce883f0042..2a57a99d507976 100644 --- a/src/platform/Linux/ConnectivityManagerImpl.cpp +++ b/src/platform/Linux/ConnectivityManagerImpl.cpp @@ -266,8 +266,7 @@ void ConnectivityManagerImpl::_ClearWiFiStationProvision() if (mWiFiStationMode != kWiFiStationMode_ApplicationControlled) { GAutoPtr err; - wpa_fi_w1_wpa_supplicant1_interface_call_remove_all_networks_sync(mWpaSupplicant.iface, nullptr, - &MakeUniquePointerReceiver(err).Get()); + wpa_fi_w1_wpa_supplicant1_interface_call_remove_all_networks_sync(mWpaSupplicant.iface, nullptr, &err.GetReceiver()); if (err != nullptr) { @@ -388,7 +387,7 @@ void ConnectivityManagerImpl::_OnWpaPropertiesChanged(WpaFiW1Wpa_supplicant1Inte WiFiDiagnosticsDelegate * delegate = GetDiagnosticDataProvider().GetWiFiDiagnosticsDelegate(); - g_variant_get(changedProperties, "a{sv}", &MakeUniquePointerReceiver(iter).Get()); + g_variant_get(changedProperties, "a{sv}", &iter.GetReceiver()); while (g_variant_iter_loop(iter.get(), "{&sv}", &key, &value)) { @@ -497,8 +496,7 @@ void ConnectivityManagerImpl::_OnWpaInterfaceProxyReady(GObject * sourceObject, std::lock_guard lock(mWpaSupplicantMutex); - WpaFiW1Wpa_supplicant1Interface * iface = - wpa_fi_w1_wpa_supplicant1_interface_proxy_new_for_bus_finish(res, &MakeUniquePointerReceiver(err).Get()); + WpaFiW1Wpa_supplicant1Interface * iface = wpa_fi_w1_wpa_supplicant1_interface_proxy_new_for_bus_finish(res, &err.GetReceiver()); if (mWpaSupplicant.iface) { @@ -552,8 +550,7 @@ void ConnectivityManagerImpl::_OnWpaBssProxyReady(GObject * sourceObject, GAsync std::lock_guard lock(mWpaSupplicantMutex); - WpaFiW1Wpa_supplicant1BSS * bss = - wpa_fi_w1_wpa_supplicant1_bss_proxy_new_for_bus_finish(res, &MakeUniquePointerReceiver(err).Get()); + WpaFiW1Wpa_supplicant1BSS * bss = wpa_fi_w1_wpa_supplicant1_bss_proxy_new_for_bus_finish(res, &err.GetReceiver()); if (mWpaSupplicant.bss) { @@ -584,7 +581,7 @@ void ConnectivityManagerImpl::_OnWpaInterfaceReady(GObject * sourceObject, GAsyn std::lock_guard lock(mWpaSupplicantMutex); gboolean result = wpa_fi_w1_wpa_supplicant1_call_get_interface_finish(mWpaSupplicant.proxy, &mWpaSupplicant.interfacePath, res, - &MakeUniquePointerReceiver(err).Get()); + &err.GetReceiver()); if (result) { mWpaSupplicant.state = GDBusWpaSupplicant::WPA_GOT_INTERFACE_PATH; @@ -622,7 +619,7 @@ void ConnectivityManagerImpl::_OnWpaInterfaceReady(GObject * sourceObject, GAsyn args = g_variant_builder_end(&builder); result = wpa_fi_w1_wpa_supplicant1_call_create_interface_sync(mWpaSupplicant.proxy, args, &mWpaSupplicant.interfacePath, - nullptr, &MakeUniquePointerReceiver(error).Get()); + nullptr, &error.GetReceiver()); if (result) { @@ -747,7 +744,7 @@ void ConnectivityManagerImpl::_OnWpaProxyReady(GObject * sourceObject, GAsyncRes std::lock_guard lock(mWpaSupplicantMutex); - mWpaSupplicant.proxy = wpa_fi_w1_wpa_supplicant1_proxy_new_for_bus_finish(res, &MakeUniquePointerReceiver(err).Get()); + mWpaSupplicant.proxy = wpa_fi_w1_wpa_supplicant1_proxy_new_for_bus_finish(res, &err.GetReceiver()); if (mWpaSupplicant.proxy != nullptr && err.get() == nullptr) { mWpaSupplicant.state = GDBusWpaSupplicant::WPA_CONNECTED; @@ -898,7 +895,7 @@ void ConnectivityManagerImpl::DriveAPState() GAutoPtr error(nullptr); gboolean result = wpa_fi_w1_wpa_supplicant1_interface_call_remove_network_sync( - mWpaSupplicant.iface, mWpaSupplicant.networkPath, nullptr, &MakeUniquePointerReceiver(error).Get()); + mWpaSupplicant.iface, mWpaSupplicant.networkPath, nullptr, &error.GetReceiver()); if (result) { @@ -963,7 +960,7 @@ CHIP_ERROR ConnectivityManagerImpl::ConfigureWiFiAP() args = g_variant_builder_end(&builder); gboolean result = wpa_fi_w1_wpa_supplicant1_interface_call_add_network_sync( - mWpaSupplicant.iface, args, &mWpaSupplicant.networkPath, nullptr, &MakeUniquePointerReceiver(err).Get()); + mWpaSupplicant.iface, args, &mWpaSupplicant.networkPath, nullptr, &err.GetReceiver()); if (result) { @@ -972,7 +969,7 @@ CHIP_ERROR ConnectivityManagerImpl::ConfigureWiFiAP() ChipLogProgress(DeviceLayer, "wpa_supplicant: added network: SSID: %s: %s", ssid, mWpaSupplicant.networkPath); result = wpa_fi_w1_wpa_supplicant1_interface_call_select_network_sync(mWpaSupplicant.iface, mWpaSupplicant.networkPath, - nullptr, &MakeUniquePointerReceiver(error).Get()); + nullptr, &error.GetReceiver()); if (result) { ChipLogProgress(DeviceLayer, "wpa_supplicant: succeeded to start softAP: SSID: %s", ssid); @@ -1033,7 +1030,7 @@ ConnectivityManagerImpl::_ConnectWiFiNetworkAsync(GVariant * args, GAutoPtr error; result = wpa_fi_w1_wpa_supplicant1_interface_call_remove_network_sync(mWpaSupplicant.iface, networkPath, nullptr, - &MakeUniquePointerReceiver(error).Get()); + &error.GetReceiver()); if (result) { @@ -1055,7 +1052,7 @@ ConnectivityManagerImpl::_ConnectWiFiNetworkAsync(GVariant * args, } result = wpa_fi_w1_wpa_supplicant1_interface_call_add_network_sync(mWpaSupplicant.iface, args, &mWpaSupplicant.networkPath, - nullptr, &MakeUniquePointerReceiver(err).Get()); + nullptr, &err.GetReceiver()); if (result) { @@ -1127,7 +1124,7 @@ static CHIP_ERROR AddOrReplaceBlob(WpaFiW1Wpa_supplicant1Interface * iface, cons const char * name = (strncmp(nameOrRef, refPrefix.data(), refPrefix.size()) == 0) ? nameOrRef + refPrefix.size() : nameOrRef; GAutoPtr err; - if (!wpa_fi_w1_wpa_supplicant1_interface_call_remove_blob_sync(iface, name, nullptr, &MakeUniquePointerReceiver(err).Get())) + if (!wpa_fi_w1_wpa_supplicant1_interface_call_remove_blob_sync(iface, name, nullptr, &err.GetReceiver())) { GAutoPtr remoteError(g_dbus_error_get_remote_error(err.get())); if (!(remoteError && strcmp(remoteError.get(), kWpaSupplicantBlobUnknown) == 0)) @@ -1138,8 +1135,7 @@ static CHIP_ERROR AddOrReplaceBlob(WpaFiW1Wpa_supplicant1Interface * iface, cons err.reset(); } if (!wpa_fi_w1_wpa_supplicant1_interface_call_add_blob_sync( - iface, name, g_variant_new_fixed_array(G_VARIANT_TYPE_BYTE, data.data(), data.size(), 1), nullptr, - &MakeUniquePointerReceiver(err).Get())) + iface, name, g_variant_new_fixed_array(G_VARIANT_TYPE_BYTE, data.data(), data.size(), 1), nullptr, &err.GetReceiver())) { ChipLogError(DeviceLayer, "wpa_supplicant: failed to add blob: %s", err ? err->message : "unknown error"); return CHIP_ERROR_INTERNAL; @@ -1239,8 +1235,8 @@ void ConnectivityManagerImpl::_ConnectWiFiNetworkAsyncCallback(GObject * sourceO std::lock_guard lock(mWpaSupplicantMutex); { - gboolean result = wpa_fi_w1_wpa_supplicant1_interface_call_select_network_finish(mWpaSupplicant.iface, res, - &MakeUniquePointerReceiver(err).Get()); + gboolean result = + wpa_fi_w1_wpa_supplicant1_interface_call_select_network_finish(mWpaSupplicant.iface, res, &err.GetReceiver()); if (!result) { ChipLogError(DeviceLayer, "Failed to perform connect network: %s", err == nullptr ? "unknown error" : err->message); @@ -1257,8 +1253,7 @@ void ConnectivityManagerImpl::_ConnectWiFiNetworkAsyncCallback(GObject * sourceO return; } - result = wpa_fi_w1_wpa_supplicant1_interface_call_save_config_sync(mWpaSupplicant.iface, nullptr, - &MakeUniquePointerReceiver(err).Get()); + result = wpa_fi_w1_wpa_supplicant1_interface_call_save_config_sync(mWpaSupplicant.iface, nullptr, &err.GetReceiver()); if (result) { ChipLogProgress(DeviceLayer, "wpa_supplicant: save config succeeded!"); @@ -1335,8 +1330,7 @@ CHIP_ERROR ConnectivityManagerImpl::CommitConfig() ChipLogProgress(DeviceLayer, "wpa_supplicant: save config"); - result = wpa_fi_w1_wpa_supplicant1_interface_call_save_config_sync(mWpaSupplicant.iface, nullptr, - &MakeUniquePointerReceiver(err).Get()); + result = wpa_fi_w1_wpa_supplicant1_interface_call_save_config_sync(mWpaSupplicant.iface, nullptr, &err.GetReceiver()); if (!result) { @@ -1486,8 +1480,7 @@ CHIP_ERROR ConnectivityManagerImpl::GetConfiguredNetwork(NetworkCommissioning::N } GAutoPtr networkInfo(wpa_fi_w1_wpa_supplicant1_network_proxy_new_for_bus_sync( - G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE, kWpaSupplicantServiceName, networkPath, nullptr, - &MakeUniquePointerReceiver(err).Get())); + G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE, kWpaSupplicantServiceName, networkPath, nullptr, &err.GetReceiver())); if (networkInfo == nullptr) { return CHIP_ERROR_INTERNAL; @@ -1518,7 +1511,7 @@ CHIP_ERROR ConnectivityManagerImpl::StopAutoScan() ChipLogDetail(DeviceLayer, "wpa_supplicant: disabling auto scan"); result = wpa_fi_w1_wpa_supplicant1_interface_call_auto_scan_sync( - mWpaSupplicant.iface, "" /* empty string means disabling auto scan */, nullptr, &MakeUniquePointerReceiver(err).Get()); + mWpaSupplicant.iface, "" /* empty string means disabling auto scan */, nullptr, &err.GetReceiver()); if (!result) { ChipLogError(DeviceLayer, "wpa_supplicant: Failed to stop auto network scan: %s", err ? err->message : "unknown"); @@ -1548,8 +1541,7 @@ CHIP_ERROR ConnectivityManagerImpl::StartWiFiScan(ByteSpan ssid, WiFiDriver::Sca g_variant_builder_add(&builder, "{sv}", "Type", g_variant_new_string("active")); args = g_variant_builder_end(&builder); - result = wpa_fi_w1_wpa_supplicant1_interface_call_scan_sync(mWpaSupplicant.iface, args, nullptr, - &MakeUniquePointerReceiver(err).Get()); + result = wpa_fi_w1_wpa_supplicant1_interface_call_scan_sync(mWpaSupplicant.iface, args, nullptr, &err.GetReceiver()); if (result) { @@ -1676,9 +1668,8 @@ bool ConnectivityManagerImpl::_GetBssInfo(const gchar * bssPath, NetworkCommissi // with the proxy object. GAutoPtr err; - GAutoPtr bss( - wpa_fi_w1_wpa_supplicant1_bss_proxy_new_for_bus_sync(G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE, kWpaSupplicantServiceName, - bssPath, nullptr, &MakeUniquePointerReceiver(err).Get())); + GAutoPtr bss(wpa_fi_w1_wpa_supplicant1_bss_proxy_new_for_bus_sync( + G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE, kWpaSupplicantServiceName, bssPath, nullptr, &err.GetReceiver())); if (bss == nullptr) { diff --git a/src/platform/Linux/ThreadStackManagerImpl.cpp b/src/platform/Linux/ThreadStackManagerImpl.cpp index a8f6c23f1e5a24..5fd865df5485ad 100644 --- a/src/platform/Linux/ThreadStackManagerImpl.cpp +++ b/src/platform/Linux/ThreadStackManagerImpl.cpp @@ -85,7 +85,7 @@ CHIP_ERROR ThreadStackManagerImpl::GLibMatterContextInitThreadStack(ThreadStackM GAutoPtr err; self->mProxy.reset(openthread_io_openthread_border_router_proxy_new_for_bus_sync( G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE, kDBusOpenThreadService, kDBusOpenThreadObjectPath, nullptr, - &MakeUniquePointerReceiver(err).Get())); + &err.GetReceiver())); VerifyOrReturnError( self->mProxy != nullptr, CHIP_ERROR_INTERNAL, ChipLogError(DeviceLayer, "openthread: failed to create openthread dbus proxy %s", err ? err->message : "unknown error")); @@ -123,7 +123,7 @@ void ThreadStackManagerImpl::OnDbusPropertiesChanged(OpenthreadIoOpenthreadBorde GVariant * value; GAutoPtr iter; - g_variant_get(changed_properties, "a{sv}", &MakeUniquePointerReceiver(iter).Get()); + g_variant_get(changed_properties, "a{sv}", &iter.GetReceiver()); if (!iter) return; while (g_variant_iter_loop(iter.get(), "{&sv}", &key, &value)) @@ -193,7 +193,7 @@ bool ThreadStackManagerImpl::_HaveRouteToAddress(const Inet::IPAddress & destAdd if (g_variant_n_children(routes.get()) > 0) { GAutoPtr iter; - g_variant_get(routes.get(), "av", &MakeUniquePointerReceiver(iter).Get()); + g_variant_get(routes.get(), "av", &iter.GetReceiver()); if (!iter) return false; @@ -207,14 +207,13 @@ bool ThreadStackManagerImpl::_HaveRouteToAddress(const Inet::IPAddress & destAdd guchar preference; gboolean stable; gboolean nextHopIsThisDevice; - g_variant_get(route, "(&vqybb)", &MakeUniquePointerReceiver(prefix).Get(), &rloc16, &preference, &stable, - &nextHopIsThisDevice); + g_variant_get(route, "(&vqybb)", &prefix.GetReceiver(), &rloc16, &preference, &stable, &nextHopIsThisDevice); if (!prefix) continue; GAutoPtr address; guchar prefixLength; - g_variant_get(prefix.get(), "(&vy)", &MakeUniquePointerReceiver(address).Get(), &prefixLength); + g_variant_get(prefix.get(), "(&vy)", &address.GetReceiver(), &prefixLength); if (!address) continue; @@ -273,8 +272,7 @@ CHIP_ERROR ThreadStackManagerImpl::_GetThreadProvision(Thread::OperationalDatase GAutoPtr err; GAutoPtr response(g_dbus_proxy_call_sync(G_DBUS_PROXY(mProxy.get()), "org.freedesktop.DBus.Properties.Get", g_variant_new("(ss)", "io.openthread.BorderRouter", "ActiveDatasetTlvs"), - G_DBUS_CALL_FLAGS_NONE, -1, nullptr, - &MakeUniquePointerReceiver(err).Get())); + G_DBUS_CALL_FLAGS_NONE, -1, nullptr, &err.GetReceiver())); if (err) { @@ -330,7 +328,7 @@ bool ThreadStackManagerImpl::_IsThreadEnabled() GAutoPtr err; GAutoPtr response(g_dbus_proxy_call_sync(G_DBUS_PROXY(mProxy.get()), "org.freedesktop.DBus.Properties.Get", g_variant_new("(ss)", "io.openthread.BorderRouter", "DeviceRole"), - G_DBUS_CALL_FLAGS_NONE, -1, nullptr, &MakeUniquePointerReceiver(err).Get())); + G_DBUS_CALL_FLAGS_NONE, -1, nullptr, &err.GetReceiver())); if (err) { @@ -390,8 +388,7 @@ CHIP_ERROR ThreadStackManagerImpl::_SetThreadEnabled(bool val) else { GAutoPtr err; - gboolean result = - openthread_io_openthread_border_router_call_reset_sync(mProxy.get(), nullptr, &MakeUniquePointerReceiver(err).Get()); + gboolean result = openthread_io_openthread_border_router_call_reset_sync(mProxy.get(), nullptr, &err.GetReceiver()); if (err) { ChipLogError(DeviceLayer, "openthread: _SetThreadEnabled calling %s failed: %s", "Reset", err->message); @@ -413,8 +410,7 @@ void ThreadStackManagerImpl::_OnThreadBrAttachFinished(GObject * source_object, GAutoPtr attachRes; GAutoPtr err; { - gboolean result = openthread_io_openthread_border_router_call_attach_finish(this_->mProxy.get(), res, - &MakeUniquePointerReceiver(err).Get()); + gboolean result = openthread_io_openthread_border_router_call_attach_finish(this_->mProxy.get(), res, &err.GetReceiver()); if (!result) { ChipLogError(DeviceLayer, "Failed to perform finish Thread network scan: %s", @@ -612,8 +608,8 @@ void ThreadStackManagerImpl::_OnNetworkScanFinished(GAsyncResult * res) GAutoPtr scan_result; GAutoPtr err; { - gboolean result = openthread_io_openthread_border_router_call_scan_finish( - mProxy.get(), &MakeUniquePointerReceiver(scan_result).Get(), res, &MakeUniquePointerReceiver(err).Get()); + gboolean result = openthread_io_openthread_border_router_call_scan_finish(mProxy.get(), &scan_result.GetReceiver(), res, + &err.GetReceiver()); if (!result) { ChipLogError(DeviceLayer, "Failed to perform finish Thread network scan: %s", @@ -635,7 +631,7 @@ void ThreadStackManagerImpl::_OnNetworkScanFinished(GAsyncResult * res) if (g_variant_n_children(scan_result.get()) > 0) { GAutoPtr iter; - g_variant_get(scan_result.get(), "a(tstayqqynyybb)", &MakeUniquePointerReceiver(iter).Get()); + g_variant_get(scan_result.get(), "a(tstayqqynyybb)", &iter.GetReceiver()); if (!iter) { delete scanResult; diff --git a/src/platform/Linux/bluez/AdapterIterator.cpp b/src/platform/Linux/bluez/AdapterIterator.cpp index 3197be4e73e175..e69c473f52bbfe 100644 --- a/src/platform/Linux/bluez/AdapterIterator.cpp +++ b/src/platform/Linux/bluez/AdapterIterator.cpp @@ -57,7 +57,7 @@ CHIP_ERROR AdapterIterator::Initialize(AdapterIterator * self) self->mManager = g_dbus_object_manager_client_new_for_bus_sync( G_BUS_TYPE_SYSTEM, G_DBUS_OBJECT_MANAGER_CLIENT_FLAGS_NONE, BLUEZ_INTERFACE, "/", bluez_object_manager_client_get_proxy_type, nullptr /* unused user data in the Proxy Type Func */, - nullptr /*destroy notify */, nullptr /* cancellable */, &MakeUniquePointerReceiver(error).Get()); + nullptr /* destroy notify */, nullptr /* cancellable */, &error.GetReceiver()); VerifyOrExit(self->mManager != nullptr, ChipLogError(DeviceLayer, "Failed to get DBUS object manager for listing adapters."); err = CHIP_ERROR_INTERNAL); diff --git a/src/platform/Linux/bluez/BluezAdvertisement.cpp b/src/platform/Linux/bluez/BluezAdvertisement.cpp index 1b95aae41a4f11..196529816b59ab 100644 --- a/src/platform/Linux/bluez/BluezAdvertisement.cpp +++ b/src/platform/Linux/bluez/BluezAdvertisement.cpp @@ -118,7 +118,7 @@ CHIP_ERROR BluezAdvertisement::Init(const BluezEndpoint & aEndpoint, const char mpRoot = reinterpret_cast(g_object_ref(aEndpoint.GetGattApplicationObjectManager())); mpAdapter = reinterpret_cast(g_object_ref(aEndpoint.GetAdapter())); - g_object_get(G_OBJECT(mpRoot), "object-path", &MakeUniquePointerReceiver(rootPath).Get(), nullptr); + g_object_get(G_OBJECT(mpRoot), "object-path", &rootPath.GetReceiver(), nullptr); mpAdvPath = g_strdup_printf("%s/advertising", rootPath.get()); mpAdvUUID = g_strdup(aAdvUUID); @@ -241,8 +241,7 @@ void BluezAdvertisement::StartDone(GObject * aObject, GAsyncResult * aResult) GAutoPtr error; gboolean success = FALSE; - success = - bluez_leadvertising_manager1_call_register_advertisement_finish(advMgr, aResult, &MakeUniquePointerReceiver(error).Get()); + success = bluez_leadvertising_manager1_call_register_advertisement_finish(advMgr, aResult, &error.GetReceiver()); if (success == FALSE) { g_dbus_object_manager_server_unexport(mpRoot, mpAdvPath); @@ -304,8 +303,7 @@ void BluezAdvertisement::StopDone(GObject * aObject, GAsyncResult * aResult) GAutoPtr error; gboolean success = FALSE; - success = - bluez_leadvertising_manager1_call_unregister_advertisement_finish(advMgr, aResult, &MakeUniquePointerReceiver(error).Get()); + success = bluez_leadvertising_manager1_call_unregister_advertisement_finish(advMgr, aResult, &error.GetReceiver()); if (success == FALSE) { diff --git a/src/platform/Linux/bluez/BluezConnection.cpp b/src/platform/Linux/bluez/BluezConnection.cpp index 39b5bb0bdb8ba6..d2d5745a4c37c2 100644 --- a/src/platform/Linux/bluez/BluezConnection.cpp +++ b/src/platform/Linux/bluez/BluezConnection.cpp @@ -180,7 +180,7 @@ CHIP_ERROR BluezConnection::BluezDisconnect(BluezConnection * conn) ChipLogDetail(DeviceLayer, "%s peer=%s", __func__, conn->GetPeerAddress()); - success = bluez_device1_call_disconnect_sync(conn->mpDevice, nullptr, &MakeUniquePointerReceiver(error).Get()); + success = bluez_device1_call_disconnect_sync(conn->mpDevice, nullptr, &error.GetReceiver()); VerifyOrExit(success == TRUE, ChipLogError(DeviceLayer, "FAIL: Disconnect: %s", error->message)); exit: @@ -284,7 +284,7 @@ CHIP_ERROR BluezConnection::SendIndicationImpl(ConnectionDataBundle * data) VerifyOrExit(len <= static_cast(std::numeric_limits::max()), ChipLogError(DeviceLayer, "FAIL: buffer too large in %s", __func__)); auto status = g_io_channel_write_chars(data->mConn.mC2Channel.mChannel.get(), buf, static_cast(len), &written, - &MakeUniquePointerReceiver(error).Get()); + &error.GetReceiver()); VerifyOrExit(status == G_IO_STATUS_NORMAL, ChipLogError(DeviceLayer, "FAIL: C2 Indicate: %s", error->message)); } else @@ -311,7 +311,7 @@ void BluezConnection::SendWriteRequestDone(GObject * aObject, GAsyncResult * aRe { BluezGattCharacteristic1 * c1 = BLUEZ_GATT_CHARACTERISTIC1(aObject); GAutoPtr error; - gboolean success = bluez_gatt_characteristic1_call_write_value_finish(c1, aResult, &MakeUniquePointerReceiver(error).Get()); + gboolean success = bluez_gatt_characteristic1_call_write_value_finish(c1, aResult, &error.GetReceiver()); VerifyOrReturn(success == TRUE, ChipLogError(DeviceLayer, "FAIL: SendWriteRequest : %s", error->message)); BLEManagerImpl::HandleWriteComplete(static_cast(apConnection)); @@ -360,7 +360,7 @@ void BluezConnection::SubscribeCharacteristicDone(GObject * aObject, GAsyncResul { BluezGattCharacteristic1 * c2 = BLUEZ_GATT_CHARACTERISTIC1(aObject); GAutoPtr error; - gboolean success = bluez_gatt_characteristic1_call_write_value_finish(c2, aResult, &MakeUniquePointerReceiver(error).Get()); + gboolean success = bluez_gatt_characteristic1_call_write_value_finish(c2, aResult, &error.GetReceiver()); VerifyOrReturn(success == TRUE, ChipLogError(DeviceLayer, "FAIL: SubscribeCharacteristic : %s", error->message)); @@ -392,7 +392,7 @@ void BluezConnection::UnsubscribeCharacteristicDone(GObject * aObject, GAsyncRes { BluezGattCharacteristic1 * c2 = BLUEZ_GATT_CHARACTERISTIC1(aObject); GAutoPtr error; - gboolean success = bluez_gatt_characteristic1_call_write_value_finish(c2, aResult, &MakeUniquePointerReceiver(error).Get()); + gboolean success = bluez_gatt_characteristic1_call_write_value_finish(c2, aResult, &error.GetReceiver()); VerifyOrReturn(success == TRUE, ChipLogError(DeviceLayer, "FAIL: UnsubscribeCharacteristic : %s", error->message)); diff --git a/src/platform/Linux/bluez/BluezEndpoint.cpp b/src/platform/Linux/bluez/BluezEndpoint.cpp index 3baca7d127f20a..e68b28b8f421a8 100644 --- a/src/platform/Linux/bluez/BluezEndpoint.cpp +++ b/src/platform/Linux/bluez/BluezEndpoint.cpp @@ -264,8 +264,7 @@ void BluezEndpoint::RegisterGattApplicationDone(GObject * aObject, GAsyncResult GAutoPtr error; BluezGattManager1 * gattMgr = BLUEZ_GATT_MANAGER1(aObject); - gboolean success = - bluez_gatt_manager1_call_register_application_finish(gattMgr, aResult, &MakeUniquePointerReceiver(error).Get()); + gboolean success = bluez_gatt_manager1_call_register_application_finish(gattMgr, aResult, &error.GetReceiver()); VerifyOrReturn(success == TRUE, { ChipLogError(DeviceLayer, "FAIL: RegisterApplication : %s", error->message); @@ -614,16 +613,16 @@ void BluezEndpoint::SetupGattServer(GDBusConnection * aConn) CHIP_ERROR BluezEndpoint::StartupEndpointBindings() { GAutoPtr err; - GAutoPtr conn(g_bus_get_sync(G_BUS_TYPE_SYSTEM, nullptr, &MakeUniquePointerReceiver(err).Get())); + GAutoPtr conn(g_bus_get_sync(G_BUS_TYPE_SYSTEM, nullptr, &err.GetReceiver())); VerifyOrReturnError(conn != nullptr, CHIP_ERROR_INTERNAL, ChipLogError(DeviceLayer, "FAIL: get bus sync in %s, error: %s", __func__, err->message)); SetupGattServer(conn.get()); - mpObjMgr = g_dbus_object_manager_client_new_sync( - conn.get(), G_DBUS_OBJECT_MANAGER_CLIENT_FLAGS_NONE, BLUEZ_INTERFACE, "/", bluez_object_manager_client_get_proxy_type, - nullptr /* unused user data in the Proxy Type Func */, nullptr /*destroy notify */, nullptr /* cancellable */, - &MakeUniquePointerReceiver(err).Get()); + mpObjMgr = g_dbus_object_manager_client_new_sync(conn.get(), G_DBUS_OBJECT_MANAGER_CLIENT_FLAGS_NONE, BLUEZ_INTERFACE, "/", + bluez_object_manager_client_get_proxy_type, + nullptr /* unused user data in the Proxy Type Func */, + nullptr /*destroy notify */, nullptr /* cancellable */, &err.GetReceiver()); VerifyOrReturnError(mpObjMgr != nullptr, CHIP_ERROR_INTERNAL, ChipLogError(DeviceLayer, "FAIL: Error getting object manager client: %s", err->message)); @@ -729,7 +728,7 @@ CHIP_ERROR BluezEndpoint::ConnectDeviceImpl(BluezDevice1 & aDevice) for (uint16_t i = 0; i < kMaxConnectRetries; i++) { GAutoPtr error; - if (bluez_device1_call_connect_sync(&aDevice, mConnectCancellable.get(), &MakeUniquePointerReceiver(error).Get())) + if (bluez_device1_call_connect_sync(&aDevice, mConnectCancellable.get(), &error.GetReceiver())) { ChipLogDetail(DeviceLayer, "ConnectDevice complete"); return CHIP_NO_ERROR; diff --git a/src/platform/Linux/bluez/ChipDeviceScanner.cpp b/src/platform/Linux/bluez/ChipDeviceScanner.cpp index 5d9cbf25c9028b..03b26aa08e3dc7 100644 --- a/src/platform/Linux/bluez/ChipDeviceScanner.cpp +++ b/src/platform/Linux/bluez/ChipDeviceScanner.cpp @@ -72,7 +72,7 @@ CHIP_ERROR ChipDeviceScanner::Init(BluezAdapter1 * adapter, ChipDeviceScannerDel self->mManager = g_dbus_object_manager_client_new_for_bus_sync( G_BUS_TYPE_SYSTEM, G_DBUS_OBJECT_MANAGER_CLIENT_FLAGS_NONE, BLUEZ_INTERFACE, "/", bluez_object_manager_client_get_proxy_type, nullptr /* unused user data in the Proxy Type Func */, - nullptr /* destroy notify */, nullptr /* cancellable */, &MakeUniquePointerReceiver(err).Get()); + nullptr /* destroy notify */, nullptr /* cancellable */, &err.GetReceiver()); VerifyOrReturnError(self->mManager != nullptr, CHIP_ERROR_INTERNAL, ChipLogError(Ble, "Failed to get D-Bus object manager for device scanning: %s", err->message)); return CHIP_NO_ERROR; @@ -205,8 +205,7 @@ CHIP_ERROR ChipDeviceScanner::MainLoopStopScan(ChipDeviceScanner * self) self->mInterfaceChangedSignal = 0; } - if (!bluez_adapter1_call_stop_discovery_sync(self->mAdapter, nullptr /* not cancellable */, - &MakeUniquePointerReceiver(error).Get())) + if (!bluez_adapter1_call_stop_discovery_sync(self->mAdapter, nullptr /* not cancellable */, &error.GetReceiver())) { ChipLogError(Ble, "Failed to stop discovery %s", error->message); return CHIP_ERROR_INTERNAL; @@ -268,7 +267,7 @@ void ChipDeviceScanner::RemoveDevice(BluezDevice1 & device) const auto devicePath = g_dbus_proxy_get_object_path(G_DBUS_PROXY(&device)); GAutoPtr error; - if (!bluez_adapter1_call_remove_device_sync(mAdapter, devicePath, nullptr, &MakeUniquePointerReceiver(error).Get())) + if (!bluez_adapter1_call_remove_device_sync(mAdapter, devicePath, nullptr, &error.GetReceiver())) { ChipLogDetail(Ble, "Failed to remove device %s: %s", StringOrNullMarker(devicePath), error->message); } @@ -303,17 +302,15 @@ CHIP_ERROR ChipDeviceScanner::MainLoopStartScan(ChipDeviceScanner * self) g_variant_builder_add(&filterBuilder, "{sv}", "Transport", g_variant_new_string("le")); GVariant * filter = g_variant_builder_end(&filterBuilder); - if (!bluez_adapter1_call_set_discovery_filter_sync(self->mAdapter, filter, self->mCancellable.get(), - &MakeUniquePointerReceiver(error).Get())) + if (!bluez_adapter1_call_set_discovery_filter_sync(self->mAdapter, filter, self->mCancellable.get(), &error.GetReceiver())) { // Not critical: ignore if fails ChipLogError(Ble, "Failed to set discovery filters: %s", error->message); - g_clear_error(&MakeUniquePointerReceiver(error).Get()); + error.reset(); } ChipLogProgress(Ble, "BLE initiating scan."); - if (!bluez_adapter1_call_start_discovery_sync(self->mAdapter, self->mCancellable.get(), - &MakeUniquePointerReceiver(error).Get())) + if (!bluez_adapter1_call_start_discovery_sync(self->mAdapter, self->mCancellable.get(), &error.GetReceiver())) { ChipLogError(Ble, "Failed to start discovery: %s", error->message); return CHIP_ERROR_INTERNAL; diff --git a/src/platform/Tizen/BLEManagerImpl.cpp b/src/platform/Tizen/BLEManagerImpl.cpp index 0a1a9468d00b06..4d4c3e77316fc7 100644 --- a/src/platform/Tizen/BLEManagerImpl.cpp +++ b/src/platform/Tizen/BLEManagerImpl.cpp @@ -208,11 +208,11 @@ void BLEManagerImpl::ReadValueRequestedCb(const char * remoteAddress, int reques GAutoPtr uuid; GAutoPtr value; - VerifyOrReturn(__GetAttInfo(gattHandle, &MakeUniquePointerReceiver(uuid).Get(), &type) == BT_ERROR_NONE, + VerifyOrReturn(__GetAttInfo(gattHandle, &uuid.GetReceiver(), &type) == BT_ERROR_NONE, ChipLogError(DeviceLayer, "Failed to fetch GATT Attribute from GATT handle")); ChipLogProgress(DeviceLayer, "Gatt read requested on %s: uuid=%s", __ConvertAttTypeToStr(type), StringOrNullMarker(uuid.get())); - ret = bt_gatt_get_value(gattHandle, &MakeUniquePointerReceiver(value).Get(), &len); + ret = bt_gatt_get_value(gattHandle, &value.GetReceiver(), &len); VerifyOrReturn(ret == BT_ERROR_NONE, ChipLogError(DeviceLayer, "bt_gatt_get_value() failed: %s", get_error_message(ret))); ChipLogByteSpan(DeviceLayer, ByteSpan(Uint8::from_const_char(value.get()), len)); @@ -233,7 +233,7 @@ void BLEManagerImpl::WriteValueRequestedCb(const char * remoteAddress, int reque conn = static_cast(g_hash_table_lookup(mConnectionMap, remoteAddress)); VerifyOrReturn(conn != nullptr, ChipLogError(DeviceLayer, "Failed to find connection info")); - VerifyOrReturn(__GetAttInfo(gattHandle, &MakeUniquePointerReceiver(uuid).Get(), &type) == BT_ERROR_NONE, + VerifyOrReturn(__GetAttInfo(gattHandle, &uuid.GetReceiver(), &type) == BT_ERROR_NONE, ChipLogError(DeviceLayer, "Failed to fetch GATT Attribute from GATT handle")); ChipLogProgress(DeviceLayer, "Gatt write requested on %s: uuid=%s len=%d", __ConvertAttTypeToStr(type), StringOrNullMarker(uuid.get()), len); @@ -268,7 +268,7 @@ void BLEManagerImpl::NotificationStateChangedCb(bool notify, bt_gatt_server_h se VerifyOrReturn(conn != nullptr, ChipLogError(DeviceLayer, "Failed to find connection info")); - int ret = __GetAttInfo(charHandle, &MakeUniquePointerReceiver(uuid).Get(), &type); + int ret = __GetAttInfo(charHandle, &uuid.GetReceiver(), &type); VerifyOrReturn(ret == BT_ERROR_NONE, ChipLogError(DeviceLayer, "Failed to fetch GATT Attribute from CHAR handle: %s", get_error_message(ret))); @@ -776,7 +776,7 @@ static bool __GattClientForeachCharCb(int total, int index, bt_gatt_h charHandle GAutoPtr uuid; auto conn = static_cast(data); - int ret = __GetAttInfo(charHandle, &MakeUniquePointerReceiver(uuid).Get(), &type); + int ret = __GetAttInfo(charHandle, &uuid.GetReceiver(), &type); VerifyOrExit(ret == BT_ERROR_NONE, ChipLogError(DeviceLayer, "Failed to fetch GATT Attribute from CHAR handle: %s", get_error_message(ret))); @@ -803,7 +803,7 @@ static bool __GattClientForeachServiceCb(int total, int index, bt_gatt_h svcHand auto conn = static_cast(data); ChipLogProgress(DeviceLayer, "__GattClientForeachServiceCb"); - int ret = __GetAttInfo(svcHandle, &MakeUniquePointerReceiver(uuid).Get(), &type); + int ret = __GetAttInfo(svcHandle, &uuid.GetReceiver(), &type); VerifyOrExit(ret == BT_ERROR_NONE, ChipLogError(DeviceLayer, "Failed to fetch GATT Attribute from SVC handle: %s", get_error_message(ret))); diff --git a/src/platform/Tizen/BUILD.gn b/src/platform/Tizen/BUILD.gn index 0d0f329be1bd5e..f2f972635a054d 100644 --- a/src/platform/Tizen/BUILD.gn +++ b/src/platform/Tizen/BUILD.gn @@ -31,6 +31,7 @@ static_library("Tizen") { sources = [ "../DeviceSafeQueue.cpp", "../DeviceSafeQueue.h", + "../GLibTypeDeleter.h", "../SingletonConfigurationManager.cpp", "AppPreference.cpp", "AppPreference.h", diff --git a/src/platform/Tizen/DnssdImpl.cpp b/src/platform/Tizen/DnssdImpl.cpp index 8d383ac48f5d13..cc3e5a1e8f76a6 100644 --- a/src/platform/Tizen/DnssdImpl.cpp +++ b/src/platform/Tizen/DnssdImpl.cpp @@ -181,13 +181,13 @@ void OnBrowse(dnssd_service_state_e state, dnssd_service_h service, void * data) chip::GAutoPtr ifaceName; uint32_t interfaceId = 0; - ret = dnssd_service_get_type(service, &MakeUniquePointerReceiver(type).Get()); + ret = dnssd_service_get_type(service, &type.GetReceiver()); VerifyOrExit(ret == DNSSD_ERROR_NONE, ChipLogError(DeviceLayer, "dnssd_service_get_type() failed: %s", get_error_message(ret))); - ret = dnssd_service_get_name(service, &MakeUniquePointerReceiver(name).Get()); + ret = dnssd_service_get_name(service, &name.GetReceiver()); VerifyOrExit(ret == DNSSD_ERROR_NONE, ChipLogError(DeviceLayer, "dnssd_service_get_name() failed: %s", get_error_message(ret))); - ret = dnssd_service_get_interface(service, &MakeUniquePointerReceiver(ifaceName).Get()); + ret = dnssd_service_get_interface(service, &ifaceName.GetReceiver()); VerifyOrExit(ret == DNSSD_ERROR_NONE, ChipLogError(DeviceLayer, "dnssd_service_get_interface() failed: %s", get_error_message(ret))); @@ -305,12 +305,12 @@ void OnResolve(dnssd_error_e result, dnssd_service_h service, void * userData) chip::Inet::IPAddress ipAddr; CHIP_ERROR err = CHIP_NO_ERROR; - int ret = dnssd_service_get_name(service, &MakeUniquePointerReceiver(name).Get()); + int ret = dnssd_service_get_name(service, &name.GetReceiver()); VerifyOrExit(ret == DNSSD_ERROR_NONE, ChipLogError(DeviceLayer, "dnssd_service_get_name() failed: %s", get_error_message(ret))); chip::Platform::CopyString(rCtx->mResult.mName, name.get()); - ret = dnssd_service_get_ip(service, &MakeUniquePointerReceiver(ipv4).Get(), &MakeUniquePointerReceiver(ipv6).Get()); + ret = dnssd_service_get_ip(service, &ipv4.GetReceiver(), &ipv6.GetReceiver()); VerifyOrExit(ret == DNSSD_ERROR_NONE, ChipLogError(DeviceLayer, "dnssd_service_get_ip() failed: %s", get_error_message(ret))); // If both IPv4 and IPv6 are set, IPv6 address has higher priority. diff --git a/src/platform/Tizen/WiFiManager.cpp b/src/platform/Tizen/WiFiManager.cpp index ed43377e5e0142..50e8b9206401d7 100644 --- a/src/platform/Tizen/WiFiManager.cpp +++ b/src/platform/Tizen/WiFiManager.cpp @@ -400,14 +400,14 @@ bool WiFiManager::_FoundAPOnScanCb(wifi_manager_ap_h ap, void * userData) wifi_manager_security_type_e type; WiFiScanResponse scannedAP; - wifiErr = wifi_manager_ap_get_essid(ap, &MakeUniquePointerReceiver(essid).Get()); + wifiErr = wifi_manager_ap_get_essid(ap, &essid.GetReceiver()); VerifyOrExit(wifiErr == WIFI_MANAGER_ERROR_NONE, ChipLogError(DeviceLayer, "FAIL: get AP essid [%s]", get_error_message(wifiErr))); ChipLogProgress(DeviceLayer, "Essid Found: %s\n", essid.get()); scannedAP.ssidLen = static_cast(std::min(strlen(essid.get()), sizeof(scannedAP.ssid))); memcpy(scannedAP.ssid, essid.get(), scannedAP.ssidLen); - wifiErr = wifi_manager_ap_get_bssid(ap, &MakeUniquePointerReceiver(bssid).Get()); + wifiErr = wifi_manager_ap_get_bssid(ap, &bssid.GetReceiver()); VerifyOrExit(wifiErr == WIFI_MANAGER_ERROR_NONE, ChipLogError(DeviceLayer, "Fail: get AP bssid [%s]", get_error_message(wifiErr))); memcpy(scannedAP.bssid, bssid.get(), std::min(strlen(bssid.get()), sizeof(scannedAP.bssid))); @@ -443,7 +443,7 @@ bool WiFiManager::_FoundAPCb(wifi_manager_ap_h ap, void * userData) bool isPassphraseRequired = false; auto clonedAp = reinterpret_cast(userData); - wifiErr = wifi_manager_ap_get_essid(ap, &MakeUniquePointerReceiver(essid).Get()); + wifiErr = wifi_manager_ap_get_essid(ap, &essid.GetReceiver()); VerifyOrExit(wifiErr == WIFI_MANAGER_ERROR_NONE, ChipLogError(DeviceLayer, "FAIL: get AP essid [%s]", get_error_message(wifiErr))); @@ -503,7 +503,7 @@ bool WiFiManager::_ConfigListCb(const wifi_manager_config_h config, void * userD GAutoPtr name; wifi_manager_security_type_e securityType = WIFI_MANAGER_SECURITY_TYPE_NONE; - wifi_manager_config_get_name(config, &MakeUniquePointerReceiver(name).Get()); + wifi_manager_config_get_name(config, &name.GetReceiver()); wifi_manager_config_get_security_type(config, &securityType); wifiErr = wifi_manager_config_remove(sInstance.mWiFiManagerHandle, config); @@ -1155,7 +1155,7 @@ CHIP_ERROR WiFiManager::GetConfiguredNetwork(NetworkCommissioning::Network & net return CHIP_ERROR_INCORRECT_STATE; } GAutoPtr essid; - int wifiErr = wifi_manager_ap_get_essid(connectedAp, &MakeUniquePointerReceiver(essid).Get()); + int wifiErr = wifi_manager_ap_get_essid(connectedAp, &essid.GetReceiver()); VerifyOrReturnError(wifiErr == WIFI_MANAGER_ERROR_NONE, CHIP_ERROR_INTERNAL, ChipLogError(DeviceLayer, "FAIL: get essid [%s]", get_error_message(wifiErr))); network.networkIDLen = static_cast(std::min(strlen(essid.get()), sizeof(network.networkID))); From e8cf8f0c6053ca93bf08b53b8fe194de17ea2831 Mon Sep 17 00:00:00 2001 From: Boris Zbarsky Date: Wed, 21 Feb 2024 11:54:39 -0500 Subject: [PATCH 045/385] Mark ServerEndpoint Darwin objects as Sendable in Swift. (#32088) These are allowed to be accessed concurrently from multiple threads, so are Sendable. --- src/darwin/Framework/CHIP/ServerEndpoint/MTRAccessGrant.h | 1 + src/darwin/Framework/CHIP/ServerEndpoint/MTRDeviceTypeRevision.h | 1 + src/darwin/Framework/CHIP/ServerEndpoint/MTRServerAttribute.h | 1 + src/darwin/Framework/CHIP/ServerEndpoint/MTRServerCluster.h | 1 + src/darwin/Framework/CHIP/ServerEndpoint/MTRServerEndpoint.h | 1 + 5 files changed, 5 insertions(+) diff --git a/src/darwin/Framework/CHIP/ServerEndpoint/MTRAccessGrant.h b/src/darwin/Framework/CHIP/ServerEndpoint/MTRAccessGrant.h index e0b25449755f16..e0dc4bd052f0f4 100644 --- a/src/darwin/Framework/CHIP/ServerEndpoint/MTRAccessGrant.h +++ b/src/darwin/Framework/CHIP/ServerEndpoint/MTRAccessGrant.h @@ -24,6 +24,7 @@ NS_ASSUME_NONNULL_BEGIN * An access grant, which can be represented as an entry in the Matter Access * Control cluster. */ +NS_SWIFT_SENDABLE MTR_NEWLY_AVAILABLE @interface MTRAccessGrant : NSObject diff --git a/src/darwin/Framework/CHIP/ServerEndpoint/MTRDeviceTypeRevision.h b/src/darwin/Framework/CHIP/ServerEndpoint/MTRDeviceTypeRevision.h index 7f4f88b0cfd643..dc95ddcddaeaeb 100644 --- a/src/darwin/Framework/CHIP/ServerEndpoint/MTRDeviceTypeRevision.h +++ b/src/darwin/Framework/CHIP/ServerEndpoint/MTRDeviceTypeRevision.h @@ -23,6 +23,7 @@ NS_ASSUME_NONNULL_BEGIN * A representation of a "device type revision" in the sense used in the Matter * specification. This has an identifier and a version number. */ +NS_SWIFT_SENDABLE MTR_NEWLY_AVAILABLE @interface MTRDeviceTypeRevision : NSObject diff --git a/src/darwin/Framework/CHIP/ServerEndpoint/MTRServerAttribute.h b/src/darwin/Framework/CHIP/ServerEndpoint/MTRServerAttribute.h index 46e95bfb39a7bd..7d8c27b74b55d3 100644 --- a/src/darwin/Framework/CHIP/ServerEndpoint/MTRServerAttribute.h +++ b/src/darwin/Framework/CHIP/ServerEndpoint/MTRServerAttribute.h @@ -25,6 +25,7 @@ NS_ASSUME_NONNULL_BEGIN * MTRDeviceController. An attribute has an identifier and a value, and may or * may not be writable. */ +NS_SWIFT_SENDABLE MTR_NEWLY_AVAILABLE @interface MTRServerAttribute : NSObject diff --git a/src/darwin/Framework/CHIP/ServerEndpoint/MTRServerCluster.h b/src/darwin/Framework/CHIP/ServerEndpoint/MTRServerCluster.h index 48604dd2a76797..02b0f4b274374d 100644 --- a/src/darwin/Framework/CHIP/ServerEndpoint/MTRServerCluster.h +++ b/src/darwin/Framework/CHIP/ServerEndpoint/MTRServerCluster.h @@ -24,6 +24,7 @@ NS_ASSUME_NONNULL_BEGIN /** * A representation of a server cluster implemented by an MTRDeviceController. */ +NS_SWIFT_SENDABLE MTR_NEWLY_AVAILABLE @interface MTRServerCluster : NSObject diff --git a/src/darwin/Framework/CHIP/ServerEndpoint/MTRServerEndpoint.h b/src/darwin/Framework/CHIP/ServerEndpoint/MTRServerEndpoint.h index 13dbe8454d759e..9716692ea8895d 100644 --- a/src/darwin/Framework/CHIP/ServerEndpoint/MTRServerEndpoint.h +++ b/src/darwin/Framework/CHIP/ServerEndpoint/MTRServerEndpoint.h @@ -25,6 +25,7 @@ NS_ASSUME_NONNULL_BEGIN /** * A representation of an endpoint implemented by an MTRDeviceController. */ +NS_SWIFT_SENDABLE MTR_NEWLY_AVAILABLE @interface MTRServerEndpoint : NSObject From 7be1b2e418e0063d8117b0ea31163703c2972105 Mon Sep 17 00:00:00 2001 From: Jean-Francois Penven <67962328+jepenven-silabs@users.noreply.github.com> Date: Wed, 21 Feb 2024 12:01:26 -0500 Subject: [PATCH 046/385] [Silabs] Silabs fix app error (#32238) * fix main * Fix app errorr --- examples/platform/silabs/main.cpp | 10 ++++++---- examples/platform/silabs/silabs_utils.cpp | 2 +- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/examples/platform/silabs/main.cpp b/examples/platform/silabs/main.cpp index 3c9829edd1954f..a3155194e8d1dd 100644 --- a/examples/platform/silabs/main.cpp +++ b/examples/platform/silabs/main.cpp @@ -71,8 +71,9 @@ int main(void) void application_start(void * unused) { - if (SilabsMatterConfig::InitMatter(BLE_DEV_NAME) != CHIP_NO_ERROR) - appError(CHIP_ERROR_INTERNAL); + CHIP_ERROR err = SilabsMatterConfig::InitMatter(BLE_DEV_NAME); + if (err != CHIP_NO_ERROR) + appError(err); gExampleDeviceInfoProvider.SetStorageDelegate(&chip::Server::GetInstance().GetPersistentStorage()); chip::DeviceLayer::SetDeviceInfoProvider(&gExampleDeviceInfoProvider); @@ -83,8 +84,9 @@ void application_start(void * unused) chip::DeviceLayer::PlatformMgr().UnlockChipStack(); SILABS_LOG("Starting App Task"); - if (AppTask::GetAppTask().StartAppTask() != CHIP_NO_ERROR) - appError(CHIP_ERROR_INTERNAL); + err = AppTask::GetAppTask().StartAppTask(); + if (err != CHIP_NO_ERROR) + appError(err); vTaskDelete(main_Task); } diff --git a/examples/platform/silabs/silabs_utils.cpp b/examples/platform/silabs/silabs_utils.cpp index 7231836c15bf7e..c8a068a328955c 100644 --- a/examples/platform/silabs/silabs_utils.cpp +++ b/examples/platform/silabs/silabs_utils.cpp @@ -27,7 +27,7 @@ void appError(int err) snprintf(faultMessage, sizeof faultMessage, "App Critical Error:%d", err); SILABS_LOG("!!!!!!!!!!!! %s !!!!!!!!!!!", faultMessage); chip::DeviceLayer::Silabs::OnSoftwareFaultEventHandler(faultMessage); - vTaskDelay(pdMS_TO_TICKS(1000)); + vTaskSuspendAll(); /* Force an assert. */ chipAbort(); } From 40fc3ea8e9da0a76371bd8bf2050efa69a7efe9e Mon Sep 17 00:00:00 2001 From: Boris Zbarsky Date: Wed, 21 Feb 2024 13:03:41 -0500 Subject: [PATCH 047/385] Improve "need a custom toolchain" message to log more information. (#32239) Logging what gn thinks is going on for the host/target OS and cpu can help diagnose why we didn't find toolchain in the big if cascade. --- build/config/BUILDCONFIG.gn | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/build/config/BUILDCONFIG.gn b/build/config/BUILDCONFIG.gn index 9d2f17d1acf86e..01626726e0b9af 100644 --- a/build/config/BUILDCONFIG.gn +++ b/build/config/BUILDCONFIG.gn @@ -127,7 +127,9 @@ if (_chip_defaults.custom_toolchain != "") { "Unsupported target_cpu: ${current_cpu}. Shall be arm for webOS") } } else { - assert(false, "No toolchain specified, please specify custom_toolchain") + assert( + false, + "No toolchain specified, please specify custom_toolchain for host_os='${host_os}', target_os='${target_os}', host_cpu='${host_cpu}', target_cpu='${target_cpu}'") } set_default_toolchain(_default_toolchain) From f72008cb8a283093245517797fcc21cb0fb3a317 Mon Sep 17 00:00:00 2001 From: Boris Zbarsky Date: Wed, 21 Feb 2024 13:21:36 -0500 Subject: [PATCH 048/385] Correctly annotate things that are unused when logging is disabled. (#32141) We don't seem to have very good CI coverage for the logging-disabled configurations. Also removes UNUSED_VAR and UNUSED_PARAMETER use in favor of the standard [[maybe_unused]]. Fixes https://github.com/project-chip/connectedhomeip/issues/32113 --- .../bridge-app/asr/subdevice/SubDeviceManager.cpp | 7 +++---- examples/bridge-app/esp32/main/main.cpp | 7 +++---- examples/bridge-app/linux/main.cpp | 7 +++---- examples/bridge-app/telink/src/AppTask.cpp | 7 +++---- examples/chip-tool/commands/common/DeviceScanner.cpp | 2 +- .../discover/DiscoverCommissionersCommand.cpp | 2 +- examples/common/websocket-server/WebSocketServer.cpp | 6 +++--- examples/light-switch-app/genio/src/main.cpp | 2 -- examples/lighting-app/genio/src/AppTask.cpp | 2 -- examples/lighting-app/genio/src/main.cpp | 2 -- examples/lock-app/genio/src/AppTask.cpp | 2 -- examples/lock-app/genio/src/main.cpp | 2 -- examples/ota-requestor-app/genio/src/AppTask.cpp | 2 -- examples/ota-requestor-app/genio/src/main.cpp | 2 -- .../silabs/efr32/rs911x/hal/efx32_ncp_host.c | 12 ++++-------- examples/platform/silabs/efr32/rs911x/hal/efx_spi.c | 5 +---- examples/thermostat/genio/src/main.cpp | 2 -- examples/tv-casting-app/linux/CastingUtils.cpp | 4 ++-- .../tv-casting-common/core/CastingPlayer.cpp | 2 +- .../tv-casting-common/src/CastingServer.cpp | 2 +- .../tv-casting-common/src/ZCLCallbacks.cpp | 4 ++-- src/app/app-platform/ContentAppPlatform.cpp | 9 ++++----- src/app/server/DefaultAclStorage.cpp | 2 +- src/app/util/types_stub.h | 6 ------ src/controller/tests/data_model/TestRead.cpp | 2 +- src/crypto/tests/TestChipCryptoPAL.cpp | 2 +- 26 files changed, 35 insertions(+), 69 deletions(-) diff --git a/examples/bridge-app/asr/subdevice/SubDeviceManager.cpp b/examples/bridge-app/asr/subdevice/SubDeviceManager.cpp index ab0f2ef3b707a1..9d4eda96e98438 100644 --- a/examples/bridge-app/asr/subdevice/SubDeviceManager.cpp +++ b/examples/bridge-app/asr/subdevice/SubDeviceManager.cpp @@ -91,12 +91,11 @@ CHIP_ERROR RemoveDeviceEndpoint(SubDevice * dev) { if (gSubDevices[index] == dev) { - EndpointId ep = emberAfClearDynamicEndpoint(index); - gSubDevices[index] = NULL; - ChipLogProgress(DeviceLayer, "Removed device %s from dynamic endpoint %d (index=%d)", dev->GetName(), ep, index); // Silence complaints about unused ep when progress logging // disabled. - UNUSED_VAR(ep); + [[maybe_unused]] EndpointId ep = emberAfClearDynamicEndpoint(index); + gSubDevices[index] = NULL; + ChipLogProgress(DeviceLayer, "Removed device %s from dynamic endpoint %d (index=%d)", dev->GetName(), ep, index); return CHIP_NO_ERROR; } } diff --git a/examples/bridge-app/esp32/main/main.cpp b/examples/bridge-app/esp32/main/main.cpp index 27cdb3c5e2dab5..07db2ba94a534f 100644 --- a/examples/bridge-app/esp32/main/main.cpp +++ b/examples/bridge-app/esp32/main/main.cpp @@ -201,12 +201,11 @@ CHIP_ERROR RemoveDeviceEndpoint(Device * dev) { if (gDevices[index] == dev) { - EndpointId ep = emberAfClearDynamicEndpoint(index); - gDevices[index] = NULL; - ChipLogProgress(DeviceLayer, "Removed device %s from dynamic endpoint %d (index=%d)", dev->GetName(), ep, index); // Silence complaints about unused ep when progress logging // disabled. - UNUSED_VAR(ep); + [[maybe_unused]] EndpointId ep = emberAfClearDynamicEndpoint(index); + gDevices[index] = NULL; + ChipLogProgress(DeviceLayer, "Removed device %s from dynamic endpoint %d (index=%d)", dev->GetName(), ep, index); return CHIP_NO_ERROR; } } diff --git a/examples/bridge-app/linux/main.cpp b/examples/bridge-app/linux/main.cpp index 80c8b17b7fbed5..c569e7c06e8b45 100644 --- a/examples/bridge-app/linux/main.cpp +++ b/examples/bridge-app/linux/main.cpp @@ -300,12 +300,11 @@ int RemoveDeviceEndpoint(Device * dev) { // Todo: Update this to schedule the work rather than use this lock DeviceLayer::StackLock lock; - EndpointId ep = emberAfClearDynamicEndpoint(index); - gDevices[index] = nullptr; - ChipLogProgress(DeviceLayer, "Removed device %s from dynamic endpoint %d (index=%d)", dev->GetName(), ep, index); // Silence complaints about unused ep when progress logging // disabled. - UNUSED_VAR(ep); + [[maybe_unused]] EndpointId ep = emberAfClearDynamicEndpoint(index); + gDevices[index] = nullptr; + ChipLogProgress(DeviceLayer, "Removed device %s from dynamic endpoint %d (index=%d)", dev->GetName(), ep, index); return index; } index++; diff --git a/examples/bridge-app/telink/src/AppTask.cpp b/examples/bridge-app/telink/src/AppTask.cpp index d21897bd2d36b6..72a997c91e9511 100644 --- a/examples/bridge-app/telink/src/AppTask.cpp +++ b/examples/bridge-app/telink/src/AppTask.cpp @@ -224,12 +224,11 @@ CHIP_ERROR RemoveDeviceEndpoint(Device * dev) { if (gDevices[index] == dev) { - EndpointId ep = emberAfClearDynamicEndpoint(index); - gDevices[index] = NULL; - ChipLogProgress(DeviceLayer, "Removed device %s from dynamic endpoint %d (index=%d)", dev->GetName(), ep, index); // Silence complaints about unused ep when progress logging // disabled. - UNUSED_VAR(ep); + [[maybe_unused]] EndpointId ep = emberAfClearDynamicEndpoint(index); + gDevices[index] = NULL; + ChipLogProgress(DeviceLayer, "Removed device %s from dynamic endpoint %d (index=%d)", dev->GetName(), ep, index); return CHIP_NO_ERROR; } } diff --git a/examples/chip-tool/commands/common/DeviceScanner.cpp b/examples/chip-tool/commands/common/DeviceScanner.cpp index 29d31c1fc80565..35d74bd06c844f 100644 --- a/examples/chip-tool/commands/common/DeviceScanner.cpp +++ b/examples/chip-tool/commands/common/DeviceScanner.cpp @@ -218,7 +218,7 @@ void DeviceScanner::Log() const auto resultsCount = mDiscoveredResults.size(); VerifyOrReturn(resultsCount > 0, ChipLogProgress(chipTool, "No device discovered.")); - uint16_t index = 0; + [[maybe_unused]] uint16_t index = 0; for (auto & instance : mDiscoveredResults) { ChipLogProgress(chipTool, "Instance Name: %s ", instance.first.c_str()); diff --git a/examples/chip-tool/commands/discover/DiscoverCommissionersCommand.cpp b/examples/chip-tool/commands/discover/DiscoverCommissionersCommand.cpp index 0d1c9a032de02c..57c7574c4ea2e3 100644 --- a/examples/chip-tool/commands/discover/DiscoverCommissionersCommand.cpp +++ b/examples/chip-tool/commands/discover/DiscoverCommissionersCommand.cpp @@ -29,7 +29,7 @@ CHIP_ERROR DiscoverCommissionersCommand::RunCommand() void DiscoverCommissionersCommand::Shutdown() { - int commissionerCount = 0; + [[maybe_unused]] int commissionerCount = 0; for (int i = 0; i < CHIP_DEVICE_CONFIG_MAX_DISCOVERED_NODES; i++) { const Dnssd::DiscoveredNodeData * commissioner = mCommissionableNodeController.GetDiscoveredCommissioner(i); diff --git a/examples/common/websocket-server/WebSocketServer.cpp b/examples/common/websocket-server/WebSocketServer.cpp index 623dda3dc47527..2dba035601ea0e 100644 --- a/examples/common/websocket-server/WebSocketServer.cpp +++ b/examples/common/websocket-server/WebSocketServer.cpp @@ -24,9 +24,9 @@ #include #include -constexpr uint16_t kDefaultWebSocketServerPort = 9002; -constexpr uint16_t kMaxMessageBufferLen = 8192; -constexpr char kWebSocketServerReadyMessage[] = "== WebSocket Server Ready"; +constexpr uint16_t kDefaultWebSocketServerPort = 9002; +constexpr uint16_t kMaxMessageBufferLen = 8192; +[[maybe_unused]] constexpr char kWebSocketServerReadyMessage[] = "== WebSocket Server Ready"; namespace { lws * gWebSocketInstance = nullptr; diff --git a/examples/light-switch-app/genio/src/main.cpp b/examples/light-switch-app/genio/src/main.cpp index 93bb82a21b0735..d545409c706913 100644 --- a/examples/light-switch-app/genio/src/main.cpp +++ b/examples/light-switch-app/genio/src/main.cpp @@ -51,8 +51,6 @@ using namespace ::chip; using namespace ::chip::Inet; using namespace ::chip::DeviceLayer; -#define UNUSED_PARAMETER(a) (a = a) - volatile int apperror_cnt; /*************************************************************************** diff --git a/examples/lighting-app/genio/src/AppTask.cpp b/examples/lighting-app/genio/src/AppTask.cpp index 6a121673a002a6..d948087833c4dd 100644 --- a/examples/lighting-app/genio/src/AppTask.cpp +++ b/examples/lighting-app/genio/src/AppTask.cpp @@ -66,8 +66,6 @@ #error "Must have portYIELD_FROM_ISR or portEND_SWITCHING_ISR" #endif -#define UNUSED_PARAMETER(a) (a = a) - #if defined(ENABLE_CHIP_SHELL) using chip::Shell::Engine; using chip::Shell::PrintCommandHelp; diff --git a/examples/lighting-app/genio/src/main.cpp b/examples/lighting-app/genio/src/main.cpp index ab578f3f2c75bd..22f654eb5f2f50 100644 --- a/examples/lighting-app/genio/src/main.cpp +++ b/examples/lighting-app/genio/src/main.cpp @@ -51,8 +51,6 @@ using namespace ::chip; using namespace ::chip::Inet; using namespace ::chip::DeviceLayer; -#define UNUSED_PARAMETER(a) (a = a) - volatile int apperror_cnt; /*************************************************************************** diff --git a/examples/lock-app/genio/src/AppTask.cpp b/examples/lock-app/genio/src/AppTask.cpp index 7a438dd4974d3d..1c2f0719790196 100644 --- a/examples/lock-app/genio/src/AppTask.cpp +++ b/examples/lock-app/genio/src/AppTask.cpp @@ -60,8 +60,6 @@ #error "Must have portYIELD_FROM_ISR or portEND_SWITCHING_ISR" #endif -#define UNUSED_PARAMETER(a) (a = a) - namespace { TimerHandle_t sFunctionTimer; // FreeRTOS app sw timer. diff --git a/examples/lock-app/genio/src/main.cpp b/examples/lock-app/genio/src/main.cpp index 416c81c53436d7..92b16a39663ee4 100644 --- a/examples/lock-app/genio/src/main.cpp +++ b/examples/lock-app/genio/src/main.cpp @@ -51,8 +51,6 @@ using namespace ::chip; using namespace ::chip::Inet; using namespace ::chip::DeviceLayer; -#define UNUSED_PARAMETER(a) (a = a) - volatile int apperror_cnt; /*************************************************************************** diff --git a/examples/ota-requestor-app/genio/src/AppTask.cpp b/examples/ota-requestor-app/genio/src/AppTask.cpp index 43c92cf26adeeb..50d1d080a5b7b4 100644 --- a/examples/ota-requestor-app/genio/src/AppTask.cpp +++ b/examples/ota-requestor-app/genio/src/AppTask.cpp @@ -53,8 +53,6 @@ #error "Must have portYIELD_FROM_ISR or portEND_SWITCHING_ISR" #endif -#define UNUSED_PARAMETER(a) (a = a) - namespace { TaskHandle_t sAppTaskHandle; diff --git a/examples/ota-requestor-app/genio/src/main.cpp b/examples/ota-requestor-app/genio/src/main.cpp index dcd85fbb920859..e3676c5c9eacbd 100644 --- a/examples/ota-requestor-app/genio/src/main.cpp +++ b/examples/ota-requestor-app/genio/src/main.cpp @@ -53,8 +53,6 @@ using namespace ::chip; using namespace ::chip::Inet; using namespace ::chip::DeviceLayer; -#define UNUSED_PARAMETER(a) (a = a) - volatile int apperror_cnt; static void OTAEventsHandler(const DeviceLayer::ChipDeviceEvent * event, intptr_t arg) diff --git a/examples/platform/silabs/efr32/rs911x/hal/efx32_ncp_host.c b/examples/platform/silabs/efr32/rs911x/hal/efx32_ncp_host.c index 82976deb6a3b09..9f07d3f8f22c16 100644 --- a/examples/platform/silabs/efr32/rs911x/hal/efx32_ncp_host.c +++ b/examples/platform/silabs/efr32/rs911x/hal/efx32_ncp_host.c @@ -57,11 +57,9 @@ LDMA_TransferCfg_t ldmaRXConfig; static osSemaphoreId_t transfer_done_semaphore = NULL; -static bool dma_callback(unsigned int channel, unsigned int sequenceNo, void * userParam) +static bool dma_callback([[maybe_unused]] unsigned int channel, [[maybe_unused]] unsigned int sequenceNo, + [[maybe_unused]] void * userParam) { - UNUSED_PARAMETER(channel); - UNUSED_PARAMETER(sequenceNo); - UNUSED_PARAMETER(userParam); #if defined(SL_CATLOG_POWER_MANAGER_PRESENT) sl_power_manager_remove_em_requirement(SL_POWER_MANAGER_EM1); #endif @@ -69,10 +67,8 @@ static bool dma_callback(unsigned int channel, unsigned int sequenceNo, void * u return false; } -static void gpio_interrupt(uint8_t interrupt_number) +static void gpio_interrupt([[maybe_unused]] uint8_t interrupt_number) { - UNUSED_PARAMETER(interrupt_number); - if (NULL != init_config.rx_irq) { init_config.rx_irq(); @@ -312,4 +308,4 @@ void sl_si91x_host_disable_bus_interrupt(void) bool sl_si91x_host_is_in_irq_context(void) { return (SCB->ICSR & SCB_ICSR_VECTACTIVE_Msk) != 0U; -} \ No newline at end of file +} diff --git a/examples/platform/silabs/efr32/rs911x/hal/efx_spi.c b/examples/platform/silabs/efr32/rs911x/hal/efx_spi.c index ad6b5ed5e3418d..9097177b73a585 100644 --- a/examples/platform/silabs/efr32/rs911x/hal/efx_spi.c +++ b/examples/platform/silabs/efr32/rs911x/hal/efx_spi.c @@ -171,10 +171,7 @@ void sl_wfx_host_reset_chip(void) vTaskDelay(pdMS_TO_TICKS(3)); } -void gpio_interrupt(uint8_t interrupt_number) -{ - UNUSED_PARAMETER(interrupt_number); -} +void gpio_interrupt([[maybe_unused]] uint8_t interrupt_number) {} /***************************************************************** * @fn void rsi_hal_board_init(void) diff --git a/examples/thermostat/genio/src/main.cpp b/examples/thermostat/genio/src/main.cpp index 93bb82a21b0735..d545409c706913 100644 --- a/examples/thermostat/genio/src/main.cpp +++ b/examples/thermostat/genio/src/main.cpp @@ -51,8 +51,6 @@ using namespace ::chip; using namespace ::chip::Inet; using namespace ::chip::DeviceLayer; -#define UNUSED_PARAMETER(a) (a = a) - volatile int apperror_cnt; /*************************************************************************** diff --git a/examples/tv-casting-app/linux/CastingUtils.cpp b/examples/tv-casting-app/linux/CastingUtils.cpp index 02b9467d884614..d4d71b5dd2c0ae 100644 --- a/examples/tv-casting-app/linux/CastingUtils.cpp +++ b/examples/tv-casting-app/linux/CastingUtils.cpp @@ -105,7 +105,7 @@ void InitCommissioningFlow(intptr_t commandArg) commissioner->LogDetail(); if (associatedConnectableVideoPlayer.HasValue()) { - TargetVideoPlayerInfo * targetVideoPlayerInfo = associatedConnectableVideoPlayer.Value(); + [[maybe_unused]] TargetVideoPlayerInfo * targetVideoPlayerInfo = associatedConnectableVideoPlayer.Value(); ChipLogProgress(AppServer, "Previously connected with nodeId 0x" ChipLogFormatX64 " fabricIndex: %d", ChipLogValueX64(targetVideoPlayerInfo->GetNodeId()), targetVideoPlayerInfo->GetFabricIndex()); } @@ -305,7 +305,7 @@ void PrintFabrics() ChipLogError(AppServer, " -- Not initialized"); continue; } - NodeId myNodeId = fb.GetNodeId(); + [[maybe_unused]] NodeId myNodeId = fb.GetNodeId(); ChipLogProgress(NotSpecified, "---- Current Fabric nodeId=0x" ChipLogFormatX64 " fabricId=0x" ChipLogFormatX64 " fabricIndex=%d", ChipLogValueX64(myNodeId), ChipLogValueX64(fb.GetFabricId()), fabricIndex); diff --git a/examples/tv-casting-app/tv-casting-common/core/CastingPlayer.cpp b/examples/tv-casting-app/tv-casting-common/core/CastingPlayer.cpp index 41d9feb52977eb..f34b6b2ef16c34 100644 --- a/examples/tv-casting-app/tv-casting-common/core/CastingPlayer.cpp +++ b/examples/tv-casting-app/tv-casting-common/core/CastingPlayer.cpp @@ -257,7 +257,7 @@ void CastingPlayer::LogDetail() const { for (unsigned j = 0; j < mAttributes.numIPs; j++) { - char * ipAddressOut = mAttributes.ipAddresses[j].ToString(buf); + [[maybe_unused]] char * ipAddressOut = mAttributes.ipAddresses[j].ToString(buf); ChipLogDetail(AppServer, "\tIP Address #%d: %s", j + 1, ipAddressOut); } } diff --git a/examples/tv-casting-app/tv-casting-common/src/CastingServer.cpp b/examples/tv-casting-app/tv-casting-common/src/CastingServer.cpp index 98f6b197a59e33..a3de0a263c3efe 100644 --- a/examples/tv-casting-app/tv-casting-common/src/CastingServer.cpp +++ b/examples/tv-casting-app/tv-casting-common/src/CastingServer.cpp @@ -695,7 +695,7 @@ void CastingServer::SetDefaultFabricIndex(std::functionGetEndpointId(); - EndpointId ep = emberAfClearDynamicEndpoint(index); - mContentApps[index] = nullptr; - ChipLogProgress(DeviceLayer, "Removed device %d from dynamic endpoint %d (index=%d)", - app->GetApplicationBasicDelegate()->HandleGetVendorId(), ep, index); // Silence complaints about unused ep when progress logging // disabled. - UNUSED_VAR(ep); + /*[[maybe_unused]]*/ EndpointId ep = emberAfClearDynamicEndpoint(index); + mContentApps[index] = nullptr; + ChipLogProgress(DeviceLayer, "Removed device %d from dynamic endpoint %d (index=%d)", + app->GetApplicationBasicDelegate()->HandleGetVendorId(), ep, index); if (curEndpoint == mCurrentAppEndpointId) { mCurrentAppEndpointId = kNoCurrentEndpointId; diff --git a/src/app/server/DefaultAclStorage.cpp b/src/app/server/DefaultAclStorage.cpp index 58d0d18feedda6..6f40cce2599893 100644 --- a/src/app/server/DefaultAclStorage.cpp +++ b/src/app/server/DefaultAclStorage.cpp @@ -138,7 +138,7 @@ CHIP_ERROR DefaultAclStorage::Init(PersistentStorageDelegate & persistentStorage CHIP_ERROR err; - size_t count = 0; + [[maybe_unused]] size_t count = 0; for (auto it = first; it != last; ++it) { diff --git a/src/app/util/types_stub.h b/src/app/util/types_stub.h index ac26684f850cd7..dbd1ea184169e1 100644 --- a/src/app/util/types_stub.h +++ b/src/app/util/types_stub.h @@ -166,12 +166,6 @@ typedef struct } EmberEventControl; -/** - * @description Useful macro for avoiding compiler warnings related to unused - * function arguments or unused variables. - */ -#define UNUSED_VAR(x) (void) (x) - /** * @brief Returns the value of the bitmask \c bits within * the register or byte \c reg. diff --git a/src/controller/tests/data_model/TestRead.cpp b/src/controller/tests/data_model/TestRead.cpp index 917c3a1251e344..fc2cfaf516524b 100644 --- a/src/controller/tests/data_model/TestRead.cpp +++ b/src/controller/tests/data_model/TestRead.cpp @@ -475,7 +475,7 @@ void TestReadInteraction::TestReadSubscribeAttributeResponseWithCache(nlTestSuit // app::InteractionModelEngine::GetInstance()->RegisterReadHandlerAppCallback(&gTestReadInteraction); - int testId = 0; + [[maybe_unused]] int testId = 0; // Read of E2C3A1(dedup), E*C3A1(E1C3A1 not exit, E2C3A1 exist), E2C3A* (5 supported attributes) // Expect no versions would be cached. diff --git a/src/crypto/tests/TestChipCryptoPAL.cpp b/src/crypto/tests/TestChipCryptoPAL.cpp index b2e12568b7c222..db5ee6b74480cd 100644 --- a/src/crypto/tests/TestChipCryptoPAL.cpp +++ b/src/crypto/tests/TestChipCryptoPAL.cpp @@ -2715,7 +2715,7 @@ static void TestVIDPID_StringExtraction(nlTestSuite * inSuite, void * inContext) }; // clang-format on - int caseIdx = 0; + [[maybe_unused]] int caseIdx = 0; for (const auto & testCase : kTestCases) { AttestationCertVidPid vidpid; From 9aeff06a884f352de973192575a44524a7da6290 Mon Sep 17 00:00:00 2001 From: arun-silabs <141724790+arun-silabs@users.noreply.github.com> Date: Thu, 22 Feb 2024 00:15:42 +0530 Subject: [PATCH 049/385] [Silabs] [WiFi] Modified logs in which AP's password is printed. (#32166) * Modified logs in which AP's password is printed. * Restyled by clang-format --------- Co-authored-by: Restyled.io --- examples/platform/silabs/SiWx917/SiWx917/sl_wifi_if.c | 3 +-- examples/platform/silabs/SiWx917/SiWx917/wfx_rsi_host.c | 2 +- examples/platform/silabs/efr32/rs911x/rsi_if.c | 6 ++---- examples/platform/silabs/efr32/rs911x/wfx_rsi_host.c | 2 +- 4 files changed, 5 insertions(+), 8 deletions(-) diff --git a/examples/platform/silabs/SiWx917/SiWx917/sl_wifi_if.c b/examples/platform/silabs/SiWx917/SiWx917/sl_wifi_if.c index f78539d9817170..6dcfcfaf46aaac 100644 --- a/examples/platform/silabs/SiWx917/SiWx917/sl_wifi_if.c +++ b/examples/platform/silabs/SiWx917/SiWx917/sl_wifi_if.c @@ -569,8 +569,7 @@ static sl_status_t wfx_rsi_do_join(void) } else { - SILABS_LOG("%s: WLAN: connecting to %s==%s, sec=%d", __func__, &wfx_rsi.sec.ssid[0], &wfx_rsi.sec.passkey[0], - wfx_rsi.sec.security); + SILABS_LOG("%s: WLAN: connecting to %s, sec=%d", __func__, &wfx_rsi.sec.ssid[0], wfx_rsi.sec.security); /* * Join the network diff --git a/examples/platform/silabs/SiWx917/SiWx917/wfx_rsi_host.c b/examples/platform/silabs/SiWx917/SiWx917/wfx_rsi_host.c index 8f1f895f9683f9..0c7efc723eb049 100644 --- a/examples/platform/silabs/SiWx917/SiWx917/wfx_rsi_host.c +++ b/examples/platform/silabs/SiWx917/SiWx917/wfx_rsi_host.c @@ -178,7 +178,7 @@ sl_status_t wfx_connect_to_ap(void) { if (wfx_rsi.dev_state & WFX_RSI_ST_STA_PROVISIONED) { - SILABS_LOG("%s: connecting to access point -> SSID: %s, PSK:%s", __func__, &wfx_rsi.sec.ssid[0], &wfx_rsi.sec.passkey[0]); + SILABS_LOG("%s: connecting to access point -> SSID: %s", __func__, &wfx_rsi.sec.ssid[0]); xEventGroupSetBits(wfx_rsi.events, WFX_EVT_STA_START_JOIN); } else diff --git a/examples/platform/silabs/efr32/rs911x/rsi_if.c b/examples/platform/silabs/efr32/rs911x/rsi_if.c index c43389761dcdfc..1ba06d0e715c16 100644 --- a/examples/platform/silabs/efr32/rs911x/rsi_if.c +++ b/examples/platform/silabs/efr32/rs911x/rsi_if.c @@ -466,8 +466,7 @@ static void wfx_rsi_save_ap_info() // translation break; } - SILABS_LOG("%s: WLAN: connecting to %s==%s, sec=%d, status=%02x", __func__, &wfx_rsi.sec.ssid[0], &wfx_rsi.sec.passkey[0], - wfx_rsi.sec.security, status); + SILABS_LOG("%s: WLAN: connecting to %s, sec=%d, status=%02x", __func__, &wfx_rsi.sec.ssid[0], wfx_rsi.sec.security, status); } /******************************************************************************************** @@ -511,8 +510,7 @@ static void wfx_rsi_do_join(void) return; } - SILABS_LOG("%s: WLAN: connecting to %s==%s, sec=%d", __func__, &wfx_rsi.sec.ssid[0], &wfx_rsi.sec.passkey[0], - wfx_rsi.sec.security); + SILABS_LOG("%s: WLAN: connecting to %s, sec=%d", __func__, &wfx_rsi.sec.ssid[0], wfx_rsi.sec.security); /* * Join the network diff --git a/examples/platform/silabs/efr32/rs911x/wfx_rsi_host.c b/examples/platform/silabs/efr32/rs911x/wfx_rsi_host.c index 331895bd3e524e..15915851c11a20 100644 --- a/examples/platform/silabs/efr32/rs911x/wfx_rsi_host.c +++ b/examples/platform/silabs/efr32/rs911x/wfx_rsi_host.c @@ -180,7 +180,7 @@ sl_status_t wfx_connect_to_ap(void) { if (wfx_rsi.dev_state & WFX_RSI_ST_STA_PROVISIONED) { - SILABS_LOG("%s: connecting to access point -> SSID: %s, PSK:%s", __func__, &wfx_rsi.sec.ssid[0], &wfx_rsi.sec.passkey[0]); + SILABS_LOG("%s: connecting to access point -> SSID: %s", __func__, &wfx_rsi.sec.ssid[0]); xEventGroupSetBits(wfx_rsi.events, WFX_EVT_STA_START_JOIN); } else From 4158d55db3f936b58cc944d10fd538a8585144f3 Mon Sep 17 00:00:00 2001 From: joonhaengHeo <85541460+joonhaengHeo@users.noreply.github.com> Date: Thu, 22 Feb 2024 08:52:08 +0900 Subject: [PATCH 050/385] Add excetpion try-catch in getConnectedPointer (#32237) --- .../clusterclient/BasicClientFragment.kt | 16 ++++- .../clusterclient/GroupSettingFragment.kt | 72 ++++++++++++------- .../clusterclient/MultiAdminClientFragment.kt | 44 +++++++++--- .../clusterclient/OnOffClientFragment.kt | 48 ++++++++++--- .../clusterclient/OpCredClientFragment.kt | 16 ++++- .../OtaProviderClientFragment.kt | 56 ++++++++++++--- .../clusterclient/SensorClientFragment.kt | 16 ++++- .../clusterclient/WildcardFragment.kt | 46 ++++++++++-- .../ClusterDetailFragment.kt | 10 ++- .../ClusterInteractionFragment.kt | 9 ++- 10 files changed, 269 insertions(+), 64 deletions(-) diff --git a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/BasicClientFragment.kt b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/BasicClientFragment.kt index f38cacbd259073..3ef61298930268 100644 --- a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/BasicClientFragment.kt +++ b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/BasicClientFragment.kt @@ -139,7 +139,13 @@ class BasicClientFragment : Fragment() { val attributeId = BasicInformation.Attribute.valueOf(attributeName).id val devicePtr = - ChipClient.getConnectedDevicePointer(requireContext(), addressUpdateFragment.deviceId) + try { + ChipClient.getConnectedDevicePointer(requireContext(), addressUpdateFragment.deviceId) + } catch (e: IllegalStateException) { + Log.d(TAG, "getConnectedDevicePointer exception", e) + showMessage("Get DevicePointer fail!") + return + } ChipClient.getDeviceController(requireContext()) .readPath( @@ -182,7 +188,13 @@ class BasicClientFragment : Fragment() { private suspend fun sendWriteAttribute(attribute: BasicInformation.Attribute, tlv: ByteArray) { val clusterId = BasicInformation.ID val devicePtr = - ChipClient.getConnectedDevicePointer(requireContext(), addressUpdateFragment.deviceId) + try { + ChipClient.getConnectedDevicePointer(requireContext(), addressUpdateFragment.deviceId) + } catch (e: IllegalStateException) { + Log.d(TAG, "getConnectedDevicePointer exception", e) + showMessage("Get DevicePointer fail!") + return + } ChipClient.getDeviceController(requireContext()) .write( diff --git a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/GroupSettingFragment.kt b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/GroupSettingFragment.kt index 8943801c080c80..bbaacbd3c997ba 100644 --- a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/GroupSettingFragment.kt +++ b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/GroupSettingFragment.kt @@ -271,11 +271,16 @@ class GroupSettingFragment : Fragment() { private suspend fun sendKeySetWrite( groupKeySetStruct: GroupKeyManagementClusterGroupKeySetStruct ) { - val cluster = - ChipClusters.GroupKeyManagementCluster( - ChipClient.getConnectedDevicePointer(requireContext(), addressUpdateFragment.deviceId), - 0 - ) + val devicePtr = + try { + ChipClient.getConnectedDevicePointer(requireContext(), addressUpdateFragment.deviceId) + } catch (e: IllegalStateException) { + Log.d(TAG, "getConnectedDevicePointer exception", e) + showMessage("Get DevicePointer fail!") + return + } + val cluster = ChipClusters.GroupKeyManagementCluster(devicePtr, 0) + cluster.keySetWrite( object : ChipClusters.DefaultClusterCallback { override fun onError(e: Exception?) { @@ -311,11 +316,15 @@ class GroupSettingFragment : Fragment() { } private suspend fun writeGroupKeyMap(groupId: UInt, groupKeySetId: UInt) { - val cluster = - ChipClusters.GroupKeyManagementCluster( - ChipClient.getConnectedDevicePointer(requireContext(), addressUpdateFragment.deviceId), - 0 - ) + val devicePtr = + try { + ChipClient.getConnectedDevicePointer(requireContext(), addressUpdateFragment.deviceId) + } catch (e: IllegalStateException) { + Log.d(TAG, "getConnectedDevicePointer exception", e) + showMessage("Get DevicePointer fail!") + return + } + val cluster = ChipClusters.GroupKeyManagementCluster(devicePtr, 0) cluster.writeGroupKeyMapAttribute( object : ChipClusters.DefaultClusterCallback { override fun onError(e: Exception?) { @@ -356,11 +365,16 @@ class GroupSettingFragment : Fragment() { } private suspend fun sendAddGroup(groupId: UInt, groupName: String) { - val cluster = - ChipClusters.GroupsCluster( - ChipClient.getConnectedDevicePointer(requireContext(), addressUpdateFragment.deviceId), - 0 - ) + val devicePtr = + try { + ChipClient.getConnectedDevicePointer(requireContext(), addressUpdateFragment.deviceId) + } catch (e: IllegalStateException) { + Log.d(TAG, "getConnectedDevicePointer exception", e) + showMessage("Get DevicePointer fail!") + return + } + val cluster = ChipClusters.GroupsCluster(devicePtr, 0) + cluster.addGroup( object : ChipClusters.GroupsCluster.AddGroupResponseCallback { override fun onError(e: Exception?) { @@ -379,11 +393,15 @@ class GroupSettingFragment : Fragment() { } private suspend fun readAccessControl() { - val cluster = - ChipClusters.AccessControlCluster( - ChipClient.getConnectedDevicePointer(requireContext(), addressUpdateFragment.deviceId), - 0 - ) + val devicePtr = + try { + ChipClient.getConnectedDevicePointer(requireContext(), addressUpdateFragment.deviceId) + } catch (e: IllegalStateException) { + Log.d(TAG, "getConnectedDevicePointer exception", e) + showMessage("Get DevicePointer fail!") + return + } + val cluster = ChipClusters.AccessControlCluster(devicePtr, 0) cluster.readAclAttribute( object : ChipClusters.AccessControlCluster.AclAttributeCallback { override fun onError(e: Exception?) { @@ -437,12 +455,16 @@ class GroupSettingFragment : Fragment() { groupId: UInt, privilege: UInt ) { + val devicePtr = + try { + ChipClient.getConnectedDevicePointer(requireContext(), addressUpdateFragment.deviceId) + } catch (e: IllegalStateException) { + Log.d(TAG, "getConnectedDevicePointer exception", e) + showMessage("Get DevicePointer fail!") + return + } // If GroupID is already added to AccessControl, do not add it. - val cluster = - ChipClusters.AccessControlCluster( - ChipClient.getConnectedDevicePointer(requireContext(), addressUpdateFragment.deviceId), - 0 - ) + val cluster = ChipClusters.AccessControlCluster(devicePtr, 0) val sendEntry = ArrayList() for (entry in value) { if ( diff --git a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/MultiAdminClientFragment.kt b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/MultiAdminClientFragment.kt index a82f0ee60ccf35..08443d6ffb4ffc 100644 --- a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/MultiAdminClientFragment.kt +++ b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/MultiAdminClientFragment.kt @@ -121,8 +121,16 @@ class MultiAdminClientFragment : Fragment() { private suspend fun sendBasicCommissioningCommandClick() { val testDuration = binding.timeoutEd.text.toString().toInt() + val devicePtr = + try { + ChipClient.getConnectedDevicePointer(requireContext(), addressUpdateFragment.deviceId) + } catch (e: IllegalStateException) { + Log.d(TAG, "getConnectedDevicePointer exception", e) + showMessage("Get DevicePointer fail!") + return + } deviceController.openPairingWindowCallback( - ChipClient.getConnectedDevicePointer(requireContext(), addressUpdateFragment.deviceId), + devicePtr, testDuration, object : OpenCommissioningCallback { override fun onError(status: Int, deviceId: Long) { @@ -140,7 +148,13 @@ class MultiAdminClientFragment : Fragment() { val testDuration = binding.timeoutEd.text.toString().toInt() val testIteration = 1000 val devicePointer = - ChipClient.getConnectedDevicePointer(requireContext(), addressUpdateFragment.deviceId) + try { + ChipClient.getConnectedDevicePointer(requireContext(), addressUpdateFragment.deviceId) + } catch (e: IllegalStateException) { + Log.d(TAG, "getConnectedDevicePointer exception", e) + showMessage("Get DevicePointer fail!") + return + } var setupPinCode: Long? = null if (!binding.setupPinCodeEd.text.toString().isEmpty()) { @@ -181,6 +195,14 @@ class MultiAdminClientFragment : Fragment() { null ) + val devicePointer = + try { + ChipClient.getConnectedDevicePointer(requireContext(), addressUpdateFragment.deviceId) + } catch (e: IllegalStateException) { + Log.d(TAG, "getConnectedDevicePointer exception", e) + showMessage("Get DevicePointer fail!") + return + } deviceController.invoke( object : InvokeCallback { override fun onError(ex: Exception?) { @@ -193,7 +215,7 @@ class MultiAdminClientFragment : Fragment() { showMessage("Revoke Commissioning success") } }, - getConnectedDevicePointer(), + devicePointer, invokeElement, timedInvokeTimeout, 0 @@ -208,6 +230,16 @@ class MultiAdminClientFragment : Fragment() { val attributeId = attribute.id val attributeName = attribute.name val attributePath = ChipAttributePath.newInstance(endpointId, clusterId, attributeId) + + val devicePointer = + try { + ChipClient.getConnectedDevicePointer(requireContext(), addressUpdateFragment.deviceId) + } catch (e: IllegalStateException) { + Log.d(TAG, "getConnectedDevicePointer exception", e) + showMessage("Get DevicePointer fail!") + return + } + deviceController.readAttributePath( object : ReportCallback { override fun onReport(nodeState: NodeState?) { @@ -230,16 +262,12 @@ class MultiAdminClientFragment : Fragment() { showMessage("read $attributeName - error : ${e?.message}") } }, - getConnectedDevicePointer(), + devicePointer, listOf(attributePath), 0 ) } - private suspend fun getConnectedDevicePointer(): Long { - return ChipClient.getConnectedDevicePointer(requireContext(), addressUpdateFragment.deviceId) - } - private fun showMessage(msg: String) { requireActivity().runOnUiThread { binding.multiAdminClusterCommandStatus.text = msg } } diff --git a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/OnOffClientFragment.kt b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/OnOffClientFragment.kt index 7994deb2f07a13..d4b55194147fca 100644 --- a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/OnOffClientFragment.kt +++ b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/OnOffClientFragment.kt @@ -105,6 +105,15 @@ class OnOffClientFragment : Fragment() { val attributePath = ChipAttributePath.newInstance(endpointId, clusterId, attributeId) + val devicePointer = + try { + ChipClient.getConnectedDevicePointer(requireContext(), addressUpdateFragment.deviceId) + } catch (e: IllegalStateException) { + Log.d(TAG, "getConnectedDevicePointer exception", e) + showMessage("Get DevicePointer fail!") + return + } + ChipClient.getDeviceController(requireContext()) .readPath( object : ReportCallback { @@ -128,7 +137,7 @@ class OnOffClientFragment : Fragment() { showMessage("On/Off attribute value: $value") } }, - getConnectedDevicePointer(), + devicePointer, listOf(attributePath), null, false, @@ -181,6 +190,15 @@ class OnOffClientFragment : Fragment() { ) } + val devicePointer = + try { + ChipClient.getConnectedDevicePointer(requireContext(), addressUpdateFragment.deviceId) + } catch (e: IllegalStateException) { + Log.d(TAG, "getConnectedDevicePointer exception", e) + showMessage("Get DevicePointer fail!") + return + } + deviceController.subscribeToPath( subscriptionEstablishedCallback, resubscriptionAttemptCallback, @@ -211,7 +229,7 @@ class OnOffClientFragment : Fragment() { showReportMessage(message) } }, - getConnectedDevicePointer(), + devicePointer, listOf(attributePath), null, minInterval, @@ -265,6 +283,15 @@ class OnOffClientFragment : Fragment() { null ) + val devicePointer = + try { + ChipClient.getConnectedDevicePointer(requireContext(), addressUpdateFragment.deviceId) + } catch (e: IllegalStateException) { + Log.d(TAG, "getConnectedDevicePointer exception", e) + showMessage("Get DevicePointer fail!") + return + } + deviceController.invoke( object : InvokeCallback { override fun onError(ex: Exception?) { @@ -277,7 +304,7 @@ class OnOffClientFragment : Fragment() { showMessage("MoveToLevel command success") } }, - getConnectedDevicePointer(), + devicePointer, invokeElement, 0, 0 @@ -298,6 +325,15 @@ class OnOffClientFragment : Fragment() { null ) + val devicePointer = + try { + ChipClient.getConnectedDevicePointer(requireContext(), addressUpdateFragment.deviceId) + } catch (e: IllegalStateException) { + Log.d(TAG, "getConnectedDevicePointer exception", e) + showMessage("Get DevicePointer fail!") + return + } + deviceController.invoke( object : InvokeCallback { override fun onError(ex: Exception?) { @@ -310,17 +346,13 @@ class OnOffClientFragment : Fragment() { showMessage("${commandId.name} command success") } }, - getConnectedDevicePointer(), + devicePointer, invokeElement, 0, 0 ) } - private suspend fun getConnectedDevicePointer(): Long { - return ChipClient.getConnectedDevicePointer(requireContext(), addressUpdateFragment.deviceId) - } - private fun showMessage(msg: String) { requireActivity().runOnUiThread { binding.commandStatusTv.text = msg } } diff --git a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/OpCredClientFragment.kt b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/OpCredClientFragment.kt index 0314f9d82e652c..1fd8db6c97a13b 100644 --- a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/OpCredClientFragment.kt +++ b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/OpCredClientFragment.kt @@ -100,7 +100,13 @@ class OpCredClientFragment : Fragment() { val attributeId = attribute.id val devicePtr = - ChipClient.getConnectedDevicePointer(requireContext(), addressUpdateFragment.deviceId) + try { + ChipClient.getConnectedDevicePointer(requireContext(), addressUpdateFragment.deviceId) + } catch (e: IllegalStateException) { + Log.d(TAG, "getConnectedDevicePointer exception", e) + showMessage("Get DevicePointer fail!") + return + } ChipClient.getDeviceController(requireContext()) .readPath( @@ -137,7 +143,13 @@ class OpCredClientFragment : Fragment() { private suspend fun sendRemoveFabricsBtnClick(fabricIndex: UInt) { val devicePtr = - ChipClient.getConnectedDevicePointer(requireContext(), addressUpdateFragment.deviceId) + try { + ChipClient.getConnectedDevicePointer(requireContext(), addressUpdateFragment.deviceId) + } catch (e: IllegalStateException) { + Log.d(TAG, "getConnectedDevicePointer exception", e) + showMessage("Get DevicePointer fail!") + return + } // TODO : Need to be implement poj-to-tlv val tlvWriter = TlvWriter() tlvWriter.startStructure(AnonymousTag) diff --git a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/OtaProviderClientFragment.kt b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/OtaProviderClientFragment.kt index c27159193ed2dc..5d2d62ee76a690 100644 --- a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/OtaProviderClientFragment.kt +++ b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/OtaProviderClientFragment.kt @@ -114,6 +114,14 @@ class OtaProviderClientFragment : Fragment() { val attributeId = ClusterIDMapping.AccessControl.Attribute.Acl.id val attributePath = ChipAttributePath.newInstance(endpointId, clusterId, attributeId) + val devicePtr = + try { + ChipClient.getConnectedDevicePointer(requireContext(), addressUpdateFragment.deviceId) + } catch (e: IllegalStateException) { + Log.d(TAG, "getConnectedDevicePointer exception", e) + showMessage("Get DevicePointer fail!") + return + } deviceController.readAttributePath( object : ReportCallback { override fun onError( @@ -136,7 +144,7 @@ class OtaProviderClientFragment : Fragment() { requireActivity().runOnUiThread { showAddAccessControlDialog(tlv) } } }, - ChipClient.getConnectedDevicePointer(requireContext(), addressUpdateFragment.deviceId), + devicePtr, listOf(attributePath), 0 ) @@ -217,6 +225,15 @@ class OtaProviderClientFragment : Fragment() { newEntry.toTlv(AnonymousTag, tlvWriter) tlvWriter.endArray() + val devicePtr = + try { + ChipClient.getConnectedDevicePointer(requireContext(), addressUpdateFragment.deviceId) + } catch (e: IllegalStateException) { + Log.d(TAG, "getConnectedDevicePointer exception", e) + showMessage("Get DevicePointer fail!") + return + } + deviceController.write( object : WriteAttributesCallback { override fun onError(attributePath: ChipAttributePath?, e: Exception?) { @@ -229,7 +246,7 @@ class OtaProviderClientFragment : Fragment() { showMessage("$attributePath : Write response: $status") } }, - ChipClient.getConnectedDevicePointer(requireContext(), addressUpdateFragment.deviceId), + devicePtr, listOf( AttributeWriteRequest.newInstance( 0, @@ -249,6 +266,14 @@ class OtaProviderClientFragment : Fragment() { val clusterId = ClusterIDMapping.OtaSoftwareUpdateRequestor.ID val attributeId = attribute.id val path = ChipAttributePath.newInstance(endpointId, clusterId, attributeId) + val devicePtr = + try { + ChipClient.getConnectedDevicePointer(requireContext(), addressUpdateFragment.deviceId) + } catch (e: IllegalStateException) { + Log.d(TAG, "getConnectedDevicePointer exception", e) + showMessage("Get DevicePointer fail!") + return + } deviceController.readAttributePath( object : ReportCallback { override fun onError( @@ -279,7 +304,7 @@ class OtaProviderClientFragment : Fragment() { showMessage("OtaSoftwareUpdateRequestor ${attribute.name} value: $value") } }, - ChipClient.getConnectedDevicePointer(requireContext(), addressUpdateFragment.deviceId), + devicePtr, listOf(path), 0 ) @@ -344,6 +369,15 @@ class OtaProviderClientFragment : Fragment() { val writeRequest = AttributeWriteRequest.newInstance(endpoint, clusterId, attributeId, tlv) + val devicePtr = + try { + ChipClient.getConnectedDevicePointer(requireContext(), addressUpdateFragment.deviceId) + } catch (e: IllegalStateException) { + Log.d(TAG, "getConnectedDevicePointer exception", e) + showMessage("Get DevicePointer fail!") + return + } + deviceController.write( object : WriteAttributesCallback { override fun onError(attributePath: ChipAttributePath?, e: Exception?) { @@ -356,7 +390,7 @@ class OtaProviderClientFragment : Fragment() { showMessage("$attributePath : Write response: $status") } }, - ChipClient.getConnectedDevicePointer(requireContext(), addressUpdateFragment.deviceId), + devicePtr, listOf(writeRequest), 0, 0 @@ -461,11 +495,17 @@ class OtaProviderClientFragment : Fragment() { private suspend fun sendAnnounceOTAProviderBtnClick() { requireActivity().runOnUiThread { updateOTAStatusBtnClick() } + val devicePtr = + try { + ChipClient.getConnectedDevicePointer(requireContext(), addressUpdateFragment.deviceId) + } catch (e: IllegalStateException) { + Log.d(TAG, "getConnectedDevicePointer exception", e) + showMessage("Get DevicePointer fail!") + return + } + val otaRequestCluster = - ChipClusters.OtaSoftwareUpdateRequestorCluster( - ChipClient.getConnectedDevicePointer(requireContext(), addressUpdateFragment.deviceId), - OTA_REQUESTER_ENDPOINT_ID - ) + ChipClusters.OtaSoftwareUpdateRequestorCluster(devicePtr, OTA_REQUESTER_ENDPOINT_ID) otaRequestCluster.announceOTAProvider( object : DefaultClusterCallback { override fun onSuccess() { diff --git a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/SensorClientFragment.kt b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/SensorClientFragment.kt index cad12a5a54bc98..88d9ed63c4f91e 100644 --- a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/SensorClientFragment.kt +++ b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/SensorClientFragment.kt @@ -155,7 +155,13 @@ class SensorClientFragment : Fragment() { val clusterName = binding.clusterNameSpinner.selectedItem.toString() val clusterId = CLUSTERS[clusterName]!!["clusterId"] as Long val attributeId = CLUSTERS[clusterName]!!["attributeId"] as Long - val device = ChipClient.getConnectedDevicePointer(requireContext(), deviceId) + val device = + try { + ChipClient.getConnectedDevicePointer(requireContext(), deviceId) + } catch (e: IllegalStateException) { + Log.d(TAG, "getConnectedDevicePointer exception", e) + return + } val callback = makeReadCallback(clusterName, false) deviceController.readAttributePath( @@ -177,7 +183,13 @@ class SensorClientFragment : Fragment() { val clusterName = binding.clusterNameSpinner.selectedItem.toString() val clusterId = CLUSTERS[clusterName]!!["clusterId"] as Long val attributeId = CLUSTERS[clusterName]!!["attributeId"] as Long - val device = ChipClient.getConnectedDevicePointer(requireContext(), deviceId) + val device = + try { + ChipClient.getConnectedDevicePointer(requireContext(), deviceId) + } catch (e: IllegalStateException) { + Log.d(TAG, "getConnectedDevicePointer exception", e) + return + } val callback = makeReadCallback(clusterName, true) deviceController.subscribeToAttributePath( diff --git a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/WildcardFragment.kt b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/WildcardFragment.kt index af119581a7047f..5b49a6d9ab05ab 100644 --- a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/WildcardFragment.kt +++ b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/WildcardFragment.kt @@ -270,12 +270,18 @@ class WildcardFragment : Fragment() { "ResubscriptionAttempt terminationCause:$terminationCause, nextResubscribeIntervalMsec:$nextResubscribeIntervalMsec" ) } - + val devicePtr = + try { + ChipClient.getConnectedDevicePointer(requireContext(), addressUpdateFragment.deviceId) + } catch (e: IllegalStateException) { + Log.d(TAG, "getConnectedDevicePointer exception", e) + return + } deviceController.subscribeToPath( subscriptionEstablishedCallback, resubscriptionAttemptCallback, reportCallback, - ChipClient.getConnectedDevicePointer(requireContext(), addressUpdateFragment.deviceId), + devicePtr, attributePath.ifEmpty { null }, eventPath.ifEmpty { null }, minInterval, @@ -288,9 +294,16 @@ class WildcardFragment : Fragment() { } private suspend fun read(isFabricFiltered: Boolean, eventMin: Long?) { + val devicePtr = + try { + ChipClient.getConnectedDevicePointer(requireContext(), addressUpdateFragment.deviceId) + } catch (e: IllegalStateException) { + Log.d(TAG, "getConnectedDevicePointer exception", e) + return + } deviceController.readPath( reportCallback, - ChipClient.getConnectedDevicePointer(requireContext(), addressUpdateFragment.deviceId), + devicePtr, attributePath.ifEmpty { null }, eventPath.ifEmpty { null }, isFabricFiltered, @@ -351,10 +364,16 @@ class WildcardFragment : Fragment() { version ) } - + val devicePtr = + try { + addressUpdateFragment.getDevicePointer(requireContext()) + } catch (e: IllegalStateException) { + Log.d(TAG, "getDevicePointer exception", e) + return + } deviceController.write( writeAttributeCallback, - addressUpdateFragment.getDevicePointer(requireContext()), + devicePtr, listOf(writeRequest), timedRequestTimeoutMs, imTimeoutMs @@ -379,9 +398,16 @@ class WildcardFragment : Fragment() { } else { InvokeElement.newInstance(endpointId, clusterId, commandId, null, jsonString) } + val devicePtr = + try { + addressUpdateFragment.getDevicePointer(requireContext()) + } catch (e: IllegalStateException) { + Log.d(TAG, "getDevicePointer exception", e) + return + } deviceController.invoke( invokeCallback, - addressUpdateFragment.getDevicePointer(requireContext()), + devicePtr, invokeElement, timedRequestTimeoutMs, imTimeoutMs @@ -555,7 +581,13 @@ class WildcardFragment : Fragment() { val clusterId = 62L // OperationalCredentials val attributeId = 5L // CurrentFabricIndex val deviceId = addressUpdateFragment.deviceId - val devicePointer = ChipClient.getConnectedDevicePointer(context, deviceId) + val devicePointer = + try { + ChipClient.getConnectedDevicePointer(context, deviceId) + } catch (e: IllegalStateException) { + Log.d(TAG, "getConnectedDevicePointer exception", e) + return 0U + } return suspendCoroutine { cont -> deviceController.readAttributePath( object : ReportCallback { diff --git a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/clusterinteraction/ClusterDetailFragment.kt b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/clusterinteraction/ClusterDetailFragment.kt index eb14eee23770bd..09270003a41a5e 100644 --- a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/clusterinteraction/ClusterDetailFragment.kt +++ b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/clusterinteraction/ClusterDetailFragment.kt @@ -67,7 +67,15 @@ class ClusterDetailFragment : Fragment() { _binding = ClusterDetailFragmentBinding.inflate(inflater, container, false) scope = viewLifecycleOwner.lifecycleScope deviceId = checkNotNull(requireArguments().getLong(DEVICE_ID)) - scope.launch { devicePtr = getConnectedDevicePointer(requireContext(), deviceId) } + scope.launch { + try { + devicePtr = getConnectedDevicePointer(requireContext(), deviceId) + } catch (e: IllegalStateException) { + Log.d(TAG, "getConnectedDevicePointer exception", e) + showMessage("Get DevicePointer fail!") + return@launch + } + } endpointId = checkNotNull(requireArguments().getInt(ENDPOINT_ID_KEY)) historyCommand = requireArguments().getSerializable(HISTORY_COMMAND) as HistoryCommand? deviceController.setCompletionListener(GenericChipDeviceListener()) diff --git a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/clusterinteraction/ClusterInteractionFragment.kt b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/clusterinteraction/ClusterInteractionFragment.kt index d723a93b674f7f..8847da71b87271 100644 --- a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/clusterinteraction/ClusterInteractionFragment.kt +++ b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/clusterinteraction/ClusterInteractionFragment.kt @@ -1,6 +1,7 @@ package com.google.chip.chiptool.clusterclient.clusterinteraction import android.os.Bundle +import android.util.Log import android.view.LayoutInflater import android.view.View import android.view.ViewGroup @@ -45,7 +46,13 @@ class ClusterInteractionFragment : Fragment() { binding.getEndpointListBtn.setOnClickListener { scope.launch { devicePtr = - ChipClient.getConnectedDevicePointer(requireContext(), addressUpdateFragment.deviceId) + try { + ChipClient.getConnectedDevicePointer(requireContext(), addressUpdateFragment.deviceId) + } catch (e: IllegalStateException) { + Log.d(TAG, "getConnectedDevicePointer exception", e) + showMessage("getConnectedDevicePointer fail!") + return@launch + } showMessage("Retrieving endpoints") binding.endpointList.visibility = View.VISIBLE } From c4927d453ae7d1c63c44dc3f2acc6f67f7bed539 Mon Sep 17 00:00:00 2001 From: Andrei Litvin Date: Wed, 21 Feb 2024 22:23:08 -0500 Subject: [PATCH 051/385] Pull in EventLogging into src/app:app (#32230) * Pull in EventLogging into src/app:app * Fix typo * Restyle --------- Co-authored-by: Andrei Litvin --- .github/workflows/lint.yml | 2 -- src/app/BUILD.gn | 2 ++ 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index d811fe05fa888f..66405b9e615b6d 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -100,8 +100,6 @@ jobs: --known-failure app/CompatEnumNames.h \ --known-failure app/data-model/ListLargeSystemExtensions.h \ --known-failure app/EventHeader.h \ - --known-failure app/EventLoggingDelegate.h \ - --known-failure app/EventLogging.h \ --known-failure app/EventLoggingTypes.h \ --known-failure app/InteractionModelHelper.h \ --known-failure app/ReadClient.h \ diff --git a/src/app/BUILD.gn b/src/app/BUILD.gn index 3dfbbbffe56daf..ec520e005b0d80 100644 --- a/src/app/BUILD.gn +++ b/src/app/BUILD.gn @@ -233,6 +233,8 @@ static_library("app") { "DefaultAttributePersistenceProvider.h", "DeferredAttributePersistenceProvider.cpp", "DeferredAttributePersistenceProvider.h", + "EventLogging.h", + "EventLoggingDelegate.h", "EventManagement.cpp", "EventManagement.h", "FailSafeContext.cpp", From 8fbe0a71deb96ade73282558a583386b80dbcd5a Mon Sep 17 00:00:00 2001 From: Vivien Nicolas Date: Thu, 22 Feb 2024 04:24:44 +0100 Subject: [PATCH 052/385] [CI] Add --trace_decode supports when starting an accessory from a YAML test (#32221) --- .../pseudo_clusters/clusters/accessory_server_bridge.py | 3 +++ .../pseudo_clusters/clusters/system_commands.py | 1 + 2 files changed, 4 insertions(+) diff --git a/scripts/py_matter_yamltests/matter_yamltests/pseudo_clusters/clusters/accessory_server_bridge.py b/scripts/py_matter_yamltests/matter_yamltests/pseudo_clusters/clusters/accessory_server_bridge.py index a8991deb9b7870..15ebdf46428830 100644 --- a/scripts/py_matter_yamltests/matter_yamltests/pseudo_clusters/clusters/accessory_server_bridge.py +++ b/scripts/py_matter_yamltests/matter_yamltests/pseudo_clusters/clusters/accessory_server_bridge.py @@ -77,6 +77,9 @@ def _get_start_options(request): elif name == 'crashLogPath': options.append('--crash_log') options.append(str(value)) + elif name == 'traceDecode': + options.append('--trace_decode') + options.append(str(value)) elif name == 'registerKey': pass else: diff --git a/scripts/py_matter_yamltests/matter_yamltests/pseudo_clusters/clusters/system_commands.py b/scripts/py_matter_yamltests/matter_yamltests/pseudo_clusters/clusters/system_commands.py index 77028c39d72a9a..92bab169f7e0c6 100644 --- a/scripts/py_matter_yamltests/matter_yamltests/pseudo_clusters/clusters/system_commands.py +++ b/scripts/py_matter_yamltests/matter_yamltests/pseudo_clusters/clusters/system_commands.py @@ -33,6 +33,7 @@ +
From 5634f0622b9c96f8c7dca10584085b20f86c1323 Mon Sep 17 00:00:00 2001 From: doru91 Date: Thu, 22 Feb 2024 16:26:50 +0200 Subject: [PATCH 053/385] Enable LIT for NXP K32W0/K32W1 platforms (#32258) * [nxp][k32w0][k32w1][comtact-sensor] update zap file Boolean state cluster * enable missing mandatory attributes (EventList) General commissioning cluster * enable missing mandatory attributes (GeneratedCommandList, AcceptedCommandList, EventList, AttributeList, FeatureMap) Basic Information Cluster * enable missing mandatory attributes (GeneratedCommandList, AcceptedCommandList, EventList, AttributeList) General Diagnostics Cluster * enable mandatory attributes introduced in Matter 1.3 (UpTime, TimeSnapshot, TimeSnapshotResponse) * enable missing mandatory attributes (GeneratedCommandList, AcceptedCommandList, EventList, AttributeList) Network Commissioning Cluster * enable optional attributes introduced in Matter 1.3 (SupportedThreadFeatures, ThreadVersion) * update cluster revision * enable missing mandatory attributes (GeneratedCommandList, AcceptedCommandList, EventList, AttributeList) Thread Network Diagnostics: * update cluster revision Access Control * enable missing mandatory attributes (GeneratedCommandList, AcceptedCommandList, EventList, AttributeList) Signed-off-by: Doru Gucea * [nxp][k32w0][k32w1][contact-sensor] Refactor files for LIT enablement * examples/contact-sensor-app/nxp/zap was renamed to examples/contact-sensor-app/nxp/zap-sit * created a new set of zap files for lit: examples/contact-sensor-app/nxp/zap-lit * moved icd common defines to nxp_sdk.gni * fixed naming around icd parameters * added lit application code (see READMEs for detailed instructions) Signed-off-by: Doru Gucea * [nxp][k32w1] update software version allow configuration of CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION_STRING/ CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION through gn arguments. Signed-off-by: Doru Gucea * [nxp][k32w0][k32w1] fix restyle and readme Signed-off-by: Doru Gucea --------- Signed-off-by: Doru Gucea --- .../nxp/k32w/k32w0/BUILD.gn | 15 +- .../nxp/k32w/k32w0/README.md | 42 + .../nxp/k32w/k32w0/args.gni | 2 + .../nxp/k32w/k32w0/main/AppTask.cpp | 57 +- .../nxp/k32w/k32w0/main/include/AppTask.h | 4 + .../nxp/k32w/k32w0/main/include/app_config.h | 1 + .../nxp/k32w/k32w1/BUILD.gn | 13 +- .../nxp/k32w/k32w1/README.md | 54 +- .../nxp/k32w/k32w1/args.gni | 2 + .../k32w/k32w1/include/CHIPProjectConfig.h | 4 +- .../nxp/k32w/k32w1/main/AppTask.cpp | 43 + .../nxp/k32w/k32w1/main/include/AppTask.h | 4 + .../nxp/k32w/k32w1/main/include/app_config.h | 1 + .../nxp/{zap => zap-lit}/BUILD.gn | 2 +- .../nxp/zap-lit/contact-sensor-app.matter | 1687 +++++++ .../nxp/zap-lit/contact-sensor-app.zap | 4161 +++++++++++++++++ .../contact-sensor-app/nxp/zap-sit/BUILD.gn | 25 + .../contact-sensor-app.matter | 33 +- .../{zap => zap-sit}/contact-sensor-app.zap | 475 +- .../k32w/k32w1/include/CHIPProjectConfig.h | 4 +- .../nxp/k32w/k32w0/CHIPPlatformConfig.h | 4 +- .../nxp/k32w/k32w1/CHIPPlatformConfig.h | 4 +- third_party/nxp/k32w0_sdk/k32w0_sdk.gni | 25 +- third_party/nxp/k32w1_sdk/k32w1_sdk.gni | 26 +- third_party/nxp/nxp_sdk.gni | 11 +- 25 files changed, 6636 insertions(+), 63 deletions(-) rename examples/contact-sensor-app/nxp/{zap => zap-lit}/BUILD.gn (96%) create mode 100644 examples/contact-sensor-app/nxp/zap-lit/contact-sensor-app.matter create mode 100644 examples/contact-sensor-app/nxp/zap-lit/contact-sensor-app.zap create mode 100644 examples/contact-sensor-app/nxp/zap-sit/BUILD.gn rename examples/contact-sensor-app/nxp/{zap => zap-sit}/contact-sensor-app.matter (97%) rename examples/contact-sensor-app/nxp/{zap => zap-sit}/contact-sensor-app.zap (88%) diff --git a/examples/contact-sensor-app/nxp/k32w/k32w0/BUILD.gn b/examples/contact-sensor-app/nxp/k32w/k32w0/BUILD.gn index cc87b4fc1532d6..c9b50a84ceb770 100644 --- a/examples/contact-sensor-app/nxp/k32w/k32w0/BUILD.gn +++ b/examples/contact-sensor-app/nxp/k32w/k32w0/BUILD.gn @@ -19,6 +19,7 @@ import("//build_overrides/openthread.gni") import("${k32w0_sdk_build_root}/k32w0_executable.gni") import("${k32w0_sdk_build_root}/k32w0_sdk.gni") +import("${chip_root}/src/app/icd/icd.gni") import("${chip_root}/src/crypto/crypto.gni") import("${chip_root}/src/lib/core/core.gni") import("${chip_root}/src/platform/device.gni") @@ -75,6 +76,8 @@ k32w0_sdk("sdk") { k32w0_executable("contact_sensor_app") { output_name = "chip-k32w0x-contact-example" + defines = [] + sources = [ "${k32w0_platform_dir}/util/LEDWidget.cpp", "${k32w0_platform_dir}/util/include/LEDWidget.h", @@ -93,13 +96,12 @@ k32w0_executable("contact_sensor_app") { "${k32w0_platform_dir}/common/CustomFactoryDataProvider.h", ] - defines = [ "CHIP_DEVICE_CONFIG_USE_CUSTOM_PROVIDER=1" ] + defines += [ "CHIP_DEVICE_CONFIG_USE_CUSTOM_PROVIDER=1" ] } deps = [ ":sdk", "${chip_root}/examples/common/QRCode", - "${chip_root}/examples/contact-sensor-app/contact-sensor-common", "${chip_root}/examples/providers:device_info_provider", "${chip_root}/src/lib", "${chip_root}/src/platform:syscalls_stub", @@ -119,6 +121,15 @@ k32w0_executable("contact_sensor_app") { ] } + #lit and sit are using different zap files + if (chip_enable_icd_lit) { + deps += [ "${chip_root}/examples/contact-sensor-app/nxp/zap-lit/" ] + + defines += [ "CHIP_ENABLE_LIT=1" ] + } else { + deps += [ "${chip_root}/examples/contact-sensor-app/nxp/zap-sit/" ] + } + cflags = [ "-Wconversion" ] output_dir = root_out_dir diff --git a/examples/contact-sensor-app/nxp/k32w/k32w0/README.md b/examples/contact-sensor-app/nxp/k32w/k32w0/README.md index 27ae15b672eb05..c325895886a093 100644 --- a/examples/contact-sensor-app/nxp/k32w/k32w0/README.md +++ b/examples/contact-sensor-app/nxp/k32w/k32w0/README.md @@ -22,6 +22,7 @@ network. - [Building](#building) - [Overwrite board config files](#overwrite-board-config-files) - [Known issues building](#known-issues-building) +- [Long Idle Time ICD Support](#long-idle-time-icd-support) - [Manufacturing data](#manufacturing-data) - [Flashing and debugging](#flashing-and-debugging) - [Pigweed Tokenizer](#pigweed-tokenizer) @@ -95,6 +96,11 @@ be discoverable over Bluetooth LE. For security reasons, you must start Bluetooth LE advertising manually after powering up the device by pressing Button USERINTERFACE. +## LIT ICD Active Mode + +If the device is acting as a LIT ICD and it's already commissioned, then Button +USERINTERFACE can be pressed for forcing the switch to Active Mode. + ### Bluetooth LE Rendezvous In this example, the commissioning procedure (called rendezvous) is done over @@ -258,6 +264,42 @@ pycryptodome 3.9.8 The resulting output file can be found in out/debug/chip-k32w0x-contact-example. +## Long Idle Time ICD Support + +By default, contact-sensor is compiled as SIT ICD (Short Idle Time +Intermittently Connected Device) - see rules from k32w0_sdk.gni: + +``` +chip_ot_idle_interval_ms = 2000 # 2s Idle Intervals +chip_ot_active_interval_ms = 500 # 500ms Active Intervals + +nxp_idle_mode_duration_s = 600 # 10min Idle Mode Interval +nxp_active_mode_duration_ms = 10000 # 10s Active Mode Interval +nxp_active_mode_threshold_ms = 1000 # 1s Active Mode Threshold +nxp_icd_supported_clients_per_fabric = 2 # 2 registration slots per fabric +``` + +If LIT ICD support is needed then `chip_enable_icd_lit=true` must be specified +as gn argument and the above parameters can be modified to comply with LIT +requirements (e.g.: LIT devices must configure +`chip_ot_idle_interval_ms > 15000`). Example LIT configuration: + +``` +chip_ot_idle_interval_ms = 15000 # 15s Idle Intervals +chip_ot_active_interval_ms = 500 # 500ms Active Intervals + +nxp_idle_mode_duration_s = 3600 # 60min Idle Mode Interval +nxp_active_mode_duration_ms = 0 # 0 Active Mode Interval +nxp_active_mode_threshold_ms = 30000 # 30s Active Mode Threshold +``` + +ICD parameters that may be disabled once LIT functionality is enabled: + +``` +chip_persist_subscriptions: try to re-establish subscriptions from the server side after reboot +chip_subscription_timeout_resumption: same as above but retries are using a Fibonacci backoff +``` + ### Overwrite board config files The example uses template/reference board configuration files. diff --git a/examples/contact-sensor-app/nxp/k32w/k32w0/args.gni b/examples/contact-sensor-app/nxp/k32w/k32w0/args.gni index 02a388daab9e1a..6e931d00452fcd 100644 --- a/examples/contact-sensor-app/nxp/k32w/k32w0/args.gni +++ b/examples/contact-sensor-app/nxp/k32w/k32w0/args.gni @@ -24,5 +24,7 @@ chip_stack_lock_tracking = "fatal" chip_enable_ble = true chip_enable_icd_server = true +chip_enable_icd_lit = false +icd_enforce_sit_slow_poll_limit = true chip_persist_subscriptions = true chip_subscription_timeout_resumption = true diff --git a/examples/contact-sensor-app/nxp/k32w/k32w0/main/AppTask.cpp b/examples/contact-sensor-app/nxp/k32w/k32w0/main/AppTask.cpp index a46ea5db28df64..17aea9d5897907 100644 --- a/examples/contact-sensor-app/nxp/k32w/k32w0/main/AppTask.cpp +++ b/examples/contact-sensor-app/nxp/k32w/k32w0/main/AppTask.cpp @@ -71,6 +71,9 @@ static LEDWidget sContactSensorLED; static bool sIsThreadProvisioned = false; static bool sHaveBLEConnections = false; +#if CHIP_ENABLE_LIT +static bool sIsDeviceCommissioned = false; +#endif static uint32_t eventMask = 0; @@ -448,6 +451,12 @@ void AppTask::ButtonEventHandler(uint8_t pin_no, uint8_t button_action) { button_event.Handler = ResetActionEventHandler; } +#endif +#if CHIP_ENABLE_LIT + if (button_action == USER_ACTIVE_MODE_TRIGGER_PUSH) + { + button_event.Handler = UserActiveModeHandler; + } #endif } @@ -486,6 +495,16 @@ void AppTask::HandleKeyboard(void) #if (defined OM15082) ButtonEventHandler(RESET_BUTTON, RESET_BUTTON_PUSH); break; +#elif CHIP_ENABLE_LIT + if (sIsDeviceCommissioned) + { + ButtonEventHandler(BLE_BUTTON, USER_ACTIVE_MODE_TRIGGER_PUSH); + } + else + { + ButtonEventHandler(BLE_BUTTON, BLE_BUTTON_PUSH); + } + break; #else ButtonEventHandler(BLE_BUTTON, BLE_BUTTON_PUSH); break; @@ -497,7 +516,15 @@ void AppTask::HandleKeyboard(void) ButtonEventHandler(OTA_BUTTON, OTA_BUTTON_PUSH); break; case gKBD_EventPB4_c: - ButtonEventHandler(BLE_BUTTON, BLE_BUTTON_PUSH); +#if CHIP_ENABLE_LIT + if (sIsDeviceCommissioned) + { + ButtonEventHandler(BLE_BUTTON, USER_ACTIVE_MODE_TRIGGER_PUSH); + } + else +#endif + + ButtonEventHandler(BLE_BUTTON, BLE_BUTTON_PUSH); break; #if !(defined OM15082) case gKBD_EventLongPB1_c: @@ -694,6 +721,28 @@ void AppTask::BleStartAdvertising(intptr_t arg) } } +#if CHIP_ENABLE_LIT +void AppTask::UserActiveModeHandler(void * aGenericEvent) +{ + AppEvent * aEvent = (AppEvent *) aGenericEvent; + + if (aEvent->ButtonEvent.PinNo != BLE_BUTTON) + return; + + if (sAppTask.mFunction != Function::kNoneSelected) + { + K32W_LOG("Another function is scheduled. Could not request ICD Active Mode!"); + return; + } + PlatformMgr().ScheduleWork(AppTask::UserActiveModeTrigger, 0); +} + +void AppTask::UserActiveModeTrigger(intptr_t arg) +{ + ICDNotifier::GetInstance().NotifyNetworkActivityNotification(); +} +#endif + void AppTask::MatterEventHandler(const ChipDeviceEvent * event, intptr_t) { if (event->Type == DeviceEventType::kServiceProvisioningChange && event->ServiceProvisioningChange.IsServiceProvisioned) @@ -707,6 +756,12 @@ void AppTask::MatterEventHandler(const ChipDeviceEvent * event, intptr_t) sIsThreadProvisioned = FALSE; } } +#if CHIP_ENABLE_LIT + else if (event->Type == DeviceEventType::kCommissioningComplete) + { + sIsDeviceCommissioned = TRUE; + } +#endif #if CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR if (event->Type == DeviceEventType::kDnssdInitialized) diff --git a/examples/contact-sensor-app/nxp/k32w/k32w0/main/include/AppTask.h b/examples/contact-sensor-app/nxp/k32w/k32w0/main/include/AppTask.h index 867a496de1e56d..c3203d78eb543e 100644 --- a/examples/contact-sensor-app/nxp/k32w/k32w0/main/include/AppTask.h +++ b/examples/contact-sensor-app/nxp/k32w/k32w0/main/include/AppTask.h @@ -85,6 +85,10 @@ class AppTask static void ContactActionEventHandler(void * aGenericEvent); static void ResetActionEventHandler(void * aGenericEvent); static void InstallEventHandler(void * aGenericEvent); +#if CHIP_ENABLE_LIT + static void UserActiveModeHandler(void * aGenericEvent); + static void UserActiveModeTrigger(intptr_t arg); +#endif static void ButtonEventHandler(uint8_t pin_no, uint8_t button_action); static void TimerEventHandler(TimerHandle_t xTimer); diff --git a/examples/contact-sensor-app/nxp/k32w/k32w0/main/include/app_config.h b/examples/contact-sensor-app/nxp/k32w/k32w0/main/include/app_config.h index 5343e1e56a3af9..61b9866055c1b5 100644 --- a/examples/contact-sensor-app/nxp/k32w/k32w0/main/include/app_config.h +++ b/examples/contact-sensor-app/nxp/k32w/k32w0/main/include/app_config.h @@ -31,6 +31,7 @@ #define CONTACT_SENSOR_BUTTON_PUSH 2 #define OTA_BUTTON_PUSH 3 #define BLE_BUTTON_PUSH 4 +#define USER_ACTIVE_MODE_TRIGGER_PUSH 5 #define APP_BUTTON_PUSH 1 diff --git a/examples/contact-sensor-app/nxp/k32w/k32w1/BUILD.gn b/examples/contact-sensor-app/nxp/k32w/k32w1/BUILD.gn index ed49c7bdd4f7a3..e44c1a9c71bd40 100644 --- a/examples/contact-sensor-app/nxp/k32w/k32w1/BUILD.gn +++ b/examples/contact-sensor-app/nxp/k32w/k32w1/BUILD.gn @@ -23,6 +23,7 @@ import("${nxp_sdk_build_root}/${nxp_sdk_name}/nxp_executable.gni") import("${nxp_sdk_build_root}/${nxp_sdk_name}/${nxp_sdk_name}.gni") +import("${chip_root}/src/app/icd/icd.gni") import("${chip_root}/src/crypto/crypto.gni") import("${chip_root}/src/lib/core/core.gni") import("${chip_root}/src/platform/device.gni") @@ -74,6 +75,8 @@ k32w1_sdk("sdk") { k32w1_executable("contact_sensor_app") { output_name = "chip-k32w1-contact-example" + defines = [] + sources = [ "${k32w1_platform_dir}/util/LEDWidget.cpp", "${k32w1_platform_dir}/util/include/LEDWidget.h", @@ -89,7 +92,6 @@ k32w1_executable("contact_sensor_app") { deps = [ ":sdk", "${chip_root}/examples/common/QRCode", - "${chip_root}/examples/contact-sensor-app/nxp/zap", "${chip_root}/examples/providers:device_info_provider", "${chip_root}/src/lib", "${chip_root}/src/platform:syscalls_stub", @@ -109,6 +111,15 @@ k32w1_executable("contact_sensor_app") { ] } + #lit and sit are using different zap files + if (chip_enable_icd_lit) { + deps += [ "${chip_root}/examples/contact-sensor-app/nxp/zap-lit/" ] + + defines += [ "CHIP_ENABLE_LIT=1" ] + } else { + deps += [ "${chip_root}/examples/contact-sensor-app/nxp/zap-sit/" ] + } + cflags = [ "-Wconversion" ] output_dir = root_out_dir diff --git a/examples/contact-sensor-app/nxp/k32w/k32w1/README.md b/examples/contact-sensor-app/nxp/k32w/k32w1/README.md index 28983f45c89578..ff3496d7b862ac 100644 --- a/examples/contact-sensor-app/nxp/k32w/k32w1/README.md +++ b/examples/contact-sensor-app/nxp/k32w/k32w1/README.md @@ -19,6 +19,7 @@ into an existing Matter network and can be controlled by this network. - [Bluetooth LE Rendezvous](#bluetooth-le-rendezvous) - [Device UI](#device-ui) - [Building](#building) +- [Long Idle Time ICD Support](#long-idle-time-icd-support) - [Manufacturing data](#manufacturing-data) - [Flashing](#flashing) - [Flashing the NBU image](#flashing-the-nbu-image) @@ -100,13 +101,15 @@ will not work. **RGB LED** shows the state of the simulated contact sensor. when the LED is lit, the sensor is contacted, when not lit, the sensor is non-contacted. -**Button SW2** can be used to start BLE advertising. A SHORT press of the button -will enable Bluetooth LE advertising for a predefined period of time. A LONG -Press Button SW2 initiates a factory reset. After an initial period of 3 -seconds, LED 2 and RGB LED will flash in unison to signal the pending reset. -After 6 seconds will cause the device to reset its persistent configuration and -initiate a reboot. The reset action can be cancelled by press SW2 button at any -point before the 6 second limit. +**Button SW2**. SHORT press function is overloaded depending on the device type +and commissioning state. If the device is not commissioned, a SHORT press of the +button will enable Bluetooth LE advertising for a predefined period of time. If +the device is commissioned and is acting as a LIT ICD then a SHORT press of the +button will enable Active Mode. A LONG Press of Button SW2 initiates a factory +reset. After an initial period of 3 seconds, LED 2 and RGB LED will flash in +unison to signal the pending reset. After 6 seconds will cause the device to +reset its persistent configuration and initiate a reboot. The reset action can +be cancelled by press SW2 button at any point before the 6 second limit. **Button SW3** can be used to change the state of the simulated contact sensor. The button behaves as a toggle, swapping the state every time it is short @@ -141,6 +144,43 @@ After a successful build, the `elf` and `srec` files are found in `out/debug/` - build, the `elf` and `srec` files are found in `out/debug/` - `see the files prefixed with chip-k32w1-contact-example`. +## Long Idle Time ICD Support + +By default, contact-sensor is compiled as SIT ICD (Short Idle Time +Intermittently Connected Device) - see rules from k32w1_sdk.gni: + +``` +chip_ot_idle_interval_ms = 2000 # 2s Idle Intervals +chip_ot_active_interval_ms = 500 # 500ms Active Intervals + +nxp_idle_mode_duration_s = 600 # 10min Idle Mode Interval +nxp_active_mode_duration_ms = 10000 # 10s Active Mode Interval +nxp_active_mode_threshold_ms = 1000 # 1s Active Mode Threshold +nxp_icd_supported_clients_per_fabric = 2 # 2 registration slots per fabric +``` + +If LIT ICD support is needed then `chip_enable_icd_lit=true` must be specified +as gn argument and the above parameters can be modified to comply with LIT +requirements (e.g.: LIT devices must configure +`chip_ot_idle_interval_ms > 15000`). Example LIT configuration: + +``` +chip_ot_idle_interval_ms = 15000 # 15s Idle Intervals +chip_ot_active_interval_ms = 500 # 500ms Active Intervals + +nxp_idle_mode_duration_s = 3600 # 60min Idle Mode Interval +nxp_active_mode_duration_ms = 0 # 0 Active Mode Interval +nxp_active_mode_threshold_ms = 30000 # 30s Active Mode Threshold +``` + +ICD parameters that may be disabled once LIT functionality is enabled: + +``` +chip_persist_subscriptions: try once to re-establish subscriptions from the server side after reboot +chip_subscription_timeout_resumption: same as above + try to re-establish timeout out subscriptions +using Fibonacci backoff for retries pacing. +``` + ## Manufacturing data Use `chip_with_factory_data=1` in the gn build command to enable factory data. diff --git a/examples/contact-sensor-app/nxp/k32w/k32w1/args.gni b/examples/contact-sensor-app/nxp/k32w/k32w1/args.gni index 18c41cb457bc86..b25f000cd85d1c 100644 --- a/examples/contact-sensor-app/nxp/k32w/k32w1/args.gni +++ b/examples/contact-sensor-app/nxp/k32w/k32w1/args.gni @@ -24,5 +24,7 @@ chip_stack_lock_tracking = "fatal" chip_enable_ble = true chip_enable_icd_server = true +chip_enable_icd_lit = false +icd_enforce_sit_slow_poll_limit = true chip_persist_subscriptions = true chip_subscription_timeout_resumption = true diff --git a/examples/contact-sensor-app/nxp/k32w/k32w1/include/CHIPProjectConfig.h b/examples/contact-sensor-app/nxp/k32w/k32w1/include/CHIPProjectConfig.h index 8846799ed6edc9..808b70aad0cab7 100644 --- a/examples/contact-sensor-app/nxp/k32w/k32w1/include/CHIPProjectConfig.h +++ b/examples/contact-sensor-app/nxp/k32w/k32w1/include/CHIPProjectConfig.h @@ -132,11 +132,11 @@ * {MAJOR_VERSION}.0d{MINOR_VERSION} */ #ifndef CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION_STRING -#define CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION_STRING "03-2022-te8" +#define CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION_STRING NXP_CONFIG_DEVICE_SOFTWARE_VERSION_STRING #endif #ifndef CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION -#define CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION 42020 +#define CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION NXP_CONFIG_DEVICE_SOFTWARE_VERSION #endif #ifndef CHIP_DEVICE_CONFIG_DEVICE_VENDOR_NAME diff --git a/examples/contact-sensor-app/nxp/k32w/k32w1/main/AppTask.cpp b/examples/contact-sensor-app/nxp/k32w/k32w1/main/AppTask.cpp index 10039bb8c9270e..3e9380254bd428 100644 --- a/examples/contact-sensor-app/nxp/k32w/k32w1/main/AppTask.cpp +++ b/examples/contact-sensor-app/nxp/k32w/k32w1/main/AppTask.cpp @@ -78,6 +78,9 @@ static LEDWidget sContactSensorLED; static bool sIsThreadProvisioned = false; static bool sHaveBLEConnections = false; +#if CHIP_ENABLE_LIT +static bool sIsDeviceCommissioned = false; +#endif static uint32_t eventMask = 0; @@ -398,6 +401,12 @@ void AppTask::ButtonEventHandler(uint8_t pin_no, uint8_t button_action) { button_event.Handler = ResetActionEventHandler; } +#if CHIP_ENABLE_LIT + else if (button_action == USER_ACTIVE_MODE_TRIGGER_PUSH) + { + button_event.Handler = UserActiveModeHandler; + } +#endif } sAppTask.PostEvent(&button_event); @@ -418,6 +427,12 @@ button_status_t AppTask::KBD_Callback(void * buttonHandle, button_callback_messa { ButtonEventHandler(BLE_BUTTON, RESET_BUTTON_PUSH); } +#if CHIP_ENABLE_LIT + else if (sIsDeviceCommissioned) + { + ButtonEventHandler(BLE_BUTTON, USER_ACTIVE_MODE_TRIGGER_PUSH); + } +#endif else { ButtonEventHandler(BLE_BUTTON, BLE_BUTTON_PUSH); @@ -616,6 +631,28 @@ void AppTask::BleStartAdvertising(intptr_t arg) } } +#if CHIP_ENABLE_LIT +void AppTask::UserActiveModeHandler(void * aGenericEvent) +{ + AppEvent * aEvent = (AppEvent *) aGenericEvent; + + if (aEvent->ButtonEvent.PinNo != BLE_BUTTON) + return; + + if (sAppTask.mFunction != Function::kNoneSelected) + { + K32W_LOG("Another function is scheduled. Could not request ICD Active Mode!"); + return; + } + PlatformMgr().ScheduleWork(AppTask::UserActiveModeTrigger, 0); +} + +void AppTask::UserActiveModeTrigger(intptr_t arg) +{ + ICDNotifier::GetInstance().NotifyNetworkActivityNotification(); +} +#endif + void AppTask::MatterEventHandler(const ChipDeviceEvent * event, intptr_t) { if (event->Type == DeviceEventType::kServiceProvisioningChange && event->ServiceProvisioningChange.IsServiceProvisioned) @@ -629,6 +666,12 @@ void AppTask::MatterEventHandler(const ChipDeviceEvent * event, intptr_t) sIsThreadProvisioned = FALSE; } } +#if CHIP_ENABLE_LIT + else if (event->Type == DeviceEventType::kCommissioningComplete) + { + sIsDeviceCommissioned = TRUE; + } +#endif #if CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR if (event->Type == DeviceEventType::kDnssdInitialized) diff --git a/examples/contact-sensor-app/nxp/k32w/k32w1/main/include/AppTask.h b/examples/contact-sensor-app/nxp/k32w/k32w1/main/include/AppTask.h index bc19b0a9862ebd..2338131f06c4b0 100644 --- a/examples/contact-sensor-app/nxp/k32w/k32w1/main/include/AppTask.h +++ b/examples/contact-sensor-app/nxp/k32w/k32w1/main/include/AppTask.h @@ -87,6 +87,10 @@ class AppTask static void ContactActionEventHandler(void * aGenericEvent); static void ResetActionEventHandler(void * aGenericEvent); static void InstallEventHandler(void * aGenericEvent); +#if CHIP_ENABLE_LIT + static void UserActiveModeHandler(void * aGenericEvent); + static void UserActiveModeTrigger(intptr_t arg); +#endif static void ButtonEventHandler(uint8_t pin_no, uint8_t button_action); static void TimerEventHandler(TimerHandle_t xTimer); diff --git a/examples/contact-sensor-app/nxp/k32w/k32w1/main/include/app_config.h b/examples/contact-sensor-app/nxp/k32w/k32w1/main/include/app_config.h index fbcf14fe7d88d7..7001f636dbd0d7 100644 --- a/examples/contact-sensor-app/nxp/k32w/k32w1/main/include/app_config.h +++ b/examples/contact-sensor-app/nxp/k32w/k32w1/main/include/app_config.h @@ -30,6 +30,7 @@ #define CONTACT_SENSOR_BUTTON_PUSH 2 #define SOFT_RESET_BUTTON_PUSH 3 #define BLE_BUTTON_PUSH 4 +#define USER_ACTIVE_MODE_TRIGGER_PUSH 5 #define APP_BUTTON_PUSH 1 diff --git a/examples/contact-sensor-app/nxp/zap/BUILD.gn b/examples/contact-sensor-app/nxp/zap-lit/BUILD.gn similarity index 96% rename from examples/contact-sensor-app/nxp/zap/BUILD.gn rename to examples/contact-sensor-app/nxp/zap-lit/BUILD.gn index be4913cf3552ee..7adfcbb7790a35 100644 --- a/examples/contact-sensor-app/nxp/zap/BUILD.gn +++ b/examples/contact-sensor-app/nxp/zap-lit/BUILD.gn @@ -16,7 +16,7 @@ import("//build_overrides/chip.gni") import("${chip_root}/examples/common/pigweed/pigweed_rpcs.gni") import("${chip_root}/src/app/chip_data_model.gni") -chip_data_model("zap") { +chip_data_model("zap-lit") { zap_file = "contact-sensor-app.zap" zap_pregenerated_dir = diff --git a/examples/contact-sensor-app/nxp/zap-lit/contact-sensor-app.matter b/examples/contact-sensor-app/nxp/zap-lit/contact-sensor-app.matter new file mode 100644 index 00000000000000..9a6eeb77ef10f2 --- /dev/null +++ b/examples/contact-sensor-app/nxp/zap-lit/contact-sensor-app.matter @@ -0,0 +1,1687 @@ +// This IDL was generated automatically by ZAP. +// It is for view/code review purposes only. + +/** Attributes and commands for putting a device into Identification mode (e.g. flashing a light). */ +cluster Identify = 3 { + revision 4; + + enum EffectIdentifierEnum : enum8 { + kBlink = 0; + kBreathe = 1; + kOkay = 2; + kChannelChange = 11; + kFinishEffect = 254; + kStopEffect = 255; + } + + enum EffectVariantEnum : enum8 { + kDefault = 0; + } + + enum IdentifyTypeEnum : enum8 { + kNone = 0; + kLightOutput = 1; + kVisibleIndicator = 2; + kAudibleBeep = 3; + kDisplay = 4; + kActuator = 5; + } + + attribute int16u identifyTime = 0; + readonly attribute IdentifyTypeEnum identifyType = 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 IdentifyRequest { + int16u identifyTime = 0; + } + + request struct TriggerEffectRequest { + EffectIdentifierEnum effectIdentifier = 0; + EffectVariantEnum effectVariant = 1; + } + + /** Command description for Identify */ + command access(invoke: manage) Identify(IdentifyRequest): DefaultSuccess = 0; + /** Command description for TriggerEffect */ + command access(invoke: manage) TriggerEffect(TriggerEffectRequest): DefaultSuccess = 64; +} + +/** The Descriptor Cluster is meant to replace the support from the Zigbee Device Object (ZDO) for describing a node, its endpoints and clusters. */ +cluster Descriptor = 29 { + revision 2; + + bitmap Feature : bitmap32 { + kTagList = 0x1; + } + + struct DeviceTypeStruct { + devtype_id deviceType = 0; + int16u revision = 1; + } + + struct SemanticTagStruct { + nullable vendor_id mfgCode = 0; + enum8 namespaceID = 1; + enum8 tag = 2; + optional nullable char_string label = 3; + } + + readonly attribute DeviceTypeStruct deviceTypeList[] = 0; + readonly attribute cluster_id serverList[] = 1; + readonly attribute cluster_id clientList[] = 2; + readonly attribute endpoint_no partsList[] = 3; + readonly attribute optional SemanticTagStruct tagList[] = 4; + 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; +} + +/** The Access Control Cluster exposes a data model view of a + Node's Access Control List (ACL), which codifies the rules used to manage + and enforce Access Control for the Node's endpoints and their associated + cluster instances. */ +cluster AccessControl = 31 { + revision 1; // NOTE: Default/not specifically set + + enum AccessControlEntryAuthModeEnum : enum8 { + kPASE = 1; + kCASE = 2; + kGroup = 3; + } + + enum AccessControlEntryPrivilegeEnum : enum8 { + kView = 1; + kProxyView = 2; + kOperate = 3; + kManage = 4; + kAdminister = 5; + } + + enum ChangeTypeEnum : enum8 { + kChanged = 0; + kAdded = 1; + kRemoved = 2; + } + + struct AccessControlTargetStruct { + nullable cluster_id cluster = 0; + nullable endpoint_no endpoint = 1; + nullable devtype_id deviceType = 2; + } + + fabric_scoped struct AccessControlEntryStruct { + fabric_sensitive AccessControlEntryPrivilegeEnum privilege = 1; + fabric_sensitive AccessControlEntryAuthModeEnum authMode = 2; + nullable fabric_sensitive int64u subjects[] = 3; + nullable fabric_sensitive AccessControlTargetStruct targets[] = 4; + fabric_idx fabricIndex = 254; + } + + fabric_scoped struct AccessControlExtensionStruct { + fabric_sensitive octet_string<128> data = 1; + fabric_idx fabricIndex = 254; + } + + fabric_sensitive info event access(read: administer) AccessControlEntryChanged = 0 { + nullable node_id adminNodeID = 1; + nullable int16u adminPasscodeID = 2; + ChangeTypeEnum changeType = 3; + nullable AccessControlEntryStruct latestValue = 4; + fabric_idx fabricIndex = 254; + } + + fabric_sensitive info event access(read: administer) AccessControlExtensionChanged = 1 { + nullable node_id adminNodeID = 1; + nullable int16u adminPasscodeID = 2; + ChangeTypeEnum changeType = 3; + nullable AccessControlExtensionStruct latestValue = 4; + fabric_idx fabricIndex = 254; + } + + attribute access(read: administer, write: administer) AccessControlEntryStruct acl[] = 0; + attribute access(read: administer, write: administer) optional AccessControlExtensionStruct extension[] = 1; + readonly attribute int16u subjectsPerAccessControlEntry = 2; + readonly attribute int16u targetsPerAccessControlEntry = 3; + readonly attribute int16u accessControlEntriesPerFabric = 4; + 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 provides attributes and events for determining basic information about Nodes, which supports both + Commissioning and operational determination of Node characteristics, such as Vendor ID, Product ID and serial number, + which apply to the whole Node. Also allows setting user device information such as location. */ +cluster BasicInformation = 40 { + revision 3; + + enum ColorEnum : enum8 { + kBlack = 0; + kNavy = 1; + kGreen = 2; + kTeal = 3; + kMaroon = 4; + kPurple = 5; + kOlive = 6; + kGray = 7; + kBlue = 8; + kLime = 9; + kAqua = 10; + kRed = 11; + kFuchsia = 12; + kYellow = 13; + kWhite = 14; + kNickel = 15; + kChrome = 16; + kBrass = 17; + kCopper = 18; + kSilver = 19; + kGold = 20; + } + + enum ProductFinishEnum : enum8 { + kOther = 0; + kMatte = 1; + kSatin = 2; + kPolished = 3; + kRugged = 4; + kFabric = 5; + } + + struct CapabilityMinimaStruct { + int16u caseSessionsPerFabric = 0; + int16u subscriptionsPerFabric = 1; + } + + struct ProductAppearanceStruct { + ProductFinishEnum finish = 0; + nullable ColorEnum primaryColor = 1; + } + + critical event StartUp = 0 { + int32u softwareVersion = 0; + } + + critical event ShutDown = 1 { + } + + info event Leave = 2 { + fabric_idx fabricIndex = 0; + } + + info event ReachableChanged = 3 { + boolean reachableNewValue = 0; + } + + readonly attribute int16u dataModelRevision = 0; + readonly attribute char_string<32> vendorName = 1; + readonly attribute vendor_id vendorID = 2; + readonly attribute char_string<32> productName = 3; + readonly attribute int16u productID = 4; + attribute access(write: manage) char_string<32> nodeLabel = 5; + attribute access(write: administer) char_string<2> location = 6; + readonly attribute int16u hardwareVersion = 7; + readonly attribute char_string<64> hardwareVersionString = 8; + readonly attribute int32u softwareVersion = 9; + readonly attribute char_string<64> softwareVersionString = 10; + readonly attribute optional char_string<16> manufacturingDate = 11; + readonly attribute optional char_string<32> partNumber = 12; + readonly attribute optional long_char_string<256> productURL = 13; + readonly attribute optional char_string<64> productLabel = 14; + readonly attribute optional char_string<32> serialNumber = 15; + attribute access(write: manage) optional boolean localConfigDisabled = 16; + readonly attribute optional boolean reachable = 17; + readonly attribute optional char_string<32> uniqueID = 18; + readonly attribute CapabilityMinimaStruct capabilityMinima = 19; + readonly attribute optional ProductAppearanceStruct productAppearance = 20; + readonly attribute int32u specificationVersion = 21; + readonly attribute int16u maxPathsPerInvoke = 22; + 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; + + command MfgSpecificPing(): DefaultSuccess = 0; +} + +/** Provides an interface for providing OTA software updates */ +cluster OtaSoftwareUpdateProvider = 41 { + revision 1; // NOTE: Default/not specifically set + + enum ApplyUpdateActionEnum : enum8 { + kProceed = 0; + kAwaitNextAction = 1; + kDiscontinue = 2; + } + + enum DownloadProtocolEnum : enum8 { + kBDXSynchronous = 0; + kBDXAsynchronous = 1; + kHTTPS = 2; + kVendorSpecific = 3; + } + + enum StatusEnum : enum8 { + kUpdateAvailable = 0; + kBusy = 1; + kNotAvailable = 2; + kDownloadProtocolNotSupported = 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; + + request struct QueryImageRequest { + vendor_id vendorID = 0; + int16u productID = 1; + int32u softwareVersion = 2; + DownloadProtocolEnum protocolsSupported[] = 3; + optional int16u hardwareVersion = 4; + optional char_string<2> location = 5; + optional boolean requestorCanConsent = 6; + optional octet_string<512> metadataForProvider = 7; + } + + response struct QueryImageResponse = 1 { + StatusEnum status = 0; + optional int32u delayedActionTime = 1; + optional char_string<256> imageURI = 2; + optional int32u softwareVersion = 3; + optional char_string<64> softwareVersionString = 4; + optional octet_string<32> updateToken = 5; + optional boolean userConsentNeeded = 6; + optional octet_string<512> metadataForRequestor = 7; + } + + request struct ApplyUpdateRequestRequest { + octet_string<32> updateToken = 0; + int32u newVersion = 1; + } + + response struct ApplyUpdateResponse = 3 { + ApplyUpdateActionEnum action = 0; + int32u delayedActionTime = 1; + } + + request struct NotifyUpdateAppliedRequest { + octet_string<32> updateToken = 0; + int32u softwareVersion = 1; + } + + /** Determine availability of a new Software Image */ + command QueryImage(QueryImageRequest): QueryImageResponse = 0; + /** Determine next action to take for a downloaded Software Image */ + command ApplyUpdateRequest(ApplyUpdateRequestRequest): ApplyUpdateResponse = 2; + /** Notify OTA Provider that an update was applied */ + command NotifyUpdateApplied(NotifyUpdateAppliedRequest): DefaultSuccess = 4; +} + +/** Provides an interface for downloading and applying OTA software updates */ +cluster OtaSoftwareUpdateRequestor = 42 { + revision 1; // NOTE: Default/not specifically set + + enum AnnouncementReasonEnum : enum8 { + kSimpleAnnouncement = 0; + kUpdateAvailable = 1; + kUrgentUpdateAvailable = 2; + } + + enum ChangeReasonEnum : enum8 { + kUnknown = 0; + kSuccess = 1; + kFailure = 2; + kTimeOut = 3; + kDelayByProvider = 4; + } + + enum UpdateStateEnum : enum8 { + kUnknown = 0; + kIdle = 1; + kQuerying = 2; + kDelayedOnQuery = 3; + kDownloading = 4; + kApplying = 5; + kDelayedOnApply = 6; + kRollingBack = 7; + kDelayedOnUserConsent = 8; + } + + fabric_scoped struct ProviderLocation { + node_id providerNodeID = 1; + endpoint_no endpoint = 2; + fabric_idx fabricIndex = 254; + } + + info event StateTransition = 0 { + UpdateStateEnum previousState = 0; + UpdateStateEnum newState = 1; + ChangeReasonEnum reason = 2; + nullable int32u targetSoftwareVersion = 3; + } + + critical event VersionApplied = 1 { + int32u softwareVersion = 0; + int16u productID = 1; + } + + info event DownloadError = 2 { + int32u softwareVersion = 0; + int64u bytesDownloaded = 1; + nullable int8u progressPercent = 2; + nullable int64s platformCode = 3; + } + + attribute access(write: administer) ProviderLocation defaultOTAProviders[] = 0; + readonly attribute boolean updatePossible = 1; + readonly attribute UpdateStateEnum updateState = 2; + readonly attribute nullable int8u updateStateProgress = 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; + + request struct AnnounceOTAProviderRequest { + node_id providerNodeID = 0; + vendor_id vendorID = 1; + AnnouncementReasonEnum announcementReason = 2; + optional octet_string<512> metadataForNode = 3; + endpoint_no endpoint = 4; + } + + /** Announce the presence of an OTA Provider */ + command AnnounceOTAProvider(AnnounceOTAProviderRequest): DefaultSuccess = 0; +} + +/** This cluster is used to manage global aspects of the Commissioning flow. */ +cluster GeneralCommissioning = 48 { + revision 1; // NOTE: Default/not specifically set + + enum CommissioningErrorEnum : enum8 { + kOK = 0; + kValueOutsideRange = 1; + kInvalidAuthentication = 2; + kNoFailSafe = 3; + kBusyWithOtherAdmin = 4; + } + + enum RegulatoryLocationTypeEnum : enum8 { + kIndoor = 0; + kOutdoor = 1; + kIndoorOutdoor = 2; + } + + struct BasicCommissioningInfo { + int16u failSafeExpiryLengthSeconds = 0; + int16u maxCumulativeFailsafeSeconds = 1; + } + + attribute access(write: administer) int64u breadcrumb = 0; + readonly attribute BasicCommissioningInfo basicCommissioningInfo = 1; + readonly attribute RegulatoryLocationTypeEnum regulatoryConfig = 2; + readonly attribute RegulatoryLocationTypeEnum locationCapability = 3; + readonly attribute boolean supportsConcurrentConnection = 4; + 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 ArmFailSafeRequest { + int16u expiryLengthSeconds = 0; + int64u breadcrumb = 1; + } + + response struct ArmFailSafeResponse = 1 { + CommissioningErrorEnum errorCode = 0; + char_string<128> debugText = 1; + } + + request struct SetRegulatoryConfigRequest { + RegulatoryLocationTypeEnum newRegulatoryConfig = 0; + char_string<2> countryCode = 1; + int64u breadcrumb = 2; + } + + response struct SetRegulatoryConfigResponse = 3 { + CommissioningErrorEnum errorCode = 0; + char_string debugText = 1; + } + + response struct CommissioningCompleteResponse = 5 { + CommissioningErrorEnum errorCode = 0; + char_string debugText = 1; + } + + /** Arm the persistent fail-safe timer with an expiry time of now + ExpiryLengthSeconds using device clock */ + command access(invoke: administer) ArmFailSafe(ArmFailSafeRequest): ArmFailSafeResponse = 0; + /** Set the regulatory configuration to be used during commissioning */ + command access(invoke: administer) SetRegulatoryConfig(SetRegulatoryConfigRequest): SetRegulatoryConfigResponse = 2; + /** Signals the Server that the Client has successfully completed all steps of Commissioning/Recofiguration needed during fail-safe period. */ + fabric command access(invoke: administer) CommissioningComplete(): CommissioningCompleteResponse = 4; +} + +/** Functionality to configure, enable, disable network credentials and access on a Matter device. */ +cluster NetworkCommissioning = 49 { + revision 1; // NOTE: Default/not specifically set + + enum NetworkCommissioningStatusEnum : enum8 { + kSuccess = 0; + kOutOfRange = 1; + kBoundsExceeded = 2; + kNetworkIDNotFound = 3; + kDuplicateNetworkID = 4; + kNetworkNotFound = 5; + kRegulatoryError = 6; + kAuthFailure = 7; + kUnsupportedSecurity = 8; + kOtherConnectionFailure = 9; + kIPV6Failed = 10; + kIPBindFailed = 11; + kUnknownError = 12; + } + + enum WiFiBandEnum : enum8 { + k2G4 = 0; + k3G65 = 1; + k5G = 2; + k6G = 3; + k60G = 4; + k1G = 5; + } + + bitmap Feature : bitmap32 { + kWiFiNetworkInterface = 0x1; + kThreadNetworkInterface = 0x2; + kEthernetNetworkInterface = 0x4; + kPerDeviceCredentials = 0x8; + } + + bitmap ThreadCapabilitiesBitmap : bitmap16 { + kIsBorderRouterCapable = 0x1; + kIsRouterCapable = 0x2; + kIsSleepyEndDeviceCapable = 0x4; + kIsFullThreadDevice = 0x8; + kIsSynchronizedSleepyEndDeviceCapable = 0x10; + } + + bitmap WiFiSecurityBitmap : bitmap8 { + kUnencrypted = 0x1; + kWEP = 0x2; + kWPAPersonal = 0x4; + kWPA2Personal = 0x8; + kWPA3Personal = 0x10; + kWPA3MatterPDC = 0x20; + } + + struct NetworkInfoStruct { + octet_string<32> networkID = 0; + boolean connected = 1; + optional nullable octet_string<20> networkIdentifier = 2; + optional nullable octet_string<20> clientIdentifier = 3; + } + + struct ThreadInterfaceScanResultStruct { + int16u panId = 0; + int64u extendedPanId = 1; + char_string<16> networkName = 2; + int16u channel = 3; + int8u version = 4; + octet_string<8> extendedAddress = 5; + int8s rssi = 6; + int8u lqi = 7; + } + + struct WiFiInterfaceScanResultStruct { + WiFiSecurityBitmap security = 0; + octet_string<32> ssid = 1; + octet_string<6> bssid = 2; + int16u channel = 3; + WiFiBandEnum wiFiBand = 4; + int8s rssi = 5; + } + + readonly attribute access(read: administer) int8u maxNetworks = 0; + readonly attribute access(read: administer) NetworkInfoStruct networks[] = 1; + readonly attribute optional int8u scanMaxTimeSeconds = 2; + readonly attribute optional int8u connectMaxTimeSeconds = 3; + attribute access(write: administer) boolean interfaceEnabled = 4; + readonly attribute access(read: administer) nullable NetworkCommissioningStatusEnum lastNetworkingStatus = 5; + readonly attribute access(read: administer) nullable octet_string<32> lastNetworkID = 6; + readonly attribute access(read: administer) nullable int32s lastConnectErrorValue = 7; + readonly attribute optional WiFiBandEnum supportedWiFiBands[] = 8; + readonly attribute optional ThreadCapabilitiesBitmap supportedThreadFeatures = 9; + readonly attribute optional int16u threadVersion = 10; + 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 ScanNetworksRequest { + optional nullable octet_string<32> ssid = 0; + optional int64u breadcrumb = 1; + } + + response struct ScanNetworksResponse = 1 { + NetworkCommissioningStatusEnum networkingStatus = 0; + optional char_string debugText = 1; + optional WiFiInterfaceScanResultStruct wiFiScanResults[] = 2; + optional ThreadInterfaceScanResultStruct threadScanResults[] = 3; + } + + request struct AddOrUpdateWiFiNetworkRequest { + octet_string<32> ssid = 0; + octet_string<64> credentials = 1; + optional int64u breadcrumb = 2; + optional octet_string<140> networkIdentity = 3; + optional octet_string<20> clientIdentifier = 4; + optional octet_string<32> possessionNonce = 5; + } + + request struct AddOrUpdateThreadNetworkRequest { + octet_string<254> operationalDataset = 0; + optional int64u breadcrumb = 1; + } + + request struct RemoveNetworkRequest { + octet_string<32> networkID = 0; + optional int64u breadcrumb = 1; + } + + response struct NetworkConfigResponse = 5 { + NetworkCommissioningStatusEnum networkingStatus = 0; + optional char_string<512> debugText = 1; + optional int8u networkIndex = 2; + optional octet_string<140> clientIdentity = 3; + optional octet_string<64> possessionSignature = 4; + } + + request struct ConnectNetworkRequest { + octet_string<32> networkID = 0; + optional int64u breadcrumb = 1; + } + + response struct ConnectNetworkResponse = 7 { + NetworkCommissioningStatusEnum networkingStatus = 0; + optional char_string debugText = 1; + nullable int32s errorValue = 2; + } + + request struct ReorderNetworkRequest { + octet_string<32> networkID = 0; + int8u networkIndex = 1; + optional int64u breadcrumb = 2; + } + + request struct QueryIdentityRequest { + octet_string<20> keyIdentifier = 0; + optional octet_string<32> possessionNonce = 1; + } + + response struct QueryIdentityResponse = 10 { + octet_string<140> identity = 0; + optional octet_string<64> possessionSignature = 1; + } + + /** Detemine the set of networks the device sees as available. */ + command access(invoke: administer) ScanNetworks(ScanNetworksRequest): ScanNetworksResponse = 0; + /** Add or update the credentials for a given Wi-Fi network. */ + command access(invoke: administer) AddOrUpdateWiFiNetwork(AddOrUpdateWiFiNetworkRequest): NetworkConfigResponse = 2; + /** Add or update the credentials for a given Thread network. */ + command access(invoke: administer) AddOrUpdateThreadNetwork(AddOrUpdateThreadNetworkRequest): NetworkConfigResponse = 3; + /** Remove the definition of a given network (including its credentials). */ + command access(invoke: administer) RemoveNetwork(RemoveNetworkRequest): NetworkConfigResponse = 4; + /** Connect to the specified network, using previously-defined credentials. */ + command access(invoke: administer) ConnectNetwork(ConnectNetworkRequest): ConnectNetworkResponse = 6; + /** Modify the order in which networks will be presented in the Networks attribute. */ + command access(invoke: administer) ReorderNetwork(ReorderNetworkRequest): NetworkConfigResponse = 8; + /** Retrieve details about and optionally proof of possession of a network client identity. */ + command access(invoke: administer) QueryIdentity(QueryIdentityRequest): QueryIdentityResponse = 9; +} + +/** 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; + + enum BootReasonEnum : enum8 { + kUnspecified = 0; + kPowerOnReboot = 1; + kBrownOutReset = 2; + kSoftwareWatchdogReset = 3; + kHardwareWatchdogReset = 4; + kSoftwareUpdateCompleted = 5; + kSoftwareReset = 6; + } + + enum HardwareFaultEnum : enum8 { + kUnspecified = 0; + kRadio = 1; + kSensor = 2; + kResettableOverTemp = 3; + kNonResettableOverTemp = 4; + kPowerSource = 5; + kVisualDisplayFault = 6; + kAudioOutputFault = 7; + kUserInterfaceFault = 8; + kNonVolatileMemoryError = 9; + kTamperDetected = 10; + } + + enum InterfaceTypeEnum : enum8 { + kUnspecified = 0; + kWiFi = 1; + kEthernet = 2; + kCellular = 3; + kThread = 4; + } + + enum NetworkFaultEnum : enum8 { + kUnspecified = 0; + kHardwareFailure = 1; + kNetworkJammed = 2; + kConnectionFailed = 3; + } + + enum RadioFaultEnum : enum8 { + kUnspecified = 0; + kWiFiFault = 1; + kCellularFault = 2; + kThreadFault = 3; + kNFCFault = 4; + kBLEFault = 5; + kEthernetFault = 6; + } + + bitmap Feature : bitmap32 { + kDataModelTest = 0x1; + } + + struct NetworkInterface { + char_string<32> name = 0; + boolean isOperational = 1; + nullable boolean offPremiseServicesReachableIPv4 = 2; + nullable boolean offPremiseServicesReachableIPv6 = 3; + octet_string<8> hardwareAddress = 4; + octet_string IPv4Addresses[] = 5; + octet_string IPv6Addresses[] = 6; + InterfaceTypeEnum type = 7; + } + + critical event HardwareFaultChange = 0 { + HardwareFaultEnum current[] = 0; + HardwareFaultEnum previous[] = 1; + } + + critical event RadioFaultChange = 1 { + RadioFaultEnum current[] = 0; + RadioFaultEnum previous[] = 1; + } + + critical event NetworkFaultChange = 2 { + NetworkFaultEnum current[] = 0; + NetworkFaultEnum previous[] = 1; + } + + critical event BootReason = 3 { + BootReasonEnum bootReason = 0; + } + + readonly attribute NetworkInterface networkInterfaces[] = 0; + readonly attribute int16u rebootCount = 1; + readonly attribute optional int64u upTime = 2; + readonly attribute optional int32u totalOperationalHours = 3; + readonly attribute optional BootReasonEnum bootReason = 4; + readonly attribute optional HardwareFaultEnum activeHardwareFaults[] = 5; + readonly attribute optional RadioFaultEnum activeRadioFaults[] = 6; + readonly attribute optional NetworkFaultEnum activeNetworkFaults[] = 7; + readonly attribute boolean testEventTriggersEnabled = 8; + 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 TestEventTriggerRequest { + octet_string<16> enableKey = 0; + int64u eventTrigger = 1; + } + + response struct TimeSnapshotResponse = 2 { + systime_ms systemTimeMs = 0; + nullable posix_ms posixTimeMs = 1; + } + + request struct PayloadTestRequestRequest { + octet_string<16> enableKey = 0; + int8u value = 1; + int16u count = 2; + } + + response struct PayloadTestResponse = 4 { + octet_string payload = 0; + } + + /** Provide a means for certification tests to trigger some test-plan-specific events */ + command access(invoke: manage) TestEventTrigger(TestEventTriggerRequest): DefaultSuccess = 0; + /** Take a snapshot of system time and epoch time. */ + command TimeSnapshot(): TimeSnapshotResponse = 1; + /** Request a variable length payload response. */ + 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 Thread 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 ThreadNetworkDiagnostics = 53 { + revision 1; // NOTE: Default/not specifically set + + enum ConnectionStatusEnum : enum8 { + kConnected = 0; + kNotConnected = 1; + } + + enum NetworkFaultEnum : enum8 { + kUnspecified = 0; + kLinkDown = 1; + kHardwareFailure = 2; + kNetworkJammed = 3; + } + + enum RoutingRoleEnum : enum8 { + kUnspecified = 0; + kUnassigned = 1; + kSleepyEndDevice = 2; + kEndDevice = 3; + kREED = 4; + kRouter = 5; + kLeader = 6; + } + + bitmap Feature : bitmap32 { + kPacketCounts = 0x1; + kErrorCounts = 0x2; + kMLECounts = 0x4; + kMACCounts = 0x8; + } + + struct NeighborTableStruct { + int64u extAddress = 0; + int32u age = 1; + int16u rloc16 = 2; + int32u linkFrameCounter = 3; + int32u mleFrameCounter = 4; + int8u lqi = 5; + nullable int8s averageRssi = 6; + nullable int8s lastRssi = 7; + int8u frameErrorRate = 8; + int8u messageErrorRate = 9; + boolean rxOnWhenIdle = 10; + boolean fullThreadDevice = 11; + boolean fullNetworkData = 12; + boolean isChild = 13; + } + + struct OperationalDatasetComponents { + boolean activeTimestampPresent = 0; + boolean pendingTimestampPresent = 1; + boolean masterKeyPresent = 2; + boolean networkNamePresent = 3; + boolean extendedPanIdPresent = 4; + boolean meshLocalPrefixPresent = 5; + boolean delayPresent = 6; + boolean panIdPresent = 7; + boolean channelPresent = 8; + boolean pskcPresent = 9; + boolean securityPolicyPresent = 10; + boolean channelMaskPresent = 11; + } + + struct RouteTableStruct { + int64u extAddress = 0; + int16u rloc16 = 1; + int8u routerId = 2; + int8u nextHop = 3; + int8u pathCost = 4; + int8u LQIIn = 5; + int8u LQIOut = 6; + int8u age = 7; + boolean allocated = 8; + boolean linkEstablished = 9; + } + + struct SecurityPolicy { + int16u rotationTime = 0; + int16u flags = 1; + } + + info event ConnectionStatus = 0 { + ConnectionStatusEnum connectionStatus = 0; + } + + info event NetworkFaultChange = 1 { + NetworkFaultEnum current[] = 0; + NetworkFaultEnum previous[] = 1; + } + + readonly attribute nullable int16u channel = 0; + readonly attribute nullable RoutingRoleEnum routingRole = 1; + readonly attribute nullable char_string<16> networkName = 2; + readonly attribute nullable int16u panId = 3; + readonly attribute nullable int64u extendedPanId = 4; + readonly attribute nullable octet_string<17> meshLocalPrefix = 5; + readonly attribute optional int64u overrunCount = 6; + readonly attribute NeighborTableStruct neighborTable[] = 7; + readonly attribute RouteTableStruct routeTable[] = 8; + readonly attribute nullable int32u partitionId = 9; + readonly attribute nullable int16u weighting = 10; + readonly attribute nullable int16u dataVersion = 11; + readonly attribute nullable int16u stableDataVersion = 12; + readonly attribute nullable int8u leaderRouterId = 13; + readonly attribute optional int16u detachedRoleCount = 14; + readonly attribute optional int16u childRoleCount = 15; + readonly attribute optional int16u routerRoleCount = 16; + readonly attribute optional int16u leaderRoleCount = 17; + readonly attribute optional int16u attachAttemptCount = 18; + readonly attribute optional int16u partitionIdChangeCount = 19; + readonly attribute optional int16u betterPartitionAttachAttemptCount = 20; + readonly attribute optional int16u parentChangeCount = 21; + readonly attribute optional int32u txTotalCount = 22; + readonly attribute optional int32u txUnicastCount = 23; + readonly attribute optional int32u txBroadcastCount = 24; + readonly attribute optional int32u txAckRequestedCount = 25; + readonly attribute optional int32u txAckedCount = 26; + readonly attribute optional int32u txNoAckRequestedCount = 27; + readonly attribute optional int32u txDataCount = 28; + readonly attribute optional int32u txDataPollCount = 29; + readonly attribute optional int32u txBeaconCount = 30; + readonly attribute optional int32u txBeaconRequestCount = 31; + readonly attribute optional int32u txOtherCount = 32; + readonly attribute optional int32u txRetryCount = 33; + readonly attribute optional int32u txDirectMaxRetryExpiryCount = 34; + readonly attribute optional int32u txIndirectMaxRetryExpiryCount = 35; + readonly attribute optional int32u txErrCcaCount = 36; + readonly attribute optional int32u txErrAbortCount = 37; + readonly attribute optional int32u txErrBusyChannelCount = 38; + readonly attribute optional int32u rxTotalCount = 39; + readonly attribute optional int32u rxUnicastCount = 40; + readonly attribute optional int32u rxBroadcastCount = 41; + readonly attribute optional int32u rxDataCount = 42; + readonly attribute optional int32u rxDataPollCount = 43; + readonly attribute optional int32u rxBeaconCount = 44; + readonly attribute optional int32u rxBeaconRequestCount = 45; + readonly attribute optional int32u rxOtherCount = 46; + readonly attribute optional int32u rxAddressFilteredCount = 47; + readonly attribute optional int32u rxDestAddrFilteredCount = 48; + readonly attribute optional int32u rxDuplicatedCount = 49; + readonly attribute optional int32u rxErrNoFrameCount = 50; + readonly attribute optional int32u rxErrUnknownNeighborCount = 51; + readonly attribute optional int32u rxErrInvalidSrcAddrCount = 52; + readonly attribute optional int32u rxErrSecCount = 53; + readonly attribute optional int32u rxErrFcsCount = 54; + readonly attribute optional int32u rxErrOtherCount = 55; + readonly attribute optional nullable int64u activeTimestamp = 56; + readonly attribute optional nullable int64u pendingTimestamp = 57; + readonly attribute optional nullable int32u delay = 58; + readonly attribute nullable SecurityPolicy securityPolicy = 59; + readonly attribute nullable octet_string<4> channelPage0Mask = 60; + readonly attribute nullable OperationalDatasetComponents operationalDatasetComponents = 61; + readonly attribute NetworkFaultEnum activeNetworkFaultsList[] = 62; + 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 OverrunCount attributes to 0 */ + command access(invoke: manage) ResetCounts(): DefaultSuccess = 0; +} + +/** Commands to trigger a Node to allow a new Administrator to commission it. */ +cluster AdministratorCommissioning = 60 { + revision 1; // NOTE: Default/not specifically set + + enum CommissioningWindowStatusEnum : enum8 { + kWindowNotOpen = 0; + kEnhancedWindowOpen = 1; + kBasicWindowOpen = 2; + } + + enum StatusCode : enum8 { + kBusy = 2; + kPAKEParameterError = 3; + kWindowNotOpen = 4; + } + + bitmap Feature : bitmap32 { + kBasic = 0x1; + } + + readonly attribute CommissioningWindowStatusEnum windowStatus = 0; + readonly attribute nullable fabric_idx adminFabricIndex = 1; + readonly attribute nullable vendor_id adminVendorId = 2; + 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 OpenCommissioningWindowRequest { + int16u commissioningTimeout = 0; + octet_string PAKEPasscodeVerifier = 1; + int16u discriminator = 2; + int32u iterations = 3; + octet_string<32> salt = 4; + } + + request struct OpenBasicCommissioningWindowRequest { + int16u commissioningTimeout = 0; + } + + /** This command is used by a current Administrator to instruct a Node to go into commissioning mode using enhanced commissioning method. */ + timed command access(invoke: administer) OpenCommissioningWindow(OpenCommissioningWindowRequest): DefaultSuccess = 0; + /** This command is used by a current Administrator to instruct a Node to go into commissioning mode using basic commissioning method, if the node supports it. */ + timed command access(invoke: administer) OpenBasicCommissioningWindow(OpenBasicCommissioningWindowRequest): DefaultSuccess = 1; + /** This command is used by a current Administrator to instruct a Node to revoke any active Open Commissioning Window or Open Basic Commissioning Window command. */ + timed command access(invoke: administer) RevokeCommissioning(): DefaultSuccess = 2; +} + +/** This cluster is used to add or remove Operational Credentials on a Commissionee or Node, as well as manage the associated Fabrics. */ +cluster OperationalCredentials = 62 { + revision 1; // NOTE: Default/not specifically set + + enum CertificateChainTypeEnum : enum8 { + kDACCertificate = 1; + kPAICertificate = 2; + } + + enum NodeOperationalCertStatusEnum : enum8 { + kOK = 0; + kInvalidPublicKey = 1; + kInvalidNodeOpId = 2; + kInvalidNOC = 3; + kMissingCsr = 4; + kTableFull = 5; + kInvalidAdminSubject = 6; + kFabricConflict = 9; + kLabelConflict = 10; + kInvalidFabricIndex = 11; + } + + fabric_scoped struct FabricDescriptorStruct { + octet_string<65> rootPublicKey = 1; + vendor_id vendorID = 2; + fabric_id fabricID = 3; + node_id nodeID = 4; + char_string<32> label = 5; + fabric_idx fabricIndex = 254; + } + + fabric_scoped struct NOCStruct { + fabric_sensitive octet_string noc = 1; + nullable fabric_sensitive octet_string icac = 2; + fabric_idx fabricIndex = 254; + } + + readonly attribute access(read: administer) NOCStruct NOCs[] = 0; + readonly attribute FabricDescriptorStruct fabrics[] = 1; + readonly attribute int8u supportedFabrics = 2; + readonly attribute int8u commissionedFabrics = 3; + readonly attribute octet_string trustedRootCertificates[] = 4; + readonly attribute int8u currentFabricIndex = 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 AttestationRequestRequest { + octet_string<32> attestationNonce = 0; + } + + response struct AttestationResponse = 1 { + octet_string<900> attestationElements = 0; + octet_string<64> attestationSignature = 1; + } + + request struct CertificateChainRequestRequest { + CertificateChainTypeEnum certificateType = 0; + } + + response struct CertificateChainResponse = 3 { + octet_string<600> certificate = 0; + } + + request struct CSRRequestRequest { + octet_string<32> CSRNonce = 0; + optional boolean isForUpdateNOC = 1; + } + + response struct CSRResponse = 5 { + octet_string NOCSRElements = 0; + octet_string attestationSignature = 1; + } + + request struct AddNOCRequest { + octet_string<400> NOCValue = 0; + optional octet_string<400> ICACValue = 1; + octet_string<16> IPKValue = 2; + int64u caseAdminSubject = 3; + vendor_id adminVendorId = 4; + } + + request struct UpdateNOCRequest { + octet_string NOCValue = 0; + optional octet_string ICACValue = 1; + } + + response struct NOCResponse = 8 { + NodeOperationalCertStatusEnum statusCode = 0; + optional fabric_idx fabricIndex = 1; + optional char_string<128> debugText = 2; + } + + request struct UpdateFabricLabelRequest { + char_string<32> label = 0; + } + + request struct RemoveFabricRequest { + fabric_idx fabricIndex = 0; + } + + request struct AddTrustedRootCertificateRequest { + octet_string rootCACertificate = 0; + } + + /** Sender is requesting attestation information from the receiver. */ + command access(invoke: administer) AttestationRequest(AttestationRequestRequest): AttestationResponse = 0; + /** Sender is requesting a device attestation certificate from the receiver. */ + command access(invoke: administer) CertificateChainRequest(CertificateChainRequestRequest): CertificateChainResponse = 2; + /** Sender is requesting a certificate signing request (CSR) from the receiver. */ + command access(invoke: administer) CSRRequest(CSRRequestRequest): CSRResponse = 4; + /** Sender is requesting to add the new node operational certificates. */ + command access(invoke: administer) AddNOC(AddNOCRequest): NOCResponse = 6; + /** Sender is requesting to update the node operational certificates. */ + fabric command access(invoke: administer) UpdateNOC(UpdateNOCRequest): NOCResponse = 7; + /** This command SHALL be used by an Administrative Node to set the user-visible Label field for a given Fabric, as reflected by entries in the Fabrics attribute. */ + fabric command access(invoke: administer) UpdateFabricLabel(UpdateFabricLabelRequest): NOCResponse = 9; + /** This command is used by Administrative Nodes to remove a given fabric index and delete all associated fabric-scoped data. */ + command access(invoke: administer) RemoveFabric(RemoveFabricRequest): NOCResponse = 10; + /** This command SHALL add a Trusted Root CA Certificate, provided as its CHIP Certificate representation. */ + command access(invoke: administer) AddTrustedRootCertificate(AddTrustedRootCertificateRequest): DefaultSuccess = 11; +} + +/** The Group Key Management Cluster is the mechanism by which group keys are managed. */ +cluster GroupKeyManagement = 63 { + revision 1; // NOTE: Default/not specifically set + + enum GroupKeySecurityPolicyEnum : enum8 { + kTrustFirst = 0; + kCacheAndSync = 1; + } + + bitmap Feature : bitmap32 { + kCacheAndSync = 0x1; + } + + fabric_scoped struct GroupInfoMapStruct { + group_id groupId = 1; + endpoint_no endpoints[] = 2; + optional char_string<16> groupName = 3; + fabric_idx fabricIndex = 254; + } + + fabric_scoped struct GroupKeyMapStruct { + group_id groupId = 1; + int16u groupKeySetID = 2; + fabric_idx fabricIndex = 254; + } + + struct GroupKeySetStruct { + int16u groupKeySetID = 0; + GroupKeySecurityPolicyEnum groupKeySecurityPolicy = 1; + nullable octet_string<16> epochKey0 = 2; + nullable epoch_us epochStartTime0 = 3; + nullable octet_string<16> epochKey1 = 4; + nullable epoch_us epochStartTime1 = 5; + nullable octet_string<16> epochKey2 = 6; + nullable epoch_us epochStartTime2 = 7; + } + + attribute access(write: manage) GroupKeyMapStruct groupKeyMap[] = 0; + readonly attribute GroupInfoMapStruct groupTable[] = 1; + readonly attribute int16u maxGroupsPerFabric = 2; + readonly attribute int16u maxGroupKeysPerFabric = 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; + + request struct KeySetWriteRequest { + GroupKeySetStruct groupKeySet = 0; + } + + request struct KeySetReadRequest { + int16u groupKeySetID = 0; + } + + response struct KeySetReadResponse = 2 { + GroupKeySetStruct groupKeySet = 0; + } + + request struct KeySetRemoveRequest { + int16u groupKeySetID = 0; + } + + response struct KeySetReadAllIndicesResponse = 5 { + int16u groupKeySetIDs[] = 0; + } + + /** Write a new set of keys for the given key set id. */ + fabric command access(invoke: administer) KeySetWrite(KeySetWriteRequest): DefaultSuccess = 0; + /** Read the keys for a given key set id. */ + fabric command access(invoke: administer) KeySetRead(KeySetReadRequest): KeySetReadResponse = 1; + /** Revoke a Root Key from a Group */ + fabric command access(invoke: administer) KeySetRemove(KeySetRemoveRequest): DefaultSuccess = 3; + /** Return the list of Group Key Sets associated with the accessing fabric */ + fabric command access(invoke: administer) KeySetReadAllIndices(): KeySetReadAllIndicesResponse = 4; +} + +/** This cluster provides an interface to a boolean state called StateValue. */ +cluster BooleanState = 69 { + revision 1; + + info event StateChange = 0 { + boolean stateValue = 0; + } + + readonly attribute boolean stateValue = 0; + 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; +} + +/** Allows servers to ensure that listed clients are notified when a server is available for communication. */ +cluster IcdManagement = 70 { + revision 2; + + enum OperatingModeEnum : enum8 { + kSIT = 0; + kLIT = 1; + } + + bitmap Feature : bitmap32 { + kCheckInProtocolSupport = 0x1; + kUserActiveModeTrigger = 0x2; + kLongIdleTimeSupport = 0x4; + } + + bitmap UserActiveModeTriggerBitmap : bitmap32 { + kPowerCycle = 0x1; + kSettingsMenu = 0x2; + kCustomInstruction = 0x4; + kDeviceManual = 0x8; + kActuateSensor = 0x10; + kActuateSensorSeconds = 0x20; + kActuateSensorTimes = 0x40; + kActuateSensorLightsBlink = 0x80; + kResetButton = 0x100; + kResetButtonLightsBlink = 0x200; + kResetButtonSeconds = 0x400; + kResetButtonTimes = 0x800; + kSetupButton = 0x1000; + kSetupButtonSeconds = 0x2000; + kSetupButtonLightsBlink = 0x4000; + kSetupButtonTimes = 0x8000; + kAppDefinedButton = 0x10000; + } + + fabric_scoped struct MonitoringRegistrationStruct { + fabric_sensitive node_id checkInNodeID = 1; + fabric_sensitive int64u monitoredSubject = 2; + fabric_idx fabricIndex = 254; + } + + readonly attribute int32u idleModeDuration = 0; + readonly attribute int32u activeModeDuration = 1; + readonly attribute int16u activeModeThreshold = 2; + readonly attribute access(read: administer) optional MonitoringRegistrationStruct registeredClients[] = 3; + readonly attribute access(read: administer) optional int32u ICDCounter = 4; + readonly attribute optional int16u clientsSupportedPerFabric = 5; + readonly attribute optional UserActiveModeTriggerBitmap userActiveModeTriggerHint = 6; + readonly attribute optional char_string<128> userActiveModeTriggerInstruction = 7; + readonly attribute optional OperatingModeEnum operatingMode = 8; + 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 RegisterClientRequest { + node_id checkInNodeID = 0; + int64u monitoredSubject = 1; + octet_string<16> key = 2; + optional octet_string<16> verificationKey = 3; + } + + response struct RegisterClientResponse = 1 { + int32u ICDCounter = 0; + } + + request struct UnregisterClientRequest { + node_id checkInNodeID = 0; + optional octet_string<16> verificationKey = 1; + } + + response struct StayActiveResponse = 4 { + int32u promisedActiveDuration = 0; + } + + /** Register a client to the end device */ + fabric command access(invoke: manage) RegisterClient(RegisterClientRequest): RegisterClientResponse = 0; + /** Unregister a client from an end device */ + fabric command access(invoke: manage) UnregisterClient(UnregisterClientRequest): DefaultSuccess = 2; + /** Request the end device to stay in Active Mode for an additional ActiveModeThreshold */ + command access(invoke: manage) StayActiveRequest(): StayActiveResponse = 3; +} + +endpoint 0 { + device type ma_rootdevice = 22, version 2; + + binding cluster OtaSoftwareUpdateProvider; + + server cluster Descriptor { + callback attribute deviceTypeList; + callback attribute serverList; + callback attribute clientList; + callback attribute partsList; + callback attribute featureMap; + callback attribute clusterRevision; + } + + server cluster AccessControl { + emits event AccessControlEntryChanged; + emits event AccessControlExtensionChanged; + callback attribute acl; + callback attribute subjectsPerAccessControlEntry; + callback attribute targetsPerAccessControlEntry; + callback attribute accessControlEntriesPerFabric; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute eventList; + callback attribute attributeList; + ram attribute featureMap default = 0; + callback attribute clusterRevision; + } + + 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; + callback attribute location; + callback attribute hardwareVersion; + callback attribute hardwareVersionString; + callback attribute softwareVersion; + callback attribute softwareVersionString; + callback attribute capabilityMinima; + callback attribute specificationVersion; + callback attribute maxPathsPerInvoke; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute eventList; + callback attribute attributeList; + ram attribute featureMap default = 0; + ram attribute clusterRevision default = 2; + } + + server cluster OtaSoftwareUpdateRequestor { + emits event StateTransition; + emits event VersionApplied; + emits event DownloadError; + callback attribute defaultOTAProviders; + ram attribute updatePossible default = 1; + ram attribute updateState default = 0; + ram attribute updateStateProgress default = 0; + ram attribute featureMap default = 0; + ram attribute clusterRevision default = 1; + + handle command AnnounceOTAProvider; + } + + 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 eventList; + callback attribute attributeList; + ram attribute featureMap default = 0; + ram attribute clusterRevision default = 1; + + handle command ArmFailSafe; + handle command ArmFailSafeResponse; + handle command SetRegulatoryConfig; + handle command SetRegulatoryConfigResponse; + handle command CommissioningComplete; + handle command CommissioningCompleteResponse; + } + + server cluster NetworkCommissioning { + ram attribute maxNetworks; + callback attribute networks; + ram attribute scanMaxTimeSeconds; + ram attribute connectMaxTimeSeconds; + ram attribute interfaceEnabled; + ram attribute lastNetworkingStatus; + ram attribute lastNetworkID; + ram attribute lastConnectErrorValue; + ram attribute supportedThreadFeatures; + ram attribute threadVersion; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute eventList; + callback attribute attributeList; + ram attribute featureMap default = 2; + ram attribute clusterRevision default = 2; + + handle command ScanNetworks; + handle command ScanNetworksResponse; + handle command AddOrUpdateThreadNetwork; + handle command RemoveNetwork; + handle command NetworkConfigResponse; + handle command ConnectNetwork; + handle command ConnectNetworkResponse; + handle command ReorderNetwork; + } + + server cluster GeneralDiagnostics { + emits event BootReason; + callback attribute networkInterfaces; + callback attribute rebootCount; + callback attribute upTime; + callback attribute activeNetworkFaults; + callback attribute testEventTriggersEnabled default = false; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute eventList; + callback attribute attributeList; + callback attribute featureMap; + callback attribute clusterRevision; + + handle command TestEventTrigger; + handle command TimeSnapshot; + handle command TimeSnapshotResponse; + } + + server cluster SoftwareDiagnostics { + callback attribute threadMetrics; + callback attribute currentHeapFree; + callback attribute currentHeapUsed; + callback attribute currentHeapHighWatermark; + callback attribute featureMap; + ram attribute clusterRevision default = 1; + + handle command ResetWatermarks; + } + + server cluster ThreadNetworkDiagnostics { + callback attribute channel; + callback attribute routingRole; + callback attribute networkName; + callback attribute panId; + callback attribute extendedPanId; + callback attribute meshLocalPrefix; + callback attribute overrunCount; + callback attribute neighborTable; + callback attribute routeTable; + callback attribute partitionId; + callback attribute weighting; + callback attribute dataVersion; + callback attribute stableDataVersion; + callback attribute leaderRouterId; + callback attribute detachedRoleCount; + callback attribute childRoleCount; + callback attribute routerRoleCount; + callback attribute leaderRoleCount; + callback attribute attachAttemptCount; + callback attribute partitionIdChangeCount; + callback attribute betterPartitionAttachAttemptCount; + callback attribute parentChangeCount; + callback attribute txTotalCount; + callback attribute txUnicastCount; + callback attribute txBroadcastCount; + callback attribute txAckRequestedCount; + callback attribute txAckedCount; + callback attribute txNoAckRequestedCount; + callback attribute txDataCount; + callback attribute txDataPollCount; + callback attribute txBeaconCount; + callback attribute txBeaconRequestCount; + callback attribute txOtherCount; + callback attribute txRetryCount; + callback attribute txDirectMaxRetryExpiryCount; + callback attribute txIndirectMaxRetryExpiryCount; + callback attribute txErrCcaCount; + callback attribute txErrAbortCount; + callback attribute txErrBusyChannelCount; + callback attribute rxTotalCount; + callback attribute rxUnicastCount; + callback attribute rxBroadcastCount; + callback attribute rxDataCount; + callback attribute rxDataPollCount; + callback attribute rxBeaconCount; + callback attribute rxBeaconRequestCount; + callback attribute rxOtherCount; + callback attribute rxAddressFilteredCount; + callback attribute rxDestAddrFilteredCount; + callback attribute rxDuplicatedCount; + callback attribute rxErrNoFrameCount; + callback attribute rxErrUnknownNeighborCount; + callback attribute rxErrInvalidSrcAddrCount; + callback attribute rxErrSecCount; + callback attribute rxErrFcsCount; + callback attribute rxErrOtherCount; + callback attribute securityPolicy; + callback attribute channelPage0Mask; + callback attribute operationalDatasetComponents; + callback attribute activeNetworkFaultsList; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute eventList; + callback attribute attributeList; + ram attribute featureMap default = 0x000F; + ram attribute clusterRevision default = 2; + + handle command ResetCounts; + } + + server cluster AdministratorCommissioning { + callback attribute windowStatus; + callback attribute adminFabricIndex; + callback attribute adminVendorId; + ram attribute featureMap default = 0; + ram attribute clusterRevision default = 1; + + handle command OpenCommissioningWindow; + handle command RevokeCommissioning; + } + + server cluster OperationalCredentials { + callback attribute NOCs; + callback attribute fabrics; + callback attribute supportedFabrics; + callback attribute commissionedFabrics; + callback attribute trustedRootCertificates; + callback attribute currentFabricIndex; + ram attribute featureMap default = 0; + ram attribute clusterRevision default = 1; + + handle command AttestationRequest; + handle command AttestationResponse; + handle command CertificateChainRequest; + handle command CertificateChainResponse; + handle command CSRRequest; + handle command CSRResponse; + handle command AddNOC; + handle command UpdateNOC; + handle command NOCResponse; + handle command UpdateFabricLabel; + handle command RemoveFabric; + handle command AddTrustedRootCertificate; + } + + server cluster GroupKeyManagement { + callback attribute groupKeyMap; + callback attribute groupTable; + callback attribute maxGroupsPerFabric; + callback attribute maxGroupKeysPerFabric; + callback attribute featureMap; + callback attribute clusterRevision; + + handle command KeySetWrite; + handle command KeySetRead; + handle command KeySetReadResponse; + handle command KeySetRemove; + handle command KeySetReadAllIndices; + handle command KeySetReadAllIndicesResponse; + } + + server cluster IcdManagement { + callback attribute idleModeDuration; + callback attribute activeModeDuration; + callback attribute activeModeThreshold; + callback attribute registeredClients; + callback attribute ICDCounter; + callback attribute clientsSupportedPerFabric; + ram attribute userActiveModeTriggerHint default = 4096; + ram attribute userActiveModeTriggerInstruction default = "Push setup button for Active Mode"; + ram attribute operatingMode default = 0; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute eventList; + callback attribute attributeList; + ram attribute featureMap default = 0x0007; + ram attribute clusterRevision default = 2; + + handle command RegisterClient; + handle command RegisterClientResponse; + handle command UnregisterClient; + handle command StayActiveRequest; + handle command StayActiveResponse; + } +} +endpoint 1 { + device type ma_contactsensor = 21, version 1; + + + server cluster Identify { + ram attribute identifyTime default = 0x0000; + ram attribute identifyType default = 0x0; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + ram attribute featureMap default = 0; + ram attribute clusterRevision default = 4; + + handle command Identify; + handle command TriggerEffect; + } + + server cluster Descriptor { + callback attribute deviceTypeList; + callback attribute serverList; + callback attribute clientList; + callback attribute partsList; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + callback attribute featureMap; + callback attribute clusterRevision; + } + + server cluster BooleanState { + emits event StateChange; + ram attribute stateValue default = 0; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute eventList; + callback attribute attributeList; + ram attribute featureMap default = 0; + ram attribute clusterRevision default = 1; + } +} + + diff --git a/examples/contact-sensor-app/nxp/zap-lit/contact-sensor-app.zap b/examples/contact-sensor-app/nxp/zap-lit/contact-sensor-app.zap new file mode 100644 index 00000000000000..3e5035049d7808 --- /dev/null +++ b/examples/contact-sensor-app/nxp/zap-lit/contact-sensor-app.zap @@ -0,0 +1,4161 @@ +{ + "fileFormat": 2, + "featureLevel": 99, + "creator": "zap", + "keyValuePairs": [ + { + "key": "commandDiscovery", + "value": "1" + }, + { + "key": "defaultResponsePolicy", + "value": "always" + }, + { + "key": "manufacturerCodes", + "value": "0x1002" + } + ], + "package": [ + { + "pathRelativity": "relativeToZap", + "path": "../../../../src/app/zap-templates/zcl/zcl.json", + "type": "zcl-properties", + "category": "matter", + "version": 1, + "description": "Matter SDK ZCL data" + }, + { + "pathRelativity": "relativeToZap", + "path": "../../../../src/app/zap-templates/app-templates.json", + "type": "gen-templates-json", + "version": "chip-v1" + } + ], + "endpointTypes": [ + { + "id": 1, + "name": "MA-rootdevice", + "deviceTypeRef": { + "code": 22, + "profileId": 259, + "label": "MA-rootdevice", + "name": "MA-rootdevice" + }, + "deviceTypes": [ + { + "code": 22, + "profileId": 259, + "label": "MA-rootdevice", + "name": "MA-rootdevice" + } + ], + "deviceVersions": [ + 2 + ], + "deviceIdentifiers": [ + 22 + ], + "deviceTypeName": "MA-rootdevice", + "deviceTypeCode": 22, + "deviceTypeProfileId": 259, + "clusters": [ + { + "name": "Descriptor", + "code": 29, + "mfgCode": null, + "define": "DESCRIPTOR_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "DeviceTypeList", + "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 + }, + { + "name": "ServerList", + "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 + }, + { + "name": "ClientList", + "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": "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": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Access Control", + "code": 31, + "mfgCode": null, + "define": "ACCESS_CONTROL_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "ACL", + "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 + }, + { + "name": "SubjectsPerAccessControlEntry", + "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": "TargetsPerAccessControlEntry", + "code": 3, + "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": "AccessControlEntriesPerFabric", + "code": 4, + "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": "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": "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, + "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": "0", + "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": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ], + "events": [ + { + "name": "AccessControlEntryChanged", + "code": 0, + "mfgCode": null, + "side": "server", + "included": 1 + }, + { + "name": "AccessControlExtensionChanged", + "code": 1, + "mfgCode": null, + "side": "server", + "included": 1 + } + ] + }, + { + "name": "Basic Information", + "code": 40, + "mfgCode": null, + "define": "BASIC_INFORMATION_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "DataModelRevision", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "VendorName", + "code": 1, + "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": "VendorID", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "vendor_id", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ProductName", + "code": 3, + "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": "ProductID", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "NodeLabel", + "code": 5, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "NVM", + "singleton": 1, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Location", + "code": 6, + "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": "HardwareVersion", + "code": 7, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "HardwareVersionString", + "code": 8, + "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": "SoftwareVersion", + "code": 9, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "SoftwareVersionString", + "code": 10, + "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": "CapabilityMinima", + "code": 19, + "mfgCode": null, + "side": "server", + "type": "CapabilityMinimaStruct", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "SpecificationVersion", + "code": 21, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MaxPathsPerInvoke", + "code": 22, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 1, + "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": 1, + "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": 1, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "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, + "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": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "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": 1, + "bounded": 0, + "defaultValue": "2", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ], + "events": [ + { + "name": "StartUp", + "code": 0, + "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 + } + ] + }, + { + "name": "OTA Software Update Provider", + "code": 41, + "mfgCode": null, + "define": "OTA_SOFTWARE_UPDATE_PROVIDER_CLUSTER", + "side": "client", + "enabled": 1, + "commands": [ + { + "name": "QueryImage", + "code": 0, + "mfgCode": null, + "source": "client", + "isIncoming": 0, + "isEnabled": 1 + }, + { + "name": "QueryImageResponse", + "code": 1, + "mfgCode": null, + "source": "server", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "ApplyUpdateRequest", + "code": 2, + "mfgCode": null, + "source": "client", + "isIncoming": 0, + "isEnabled": 1 + }, + { + "name": "ApplyUpdateResponse", + "code": 3, + "mfgCode": null, + "source": "server", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "NotifyUpdateApplied", + "code": 4, + "mfgCode": null, + "source": "client", + "isIncoming": 0, + "isEnabled": 1 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "OTA Software Update Requestor", + "code": 42, + "mfgCode": null, + "define": "OTA_SOFTWARE_UPDATE_REQUESTOR_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [ + { + "name": "AnnounceOTAProvider", + "code": 0, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + } + ], + "attributes": [ + { + "name": "DefaultOTAProviders", + "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 + }, + { + "name": "UpdatePossible", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "UpdateState", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "UpdateStateEnum", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "UpdateStateProgress", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "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": "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 + } + ], + "events": [ + { + "name": "StateTransition", + "code": 0, + "mfgCode": null, + "side": "server", + "included": 1 + }, + { + "name": "VersionApplied", + "code": 1, + "mfgCode": null, + "side": "server", + "included": 1 + }, + { + "name": "DownloadError", + "code": 2, + "mfgCode": null, + "side": "server", + "included": 1 + } + ] + }, + { + "name": "General Commissioning", + "code": 48, + "mfgCode": null, + "define": "GENERAL_COMMISSIONING_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [ + { + "name": "ArmFailSafe", + "code": 0, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "ArmFailSafeResponse", + "code": 1, + "mfgCode": null, + "source": "server", + "isIncoming": 0, + "isEnabled": 1 + }, + { + "name": "SetRegulatoryConfig", + "code": 2, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "SetRegulatoryConfigResponse", + "code": 3, + "mfgCode": null, + "source": "server", + "isIncoming": 0, + "isEnabled": 1 + }, + { + "name": "CommissioningComplete", + "code": 4, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "CommissioningCompleteResponse", + "code": 5, + "mfgCode": null, + "source": "server", + "isIncoming": 0, + "isEnabled": 1 + } + ], + "attributes": [ + { + "name": "Breadcrumb", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "int64u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000000000000000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "BasicCommissioningInfo", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "BasicCommissioningInfo", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RegulatoryConfig", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "RegulatoryLocationTypeEnum", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "LocationCapability", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "RegulatoryLocationTypeEnum", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "SupportsConcurrentConnection", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "boolean", + "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": "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, + "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": "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": "Network Commissioning", + "code": 49, + "mfgCode": null, + "define": "NETWORK_COMMISSIONING_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [ + { + "name": "ScanNetworks", + "code": 0, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "ScanNetworksResponse", + "code": 1, + "mfgCode": null, + "source": "server", + "isIncoming": 0, + "isEnabled": 1 + }, + { + "name": "AddOrUpdateThreadNetwork", + "code": 3, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "RemoveNetwork", + "code": 4, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "NetworkConfigResponse", + "code": 5, + "mfgCode": null, + "source": "server", + "isIncoming": 0, + "isEnabled": 1 + }, + { + "name": "ConnectNetwork", + "code": 6, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "ConnectNetworkResponse", + "code": 7, + "mfgCode": null, + "source": "server", + "isIncoming": 0, + "isEnabled": 1 + }, + { + "name": "ReorderNetwork", + "code": 8, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + } + ], + "attributes": [ + { + "name": "MaxNetworks", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "Networks", + "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 + }, + { + "name": "ScanMaxTimeSeconds", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ConnectMaxTimeSeconds", + "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": "InterfaceEnabled", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "LastNetworkingStatus", + "code": 5, + "mfgCode": null, + "side": "server", + "type": "NetworkCommissioningStatusEnum", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "LastNetworkID", + "code": 6, + "mfgCode": null, + "side": "server", + "type": "octet_string", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "LastConnectErrorValue", + "code": 7, + "mfgCode": null, + "side": "server", + "type": "int32s", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "SupportedThreadFeatures", + "code": 9, + "mfgCode": null, + "side": "server", + "type": "ThreadCapabilitiesBitmap", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ThreadVersion", + "code": 10, + "mfgCode": null, + "side": "server", + "type": "int16u", + "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": "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, + "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": "2", + "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": "2", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "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", + "included": 1, + "storageOption": "External", + "singleton": 0, + "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": "ActiveNetworkFaults", + "code": 7, + "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": "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", + "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": "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, + "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 + } + ], + "events": [ + { + "name": "BootReason", + "code": 3, + "mfgCode": null, + "side": "server", + "included": 1 + } + ] + }, + { + "name": "Software Diagnostics", + "code": 52, + "mfgCode": null, + "define": "SOFTWARE_DIAGNOSTICS_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [ + { + "name": "ResetWatermarks", + "code": 0, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + } + ], + "attributes": [ + { + "name": "ThreadMetrics", + "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 + }, + { + "name": "CurrentHeapFree", + "code": 1, + "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": "CurrentHeapUsed", + "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": "CurrentHeapHighWatermark", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "int64u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "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": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Thread Network Diagnostics", + "code": 53, + "mfgCode": null, + "define": "THREAD_NETWORK_DIAGNOSTICS_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [ + { + "name": "ResetCounts", + "code": 0, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + } + ], + "attributes": [ + { + "name": "Channel", + "code": 0, + "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": "RoutingRole", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "RoutingRoleEnum", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "NetworkName", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "PanId", + "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": "ExtendedPanId", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "int64u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "MeshLocalPrefix", + "code": 5, + "mfgCode": null, + "side": "server", + "type": "octet_string", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "OverrunCount", + "code": 6, + "mfgCode": null, + "side": "server", + "type": "int64u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "NeighborTable", + "code": 7, + "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": "RouteTable", + "code": 8, + "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": "PartitionId", + "code": 9, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Weighting", + "code": 10, + "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": "DataVersion", + "code": 11, + "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": "StableDataVersion", + "code": 12, + "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": "LeaderRouterId", + "code": 13, + "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": "DetachedRoleCount", + "code": 14, + "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": "ChildRoleCount", + "code": 15, + "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": "RouterRoleCount", + "code": 16, + "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": "LeaderRoleCount", + "code": 17, + "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": "AttachAttemptCount", + "code": 18, + "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": "PartitionIdChangeCount", + "code": 19, + "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": "BetterPartitionAttachAttemptCount", + "code": 20, + "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": "ParentChangeCount", + "code": 21, + "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": "TxTotalCount", + "code": 22, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "TxUnicastCount", + "code": 23, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "TxBroadcastCount", + "code": 24, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "TxAckRequestedCount", + "code": 25, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "TxAckedCount", + "code": 26, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "TxNoAckRequestedCount", + "code": 27, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "TxDataCount", + "code": 28, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "TxDataPollCount", + "code": 29, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "TxBeaconCount", + "code": 30, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "TxBeaconRequestCount", + "code": 31, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "TxOtherCount", + "code": 32, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "TxRetryCount", + "code": 33, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "TxDirectMaxRetryExpiryCount", + "code": 34, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "TxIndirectMaxRetryExpiryCount", + "code": 35, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "TxErrCcaCount", + "code": 36, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "TxErrAbortCount", + "code": 37, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "TxErrBusyChannelCount", + "code": 38, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RxTotalCount", + "code": 39, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RxUnicastCount", + "code": 40, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RxBroadcastCount", + "code": 41, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RxDataCount", + "code": 42, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RxDataPollCount", + "code": 43, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RxBeaconCount", + "code": 44, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RxBeaconRequestCount", + "code": 45, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RxOtherCount", + "code": 46, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RxAddressFilteredCount", + "code": 47, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RxDestAddrFilteredCount", + "code": 48, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RxDuplicatedCount", + "code": 49, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RxErrNoFrameCount", + "code": 50, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RxErrUnknownNeighborCount", + "code": 51, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RxErrInvalidSrcAddrCount", + "code": 52, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RxErrSecCount", + "code": 53, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RxErrFcsCount", + "code": 54, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RxErrOtherCount", + "code": 55, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "SecurityPolicy", + "code": 59, + "mfgCode": null, + "side": "server", + "type": "SecurityPolicy", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ChannelPage0Mask", + "code": 60, + "mfgCode": null, + "side": "server", + "type": "octet_string", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "OperationalDatasetComponents", + "code": 61, + "mfgCode": null, + "side": "server", + "type": "OperationalDatasetComponents", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ActiveNetworkFaultsList", + "code": 62, + "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": "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": "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, + "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": "0x000F", + "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": "2", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Administrator Commissioning", + "code": 60, + "mfgCode": null, + "define": "ADMINISTRATOR_COMMISSIONING_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [ + { + "name": "OpenCommissioningWindow", + "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", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "CommissioningWindowStatusEnum", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AdminFabricIndex", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "fabric_idx", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AdminVendorId", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "vendor_id", + "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": "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": "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", + "code": 5, + "mfgCode": null, + "source": "server", + "isIncoming": 0, + "isEnabled": 1 + }, + { + "name": "AddNOC", + "code": 6, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "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": "UpdateFabricLabel", + "code": 9, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "RemoveFabric", + "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", + "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": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "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": 1, + "maxInterval": 65534, + "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": 1, + "maxInterval": 65534, + "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, + "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": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "ICD Management", + "code": 70, + "mfgCode": null, + "define": "ICD_MANAGEMENT_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [ + { + "name": "RegisterClient", + "code": 0, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "RegisterClientResponse", + "code": 1, + "mfgCode": null, + "source": "server", + "isIncoming": 0, + "isEnabled": 1 + }, + { + "name": "UnregisterClient", + "code": 2, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "StayActiveRequest", + "code": 3, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "StayActiveResponse", + "code": 4, + "mfgCode": null, + "source": "server", + "isIncoming": 0, + "isEnabled": 1 + } + ], + "attributes": [ + { + "name": "IdleModeDuration", + "code": 0, + "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": "ActiveModeDuration", + "code": 1, + "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": "ActiveModeThreshold", + "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": "RegisteredClients", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ICDCounter", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClientsSupportedPerFabric", + "code": 5, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "UserActiveModeTriggerHint", + "code": 6, + "mfgCode": null, + "side": "server", + "type": "UserActiveModeTriggerBitmap", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "4096", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "UserActiveModeTriggerInstruction", + "code": 7, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "Push setup button for Active Mode", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "OperatingMode", + "code": 8, + "mfgCode": null, + "side": "server", + "type": "OperatingModeEnum", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "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": "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, + "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": "0x0007", + "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": "2", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + } + ] + }, + { + "id": 2, + "name": "MA-dimmablelight", + "deviceTypeRef": { + "code": 21, + "profileId": 259, + "label": "MA-contactsensor", + "name": "MA-contactsensor" + }, + "deviceTypes": [ + { + "code": 21, + "profileId": 259, + "label": "MA-contactsensor", + "name": "MA-contactsensor" + } + ], + "deviceVersions": [ + 1 + ], + "deviceIdentifiers": [ + 21 + ], + "deviceTypeName": "MA-contactsensor", + "deviceTypeCode": 21, + "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": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "IdentifyType", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "IdentifyTypeEnum", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0", + "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": "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": "4", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Descriptor", + "code": 29, + "mfgCode": null, + "define": "DESCRIPTOR_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "DeviceTypeList", + "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 + }, + { + "name": "ServerList", + "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 + }, + { + "name": "ClientList", + "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 + }, + { + "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": "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": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Boolean State", + "code": 69, + "mfgCode": null, + "define": "BOOLEAN_STATE_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "StateValue", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "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": "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, + "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": "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": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ], + "events": [ + { + "name": "StateChange", + "code": 0, + "mfgCode": null, + "side": "server", + "included": 1 + } + ] + } + ] + } + ], + "endpoints": [ + { + "endpointTypeName": "MA-rootdevice", + "endpointTypeIndex": 0, + "profileId": 259, + "endpointId": 0, + "networkId": 0 + }, + { + "endpointTypeName": "MA-dimmablelight", + "endpointTypeIndex": 1, + "profileId": 259, + "endpointId": 1, + "networkId": 0 + } + ] +} \ No newline at end of file diff --git a/examples/contact-sensor-app/nxp/zap-sit/BUILD.gn b/examples/contact-sensor-app/nxp/zap-sit/BUILD.gn new file mode 100644 index 00000000000000..e9a20db41208d3 --- /dev/null +++ b/examples/contact-sensor-app/nxp/zap-sit/BUILD.gn @@ -0,0 +1,25 @@ +# Copyright (c) 2023 Project CHIP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build_overrides/chip.gni") +import("${chip_root}/examples/common/pigweed/pigweed_rpcs.gni") +import("${chip_root}/src/app/chip_data_model.gni") + +chip_data_model("zap-sit") { + zap_file = "contact-sensor-app.zap" + + zap_pregenerated_dir = + "${chip_root}/zzz_generated/contact-sensor-app/nxp/zap-generated" + is_server = true +} diff --git a/examples/contact-sensor-app/nxp/zap/contact-sensor-app.matter b/examples/contact-sensor-app/nxp/zap-sit/contact-sensor-app.matter similarity index 97% rename from examples/contact-sensor-app/nxp/zap/contact-sensor-app.matter rename to examples/contact-sensor-app/nxp/zap-sit/contact-sensor-app.matter index 03736833bb02d3..479f8baa86284c 100644 --- a/examples/contact-sensor-app/nxp/zap/contact-sensor-app.matter +++ b/examples/contact-sensor-app/nxp/zap-sit/contact-sensor-app.matter @@ -1370,6 +1370,9 @@ endpoint 0 { callback attribute subjectsPerAccessControlEntry; callback attribute targetsPerAccessControlEntry; callback attribute accessControlEntriesPerFabric; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute eventList; callback attribute attributeList; ram attribute featureMap default = 0; callback attribute clusterRevision; @@ -1393,6 +1396,10 @@ endpoint 0 { callback attribute capabilityMinima; callback attribute specificationVersion; callback attribute maxPathsPerInvoke; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute eventList; + callback attribute attributeList; ram attribute featureMap default = 0; ram attribute clusterRevision default = 2; } @@ -1417,6 +1424,10 @@ endpoint 0 { callback attribute regulatoryConfig; callback attribute locationCapability; callback attribute supportsConcurrentConnection; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute eventList; + callback attribute attributeList; ram attribute featureMap default = 0; ram attribute clusterRevision default = 1; @@ -1437,8 +1448,14 @@ endpoint 0 { ram attribute lastNetworkingStatus; ram attribute lastNetworkID; ram attribute lastConnectErrorValue; + ram attribute supportedThreadFeatures; + ram attribute threadVersion; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute eventList; + callback attribute attributeList; ram attribute featureMap default = 2; - ram attribute clusterRevision default = 1; + ram attribute clusterRevision default = 2; handle command ScanNetworks; handle command ScanNetworksResponse; @@ -1454,12 +1471,19 @@ endpoint 0 { emits event BootReason; callback attribute networkInterfaces; callback attribute rebootCount; + callback attribute upTime; callback attribute activeNetworkFaults; callback attribute testEventTriggersEnabled default = false; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute eventList; + callback attribute attributeList; callback attribute featureMap; callback attribute clusterRevision; handle command TestEventTrigger; + handle command TimeSnapshot; + handle command TimeSnapshotResponse; } server cluster SoftwareDiagnostics { @@ -1534,8 +1558,12 @@ endpoint 0 { callback attribute channelPage0Mask; callback attribute operationalDatasetComponents; callback attribute activeNetworkFaultsList; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute eventList; + callback attribute attributeList; ram attribute featureMap default = 0x000F; - ram attribute clusterRevision default = 1; + ram attribute clusterRevision default = 2; handle command ResetCounts; } @@ -1637,6 +1665,7 @@ endpoint 1 { ram attribute stateValue default = 0; callback attribute generatedCommandList; callback attribute acceptedCommandList; + callback attribute eventList; callback attribute attributeList; ram attribute featureMap default = 0; ram attribute clusterRevision default = 1; diff --git a/examples/contact-sensor-app/nxp/zap/contact-sensor-app.zap b/examples/contact-sensor-app/nxp/zap-sit/contact-sensor-app.zap similarity index 88% rename from examples/contact-sensor-app/nxp/zap/contact-sensor-app.zap rename to examples/contact-sensor-app/nxp/zap-sit/contact-sensor-app.zap index bf037957bd2629..d7145e74d9fe0b 100644 --- a/examples/contact-sensor-app/nxp/zap/contact-sensor-app.zap +++ b/examples/contact-sensor-app/nxp/zap-sit/contact-sensor-app.zap @@ -139,10 +139,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, @@ -238,6 +238,54 @@ "maxInterval": 65534, "reportableChange": 0 }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "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": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "EventList", + "code": 65530, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, { "name": "AttributeList", "code": 65531, @@ -514,7 +562,7 @@ "storageOption": "External", "singleton": 1, "bounded": 0, - "defaultValue": "", + "defaultValue": null, "reportable": 1, "minInterval": 1, "maxInterval": 65534, @@ -530,7 +578,71 @@ "storageOption": "External", "singleton": 1, "bounded": 0, - "defaultValue": "", + "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": 1, + "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": 1, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "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, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": null, "reportable": 1, "minInterval": 1, "maxInterval": 65534, @@ -938,6 +1050,70 @@ "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": "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, + "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, @@ -1174,6 +1350,102 @@ "maxInterval": 65534, "reportableChange": 0 }, + { + "name": "SupportedThreadFeatures", + "code": 9, + "mfgCode": null, + "side": "server", + "type": "ThreadCapabilitiesBitmap", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ThreadVersion", + "code": 10, + "mfgCode": null, + "side": "server", + "type": "int16u", + "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": "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, + "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, @@ -1200,7 +1472,7 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "1", + "defaultValue": "2", "reportable": 1, "minInterval": 0, "maxInterval": 65344, @@ -1223,6 +1495,22 @@ "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": [ @@ -1258,6 +1546,22 @@ "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": "ActiveNetworkFaults", "code": 7, @@ -1290,6 +1594,70 @@ "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": "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, + "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, @@ -1297,10 +1665,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, @@ -1313,10 +1681,10 @@ "side": "server", "type": "int16u", "included": 1, - "storageOption": "RAM", + "storageOption": "External", "singleton": 0, "bounded": 0, - "defaultValue": "1", + "defaultValue": null, "reportable": 1, "minInterval": 0, "maxInterval": 65344, @@ -2427,6 +2795,70 @@ "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": "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, + "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, @@ -2453,7 +2885,7 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "1", + "defaultValue": "2", "reportable": 1, "minInterval": 0, "maxInterval": 65344, @@ -3411,10 +3843,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, @@ -3494,6 +3926,22 @@ "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, @@ -3571,6 +4019,5 @@ "endpointId": 1, "networkId": 0 } - ], - "log": [] + ] } \ No newline at end of file diff --git a/examples/lighting-app/nxp/k32w/k32w1/include/CHIPProjectConfig.h b/examples/lighting-app/nxp/k32w/k32w1/include/CHIPProjectConfig.h index 536b822d776377..05f8042ed28138 100644 --- a/examples/lighting-app/nxp/k32w/k32w1/include/CHIPProjectConfig.h +++ b/examples/lighting-app/nxp/k32w/k32w1/include/CHIPProjectConfig.h @@ -139,11 +139,11 @@ * {MAJOR_VERSION}.0d{MINOR_VERSION} */ #ifndef CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION_STRING -#define CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION_STRING "03-2022-te8" +#define CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION_STRING NXP_CONFIG_DEVICE_SOFTWARE_VERSION_STRING #endif #ifndef CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION -#define CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION 42020 +#define CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION NXP_CONFIG_DEVICE_SOFTWARE_VERSION #endif #ifndef CHIP_DEVICE_CONFIG_DEVICE_VENDOR_NAME diff --git a/src/platform/nxp/k32w/k32w0/CHIPPlatformConfig.h b/src/platform/nxp/k32w/k32w0/CHIPPlatformConfig.h index 830024033fc0e7..8ae71ce32aeae2 100644 --- a/src/platform/nxp/k32w/k32w0/CHIPPlatformConfig.h +++ b/src/platform/nxp/k32w/k32w0/CHIPPlatformConfig.h @@ -80,11 +80,11 @@ #if NXP_ICD_ENABLED #ifndef CHIP_CONFIG_ICD_IDLE_MODE_DURATION_SEC -#define CHIP_CONFIG_ICD_IDLE_MODE_DURATION_SEC NXP_IDLE_MODE_INTERVAL +#define CHIP_CONFIG_ICD_IDLE_MODE_DURATION_SEC NXP_IDLE_MODE_DURATION_SEC #endif // CHIP_CONFIG_ICD_IDLE_MODE_DURATION_SEC #ifndef CHIP_CONFIG_ICD_ACTIVE_MODE_DURATION_MS -#define CHIP_CONFIG_ICD_ACTIVE_MODE_DURATION_MS NXP_ACTIVE_MODE_INTERVAL +#define CHIP_CONFIG_ICD_ACTIVE_MODE_DURATION_MS NXP_ACTIVE_MODE_DURATION_MS #endif // CHIP_CONFIG_ICD_ACTIVE_MODE_DURATION_MS #ifndef CHIP_CONFIG_ICD_ACTIVE_MODE_THRESHOLD_MS diff --git a/src/platform/nxp/k32w/k32w1/CHIPPlatformConfig.h b/src/platform/nxp/k32w/k32w1/CHIPPlatformConfig.h index cacc28dd4a60d6..9d43598ca3583f 100644 --- a/src/platform/nxp/k32w/k32w1/CHIPPlatformConfig.h +++ b/src/platform/nxp/k32w/k32w1/CHIPPlatformConfig.h @@ -80,11 +80,11 @@ #if NXP_ICD_ENABLED #ifndef CHIP_CONFIG_ICD_IDLE_MODE_DURATION_SEC -#define CHIP_CONFIG_ICD_IDLE_MODE_DURATION_SEC NXP_IDLE_MODE_INTERVAL +#define CHIP_CONFIG_ICD_IDLE_MODE_DURATION_SEC NXP_IDLE_MODE_DURATION_SEC #endif // CHIP_CONFIG_ICD_IDLE_MODE_DURATION_SEC #ifndef CHIP_CONFIG_ICD_ACTIVE_MODE_DURATION_MS -#define CHIP_CONFIG_ICD_ACTIVE_MODE_DURATION_MS NXP_ACTIVE_MODE_INTERVAL +#define CHIP_CONFIG_ICD_ACTIVE_MODE_DURATION_MS NXP_ACTIVE_MODE_DURATION_MS #endif // CHIP_CONFIG_ICD_ACTIVE_MODE_DURATION_MS #ifndef CHIP_CONFIG_ICD_ACTIVE_MODE_THRESHOLD_MS diff --git a/third_party/nxp/k32w0_sdk/k32w0_sdk.gni b/third_party/nxp/k32w0_sdk/k32w0_sdk.gni index ab37141606f19a..754ac91df80875 100644 --- a/third_party/nxp/k32w0_sdk/k32w0_sdk.gni +++ b/third_party/nxp/k32w0_sdk/k32w0_sdk.gni @@ -49,19 +49,18 @@ declare_args() { ota_custom_entry_address = "0x000C1000" use_antenna_diversity = 0 - #ICD Matter Configuration flags + chip_with_ota_encryption = 0 + chip_with_ota_key = "1234567890ABCDEFA1B2C3D4E5F6F1B4" + chip_with_sdk_package = 1 - chip_ot_idle_interval_ms = 2000 # 2s Idle Intervals - chip_ot_active_interval_ms = 500 # 500ms Active Intervals + # ICD Matter Configuration flags + nxp_ot_idle_interval_ms = 2000 # 2s Idle Intervals + nxp_ot_active_interval_ms = 500 # 500ms Active Intervals - nxp_idle_mode_interval_s = 600 # 10min Idle Mode Interval - nxp_active_mode_interval_ms = 10000 # 10s Active Mode Interval + nxp_idle_mode_duration_s = 600 # 10min Idle Mode Interval + nxp_active_mode_duration_ms = 10000 # 10s Active Mode Interval nxp_active_mode_threshold_ms = 1000 # 1s Active Mode Threshold nxp_icd_supported_clients_per_fabric = 2 # 2 registration slots per fabric - - chip_with_ota_encryption = 0 - chip_with_ota_key = "1234567890ABCDEFA1B2C3D4E5F6F1B4" - chip_with_sdk_package = 1 } assert(k32w0_sdk_root != "", "k32w0_sdk_root must be specified") @@ -367,12 +366,12 @@ template("k32w0_sdk") { "gResetSystemReset_d=1", # TODO: move these platform specific defines to args.gni - "NXP_OT_IDLE_INTERVAL=${chip_ot_idle_interval_ms}", - "NXP_OT_ACTIVE_INTERVAL=${chip_ot_active_interval_ms}", + "NXP_OT_IDLE_INTERVAL=${nxp_ot_idle_interval_ms}", + "NXP_OT_ACTIVE_INTERVAL=${nxp_ot_active_interval_ms}", "NXP_ICD_ENABLED=1", "NXP_ACTIVE_MODE_THRESHOLD=${nxp_active_mode_threshold_ms}", - "NXP_ACTIVE_MODE_INTERVAL=${nxp_active_mode_interval_ms}", - "NXP_IDLE_MODE_INTERVAL=${nxp_idle_mode_interval_s}", + "NXP_ACTIVE_MODE_DURATION_MS=${nxp_active_mode_duration_ms}", + "NXP_IDLE_MODE_DURATION_SEC=${nxp_idle_mode_duration_s}", "NXP_ICD_SUPPORTED_CLIENTS_PER_FABRIC=${nxp_icd_supported_clients_per_fabric}", ] diff --git a/third_party/nxp/k32w1_sdk/k32w1_sdk.gni b/third_party/nxp/k32w1_sdk/k32w1_sdk.gni index 7a8bf40afe7a04..d6d9f6146086d7 100644 --- a/third_party/nxp/k32w1_sdk/k32w1_sdk.gni +++ b/third_party/nxp/k32w1_sdk/k32w1_sdk.gni @@ -36,15 +36,6 @@ declare_args() { use_smu2_dynamic = false use_hw_sha256 = false use_hw_aes = false - - # ICD Matter Configuration flags - chip_ot_idle_interval_ms = 2000 # 2s Idle Intervals - chip_ot_active_interval_ms = 500 # 500ms Active Intervals - - nxp_idle_mode_interval_s = 600 # 10min Idle Mode Interval - nxp_active_mode_interval_ms = 10000 # 10s Active Mode Interval - nxp_active_mode_threshold_ms = 1000 # 1s Active Mode Threshold - nxp_icd_supported_clients_per_fabric = 2 # 2 registration slots per fabric } openthread_nxp_root = "${chip_root}/third_party/openthread/ot-nxp" @@ -270,12 +261,12 @@ template("k32w1_sdk") { "gConnectPowerLeveldBm_c=0", #move these platform specific defines to args.gni - "NXP_OT_IDLE_INTERVAL=${chip_ot_idle_interval_ms}", - "NXP_OT_ACTIVE_INTERVAL=${chip_ot_active_interval_ms}", + "NXP_OT_IDLE_INTERVAL=${nxp_ot_idle_interval_ms}", + "NXP_OT_ACTIVE_INTERVAL=${nxp_ot_active_interval_ms}", "NXP_ICD_ENABLED=1", "NXP_ACTIVE_MODE_THRESHOLD=${nxp_active_mode_threshold_ms}", - "NXP_ACTIVE_MODE_INTERVAL=${nxp_active_mode_interval_ms}", - "NXP_IDLE_MODE_INTERVAL=${nxp_idle_mode_interval_s}", + "NXP_ACTIVE_MODE_DURATION_MS=${nxp_active_mode_duration_ms}", + "NXP_IDLE_MODE_DURATION_SEC=${nxp_idle_mode_duration_s}", "NXP_ICD_SUPPORTED_CLIENTS_PER_FABRIC=${nxp_icd_supported_clients_per_fabric}", ] @@ -358,6 +349,15 @@ template("k32w1_sdk") { defines += [ "USE_HW_AES" ] } + if (nxp_software_version != "") { + defines += + [ "NXP_CONFIG_DEVICE_SOFTWARE_VERSION=${nxp_software_version}" ] + } + + if (nxp_software_version_string != "") { + defines += [ "NXP_CONFIG_DEVICE_SOFTWARE_VERSION_STRING=\"${nxp_software_version_string}\"" ] + } + if (defined(invoker.defines)) { defines += invoker.defines } diff --git a/third_party/nxp/nxp_sdk.gni b/third_party/nxp/nxp_sdk.gni index d87d99d2911ae2..da66a0d51c5721 100644 --- a/third_party/nxp/nxp_sdk.gni +++ b/third_party/nxp/nxp_sdk.gni @@ -45,7 +45,16 @@ declare_args() { nxp_software_version = 1 # Defines the current software string version - nxp_software_version_string = "1.1" + nxp_software_version_string = "1.3" + + # ICD Matter Configuration flags + nxp_ot_idle_interval_ms = 2000 # 2s Idle Intervals + nxp_ot_active_interval_ms = 500 # 500ms Active Intervals + + nxp_idle_mode_duration_s = 600 # 10min Idle Mode Interval + nxp_active_mode_duration_ms = 10000 # 10s Active Mode Interval + nxp_active_mode_threshold_ms = 1000 # 1s Active Mode Threshold + nxp_icd_supported_clients_per_fabric = 2 # 2 registration slots per fabric } declare_args() { From fc61ca0790d392a61ef616847ab36e8a006e4a1d Mon Sep 17 00:00:00 2001 From: dinabenamar <108664279+dinabenamar@users.noreply.github.com> Date: Thu, 22 Feb 2024 16:25:32 +0100 Subject: [PATCH 054/385] [Docker][NXP] Update Docker image for RW61X SDK (#32240) --- integrations/docker/images/base/chip-build/version | 2 +- .../docker/images/stage-2/chip-build-rw61x/Dockerfile | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/integrations/docker/images/base/chip-build/version b/integrations/docker/images/base/chip-build/version index 3f8f2543a19424..7c7cf32a71a021 100644 --- a/integrations/docker/images/base/chip-build/version +++ b/integrations/docker/images/base/chip-build/version @@ -1 +1 @@ -36 : [Silabs] Update GeckoSDK and WIFI SDK +37 : [NXP] Update Docker image for RW61X SDK diff --git a/integrations/docker/images/stage-2/chip-build-rw61x/Dockerfile b/integrations/docker/images/stage-2/chip-build-rw61x/Dockerfile index 02053b183b402c..399609fe170c49 100644 --- a/integrations/docker/images/stage-2/chip-build-rw61x/Dockerfile +++ b/integrations/docker/images/stage-2/chip-build-rw61x/Dockerfile @@ -14,9 +14,9 @@ WORKDIR /opt/sdk # Setup RW61x SDK RUN set -x \ && mkdir -p rw61x \ - && wget https://www.nxp.com/lgfiles/bsps/SDK_2_13_2_RD-RW612-BGA.zip \ - && unzip SDK_2_13_2_RD-RW612-BGA.zip -d rw61x \ - && rm -rf SDK_2_13_2_RD-RW612-BGA.zip \ + && wget https://www.nxp.com/lgfiles/bsps/SDK_2_13_3_RD-RW612-BGA.zip \ + && unzip SDK_2_13_3_RD-RW612-BGA.zip -d rw61x \ + && rm -rf SDK_2_13_3_RD-RW612-BGA.zip \ && : # last line FROM ghcr.io/project-chip/chip-build:${VERSION} From c5ab509360749485cd1267b2b43d27ed4f3c29ea Mon Sep 17 00:00:00 2001 From: chirag-silabs <100861685+chirag-silabs@users.noreply.github.com> Date: Thu, 22 Feb 2024 21:15:05 +0530 Subject: [PATCH 055/385] [Silabs][SiWx917] 917 SoC and NCP sleepy Improvements for the better power consumption (#32216) * letting our device sleep when it is uncommissioned * using the default clk for the 917 SoC * reducing the firmware retry to 5 * formatting changes reverting which was not needed * Restyled by clang-format * fix the warning for the 917 SoC * Restyled by clang-format * addressing review comments --------- Co-authored-by: Restyled.io --- examples/platform/silabs/BaseApplication.cpp | 26 ++++++++- examples/platform/silabs/BaseApplication.h | 15 +++++ examples/platform/silabs/MatterConfig.cpp | 10 ++-- .../silabs/SiWx917/SiWx917/sl_wifi_if.c | 31 ++++++++--- .../platform/silabs/SiWx917/SiWx917/wfx_rsi.h | 2 +- .../silabs/SiWx917/SiWx917/wfx_rsi_host.c | 7 ++- .../efr32/rs911x/hal/sl_board_configuration.h | 2 - .../platform/silabs/efr32/rs911x/wfx_rsi.h | 4 ++ .../silabs/efr32/rs911x/wfx_rsi_host.c | 16 ++++++ .../silabs/ConnectivityManagerImpl_WIFI.cpp | 4 ++ .../silabs/SiWx917/OTAImageProcessorImpl.cpp | 55 +++++++++++++++---- .../silabs/SiWx917/wifi/wfx_host_events.h | 6 +- .../silabs/SiWx917/wifi/wfx_notify.cpp | 40 ++++++++++++++ .../silabs/efr32/wifi/wfx_host_events.h | 7 +++ .../platformAbstraction/WiseMcuSpam.cpp | 2 + 15 files changed, 193 insertions(+), 34 deletions(-) diff --git a/examples/platform/silabs/BaseApplication.cpp b/examples/platform/silabs/BaseApplication.cpp index 4216dbb4864452..c98882f30aba96 100644 --- a/examples/platform/silabs/BaseApplication.cpp +++ b/examples/platform/silabs/BaseApplication.cpp @@ -146,6 +146,9 @@ Identify gIdentify = { bool BaseApplication::sIsProvisioned = false; bool BaseApplication::sIsFactoryResetTriggered = false; LEDWidget * BaseApplication::sAppActionLed = nullptr; +#if CHIP_CONFIG_ENABLE_ICD_SERVER && SLI_SI917 +BaseApplicationDelegate BaseApplication::sAppDelegate = BaseApplicationDelegate(); +#endif // CHIP_CONFIG_ENABLE_ICD_SERVER && SLI_SI917 #ifdef DIC_ENABLE namespace { @@ -163,6 +166,28 @@ void AppSpecificConnectivityEventCallback(const ChipDeviceEvent * event, intptr_ } // namespace #endif // DIC_ENABLE +#if CHIP_CONFIG_ENABLE_ICD_SERVER && SLI_SI917 +void BaseApplicationDelegate::OnCommissioningSessionStarted() +{ + isComissioningStarted = true; +} +void BaseApplicationDelegate::OnCommissioningSessionStopped() +{ + isComissioningStarted = false; +} +void BaseApplicationDelegate::OnCommissioningWindowClosed() +{ + if (!BaseApplication::GetProvisionStatus() && !isComissioningStarted) + { + int32_t status = wfx_power_save(RSI_SLEEP_MODE_8, STANDBY_POWER_SAVE_WITH_RAM_RETENTION); + if (status != SL_STATUS_OK) + { + ChipLogError(DeviceLayer, "Failed to enable the TA Deep Sleep"); + } + } +} +#endif // CHIP_CONFIG_ENABLE_ICD_SERVER && SLI_SI917 + /********************************************************** * AppTask Definitions *********************************************************/ @@ -261,7 +286,6 @@ CHIP_ERROR BaseApplication::Init() #if CHIP_ENABLE_OPENTHREAD BaseApplication::sIsProvisioned = ConnectivityMgr().IsThreadProvisioned(); #endif - return err; } diff --git a/examples/platform/silabs/BaseApplication.h b/examples/platform/silabs/BaseApplication.h index 1714f47024f2c2..1a5c55587d76fe 100644 --- a/examples/platform/silabs/BaseApplication.h +++ b/examples/platform/silabs/BaseApplication.h @@ -30,6 +30,7 @@ #include "FreeRTOS.h" #include "timers.h" // provides FreeRTOS timer support #include +#include #include #include #include @@ -62,6 +63,17 @@ #define APP_ERROR_START_TIMER_FAILED CHIP_APPLICATION_ERROR(0x05) #define APP_ERROR_STOP_TIMER_FAILED CHIP_APPLICATION_ERROR(0x06) +#if CHIP_CONFIG_ENABLE_ICD_SERVER && SLI_SI917 +class BaseApplicationDelegate : public AppDelegate +{ +private: + bool isComissioningStarted; + void OnCommissioningSessionStarted() override; + void OnCommissioningSessionStopped() override; + void OnCommissioningWindowClosed() override; +}; +#endif // CHIP_CONFIG_ENABLE_ICD_SERVER && SLI_SI917 + /********************************************************** * BaseApplication Declaration *********************************************************/ @@ -75,6 +87,9 @@ class BaseApplication static bool sIsProvisioned; static bool sIsFactoryResetTriggered; static LEDWidget * sAppActionLed; +#if CHIP_CONFIG_ENABLE_ICD_SERVER && SLI_SI917 + static BaseApplicationDelegate sAppDelegate; +#endif // CHIP_CONFIG_ENABLE_ICD_SERVER && SLI_SI917 /** * @brief Create AppTask task and Event Queue diff --git a/examples/platform/silabs/MatterConfig.cpp b/examples/platform/silabs/MatterConfig.cpp index e9fed8d924c3e0..32bf04cf0e0f7b 100644 --- a/examples/platform/silabs/MatterConfig.cpp +++ b/examples/platform/silabs/MatterConfig.cpp @@ -18,6 +18,7 @@ */ #include "AppConfig.h" +#include "BaseApplication.h" #include "OTAConfig.h" #include @@ -254,6 +255,9 @@ CHIP_ERROR SilabsMatterConfig::InitMatter(const char * appName) initParams.endpointNativeParams = static_cast(&nativeParams); #endif +#if CHIP_CONFIG_ENABLE_ICD_SERVER && SLI_SI917 + initParams.appDelegate = &BaseApplication::sAppDelegate; +#endif // CHIP_CONFIG_ENABLE_ICD_SERVER && SLI_SI917 // Init Matter Server and Start Event Loop err = chip::Server::GetInstance().Init(initParams); @@ -303,10 +307,6 @@ CHIP_ERROR SilabsMatterConfig::InitWiFi(void) extern "C" void vApplicationIdleHook(void) { #if SIWX_917 && CHIP_CONFIG_ENABLE_ICD_SERVER - if (ConnectivityMgr().IsWiFiStationConnected()) - { - // Let the M4 sleep once commissioning is done and device is in idle state - sl_wfx_host_si91x_sleep_wakeup(); - } + sl_wfx_host_si91x_sleep_wakeup(); #endif } diff --git a/examples/platform/silabs/SiWx917/SiWx917/sl_wifi_if.c b/examples/platform/silabs/SiWx917/SiWx917/sl_wifi_if.c index 6dcfcfaf46aaac..c5044fcf255a8e 100644 --- a/examples/platform/silabs/SiWx917/SiWx917/sl_wifi_if.c +++ b/examples/platform/silabs/SiWx917/SiWx917/sl_wifi_if.c @@ -44,6 +44,7 @@ #if SL_ICD_ENABLED && SIWX_917 #include "rsi_rom_power_save.h" #include "sl_si91x_button_pin_config.h" +#include "sl_si91x_driver.h" #include "sl_si91x_m4_ps.h" // TODO: should be removed once we are getting the press interrupt for button 0 with sleep @@ -188,8 +189,8 @@ sl_status_t join_callback_handler(sl_wifi_event_t event, char * result, uint32_t SILABS_LOG("F: Join Event received with %u bytes payload\n", result_length); callback_status = *(sl_status_t *) result; wfx_rsi.dev_state &= ~(WFX_RSI_ST_STA_CONNECTED); - wfx_retry_interval_handler(is_wifi_disconnection_event, wfx_rsi.join_retries++); is_wifi_disconnection_event = true; + wfx_retry_interval_handler(is_wifi_disconnection_event, wfx_rsi.join_retries++); if (is_wifi_disconnection_event || wfx_rsi.join_retries <= WFX_RSI_CONFIG_MAX_JOIN) { xEventGroupSetBits(wfx_rsi.events, WFX_EVT_STA_START_JOIN); @@ -256,28 +257,36 @@ void sl_wfx_host_si91x_sleep_wakeup() * @brief * Setting the RS911x in DTIM sleep based mode * - * @param[in] None + * @param[in] sl_si91x_ble_state : State to set for the BLE + sl_si91x_wifi_state : State to set for the WiFi * @return * None *********************************************************************/ -int32_t wfx_rsi_power_save() +int32_t wfx_rsi_power_save(rsi_power_save_profile_mode_t sl_si91x_ble_state, sl_si91x_performance_profile_t sl_si91x_wifi_state) { int32_t status; - status = rsi_bt_power_save_profile(2, 0); + + status = rsi_bt_power_save_profile(sl_si91x_ble_state, 0); if (status != RSI_SUCCESS) { SILABS_LOG("BT Powersave Config Failed, Error Code : 0x%lX", status); return status; } - - sl_wifi_performance_profile_t wifi_profile = { .profile = ASSOCIATED_POWER_SAVE }; + sl_wifi_performance_profile_t wifi_profile = { .profile = sl_si91x_wifi_state }; status = sl_wifi_set_performance_profile(&wifi_profile); if (status != RSI_SUCCESS) { SILABS_LOG("Powersave Config Failed, Error Code : 0x%lX", status); return status; } - wfx_rsi.dev_state |= WFX_RSI_ST_SLEEP_READY; + if (sl_si91x_wifi_state == HIGH_PERFORMANCE) + { + wfx_rsi.dev_state &= ~(WFX_RSI_ST_SLEEP_READY); + } + else + { + wfx_rsi.dev_state |= WFX_RSI_ST_SLEEP_READY; + } return status; } #endif /* SL_ICD_ENABLED */ @@ -376,7 +385,7 @@ static sl_status_t wfx_rsi_init(void) } // Initiate and program the key required for TRNG hardware engine - status = sl_si91x_trng_program_key(trngKey, TRNGKEY_SIZE); + status = sl_si91x_trng_program_key((uint32_t *) trngKey, TRNGKEY_SIZE); if (status != SL_STATUS_OK) { SILABS_LOG("TRNG Key Programming Failed"); @@ -581,10 +590,14 @@ static sl_status_t wfx_rsi_do_join(void) sl_wifi_set_join_callback(join_callback_handler, NULL); +#if SL_ICD_ENABLED // Setting the listen interval to 0 which will set it to DTIM interval sl_wifi_listen_interval_t sleep_interval = { .listen_interval = 0 }; status = sl_wifi_set_listen_interval(SL_WIFI_CLIENT_INTERFACE, sleep_interval); + sl_wifi_advanced_client_configuration_t client_config = { .max_retry_attempts = 5 }; + sl_wifi_set_advanced_client_configuration(SL_WIFI_CLIENT_INTERFACE, &client_config); +#endif // SL_ICD_ENABLED /* Try to connect Wifi with given Credentials * untill there is a success or maximum number of tries allowed */ @@ -629,11 +642,11 @@ static sl_status_t wfx_rsi_do_join(void) wfx_rsi.join_retries); wfx_rsi.join_retries += 1; wfx_rsi.dev_state &= ~(WFX_RSI_ST_STA_CONNECTING | WFX_RSI_ST_STA_CONNECTED); + wfx_retry_interval_handler(is_wifi_disconnection_event, wfx_rsi.join_retries); if (is_wifi_disconnection_event || wfx_rsi.join_retries <= MAX_JOIN_RETRIES_COUNT) { xEventGroupSetBits(wfx_rsi.events, WFX_EVT_STA_START_JOIN); } - wfx_retry_interval_handler(is_wifi_disconnection_event, wfx_rsi.join_retries); } } } diff --git a/examples/platform/silabs/SiWx917/SiWx917/wfx_rsi.h b/examples/platform/silabs/SiWx917/SiWx917/wfx_rsi.h index 6721071a1de181..998b3ac1ef5d7a 100644 --- a/examples/platform/silabs/SiWx917/SiWx917/wfx_rsi.h +++ b/examples/platform/silabs/SiWx917/SiWx917/wfx_rsi.h @@ -95,7 +95,7 @@ int32_t wfx_rsi_disconnect(); int32_t wfx_wifi_rsi_init(void); #if SL_ICD_ENABLED void sl_wfx_host_si91x_sleep_wakeup(); -int32_t wfx_rsi_power_save(); +int32_t wfx_rsi_power_save(rsi_power_save_profile_mode_t sl_si91x_ble_state, sl_si91x_performance_profile_t sl_si91x_wifi_state); #endif /* SL_ICD_ENABLED */ #ifdef __cplusplus diff --git a/examples/platform/silabs/SiWx917/SiWx917/wfx_rsi_host.c b/examples/platform/silabs/SiWx917/SiWx917/wfx_rsi_host.c index 0c7efc723eb049..85525fc1bc6dd0 100644 --- a/examples/platform/silabs/SiWx917/SiWx917/wfx_rsi_host.c +++ b/examples/platform/silabs/SiWx917/SiWx917/wfx_rsi_host.c @@ -194,13 +194,14 @@ sl_status_t wfx_connect_to_ap(void) * @fn sl_status_t wfx_power_save() * @brief * Implements the power save in sleepy application - * @param[in] None + * @param[in] sl_si91x_ble_state : State to set for the BLE + sl_si91x_wifi_state : State to set for the WiFi * @return SL_STATUS_OK if successful, * SL_STATUS_FAIL otherwise ***********************************************************************/ -sl_status_t wfx_power_save() +sl_status_t wfx_power_save(rsi_power_save_profile_mode_t sl_si91x_ble_state, sl_si91x_performance_profile_t sl_si91x_wifi_state) { - if (wfx_rsi_power_save() != SL_STATUS_OK) + if (wfx_rsi_power_save(sl_si91x_ble_state, sl_si91x_wifi_state) != SL_STATUS_OK) { return SL_STATUS_FAIL; } diff --git a/examples/platform/silabs/efr32/rs911x/hal/sl_board_configuration.h b/examples/platform/silabs/efr32/rs911x/hal/sl_board_configuration.h index 4310bf719f8179..5591467580bbc4 100644 --- a/examples/platform/silabs/efr32/rs911x/hal/sl_board_configuration.h +++ b/examples/platform/silabs/efr32/rs911x/hal/sl_board_configuration.h @@ -48,6 +48,4 @@ typedef struct #define INTERRUPT_PIN PIN(A, 7) #define SLEEP_CONFIRM_PIN PIN(A, 5) /* Exp hdr 7 */ #endif - -#define NETWORK_INTERFACE_VALID(x) (x == SL_NET_DEFAULT_WIFI_CLIENT_INTERFACE) || (x == SL_NET_DEFAULT_WIFI_AP_INTERFACE) #endif /* _RSI_BOARD_CONFIGURATION_H_ */ \ No newline at end of file diff --git a/examples/platform/silabs/efr32/rs911x/wfx_rsi.h b/examples/platform/silabs/efr32/rs911x/wfx_rsi.h index 4d692064a5768f..07217056cef11b 100644 --- a/examples/platform/silabs/efr32/rs911x/wfx_rsi.h +++ b/examples/platform/silabs/efr32/rs911x/wfx_rsi.h @@ -92,7 +92,11 @@ int32_t wfx_rsi_get_ap_ext(wfx_wifi_scan_ext_t * extra_info); int32_t wfx_rsi_reset_count(); int32_t wfx_rsi_disconnect(); #if SL_ICD_ENABLED +#if SLI_SI917 +int32_t wfx_rsi_power_save(rsi_power_save_profile_mode_t sl_si91x_ble_state, sl_si91x_performance_profile_t sl_si91x_wifi_state); +#else int32_t wfx_rsi_power_save(); +#endif /* SLI_SI917 */ #endif /* SL_ICD_ENABLED */ #ifdef __cplusplus diff --git a/examples/platform/silabs/efr32/rs911x/wfx_rsi_host.c b/examples/platform/silabs/efr32/rs911x/wfx_rsi_host.c index 15915851c11a20..8764c0a9dda8bb 100644 --- a/examples/platform/silabs/efr32/rs911x/wfx_rsi_host.c +++ b/examples/platform/silabs/efr32/rs911x/wfx_rsi_host.c @@ -192,6 +192,21 @@ sl_status_t wfx_connect_to_ap(void) } #if SL_ICD_ENABLED +#if SLI_SI917 +/********************************************************************* + * @fn sl_status_t wfx_power_save() + * @brief + * Implements the power save in sleepy application + * @param[in] sl_si91x_ble_state : State to set for the BLE + sl_si91x_wifi_state : State to set for the WiFi + * @return SL_STATUS_OK if successful, + * SL_STATUS_FAIL otherwise + ***********************************************************************/ +sl_status_t wfx_power_save(rsi_power_save_profile_mode_t sl_si91x_ble_state, sl_si91x_performance_profile_t sl_si91x_wifi_state) +{ + return (wfx_rsi_power_save(sl_si91x_ble_state, sl_si91x_wifi_state) ? SL_STATUS_FAIL : SL_STATUS_OK); +} +#else // For RS9116 /********************************************************************* * @fn sl_status_t wfx_power_save() * @brief @@ -204,6 +219,7 @@ sl_status_t wfx_power_save() { return (wfx_rsi_power_save() ? SL_STATUS_FAIL : SL_STATUS_OK); } +#endif /* SLI_SI917 */ #endif /* SL_ICD_ENABLED */ /********************************************************************* diff --git a/src/platform/silabs/ConnectivityManagerImpl_WIFI.cpp b/src/platform/silabs/ConnectivityManagerImpl_WIFI.cpp index c1a1a7de4c0ed1..214b0974668fbb 100644 --- a/src/platform/silabs/ConnectivityManagerImpl_WIFI.cpp +++ b/src/platform/silabs/ConnectivityManagerImpl_WIFI.cpp @@ -368,7 +368,11 @@ void ConnectivityManagerImpl::OnStationConnected() (void) PlatformMgr().PostEvent(&event); // Setting the rs911x in the power save mode #if (CHIP_CONFIG_ENABLE_ICD_SERVER && RS911X_WIFI) +#if SLI_SI917 + sl_status_t err = wfx_power_save(RSI_SLEEP_MODE_2, ASSOCIATED_POWER_SAVE); +#else sl_status_t err = wfx_power_save(); +#endif /* SLI_SI917 */ if (err != SL_STATUS_OK) { ChipLogError(DeviceLayer, "Power save config for Wifi failed"); diff --git a/src/platform/silabs/SiWx917/OTAImageProcessorImpl.cpp b/src/platform/silabs/SiWx917/OTAImageProcessorImpl.cpp index b4755995e36b01..7e581135fde8bd 100644 --- a/src/platform/silabs/SiWx917/OTAImageProcessorImpl.cpp +++ b/src/platform/silabs/SiWx917/OTAImageProcessorImpl.cpp @@ -20,8 +20,8 @@ #include #include +#include "wfx_host_events.h" #include - #ifdef __cplusplus extern "C" { #endif @@ -35,8 +35,7 @@ extern "C" { #define RPS_HEADER 1 #define RPS_DATA 2 -/// No error, operation OK -#define SL_BOOTLOADER_OK 0L + #define SL_STATUS_FW_UPDATE_DONE SL_STATUS_SI91X_NO_AP_FOUND uint8_t flag = RPS_HEADER; @@ -124,7 +123,7 @@ CHIP_ERROR OTAImageProcessorImpl::ConfirmCurrentImage() void OTAImageProcessorImpl::HandlePrepareDownload(intptr_t context) { - int32_t err = SL_BOOTLOADER_OK; + int32_t status = SL_STATUS_OK; auto * imageProcessor = reinterpret_cast(context); if (imageProcessor == nullptr) @@ -148,15 +147,21 @@ void OTAImageProcessorImpl::HandlePrepareDownload(intptr_t context) imageProcessor->mHeaderParser.Init(); - // Not calling bootloader_eraseStorageSlot(mSlotId) here because we erase during each write + // Setting the device is in high performace - no-sleepy mode while OTA tranfer +#if (CHIP_CONFIG_ENABLE_ICD_SERVER) + status = wfx_power_save(RSI_ACTIVE, HIGH_PERFORMANCE); + if (status != SL_STATUS_OK) + { + ChipLogError(DeviceLayer, "Failed to enable the TA Deep Sleep"); + } +#endif /* CHIP_CONFIG_ENABLE_ICD_SERVER*/ imageProcessor->mDownloader->OnPreparedForDownload(CHIP_NO_ERROR); } void OTAImageProcessorImpl::HandleFinalize(intptr_t context) { - uint32_t err = SL_BOOTLOADER_OK; - int32_t status = 0; + int32_t status = SL_STATUS_OK; auto * imageProcessor = reinterpret_cast(context); if (imageProcessor == nullptr) { @@ -177,7 +182,7 @@ void OTAImageProcessorImpl::HandleFinalize(intptr_t context) } else { - ChipLogError(SoftwareUpdate, "ERROR: In HandleFinalize for last chunk rsi_fwup() error %ld", status); + ChipLogError(SoftwareUpdate, "ERROR: In HandleFinalize for last chunk sl_si91x_fwup_load() error %ld", status); imageProcessor->mDownloader->EndDownload(CHIP_ERROR_WRITE_FAILED); return; } @@ -185,12 +190,21 @@ void OTAImageProcessorImpl::HandleFinalize(intptr_t context) } imageProcessor->ReleaseBlock(); + // Setting the device back to power save mode when transfer is completed successfully +#if (CHIP_CONFIG_ENABLE_ICD_SERVER) + sl_status_t err = wfx_power_save(RSI_SLEEP_MODE_2, ASSOCIATED_POWER_SAVE); + if (err != SL_STATUS_OK) + { + ChipLogError(DeviceLayer, "Power save config for Wifi failed"); + } +#endif /* CHIP_CONFIG_ENABLE_ICD_SERVER*/ + ChipLogProgress(SoftwareUpdate, "OTA image downloaded successfully"); } void OTAImageProcessorImpl::HandleApply(intptr_t context) { - uint32_t err = SL_BOOTLOADER_OK; + int32_t status = SL_STATUS_OK; ChipLogProgress(SoftwareUpdate, "OTAImageProcessorImpl::HandleApply()"); @@ -199,6 +213,15 @@ void OTAImageProcessorImpl::HandleApply(intptr_t context) ChipLogProgress(SoftwareUpdate, "OTA image downloaded successfully in HandleApply"); + // Setting the device is in high performace - no-sleepy mode before soft reset as soft reset is not happening in sleep mode +#if (CHIP_CONFIG_ENABLE_ICD_SERVER) + status = wfx_power_save(RSI_ACTIVE, HIGH_PERFORMANCE); + if (status != SL_STATUS_OK) + { + ChipLogError(DeviceLayer, "Failed to enable the TA Deep Sleep"); + } +#endif /* CHIP_CONFIG_ENABLE_ICD_SERVER*/ + if (mReset) { ChipLogProgress(SoftwareUpdate, "M4 Firmware update complete"); @@ -217,14 +240,22 @@ void OTAImageProcessorImpl::HandleAbort(intptr_t context) return; } + // Setting the device back to power save mode when transfer is aborted in the middle +#if (CHIP_CONFIG_ENABLE_ICD_SERVER) + sl_status_t err = wfx_power_save(RSI_SLEEP_MODE_2, ASSOCIATED_POWER_SAVE); + if (err != SL_STATUS_OK) + { + ChipLogError(DeviceLayer, "Power save config for Wifi failed"); + } +#endif /* CHIP_CONFIG_ENABLE_ICD_SERVER*/ + // Not clearing the image storage area as it is done during each write imageProcessor->ReleaseBlock(); } void OTAImageProcessorImpl::HandleProcessBlock(intptr_t context) { - uint32_t err = SL_BOOTLOADER_OK; - int32_t status = 0; + int32_t status = SL_STATUS_OK; int32_t content_block = 0; auto * imageProcessor = reinterpret_cast(context); if (imageProcessor == nullptr) @@ -280,7 +311,7 @@ void OTAImageProcessorImpl::HandleProcessBlock(intptr_t context) } else { - ChipLogError(SoftwareUpdate, "ERROR: In HandleFinalize for last chunk rsi_fwup() error %ld", status); + ChipLogError(SoftwareUpdate, "ERROR: In HandleProcessBlock sl_si91x_fwup_load() error %ld", status); imageProcessor->mDownloader->EndDownload(CHIP_ERROR_WRITE_FAILED); return; } diff --git a/src/platform/silabs/SiWx917/wifi/wfx_host_events.h b/src/platform/silabs/SiWx917/wifi/wfx_host_events.h index e153a12c0461ae..455563e1899bb8 100644 --- a/src/platform/silabs/SiWx917/wifi/wfx_host_events.h +++ b/src/platform/silabs/SiWx917/wifi/wfx_host_events.h @@ -32,6 +32,9 @@ #include "sl_status.h" +#include "rsi_common_apis.h" +#include "sl_wifi_device.h" + #define SL_WIFI_ALLOCATE_COMMAND_BUFFER_WAIT_TIME_MS 1000 /* Wi-Fi events*/ #define SL_WFX_STARTUP_IND_ID (1) @@ -246,7 +249,8 @@ sl_status_t sl_si91x_host_process_data_frame(sl_wifi_interface_t interface, sl_w void * sl_si91x_host_get_buffer_data(sl_wifi_buffer_t * buffer, uint16_t offset, uint16_t * data_length); #if SL_ICD_ENABLED -sl_status_t wfx_power_save(); +sl_status_t wfx_power_save(rsi_power_save_profile_mode_t sl_si91x_ble_state, sl_si91x_performance_profile_t sl_si91x_wifi_state); +void sl_button_on_change(uint8_t btn, uint8_t btnAction); #endif /* SL_ICD_ENABLED */ void wfx_ipv6_notify(int got_ip); diff --git a/src/platform/silabs/SiWx917/wifi/wfx_notify.cpp b/src/platform/silabs/SiWx917/wifi/wfx_notify.cpp index 3d0f56cf14f442..ac5e8c304f5dcf 100644 --- a/src/platform/silabs/SiWx917/wifi/wfx_notify.cpp +++ b/src/platform/silabs/SiWx917/wifi/wfx_notify.cpp @@ -31,6 +31,18 @@ #include "wfx_rsi.h" #endif +#if SL_ICD_ENABLED +#ifdef __cplusplus +extern "C" { +#endif +#include "sl_si91x_m4_ps.h" +extern "C" uint8_t m4_alarm_initialization_done; +extern "C" void set_alarm_interrupt_timer(uint16_t interval); +#ifdef __cplusplus +} +#endif +#endif // SL_ICD_ENABLED + #include // #include #include @@ -191,6 +203,12 @@ void wfx_ip_changed_notify(int got_ip) ********************************************************************************************/ void wfx_retry_interval_handler(bool is_wifi_disconnection_event, uint16_t retryJoin) { +#if SL_ICD_ENABLED + if (m4_alarm_initialization_done == false) + { + initialize_m4_alarm(); + } +#endif // SL_ICD_ENABLED if (!is_wifi_disconnection_event) { /* After the reboot or a commissioning time device failed to connect with AP. @@ -199,7 +217,22 @@ void wfx_retry_interval_handler(bool is_wifi_disconnection_event, uint16_t retry if (retryJoin < MAX_JOIN_RETRIES_COUNT) { SILABS_LOG("wfx_retry_interval_handler : Next attempt after %d Seconds", CONVERT_MS_TO_SEC(WLAN_RETRY_TIMER_MS)); +#if SL_ICD_ENABLED + // TODO: cleanup the retry logic MATTER-1921 + if (!chip::Server::GetInstance().GetCommissioningWindowManager().IsCommissioningWindowOpen()) + { + set_alarm_interrupt_timer(WLAN_RETRY_TIMER_MS / 1000); + wfx_rsi_power_save(RSI_SLEEP_MODE_8, STANDBY_POWER_SAVE_WITH_RAM_RETENTION); + // TODO: remove this once TICKLESS_IDLE is applied. MATTER-3134 + sl_wfx_host_si91x_sleep_wakeup(); + } + else + { + vTaskDelay(pdMS_TO_TICKS(WLAN_RETRY_TIMER_MS)); + } +#else vTaskDelay(pdMS_TO_TICKS(WLAN_RETRY_TIMER_MS)); +#endif // SL_ICD_ENABLED } else { @@ -218,7 +251,14 @@ void wfx_retry_interval_handler(bool is_wifi_disconnection_event, uint16_t retry retryInterval = WLAN_MAX_RETRY_TIMER_MS; } SILABS_LOG("wfx_retry_interval_handler : Next attempt after %d Seconds", CONVERT_MS_TO_SEC(retryInterval)); +#if SL_ICD_ENABLED + set_alarm_interrupt_timer(retryInterval / 1000); + wfx_rsi_power_save(RSI_SLEEP_MODE_8, STANDBY_POWER_SAVE_WITH_RAM_RETENTION); + // TODO: remove this once TICKLESS_IDLE is applied. MATTER-3134 + sl_wfx_host_si91x_sleep_wakeup(); +#else vTaskDelay(pdMS_TO_TICKS(retryInterval)); +#endif // SL_ICD_ENABLED retryInterval += retryInterval; } } diff --git a/src/platform/silabs/efr32/wifi/wfx_host_events.h b/src/platform/silabs/efr32/wifi/wfx_host_events.h index 4070cf4ea93700..c9f451f8ac063a 100644 --- a/src/platform/silabs/efr32/wifi/wfx_host_events.h +++ b/src/platform/silabs/efr32/wifi/wfx_host_events.h @@ -103,6 +103,9 @@ typedef struct __attribute__((__packed__)) sl_wfx_mib_req_s #include "sl_status.h" #include "sl_wifi_constants.h" +#include "rsi_common_apis.h" +#include "sl_wifi_device.h" + #define SL_WIFI_ALLOCATE_COMMAND_BUFFER_WAIT_TIME_MS 1000 #endif @@ -365,7 +368,11 @@ void * wfx_rsi_alloc_pkt(void); #ifdef RS911X_WIFI /* RSI Power Save */ #if SL_ICD_ENABLED +#if SLI_SI917 +sl_status_t wfx_power_save(rsi_power_save_profile_mode_t sl_si91x_ble_state, sl_si91x_performance_profile_t sl_si91x_wifi_state); +#else sl_status_t wfx_power_save(); +#endif /* SLI_SI917 */ #endif /* SL_ICD_ENABLED */ /* RSI for LWIP */ void wfx_rsi_pkt_add_data(void * p, uint8_t * buf, uint16_t len, uint16_t off); diff --git a/src/platform/silabs/platformAbstraction/WiseMcuSpam.cpp b/src/platform/silabs/platformAbstraction/WiseMcuSpam.cpp index 1015d959ee0825..f57b73f0499d41 100644 --- a/src/platform/silabs/platformAbstraction/WiseMcuSpam.cpp +++ b/src/platform/silabs/platformAbstraction/WiseMcuSpam.cpp @@ -55,8 +55,10 @@ CHIP_ERROR SilabsPlatform::Init(void) // TODO: Setting the highest priority for SVCall_IRQn to avoid the HardFault issue NVIC_SetPriority(SVCall_IRQn, CORE_INTERRUPT_HIGHEST_PRIORITY); +#if !CHIP_CONFIG_ENABLE_ICD_SERVER // Configuration the clock rate soc_pll_config(); +#endif #if SILABS_LOG_ENABLED silabsInitLog(); From 93da26309ae76b1d5a4a3875e7ebb853ab18e848 Mon Sep 17 00:00:00 2001 From: Andrei Litvin Date: Thu, 22 Feb 2024 11:31:00 -0500 Subject: [PATCH 056/385] Remove unnecessary include from OperationalSessionSetupPool.h (#32229) * Remove backwards circular include * Since we include bits, remove the forward declaration (since now things are not broken anymore due to circularity) --------- Co-authored-by: Andrei Litvin --- src/app/CASESessionManager.h | 2 -- src/app/OperationalSessionSetupPool.h | 1 - 2 files changed, 3 deletions(-) diff --git a/src/app/CASESessionManager.h b/src/app/CASESessionManager.h index 92fb7a9ba783c7..3e668fa905cbdf 100644 --- a/src/app/CASESessionManager.h +++ b/src/app/CASESessionManager.h @@ -30,8 +30,6 @@ namespace chip { -class OperationalSessionSetupPoolDelegate; - struct CASESessionManagerConfig { CASEClientInitParams sessionInitParams; diff --git a/src/app/OperationalSessionSetupPool.h b/src/app/OperationalSessionSetupPool.h index 583c7e8d4cc64b..30160a1cb572c9 100644 --- a/src/app/OperationalSessionSetupPool.h +++ b/src/app/OperationalSessionSetupPool.h @@ -17,7 +17,6 @@ #pragma once -#include #include #include #include From 24b5b5462974e80981a78290a04f4306e1dcdb81 Mon Sep 17 00:00:00 2001 From: yunhanw-google Date: Thu, 22 Feb 2024 09:33:58 -0800 Subject: [PATCH 057/385] [Android] Move kotlin tlv/jsontlv out from java device controller lib (#32252) * remove kotlin tlv/jsontlv from java device controller lib * Restyled by gn --------- Co-authored-by: Restyled.io --- BUILD.gn | 2 ++ src/controller/java/BUILD.gn | 2 -- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/BUILD.gn b/BUILD.gn index a96f2a2e67265a..0992c61b0510c6 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -182,7 +182,9 @@ if (current_toolchain != "${dir_pw_toolchain}/default:default") { deps += [ "${chip_root}/src/app/server/java", "${chip_root}/src/controller/java", + "${chip_root}/src/controller/java:jsontlv", "${chip_root}/src/controller/java:onboarding_payload", + "${chip_root}/src/controller/java:tlv", "${chip_root}/src/platform/android:java", ] } diff --git a/src/controller/java/BUILD.gn b/src/controller/java/BUILD.gn index 678a03a6bf63bc..31dbaafc9fb21f 100644 --- a/src/controller/java/BUILD.gn +++ b/src/controller/java/BUILD.gn @@ -442,8 +442,6 @@ android_library("java") { deps = [ ":chipcluster", ":chipclusterID", - ":jsontlv", - ":tlv", "${chip_root}/third_party/java_deps:annotation", ] From a2c53a27dbbad2f5ed2d83335e0d0c7817c59baa Mon Sep 17 00:00:00 2001 From: Boris Zbarsky Date: Thu, 22 Feb 2024 12:55:03 -0500 Subject: [PATCH 058/385] Make MTRServerCluster threadsafe. (#32245) * Make MTRServerCluster threadsafe. If two API clients are both touching the same instance of MTRServerCluster on different threads, we should handle that correctly. * Address review comments. --- .../CHIP/ServerEndpoint/MTRServerAttribute.h | 10 +- .../CHIP/ServerEndpoint/MTRServerCluster.h | 10 +- .../CHIP/ServerEndpoint/MTRServerCluster.mm | 104 +++++++++++++++++- .../MTRServerCluster_Internal.h | 24 ++-- .../CHIP/ServerEndpoint/MTRServerEndpoint.mm | 14 +-- 5 files changed, 132 insertions(+), 30 deletions(-) diff --git a/src/darwin/Framework/CHIP/ServerEndpoint/MTRServerAttribute.h b/src/darwin/Framework/CHIP/ServerEndpoint/MTRServerAttribute.h index 7d8c27b74b55d3..f9c7e7ca6dfe4b 100644 --- a/src/darwin/Framework/CHIP/ServerEndpoint/MTRServerAttribute.h +++ b/src/darwin/Framework/CHIP/ServerEndpoint/MTRServerAttribute.h @@ -24,6 +24,8 @@ NS_ASSUME_NONNULL_BEGIN * A representation of an attribute implemented on a server cluster by an * MTRDeviceController. An attribute has an identifier and a value, and may or * may not be writable. + * + * MTRServerAttribute's API can be accessed from any thread. */ NS_SWIFT_SENDABLE MTR_NEWLY_AVAILABLE @@ -51,13 +53,13 @@ MTR_NEWLY_AVAILABLE */ - (BOOL)setValue:(NSDictionary *)value; -@property (nonatomic, copy, readonly) NSNumber * attributeID; -@property (nonatomic, copy, readonly) NSDictionary * value; +@property (atomic, copy, readonly) NSNumber * attributeID; +@property (atomic, copy, readonly) NSDictionary * value; /** * The privilege level necessary to read this attribute. */ -@property (nonatomic, assign, readonly) MTRAccessControlEntryPrivilege requiredReadPrivilege; -@property (nonatomic, assign, readonly, getter=isWritable) BOOL writable; +@property (atomic, assign, readonly) MTRAccessControlEntryPrivilege requiredReadPrivilege; +@property (atomic, assign, readonly, getter=isWritable) BOOL writable; @end diff --git a/src/darwin/Framework/CHIP/ServerEndpoint/MTRServerCluster.h b/src/darwin/Framework/CHIP/ServerEndpoint/MTRServerCluster.h index 02b0f4b274374d..591d3afec59779 100644 --- a/src/darwin/Framework/CHIP/ServerEndpoint/MTRServerCluster.h +++ b/src/darwin/Framework/CHIP/ServerEndpoint/MTRServerCluster.h @@ -23,6 +23,8 @@ NS_ASSUME_NONNULL_BEGIN /** * A representation of a server cluster implemented by an MTRDeviceController. + * + * MTRServerCluster's API can be accessed from any thread. */ NS_SWIFT_SENDABLE MTR_NEWLY_AVAILABLE @@ -90,9 +92,9 @@ MTR_NEWLY_AVAILABLE */ + (MTRServerCluster *)newDescriptorCluster; -@property (nonatomic, copy, readonly) NSNumber * clusterID; +@property (atomic, copy, readonly) NSNumber * clusterID; -@property (nonatomic, copy, readonly) NSNumber * clusterRevision; +@property (atomic, copy, readonly) NSNumber * clusterRevision; /** * The list of entities that are allowed to access this cluster instance. This @@ -100,12 +102,12 @@ MTR_NEWLY_AVAILABLE * * Defaults to empty list, which means no additional access grants. */ -@property (nonatomic, copy, readonly) NSArray * accessGrants; +@property (atomic, copy, readonly) NSArray * accessGrants; /** * The list of attributes supported by the cluster. */ -@property (nonatomic, copy, readonly) NSArray * attributes; +@property (atomic, copy, readonly) NSArray * attributes; @end diff --git a/src/darwin/Framework/CHIP/ServerEndpoint/MTRServerCluster.mm b/src/darwin/Framework/CHIP/ServerEndpoint/MTRServerCluster.mm index c0fba9e9bda64d..7439c0ff6a453a 100644 --- a/src/darwin/Framework/CHIP/ServerEndpoint/MTRServerCluster.mm +++ b/src/darwin/Framework/CHIP/ServerEndpoint/MTRServerCluster.mm @@ -20,11 +20,12 @@ #import "MTRServerAttribute_Internal.h" #import "MTRServerCluster_Internal.h" #import "MTRServerEndpoint_Internal.h" +#import "MTRUnfairLock.h" +#import "NSDataSpanConversion.h" + #import #import -#import "NSDataSpanConversion.h" - #include #include #include @@ -71,11 +72,26 @@ @implementation MTRServerCluster { std::unique_ptr _attributeAccessInterface; // We can't use something like std::unique_ptr // because EmberAfAttributeMetadata does not have a default constructor, so - // we can't alloc and then initializer later. + // we can't alloc and then initialize later. std::vector _matterAttributeMetadata; std::unique_ptr _matterAcceptedCommandList; std::unique_ptr _matterGeneratedCommandList; + + NSSet * _matterAccessGrants; + + chip::EndpointId _parentEndpoint; + + // _acceptedCommands and _generatedCommands are touched directly by our API + // consumer. + NSArray * _acceptedCommands; + NSArray * _generatedCommands; + + /** + * _lock always protects access to all our mutable ivars (the ones that are + * modified after init). + */ + os_unfair_lock _lock; } - (nullable instancetype)initWithClusterID:(NSNumber *)clusterID revision:(NSNumber *)revision @@ -117,6 +133,7 @@ - (instancetype)initInternalWithClusterID:(NSNumber *)clusterID revision:(NSNumb return nil; } + _lock = OS_UNFAIR_LOCK_INIT; _clusterID = [clusterID copy]; _clusterRevision = [revision copy]; _accessGrants = [[NSMutableSet alloc] init]; @@ -141,6 +158,8 @@ - (instancetype)initInternalWithClusterID:(NSNumber *)clusterID revision:(NSNumb - (void)updateMatterAccessGrants { + os_unfair_lock_assert_owner(&_lock); + MTRDeviceController * deviceController = _deviceController; if (deviceController == nil) { // _matterAccessGrants will be updated when we get bound to a controller. @@ -149,6 +168,7 @@ - (void)updateMatterAccessGrants NSSet * grants = [_accessGrants copy]; [deviceController asyncDispatchToMatterQueue:^{ + std::lock_guard lock(self->_lock); self->_matterAccessGrants = grants; } errorHandler:nil]; @@ -156,6 +176,8 @@ - (void)updateMatterAccessGrants - (void)addAccessGrant:(MTRAccessGrant *)accessGrant { + std::lock_guard lock(self->_lock); + [_accessGrants addObject:accessGrant]; [self updateMatterAccessGrants]; @@ -163,13 +185,24 @@ - (void)addAccessGrant:(MTRAccessGrant *)accessGrant - (void)removeAccessGrant:(MTRAccessGrant *)accessGrant; { + std::lock_guard lock(self->_lock); + [_accessGrants removeObject:accessGrant]; [self updateMatterAccessGrants]; } +- (NSArray *)matterAccessGrants +{ + std::lock_guard lock(self->_lock); + + return [_matterAccessGrants allObjects]; +} + - (BOOL)addAttribute:(MTRServerAttribute *)attribute { + std::lock_guard lock(self->_lock); + MTRDeviceController * deviceController = _deviceController; if (deviceController != nil) { MTR_LOG_ERROR("Cannot add attribute on cluster %llx which is already in use", _clusterID.unsignedLongLongValue); @@ -213,6 +246,8 @@ - (BOOL)addAttribute:(MTRServerAttribute *)attribute - (BOOL)associateWithController:(nullable MTRDeviceController *)controller { + std::lock_guard lock(self->_lock); + MTRDeviceController * existingController = _deviceController; if (existingController != nil) { #if MTR_PER_CONTROLLER_STORAGE_ENABLED @@ -313,7 +348,7 @@ - (BOOL)associateWithController:(nullable MTRDeviceController *)controller _deviceController = controller; - MTR_LOG_DEFAULT("Associated %@, attribute count %llu, with controller", self, + MTR_LOG_DEFAULT("Associated %@, attribute count %llu, with controller", [self _descriptionWhileLocked], static_cast(attributeCount)); return YES; @@ -321,6 +356,8 @@ - (BOOL)associateWithController:(nullable MTRDeviceController *)controller - (void)invalidate { + std::lock_guard lock(_lock); + // Undo any work associateWithController did. for (MTRServerAttribute * attr in _attributes) { [attr invalidate]; @@ -342,6 +379,8 @@ - (void)registerMatterCluster { assertChipStackLockedByCurrentThread(); + std::lock_guard lock(_lock); + if (!registerAttributeAccessOverride(_attributeAccessInterface.get())) { // This should only happen if we somehow managed to register an // AttributeAccessInterface for the same (endpoint, cluster) pair. @@ -354,6 +393,8 @@ - (void)unregisterMatterCluster { assertChipStackLockedByCurrentThread(); + std::lock_guard lock(_lock); + if (_attributeAccessInterface != nullptr) { unregisterAttributeAccessOverride(_attributeAccessInterface.get()); } @@ -361,38 +402,84 @@ - (void)unregisterMatterCluster - (NSArray *)accessGrants { + std::lock_guard lock(_lock); + return [_accessGrants allObjects]; } - (NSArray *)attributes { + std::lock_guard lock(_lock); + return [_attributes copy]; } -- (void)setParentEndpoint:(EndpointId)endpoint +- (BOOL)addToEndpoint:(chip::EndpointId)endpoint { + std::lock_guard lock(_lock); + + if (_parentEndpoint != kInvalidEndpointId) { + MTR_LOG_ERROR("Cannot add cluster " ChipLogFormatMEI " to endpoint %" PRIu32 "; already added to endpoint %" PRIu32, + ChipLogValueMEI(_clusterID.unsignedLongLongValue), endpoint, _parentEndpoint); + return NO; + } + _parentEndpoint = endpoint; // Update it on all the attributes, in case the attributes were added to us // before we were added to the endpoint. for (MTRServerAttribute * attr in _attributes) { [attr updateParentCluster:ConcreteClusterPath(endpoint, static_cast(_clusterID.unsignedLongLongValue))]; } + return YES; +} + +- (chip::EndpointId)parentEndpoint +{ + std::lock_guard lock(_lock); + return _parentEndpoint; } - (Span)matterAttributeMetadata { // This is always called after our _matterAttributeMetadata has been set up // by associateWithController. + std::lock_guard lock(_lock); return Span(_matterAttributeMetadata.data(), _matterAttributeMetadata.size()); } +- (void)setAcceptedCommands:(NSArray *)acceptedCommands +{ + std::lock_guard lock(_lock); + _acceptedCommands = [acceptedCommands copy]; +} + +- (NSArray *)acceptedCommands +{ + std::lock_guard lock(_lock); + return [_acceptedCommands copy]; +} + +- (void)setGeneratedCommands:(NSArray *)generatedCommands +{ + std::lock_guard lock(_lock); + _generatedCommands = [generatedCommands copy]; +} + +- (NSArray *)generatedCommands +{ + std::lock_guard lock(_lock); + return [_generatedCommands copy]; +} + - (CommandId *)matterAcceptedCommands { + std::lock_guard lock(_lock); return _matterAcceptedCommandList.get(); } - (CommandId *)matterGeneratedCommands { + std::lock_guard lock(_lock); return _matterGeneratedCommandList.get(); } @@ -413,6 +500,13 @@ - (CommandId *)matterGeneratedCommands - (NSString *)description { + std::lock_guard lock(_lock); + return [self _descriptionWhileLocked]; +} + +- (NSString *)_descriptionWhileLocked +{ + os_unfair_lock_assert_owner(&_lock); return [NSString stringWithFormat:@"", _parentEndpoint, ChipLogValueMEI(_clusterID.unsignedLongLongValue)]; } diff --git a/src/darwin/Framework/CHIP/ServerEndpoint/MTRServerCluster_Internal.h b/src/darwin/Framework/CHIP/ServerEndpoint/MTRServerCluster_Internal.h index 4ae3d0db348533..253885b7d82e98 100644 --- a/src/darwin/Framework/CHIP/ServerEndpoint/MTRServerCluster_Internal.h +++ b/src/darwin/Framework/CHIP/ServerEndpoint/MTRServerCluster_Internal.h @@ -57,40 +57,46 @@ NS_ASSUME_NONNULL_BEGIN - (void)invalidate; /** - * The access grants the Matter stack can observe. Only modified while in - * Initializing state or on the Matter queue. + * Add the cluster to an endpoint with the given endpoint ID. Will return NO + * if the cluster is already added to an endpoint. */ -@property (nonatomic, strong, readonly) NSSet * matterAccessGrants; +- (BOOL)addToEndpoint:(chip::EndpointId)endpoint; + +/** + * The access grants the Matter stack can observe. Only modified while + * associating with a controller or on the Matter queue. + */ +@property (atomic, copy, readonly) NSArray * matterAccessGrants; /** * parentEndpoint will be kInvalidEndpointId until the cluster is added to an endpoint. */ -@property (nonatomic, assign) chip::EndpointId parentEndpoint; +@property (atomic, assign, readonly) chip::EndpointId parentEndpoint; /** * The attribute metadata for the cluster. Only valid after associateWithController: has succeeded. */ -@property (nonatomic, assign, readonly) chip::Span matterAttributeMetadata; +@property (atomic, assign, readonly) chip::Span matterAttributeMetadata; /** * The list of accepted command IDs. */ -@property (nonatomic, copy, nullable) NSArray * acceptedCommands; +@property (atomic, copy, nullable) NSArray * acceptedCommands; /** * The list of generated command IDs. */ -@property (nonatomic, copy, nullable) NSArray * generatedCommands; +@property (atomic, copy, nullable) NSArray * generatedCommands; /** * The list of accepted commands IDs in the format the Matter stack needs. */ -@property (nonatomic, assign, nullable, readonly) chip::CommandId * matterAcceptedCommands; +@property (atomic, assign, nullable, readonly) chip::CommandId * matterAcceptedCommands; /** * The list of generated commands IDs in the format the Matter stack needs. */ -@property (nonatomic, assign, nullable, readonly) chip::CommandId * matterGeneratedCommands; +@property (atomic, assign, nullable, readonly) chip::CommandId * matterGeneratedCommands; @end diff --git a/src/darwin/Framework/CHIP/ServerEndpoint/MTRServerEndpoint.mm b/src/darwin/Framework/CHIP/ServerEndpoint/MTRServerEndpoint.mm index c58b1ac4fa7744..c7553230f3748e 100644 --- a/src/darwin/Framework/CHIP/ServerEndpoint/MTRServerEndpoint.mm +++ b/src/darwin/Framework/CHIP/ServerEndpoint/MTRServerEndpoint.mm @@ -154,20 +154,18 @@ - (BOOL)addServerCluster:(MTRServerCluster *)serverCluster return NO; } - if (serverCluster.parentEndpoint != kInvalidEndpointId) { - MTR_LOG_ERROR("Cannot add cluster to endpoint %llu; already added to endpoint %" PRIu32, _endpointID.unsignedLongLongValue, serverCluster.parentEndpoint); - return NO; - } - for (MTRServerCluster * existingCluster in _serverClusters) { if ([existingCluster.clusterID isEqual:serverCluster.clusterID]) { - MTR_LOG_ERROR("Cannot add second cluster with ID %llx on endpoint %llu", serverCluster.clusterID.unsignedLongLongValue, _endpointID.unsignedLongLongValue); + MTR_LOG_ERROR("Cannot add second cluster with ID " ChipLogFormatMEI " on endpoint %llu", ChipLogValueMEI(serverCluster.clusterID.unsignedLongLongValue), _endpointID.unsignedLongLongValue); return NO; } } + if (![serverCluster addToEndpoint:static_cast(_endpointID.unsignedLongLongValue)]) { + return NO; + } [_serverClusters addObject:serverCluster]; - serverCluster.parentEndpoint = static_cast(_endpointID.unsignedLongLongValue); + return YES; } @@ -401,7 +399,7 @@ - (void)invalidate NSMutableArray * grants = [[_matterAccessGrants allObjects] mutableCopy]; for (MTRServerCluster * cluster in _serverClusters) { if ([cluster.clusterID isEqual:clusterID]) { - [grants addObjectsFromArray:[cluster.matterAccessGrants allObjects]]; + [grants addObjectsFromArray:cluster.matterAccessGrants]; } } From b2da1b043c4cd6b7140d6373655c03bdaff502ae Mon Sep 17 00:00:00 2001 From: Andrei Litvin Date: Thu, 22 Feb 2024 13:44:16 -0500 Subject: [PATCH 059/385] Move CommandSender and PendingResponseTracker to IM. (#32227) * Move CommandSender and PendingResponseTracker to IM. Previous location of these files was `app` however this created apparent circular dependencies for includes. * Restyle * CommandSender is now tracked * Move read and write clients to interactionmodel as well * Also pull in interactionmodelhelper .... this is a very poorly named file --------- Co-authored-by: Andrei Litvin --- .github/workflows/lint.yml | 4 ---- src/app/BUILD.gn | 30 ++++++++++++++++-------------- src/app/CommandSender.cpp | 8 +------- 3 files changed, 17 insertions(+), 25 deletions(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 66405b9e615b6d..69613217033e8b 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -95,14 +95,11 @@ jobs: --known-failure app/att-storage.h \ --known-failure app/CommandHandler.h \ --known-failure app/CommandHandlerInterface.h \ - --known-failure app/CommandSender.h \ --known-failure app/CommandSenderLegacyCallback.h \ --known-failure app/CompatEnumNames.h \ --known-failure app/data-model/ListLargeSystemExtensions.h \ --known-failure app/EventHeader.h \ --known-failure app/EventLoggingTypes.h \ - --known-failure app/InteractionModelHelper.h \ - --known-failure app/ReadClient.h \ --known-failure app/ReadHandler.h \ --known-failure app/ReadPrepareParams.h \ --known-failure app/reporting/tests/MockReportScheduler.cpp \ @@ -132,7 +129,6 @@ jobs: --known-failure app/util/odd-sized-integers.h \ --known-failure app/util/util.cpp \ --known-failure app/util/util.h \ - --known-failure app/WriteClient.h \ --known-failure app/WriteHandler.h \ --known-failure lib/core/CHIPVendorIdentifiers.hpp \ --known-failure platform/DeviceSafeQueue.cpp \ diff --git a/src/app/BUILD.gn b/src/app/BUILD.gn index ec520e005b0d80..f714560afc15cb 100644 --- a/src/app/BUILD.gn +++ b/src/app/BUILD.gn @@ -140,16 +140,24 @@ static_library("interaction-model") { "CASEClientPool.h", "CASESessionManager.cpp", "CASESessionManager.h", + "CommandSender.cpp", + "CommandSender.h", "DeviceProxy.cpp", "DeviceProxy.h", "InteractionModelDelegatePointers.cpp", "InteractionModelDelegatePointers.h", "InteractionModelEngine.cpp", "InteractionModelEngine.h", + "InteractionModelHelper.h", "InteractionModelTimeout.h", "OperationalSessionSetup.cpp", "OperationalSessionSetup.h", "OperationalSessionSetupPool.h", + "PendingResponseTracker.h", + "PendingResponseTrackerImpl.cpp", + "PendingResponseTrackerImpl.h", + "ReadClient.h", # TODO: cpp is only included conditionally. Needs logic + # fixing "RequiredPrivilege.cpp", "RequiredPrivilege.h", "StatusResponse.cpp", @@ -157,6 +165,10 @@ static_library("interaction-model") { "SubscriptionResumptionStorage.h", "TimedHandler.cpp", "TimedHandler.h", + "TimedRequest.cpp", + "TimedRequest.h", + "WriteClient.cpp", + "WriteClient.h", "reporting/Engine.cpp", "reporting/Engine.h", "reporting/ReportScheduler.h", @@ -184,6 +196,10 @@ static_library("interaction-model") { public_configs = [ "${chip_root}/src:includes" ] + if (chip_enable_read_client) { + sources += [ "ReadClient.cpp" ] + } + if (chip_persist_subscriptions) { sources += [ "SimpleSubscriptionResumptionStorage.cpp", @@ -228,7 +244,6 @@ static_library("app") { "CommandResponseHelper.h", "CommandResponseSender.cpp", "CommandResponseSender.h", - "CommandSender.cpp", "DefaultAttributePersistenceProvider.cpp", "DefaultAttributePersistenceProvider.h", "DeferredAttributePersistenceProvider.cpp", @@ -240,26 +255,17 @@ static_library("app") { "FailSafeContext.cpp", "FailSafeContext.h", "OTAUserConsentCommon.h", - "PendingResponseTracker.h", - "PendingResponseTrackerImpl.cpp", - "PendingResponseTrackerImpl.h", "ReadHandler.cpp", "SafeAttributePersistenceProvider.h", - "TimedRequest.cpp", - "TimedRequest.h", "TimerDelegates.cpp", "TimerDelegates.h", - "WriteClient.cpp", "WriteHandler.cpp", # TODO: the following items cannot be included due to interaction-model circularity # (app depending on im and im including these headers): # Name with _ so that linter does not recognize it # "CommandHandler._h" - # "CommandSender._h", - # "ReadClient._h", # "ReadHandler._h", - # "WriteClient._h", # "WriteHandler._h" # TODO: the following items cannot be included due to platform includes not being @@ -288,10 +294,6 @@ static_library("app") { "BufferedReadCallback.h", "ClusterStateCache.cpp", "ClusterStateCache.h", - "ReadClient.cpp", - - # TODO: cannot include "ReadClient._h" because interaction-model backreference - # Name with _ so that linter does not recognize it ] } diff --git a/src/app/CommandSender.cpp b/src/app/CommandSender.cpp index 03ce2786b93d8d..18f4e755835076 100644 --- a/src/app/CommandSender.cpp +++ b/src/app/CommandSender.cpp @@ -16,15 +16,9 @@ * limitations under the License. */ -/** - * @file - * This file defines objects for a CHIP IM Invoke Command Sender - * - */ - #include "CommandSender.h" -#include "InteractionModelEngine.h" #include "StatusResponse.h" +#include #include #include #include From 091ee228cc453c7f2f45ee1f1eb4a10933b35d94 Mon Sep 17 00:00:00 2001 From: Kai Liao <140431279+kliao-csa@users.noreply.github.com> Date: Thu, 22 Feb 2024 10:47:31 -0800 Subject: [PATCH 060/385] Update spell.yml (#32132) * Update spell.yml Update the spell checker used * Update .wordlist.txt Remove defaultValue, an example of the camelcase we are working around, to trigger test on PR * Update .spellcheck.yml camelcase true * Update spell.yml * Wordlist camelcase removal * Update .wordlist.txt --- .github/.wordlist.txt | 32 +------------------------------- .github/workflows/spell.yml | 21 +++++++++++---------- .spellcheck.yml | 1 + 3 files changed, 13 insertions(+), 41 deletions(-) diff --git a/.github/.wordlist.txt b/.github/.wordlist.txt index 155e909a43f526..d92158e3277bc1 100644 --- a/.github/.wordlist.txt +++ b/.github/.wordlist.txt @@ -14,29 +14,19 @@ abfb ABI ABIs ables -AccessControl -AccessControlEntry +accesscontrol accessor Accessors -AccountLogin acdbc ack ACKed ACL ACLs actdiag -AdapterAddress -AdapterName adb AddNOC -AddOrUpdateThreadNetwork -AddOrUpdateWiFiNetwork addr -AddResponse -AddThreadNetwork -AddStatus adk -AdministratorCommissioning adoc adr AdvAutonomous @@ -48,7 +38,6 @@ AE aef AES AIDL -AlarmCode algs alloc Ameba @@ -61,15 +50,12 @@ AnnounceOTAProvider AnnounceOTAProviderRequest APIs apk -AppConfig AppImpl AppleTV appliable -ApplianceControl applianceeventsandalert ApplianceIdentification appliancestatistics -ApplicationBasic ApplicationId ApplicationIdentifier ApplicationLauncher @@ -171,7 +157,6 @@ BRD breakpoint bredr BridgedDeviceBasicInformation -bridgedLightEndpoint bringup BroadcastReceiver BromateConcentrationMeasurement @@ -259,9 +244,6 @@ CLIs cloudbuild CLRF clusterAttrs -clusterId -clusterList -clusterListName ClusterName ClusterObjectTests ClusterRevision @@ -315,7 +297,6 @@ ContentApp's ContentAppPlatform ContentLaunch ContentLauncher -continuousHinting contrib controllee conv @@ -382,7 +363,6 @@ DefaultOTARequestor DefaultOTARequestorDriver DefaultOTARequestorStorage DefaultSuccess -defaultValue definedValue DehumidificationControl DelayedActionTime @@ -415,9 +395,7 @@ DeviceLayer DeviceNetworkProvisioningDelegate DeviceNetworkProvisioningDelegateImpl DevicePairingDelegate -deviceSoftwareVersionModel DeviceTemperatureConfiguration -deviceType DevKitC DevKitM devtype @@ -511,8 +489,6 @@ EnableNetwork EnableWiFiNetwork endian EndpointId -endpointName -endsWith eno entrypoint enum @@ -580,7 +556,6 @@ FlowMeasurement FluorideConcentrationMeasurement focusable forkpty -formatOnSave FOTA FreeRTOS FreeRTOSConfig @@ -614,7 +589,6 @@ GetIP getManualTests GetSafeAttributePersistenceProvider getstarted -getTests GH ghcr ghp @@ -639,8 +613,6 @@ graphviz Groupcast GroupId GroupKeyManagement -groupKeySecurityPolicy -groupKeySetID groupsettings gsdk gtk @@ -694,8 +666,6 @@ ifconfig ifdef ifdefs IGMP -ignoreApplyUpdate -ignoreQueryImage ihex IlluminanceMeasurement IM diff --git a/.github/workflows/spell.yml b/.github/workflows/spell.yml index 57593372543079..1e8194a9a2075f 100644 --- a/.github/workflows/spell.yml +++ b/.github/workflows/spell.yml @@ -25,19 +25,20 @@ on: - ".github/.wordlist.txt" jobs: - check-reviewdog: - name: Check Spelling - reviewdog - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v4 - - uses: reviewdog/action-misspell@v1 - with: - github_token: ${{ secrets.GITHUB_TOKEN }} +# Seems redundant; removed as pyspelling is customized while this is not +# check-reviewdog: +# name: Check Spelling - reviewdog +# runs-on: ubuntu-latest +# steps: +# - name: Checkout +# uses: actions/checkout@v4 +# - uses: reviewdog/action-misspell@v1 +# with: +# github_token: ${{ secrets.GITHUB_TOKEN }} check-spellcheck: name: Check Spelling - pyspelling runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v4 - - uses: igsekor/pyspelling-any@v1.0.4 + - uses: rojopolis/spellcheck-github-actions@0.36.0 diff --git a/.spellcheck.yml b/.spellcheck.yml index c04880827addba..27a48c7de8e174 100644 --- a/.spellcheck.yml +++ b/.spellcheck.yml @@ -68,3 +68,4 @@ matrix: - '**/*.md|!third_party/**|!examples/common/**/repo/**|!docs/ERROR_CODES.md|!docs/clusters.md|!docs/testing/yaml_schema.md|!docs/testing/yaml_pseudocluster.md' aspell: ignore-case: true + camel-case: true From 3edfb9c77181822f6c92b92bf47ca8684f88984d Mon Sep 17 00:00:00 2001 From: Curtis Rahman <111998767+CuRahman@users.noreply.github.com> Date: Thu, 22 Feb 2024 14:44:43 -0500 Subject: [PATCH 061/385] Changed #if statement to #ifdef for SL_CATALOG_SYSTEMVIEW_TRACE_PRESENT (#32268) --- examples/platform/silabs/FreeRTOSConfig.h | 2 +- src/platform/silabs/platformAbstraction/GsdkSpam.cpp | 4 ++-- third_party/silabs/efr32_sdk.gni | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/platform/silabs/FreeRTOSConfig.h b/examples/platform/silabs/FreeRTOSConfig.h index 93c7ee36444715..478dfa10be547f 100644 --- a/examples/platform/silabs/FreeRTOSConfig.h +++ b/examples/platform/silabs/FreeRTOSConfig.h @@ -122,7 +122,7 @@ extern uint32_t SystemCoreClock; #include "sl_component_catalog.h" #endif -#if SL_CATALOG_SYSTEMVIEW_TRACE_PRESENT +#ifdef SL_CATALOG_SYSTEMVIEW_TRACE_PRESENT #include "SEGGER_SYSVIEW_FreeRTOS.h" #endif diff --git a/src/platform/silabs/platformAbstraction/GsdkSpam.cpp b/src/platform/silabs/platformAbstraction/GsdkSpam.cpp index dda1b7e0e19dac..5527fbfe90d73d 100644 --- a/src/platform/silabs/platformAbstraction/GsdkSpam.cpp +++ b/src/platform/silabs/platformAbstraction/GsdkSpam.cpp @@ -49,7 +49,7 @@ extern "C" { #include "uart.h" #endif -#if SL_CATALOG_SYSTEMVIEW_TRACE_PRESENT +#ifdef SL_CATALOG_SYSTEMVIEW_TRACE_PRESENT #include "SEGGER_SYSVIEW.h" #endif } @@ -78,7 +78,7 @@ CHIP_ERROR SilabsPlatform::Init(void) sl_ot_sys_init(); #endif -#if SL_CATALOG_SYSTEMVIEW_TRACE_PRESENT +#ifdef SL_CATALOG_SYSTEMVIEW_TRACE_PRESENT SEGGER_SYSVIEW_Conf(); SEGGER_SYSVIEW_Start(); #endif diff --git a/third_party/silabs/efr32_sdk.gni b/third_party/silabs/efr32_sdk.gni index 9868b47efb8a8d..8510295bf7c2e0 100644 --- a/third_party/silabs/efr32_sdk.gni +++ b/third_party/silabs/efr32_sdk.gni @@ -401,7 +401,7 @@ template("efr32_sdk") { "${efr32_sdk_root}/util/third_party/segger/systemview/profiles/freertos_v10/", ] - defines += [ "SL_CATALOG_SYSTEMVIEW_TRACE_PRESENT=1" ] + defines += [ "SL_CATALOG_SYSTEMVIEW_TRACE_PRESENT" ] } defines += board_defines From f2bdd1fc34b6b09ac9fe1d8a18e6c6b6b5001a31 Mon Sep 17 00:00:00 2001 From: Robert Szewczyk Date: Thu, 22 Feb 2024 20:58:26 +0000 Subject: [PATCH 062/385] EnergyPreference: Simplify logic around interaction with delegate (#32271) `Optional` is directly constructible from `Optional` --- .../energy-preference-server/energy-preference-server.cpp | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/app/clusters/energy-preference-server/energy-preference-server.cpp b/src/app/clusters/energy-preference-server/energy-preference-server.cpp index 7cb377a7221ba1..c3c645f3108982 100644 --- a/src/app/clusters/energy-preference-server/energy-preference-server.cpp +++ b/src/app/clusters/energy-preference-server/energy-preference-server.cpp @@ -78,9 +78,7 @@ CHIP_ERROR EnergyPrefAttrAccess::Read(const ConcreteReadAttributePath & aPath, A Optional label{ MutableCharSpan(buffer) }; if ((err = gsDelegate->GetEnergyBalanceAtIndex(endpoint, index, step, label)) == CHIP_NO_ERROR) { - BalanceStruct::Type balance = { step, - label.HasValue() ? Optional(label.Value()) - : Optional() }; + BalanceStruct::Type balance = { step, Optional(label) }; ReturnErrorOnFailure(encoder.Encode(balance)); index++; } @@ -137,9 +135,7 @@ CHIP_ERROR EnergyPrefAttrAccess::Read(const ConcreteReadAttributePath & aPath, A Optional label{ MutableCharSpan(buffer) }; if ((err = gsDelegate->GetLowPowerModeSensitivityAtIndex(endpoint, index, step, label)) == CHIP_NO_ERROR) { - BalanceStruct::Type balance = { step, - label.HasValue() ? Optional(label.Value()) - : Optional() }; + BalanceStruct::Type balance = { step, Optional(label) }; ReturnErrorOnFailure(encoder.Encode(balance)); index++; } From 7e3774e7c7bbb2cb949437b960a95a4589c8d1dc Mon Sep 17 00:00:00 2001 From: Andrei Litvin Date: Thu, 22 Feb 2024 16:38:21 -0500 Subject: [PATCH 063/385] zap pregenerated dir does not exist anymore at all. zzz_generated is mostly empty (#32272) Co-authored-by: Andrei Litvin --- .../air-purifier-common/BUILD.gn | 3 -- .../air-quality-sensor-common/BUILD.gn | 3 -- .../all-clusters-common/BUILD.gn | 3 -- .../all-clusters-common/BUILD.gn | 3 -- examples/bridge-app/bridge-common/BUILD.gn | 1 - examples/chef/linux/BUILD.gn | 2 -- examples/chef/silabs/BUILD.gn | 2 -- .../contact-sensor-common/BUILD.gn | 3 -- .../contact-sensor-app/nxp/zap-lit/BUILD.gn | 3 -- .../contact-sensor-app/nxp/zap-sit/BUILD.gn | 3 -- .../dishwasher-app/dishwasher-common/BUILD.gn | 3 -- .../energy-management-common/BUILD.gn | 3 -- .../light-switch-common/BUILD.gn | 4 --- examples/light-switch-app/qpg/zap/BUILD.gn | 3 -- .../lighting-app/bouffalolab/bl602/BUILD.gn | 2 -- .../lighting-app/bouffalolab/bl702/BUILD.gn | 2 -- .../lighting-app/bouffalolab/bl702l/BUILD.gn | 2 -- .../lighting-app/lighting-common/BUILD.gn | 2 -- examples/lighting-app/nxp/zap/BUILD.gn | 3 -- examples/lighting-app/qpg/zap/BUILD.gn | 3 -- .../lighting-app/silabs/data_model/BUILD.gn | 2 -- examples/lit-icd-app/lit-icd-common/BUILD.gn | 3 -- examples/lock-app/lock-common/BUILD.gn | 2 -- examples/lock-app/nxp/zap/BUILD.gn | 2 -- examples/lock-app/qpg/zap/BUILD.gn | 2 -- .../log-source-app/log-source-common/BUILD.gn | 3 -- .../microwave-oven-common/BUILD.gn | 3 -- .../network-manager-common/BUILD.gn | 3 -- .../ota-provider-common/BUILD.gn | 3 -- .../ota-requestor-common/BUILD.gn | 3 -- examples/placeholder/linux/apps/app1/BUILD.gn | 3 -- examples/placeholder/linux/apps/app2/BUILD.gn | 3 -- examples/pump-app/pump-common/BUILD.gn | 2 -- examples/pump-app/silabs/data_model/BUILD.gn | 2 -- .../pump-controller-common/BUILD.gn | 3 -- .../refrigerator-common/BUILD.gn | 3 -- examples/rvc-app/rvc-common/BUILD.gn | 2 -- .../smoke-co-alarm-common/BUILD.gn | 3 -- .../temperature-measurement-common/BUILD.gn | 3 -- examples/thermostat/nxp/zap/BUILD.gn | 2 -- examples/thermostat/qpg/zap/BUILD.gn | 3 -- .../thermostat/thermostat-common/BUILD.gn | 2 -- examples/tv-app/tv-common/BUILD.gn | 2 -- .../tv-casting-app/tv-casting-common/BUILD.gn | 3 -- .../virtual-device-common/BUILD.gn | 3 -- examples/window-app/common/BUILD.gn | 2 -- src/app/chip_data_model.gni | 35 +------------------ src/controller/data_model/BUILD.gn | 4 --- 48 files changed, 1 insertion(+), 158 deletions(-) diff --git a/examples/air-purifier-app/air-purifier-common/BUILD.gn b/examples/air-purifier-app/air-purifier-common/BUILD.gn index 9715f88e65f2b3..aaf01bf29b7ba0 100755 --- a/examples/air-purifier-app/air-purifier-common/BUILD.gn +++ b/examples/air-purifier-app/air-purifier-common/BUILD.gn @@ -17,8 +17,5 @@ import("${chip_root}/src/app/chip_data_model.gni") chip_data_model("air-purifier-common") { zap_file = "air-purifier-app.zap" - - zap_pregenerated_dir = - "${chip_root}/zzz_generated/air-purifier-app/zap-generated" is_server = true } diff --git a/examples/air-quality-sensor-app/air-quality-sensor-common/BUILD.gn b/examples/air-quality-sensor-app/air-quality-sensor-common/BUILD.gn index 6ca5be5ba634db..5cdba00ee78fc0 100755 --- a/examples/air-quality-sensor-app/air-quality-sensor-common/BUILD.gn +++ b/examples/air-quality-sensor-app/air-quality-sensor-common/BUILD.gn @@ -17,8 +17,5 @@ import("${chip_root}/src/app/chip_data_model.gni") chip_data_model("air-quality-sensor-common") { zap_file = "air-quality-sensor-app.zap" - - zap_pregenerated_dir = - "${chip_root}/zzz_generated/air-quality-sensor-app/zap-generated" is_server = true } diff --git a/examples/all-clusters-app/all-clusters-common/BUILD.gn b/examples/all-clusters-app/all-clusters-common/BUILD.gn index 0210fcedb2c646..1b29a9c2775353 100644 --- a/examples/all-clusters-app/all-clusters-common/BUILD.gn +++ b/examples/all-clusters-app/all-clusters-common/BUILD.gn @@ -18,8 +18,5 @@ import("${chip_root}/src/app/chip_data_model.gni") chip_data_model("all-clusters-common") { zap_file = "all-clusters-app.zap" - - zap_pregenerated_dir = - "${chip_root}/zzz_generated/all-clusters-app/zap-generated" is_server = true } diff --git a/examples/all-clusters-minimal-app/all-clusters-common/BUILD.gn b/examples/all-clusters-minimal-app/all-clusters-common/BUILD.gn index 9991df1e8274ea..cd518cb42fe388 100644 --- a/examples/all-clusters-minimal-app/all-clusters-common/BUILD.gn +++ b/examples/all-clusters-minimal-app/all-clusters-common/BUILD.gn @@ -18,8 +18,5 @@ import("${chip_root}/src/app/chip_data_model.gni") chip_data_model("all-clusters-common") { zap_file = "all-clusters-minimal-app.zap" - - zap_pregenerated_dir = - "${chip_root}/zzz_generated/all-clusters-minimal-app/zap-generated" is_server = true } diff --git a/examples/bridge-app/bridge-common/BUILD.gn b/examples/bridge-app/bridge-common/BUILD.gn index ac3aa414ae3791..e833d33429567e 100644 --- a/examples/bridge-app/bridge-common/BUILD.gn +++ b/examples/bridge-app/bridge-common/BUILD.gn @@ -19,7 +19,6 @@ import("${chip_root}/src/app/chip_data_model.gni") chip_data_model("bridge-common") { zap_file = "bridge-app.zap" - zap_pregenerated_dir = "${chip_root}/zzz_generated/bridge-app/zap-generated" is_server = true # TODO: the definition of DYNAMIC_ENDPOINT_COUNT needs find a common home! diff --git a/examples/chef/linux/BUILD.gn b/examples/chef/linux/BUILD.gn index a119f832e051db..02fa77dac864e5 100644 --- a/examples/chef/linux/BUILD.gn +++ b/examples/chef/linux/BUILD.gn @@ -35,8 +35,6 @@ project_dir = "./.." chip_data_model("chef-data-model") { zap_file = "${project_dir}/devices/${sample_zap_file}" - zap_pregenerated_dir = - "${chip_root}/examples/chef/out/${sample_name}/zap-generated/" is_server = true } diff --git a/examples/chef/silabs/BUILD.gn b/examples/chef/silabs/BUILD.gn index 3f74106f9f54c2..528fe2f2cfc50a 100644 --- a/examples/chef/silabs/BUILD.gn +++ b/examples/chef/silabs/BUILD.gn @@ -48,8 +48,6 @@ declare_args() { chip_data_model("chef-common") { zap_file = "${chef_project_dir}/devices/${sample_name}.zap" - - zap_pregenerated_dir = "${chef_project_dir}/out/${sample_name}/zap-generated/" is_server = true } diff --git a/examples/contact-sensor-app/contact-sensor-common/BUILD.gn b/examples/contact-sensor-app/contact-sensor-common/BUILD.gn index d95af40a21a3ff..b95b549f746cb6 100755 --- a/examples/contact-sensor-app/contact-sensor-common/BUILD.gn +++ b/examples/contact-sensor-app/contact-sensor-common/BUILD.gn @@ -17,8 +17,5 @@ import("${chip_root}/src/app/chip_data_model.gni") chip_data_model("contact-sensor-common") { zap_file = "contact-sensor-app.zap" - - zap_pregenerated_dir = - "${chip_root}/zzz_generated/contact-sensor-app/zap-generated" is_server = true } diff --git a/examples/contact-sensor-app/nxp/zap-lit/BUILD.gn b/examples/contact-sensor-app/nxp/zap-lit/BUILD.gn index 7adfcbb7790a35..3baf5c4f59f105 100644 --- a/examples/contact-sensor-app/nxp/zap-lit/BUILD.gn +++ b/examples/contact-sensor-app/nxp/zap-lit/BUILD.gn @@ -18,8 +18,5 @@ import("${chip_root}/src/app/chip_data_model.gni") chip_data_model("zap-lit") { zap_file = "contact-sensor-app.zap" - - zap_pregenerated_dir = - "${chip_root}/zzz_generated/contact-sensor-app/nxp/zap-generated" is_server = true } diff --git a/examples/contact-sensor-app/nxp/zap-sit/BUILD.gn b/examples/contact-sensor-app/nxp/zap-sit/BUILD.gn index e9a20db41208d3..55fed097d333c8 100644 --- a/examples/contact-sensor-app/nxp/zap-sit/BUILD.gn +++ b/examples/contact-sensor-app/nxp/zap-sit/BUILD.gn @@ -18,8 +18,5 @@ import("${chip_root}/src/app/chip_data_model.gni") chip_data_model("zap-sit") { zap_file = "contact-sensor-app.zap" - - zap_pregenerated_dir = - "${chip_root}/zzz_generated/contact-sensor-app/nxp/zap-generated" is_server = true } diff --git a/examples/dishwasher-app/dishwasher-common/BUILD.gn b/examples/dishwasher-app/dishwasher-common/BUILD.gn index 01b634362098cd..73debf8ce3cbe1 100644 --- a/examples/dishwasher-app/dishwasher-common/BUILD.gn +++ b/examples/dishwasher-app/dishwasher-common/BUILD.gn @@ -21,8 +21,5 @@ config("config") { chip_data_model("dishwasher-common") { zap_file = "dishwasher-app.zap" - - zap_pregenerated_dir = - "${chip_root}/zzz_generated/dishwasher-app/zap-generated" is_server = true } diff --git a/examples/energy-management-app/energy-management-common/BUILD.gn b/examples/energy-management-app/energy-management-common/BUILD.gn index 7c2040c1a4dc37..937aca9f1746d0 100644 --- a/examples/energy-management-app/energy-management-common/BUILD.gn +++ b/examples/energy-management-app/energy-management-common/BUILD.gn @@ -22,8 +22,5 @@ config("config") { chip_data_model("energy-management-common") { zap_file = "energy-management-app.zap" - - zap_pregenerated_dir = - "${chip_root}/zzz_generated/energy-management-app/zap-generated" is_server = true } diff --git a/examples/light-switch-app/light-switch-common/BUILD.gn b/examples/light-switch-app/light-switch-common/BUILD.gn index 163e841678101a..8ec49aac0fa870 100644 --- a/examples/light-switch-app/light-switch-common/BUILD.gn +++ b/examples/light-switch-app/light-switch-common/BUILD.gn @@ -17,9 +17,5 @@ import("${chip_root}/src/app/chip_data_model.gni") chip_data_model("light-switch-common") { zap_file = "light-switch-app.zap" - - zap_pregenerated_dir = - "${chip_root}/zzz_generated/light-switch-app/zap-generated" - is_server = true } diff --git a/examples/light-switch-app/qpg/zap/BUILD.gn b/examples/light-switch-app/qpg/zap/BUILD.gn index 35ac7ff5f28346..87282159a25ab3 100644 --- a/examples/light-switch-app/qpg/zap/BUILD.gn +++ b/examples/light-switch-app/qpg/zap/BUILD.gn @@ -17,8 +17,5 @@ import("${chip_root}/src/app/chip_data_model.gni") chip_data_model("zap") { zap_file = "switch.zap" - - zap_pregenerated_dir = - "${chip_root}/zzz_generated/light-switch-app/qpg/zap-generated" is_server = true } diff --git a/examples/lighting-app/bouffalolab/bl602/BUILD.gn b/examples/lighting-app/bouffalolab/bl602/BUILD.gn index ab89ae3f3bdb63..7a4d4545e5ef28 100644 --- a/examples/lighting-app/bouffalolab/bl602/BUILD.gn +++ b/examples/lighting-app/bouffalolab/bl602/BUILD.gn @@ -90,8 +90,6 @@ bl_iot_sdk("sdk") { chip_data_model("bouffalolab-lighting") { zap_file = "${example_dir}/data_model/lighting-app-wifi.zap" - - zap_pregenerated_dir = "${chip_root}/zzz_generated/lighting-app/zap-generated" is_server = true } diff --git a/examples/lighting-app/bouffalolab/bl702/BUILD.gn b/examples/lighting-app/bouffalolab/bl702/BUILD.gn index f923e3bad6ffe9..05526ff9563e58 100644 --- a/examples/lighting-app/bouffalolab/bl702/BUILD.gn +++ b/examples/lighting-app/bouffalolab/bl702/BUILD.gn @@ -122,8 +122,6 @@ chip_data_model("bouffalolab-lighting") { } else { zap_file = "${example_dir}/data_model/lighting-app-ethernet.zap" } - - zap_pregenerated_dir = "${chip_root}/zzz_generated/lighting-app/zap-generated" is_server = true } diff --git a/examples/lighting-app/bouffalolab/bl702l/BUILD.gn b/examples/lighting-app/bouffalolab/bl702l/BUILD.gn index 24fad9ffa1897d..ea06cfa41ac001 100644 --- a/examples/lighting-app/bouffalolab/bl702l/BUILD.gn +++ b/examples/lighting-app/bouffalolab/bl702l/BUILD.gn @@ -99,8 +99,6 @@ bl_iot_sdk("sdk") { chip_data_model("bouffalolab-lighting") { zap_file = "${example_dir}/data_model/lighting-app-thread.zap" - - zap_pregenerated_dir = "${chip_root}/zzz_generated/lighting-app/zap-generated" is_server = true } diff --git a/examples/lighting-app/lighting-common/BUILD.gn b/examples/lighting-app/lighting-common/BUILD.gn index e983b3e0e0f11c..eb24b69dd214e1 100644 --- a/examples/lighting-app/lighting-common/BUILD.gn +++ b/examples/lighting-app/lighting-common/BUILD.gn @@ -21,8 +21,6 @@ config("config") { chip_data_model("lighting-common") { zap_file = "lighting-app.zap" - - zap_pregenerated_dir = "${chip_root}/zzz_generated/lighting-app/zap-generated" is_server = true } diff --git a/examples/lighting-app/nxp/zap/BUILD.gn b/examples/lighting-app/nxp/zap/BUILD.gn index fd4026e2b9dbf7..4280629a03cc3a 100644 --- a/examples/lighting-app/nxp/zap/BUILD.gn +++ b/examples/lighting-app/nxp/zap/BUILD.gn @@ -18,8 +18,5 @@ import("${chip_root}/src/app/chip_data_model.gni") chip_data_model("zap") { zap_file = "lighting-on-off.zap" - - zap_pregenerated_dir = - "${chip_root}/zzz_generated/lighting-app/nxp/zap-generated" is_server = true } diff --git a/examples/lighting-app/qpg/zap/BUILD.gn b/examples/lighting-app/qpg/zap/BUILD.gn index ec69db0b412a8c..c9de674a2bf8c8 100644 --- a/examples/lighting-app/qpg/zap/BUILD.gn +++ b/examples/lighting-app/qpg/zap/BUILD.gn @@ -17,8 +17,5 @@ import("${chip_root}/src/app/chip_data_model.gni") chip_data_model("zap") { zap_file = "light.zap" - - zap_pregenerated_dir = - "${chip_root}/zzz_generated/lighting-app/qpg/zap-generated" is_server = true } diff --git a/examples/lighting-app/silabs/data_model/BUILD.gn b/examples/lighting-app/silabs/data_model/BUILD.gn index 9f1ee0d2aee78e..45062169315f03 100644 --- a/examples/lighting-app/silabs/data_model/BUILD.gn +++ b/examples/lighting-app/silabs/data_model/BUILD.gn @@ -22,7 +22,5 @@ chip_data_model("silabs-lighting") { } else { zap_file = "lighting-thread-app.zap" } - - zap_pregenerated_dir = "${chip_root}/zzz_generated/lighting-app/zap-generated" is_server = true } diff --git a/examples/lit-icd-app/lit-icd-common/BUILD.gn b/examples/lit-icd-app/lit-icd-common/BUILD.gn index a20d519c1cd7fa..28aa29a3981a69 100644 --- a/examples/lit-icd-app/lit-icd-common/BUILD.gn +++ b/examples/lit-icd-app/lit-icd-common/BUILD.gn @@ -17,8 +17,5 @@ import("${chip_root}/src/app/chip_data_model.gni") chip_data_model("lit-icd-common") { zap_file = "lit-icd-server-app.zap" - - zap_pregenerated_dir = - "${chip_root}/zzz_generated/lit-icd-server-app/zap-generated" is_server = true } diff --git a/examples/lock-app/lock-common/BUILD.gn b/examples/lock-app/lock-common/BUILD.gn index bb01a5185f80f7..1312ec49bd134f 100644 --- a/examples/lock-app/lock-common/BUILD.gn +++ b/examples/lock-app/lock-common/BUILD.gn @@ -17,8 +17,6 @@ import("${chip_root}/src/app/chip_data_model.gni") chip_data_model("lock-common") { zap_file = "lock-app.zap" - - zap_pregenerated_dir = "${chip_root}/zzz_generated/lock-app/zap-generated" is_server = true } diff --git a/examples/lock-app/nxp/zap/BUILD.gn b/examples/lock-app/nxp/zap/BUILD.gn index cc5fe9361c32a3..a21a2d57a57212 100644 --- a/examples/lock-app/nxp/zap/BUILD.gn +++ b/examples/lock-app/nxp/zap/BUILD.gn @@ -17,7 +17,5 @@ import("${chip_root}/src/app/chip_data_model.gni") chip_data_model("zap") { zap_file = "lock-app.zap" - - zap_pregenerated_dir = "${chip_root}/zzz_generated/lock-app/nxp/zap-generated" is_server = true } diff --git a/examples/lock-app/qpg/zap/BUILD.gn b/examples/lock-app/qpg/zap/BUILD.gn index 67e29db5f3f249..8560b5249ca5c9 100644 --- a/examples/lock-app/qpg/zap/BUILD.gn +++ b/examples/lock-app/qpg/zap/BUILD.gn @@ -17,7 +17,5 @@ import("${chip_root}/src/app/chip_data_model.gni") chip_data_model("zap") { zap_file = "lock.zap" - - zap_pregenerated_dir = "${chip_root}/zzz_generated/lock-app/qpg/zap-generated" is_server = true } diff --git a/examples/log-source-app/log-source-common/BUILD.gn b/examples/log-source-app/log-source-common/BUILD.gn index 1c434c209fb057..9aa178c078ed82 100644 --- a/examples/log-source-app/log-source-common/BUILD.gn +++ b/examples/log-source-app/log-source-common/BUILD.gn @@ -23,9 +23,6 @@ config("config") { chip_data_model("log-source-common") { zap_file = "log-source-app.zap" - zap_pregenerated_dir = - "${chip_root}/zzz_generated/log-source-app/zap-generated" - deps = [ "${chip_root}/src/protocols/bdx" ] is_server = true diff --git a/examples/microwave-oven-app/microwave-oven-common/BUILD.gn b/examples/microwave-oven-app/microwave-oven-common/BUILD.gn index 121f067a6a7d75..dd91ce23a30eed 100644 --- a/examples/microwave-oven-app/microwave-oven-common/BUILD.gn +++ b/examples/microwave-oven-app/microwave-oven-common/BUILD.gn @@ -21,8 +21,5 @@ config("config") { chip_data_model("microwave-oven-common") { zap_file = "microwave-oven-app.zap" - - zap_pregenerated_dir = - "${chip_root}/zzz_generated/microwave-oven-app/zap-generated" is_server = true } diff --git a/examples/network-manager-app/network-manager-common/BUILD.gn b/examples/network-manager-app/network-manager-common/BUILD.gn index eced7ddbbbff7a..e220377a7963cb 100644 --- a/examples/network-manager-app/network-manager-common/BUILD.gn +++ b/examples/network-manager-app/network-manager-common/BUILD.gn @@ -17,8 +17,5 @@ import("${chip_root}/src/app/chip_data_model.gni") chip_data_model("network-manager-common") { zap_file = "network-manager-app.zap" - - zap_pregenerated_dir = - "${chip_root}/zzz_generated/network-manager-app/zap-generated" is_server = true } diff --git a/examples/ota-provider-app/ota-provider-common/BUILD.gn b/examples/ota-provider-app/ota-provider-common/BUILD.gn index 63c5f2d1de5083..c13b1e1e73254c 100644 --- a/examples/ota-provider-app/ota-provider-common/BUILD.gn +++ b/examples/ota-provider-app/ota-provider-common/BUILD.gn @@ -23,9 +23,6 @@ config("config") { chip_data_model("ota-provider-common") { zap_file = "ota-provider-app.zap" - zap_pregenerated_dir = - "${chip_root}/zzz_generated/ota-provider-app/zap-generated" - sources = [ "BdxOtaSender.cpp", "BdxOtaSender.h", diff --git a/examples/ota-requestor-app/ota-requestor-common/BUILD.gn b/examples/ota-requestor-app/ota-requestor-common/BUILD.gn index edce1324ea7e1f..550d4c09aeb968 100644 --- a/examples/ota-requestor-app/ota-requestor-common/BUILD.gn +++ b/examples/ota-requestor-app/ota-requestor-common/BUILD.gn @@ -23,9 +23,6 @@ config("config") { chip_data_model("ota-requestor-common") { zap_file = "ota-requestor-app.zap" - zap_pregenerated_dir = - "${chip_root}/zzz_generated/ota-requestor-app/zap-generated" - deps = [ "${chip_root}/src/lib" ] public_configs = [ ":config" ] diff --git a/examples/placeholder/linux/apps/app1/BUILD.gn b/examples/placeholder/linux/apps/app1/BUILD.gn index ef7c277ec7f663..f16b9301ce3a90 100644 --- a/examples/placeholder/linux/apps/app1/BUILD.gn +++ b/examples/placeholder/linux/apps/app1/BUILD.gn @@ -17,9 +17,6 @@ import("${chip_root}/src/app/chip_data_model.gni") chip_data_model("configuration") { zap_file = "config.zap" - - zap_pregenerated_dir = - "${chip_root}/zzz_generated/placeholder/app1/zap-generated" is_server = true } diff --git a/examples/placeholder/linux/apps/app2/BUILD.gn b/examples/placeholder/linux/apps/app2/BUILD.gn index 5c18b7d2dc0914..2bea36611ffb37 100644 --- a/examples/placeholder/linux/apps/app2/BUILD.gn +++ b/examples/placeholder/linux/apps/app2/BUILD.gn @@ -17,9 +17,6 @@ import("${chip_root}/src/app/chip_data_model.gni") chip_data_model("configuration") { zap_file = "config.zap" - - zap_pregenerated_dir = - "${chip_root}/zzz_generated/placeholder/app2/zap-generated" is_server = true } diff --git a/examples/pump-app/pump-common/BUILD.gn b/examples/pump-app/pump-common/BUILD.gn index 58508f60af8adb..1e7280f5190079 100644 --- a/examples/pump-app/pump-common/BUILD.gn +++ b/examples/pump-app/pump-common/BUILD.gn @@ -18,7 +18,5 @@ import("${chip_root}/src/app/chip_data_model.gni") chip_data_model("pump-common") { zap_file = "pump-app.zap" - - zap_pregenerated_dir = "${chip_root}/zzz_generated/pump-app/zap-generated" is_server = true } diff --git a/examples/pump-app/silabs/data_model/BUILD.gn b/examples/pump-app/silabs/data_model/BUILD.gn index 35d878aedcb90f..230ba5406364e3 100644 --- a/examples/pump-app/silabs/data_model/BUILD.gn +++ b/examples/pump-app/silabs/data_model/BUILD.gn @@ -22,7 +22,5 @@ chip_data_model("silabs-pump") { } else { zap_file = "pump-thread-app.zap" } - - zap_pregenerated_dir = "${chip_root}/zzz_generated/pump-app/zap-generated" is_server = true } diff --git a/examples/pump-controller-app/pump-controller-common/BUILD.gn b/examples/pump-controller-app/pump-controller-common/BUILD.gn index e62de422b08097..82e222e43ff4e1 100644 --- a/examples/pump-controller-app/pump-controller-common/BUILD.gn +++ b/examples/pump-controller-app/pump-controller-common/BUILD.gn @@ -18,8 +18,5 @@ import("${chip_root}/src/app/chip_data_model.gni") chip_data_model("pump-controller-common") { zap_file = "pump-controller-app.zap" - - zap_pregenerated_dir = - "${chip_root}/zzz_generated/pump-controller-app/zap-generated" is_server = true } diff --git a/examples/refrigerator-app/refrigerator-common/BUILD.gn b/examples/refrigerator-app/refrigerator-common/BUILD.gn index c747755e86c598..4e8e72bb343ff3 100644 --- a/examples/refrigerator-app/refrigerator-common/BUILD.gn +++ b/examples/refrigerator-app/refrigerator-common/BUILD.gn @@ -21,8 +21,5 @@ config("config") { chip_data_model("refrigerator-common") { zap_file = "refrigerator-app.zap" - - zap_pregenerated_dir = - "${chip_root}/zzz_generated/refrigerator-app/zap-generated" is_server = true } diff --git a/examples/rvc-app/rvc-common/BUILD.gn b/examples/rvc-app/rvc-common/BUILD.gn index d567043f3ee346..2491f97d9b9809 100644 --- a/examples/rvc-app/rvc-common/BUILD.gn +++ b/examples/rvc-app/rvc-common/BUILD.gn @@ -21,7 +21,5 @@ config("config") { chip_data_model("rvc-common") { zap_file = "rvc-app.zap" - - zap_pregenerated_dir = "${chip_root}/zzz_generated/rvc-app/zap-generated" is_server = true } diff --git a/examples/smoke-co-alarm-app/smoke-co-alarm-common/BUILD.gn b/examples/smoke-co-alarm-app/smoke-co-alarm-common/BUILD.gn index 16e5328c1ba01c..6e78dcbf5c4f92 100644 --- a/examples/smoke-co-alarm-app/smoke-co-alarm-common/BUILD.gn +++ b/examples/smoke-co-alarm-app/smoke-co-alarm-common/BUILD.gn @@ -17,8 +17,5 @@ import("${chip_root}/src/app/chip_data_model.gni") chip_data_model("smoke-co-alarm-common") { zap_file = "smoke-co-alarm-app.zap" - - zap_pregenerated_dir = - "${chip_root}/zzz_generated/smoke-co-alarm-app/zap-generated" is_server = true } diff --git a/examples/temperature-measurement-app/temperature-measurement-common/BUILD.gn b/examples/temperature-measurement-app/temperature-measurement-common/BUILD.gn index 0430c288a90354..1f0f2daea65c76 100644 --- a/examples/temperature-measurement-app/temperature-measurement-common/BUILD.gn +++ b/examples/temperature-measurement-app/temperature-measurement-common/BUILD.gn @@ -18,8 +18,5 @@ import("${chip_root}/src/app/chip_data_model.gni") chip_data_model("temperature-measurement-common") { zap_file = "temperature-measurement.zap" - - zap_pregenerated_dir = - "${chip_root}/zzz_generated/temperature-measurement/zap-generated" is_server = true } diff --git a/examples/thermostat/nxp/zap/BUILD.gn b/examples/thermostat/nxp/zap/BUILD.gn index 976cd78f2e1a79..c3a3df7bd6729e 100644 --- a/examples/thermostat/nxp/zap/BUILD.gn +++ b/examples/thermostat/nxp/zap/BUILD.gn @@ -28,7 +28,5 @@ chip_data_model("zap") { zap_file = "thermostat_matter_thread.zap" } - # Defining zap_pregenerated_dir is required by chip_data_model.gni in order to build IMClusterCommandHandler.cpp - zap_pregenerated_dir = "" is_server = true } diff --git a/examples/thermostat/qpg/zap/BUILD.gn b/examples/thermostat/qpg/zap/BUILD.gn index 38074c904f32eb..3ea8a750459afc 100644 --- a/examples/thermostat/qpg/zap/BUILD.gn +++ b/examples/thermostat/qpg/zap/BUILD.gn @@ -17,8 +17,5 @@ import("${chip_root}/src/app/chip_data_model.gni") chip_data_model("zap") { zap_file = "thermostaticRadiatorValve.zap" - - zap_pregenerated_dir = - "${chip_root}/zzz_generated/thermostat/qpg/zap-generated" is_server = true } diff --git a/examples/thermostat/thermostat-common/BUILD.gn b/examples/thermostat/thermostat-common/BUILD.gn index 7f35acfdf371ad..93a0c7540fb93a 100644 --- a/examples/thermostat/thermostat-common/BUILD.gn +++ b/examples/thermostat/thermostat-common/BUILD.gn @@ -18,7 +18,5 @@ import("${chip_root}/src/app/chip_data_model.gni") chip_data_model("thermostat-common") { zap_file = "thermostat.zap" - - zap_pregenerated_dir = "${chip_root}/zzz_generated/thermostat/zap-generated" is_server = true } diff --git a/examples/tv-app/tv-common/BUILD.gn b/examples/tv-app/tv-common/BUILD.gn index 699a13a20ec6e0..c253459d177caa 100644 --- a/examples/tv-app/tv-common/BUILD.gn +++ b/examples/tv-app/tv-common/BUILD.gn @@ -19,8 +19,6 @@ import("${chip_root}/src/lib/lib.gni") chip_data_model("tv-common") { zap_file = "tv-app.zap" - - zap_pregenerated_dir = "${chip_root}/zzz_generated/tv-app/zap-generated" is_server = true } diff --git a/examples/tv-casting-app/tv-casting-common/BUILD.gn b/examples/tv-casting-app/tv-casting-common/BUILD.gn index 38b983485c1800..ea6607a724b5cb 100644 --- a/examples/tv-casting-app/tv-casting-common/BUILD.gn +++ b/examples/tv-casting-app/tv-casting-common/BUILD.gn @@ -34,9 +34,6 @@ config("config") { chip_data_model("tv-casting-common") { zap_file = "tv-casting-app.zap" - zap_pregenerated_dir = - "${chip_root}/zzz_generated/tv-casting-app/zap-generated" - sources = [ "${chip_root}/examples/chip-tool/commands/clusters/ModelCommand.h", "${chip_root}/examples/chip-tool/commands/common/BDXDiagnosticLogsServerDelegate.cpp", diff --git a/examples/virtual-device-app/virtual-device-common/BUILD.gn b/examples/virtual-device-app/virtual-device-common/BUILD.gn index 73be6ac9628be1..82eaf78d8f63e6 100644 --- a/examples/virtual-device-app/virtual-device-common/BUILD.gn +++ b/examples/virtual-device-app/virtual-device-common/BUILD.gn @@ -19,8 +19,5 @@ import("${chip_root}/src/lib/lib.gni") chip_data_model("virtual-device-common") { zap_file = "virtual-device-app.zap" - - zap_pregenerated_dir = - "${chip_root}/zzz_generated/virtual-device-app/zap-generated" is_server = true } diff --git a/examples/window-app/common/BUILD.gn b/examples/window-app/common/BUILD.gn index 42941ee10d38d5..62fbc3aa3da4cf 100644 --- a/examples/window-app/common/BUILD.gn +++ b/examples/window-app/common/BUILD.gn @@ -18,7 +18,5 @@ import("${chip_root}/src/app/chip_data_model.gni") chip_data_model("window-common") { zap_file = "window-app.zap" - - zap_pregenerated_dir = "${chip_root}/zzz_generated/window-app/zap-generated" is_server = true } diff --git a/src/app/chip_data_model.gni b/src/app/chip_data_model.gni index 85f5224ada7d37..3763243e404407 100644 --- a/src/app/chip_data_model.gni +++ b/src/app/chip_data_model.gni @@ -23,9 +23,6 @@ _app_root = get_path_info(".", "abspath") # Defines a source_set for CHIP data model. # # Arguments: -# zap_pregenerated_dir -# Path to the ZAP "gen" dir. -# # zap_file # Path to the ZAP input file. # @@ -54,14 +51,6 @@ template("chip_data_model") { _idl = string_replace(invoker.zap_file, ".zap", ".matter") } - config("${_data_model_name}_config") { - include_dirs = [] - - if (defined(invoker.zap_pregenerated_dir)) { - include_dirs += [ "${invoker.zap_pregenerated_dir}/.." ] - } - } - chip_zapgen("${_data_model_name}_zapgen") { input = rebase_path(invoker.zap_file) generator = "app-templates" @@ -82,18 +71,7 @@ template("chip_data_model") { prune_outputs = [] } - # TODO: It is unclear here why `zap_pregenerated_dir` has any relevance - # in including IMClusterCommandHandler or not. - # - # This logic has been carried over from previous code during compile - # time codegen addition, however the rationale of why pregenerated - # dir controls IMClusterCommandHandler needs to be explained and - # potentially controlled by a clearer variable (is this for controllers? - # is this during app compile but not others? I am unclear what - # zap_pregenerated_dir is supposed to convey. Existence of a directory - # does not obviously map to "need command handler cpp compiled in"). - if (defined(invoker.zap_pregenerated_dir) && - !chip_build_controller_dynamic_server) { + if (!chip_build_controller_dynamic_server) { outputs += [ "zap-generated/IMClusterCommandHandler.cpp" ] } else { if (defined(prune_outputs)) { @@ -101,8 +79,6 @@ template("chip_data_model") { } } - public_configs = [ ":${_data_model_name}_config" ] - if (!defined(deps)) { deps = [] } @@ -120,8 +96,6 @@ template("chip_data_model") { "app/cluster-init-callback.cpp", ] - public_configs = [ ":${_data_model_name}_config" ] - if (!defined(deps)) { deps = [] } @@ -136,7 +110,6 @@ template("chip_data_model") { forward_variables_from(invoker, "*", [ - "zap_pregenerated_dir", "zap_file", "is_server", "external_clusters", @@ -390,11 +363,5 @@ template("chip_data_model") { if (non_spec_compliant_ota_action_delay_floor >= 0) { cflags += [ "-DNON_SPEC_COMPLIANT_OTA_ACTION_DELAY_FLOOR=${non_spec_compliant_ota_action_delay_floor}" ] } - - if (!defined(public_configs)) { - public_configs = [] - } - - public_configs += [ ":${_data_model_name}_config" ] } } diff --git a/src/controller/data_model/BUILD.gn b/src/controller/data_model/BUILD.gn index 3b66d026699908..a0b57e7b91fc1e 100644 --- a/src/controller/data_model/BUILD.gn +++ b/src/controller/data_model/BUILD.gn @@ -42,9 +42,5 @@ chip_codegen("cluster-tlv-metadata") { chip_data_model("data_model") { zap_file = "controller-clusters.zap" - - zap_pregenerated_dir = - "${chip_root}/zzz_generated/controller-clusters/zap-generated" - allow_circular_includes_from = [ "${chip_root}/src/controller" ] } From 1cac17326c5c8e01fcdaa5b1808fa441ebea312c Mon Sep 17 00:00:00 2001 From: Andrei Litvin Date: Thu, 22 Feb 2024 17:15:02 -0500 Subject: [PATCH 064/385] Bump pigweed to latest version (#32264) * Bump pigweed * Remove EnumCastOutOfRange check - todo to enable it later * zap-regen: apparently clang-format version changed * Minor updates based on clang-tidy feedback * Update size_t for RecordWriter.cpp * Restore pigweed update --------- Co-authored-by: Andrei Litvin --- .clang-tidy | 1 + .../app-templates/endpoint_config.h | 34 +++++++++---------- .../dnssd/minimal_mdns/core/RecordWriter.cpp | 2 +- src/lib/shell/commands/Dns.cpp | 2 +- src/lib/support/tests/TestIniEscaping.cpp | 1 - third_party/pigweed/repo | 2 +- 6 files changed, 21 insertions(+), 21 deletions(-) diff --git a/.clang-tidy b/.clang-tidy index b494558e513460..fcb62d5d505d32 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -35,6 +35,7 @@ Checks: > -clang-analyzer-cplusplus.Move, -clang-analyzer-deadcode.DeadStores, -clang-analyzer-nullability.NullablePassedToNonnull, + -clang-analyzer-optin.core.EnumCastOutOfRange, -clang-analyzer-optin.cplusplus.UninitializedObject, -clang-analyzer-optin.cplusplus.VirtualCall, -clang-analyzer-optin.osx.cocoa.localizability.EmptyLocalizationContextChecker, diff --git a/scripts/tools/zap/tests/outputs/all-clusters-app/app-templates/endpoint_config.h b/scripts/tools/zap/tests/outputs/all-clusters-app/app-templates/endpoint_config.h index 6985b44ac27da5..38f04fbfea5857 100644 --- a/scripts/tools/zap/tests/outputs/all-clusters-app/app-templates/endpoint_config.h +++ b/scripts/tools/zap/tests/outputs/all-clusters-app/app-templates/endpoint_config.h @@ -302,15 +302,15 @@ { (uint16_t) 0x0, (uint16_t) 0x0, (uint16_t) 0x7 }, /* ControlMode */ \ \ /* Endpoint: 1, Cluster: Thermostat (server) */ \ - { (uint16_t) 0xA28, (uint16_t) -0x6AB3, (uint16_t) 0x7FFF }, /* OccupiedCoolingSetpoint */ \ - { (uint16_t) 0x7D0, (uint16_t) -0x6AB3, (uint16_t) 0x7FFF }, /* OccupiedHeatingSetpoint */ \ - { (uint16_t) 0x2BC, (uint16_t) -0x6AB3, (uint16_t) 0x7FFF }, /* MinHeatSetpointLimit */ \ - { (uint16_t) 0xBB8, (uint16_t) -0x6AB3, (uint16_t) 0x7FFF }, /* MaxHeatSetpointLimit */ \ - { (uint16_t) 0x640, (uint16_t) -0x6AB3, (uint16_t) 0x7FFF }, /* MinCoolSetpointLimit */ \ - { (uint16_t) 0xC80, (uint16_t) -0x6AB3, (uint16_t) 0x7FFF }, /* MaxCoolSetpointLimit */ \ - { (uint16_t) 0x19, (uint16_t) 0x0, (uint16_t) 0x19 }, /* MinSetpointDeadBand */ \ - { (uint16_t) 0x4, (uint16_t) 0x0, (uint16_t) 0x5 }, /* ControlSequenceOfOperation */ \ - { (uint16_t) 0x1, (uint16_t) 0x0, (uint16_t) 0x9 }, /* SystemMode */ \ + { (uint16_t) 0xA28, (uint16_t) - 0x6AB3, (uint16_t) 0x7FFF }, /* OccupiedCoolingSetpoint */ \ + { (uint16_t) 0x7D0, (uint16_t) - 0x6AB3, (uint16_t) 0x7FFF }, /* OccupiedHeatingSetpoint */ \ + { (uint16_t) 0x2BC, (uint16_t) - 0x6AB3, (uint16_t) 0x7FFF }, /* MinHeatSetpointLimit */ \ + { (uint16_t) 0xBB8, (uint16_t) - 0x6AB3, (uint16_t) 0x7FFF }, /* MaxHeatSetpointLimit */ \ + { (uint16_t) 0x640, (uint16_t) - 0x6AB3, (uint16_t) 0x7FFF }, /* MinCoolSetpointLimit */ \ + { (uint16_t) 0xC80, (uint16_t) - 0x6AB3, (uint16_t) 0x7FFF }, /* MaxCoolSetpointLimit */ \ + { (uint16_t) 0x19, (uint16_t) 0x0, (uint16_t) 0x19 }, /* MinSetpointDeadBand */ \ + { (uint16_t) 0x4, (uint16_t) 0x0, (uint16_t) 0x5 }, /* ControlSequenceOfOperation */ \ + { (uint16_t) 0x1, (uint16_t) 0x0, (uint16_t) 0x9 }, /* SystemMode */ \ \ /* Endpoint: 1, Cluster: Fan Control (server) */ \ { (uint16_t) 0x0, (uint16_t) 0x0, (uint16_t) 0x6 }, /* FanMode */ \ @@ -334,14 +334,14 @@ { (uint16_t) 0x0, (uint16_t) 0x0, (uint16_t) 0xFEFF }, /* StartUpColorTemperatureMireds */ \ \ /* Endpoint: 1, Cluster: Unit Testing (server) */ \ - { (uint16_t) 0x46, (uint16_t) 0x14, (uint16_t) 0x64 }, /* range_restricted_int8u */ \ - { (uint16_t) -0x14, (uint16_t) -0x28, (uint16_t) 0x32 }, /* range_restricted_int8s */ \ - { (uint16_t) 0xC8, (uint16_t) 0x64, (uint16_t) 0x3E8 }, /* range_restricted_int16u */ \ - { (uint16_t) -0x64, (uint16_t) -0x96, (uint16_t) 0xC8 }, /* range_restricted_int16s */ \ - { (uint16_t) 0x46, (uint16_t) 0x14, (uint16_t) 0x64 }, /* nullable_range_restricted_int8u */ \ - { (uint16_t) -0x14, (uint16_t) -0x28, (uint16_t) 0x32 }, /* nullable_range_restricted_int8s */ \ - { (uint16_t) 0xC8, (uint16_t) 0x64, (uint16_t) 0x3E8 }, /* nullable_range_restricted_int16u */ \ - { (uint16_t) -0x64, (uint16_t) -0x96, (uint16_t) 0xC8 }, /* nullable_range_restricted_int16s */ \ + { (uint16_t) 0x46, (uint16_t) 0x14, (uint16_t) 0x64 }, /* range_restricted_int8u */ \ + { (uint16_t) - 0x14, (uint16_t) - 0x28, (uint16_t) 0x32 }, /* range_restricted_int8s */ \ + { (uint16_t) 0xC8, (uint16_t) 0x64, (uint16_t) 0x3E8 }, /* range_restricted_int16u */ \ + { (uint16_t) - 0x64, (uint16_t) - 0x96, (uint16_t) 0xC8 }, /* range_restricted_int16s */ \ + { (uint16_t) 0x46, (uint16_t) 0x14, (uint16_t) 0x64 }, /* nullable_range_restricted_int8u */ \ + { (uint16_t) - 0x14, (uint16_t) - 0x28, (uint16_t) 0x32 }, /* nullable_range_restricted_int8s */ \ + { (uint16_t) 0xC8, (uint16_t) 0x64, (uint16_t) 0x3E8 }, /* nullable_range_restricted_int16u */ \ + { (uint16_t) - 0x64, (uint16_t) - 0x96, (uint16_t) 0xC8 }, /* nullable_range_restricted_int16s */ \ \ /* Endpoint: 2, Cluster: On/Off (server) */ \ { \ diff --git a/src/lib/dnssd/minimal_mdns/core/RecordWriter.cpp b/src/lib/dnssd/minimal_mdns/core/RecordWriter.cpp index 0249d80d6e35ff..41e9985687ad81 100644 --- a/src/lib/dnssd/minimal_mdns/core/RecordWriter.cpp +++ b/src/lib/dnssd/minimal_mdns/core/RecordWriter.cpp @@ -41,7 +41,7 @@ RecordWriter & RecordWriter::WriteQName(const FullQName & qname) size_t qNameWriteStart = mOutput->WritePos(); bool isFullyCompressed = true; - for (uint16_t i = 0; i < qname.nameCount; i++) + for (size_t i = 0; i < qname.nameCount; i++) { // find out if the record part remaining already is located somewhere diff --git a/src/lib/shell/commands/Dns.cpp b/src/lib/shell/commands/Dns.cpp index badd6681fceec3..6abb2dc0393fec 100644 --- a/src/lib/shell/commands/Dns.cpp +++ b/src/lib/shell/commands/Dns.cpp @@ -131,7 +131,7 @@ class DnsShellResolverDelegate : public Dnssd::CommissioningResolveDelegate, pub nodeData.resolutionData.isICDOperatingAsLIT.Value() ? "LIT" : "SIT"); } streamer_printf(streamer_get(), " IP addresses:\r\n"); - for (uint8_t i = 0; i < nodeData.resolutionData.numIPs; i++) + for (size_t i = 0; i < nodeData.resolutionData.numIPs; i++) { streamer_printf(streamer_get(), " %s\r\n", nodeData.resolutionData.ipAddress[i].ToString(ipAddressBuf)); } diff --git a/src/lib/support/tests/TestIniEscaping.cpp b/src/lib/support/tests/TestIniEscaping.cpp index 44f8b37058b3cb..784a8fffdcb156 100644 --- a/src/lib/support/tests/TestIniEscaping.cpp +++ b/src/lib/support/tests/TestIniEscaping.cpp @@ -45,7 +45,6 @@ void TestUnescaping(nlTestSuite * inSuite, void * inContext) // Test valid cases NL_TEST_ASSERT(inSuite, UnescapeKey("") == ""); NL_TEST_ASSERT(inSuite, UnescapeKey("abcd1234,!") == "abcd1234,!"); - std::string out = UnescapeKey("abcd1234,!"); NL_TEST_ASSERT(inSuite, UnescapeKey("ab\\x0acd\\x20\\x3d12\\x5c34\\x7f") == "ab\ncd =12\\34\x7f"); NL_TEST_ASSERT(inSuite, UnescapeKey("\\x20") == " "); NL_TEST_ASSERT(inSuite, UnescapeKey("\\x3d\\x3d\\x3d") == "==="); diff --git a/third_party/pigweed/repo b/third_party/pigweed/repo index 0380161bd68c21..5165b9c17a9933 160000 --- a/third_party/pigweed/repo +++ b/third_party/pigweed/repo @@ -1 +1 @@ -Subproject commit 0380161bd68c216a590230f0cc49d26add7eef8a +Subproject commit 5165b9c17a9933b8d0714ef701421bf065d5d66a From 6af0d149bfd850ce5a89d1f73a5a92b17f385097 Mon Sep 17 00:00:00 2001 From: Tennessee Carmel-Veilleux Date: Thu, 22 Feb 2024 17:44:52 -0500 Subject: [PATCH 065/385] Set extended default advertising to be 1285ms (#32277) * Set extended default advertising to be 1285ms - 1285ms is more reliable than 1200ms in general (https://github.com/CHIP-Specifications/connectedhomeip-spec/pull/8965) - Update TC-DD-2.1 script to match (https://github.com/CHIP-Specifications/chip-test-plans/pull/4020) - Update EFR32 platform to be tolerant of min==max for advertising rate Issue #32274 Fixes #32275 Testing done: - Linux builds, still discoverable, extended rate 1285ms - Tested with nRFConnect - EFR32 builds, still discoverable, extended rate 1285ms +/- 2ms - Tested with nRFConnect and xG24 Explorer kit * Restyled by clang-format --------- Co-authored-by: Restyled.io --- .../suites/certification/Test_TC_DD_2_1.yaml | 5 +++-- src/include/platform/CHIPDeviceConfig.h | 18 ++++++++---------- src/platform/silabs/efr32/BLEManagerImpl.cpp | 7 +++++++ 3 files changed, 18 insertions(+), 12 deletions(-) diff --git a/src/app/tests/suites/certification/Test_TC_DD_2_1.yaml b/src/app/tests/suites/certification/Test_TC_DD_2_1.yaml index 07533321325728..94888631f6a143 100644 --- a/src/app/tests/suites/certification/Test_TC_DD_2_1.yaml +++ b/src/app/tests/suites/certification/Test_TC_DD_2_1.yaml @@ -123,8 +123,9 @@ tests: Try NRF Connect app (https://www.nordicsemi.com/Products/Development-tools/nrf-connect-for-desktop) OR HCIDump (https://ubuntu.com/core/docs/bluez/reference/commands) - ->For T0 and 30s we have to get advertisement range between 20ms to 60ms - ->For 30s and 15mins we have to get advertisement range between 150ms to 1200ms + ->Between [0 .. 30s[ expect advertisement range between 20ms to 60ms. + ->Between [30s .. 900s[ expect advertisement range between 150ms to 1285ms. Allow +/- 10ms margin on the measured value. + ->Starting at 900s expect advertisement range larger or equal to 1200ms. disabled: true - label: "Step 6: TH does not respond to DUT. User power cycles the DUT" diff --git a/src/include/platform/CHIPDeviceConfig.h b/src/include/platform/CHIPDeviceConfig.h index 6ee7d9c9634999..88ef78d1005314 100644 --- a/src/include/platform/CHIPDeviceConfig.h +++ b/src/include/platform/CHIPDeviceConfig.h @@ -647,28 +647,26 @@ * CHIP_DEVICE_CONFIG_BLE_EXT_ADVERTISING_INTERVAL_MIN * * The minimum interval (in units of 0.625ms) at which the device will send BLE advertisements while - * in the extended advertising mode. The minimum interval shall not be smaller than the default value - * and should not be equal to the CHIP_DEVICE_CONFIG_BLE_EXT_ADVERTISING_INTERVAL_MAX. + * in the extended advertising mode. The minimum interval shall not be smaller than the default value. * - * Defaults to 1920 (1200 ms). + * Defaults to 2056 (1285 ms). */ -#define CHIP_DEVICE_CONFIG_BLE_EXT_ADVERTISING_INTERVAL_MIN 1920 +#define CHIP_DEVICE_CONFIG_BLE_EXT_ADVERTISING_INTERVAL_MIN 2056 /** * CHIP_DEVICE_CONFIG_BLE_EXT_ADVERTISING_INTERVAL_MAX * * The maximum interval (in units of 0.625ms) at which the device will send BLE advertisements while - * in the extended advertising mode. The maximum interval should be greater and not equal to the - * CHIP_DEVICE_CONFIG_BLE_EXT_ADVERTISING_INTERVAL_MIN. + * in the extended advertising mode. The maximum interval should be greater. * - * Defaults to 1936 (1210 ms). + * Defaults to 2056 (1285 ms). */ #ifndef CHIP_DEVICE_CONFIG_BLE_EXT_ADVERTISING_INTERVAL_MAX -#define CHIP_DEVICE_CONFIG_BLE_EXT_ADVERTISING_INTERVAL_MAX 1936 +#define CHIP_DEVICE_CONFIG_BLE_EXT_ADVERTISING_INTERVAL_MAX 2056 #endif -static_assert(CHIP_DEVICE_CONFIG_BLE_EXT_ADVERTISING_INTERVAL_MIN < CHIP_DEVICE_CONFIG_BLE_EXT_ADVERTISING_INTERVAL_MAX, - "Max Extended Advertising Interval cannot be smaller or equal to the Min Extended Advertising Interval"); +static_assert(CHIP_DEVICE_CONFIG_BLE_EXT_ADVERTISING_INTERVAL_MIN <= CHIP_DEVICE_CONFIG_BLE_EXT_ADVERTISING_INTERVAL_MAX, + "Max Extended Advertising Interval cannot be larger to the Min Extended Advertising Interval"); #endif diff --git a/src/platform/silabs/efr32/BLEManagerImpl.cpp b/src/platform/silabs/efr32/BLEManagerImpl.cpp index bd4aee39cf8160..4df91ad23368bb 100644 --- a/src/platform/silabs/efr32/BLEManagerImpl.cpp +++ b/src/platform/silabs/efr32/BLEManagerImpl.cpp @@ -582,6 +582,13 @@ CHIP_ERROR BLEManagerImpl::StartAdvertising(void) #endif } + // TODO(#32274): Explain why we cannot have interval_min == interval_max. + if (interval_min == interval_max) + { + ++interval_max; + } + ChipLogProgress(DeviceLayer, "Starting advertising with interval_min=%u, intverval_max=%u (units of 625us)", + static_cast(interval_min), static_cast(interval_max)); ret = sl_bt_advertiser_set_timing(advertising_set_handle, interval_min, interval_max, 0, 0); err = MapBLEError(ret); SuccessOrExit(err); From 524b8a8734b0a4cf9997a4c2988047e2c2d75342 Mon Sep 17 00:00:00 2001 From: Terence Hampson Date: Thu, 22 Feb 2024 20:16:00 -0500 Subject: [PATCH 066/385] comment removed (#32261) --- src/app/CommandSender.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/app/CommandSender.cpp b/src/app/CommandSender.cpp index 18f4e755835076..7a03985b61b365 100644 --- a/src/app/CommandSender.cpp +++ b/src/app/CommandSender.cpp @@ -325,10 +325,7 @@ void CommandSender::OnResponseTimeout(Messaging::ExchangeContext * apExchangeCon ChipLogProgress(DataManagement, "Time out! failed to receive invoke command response from Exchange: " ChipLogFormatExchange, ChipLogValueExchange(apExchangeContext)); - // TODO(#30453) When timeout occurs for batch commands what should be done? Should all individual - // commands have a path specific error of timeout, or do we give or NoCommandResponse. OnErrorCallback(CHIP_ERROR_TIMEOUT); - Close(); } From 7f8c40bdaf984f8f11fe6aedc91c165e7e524eeb Mon Sep 17 00:00:00 2001 From: joonhaengHeo <85541460+joonhaengHeo@users.noreply.github.com> Date: Fri, 23 Feb 2024 13:34:42 +0900 Subject: [PATCH 067/385] Fix crash in Wi-Fi Connect Network (#32253) * Fix crash in Wi-Fi Connect Network * Update from comment * Restyled by clang-format --------- Co-authored-by: Restyled.io --- src/controller/CHIPDeviceController.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/controller/CHIPDeviceController.cpp b/src/controller/CHIPDeviceController.cpp index 57c75cd0d813ae..69e95244dcce01 100644 --- a/src/controller/CHIPDeviceController.cpp +++ b/src/controller/CHIPDeviceController.cpp @@ -3040,8 +3040,10 @@ void DeviceCommissioner::PerformCommissioningStep(DeviceProxy * proxy, Commissio request.breadcrumb.Emplace(breadcrumb); CHIP_ERROR err = CHIP_NO_ERROR; - ChipLogProgress(Controller, "SendCommand kWiFiNetworkEnable, supportsConcurrentConnection=%d", - params.GetSupportsConcurrentConnection().Value()); + ChipLogProgress(Controller, "SendCommand kWiFiNetworkEnable, supportsConcurrentConnection=%s", + params.GetSupportsConcurrentConnection().HasValue() + ? (params.GetSupportsConcurrentConnection().Value() ? "true" : "false") + : "missing"); err = SendCommand(proxy, request, OnConnectNetworkResponse, OnBasicFailure, endpoint, timeout); if (err != CHIP_NO_ERROR) From 233c1777a12416be68b8c27b2fb7464dbfc94dac Mon Sep 17 00:00:00 2001 From: Karsten Sperling <113487422+ksperling-apple@users.noreply.github.com> Date: Fri, 23 Feb 2024 19:49:06 +1300 Subject: [PATCH 068/385] Darwin: Propagate sanitizer flags from Xcode into GN build (#32278) * Darwin: Propagate sanitizer flags from Xcode into GN build When ASAN, TSAN, or UBSAN are enabled from Xcode, turn on the corresponding setting in the GN build. * Set _LIBCPP_HAS_NO_ASAN for ASAN builds to match Xcodebuild --- .github/workflows/darwin.yaml | 18 +++++++----------- build/config/compiler/BUILD.gn | 5 +++++ .../Framework/chip_xcode_build_connector.sh | 6 +++--- 3 files changed, 15 insertions(+), 14 deletions(-) diff --git a/.github/workflows/darwin.yaml b/.github/workflows/darwin.yaml index 2d7443f9e9758c..a58617131a035d 100644 --- a/.github/workflows/darwin.yaml +++ b/.github/workflows/darwin.yaml @@ -105,19 +105,15 @@ jobs: mkdir -p /tmp/darwin/framework-tests ../../../out/debug/chip-all-clusters-app --interface-id -1 > >(tee /tmp/darwin/framework-tests/all-cluster-app.log) 2> >(tee /tmp/darwin/framework-tests/all-cluster-app-err.log >&2) & ../../../out/debug/chip-all-clusters-app --interface-id -1 --dac_provider ../../../credentials/development/commissioner_dut/struct_cd_origin_pid_vid_correct/test_case_vector.json --product-id 32768 --discriminator 3839 --secured-device-port 5539 --KVS /tmp/chip-all-clusters-app-kvs2 > >(tee /tmp/darwin/framework-tests/all-cluster-app-origin-vid.log) 2> >(tee /tmp/darwin/framework-tests/all-cluster-app-origin-vid-err.log >&2) & - # Disable BLE because the app does not have the permission to use - # it and that may crash the CI. - # - # -enableUndefinedBehaviorSanitizer instruments the code in Matter.framework, - # but to instrument the code in the underlying libCHIP we need to pass CHIP_IS_UBSAN=YES - TEST_RUNNER_ASAN_OPTIONS=__CURRENT_VALUE__:detect_stack_use_after_return=1 xcodebuild test -target "Matter" -scheme "Matter Framework Tests" -sdk macosx -enableAddressSanitizer YES -enableUndefinedBehaviorSanitizer YES OTHER_CFLAGS='${inherited} -Werror -Wconversion' CHIP_IS_UBSAN=YES CHIP_IS_BLE=NO GCC_PREPROCESSOR_DEFINITIONS='${inherited} MTR_NO_AVAILABILITY=1'> >(tee /tmp/darwin/framework-tests/darwin-tests-asan.log) 2> >(tee /tmp/darwin/framework-tests/darwin-tests-asan-err.log >&2) + # Disable BLE (CHIP_IS_BLE=NO) because the app does not have the permission to use it and that may crash the CI. + + TEST_RUNNER_ASAN_OPTIONS=__CURRENT_VALUE__:detect_stack_use_after_return=1 xcodebuild test -target "Matter" -scheme "Matter Framework Tests" -sdk macosx -enableAddressSanitizer YES -enableUndefinedBehaviorSanitizer YES OTHER_CFLAGS='${inherited} -Werror -Wconversion' CHIP_IS_BLE=NO GCC_PREPROCESSOR_DEFINITIONS='${inherited} MTR_NO_AVAILABILITY=1'> >(tee /tmp/darwin/framework-tests/darwin-tests-asan.log) 2> >(tee /tmp/darwin/framework-tests/darwin-tests-asan-err.log >&2) # And the same thing, but with MTR_PER_CONTROLLER_STORAGE_ENABLED turned off, so we test that it does not break for now. - TEST_RUNNER_ASAN_OPTIONS=__CURRENT_VALUE__:detect_stack_use_after_return=1 xcodebuild test -target "Matter" -scheme "Matter Framework Tests" -sdk macosx -enableAddressSanitizer YES -enableUndefinedBehaviorSanitizer YES OTHER_CFLAGS='${inherited} -Werror -Wconversion' CHIP_IS_UBSAN=YES CHIP_IS_BLE=NO GCC_PREPROCESSOR_DEFINITIONS='${inherited} MTR_NO_AVAILABILITY=1 MTR_PER_CONTROLLER_STORAGE_ENABLED=0' > >(tee /tmp/darwin/framework-tests/darwin-tests-asan-controller-storage.log) 2> >(tee /tmp/darwin/framework-tests/darwin-tests-asan-controller-storage-err.log >&2) + TEST_RUNNER_ASAN_OPTIONS=__CURRENT_VALUE__:detect_stack_use_after_return=1 xcodebuild test -target "Matter" -scheme "Matter Framework Tests" -sdk macosx -enableAddressSanitizer YES -enableUndefinedBehaviorSanitizer YES OTHER_CFLAGS='${inherited} -Werror -Wconversion' CHIP_IS_BLE=NO GCC_PREPROCESSOR_DEFINITIONS='${inherited} MTR_NO_AVAILABILITY=1 MTR_PER_CONTROLLER_STORAGE_ENABLED=0' > >(tee /tmp/darwin/framework-tests/darwin-tests-asan-controller-storage.log) 2> >(tee /tmp/darwin/framework-tests/darwin-tests-asan-controller-storage-err.log >&2) # And the same thing, but with MTR_NO_AVAILABILITY not turned on. This requires -Wno-unguarded-availability-new to avoid availability errors. - TEST_RUNNER_ASAN_OPTIONS=__CURRENT_VALUE__:detect_stack_use_after_return=1 xcodebuild test -target "Matter" -scheme "Matter Framework Tests" -sdk macosx -enableAddressSanitizer YES -enableUndefinedBehaviorSanitizer YES OTHER_CFLAGS='${inherited} -Werror -Wconversion -Wno-unguarded-availability-new' CHIP_IS_UBSAN=YES CHIP_IS_BLE=NO GCC_PREPROCESSOR_DEFINITIONS='${inherited}' > >(tee /tmp/darwin/framework-tests/darwin-tests-asan-with-availability-annotations.log) 2> >(tee /tmp/darwin/framework-tests/darwin-tests-asan-with-availability-annotations-err.log >&2) - # -enableThreadSanitizer instruments the code in Matter.framework, - # but to instrument the code in the underlying libCHIP we need to pass CHIP_IS_TSAN=YES - xcodebuild test -target "Matter" -scheme "Matter Framework Tests" -sdk macosx -enableThreadSanitizer YES OTHER_CFLAGS='${inherited} -Werror -Wconversion' CHIP_IS_TSAN=YES CHIP_IS_BLE=NO GCC_PREPROCESSOR_DEFINITIONS='${inherited} MTR_NO_AVAILABILITY=1' > >(tee /tmp/darwin/framework-tests/darwin-tests-tsan.log) 2> >(tee /tmp/darwin/framework-tests/darwin-tests-tsan-err.log >&2) + TEST_RUNNER_ASAN_OPTIONS=__CURRENT_VALUE__:detect_stack_use_after_return=1 xcodebuild test -target "Matter" -scheme "Matter Framework Tests" -sdk macosx -enableAddressSanitizer YES -enableUndefinedBehaviorSanitizer YES OTHER_CFLAGS='${inherited} -Werror -Wconversion -Wno-unguarded-availability-new' CHIP_IS_BLE=NO GCC_PREPROCESSOR_DEFINITIONS='${inherited}' > >(tee /tmp/darwin/framework-tests/darwin-tests-asan-with-availability-annotations.log) 2> >(tee /tmp/darwin/framework-tests/darwin-tests-asan-with-availability-annotations-err.log >&2) + + xcodebuild test -target "Matter" -scheme "Matter Framework Tests" -sdk macosx -enableThreadSanitizer YES OTHER_CFLAGS='${inherited} -Werror -Wconversion' CHIP_IS_BLE=NO GCC_PREPROCESSOR_DEFINITIONS='${inherited} MTR_NO_AVAILABILITY=1' > >(tee /tmp/darwin/framework-tests/darwin-tests-tsan.log) 2> >(tee /tmp/darwin/framework-tests/darwin-tests-tsan-err.log >&2) working-directory: src/darwin/Framework - name: Build Matter TV Casting Bridge run: | diff --git a/build/config/compiler/BUILD.gn b/build/config/compiler/BUILD.gn index b6ad67a64944fd..7ada1348f797b4 100644 --- a/build/config/compiler/BUILD.gn +++ b/build/config/compiler/BUILD.gn @@ -395,11 +395,16 @@ declare_args() { } config("sanitize_address") { + defines = [] cflags = [ "-fsanitize=address", "-fno-omit-frame-pointer", ] ldflags = cflags + + if (target_os == "mac" || target_os == "ios") { + defines += [ "_LIBCPP_HAS_NO_ASAN" ] + } } config("sanitize_thread") { diff --git a/src/darwin/Framework/chip_xcode_build_connector.sh b/src/darwin/Framework/chip_xcode_build_connector.sh index 3ab0464bb79482..e802e99cd0cfcd 100755 --- a/src/darwin/Framework/chip_xcode_build_connector.sh +++ b/src/darwin/Framework/chip_xcode_build_connector.sh @@ -132,19 +132,19 @@ esac ) } -[[ $CHIP_IS_ASAN == YES ]] && { +[[ $CHIP_IS_ASAN == YES || $ENABLE_ADDRESS_SANITIZER == YES ]] && { args+=( 'is_asan=true' ) } -[[ $CHIP_IS_UBSAN == YES ]] && { +[[ $CHIP_IS_UBSAN == YES || $ENABLE_UNDEFINED_BEHAVIOR_SANITIZER == YES ]] && { args+=( 'is_ubsan=true' ) } -[[ $CHIP_IS_TSAN == YES ]] && { +[[ $CHIP_IS_TSAN == YES || $ENABLE_THREAD_SANITIZER == YES ]] && { args+=( 'is_tsan=true' # The system stats stuff races on the stats in various ways, From 003c478222211e877755ae2e0f58a4779a06bc8c Mon Sep 17 00:00:00 2001 From: Arkadiusz Bokowy Date: Fri, 23 Feb 2024 10:54:21 +0100 Subject: [PATCH 069/385] [Linux] Fix memory leaks when handling BluezAdapter1 objects (#32263) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Convert glib object to GAutoPtr<> in Bluez * Do not keep a copy of BluezAdapter1 properties * Use GAutoPtr to manage BluezAdapter1 life cycle * Simplify adapter retrieval from BlueZ object * Properly release objects obtained with bluez_object_get_*() * Use reinterpret_cast when using g_object_ref() * Use on-the-stack strings to simplify memory management * Manage BluezLEAdvertisement1 with GAutoPtr * Do not leak GDBusObjectManagerServer in case of re-initialization * Fix life cycle of exported advertisement D-Bus object * Restart BLE advertisement in case of premature release --------- Co-authored-by: Damian Michalak-Szmaciński --- src/platform/GLibTypeDeleter.h | 6 + src/platform/Linux/BLEManagerImpl.cpp | 30 +++-- src/platform/Linux/BLEManagerImpl.h | 7 +- src/platform/Linux/CHIPDevicePlatformEvent.h | 11 +- src/platform/Linux/bluez/AdapterIterator.cpp | 47 +++---- src/platform/Linux/bluez/AdapterIterator.h | 28 ++-- .../Linux/bluez/BluezAdvertisement.cpp | 123 +++++++----------- src/platform/Linux/bluez/BluezAdvertisement.h | 14 +- src/platform/Linux/bluez/BluezConnection.cpp | 16 +-- src/platform/Linux/bluez/BluezEndpoint.cpp | 70 +++++----- src/platform/Linux/bluez/BluezEndpoint.h | 4 +- .../Linux/bluez/ChipDeviceScanner.cpp | 18 +-- src/platform/Linux/bluez/ChipDeviceScanner.h | 6 +- src/platform/Linux/bluez/Types.h | 24 ++++ 14 files changed, 194 insertions(+), 210 deletions(-) diff --git a/src/platform/GLibTypeDeleter.h b/src/platform/GLibTypeDeleter.h index f217d559e9cc66..f083a6c5e460d5 100644 --- a/src/platform/GLibTypeDeleter.h +++ b/src/platform/GLibTypeDeleter.h @@ -120,6 +120,12 @@ struct GAutoPtrDeleter using deleter = GObjectDeleter; }; +template <> +struct GAutoPtrDeleter +{ + using deleter = GObjectDeleter; +}; + template <> struct GAutoPtrDeleter { diff --git a/src/platform/Linux/BLEManagerImpl.cpp b/src/platform/Linux/BLEManagerImpl.cpp index d5129a983f092d..dbf3791c905ac1 100644 --- a/src/platform/Linux/BLEManagerImpl.cpp +++ b/src/platform/Linux/BLEManagerImpl.cpp @@ -289,8 +289,13 @@ void BLEManagerImpl::HandlePlatformSpecificBLEEvent(const ChipDeviceEvent * apEv case DeviceEventType::kPlatformLinuxBLEPeripheralAdvStartComplete: VerifyOrExit(apEvent->Platform.BLEPeripheralAdvStartComplete.mIsSuccess, err = CHIP_ERROR_INCORRECT_STATE); sInstance.mFlags.Clear(Flags::kControlOpInProgress).Clear(Flags::kAdvertisingRefreshNeeded); - // Start a timer to make sure that the fast advertising is stopped after specified timeout. - SuccessOrExit(err = DeviceLayer::SystemLayer().StartTimer(kFastAdvertiseTimeout, HandleAdvertisingTimer, this)); + // Do not restart the timer if it is still active. This is to avoid the timer from being restarted + // if the advertising is stopped due to a premature release. + if (!DeviceLayer::SystemLayer().IsTimerActive(HandleAdvertisingTimer, this)) + { + // Start a timer to make sure that the fast advertising is stopped after specified timeout. + SuccessOrExit(err = DeviceLayer::SystemLayer().StartTimer(kFastAdvertiseTimeout, HandleAdvertisingTimer, this)); + } sInstance.mFlags.Set(Flags::kAdvertising); break; case DeviceEventType::kPlatformLinuxBLEPeripheralAdvStopComplete: @@ -305,6 +310,11 @@ void BLEManagerImpl::HandlePlatformSpecificBLEEvent(const ChipDeviceEvent * apEv ChipLogProgress(DeviceLayer, "CHIPoBLE advertising stopped"); } break; + case DeviceEventType::kPlatformLinuxBLEPeripheralAdvReleased: + // If the advertising was stopped due to a premature release, check if it needs to be restarted. + sInstance.mFlags.Clear(Flags::kAdvertising); + DriveBLEState(); + break; case DeviceEventType::kPlatformLinuxBLEPeripheralRegisterAppComplete: VerifyOrExit(apEvent->Platform.BLEPeripheralRegisterAppComplete.mIsSuccess, err = CHIP_ERROR_INCORRECT_STATE); mFlags.Set(Flags::kAppRegistered); @@ -780,30 +790,34 @@ CHIP_ERROR BLEManagerImpl::CancelConnection() return CHIP_NO_ERROR; } -void BLEManagerImpl::NotifyBLEPeripheralRegisterAppComplete(bool aIsSuccess, void * apAppstate) +void BLEManagerImpl::NotifyBLEPeripheralRegisterAppComplete(bool aIsSuccess) { ChipDeviceEvent event; event.Type = DeviceEventType::kPlatformLinuxBLEPeripheralRegisterAppComplete; event.Platform.BLEPeripheralRegisterAppComplete.mIsSuccess = aIsSuccess; - event.Platform.BLEPeripheralRegisterAppComplete.mpAppstate = apAppstate; PlatformMgr().PostEventOrDie(&event); } -void BLEManagerImpl::NotifyBLEPeripheralAdvStartComplete(bool aIsSuccess, void * apAppstate) +void BLEManagerImpl::NotifyBLEPeripheralAdvStartComplete(bool aIsSuccess) { ChipDeviceEvent event; event.Type = DeviceEventType::kPlatformLinuxBLEPeripheralAdvStartComplete; event.Platform.BLEPeripheralAdvStartComplete.mIsSuccess = aIsSuccess; - event.Platform.BLEPeripheralAdvStartComplete.mpAppstate = apAppstate; PlatformMgr().PostEventOrDie(&event); } -void BLEManagerImpl::NotifyBLEPeripheralAdvStopComplete(bool aIsSuccess, void * apAppstate) +void BLEManagerImpl::NotifyBLEPeripheralAdvStopComplete(bool aIsSuccess) { ChipDeviceEvent event; event.Type = DeviceEventType::kPlatformLinuxBLEPeripheralAdvStopComplete; event.Platform.BLEPeripheralAdvStopComplete.mIsSuccess = aIsSuccess; - event.Platform.BLEPeripheralAdvStopComplete.mpAppstate = apAppstate; + PlatformMgr().PostEventOrDie(&event); +} + +void BLEManagerImpl::NotifyBLEPeripheralAdvReleased() +{ + ChipDeviceEvent event; + event.Type = DeviceEventType::kPlatformLinuxBLEPeripheralAdvReleased; PlatformMgr().PostEventOrDie(&event); } diff --git a/src/platform/Linux/BLEManagerImpl.h b/src/platform/Linux/BLEManagerImpl.h index 61d2dff02757c7..6e3c1a687a5594 100644 --- a/src/platform/Linux/BLEManagerImpl.h +++ b/src/platform/Linux/BLEManagerImpl.h @@ -92,9 +92,10 @@ class BLEManagerImpl final : public BLEManager, static void HandleTXCharCCCDWrite(BLE_CONNECTION_OBJECT user_data); static void HandleTXComplete(BLE_CONNECTION_OBJECT user_data); - static void NotifyBLEPeripheralRegisterAppComplete(bool aIsSuccess, void * apAppstate); - static void NotifyBLEPeripheralAdvStartComplete(bool aIsSuccess, void * apAppstate); - static void NotifyBLEPeripheralAdvStopComplete(bool aIsSuccess, void * apAppstate); + static void NotifyBLEPeripheralRegisterAppComplete(bool aIsSuccess); + static void NotifyBLEPeripheralAdvStartComplete(bool aIsSuccess); + static void NotifyBLEPeripheralAdvStopComplete(bool aIsSuccess); + static void NotifyBLEPeripheralAdvReleased(); private: // ===== Members that implement the BLEManager internal interface. diff --git a/src/platform/Linux/CHIPDevicePlatformEvent.h b/src/platform/Linux/CHIPDevicePlatformEvent.h index 8618b9ebeaa0a8..b6e0b55cafdbb2 100644 --- a/src/platform/Linux/CHIPDevicePlatformEvent.h +++ b/src/platform/Linux/CHIPDevicePlatformEvent.h @@ -54,7 +54,8 @@ enum InternalPlatformSpecificEventTypes kPlatformLinuxBLEOutOfBuffersEvent, kPlatformLinuxBLEPeripheralRegisterAppComplete, kPlatformLinuxBLEPeripheralAdvStartComplete, - kPlatformLinuxBLEPeripheralAdvStopComplete + kPlatformLinuxBLEPeripheralAdvStopComplete, + kPlatformLinuxBLEPeripheralAdvReleased, }; } // namespace DeviceEventType @@ -91,22 +92,14 @@ struct ChipDevicePlatformEvent struct { bool mIsSuccess; - void * mpAppstate; } BLEPeripheralRegisterAppComplete; struct { bool mIsSuccess; - void * mpAppstate; - } BLEPeripheralAdvConfiguredComplete; - struct - { - bool mIsSuccess; - void * mpAppstate; } BLEPeripheralAdvStartComplete; struct { bool mIsSuccess; - void * mpAppstate; } BLEPeripheralAdvStopComplete; }; }; diff --git a/src/platform/Linux/bluez/AdapterIterator.cpp b/src/platform/Linux/bluez/AdapterIterator.cpp index e69c473f52bbfe..5510ceae996ce2 100644 --- a/src/platform/Linux/bluez/AdapterIterator.cpp +++ b/src/platform/Linux/bluez/AdapterIterator.cpp @@ -37,12 +37,6 @@ AdapterIterator::~AdapterIterator() { g_list_free_full(mObjectList, g_object_unref); } - - if (mCurrent.adapter != nullptr) - { - g_object_unref(mCurrent.adapter); - mCurrent.adapter = nullptr; - } } CHIP_ERROR AdapterIterator::Initialize(AdapterIterator * self) @@ -90,30 +84,7 @@ bool AdapterIterator::Advance() continue; } - // PATH is of the for BLUEZ_PATH / hci, i.e. like - // '/org/bluez/hci0' - // Index represents the number after hci - const char * path = g_dbus_proxy_get_object_path(G_DBUS_PROXY(adapter)); - unsigned index = 0; - - if (sscanf(path, BLUEZ_PATH "/hci%u", &index) != 1) - { - ChipLogError(DeviceLayer, "Failed to extract HCI index from '%s'", StringOrNullMarker(path)); - index = 0; - } - - if (mCurrent.adapter != nullptr) - { - g_object_unref(mCurrent.adapter); - mCurrent.adapter = nullptr; - } - - mCurrent.index = index; - mCurrent.address = bluez_adapter1_get_address(adapter); - mCurrent.alias = bluez_adapter1_get_alias(adapter); - mCurrent.name = bluez_adapter1_get_name(adapter); - mCurrent.powered = bluez_adapter1_get_powered(adapter); - mCurrent.adapter = adapter; + mCurrentAdapter.reset(adapter); mCurrentListItem = mCurrentListItem->next; @@ -123,6 +94,22 @@ bool AdapterIterator::Advance() return false; } +uint32_t AdapterIterator::GetIndex() const +{ + // PATH is of the for BLUEZ_PATH / hci, i.e. like '/org/bluez/hci0' + // Index represents the number after hci + const char * path = g_dbus_proxy_get_object_path(G_DBUS_PROXY(mCurrentAdapter.get())); + unsigned index = 0; + + if (sscanf(path, BLUEZ_PATH "/hci%u", &index) != 1) + { + ChipLogError(DeviceLayer, "Failed to extract HCI index from '%s'", StringOrNullMarker(path)); + index = 0; + } + + return index; +} + bool AdapterIterator::Next() { if (mManager == nullptr) diff --git a/src/platform/Linux/bluez/AdapterIterator.h b/src/platform/Linux/bluez/AdapterIterator.h index 85697b5d544c9a..0d44074889773b 100644 --- a/src/platform/Linux/bluez/AdapterIterator.h +++ b/src/platform/Linux/bluez/AdapterIterator.h @@ -56,12 +56,12 @@ class AdapterIterator // Information about the current value. Safe to call only after // "Next" has returned true. - uint32_t GetIndex() const { return mCurrent.index; } - const char * GetAddress() const { return mCurrent.address.c_str(); } - const char * GetAlias() const { return mCurrent.alias.c_str(); } - const char * GetName() const { return mCurrent.name.c_str(); } - bool IsPowered() const { return mCurrent.powered; } - BluezAdapter1 * GetAdapter() const { return mCurrent.adapter; } + uint32_t GetIndex() const; + const char * GetAddress() const { return bluez_adapter1_get_address(mCurrentAdapter.get()); } + const char * GetAlias() const { return bluez_adapter1_get_alias(mCurrentAdapter.get()); } + const char * GetName() const { return bluez_adapter1_get_name(mCurrentAdapter.get()); } + bool IsPowered() const { return bluez_adapter1_get_powered(mCurrentAdapter.get()); } + BluezAdapter1 * GetAdapter() const { return mCurrentAdapter.get(); } private: /// Sets up the DBUS manager and loads the list @@ -73,23 +73,11 @@ class AdapterIterator /// iterate through. bool Advance(); - static constexpr size_t kMaxAddressLength = 19; // xx:xx:xx:xx:xx:xx - static constexpr size_t kMaxNameLength = 64; - GDBusObjectManager * mManager = nullptr; // DBus connection GList * mObjectList = nullptr; // listing of objects on the bus GList * mCurrentListItem = nullptr; // current item viewed in the list - - // data valid only if Next() returns true - struct - { - uint32_t index; - std::string address; - std::string alias; - std::string name; - bool powered; - BluezAdapter1 * adapter; - } mCurrent = { 0 }; + // Data valid only if Next() returns true + GAutoPtr mCurrentAdapter; }; } // namespace Internal diff --git a/src/platform/Linux/bluez/BluezAdvertisement.cpp b/src/platform/Linux/bluez/BluezAdvertisement.cpp index 196529816b59ab..06f831bff8b58f 100644 --- a/src/platform/Linux/bluez/BluezAdvertisement.cpp +++ b/src/platform/Linux/bluez/BluezAdvertisement.cpp @@ -45,13 +45,13 @@ BluezLEAdvertisement1 * BluezAdvertisement::CreateLEAdvertisement() GVariant * serviceUUID; GVariantBuilder serviceUUIDsBuilder; - ChipLogDetail(DeviceLayer, "Create BLE adv object at %s", mpAdvPath); - object = bluez_object_skeleton_new(mpAdvPath); + ChipLogDetail(DeviceLayer, "Create BLE adv object at %s", mAdvPath); + object = bluez_object_skeleton_new(mAdvPath); adv = bluez_leadvertisement1_skeleton_new(); g_variant_builder_init(&serviceUUIDsBuilder, G_VARIANT_TYPE("as")); - g_variant_builder_add(&serviceUUIDsBuilder, "s", mpAdvUUID); + g_variant_builder_add(&serviceUUIDsBuilder, "s", mAdvUUID); serviceUUID = g_variant_builder_end(&serviceUUIDsBuilder); @@ -81,7 +81,7 @@ BluezLEAdvertisement1 * BluezAdvertisement::CreateLEAdvertisement() }), this); - g_dbus_object_manager_server_export(mpRoot, G_DBUS_OBJECT_SKELETON(object)); + g_dbus_object_manager_server_export(mRoot.get(), G_DBUS_OBJECT_SKELETON(object)); g_object_unref(object); return adv; @@ -89,11 +89,11 @@ BluezLEAdvertisement1 * BluezAdvertisement::CreateLEAdvertisement() gboolean BluezAdvertisement::BluezLEAdvertisement1Release(BluezLEAdvertisement1 * aAdv, GDBusMethodInvocation * aInvocation) { - ChipLogDetail(DeviceLayer, "Release BLE adv object in %s", __func__); - g_dbus_object_manager_server_unexport(mpRoot, mpAdvPath); - g_object_unref(mpAdv); - mpAdv = nullptr; + // This method is called when the advertisement is stopped (released) by BlueZ. + // We can use it to update the state of the advertisement in the CHIP layer. + ChipLogDetail(DeviceLayer, "BLE advertisement stopped by BlueZ"); mIsAdvertising = false; + BLEManagerImpl::NotifyBLEPeripheralAdvReleased(); return TRUE; } @@ -103,7 +103,7 @@ CHIP_ERROR BluezAdvertisement::InitImpl() // all D-Bus signals will be delivered to the GLib global default main context. VerifyOrDie(g_main_context_get_thread_default() != nullptr); - mpAdv = CreateLEAdvertisement(); + mAdv.reset(CreateLEAdvertisement()); return CHIP_NO_ERROR; } @@ -112,19 +112,19 @@ CHIP_ERROR BluezAdvertisement::Init(const BluezEndpoint & aEndpoint, const char GAutoPtr rootPath; CHIP_ERROR err; - VerifyOrExit(mpAdv == nullptr, err = CHIP_ERROR_INCORRECT_STATE; + VerifyOrExit(!mAdv, err = CHIP_ERROR_INCORRECT_STATE; ChipLogError(DeviceLayer, "FAIL: BLE advertisement already initialized in %s", __func__)); - mpRoot = reinterpret_cast(g_object_ref(aEndpoint.GetGattApplicationObjectManager())); - mpAdapter = reinterpret_cast(g_object_ref(aEndpoint.GetAdapter())); + mRoot.reset(reinterpret_cast(g_object_ref(aEndpoint.GetGattApplicationObjectManager()))); + mAdapter.reset(reinterpret_cast(g_object_ref(aEndpoint.GetAdapter()))); - g_object_get(G_OBJECT(mpRoot), "object-path", &rootPath.GetReceiver(), nullptr); - mpAdvPath = g_strdup_printf("%s/advertising", rootPath.get()); - mpAdvUUID = g_strdup(aAdvUUID); + g_object_get(G_OBJECT(mRoot.get()), "object-path", &rootPath.GetReceiver(), nullptr); + g_snprintf(mAdvPath, sizeof(mAdvPath), "%s/advertising", rootPath.get()); + g_strlcpy(mAdvUUID, aAdvUUID, sizeof(mAdvUUID)); if (aAdvName != nullptr) { - g_snprintf(mAdvName, sizeof(mAdvName), "%s", aAdvName); + g_strlcpy(mAdvName, aAdvName, sizeof(mAdvName)); } else { @@ -145,17 +145,17 @@ CHIP_ERROR BluezAdvertisement::Init(const BluezEndpoint & aEndpoint, const char CHIP_ERROR BluezAdvertisement::SetIntervals(AdvertisingIntervals aAdvIntervals) { - VerifyOrReturnError(mpAdv != nullptr, CHIP_ERROR_UNINITIALIZED); + VerifyOrReturnError(mAdv, CHIP_ERROR_UNINITIALIZED); // If the advertisement is already running, BlueZ will update the intervals // automatically. There is no need to stop and restart the advertisement. - bluez_leadvertisement1_set_min_interval(mpAdv, aAdvIntervals.first * 0.625); - bluez_leadvertisement1_set_max_interval(mpAdv, aAdvIntervals.second * 0.625); + bluez_leadvertisement1_set_min_interval(mAdv.get(), aAdvIntervals.first * 0.625); + bluez_leadvertisement1_set_max_interval(mAdv.get(), aAdvIntervals.second * 0.625); return CHIP_NO_ERROR; } CHIP_ERROR BluezAdvertisement::SetupServiceData(ServiceDataFlags aFlags) { - VerifyOrReturnError(mpAdv != nullptr, CHIP_ERROR_UNINITIALIZED); + VerifyOrReturnError(mAdv, CHIP_ERROR_UNINITIALIZED); Ble::ChipBLEDeviceIdentificationInfo deviceInfo; ReturnErrorOnFailure(ConfigurationMgr().GetBLEDeviceIdentificationInfo(deviceInfo)); @@ -177,7 +177,7 @@ CHIP_ERROR BluezAdvertisement::SetupServiceData(ServiceDataFlags aFlags) GVariantBuilder serviceDataBuilder; g_variant_builder_init(&serviceDataBuilder, G_VARIANT_TYPE("a{sv}")); - g_variant_builder_add(&serviceDataBuilder, "{sv}", mpAdvUUID, + g_variant_builder_add(&serviceDataBuilder, "{sv}", mAdvUUID, g_variant_new_fixed_array(G_VARIANT_TYPE_BYTE, &deviceInfo, sizeof(deviceInfo), sizeof(uint8_t))); GVariant * serviceData = g_variant_builder_end(&serviceDataBuilder); @@ -185,7 +185,7 @@ CHIP_ERROR BluezAdvertisement::SetupServiceData(ServiceDataFlags aFlags) GAutoPtr debugStr(g_variant_print(serviceData, TRUE)); ChipLogDetail(DeviceLayer, "SET service data to %s", StringOrNullMarker(debugStr.get())); - bluez_leadvertisement1_set_service_data(mpAdv, serviceData); + bluez_leadvertisement1_set_service_data(mAdv.get(), serviceData); return CHIP_NO_ERROR; } @@ -208,30 +208,17 @@ void BluezAdvertisement::Shutdown() // attached to the advertising object that may run on the glib thread. PlatformMgrImpl().GLibMatterContextInvokeSync( +[](BluezAdvertisement * self) { - if (self->mpRoot != nullptr) - { - g_object_unref(self->mpRoot); - self->mpRoot = nullptr; - } - if (self->mpAdapter != nullptr) - { - g_object_unref(self->mpAdapter); - self->mpAdapter = nullptr; - } - if (self->mpAdv != nullptr) - { - g_object_unref(self->mpAdv); - self->mpAdv = nullptr; - } + // The object manager server (mRoot) might not be released right away (it may be held + // by other BLE layer objects). We need to unexport the advertisement object in the + // explicit way to make sure that we can export it again in the Init() method. + g_dbus_object_manager_server_unexport(self->mRoot.get(), self->mAdvPath); + self->mRoot.reset(); + self->mAdapter.reset(); + self->mAdv.reset(); return CHIP_NO_ERROR; }, this); - g_free(mpAdvPath); - mpAdvPath = nullptr; - g_free(mpAdvUUID); - mpAdvUUID = nullptr; - mIsInitialized = false; } @@ -242,10 +229,6 @@ void BluezAdvertisement::StartDone(GObject * aObject, GAsyncResult * aResult) gboolean success = FALSE; success = bluez_leadvertising_manager1_call_register_advertisement_finish(advMgr, aResult, &error.GetReceiver()); - if (success == FALSE) - { - g_dbus_object_manager_server_unexport(mpRoot, mpAdvPath); - } VerifyOrExit(success == TRUE, ChipLogError(DeviceLayer, "FAIL: RegisterAdvertisement : %s", error->message)); mIsAdvertising = true; @@ -253,30 +236,30 @@ void BluezAdvertisement::StartDone(GObject * aObject, GAsyncResult * aResult) ChipLogDetail(DeviceLayer, "RegisterAdvertisement complete"); exit: - BLEManagerImpl::NotifyBLEPeripheralAdvStartComplete(success == TRUE, nullptr); + BLEManagerImpl::NotifyBLEPeripheralAdvStartComplete(success == TRUE); } CHIP_ERROR BluezAdvertisement::StartImpl() { - GDBusObject * adapter; - BluezLEAdvertisingManager1 * advMgr = nullptr; + GDBusObject * adapterObject; + GAutoPtr advMgr; GVariantBuilder optionsBuilder; GVariant * options; VerifyOrExit(!mIsAdvertising, ChipLogError(DeviceLayer, "FAIL: Advertising has already been enabled in %s", __func__)); - VerifyOrExit(mpAdapter != nullptr, ChipLogError(DeviceLayer, "FAIL: NULL mpAdapter in %s", __func__)); + VerifyOrExit(mAdapter.get() != nullptr, ChipLogError(DeviceLayer, "FAIL: NULL mAdapter in %s", __func__)); - adapter = g_dbus_interface_get_object(G_DBUS_INTERFACE(mpAdapter)); - VerifyOrExit(adapter != nullptr, ChipLogError(DeviceLayer, "FAIL: NULL adapter in %s", __func__)); + adapterObject = g_dbus_interface_get_object(G_DBUS_INTERFACE(mAdapter.get())); + VerifyOrExit(adapterObject != nullptr, ChipLogError(DeviceLayer, "FAIL: NULL adapterObject in %s", __func__)); - advMgr = bluez_object_get_leadvertising_manager1(BLUEZ_OBJECT(adapter)); - VerifyOrExit(advMgr != nullptr, ChipLogError(DeviceLayer, "FAIL: NULL advMgr in %s", __func__)); + advMgr.reset(bluez_object_get_leadvertising_manager1(BLUEZ_OBJECT(adapterObject))); + VerifyOrExit(advMgr.get() != nullptr, ChipLogError(DeviceLayer, "FAIL: NULL advMgr in %s", __func__)); g_variant_builder_init(&optionsBuilder, G_VARIANT_TYPE("a{sv}")); options = g_variant_builder_end(&optionsBuilder); bluez_leadvertising_manager1_call_register_advertisement( - advMgr, mpAdvPath, options, nullptr, + advMgr.get(), mAdvPath, options, nullptr, [](GObject * aObject, GAsyncResult * aResult, void * aData) { reinterpret_cast(aData)->StartDone(aObject, aResult); }, @@ -304,40 +287,32 @@ void BluezAdvertisement::StopDone(GObject * aObject, GAsyncResult * aResult) gboolean success = FALSE; success = bluez_leadvertising_manager1_call_unregister_advertisement_finish(advMgr, aResult, &error.GetReceiver()); + VerifyOrExit(success == TRUE, ChipLogError(DeviceLayer, "FAIL: UnregisterAdvertisement: %s", error->message)); - if (success == FALSE) - { - g_dbus_object_manager_server_unexport(mpRoot, mpAdvPath); - } - else - { - mIsAdvertising = false; - } - - VerifyOrExit(success == TRUE, ChipLogError(DeviceLayer, "FAIL: UnregisterAdvertisement : %s", error->message)); + mIsAdvertising = false; ChipLogDetail(DeviceLayer, "UnregisterAdvertisement complete"); exit: - BLEManagerImpl::NotifyBLEPeripheralAdvStopComplete(success == TRUE, nullptr); + BLEManagerImpl::NotifyBLEPeripheralAdvStopComplete(success == TRUE); } CHIP_ERROR BluezAdvertisement::StopImpl() { - GDBusObject * adapter; - BluezLEAdvertisingManager1 * advMgr = nullptr; + GDBusObject * adapterObject; + GAutoPtr advMgr; VerifyOrExit(mIsAdvertising, ChipLogError(DeviceLayer, "FAIL: Advertising has already been disabled in %s", __func__)); - VerifyOrExit(mpAdapter != nullptr, ChipLogError(DeviceLayer, "FAIL: NULL mpAdapter in %s", __func__)); + VerifyOrExit(mAdapter.get() != nullptr, ChipLogError(DeviceLayer, "FAIL: NULL mAdapter in %s", __func__)); - adapter = g_dbus_interface_get_object(G_DBUS_INTERFACE(mpAdapter)); - VerifyOrExit(adapter != nullptr, ChipLogError(DeviceLayer, "FAIL: NULL adapter in %s", __func__)); + adapterObject = g_dbus_interface_get_object(G_DBUS_INTERFACE(mAdapter.get())); + VerifyOrExit(adapterObject != nullptr, ChipLogError(DeviceLayer, "FAIL: NULL adapterObject in %s", __func__)); - advMgr = bluez_object_get_leadvertising_manager1(BLUEZ_OBJECT(adapter)); - VerifyOrExit(advMgr != nullptr, ChipLogError(DeviceLayer, "FAIL: NULL advMgr in %s", __func__)); + advMgr.reset(bluez_object_get_leadvertising_manager1(BLUEZ_OBJECT(adapterObject))); + VerifyOrExit(advMgr.get() != nullptr, ChipLogError(DeviceLayer, "FAIL: NULL advMgr in %s", __func__)); bluez_leadvertising_manager1_call_unregister_advertisement( - advMgr, mpAdvPath, nullptr, + advMgr.get(), mAdvPath, nullptr, [](GObject * aObject, GAsyncResult * aResult, void * aData) { reinterpret_cast(aData)->StopDone(aObject, aResult); }, diff --git a/src/platform/Linux/bluez/BluezAdvertisement.h b/src/platform/Linux/bluez/BluezAdvertisement.h index 11fe51c8e7cdb9..f41d591410b8e3 100644 --- a/src/platform/Linux/bluez/BluezAdvertisement.h +++ b/src/platform/Linux/bluez/BluezAdvertisement.h @@ -26,6 +26,7 @@ #include #include +#include #include #include "Types.h" @@ -64,6 +65,9 @@ class BluezAdvertisement /// /// BLE advertising is stopped asynchronously. Application will be notified of /// completion via a call to BLEManagerImpl::NotifyBLEPeripheralAdvStopComplete(). + /// + /// It is also possible that the advertising is released by BlueZ. In that case, + /// the application will be notified by BLEManagerImpl::NotifyBLEPeripheralAdvReleased(). CHIP_ERROR Stop(); private: @@ -79,15 +83,15 @@ class BluezAdvertisement CHIP_ERROR StopImpl(); // Objects (interfaces) used by LE advertisement - GDBusObjectManagerServer * mpRoot = nullptr; - BluezAdapter1 * mpAdapter = nullptr; - BluezLEAdvertisement1 * mpAdv = nullptr; + GAutoPtr mRoot; + GAutoPtr mAdapter; + GAutoPtr mAdv; bool mIsInitialized = false; bool mIsAdvertising = false; - char * mpAdvPath = nullptr; - char * mpAdvUUID = nullptr; + char mAdvPath[64] = ""; // D-Bus path of the advertisement object + char mAdvUUID[64] = ""; // UUID of the service to be advertised char mAdvName[32] = ""; }; diff --git a/src/platform/Linux/bluez/BluezConnection.cpp b/src/platform/Linux/bluez/BluezConnection.cpp index d2d5745a4c37c2..d2db5edc005eba 100644 --- a/src/platform/Linux/bluez/BluezConnection.cpp +++ b/src/platform/Linux/bluez/BluezConnection.cpp @@ -60,7 +60,7 @@ gboolean BluezIsCharOnService(BluezGattCharacteristic1 * aChar, BluezGattService } // namespace BluezConnection::BluezConnection(const BluezEndpoint & aEndpoint, BluezDevice1 * apDevice) : - mpDevice(BLUEZ_DEVICE1(g_object_ref(apDevice))) + mpDevice(reinterpret_cast(g_object_ref(apDevice))) { Init(aEndpoint); } @@ -101,9 +101,9 @@ CHIP_ERROR BluezConnection::Init(const BluezEndpoint & aEndpoint) if (!aEndpoint.mIsCentral) { - mpService = BLUEZ_GATT_SERVICE1(g_object_ref(aEndpoint.mpService)); - mpC1 = BLUEZ_GATT_CHARACTERISTIC1(g_object_ref(aEndpoint.mpC1)); - mpC2 = BLUEZ_GATT_CHARACTERISTIC1(g_object_ref(aEndpoint.mpC2)); + mpService = reinterpret_cast(g_object_ref(aEndpoint.mpService)); + mpC1 = reinterpret_cast(g_object_ref(aEndpoint.mpC1)); + mpC2 = reinterpret_cast(g_object_ref(aEndpoint.mpC2)); } else { @@ -111,9 +111,7 @@ CHIP_ERROR BluezConnection::Init(const BluezEndpoint & aEndpoint) for (l = objects; l != nullptr; l = l->next) { - BluezObject * object = BLUEZ_OBJECT(l->data); - BluezGattService1 * service = bluez_object_get_gatt_service1(object); - + BluezGattService1 * service = bluez_object_get_gatt_service1(BLUEZ_OBJECT(l->data)); if (service != nullptr) { if ((BluezIsServiceOnDevice(service, mpDevice)) == TRUE && @@ -130,9 +128,7 @@ CHIP_ERROR BluezConnection::Init(const BluezEndpoint & aEndpoint) for (l = objects; l != nullptr; l = l->next) { - BluezObject * object = BLUEZ_OBJECT(l->data); - BluezGattCharacteristic1 * char1 = bluez_object_get_gatt_characteristic1(object); - + BluezGattCharacteristic1 * char1 = bluez_object_get_gatt_characteristic1(BLUEZ_OBJECT(l->data)); if (char1 != nullptr) { if ((BluezIsCharOnService(char1, mpService) == TRUE) && diff --git a/src/platform/Linux/bluez/BluezEndpoint.cpp b/src/platform/Linux/bluez/BluezEndpoint.cpp index e68b28b8f421a8..2fdd1e1788af6b 100644 --- a/src/platform/Linux/bluez/BluezEndpoint.cpp +++ b/src/platform/Linux/bluez/BluezEndpoint.cpp @@ -268,33 +268,33 @@ void BluezEndpoint::RegisterGattApplicationDone(GObject * aObject, GAsyncResult VerifyOrReturn(success == TRUE, { ChipLogError(DeviceLayer, "FAIL: RegisterApplication : %s", error->message); - BLEManagerImpl::NotifyBLEPeripheralRegisterAppComplete(false, nullptr); + BLEManagerImpl::NotifyBLEPeripheralRegisterAppComplete(false); }); - BLEManagerImpl::NotifyBLEPeripheralRegisterAppComplete(true, nullptr); + BLEManagerImpl::NotifyBLEPeripheralRegisterAppComplete(true); ChipLogDetail(DeviceLayer, "BluezPeripheralRegisterAppDone done"); } CHIP_ERROR BluezEndpoint::RegisterGattApplicationImpl() { - GDBusObject * adapter; - BluezGattManager1 * gattMgr; + GDBusObject * adapterObject; + GAutoPtr gattMgr; GVariantBuilder optionsBuilder; GVariant * options; - VerifyOrExit(mpAdapter != nullptr, ChipLogError(DeviceLayer, "FAIL: NULL mpAdapter in %s", __func__)); + VerifyOrExit(mAdapter.get() != nullptr, ChipLogError(DeviceLayer, "FAIL: NULL mAdapter in %s", __func__)); - adapter = g_dbus_interface_get_object(G_DBUS_INTERFACE(mpAdapter)); - VerifyOrExit(adapter != nullptr, ChipLogError(DeviceLayer, "FAIL: NULL adapter in %s", __func__)); + adapterObject = g_dbus_interface_get_object(G_DBUS_INTERFACE(mAdapter.get())); + VerifyOrExit(adapterObject != nullptr, ChipLogError(DeviceLayer, "FAIL: NULL adapterObject in %s", __func__)); - gattMgr = bluez_object_get_gatt_manager1(BLUEZ_OBJECT(adapter)); - VerifyOrExit(gattMgr != nullptr, ChipLogError(DeviceLayer, "FAIL: NULL gattMgr in %s", __func__)); + gattMgr.reset(bluez_object_get_gatt_manager1(BLUEZ_OBJECT(adapterObject))); + VerifyOrExit(gattMgr.get() != nullptr, ChipLogError(DeviceLayer, "FAIL: NULL gattMgr in %s", __func__)); g_variant_builder_init(&optionsBuilder, G_VARIANT_TYPE("a{sv}")); options = g_variant_builder_end(&optionsBuilder); bluez_gatt_manager1_call_register_application( - gattMgr, mpRootPath, options, nullptr, + gattMgr.get(), mpRootPath, options, nullptr, +[](GObject * aObj, GAsyncResult * aResult, void * self) { reinterpret_cast(self)->RegisterGattApplicationDone(aObj, aResult); }, @@ -344,11 +344,11 @@ void BluezEndpoint::BluezSignalInterfacePropertiesChanged(GDBusObjectManagerClie GDBusProxy * aInterface, GVariant * aChangedProperties, const char * const * aInvalidatedProps) { - VerifyOrReturn(mpAdapter != nullptr, ChipLogError(DeviceLayer, "FAIL: NULL mpAdapter in %s", __func__)); + VerifyOrReturn(mAdapter.get() != nullptr, ChipLogError(DeviceLayer, "FAIL: NULL mAdapter in %s", __func__)); VerifyOrReturn(strcmp(g_dbus_proxy_get_interface_name(aInterface), DEVICE_INTERFACE) == 0, ); BluezDevice1 * device = BLUEZ_DEVICE1(aInterface); - VerifyOrReturn(BluezIsDeviceOnAdapter(device, mpAdapter)); + VerifyOrReturn(BluezIsDeviceOnAdapter(device, mAdapter.get())); UpdateConnectionTable(device); } @@ -386,7 +386,7 @@ void BluezEndpoint::BluezSignalOnObjectAdded(GDBusObjectManager * aManager, GDBu GAutoPtr device(bluez_object_get_device1(BLUEZ_OBJECT(aObject))); VerifyOrReturn(device.get() != nullptr); - if (BluezIsDeviceOnAdapter(device.get(), mpAdapter) == TRUE) + if (BluezIsDeviceOnAdapter(device.get(), mAdapter.get()) == TRUE) { HandleNewDevice(device.get()); } @@ -395,7 +395,7 @@ void BluezEndpoint::BluezSignalOnObjectAdded(GDBusObjectManager * aManager, GDBu void BluezEndpoint::BluezSignalOnObjectRemoved(GDBusObjectManager * aManager, GDBusObject * aObject) { // TODO: for Device1, lookup connection, and call otPlatTobleHandleDisconnected - // for Adapter1: unclear, crash if this pertains to our adapter? at least null out the self->mpAdapter. + // for Adapter1: unclear, crash if this pertains to our adapter? at least null out the self->mAdapter. // for Characteristic1, or GattService -- handle here via calling otPlatTobleHandleDisconnected, or ignore. } @@ -427,43 +427,38 @@ void BluezEndpoint::SetupAdapter() snprintf(expectedPath, sizeof(expectedPath), BLUEZ_PATH "/hci%u", mAdapterId); GList * objects = g_dbus_object_manager_get_objects(mpObjMgr); - for (auto l = objects; l != nullptr && mpAdapter == nullptr; l = l->next) + for (auto l = objects; l != nullptr && mAdapter.get() == nullptr; l = l->next) { - BluezObject * object = BLUEZ_OBJECT(l->data); - - GList * interfaces = g_dbus_object_get_interfaces(G_DBUS_OBJECT(object)); - for (auto ll = interfaces; ll != nullptr; ll = ll->next) + GAutoPtr adapter(bluez_object_get_adapter1(BLUEZ_OBJECT(l->data))); + if (adapter.get() != nullptr) { - if (BLUEZ_IS_ADAPTER1(ll->data)) - { // we found the adapter - BluezAdapter1 * adapter = BLUEZ_ADAPTER1(ll->data); - if (mpAdapterAddr == nullptr) // no adapter address provided, bind to the hci indicated by nodeid + if (mpAdapterAddr == nullptr) // no adapter address provided, bind to the hci indicated by nodeid + { + if (strcmp(g_dbus_proxy_get_object_path(G_DBUS_PROXY(adapter.get())), expectedPath) == 0) { - if (strcmp(g_dbus_proxy_get_object_path(G_DBUS_PROXY(adapter)), expectedPath) == 0) - { - mpAdapter = static_cast(g_object_ref(adapter)); - } + mAdapter.reset(static_cast(g_object_ref(adapter.get()))); + break; } - else + } + else + { + if (strcmp(bluez_adapter1_get_address(adapter.get()), mpAdapterAddr) == 0) { - if (strcmp(bluez_adapter1_get_address(adapter), mpAdapterAddr) == 0) - { - mpAdapter = static_cast(g_object_ref(adapter)); - } + mAdapter.reset(static_cast(g_object_ref(adapter.get()))); + break; } } } - g_list_free_full(interfaces, g_object_unref); } - VerifyOrExit(mpAdapter != nullptr, ChipLogError(DeviceLayer, "FAIL: NULL mpAdapter in %s", __func__)); + VerifyOrExit(mAdapter.get() != nullptr, ChipLogError(DeviceLayer, "FAIL: NULL mAdapter in %s", __func__)); - bluez_adapter1_set_powered(mpAdapter, TRUE); + bluez_adapter1_set_powered(mAdapter.get(), TRUE); // Setting "Discoverable" to False on the adapter and to True on the advertisement convinces // Bluez to set "BR/EDR Not Supported" flag. Bluez doesn't provide API to do that explicitly // and the flag is necessary to force using LE transport. - bluez_adapter1_set_discoverable(mpAdapter, FALSE); + bluez_adapter1_set_discoverable(mAdapter.get(), FALSE); exit: g_list_free_full(objects, g_object_unref); @@ -692,8 +687,7 @@ void BluezEndpoint::Shutdown() +[](BluezEndpoint * self) { if (self->mpObjMgr != nullptr) g_object_unref(self->mpObjMgr); - if (self->mpAdapter != nullptr) - g_object_unref(self->mpAdapter); + self->mAdapter.reset(); if (self->mpRoot != nullptr) g_object_unref(self->mpRoot); if (self->mpService != nullptr) diff --git a/src/platform/Linux/bluez/BluezEndpoint.h b/src/platform/Linux/bluez/BluezEndpoint.h index 115731d665d4ba..d35cebdf6a6cfe 100644 --- a/src/platform/Linux/bluez/BluezEndpoint.h +++ b/src/platform/Linux/bluez/BluezEndpoint.h @@ -74,7 +74,7 @@ class BluezEndpoint CHIP_ERROR Init(bool aIsCentral, const char * apBleAddr); void Shutdown(); - BluezAdapter1 * GetAdapter() const { return mpAdapter; } + BluezAdapter1 * GetAdapter() const { return mAdapter.get(); } CHIP_ERROR RegisterGattApplication(); GDBusObjectManagerServer * GetGattApplicationObjectManager() const { return mpRoot; } @@ -127,7 +127,7 @@ class BluezEndpoint // Objects (interfaces) subscribed to by this service GDBusObjectManager * mpObjMgr = nullptr; - BluezAdapter1 * mpAdapter = nullptr; + GAutoPtr mAdapter; // Objects (interfaces) published by this service GDBusObjectManagerServer * mpRoot = nullptr; diff --git a/src/platform/Linux/bluez/ChipDeviceScanner.cpp b/src/platform/Linux/bluez/ChipDeviceScanner.cpp index 03b26aa08e3dc7..0d248058c3d1a0 100644 --- a/src/platform/Linux/bluez/ChipDeviceScanner.cpp +++ b/src/platform/Linux/bluez/ChipDeviceScanner.cpp @@ -58,7 +58,7 @@ CHIP_ERROR ChipDeviceScanner::Init(BluezAdapter1 * adapter, ChipDeviceScannerDel // Make this function idempotent by shutting down previously initialized state if any. Shutdown(); - mAdapter = BLUEZ_ADAPTER1(g_object_ref(adapter)); + mAdapter.reset(reinterpret_cast(g_object_ref(adapter))); mDelegate = delegate; // Create the D-Bus object manager client object on the glib thread, so that all D-Bus signals @@ -97,8 +97,7 @@ void ChipDeviceScanner::Shutdown() +[](ChipDeviceScanner * self) { if (self->mManager != nullptr) g_object_unref(self->mManager); - if (self->mAdapter != nullptr) - g_object_unref(self->mAdapter); + self->mAdapter.reset(); return CHIP_NO_ERROR; }, this); @@ -205,7 +204,7 @@ CHIP_ERROR ChipDeviceScanner::MainLoopStopScan(ChipDeviceScanner * self) self->mInterfaceChangedSignal = 0; } - if (!bluez_adapter1_call_stop_discovery_sync(self->mAdapter, nullptr /* not cancellable */, &error.GetReceiver())) + if (!bluez_adapter1_call_stop_discovery_sync(self->mAdapter.get(), nullptr /* not cancellable */, &error.GetReceiver())) { ChipLogError(Ble, "Failed to stop discovery %s", error->message); return CHIP_ERROR_INTERNAL; @@ -234,7 +233,7 @@ void ChipDeviceScanner::SignalInterfaceChanged(GDBusObjectManagerClient * manage void ChipDeviceScanner::ReportDevice(BluezDevice1 & device) { - if (strcmp(bluez_device1_get_adapter(&device), g_dbus_proxy_get_object_path(G_DBUS_PROXY(mAdapter))) != 0) + if (strcmp(bluez_device1_get_adapter(&device), g_dbus_proxy_get_object_path(G_DBUS_PROXY(mAdapter.get()))) != 0) { return; } @@ -252,7 +251,7 @@ void ChipDeviceScanner::ReportDevice(BluezDevice1 & device) void ChipDeviceScanner::RemoveDevice(BluezDevice1 & device) { - if (strcmp(bluez_device1_get_adapter(&device), g_dbus_proxy_get_object_path(G_DBUS_PROXY(mAdapter))) != 0) + if (strcmp(bluez_device1_get_adapter(&device), g_dbus_proxy_get_object_path(G_DBUS_PROXY(mAdapter.get()))) != 0) { return; } @@ -267,7 +266,7 @@ void ChipDeviceScanner::RemoveDevice(BluezDevice1 & device) const auto devicePath = g_dbus_proxy_get_object_path(G_DBUS_PROXY(&device)); GAutoPtr error; - if (!bluez_adapter1_call_remove_device_sync(mAdapter, devicePath, nullptr, &error.GetReceiver())) + if (!bluez_adapter1_call_remove_device_sync(mAdapter.get(), devicePath, nullptr, &error.GetReceiver())) { ChipLogDetail(Ble, "Failed to remove device %s: %s", StringOrNullMarker(devicePath), error->message); } @@ -302,7 +301,8 @@ CHIP_ERROR ChipDeviceScanner::MainLoopStartScan(ChipDeviceScanner * self) g_variant_builder_add(&filterBuilder, "{sv}", "Transport", g_variant_new_string("le")); GVariant * filter = g_variant_builder_end(&filterBuilder); - if (!bluez_adapter1_call_set_discovery_filter_sync(self->mAdapter, filter, self->mCancellable.get(), &error.GetReceiver())) + if (!bluez_adapter1_call_set_discovery_filter_sync(self->mAdapter.get(), filter, self->mCancellable.get(), + &error.GetReceiver())) { // Not critical: ignore if fails ChipLogError(Ble, "Failed to set discovery filters: %s", error->message); @@ -310,7 +310,7 @@ CHIP_ERROR ChipDeviceScanner::MainLoopStartScan(ChipDeviceScanner * self) } ChipLogProgress(Ble, "BLE initiating scan."); - if (!bluez_adapter1_call_start_discovery_sync(self->mAdapter, self->mCancellable.get(), &error.GetReceiver())) + if (!bluez_adapter1_call_start_discovery_sync(self->mAdapter.get(), self->mCancellable.get(), &error.GetReceiver())) { ChipLogError(Ble, "Failed to start discovery: %s", error->message); return CHIP_ERROR_INTERNAL; diff --git a/src/platform/Linux/bluez/ChipDeviceScanner.h b/src/platform/Linux/bluez/ChipDeviceScanner.h index 1271ec39cb241a..276499d73ef82a 100644 --- a/src/platform/Linux/bluez/ChipDeviceScanner.h +++ b/src/platform/Linux/bluez/ChipDeviceScanner.h @@ -27,6 +27,8 @@ #include #include +#include "Types.h" + namespace chip { namespace DeviceLayer { namespace Internal { @@ -105,8 +107,8 @@ class ChipDeviceScanner /// so that it can be re-discovered if it's still advertising. void RemoveDevice(BluezDevice1 & device); - GDBusObjectManager * mManager = nullptr; - BluezAdapter1 * mAdapter = nullptr; + GDBusObjectManager * mManager = nullptr; + GAutoPtr mAdapter; ChipDeviceScannerDelegate * mDelegate = nullptr; gulong mObjectAddedSignal = 0; gulong mInterfaceChangedSignal = 0; diff --git a/src/platform/Linux/bluez/Types.h b/src/platform/Linux/bluez/Types.h index f7be4d858d079a..729f3b445224af 100644 --- a/src/platform/Linux/bluez/Types.h +++ b/src/platform/Linux/bluez/Types.h @@ -54,12 +54,36 @@ namespace chip { +template <> +struct GAutoPtrDeleter +{ + using deleter = GObjectDeleter; +}; + template <> struct GAutoPtrDeleter { using deleter = GObjectDeleter; }; +template <> +struct GAutoPtrDeleter +{ + using deleter = GObjectDeleter; +}; + +template <> +struct GAutoPtrDeleter +{ + using deleter = GObjectDeleter; +}; + +template <> +struct GAutoPtrDeleter +{ + using deleter = GObjectDeleter; +}; + namespace DeviceLayer { namespace Internal { From ef8ee3239de27f1ca9290b51738ae407922d4c16 Mon Sep 17 00:00:00 2001 From: Vivien Nicolas Date: Fri, 23 Feb 2024 11:19:12 +0100 Subject: [PATCH 070/385] [DiagnosticLogs] Allow TransferFileDesignator or size 0 (#32267) --- .../common/BDXDiagnosticLogsServerDelegate.cpp | 13 ++++++++++--- .../diagnostic-logs-server.cpp | 2 -- src/protocols/bdx/BdxTransferProxyDiagnosticLog.cpp | 1 - src/protocols/bdx/StatusCode.cpp | 8 ++++++++ 4 files changed, 18 insertions(+), 6 deletions(-) diff --git a/examples/chip-tool/commands/common/BDXDiagnosticLogsServerDelegate.cpp b/examples/chip-tool/commands/common/BDXDiagnosticLogsServerDelegate.cpp index 27260a54f57887..2a5b2d5d7c97a1 100644 --- a/examples/chip-tool/commands/common/BDXDiagnosticLogsServerDelegate.cpp +++ b/examples/chip-tool/commands/common/BDXDiagnosticLogsServerDelegate.cpp @@ -25,9 +25,10 @@ constexpr uint8_t kMaxFileDesignatorLen = 32; constexpr uint16_t kMaxFilePathLen = kMaxFileDesignatorLen + sizeof(kTmpDir) + 1; // For testing a few file names trigger an error depending on the current 'phase'. -constexpr char kErrorOnTransferBegin[] = "Error:OnTransferBegin"; -constexpr char kErrorOnTransferData[] = "Error:OnTransferData"; -constexpr char kErrorOnTransferEnd[] = "Error:OnTransferEnd"; +constexpr char kErrorOnTransferBegin[] = "Error:OnTransferBegin"; +constexpr char kErrorOnTransferData[] = "Error:OnTransferData"; +constexpr char kErrorOnTransferEnd[] = "Error:OnTransferEnd"; +constexpr char kErrorTransferMethodNotSupported[] = "TransferMethodNotSupported.txt"; BDXDiagnosticLogsServerDelegate BDXDiagnosticLogsServerDelegate::sInstance; @@ -136,8 +137,14 @@ CHIP_ERROR BDXDiagnosticLogsServerDelegate::OnTransferBegin(chip::bdx::BDXTransf auto fileDesignator = transfer->GetFileDesignator(); LogFileDesignator("OnTransferBegin", fileDesignator); + VerifyOrReturnError(fileDesignator.size() != 0, CHIP_ERROR_UNKNOWN_RESOURCE_ID); + chip::CharSpan phaseErrorTarget(kErrorOnTransferBegin, sizeof(kErrorOnTransferBegin) - 1); ReturnErrorOnFailure(CheckForErrorRequested(phaseErrorTarget, fileDesignator)); + + chip::CharSpan transferErrorTarget(kErrorTransferMethodNotSupported, sizeof(kErrorTransferMethodNotSupported) - 1); + VerifyOrReturnError(!transferErrorTarget.data_equal(fileDesignator), CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE); + ReturnErrorOnFailure(CheckFileDesignatorAllowed(mFileDesignators, fileDesignator)); char outputFilePath[kMaxFilePathLen] = { 0 }; diff --git a/src/app/clusters/diagnostic-logs-server/diagnostic-logs-server.cpp b/src/app/clusters/diagnostic-logs-server/diagnostic-logs-server.cpp index 7b1b036ee4857b..83beb46484bb71 100644 --- a/src/app/clusters/diagnostic-logs-server/diagnostic-logs-server.cpp +++ b/src/app/clusters/diagnostic-logs-server/diagnostic-logs-server.cpp @@ -132,8 +132,6 @@ void DiagnosticLogsServer::HandleLogRequestForBdx(CommandHandler * commandObj, c // INVALID_COMMAND. VerifyOrReturn(transferFileDesignator.HasValue(), commandObj->AddStatus(path, Status::InvalidCommand)); - VerifyOrReturn(transferFileDesignator.Value().size() > 0, commandObj->AddStatus(path, Status::ConstraintError)); - VerifyOrReturn(transferFileDesignator.Value().size() <= kMaxFileDesignatorLen, commandObj->AddStatus(path, Status::ConstraintError)); diff --git a/src/protocols/bdx/BdxTransferProxyDiagnosticLog.cpp b/src/protocols/bdx/BdxTransferProxyDiagnosticLog.cpp index 3f8915462941fb..ba1a41376afbbe 100644 --- a/src/protocols/bdx/BdxTransferProxyDiagnosticLog.cpp +++ b/src/protocols/bdx/BdxTransferProxyDiagnosticLog.cpp @@ -33,7 +33,6 @@ CHIP_ERROR BDXTransferProxyDiagnosticLog::Init(TransferSession * transferSession uint16_t fileDesignatorLength = 0; auto fileDesignator = transferSession->GetFileDesignator(fileDesignatorLength); - VerifyOrReturnError(fileDesignatorLength > 0, CHIP_ERROR_INVALID_STRING_LENGTH); VerifyOrReturnError(fileDesignatorLength <= ArraySize(mFileDesignator), CHIP_ERROR_INVALID_STRING_LENGTH); mTransfer = transferSession; diff --git a/src/protocols/bdx/StatusCode.cpp b/src/protocols/bdx/StatusCode.cpp index 2f739b5e831de2..9ab6f8d9b442be 100644 --- a/src/protocols/bdx/StatusCode.cpp +++ b/src/protocols/bdx/StatusCode.cpp @@ -33,6 +33,14 @@ StatusCode GetBdxStatusCodeFromChipError(CHIP_ERROR error) { status = StatusCode::kBadMessageContents; } + else if (error == CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE) + { + status = StatusCode::kTransferMethodNotSupported; + } + else if (error == CHIP_ERROR_UNKNOWN_RESOURCE_ID) + { + status = StatusCode::kFileDesignatorUnknown; + } return status; } From a6fd6ce388bcb120b3d0128779fa0ecf40a5ee16 Mon Sep 17 00:00:00 2001 From: Andrei Litvin Date: Fri, 23 Feb 2024 09:55:29 -0500 Subject: [PATCH 071/385] Create a separate 'constants' source set in `src/app` (#32228) * Create constants file * Restyle * Place everything into a `Revision` namespace to avoid name collision with a Tags enum * Rename --------- Co-authored-by: Andrei Litvin --- src/app/BUILD.gn | 23 +++++++------ src/app/DataModelRevision.h | 31 ----------------- src/app/InteractionModelTimeout.h | 1 - src/app/MessageDef/BUILD.gn | 2 +- src/app/MessageDef/InvokeRequestMessage.cpp | 2 +- src/app/MessageDef/InvokeResponseMessage.cpp | 2 +- src/app/MessageDef/MessageBuilder.cpp | 3 +- src/app/MessageDef/MessageBuilder.h | 2 +- src/app/MessageDef/MessageDefHelper.cpp | 2 +- src/app/MessageDef/MessageParser.cpp | 4 +-- src/app/MessageDef/MessageParser.h | 2 +- src/app/MessageDef/ReadRequestMessage.cpp | 2 +- src/app/MessageDef/ReportDataMessage.cpp | 2 +- src/app/MessageDef/StatusResponseMessage.cpp | 2 +- .../MessageDef/SubscribeRequestMessage.cpp | 2 +- .../MessageDef/SubscribeResponseMessage.cpp | 2 +- src/app/MessageDef/TimedRequestMessage.cpp | 2 +- src/app/MessageDef/WriteRequestMessage.cpp | 2 +- src/app/MessageDef/WriteResponseMessage.cpp | 2 +- ...sion.h => SpecificationDefinedRevisions.h} | 33 +++++++++++++++---- src/app/SpecificationVersion.h | 31 ----------------- .../basic-information/basic-information.cpp | 7 ++-- src/protocols/secure_channel/BUILD.gn | 2 +- .../secure_channel/PairingSession.cpp | 10 +++--- 24 files changed, 65 insertions(+), 108 deletions(-) delete mode 100644 src/app/DataModelRevision.h rename src/app/{InteractionModelRevision.h => SpecificationDefinedRevisions.h} (51%) delete mode 100644 src/app/SpecificationVersion.h diff --git a/src/app/BUILD.gn b/src/app/BUILD.gn index f714560afc15cb..69f5926909756d 100644 --- a/src/app/BUILD.gn +++ b/src/app/BUILD.gn @@ -76,14 +76,6 @@ source_set("app_config") { deps = [ ":app_buildconfig" ] } -source_set("revision_info") { - sources = [ - "DataModelRevision.h", - "InteractionModelRevision.h", - "SpecificationVersion.h", - ] -} - source_set("paths") { sources = [ "AttributePathParams.h", @@ -130,6 +122,17 @@ config("config-controller-dynamic-server") { ] } +source_set("constants") { + sources = [ + "InteractionModelTimeout.h", + "SpecificationDefinedRevisions.h", + ] + public_deps = [ + "${chip_root}/src/lib/core", + "${chip_root}/src/system", + ] +} + # interaction-model is a static-library because it currently requires global functions (app/util/...) that are stubbed in different test files that depend on the app static_library # which in tern depens on the interaction-model. # Using source_set prevents the unit test to build correctly. @@ -149,7 +152,6 @@ static_library("interaction-model") { "InteractionModelEngine.cpp", "InteractionModelEngine.h", "InteractionModelHelper.h", - "InteractionModelTimeout.h", "OperationalSessionSetup.cpp", "OperationalSessionSetup.h", "OperationalSessionSetupPool.h", @@ -181,6 +183,7 @@ static_library("interaction-model") { public_deps = [ ":app_config", + ":constants", ":paths", ":subscription-manager", "${chip_root}/src/app/MessageDef", @@ -276,9 +279,9 @@ static_library("app") { public_deps = [ ":app_config", + ":constants", ":global-attributes", ":interaction-model", - ":revision_info", "${chip_root}/src/app/data-model", "${chip_root}/src/app/icd/server:icd-server-config", "${chip_root}/src/lib/address_resolve", diff --git a/src/app/DataModelRevision.h b/src/app/DataModelRevision.h deleted file mode 100644 index 47ecb626a13ffa..00000000000000 --- a/src/app/DataModelRevision.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * - * Copyright (c) 2022 Project CHIP Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#pragma once - -/** - * CHIP_DEVICE_DATA_MODEL_REVISION - * - * A monotonic number identifying the revision number of the Data Model against - * which the Node is certified. - * - * See section 7.1.1. "Revision History" in the "Data Model Specification" - * chapter of the core Matter specification. - */ -#ifndef CHIP_DEVICE_DATA_MODEL_REVISION -#define CHIP_DEVICE_DATA_MODEL_REVISION 17 -#endif diff --git a/src/app/InteractionModelTimeout.h b/src/app/InteractionModelTimeout.h index 3511ed5412049d..43153c679f2361 100644 --- a/src/app/InteractionModelTimeout.h +++ b/src/app/InteractionModelTimeout.h @@ -18,7 +18,6 @@ #pragma once #include -#include namespace chip { namespace app { diff --git a/src/app/MessageDef/BUILD.gn b/src/app/MessageDef/BUILD.gn index 4880a9a8b126e4..18b254038fe2b8 100644 --- a/src/app/MessageDef/BUILD.gn +++ b/src/app/MessageDef/BUILD.gn @@ -113,8 +113,8 @@ source_set("MessageDef") { deps = [ "${chip_root}/src/app:app_config", + "${chip_root}/src/app:constants", "${chip_root}/src/app:paths", - "${chip_root}/src/app:revision_info", "${chip_root}/src/lib/core", "${chip_root}/src/lib/support", "${chip_root}/src/protocols/interaction_model", diff --git a/src/app/MessageDef/InvokeRequestMessage.cpp b/src/app/MessageDef/InvokeRequestMessage.cpp index 50bd5cd45f70c0..d334b05dfa0362 100644 --- a/src/app/MessageDef/InvokeRequestMessage.cpp +++ b/src/app/MessageDef/InvokeRequestMessage.cpp @@ -74,7 +74,7 @@ CHIP_ERROR InvokeRequestMessage::Parser::PrettyPrint() const PRETTY_PRINT_DECDEPTH(); } break; - case kInteractionModelRevisionTag: + case Revision::kInteractionModelRevisionTag: ReturnErrorOnFailure(MessageParser::CheckInteractionModelRevision(reader)); break; default: diff --git a/src/app/MessageDef/InvokeResponseMessage.cpp b/src/app/MessageDef/InvokeResponseMessage.cpp index f9887530c15e15..53568ce14d9b5e 100644 --- a/src/app/MessageDef/InvokeResponseMessage.cpp +++ b/src/app/MessageDef/InvokeResponseMessage.cpp @@ -73,7 +73,7 @@ CHIP_ERROR InvokeResponseMessage::Parser::PrettyPrint() const } #endif // CHIP_DETAIL_LOGGING break; - case kInteractionModelRevisionTag: + case Revision::kInteractionModelRevisionTag: ReturnErrorOnFailure(MessageParser::CheckInteractionModelRevision(reader)); break; default: diff --git a/src/app/MessageDef/MessageBuilder.cpp b/src/app/MessageDef/MessageBuilder.cpp index b9ad0e58968d23..4effd887c6814c 100644 --- a/src/app/MessageDef/MessageBuilder.cpp +++ b/src/app/MessageDef/MessageBuilder.cpp @@ -24,8 +24,7 @@ namespace chip { namespace app { CHIP_ERROR MessageBuilder::EncodeInteractionModelRevision() { - return mpWriter->Put(TLV::ContextTag(kInteractionModelRevisionTag), - static_cast(CHIP_DEVICE_INTERACTION_MODEL_REVISION)); + return mpWriter->Put(TLV::ContextTag(Revision::kInteractionModelRevisionTag), Revision::kInteractionModelRevision); } } // namespace app } // namespace chip diff --git a/src/app/MessageDef/MessageBuilder.h b/src/app/MessageDef/MessageBuilder.h index 03210b3011cf21..fac114ad1379b5 100644 --- a/src/app/MessageDef/MessageBuilder.h +++ b/src/app/MessageDef/MessageBuilder.h @@ -18,7 +18,7 @@ #pragma once #include "StructBuilder.h" -#include +#include #include namespace chip { diff --git a/src/app/MessageDef/MessageDefHelper.cpp b/src/app/MessageDef/MessageDefHelper.cpp index db24b2623dcc00..82fcf286d1751b 100644 --- a/src/app/MessageDef/MessageDefHelper.cpp +++ b/src/app/MessageDef/MessageDefHelper.cpp @@ -24,7 +24,7 @@ #include "MessageDefHelper.h" #include #include -#include +#include #include #include #include diff --git a/src/app/MessageDef/MessageParser.cpp b/src/app/MessageDef/MessageParser.cpp index b855a93afcd7eb..7d74378b49f0c2 100644 --- a/src/app/MessageDef/MessageParser.cpp +++ b/src/app/MessageDef/MessageParser.cpp @@ -16,7 +16,7 @@ #include "MessageParser.h" #include "MessageDefHelper.h" -#include +#include namespace chip { namespace app { @@ -52,7 +52,7 @@ CHIP_ERROR MessageParser::CheckInteractionModelRevision(TLV::TLVReader & aReader CHIP_ERROR MessageParser::GetInteractionModelRevision(InteractionModelRevision * const apInteractionModelRevision) const { - return GetUnsignedInteger(kInteractionModelRevisionTag, apInteractionModelRevision); + return GetUnsignedInteger(Revision::kInteractionModelRevisionTag, apInteractionModelRevision); } } // namespace app diff --git a/src/app/MessageDef/MessageParser.h b/src/app/MessageDef/MessageParser.h index e307d5b905d965..4886f295e253eb 100644 --- a/src/app/MessageDef/MessageParser.h +++ b/src/app/MessageDef/MessageParser.h @@ -20,7 +20,7 @@ #include "StructParser.h" #include -#include +#include #include namespace chip { diff --git a/src/app/MessageDef/ReadRequestMessage.cpp b/src/app/MessageDef/ReadRequestMessage.cpp index 8b96b044d774c5..855d0a3e14d936 100644 --- a/src/app/MessageDef/ReadRequestMessage.cpp +++ b/src/app/MessageDef/ReadRequestMessage.cpp @@ -91,7 +91,7 @@ CHIP_ERROR ReadRequestMessage::Parser::PrettyPrint() const } #endif // CHIP_DETAIL_LOGGING break; - case kInteractionModelRevisionTag: + case Revision::kInteractionModelRevisionTag: ReturnErrorOnFailure(MessageParser::CheckInteractionModelRevision(reader)); break; default: diff --git a/src/app/MessageDef/ReportDataMessage.cpp b/src/app/MessageDef/ReportDataMessage.cpp index c3c569572ae9fe..a2a8ec47968ec1 100644 --- a/src/app/MessageDef/ReportDataMessage.cpp +++ b/src/app/MessageDef/ReportDataMessage.cpp @@ -112,7 +112,7 @@ CHIP_ERROR ReportDataMessage::Parser::PrettyPrint() const } #endif // CHIP_DETAIL_LOGGING break; - case kInteractionModelRevisionTag: + case Revision::kInteractionModelRevisionTag: ReturnErrorOnFailure(MessageParser::CheckInteractionModelRevision(reader)); break; default: diff --git a/src/app/MessageDef/StatusResponseMessage.cpp b/src/app/MessageDef/StatusResponseMessage.cpp index f702998c90ed23..fbf3a870d542c6 100644 --- a/src/app/MessageDef/StatusResponseMessage.cpp +++ b/src/app/MessageDef/StatusResponseMessage.cpp @@ -52,7 +52,7 @@ CHIP_ERROR StatusResponseMessage::Parser::PrettyPrint() const } #endif // CHIP_DETAIL_LOGGING break; - case kInteractionModelRevisionTag: + case Revision::kInteractionModelRevisionTag: ReturnErrorOnFailure(MessageParser::CheckInteractionModelRevision(reader)); break; default: diff --git a/src/app/MessageDef/SubscribeRequestMessage.cpp b/src/app/MessageDef/SubscribeRequestMessage.cpp index b536570891bade..7224c850baaa20 100644 --- a/src/app/MessageDef/SubscribeRequestMessage.cpp +++ b/src/app/MessageDef/SubscribeRequestMessage.cpp @@ -115,7 +115,7 @@ CHIP_ERROR SubscribeRequestMessage::Parser::PrettyPrint() const } #endif // CHIP_DETAIL_LOGGING break; - case kInteractionModelRevisionTag: + case Revision::kInteractionModelRevisionTag: ReturnErrorOnFailure(MessageParser::CheckInteractionModelRevision(reader)); break; default: diff --git a/src/app/MessageDef/SubscribeResponseMessage.cpp b/src/app/MessageDef/SubscribeResponseMessage.cpp index 99528895e49796..25ef8ec0bd3038 100644 --- a/src/app/MessageDef/SubscribeResponseMessage.cpp +++ b/src/app/MessageDef/SubscribeResponseMessage.cpp @@ -59,7 +59,7 @@ CHIP_ERROR SubscribeResponseMessage::Parser::PrettyPrint() const } #endif // CHIP_DETAIL_LOGGING break; - case kInteractionModelRevisionTag: + case Revision::kInteractionModelRevisionTag: ReturnErrorOnFailure(MessageParser::CheckInteractionModelRevision(reader)); break; default: diff --git a/src/app/MessageDef/TimedRequestMessage.cpp b/src/app/MessageDef/TimedRequestMessage.cpp index bf6bdc5b79a45b..830a3d66894377 100644 --- a/src/app/MessageDef/TimedRequestMessage.cpp +++ b/src/app/MessageDef/TimedRequestMessage.cpp @@ -49,7 +49,7 @@ CHIP_ERROR TimedRequestMessage::Parser::PrettyPrint() const } #endif // CHIP_DETAIL_LOGGING break; - case kInteractionModelRevisionTag: + case Revision::kInteractionModelRevisionTag: ReturnErrorOnFailure(MessageParser::CheckInteractionModelRevision(reader)); break; default: diff --git a/src/app/MessageDef/WriteRequestMessage.cpp b/src/app/MessageDef/WriteRequestMessage.cpp index 8cf3d4048d9b2f..5278fff2c94166 100644 --- a/src/app/MessageDef/WriteRequestMessage.cpp +++ b/src/app/MessageDef/WriteRequestMessage.cpp @@ -88,7 +88,7 @@ CHIP_ERROR WriteRequestMessage::Parser::PrettyPrint() const } #endif // CHIP_DETAIL_LOGGING break; - case kInteractionModelRevisionTag: + case Revision::kInteractionModelRevisionTag: ReturnErrorOnFailure(MessageParser::CheckInteractionModelRevision(reader)); break; default: diff --git a/src/app/MessageDef/WriteResponseMessage.cpp b/src/app/MessageDef/WriteResponseMessage.cpp index 4426d5e3db7c5e..e8da708bfc94e5 100644 --- a/src/app/MessageDef/WriteResponseMessage.cpp +++ b/src/app/MessageDef/WriteResponseMessage.cpp @@ -54,7 +54,7 @@ CHIP_ERROR WriteResponseMessage::Parser::PrettyPrint() const ReturnErrorOnFailure(writeResponses.PrettyPrint()); PRETTY_PRINT_DECDEPTH(); break; - case kInteractionModelRevisionTag: + case Revision::kInteractionModelRevisionTag: ReturnErrorOnFailure(MessageParser::CheckInteractionModelRevision(reader)); break; default: diff --git a/src/app/InteractionModelRevision.h b/src/app/SpecificationDefinedRevisions.h similarity index 51% rename from src/app/InteractionModelRevision.h rename to src/app/SpecificationDefinedRevisions.h index 529ac0f839c80e..cad67aced413b0 100644 --- a/src/app/InteractionModelRevision.h +++ b/src/app/SpecificationDefinedRevisions.h @@ -20,16 +20,37 @@ #include #include +#include + +namespace chip { +namespace Revision { + /** - * CHIP_DEVICE_INTERACTION_MODEL_REVISION - * * A monothonic number identifying the interaction model revision. * * See section 8.1.1. "Revision History" in the "Interaction Model * Specification" chapter of the core Matter specification. */ -#ifndef CHIP_DEVICE_INTERACTION_MODEL_REVISION -#define CHIP_DEVICE_INTERACTION_MODEL_REVISION 11 -#endif +inline constexpr InteractionModelRevision kInteractionModelRevision = 11; +inline constexpr uint8_t kInteractionModelRevisionTag = 0xFF; + +/** + * A monotonic number identifying the revision number of the Data Model against + * which the Node is certified. + * + * See section 7.1.1. "Revision History" in the "Data Model Specification" + * chapter of the core Matter specification. + */ +inline constexpr uint16_t kDataModelRevision = 17; + +/* + * A number identifying the specification version against which the + * Node is certified. + * + * See section 11.1.5.22. "SpecificationVersion Attribute" in "Service and + * Device Management" chapter of the core Matter specification. + */ +inline constexpr uint32_t kSpecificationVersion = 0x01030000; -inline constexpr uint8_t kInteractionModelRevisionTag = 0xFF; +} // namespace Revision +} // namespace chip diff --git a/src/app/SpecificationVersion.h b/src/app/SpecificationVersion.h deleted file mode 100644 index b0570dad14c4ce..00000000000000 --- a/src/app/SpecificationVersion.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * - * Copyright (c) 2023 Project CHIP Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#pragma once - -/** - * CHIP_DEVICE_SPECIFICATION_VERSION - * - * A number identifying the specification version against which the - * Node is certified. - * - * See section 11.1.5.22. "SpecificationVersion Attribute" in "Service and - * Device Management" chapter of the core Matter specification. - */ -#ifndef CHIP_DEVICE_SPECIFICATION_VERSION -#define CHIP_DEVICE_SPECIFICATION_VERSION 0x01030000 -#endif diff --git a/src/app/clusters/basic-information/basic-information.cpp b/src/app/clusters/basic-information/basic-information.cpp index 641dc59a853dd6..91eef9d9dae899 100644 --- a/src/app/clusters/basic-information/basic-information.cpp +++ b/src/app/clusters/basic-information/basic-information.cpp @@ -20,10 +20,9 @@ #include #include -#include #include #include -#include +#include #include #include #include @@ -314,7 +313,7 @@ CHIP_ERROR BasicAttrAccess::Read(const ConcreteReadAttributePath & aPath, Attrib CHIP_ERROR BasicAttrAccess::ReadDataModelRevision(AttributeValueEncoder & aEncoder) { - uint16_t revision = CHIP_DEVICE_DATA_MODEL_REVISION; + uint16_t revision = Revision::kDataModelRevision; return aEncoder.Encode(revision); } @@ -399,7 +398,7 @@ CHIP_ERROR BasicAttrAccess::ReadProductAppearance(AttributeValueEncoder & aEncod CHIP_ERROR BasicAttrAccess::ReadSpecificationVersion(AttributeValueEncoder & aEncoder) { - uint32_t specification_version = CHIP_DEVICE_SPECIFICATION_VERSION; + uint32_t specification_version = Revision::kSpecificationVersion; return aEncoder.Encode(specification_version); } diff --git a/src/protocols/secure_channel/BUILD.gn b/src/protocols/secure_channel/BUILD.gn index dcae65a6f4d271..1202c0bb88a9ae 100644 --- a/src/protocols/secure_channel/BUILD.gn +++ b/src/protocols/secure_channel/BUILD.gn @@ -88,5 +88,5 @@ static_library("secure_channel") { "${chip_root}/src/transport", ] - deps = [ "${chip_root}/src/app:revision_info" ] + deps = [ "${chip_root}/src/app:constants" ] } diff --git a/src/protocols/secure_channel/PairingSession.cpp b/src/protocols/secure_channel/PairingSession.cpp index 23daea30f2800c..80e048597578be 100644 --- a/src/protocols/secure_channel/PairingSession.cpp +++ b/src/protocols/secure_channel/PairingSession.cpp @@ -18,9 +18,7 @@ #include -#include -#include -#include +#include #include #include #include @@ -112,13 +110,13 @@ CHIP_ERROR PairingSession::EncodeSessionParameters(TLV::Tag tag, const Optional< ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(SessionParameters::Tag::kSessionActiveThreshold), mrpLocalConfig.mActiveThresholdTime.count())); - uint16_t dataModel = CHIP_DEVICE_DATA_MODEL_REVISION; + uint16_t dataModel = Revision::kDataModelRevision; ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(SessionParameters::Tag::kDataModelRevision), dataModel)); - uint16_t interactionModel = CHIP_DEVICE_INTERACTION_MODEL_REVISION; + uint16_t interactionModel = Revision::kInteractionModelRevision; ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(SessionParameters::Tag::kInteractionModelRevision), interactionModel)); - uint32_t specVersion = CHIP_DEVICE_SPECIFICATION_VERSION; + uint32_t specVersion = Revision::kSpecificationVersion; ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(SessionParameters::Tag::kSpecificationVersion), specVersion)); uint16_t maxPathsPerInvoke = CHIP_CONFIG_MAX_PATHS_PER_INVOKE; From 52f5f019eeb0274a4f929cd607edf761dfbff482 Mon Sep 17 00:00:00 2001 From: Andrei Litvin Date: Fri, 23 Feb 2024 11:07:22 -0500 Subject: [PATCH 072/385] Move `declare_args` sections from `data_model` into AppConfig.h (#32270) * Move defines into buildconfig_headers rather than data_model templates * Restyle * Update src/app/BUILD.gn Co-authored-by: Boris Zbarsky * Add minssing include --------- Co-authored-by: Andrei Litvin Co-authored-by: Boris Zbarsky --- src/app/BUILD.gn | 11 +++++++++++ src/app/chip_data_model.gni | 13 ------------- .../ota-requestor/DefaultOTARequestorDriver.cpp | 4 +++- .../time-synchronization-server.cpp | 11 +++++------ .../time-synchronization-server.h | 14 +++++++------- 5 files changed, 26 insertions(+), 27 deletions(-) diff --git a/src/app/BUILD.gn b/src/app/BUILD.gn index 69f5926909756d..e6754bd8c32a31 100644 --- a/src/app/BUILD.gn +++ b/src/app/BUILD.gn @@ -43,6 +43,15 @@ declare_args() { enable_eventlist_attribute = false + # Allow building ota-requestor-app with a non-spec-compliant floor + # (i.e. smaller than 2 minutes) for action delays. + non_spec_compliant_ota_action_delay_floor = -1 + + # enable time sync client for use in `time-synchronization-server` (if linked) + # TODO: this should probably be migrated to be time-synchronization-server specific + # if the cluster build targets are decoupled as stand-alone units. + time_sync_enable_tsc_feature = 1 + # Systems that can spare a bit of RAM for InteractionModelEngine/delegate # pointers should do so (allows InteractionModelEngine decoupling and less usage # of global pointers) @@ -65,6 +74,8 @@ buildconfig_header("app_buildconfig") { "CHIP_CONFIG_ENABLE_EVENTLIST_ATTRIBUTE=${enable_eventlist_attribute}", "CHIP_CONFIG_ENABLE_READ_CLIENT=${chip_enable_read_client}", "CHIP_CONFIG_STATIC_GLOBAL_INTERACTION_MODEL_ENGINE=${chip_im_static_global_interaction_model_engine}", + "TIME_SYNC_ENABLE_TSC_FEATURE=${time_sync_enable_tsc_feature}", + "NON_SPEC_COMPLIANT_OTA_ACTION_DELAY_FLOOR=${non_spec_compliant_ota_action_delay_floor}", ] visibility = [ ":app_config" ] diff --git a/src/app/chip_data_model.gni b/src/app/chip_data_model.gni index 3763243e404407..42bc2f9b74ad64 100644 --- a/src/app/chip_data_model.gni +++ b/src/app/chip_data_model.gni @@ -35,13 +35,6 @@ _app_root = get_path_info(".", "abspath") template("chip_data_model") { _data_model_name = target_name - declare_args() { - # Allow building ota-requestor-app with a non-spec-compliant floor - # (i.e. smaller than 2 minutes) for action delays. - non_spec_compliant_ota_action_delay_floor = -1 - time_sync_enable_tsc_feature = 1 - } - if (defined(invoker.idl)) { _idl = invoker.idl } else { @@ -244,8 +237,6 @@ template("chip_data_model") { "${_app_root}/clusters/${cluster}/DefaultTimeSyncDelegate.cpp", "${_app_root}/clusters/${cluster}/TimeSyncDataProvider.cpp", ] - defines += - [ "TIME_SYNC_ENABLE_TSC_FEATURE=${time_sync_enable_tsc_feature}" ] } else if (cluster == "scenes-server") { sources += [ "${_app_root}/clusters/${cluster}/${cluster}.cpp", @@ -359,9 +350,5 @@ template("chip_data_model") { } cflags += [ "-Wconversion" ] - - if (non_spec_compliant_ota_action_delay_floor >= 0) { - cflags += [ "-DNON_SPEC_COMPLIANT_OTA_ACTION_DELAY_FLOOR=${non_spec_compliant_ota_action_delay_floor}" ] - } } } diff --git a/src/app/clusters/ota-requestor/DefaultOTARequestorDriver.cpp b/src/app/clusters/ota-requestor/DefaultOTARequestorDriver.cpp index 60cc54277c36cd..d3efeaee6fb3a9 100644 --- a/src/app/clusters/ota-requestor/DefaultOTARequestorDriver.cpp +++ b/src/app/clusters/ota-requestor/DefaultOTARequestorDriver.cpp @@ -38,6 +38,8 @@ #include "DefaultOTARequestorDriver.h" #include "OTARequestorInterface.h" +#include + namespace chip { namespace DeviceLayer { namespace { @@ -49,7 +51,7 @@ constexpr uint8_t kMaxInvalidSessionRetries = 1; // Max # of query image constexpr uint32_t kDelayQueryUponCommissioningSec = 30; // Delay before sending the initial image query after commissioning constexpr uint32_t kImmediateStartDelaySec = 1; // Delay before sending a query in response to UrgentUpdateAvailable -#ifdef NON_SPEC_COMPLIANT_OTA_ACTION_DELAY_FLOOR +#if NON_SPEC_COMPLIANT_OTA_ACTION_DELAY_FLOOR >= 0 constexpr System::Clock::Seconds32 kDefaultDelayedActionTime = System::Clock::Seconds32(NON_SPEC_COMPLIANT_OTA_ACTION_DELAY_FLOOR); #else constexpr System::Clock::Seconds32 kDefaultDelayedActionTime = System::Clock::Seconds32(120); diff --git a/src/app/clusters/time-synchronization-server/time-synchronization-server.cpp b/src/app/clusters/time-synchronization-server/time-synchronization-server.cpp index cc6c3f509c8937..a8433397ee6751 100644 --- a/src/app/clusters/time-synchronization-server/time-synchronization-server.cpp +++ b/src/app/clusters/time-synchronization-server/time-synchronization-server.cpp @@ -18,11 +18,8 @@ #include "DefaultTimeSyncDelegate.h" #include "time-synchronization-delegate.h" -#if TIME_SYNC_ENABLE_TSC_FEATURE -#include -#endif - #include +#include #include #include #include @@ -37,10 +34,12 @@ #include #include -#include - #include +#if TIME_SYNC_ENABLE_TSC_FEATURE +#include +#endif + using namespace chip; using namespace chip::app; using namespace chip::DeviceLayer; diff --git a/src/app/clusters/time-synchronization-server/time-synchronization-server.h b/src/app/clusters/time-synchronization-server/time-synchronization-server.h index c6012b19bb0836..ef40eaacc790c4 100644 --- a/src/app/clusters/time-synchronization-server/time-synchronization-server.h +++ b/src/app/clusters/time-synchronization-server/time-synchronization-server.h @@ -21,16 +21,10 @@ #pragma once -#ifndef TIME_SYNC_ENABLE_TSC_FEATURE -#define TIME_SYNC_ENABLE_TSC_FEATURE 1 -#endif - #include "TimeSyncDataProvider.h" #include "time-synchronization-delegate.h" -#if TIME_SYNC_ENABLE_TSC_FEATURE -#include -#endif +#include #include #include #include @@ -40,6 +34,12 @@ #include #include +// NOTE: this is part of AppConfig, so this has to be checked for AFTER the inclusion +// of that header +#if TIME_SYNC_ENABLE_TSC_FEATURE +#include +#endif + namespace chip { namespace app { namespace Clusters { From c49e7844d071866720fea23bed5bbdeb764fd991 Mon Sep 17 00:00:00 2001 From: joonhaengHeo <85541460+joonhaengHeo@users.noreply.github.com> Date: Sat, 24 Feb 2024 01:19:00 +0900 Subject: [PATCH 073/385] [Android] Fix NsdService crash (#32284) * Fix NsdService crash in Android Platform * Restyled by google-java-format --------- Co-authored-by: Restyled.io --- .../java/chip/platform/NsdServiceFinderAndResolver.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/platform/android/java/chip/platform/NsdServiceFinderAndResolver.java b/src/platform/android/java/chip/platform/NsdServiceFinderAndResolver.java index 7ee8f979e5ac33..fc3425f7bd8889 100644 --- a/src/platform/android/java/chip/platform/NsdServiceFinderAndResolver.java +++ b/src/platform/android/java/chip/platform/NsdServiceFinderAndResolver.java @@ -71,9 +71,6 @@ public NsdServiceFinderAndResolver( public void start() { multicastLock.acquire(); - this.nsdManager.discoverServices( - targetServiceInfo.getServiceType(), NsdManager.PROTOCOL_DNS_SD, this); - NsdServiceFinderAndResolver serviceFinderResolver = this; this.stopDiscoveryRunnable = Executors.newSingleThreadScheduledExecutor() @@ -92,6 +89,9 @@ public void run() { }, BROWSE_SERVICE_TIMEOUT_MS, TimeUnit.MILLISECONDS); + + this.nsdManager.discoverServices( + targetServiceInfo.getServiceType(), NsdManager.PROTOCOL_DNS_SD, this); } @Override From 52ab3dbbfe2bbb79e590aa6396fbee8985cdc469 Mon Sep 17 00:00:00 2001 From: C Freeman Date: Fri, 23 Feb 2024 12:46:55 -0500 Subject: [PATCH 074/385] TC-IDM-10.1: Fix guard around non-standard attributes (#32231) --- src/controller/python/chip/clusters/ClusterObjects.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/controller/python/chip/clusters/ClusterObjects.py b/src/controller/python/chip/clusters/ClusterObjects.py index 111274c884a8dd..bf07544af9e888 100644 --- a/src/controller/python/chip/clusters/ClusterObjects.py +++ b/src/controller/python/chip/clusters/ClusterObjects.py @@ -301,10 +301,11 @@ def __init_subclass__(cls, *args, **kwargs) -> None: """Register a subclass.""" super().__init_subclass__(*args, **kwargs) try: - if cls.standard_attribute and cls.cluster_id not in ALL_ATTRIBUTES: - ALL_ATTRIBUTES[cls.cluster_id] = {} - # register this clusterattribute in the ALL_ATTRIBUTES dict for quick lookups - ALL_ATTRIBUTES[cls.cluster_id][cls.attribute_id] = cls + if cls.standard_attribute: + if cls.cluster_id not in ALL_ATTRIBUTES: + ALL_ATTRIBUTES[cls.cluster_id] = {} + # register this clusterattribute in the ALL_ATTRIBUTES dict for quick lookups + ALL_ATTRIBUTES[cls.cluster_id][cls.attribute_id] = cls except NotImplementedError: # handle case where the ClusterAttribute class is not (fully) subclassed # and accessing the id property throws a NotImplementedError. From 3903f6cbef862b691645eec706fc669f33646ab9 Mon Sep 17 00:00:00 2001 From: Wang Qixiang <43193572+wqx6@users.noreply.github.com> Date: Sat, 24 Feb 2024 02:24:47 +0800 Subject: [PATCH 075/385] Add more ICD menuconfig options for ICD server (#32286) --- config/esp32/components/chip/CMakeLists.txt | 19 ++++++++ config/esp32/components/chip/Kconfig | 52 ++++++++++++++++++++- 2 files changed, 69 insertions(+), 2 deletions(-) diff --git a/config/esp32/components/chip/CMakeLists.txt b/config/esp32/components/chip/CMakeLists.txt index 7f62ce6cc0087a..14594a03b74352 100644 --- a/config/esp32/components/chip/CMakeLists.txt +++ b/config/esp32/components/chip/CMakeLists.txt @@ -131,6 +131,25 @@ endif() if(CONFIG_ENABLE_ICD_SERVER) chip_gn_arg_append("chip_enable_icd_server" "true") + if(CONFIG_ICD_ENFORCE_SIT_SLOW_POLL_LIMIT) + chip_gn_arg_append("icd_enforce_sit_slow_poll_limit" "true") + endif() + if(CONFIG_ICD_REPORT_ON_ACTIVE_MODE) + chip_gn_arg_append("chip_icd_report_on_active_mode" "true") + endif() + if(CONFIG_ENABLE_ICD_LIT) + chip_gn_arg_append("chip_enable_icd_lit" "true") + if(CONFIG_ENABLE_ICD_CIP) + chip_gn_arg_append("chip_enable_icd_checkin" "true") + else() + chip_gn_arg_append("chip_enable_icd_checkin" "false") + endif() + if(CONFIG_ENABLE_ICD_USER_ACTIVE_MODE_TRIGGER) + chip_gn_arg_append("chip_enable_icd_user_active_mode_trigger" "true") + else() + chip_gn_arg_append("chip_enable_icd_user_active_mode_trigger" "false") + endif() + endif() endif() if(CONFIG_ENABLE_PW_RPC) diff --git a/config/esp32/components/chip/Kconfig b/config/esp32/components/chip/Kconfig index 0dce48b5f720be..b39105d1285fac 100644 --- a/config/esp32/components/chip/Kconfig +++ b/config/esp32/components/chip/Kconfig @@ -340,13 +340,27 @@ menu "CHIP Device Layer" help Enables or Disables the support for Commissionable Device Type. - config ENABLE_ICD_SERVER + menuconfig ENABLE_ICD_SERVER bool "Enable ICD server" depends on OPENTHREAD_MTD default n help Enables or Disables ICD server + config ICD_ENFORCE_SIT_SLOW_POLL_LIMIT + bool "Enforce SIT Slow Polling Max value to 15 seconds" + depends on ENABLE_ICD_SERVER + default n + help + Set to true to enforce SIT Slow Polling Max value to 15seconds + + config ICD_REPORT_ON_ACTIVE_MODE + bool "Emit a report on entering active mode" + depends on ENABLE_ICD_SERVER + default n + help + Make the ICD manager emit a report on entering active mode + config ICD_SLOW_POLL_INTERVAL_MS int "ICD Slow Polling Interval(ms)" depends on ENABLE_ICD_SERVER @@ -389,14 +403,48 @@ menu "CHIP Device Layer" This value indicates the minimum amount of time in milliseconds the server typically will stay active after network activity when in active mode. + config ENABLE_ICD_LIT + bool "Enable Long Idle Time ICD" + depends on ENABLE_ICD_SERVER + default n + help + Enables or Disables LIT ICD + + config ENABLE_ICD_CIP + bool "Enable Check-in protocol" + depends on ENABLE_ICD_LIT + default y + help + Enables or Disables ICD Check-in protocol + config ICD_CLIENTS_SUPPORTED_PER_FABRIC int "ICD Clients Number Supported Per Fabric" - depends on ENABLE_ICD_SERVER + depends on ENABLE_ICD_CIP default 1 help This value indicates the maximum number of entries that the ICD server is able to store for each fabric in the RegisteredClients attribute. + config ICD_MAX_NOTIFICATION_SUBSCRIBERS + int "Max ICD notification subscribers" + depends on ENABLE_ICD_SERVER + default 1 + help + The ICDManager implements the ICDListener functions and is always subscribed to the ICDNotifier + This allows other Matter modules to inform the ICDManager that it needs to go and may have to stay in Active Mode, + outside of its standard ActiveModeDuration and IdleModeDuration, without being tightly coupled the application + data model + + This implementation also allows other modules to implement an ICDListener and subscribe to ICDNotifier + to couple behaviours with the ICD cycles. In such cases, ICD_MAX_NOTIFICATION_SUBSCRIBERS need to be adjusted + + config ENABLE_ICD_USER_ACTIVE_MODE_TRIGGER + bool "Enable User Active Mode Trigger feature" + depends on ENABLE_ICD_LIT + default y + help + Enables or Disables ICD User Active Mode Trigger feature + config ENABLE_BG_EVENT_PROCESSING bool "Enable Background event processing" default n From 7ba98fb892a5e80e5872c0546e05338e0b7de9e6 Mon Sep 17 00:00:00 2001 From: Hasty Granbery Date: Sat, 24 Feb 2024 03:28:18 +0900 Subject: [PATCH 076/385] [Messages] Change message duration to uint64 (#32248) * Change message duration to uint64 * Fixes to Java build * Missed a HandlePresentMessagesRequest signature --- data_model/clusters/Messages.xml | 2 +- .../include/messages/MessagesManager.cpp | 2 +- .../include/messages/MessagesManager.h | 2 +- .../tv-app/android/java/MessagesManager.cpp | 12 +++++------ .../tv-app/android/java/MessagesManager.h | 2 +- .../com/matter/tv/server/tvapp/Message.java | 4 ++-- .../tv/server/tvapp/MessagesManager.java | 2 +- .../tv/server/tvapp/MessagesManagerStub.java | 2 +- .../clusters/messages/MessagesManager.cpp | 2 +- .../clusters/messages/MessagesManager.h | 6 +++--- examples/tv-app/tv-common/tv-app.matter | 4 ++-- .../tv-casting-common/tv-casting-app.matter | 4 ++-- .../messages-server/messages-delegate.h | 2 +- .../zcl/data-model/chip/messages-cluster.xml | 4 ++-- .../data_model/controller-clusters.matter | 4 ++-- .../chip/devicecontroller/ChipClusters.java | 4 ++-- .../chip/devicecontroller/ChipStructs.java | 8 +++---- .../devicecontroller/ClusterInfoMapping.java | 4 ++-- .../structs/MessagesClusterMessageStruct.kt | 4 ++-- .../cluster/clusters/MessagesCluster.kt | 2 +- .../structs/MessagesClusterMessageStruct.kt | 4 ++-- .../CHIPAttributeTLVValueDecoder.cpp | 21 +++++++++---------- .../MTRAttributeTLVValueDecoder.mm | 2 +- .../zap-generated/MTRCommandPayloadsObjc.mm | 2 +- .../zap-generated/cluster-objects.h | 8 +++---- .../zap-generated/cluster/Commands.h | 2 +- .../zap-generated/cluster/Commands.h | 4 ++-- 27 files changed, 59 insertions(+), 60 deletions(-) diff --git a/data_model/clusters/Messages.xml b/data_model/clusters/Messages.xml index cea28ac15f54c9..5bc3ce81fa2a0d 100644 --- a/data_model/clusters/Messages.xml +++ b/data_model/clusters/Messages.xml @@ -216,7 +216,7 @@ Davis, CA 95616, USA - + diff --git a/examples/tv-app/android/include/messages/MessagesManager.cpp b/examples/tv-app/android/include/messages/MessagesManager.cpp index dcd48f028b961e..00848c67312751 100644 --- a/examples/tv-app/android/include/messages/MessagesManager.cpp +++ b/examples/tv-app/android/include/messages/MessagesManager.cpp @@ -25,7 +25,7 @@ using namespace chip::app::Clusters::Messages; void MessagesManager::HandlePresentMessagesRequest( const chip::ByteSpan & messageId, const MessagePriorityEnum & priority, const chip::BitMask & messageControl, const chip::app::DataModel::Nullable & startTime, - const chip::app::DataModel::Nullable & duration, const chip::CharSpan & messageText, + const chip::app::DataModel::Nullable & duration, const chip::CharSpan & messageText, const chip::Optional> & responses) { // TODO: Present Message diff --git a/examples/tv-app/android/include/messages/MessagesManager.h b/examples/tv-app/android/include/messages/MessagesManager.h index 5f06d253846c4f..d6759061800621 100644 --- a/examples/tv-app/android/include/messages/MessagesManager.h +++ b/examples/tv-app/android/include/messages/MessagesManager.h @@ -27,7 +27,7 @@ class MessagesManager : public chip::app::Clusters::Messages::Delegate void HandlePresentMessagesRequest( const chip::ByteSpan & messageId, const chip::app::Clusters::Messages::MessagePriorityEnum & priority, const chip::BitMask & messageControl, - const chip::app::DataModel::Nullable & startTime, const chip::app::DataModel::Nullable & duration, + const chip::app::DataModel::Nullable & startTime, const chip::app::DataModel::Nullable & duration, const chip::CharSpan & messageText, const chip::Optional> & responses) override; diff --git a/examples/tv-app/android/java/MessagesManager.cpp b/examples/tv-app/android/java/MessagesManager.cpp index 9203d7b54510f5..dbcb5c5994504b 100644 --- a/examples/tv-app/android/java/MessagesManager.cpp +++ b/examples/tv-app/android/java/MessagesManager.cpp @@ -183,10 +183,10 @@ CHIP_ERROR MessagesManager::HandleGetMessages(AttributeValueEncoder & aEncoder) } jfieldID durationField = env->GetFieldID(messageClass, "duration", "I"); - jint jduration = env->GetIntField(messageObject, durationField); + jlong jduration = env->GetLongField(messageObject, durationField); if (jduration >= 0) { - message.duration = DataModel::Nullable(static_cast(jduration)); + message.duration = DataModel::Nullable(static_cast(jduration)); } jfieldID getResponseOptionsField = @@ -301,7 +301,7 @@ CHIP_ERROR MessagesManager::HandleGetActiveMessageIds(AttributeValueEncoder & aE CHIP_ERROR MessagesManager::HandlePresentMessagesRequest( const ByteSpan & messageId, const MessagePriorityEnum & priority, const BitMask & messageControl, - const DataModel::Nullable & startTime, const DataModel::Nullable & duration, const CharSpan & messageText, + const DataModel::Nullable & startTime, const DataModel::Nullable & duration, const CharSpan & messageText, const Optional> & responses) { DeviceLayer::StackUnlock unlock; @@ -336,11 +336,11 @@ CHIP_ERROR MessagesManager::HandlePresentMessagesRequest( return CHIP_ERROR_INTERNAL; } - jint jcontrol = static_cast(messageControl.Raw()); - jint jduration = -1; + jint jcontrol = static_cast(messageControl.Raw()); + jlong jduration = -1; if (!duration.IsNull()) { - jduration = static_cast(duration.Value()); + jduration = static_cast(duration.Value()); } jlong jstartTime = -1; if (!startTime.IsNull()) diff --git a/examples/tv-app/android/java/MessagesManager.h b/examples/tv-app/android/java/MessagesManager.h index 563192a542bdf6..089d3e4360afe0 100644 --- a/examples/tv-app/android/java/MessagesManager.h +++ b/examples/tv-app/android/java/MessagesManager.h @@ -35,7 +35,7 @@ class MessagesManager : public chip::app::Clusters::Messages::Delegate CHIP_ERROR HandlePresentMessagesRequest( const chip::ByteSpan & messageId, const chip::app::Clusters::Messages::MessagePriorityEnum & priority, const chip::BitMask & messageControl, - const chip::app::DataModel::Nullable & startTime, const chip::app::DataModel::Nullable & duration, + const chip::app::DataModel::Nullable & startTime, const chip::app::DataModel::Nullable & duration, const chip::CharSpan & messageText, const chip::Optional< chip::app::DataModel::DecodableList> & diff --git a/examples/tv-app/android/java/src/com/matter/tv/server/tvapp/Message.java b/examples/tv-app/android/java/src/com/matter/tv/server/tvapp/Message.java index c194ffb44f9ee1..8949ab8283b10d 100644 --- a/examples/tv-app/android/java/src/com/matter/tv/server/tvapp/Message.java +++ b/examples/tv-app/android/java/src/com/matter/tv/server/tvapp/Message.java @@ -23,7 +23,7 @@ public class Message { public int priority; public int messageControl; public long startTime; - public int duration; + public long duration; public String messageText; public MessageResponseOption responseOptions[]; @@ -32,7 +32,7 @@ public Message( int priority, int messageControl, long startTime, - int duration, + long duration, String messageText, MessageResponseOption responseOptions[]) { this.messageId = messageId; diff --git a/examples/tv-app/android/java/src/com/matter/tv/server/tvapp/MessagesManager.java b/examples/tv-app/android/java/src/com/matter/tv/server/tvapp/MessagesManager.java index 0a5680866714c6..5d97083cafe8a4 100644 --- a/examples/tv-app/android/java/src/com/matter/tv/server/tvapp/MessagesManager.java +++ b/examples/tv-app/android/java/src/com/matter/tv/server/tvapp/MessagesManager.java @@ -28,7 +28,7 @@ boolean presentMessages( int priority, int messageControl, long startTime, - int duration, + long duration, String messageText, HashMap responseOptions); diff --git a/examples/tv-app/android/java/src/com/matter/tv/server/tvapp/MessagesManagerStub.java b/examples/tv-app/android/java/src/com/matter/tv/server/tvapp/MessagesManagerStub.java index 63fef69d35c936..55d94209197559 100644 --- a/examples/tv-app/android/java/src/com/matter/tv/server/tvapp/MessagesManagerStub.java +++ b/examples/tv-app/android/java/src/com/matter/tv/server/tvapp/MessagesManagerStub.java @@ -52,7 +52,7 @@ public boolean presentMessages( int priority, int messageControl, long startTime, - int duration, + long duration, String messageText, HashMap responseOptions) { Log.d( diff --git a/examples/tv-app/tv-common/clusters/messages/MessagesManager.cpp b/examples/tv-app/tv-common/clusters/messages/MessagesManager.cpp index 6ffbb9a3476258..461e35524c0736 100644 --- a/examples/tv-app/tv-common/clusters/messages/MessagesManager.cpp +++ b/examples/tv-app/tv-common/clusters/messages/MessagesManager.cpp @@ -30,7 +30,7 @@ using MessageResponseOption = chip::app::Clusters::Messages::Structs::MessageRes // Commands CHIP_ERROR MessagesManager::HandlePresentMessagesRequest( const ByteSpan & messageId, const MessagePriorityEnum & priority, const BitMask & messageControl, - const DataModel::Nullable & startTime, const DataModel::Nullable & duration, const CharSpan & messageText, + const DataModel::Nullable & startTime, const DataModel::Nullable & duration, const CharSpan & messageText, const Optional> & responses) { ChipLogProgress(Zcl, "HandlePresentMessagesRequest message:%s", std::string(messageText.data(), messageText.size()).c_str()); diff --git a/examples/tv-app/tv-common/clusters/messages/MessagesManager.h b/examples/tv-app/tv-common/clusters/messages/MessagesManager.h index 325cd56fc788af..777f202e28548a 100644 --- a/examples/tv-app/tv-common/clusters/messages/MessagesManager.h +++ b/examples/tv-app/tv-common/clusters/messages/MessagesManager.h @@ -64,7 +64,7 @@ struct CachedMessage CachedMessage(const chip::ByteSpan & messageId, const chip::app::Clusters::Messages::MessagePriorityEnum & priority, const chip::BitMask & messageControl, const chip::app::DataModel::Nullable & startTime, - const chip::app::DataModel::Nullable & duration, std::string messageText) : + const chip::app::DataModel::Nullable & duration, std::string messageText) : mPriority(priority), mMessageControl(messageControl), mStartTime(startTime), mDuration(duration), mMessageText(messageText) { @@ -110,7 +110,7 @@ struct CachedMessage const chip::app::Clusters::Messages::MessagePriorityEnum mPriority; const chip::BitMask mMessageControl; const chip::app::DataModel::Nullable mStartTime; - const chip::app::DataModel::Nullable mDuration; + const chip::app::DataModel::Nullable mDuration; std::string mMessageText; uint8_t mMessageIdBuffer[chip::app::Clusters::Messages::kMessageIdLength]; @@ -126,7 +126,7 @@ class MessagesManager : public chip::app::Clusters::Messages::Delegate CHIP_ERROR HandlePresentMessagesRequest( const chip::ByteSpan & messageId, const chip::app::Clusters::Messages::MessagePriorityEnum & priority, const chip::BitMask & messageControl, - const chip::app::DataModel::Nullable & startTime, const chip::app::DataModel::Nullable & duration, + const chip::app::DataModel::Nullable & startTime, const chip::app::DataModel::Nullable & duration, const chip::CharSpan & messageText, const chip::Optional< chip::app::DataModel::DecodableList> & diff --git a/examples/tv-app/tv-common/tv-app.matter b/examples/tv-app/tv-common/tv-app.matter index 6effacc92c0812..37fd9cb777b98b 100644 --- a/examples/tv-app/tv-common/tv-app.matter +++ b/examples/tv-app/tv-common/tv-app.matter @@ -2067,7 +2067,7 @@ provisional cluster Messages = 151 { MessagePriorityEnum priority = 1; MessageControlBitmap messageControl = 2; nullable epoch_s startTime = 3; - nullable int16u duration = 4; + nullable int64u duration = 4; char_string<256> messageText = 5; optional MessageResponseOptionStruct responses[] = 6; } @@ -2101,7 +2101,7 @@ provisional cluster Messages = 151 { MessagePriorityEnum priority = 1; MessageControlBitmap messageControl = 2; nullable epoch_s startTime = 3; - nullable int16u duration = 4; + nullable int64u duration = 4; char_string<256> messageText = 5; optional MessageResponseOptionStruct responses[] = 6; } diff --git a/examples/tv-casting-app/tv-casting-common/tv-casting-app.matter b/examples/tv-casting-app/tv-casting-common/tv-casting-app.matter index 4bece078774075..35a766e68307aa 100644 --- a/examples/tv-casting-app/tv-casting-common/tv-casting-app.matter +++ b/examples/tv-casting-app/tv-casting-common/tv-casting-app.matter @@ -1545,7 +1545,7 @@ provisional cluster Messages = 151 { MessagePriorityEnum priority = 1; MessageControlBitmap messageControl = 2; nullable epoch_s startTime = 3; - nullable int16u duration = 4; + nullable int64u duration = 4; char_string<256> messageText = 5; optional MessageResponseOptionStruct responses[] = 6; } @@ -1579,7 +1579,7 @@ provisional cluster Messages = 151 { MessagePriorityEnum priority = 1; MessageControlBitmap messageControl = 2; nullable epoch_s startTime = 3; - nullable int16u duration = 4; + nullable int64u duration = 4; char_string<256> messageText = 5; optional MessageResponseOptionStruct responses[] = 6; } diff --git a/src/app/clusters/messages-server/messages-delegate.h b/src/app/clusters/messages-server/messages-delegate.h index aba771aad23953..6be09de781d340 100644 --- a/src/app/clusters/messages-server/messages-delegate.h +++ b/src/app/clusters/messages-server/messages-delegate.h @@ -42,7 +42,7 @@ class Delegate virtual CHIP_ERROR HandlePresentMessagesRequest( const ByteSpan & messageId, const MessagePriorityEnum & priority, const chip::BitMask & messageControl, const DataModel::Nullable & startTime, - const DataModel::Nullable & duration, const CharSpan & messageText, + const DataModel::Nullable & duration, const CharSpan & messageText, const chip::Optional> & responses) = 0; virtual CHIP_ERROR HandleCancelMessagesRequest(const DataModel::DecodableList & messageIds) = 0; diff --git a/src/app/zap-templates/zcl/data-model/chip/messages-cluster.xml b/src/app/zap-templates/zcl/data-model/chip/messages-cluster.xml index 2da346cd49a6f7..16b1527625d320 100644 --- a/src/app/zap-templates/zcl/data-model/chip/messages-cluster.xml +++ b/src/app/zap-templates/zcl/data-model/chip/messages-cluster.xml @@ -58,7 +58,7 @@ limitations under the License. - + @@ -88,7 +88,7 @@ limitations under the License. - + diff --git a/src/controller/data_model/controller-clusters.matter b/src/controller/data_model/controller-clusters.matter index 235366f4206e78..8611f4bdcf62d8 100644 --- a/src/controller/data_model/controller-clusters.matter +++ b/src/controller/data_model/controller-clusters.matter @@ -4539,7 +4539,7 @@ provisional cluster Messages = 151 { MessagePriorityEnum priority = 1; MessageControlBitmap messageControl = 2; nullable epoch_s startTime = 3; - nullable int16u duration = 4; + nullable int64u duration = 4; char_string<256> messageText = 5; optional MessageResponseOptionStruct responses[] = 6; } @@ -4573,7 +4573,7 @@ provisional cluster Messages = 151 { MessagePriorityEnum priority = 1; MessageControlBitmap messageControl = 2; nullable epoch_s startTime = 3; - nullable int16u duration = 4; + nullable int64u duration = 4; char_string<256> messageText = 5; optional MessageResponseOptionStruct responses[] = 6; } diff --git a/src/controller/java/generated/java/chip/devicecontroller/ChipClusters.java b/src/controller/java/generated/java/chip/devicecontroller/ChipClusters.java index fcc9154511d2b7..7025f3cde37858 100644 --- a/src/controller/java/generated/java/chip/devicecontroller/ChipClusters.java +++ b/src/controller/java/generated/java/chip/devicecontroller/ChipClusters.java @@ -29906,11 +29906,11 @@ public long initWithDevice(long devicePtr, int endpointId) { return 0L; } - public void presentMessagesRequest(DefaultClusterCallback callback, byte[] messageID, Integer priority, Integer messageControl, @Nullable Long startTime, @Nullable Integer duration, String messageText, Optional> responses) { + public void presentMessagesRequest(DefaultClusterCallback callback, byte[] messageID, Integer priority, Integer messageControl, @Nullable Long startTime, @Nullable Long duration, String messageText, Optional> responses) { presentMessagesRequest(callback, messageID, priority, messageControl, startTime, duration, messageText, responses, 0); } - public void presentMessagesRequest(DefaultClusterCallback callback, byte[] messageID, Integer priority, Integer messageControl, @Nullable Long startTime, @Nullable Integer duration, String messageText, Optional> responses, int timedInvokeTimeoutMs) { + public void presentMessagesRequest(DefaultClusterCallback callback, byte[] messageID, Integer priority, Integer messageControl, @Nullable Long startTime, @Nullable Long duration, String messageText, Optional> responses, int timedInvokeTimeoutMs) { final long commandId = 0L; ArrayList elements = new ArrayList<>(); diff --git a/src/controller/java/generated/java/chip/devicecontroller/ChipStructs.java b/src/controller/java/generated/java/chip/devicecontroller/ChipStructs.java index 6fb0469aded45c..7730f05efe734a 100644 --- a/src/controller/java/generated/java/chip/devicecontroller/ChipStructs.java +++ b/src/controller/java/generated/java/chip/devicecontroller/ChipStructs.java @@ -7130,7 +7130,7 @@ public static class MessagesClusterMessageStruct { public Integer priority; public Integer messageControl; public @Nullable Long startTime; - public @Nullable Integer duration; + public @Nullable Long duration; public String messageText; public Optional> responses; private static final long MESSAGE_I_D_ID = 0L; @@ -7146,7 +7146,7 @@ public MessagesClusterMessageStruct( Integer priority, Integer messageControl, @Nullable Long startTime, - @Nullable Integer duration, + @Nullable Long duration, String messageText, Optional> responses ) { @@ -7180,7 +7180,7 @@ public static MessagesClusterMessageStruct decodeTlv(BaseTLVType tlvValue) { Integer priority = null; Integer messageControl = null; @Nullable Long startTime = null; - @Nullable Integer duration = null; + @Nullable Long duration = null; String messageText = null; Optional> responses = Optional.empty(); for (StructElement element: ((StructType)tlvValue).value()) { @@ -7207,7 +7207,7 @@ public static MessagesClusterMessageStruct decodeTlv(BaseTLVType tlvValue) { } else if (element.contextTagNum() == DURATION_ID) { if (element.value(BaseTLVType.class).type() == TLVType.UInt) { UIntType castingValue = element.value(UIntType.class); - duration = castingValue.value(Integer.class); + duration = castingValue.value(Long.class); } } else if (element.contextTagNum() == MESSAGE_TEXT_ID) { if (element.value(BaseTLVType.class).type() == TLVType.String) { diff --git a/src/controller/java/generated/java/chip/devicecontroller/ClusterInfoMapping.java b/src/controller/java/generated/java/chip/devicecontroller/ClusterInfoMapping.java index 14b4a97284f173..5162f9766a74da 100644 --- a/src/controller/java/generated/java/chip/devicecontroller/ClusterInfoMapping.java +++ b/src/controller/java/generated/java/chip/devicecontroller/ClusterInfoMapping.java @@ -24325,7 +24325,7 @@ public Map> getCommandMap() { CommandParameterInfo messagespresentMessagesRequeststartTimeCommandParameterInfo = new CommandParameterInfo("startTime", Long.class, Long.class); messagespresentMessagesRequestCommandParams.put("startTime",messagespresentMessagesRequeststartTimeCommandParameterInfo); - CommandParameterInfo messagespresentMessagesRequestdurationCommandParameterInfo = new CommandParameterInfo("duration", Integer.class, Integer.class); + CommandParameterInfo messagespresentMessagesRequestdurationCommandParameterInfo = new CommandParameterInfo("duration", Long.class, Long.class); messagespresentMessagesRequestCommandParams.put("duration",messagespresentMessagesRequestdurationCommandParameterInfo); CommandParameterInfo messagespresentMessagesRequestmessageTextCommandParameterInfo = new CommandParameterInfo("messageText", String.class, String.class); @@ -24343,7 +24343,7 @@ public Map> getCommandMap() { commandArguments.get("messageControl") , (Long) commandArguments.get("startTime") - , (Integer) + , (Long) commandArguments.get("duration") , (String) commandArguments.get("messageText") diff --git a/src/controller/java/generated/java/chip/devicecontroller/cluster/structs/MessagesClusterMessageStruct.kt b/src/controller/java/generated/java/chip/devicecontroller/cluster/structs/MessagesClusterMessageStruct.kt index d1749289a3b652..03a544caf41c32 100644 --- a/src/controller/java/generated/java/chip/devicecontroller/cluster/structs/MessagesClusterMessageStruct.kt +++ b/src/controller/java/generated/java/chip/devicecontroller/cluster/structs/MessagesClusterMessageStruct.kt @@ -29,7 +29,7 @@ class MessagesClusterMessageStruct( val priority: UInt, val messageControl: UInt, val startTime: ULong?, - val duration: UInt?, + val duration: ULong?, val messageText: String, val responses: Optional> ) { @@ -97,7 +97,7 @@ class MessagesClusterMessageStruct( } val duration = if (!tlvReader.isNull()) { - tlvReader.getUInt(ContextSpecificTag(TAG_DURATION)) + tlvReader.getULong(ContextSpecificTag(TAG_DURATION)) } else { tlvReader.getNull(ContextSpecificTag(TAG_DURATION)) null diff --git a/src/controller/java/generated/java/matter/controller/cluster/clusters/MessagesCluster.kt b/src/controller/java/generated/java/matter/controller/cluster/clusters/MessagesCluster.kt index 5ce55e2e0dd21b..3e3fcd8f02d2f8 100644 --- a/src/controller/java/generated/java/matter/controller/cluster/clusters/MessagesCluster.kt +++ b/src/controller/java/generated/java/matter/controller/cluster/clusters/MessagesCluster.kt @@ -106,7 +106,7 @@ class MessagesCluster(private val controller: MatterController, private val endp priority: UByte, messageControl: UByte, startTime: UInt?, - duration: UShort?, + duration: ULong?, messageText: String, responses: List?, timedInvokeTimeout: Duration? = null diff --git a/src/controller/java/generated/java/matter/controller/cluster/structs/MessagesClusterMessageStruct.kt b/src/controller/java/generated/java/matter/controller/cluster/structs/MessagesClusterMessageStruct.kt index 8560beb0a72ce1..14c573c396ca18 100644 --- a/src/controller/java/generated/java/matter/controller/cluster/structs/MessagesClusterMessageStruct.kt +++ b/src/controller/java/generated/java/matter/controller/cluster/structs/MessagesClusterMessageStruct.kt @@ -29,7 +29,7 @@ class MessagesClusterMessageStruct( val priority: UByte, val messageControl: UByte, val startTime: UInt?, - val duration: UShort?, + val duration: ULong?, val messageText: String, val responses: Optional> ) { @@ -97,7 +97,7 @@ class MessagesClusterMessageStruct( } val duration = if (!tlvReader.isNull()) { - tlvReader.getUShort(ContextSpecificTag(TAG_DURATION)) + tlvReader.getULong(ContextSpecificTag(TAG_DURATION)) } else { tlvReader.getNull(ContextSpecificTag(TAG_DURATION)) null diff --git a/src/controller/java/zap-generated/CHIPAttributeTLVValueDecoder.cpp b/src/controller/java/zap-generated/CHIPAttributeTLVValueDecoder.cpp index 7a8aebe5b5c493..2400ba818c7cb9 100644 --- a/src/controller/java/zap-generated/CHIPAttributeTLVValueDecoder.cpp +++ b/src/controller/java/zap-generated/CHIPAttributeTLVValueDecoder.cpp @@ -23068,12 +23068,12 @@ jobject DecodeAttributeValue(const app::ConcreteAttributePath & aPath, TLV::TLVR } else { - std::string newElement_0_durationClassName = "java/lang/Integer"; - std::string newElement_0_durationCtorSignature = "(I)V"; - jint jninewElement_0_duration = static_cast(entry_0.duration.Value()); - chip::JniReferences::GetInstance().CreateBoxedObject(newElement_0_durationClassName.c_str(), - newElement_0_durationCtorSignature.c_str(), - jninewElement_0_duration, newElement_0_duration); + std::string newElement_0_durationClassName = "java/lang/Long"; + std::string newElement_0_durationCtorSignature = "(J)V"; + jlong jninewElement_0_duration = static_cast(entry_0.duration.Value()); + chip::JniReferences::GetInstance().CreateBoxedObject(newElement_0_durationClassName.c_str(), + newElement_0_durationCtorSignature.c_str(), + jninewElement_0_duration, newElement_0_duration); } jobject newElement_0_messageText; LogErrorOnFailure( @@ -23163,11 +23163,10 @@ jobject DecodeAttributeValue(const app::ConcreteAttributePath & aPath, TLV::TLVR } jmethodID messageStructStructCtor_1; - err = - chip::JniReferences::GetInstance().FindMethod(env, messageStructStructClass_1, "", - "([BLjava/lang/Integer;Ljava/lang/Integer;Ljava/lang/Long;Ljava/" - "lang/Integer;Ljava/lang/String;Ljava/util/Optional;)V", - &messageStructStructCtor_1); + err = chip::JniReferences::GetInstance().FindMethod(env, messageStructStructClass_1, "", + "([BLjava/lang/Integer;Ljava/lang/Integer;Ljava/lang/" + "Long;Ljava/lang/Long;Ljava/lang/String;Ljava/util/Optional;)V", + &messageStructStructCtor_1); if (err != CHIP_NO_ERROR || messageStructStructCtor_1 == nullptr) { ChipLogError(Zcl, "Could not find ChipStructs$MessagesClusterMessageStruct constructor"); diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRAttributeTLVValueDecoder.mm b/src/darwin/Framework/CHIP/zap-generated/MTRAttributeTLVValueDecoder.mm index 298c127feeb02d..bae1643f3beb39 100644 --- a/src/darwin/Framework/CHIP/zap-generated/MTRAttributeTLVValueDecoder.mm +++ b/src/darwin/Framework/CHIP/zap-generated/MTRAttributeTLVValueDecoder.mm @@ -8750,7 +8750,7 @@ static id _Nullable DecodeAttributeValueForMessagesCluster(AttributeId aAttribut if (entry_0.duration.IsNull()) { newElement_0.duration = nil; } else { - newElement_0.duration = [NSNumber numberWithUnsignedShort:entry_0.duration.Value()]; + newElement_0.duration = [NSNumber numberWithUnsignedLongLong:entry_0.duration.Value()]; } newElement_0.messageText = AsString(entry_0.messageText); if (newElement_0.messageText == nil) { diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloadsObjc.mm b/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloadsObjc.mm index b2c13559d07aec..60757c92d0dfdb 100644 --- a/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloadsObjc.mm +++ b/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloadsObjc.mm @@ -15516,7 +15516,7 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader encodableStruct.duration.SetNull(); } else { auto & nonNullValue_0 = encodableStruct.duration.SetNonNull(); - nonNullValue_0 = self.duration.unsignedShortValue; + nonNullValue_0 = self.duration.unsignedLongLongValue; } } { diff --git a/zzz_generated/app-common/app-common/zap-generated/cluster-objects.h b/zzz_generated/app-common/app-common/zap-generated/cluster-objects.h index 99e6e3bb1d63f7..dfdf2e691686f2 100644 --- a/zzz_generated/app-common/app-common/zap-generated/cluster-objects.h +++ b/zzz_generated/app-common/app-common/zap-generated/cluster-objects.h @@ -21506,7 +21506,7 @@ struct Type MessagePriorityEnum priority = static_cast(0); chip::BitMask messageControl = static_cast>(0); DataModel::Nullable startTime; - DataModel::Nullable duration; + DataModel::Nullable duration; chip::CharSpan messageText; Optional> responses; @@ -21522,7 +21522,7 @@ struct DecodableType MessagePriorityEnum priority = static_cast(0); chip::BitMask messageControl = static_cast>(0); DataModel::Nullable startTime; - DataModel::Nullable duration; + DataModel::Nullable duration; chip::CharSpan messageText; Optional> responses; @@ -21573,7 +21573,7 @@ struct Type MessagePriorityEnum priority = static_cast(0); chip::BitMask messageControl = static_cast>(0); DataModel::Nullable startTime; - DataModel::Nullable duration; + DataModel::Nullable duration; chip::CharSpan messageText; Optional> responses; @@ -21594,7 +21594,7 @@ struct DecodableType MessagePriorityEnum priority = static_cast(0); chip::BitMask messageControl = static_cast>(0); DataModel::Nullable startTime; - DataModel::Nullable duration; + DataModel::Nullable duration; chip::CharSpan messageText; Optional> responses; CHIP_ERROR Decode(TLV::TLVReader & reader); diff --git a/zzz_generated/chip-tool/zap-generated/cluster/Commands.h b/zzz_generated/chip-tool/zap-generated/cluster/Commands.h index 3a7a4e981629b6..6191eb2aa3ec2d 100644 --- a/zzz_generated/chip-tool/zap-generated/cluster/Commands.h +++ b/zzz_generated/chip-tool/zap-generated/cluster/Commands.h @@ -6837,7 +6837,7 @@ class MessagesPresentMessagesRequest : public ClusterCommand AddArgument("Priority", 0, UINT8_MAX, &mRequest.priority); AddArgument("MessageControl", 0, UINT8_MAX, &mRequest.messageControl); AddArgument("StartTime", 0, UINT32_MAX, &mRequest.startTime); - AddArgument("Duration", 0, UINT16_MAX, &mRequest.duration); + AddArgument("Duration", 0, UINT64_MAX, &mRequest.duration); AddArgument("MessageText", &mRequest.messageText); AddArgument("Responses", &mComplex_Responses, "", Argument::kOptional); ClusterCommand::AddArguments(); diff --git a/zzz_generated/darwin-framework-tool/zap-generated/cluster/Commands.h b/zzz_generated/darwin-framework-tool/zap-generated/cluster/Commands.h index 9a1389e416deb4..60843e78e103e7 100644 --- a/zzz_generated/darwin-framework-tool/zap-generated/cluster/Commands.h +++ b/zzz_generated/darwin-framework-tool/zap-generated/cluster/Commands.h @@ -81043,7 +81043,7 @@ class MessagesPresentMessagesRequest : public ClusterCommand { AddArgument("StartTime", 0, UINT32_MAX, &mRequest.startTime); #endif // MTR_ENABLE_PROVISIONAL #if MTR_ENABLE_PROVISIONAL - AddArgument("Duration", 0, UINT16_MAX, &mRequest.duration); + AddArgument("Duration", 0, UINT64_MAX, &mRequest.duration); #endif // MTR_ENABLE_PROVISIONAL #if MTR_ENABLE_PROVISIONAL AddArgument("MessageText", &mRequest.messageText); @@ -81085,7 +81085,7 @@ class MessagesPresentMessagesRequest : public ClusterCommand { if (mRequest.duration.IsNull()) { params.duration = nil; } else { - params.duration = [NSNumber numberWithUnsignedShort:mRequest.duration.Value()]; + params.duration = [NSNumber numberWithUnsignedLongLong:mRequest.duration.Value()]; } #endif // MTR_ENABLE_PROVISIONAL #if MTR_ENABLE_PROVISIONAL From 9cf74ab126b0f80068a3600ca9f08ebca59a53e0 Mon Sep 17 00:00:00 2001 From: yunhanw-google Date: Fri, 23 Feb 2024 10:30:36 -0800 Subject: [PATCH 077/385] Update logEvent restriction description in doc (#32150) * Update logEvent restriction description in doc * Restyled by prettier-markdown --------- Co-authored-by: Restyled.io --- .../cluster_and_device_type_dev.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/cluster_and_device_type_dev/cluster_and_device_type_dev.md b/docs/cluster_and_device_type_dev/cluster_and_device_type_dev.md index 9e34e961ae6d87..ca8e295a1cabf9 100644 --- a/docs/cluster_and_device_type_dev/cluster_and_device_type_dev.md +++ b/docs/cluster_and_device_type_dev/cluster_and_device_type_dev.md @@ -238,7 +238,9 @@ pure CommandHandlerInterface implementations. - **MatterReportingAttributeChangeCallback** - **Events** - No direct ember support - - Call LogEvent function in EventLogging.h + - Call LogEvent function in EventLogging.h. Caller has to either lock the + Matter stack lock or queue the event to the Matter event queue when + using LogEvent. #### A note on Dynamic Endpoints From b7a781a66ebfa68d4576c472f0ed3b11b24de0e6 Mon Sep 17 00:00:00 2001 From: Yufeng Wang Date: Fri, 23 Feb 2024 12:14:07 -0800 Subject: [PATCH 078/385] Support for encoding Field IDs with an MC source (#32276) * Support for encoding Field IDs with an MC source * Update src/lib/support/jsontlv/JsonToTlv.h Co-authored-by: Tennessee Carmel-Veilleux * Address review comments * Fix linter * Fix linter * restyle --------- Co-authored-by: Tennessee Carmel-Veilleux --- src/lib/support/jsontlv/JsonToTlv.cpp | 52 ++++++++++--- src/lib/support/jsontlv/JsonToTlv.h | 12 ++- src/lib/support/jsontlv/TlvToJson.cpp | 11 +-- src/lib/support/tests/TestJsonToTlv.cpp | 73 ++++++++++++++++++- src/lib/support/tests/TestJsonToTlvToJson.cpp | 53 +++++++++++--- 5 files changed, 167 insertions(+), 34 deletions(-) diff --git a/src/lib/support/jsontlv/JsonToTlv.cpp b/src/lib/support/jsontlv/JsonToTlv.cpp index 387c5f94594da1..0cc816133be9e7 100644 --- a/src/lib/support/jsontlv/JsonToTlv.cpp +++ b/src/lib/support/jsontlv/JsonToTlv.cpp @@ -16,6 +16,7 @@ */ #include +#include #include #include #include @@ -179,26 +180,34 @@ bool CompareByTag(const ElementContext & a, const ElementContext & b) return IsContextTag(a.tag); } -CHIP_ERROR InternalConvertTlvTag(const uint64_t tagNumber, TLV::Tag & tag, const uint32_t profileId = kTemporaryImplicitProfileId) +// The profileId parameter is used when encoding a tag for a TLV element to specify the profile that the tag belongs to. +// If the vendor ID is zero but the tag ID does not fit within an 8-bit value, the function uses Implicit Profile Tag. +// Here, the kTemporaryImplicitProfileId serves as a default value for cases where no explicit profile ID is provided by +// the caller. This allows for the encoding of tags that are not vendor-specific or context-specific but are instead +// associated with a temporary implicit profile ID (0xFF01). +CHIP_ERROR InternalConvertTlvTag(uint32_t tagNumber, TLV::Tag & tag, const uint32_t profileId = kTemporaryImplicitProfileId) { - if (tagNumber <= UINT8_MAX) + uint16_t vendor_id = static_cast(tagNumber >> 16); + uint16_t tag_id = static_cast(tagNumber & 0xFFFF); + + if (vendor_id != 0) { - tag = TLV::ContextTag(static_cast(tagNumber)); + tag = TLV::ProfileTag(vendor_id, /*profileNum=*/0, tag_id); } - else if (tagNumber <= UINT32_MAX) + else if (tag_id <= UINT8_MAX) { - tag = TLV::ProfileTag(profileId, static_cast(tagNumber)); + tag = TLV::ContextTag(static_cast(tagNumber)); } else { - return CHIP_ERROR_INVALID_ARGUMENT; + tag = TLV::ProfileTag(profileId, tagNumber); } return CHIP_NO_ERROR; } CHIP_ERROR ParseJsonName(const std::string name, ElementContext & elementCtx, uint32_t implicitProfileId) { - uint64_t tagNumber = 0; + uint32_t tagNumber = 0; const char * elementType = nullptr; std::vector nameFields = SplitIntoFieldsBySeparator(name, ':'); TLV::Tag tag = TLV::AnonymousTag(); @@ -208,13 +217,27 @@ CHIP_ERROR ParseJsonName(const std::string name, ElementContext & elementCtx, ui if (nameFields.size() == 2) { VerifyOrReturnError(IsUnsignedInteger(nameFields[0]), CHIP_ERROR_INVALID_ARGUMENT); - tagNumber = std::strtoull(nameFields[0].c_str(), nullptr, 10); + + char * endPtr; + errno = 0; + unsigned long result = strtoul(nameFields[0].c_str(), &endPtr, 10); + VerifyOrReturnError(nameFields[0].c_str() != endPtr, CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrReturnError((errno != ERANGE && result <= UINT32_MAX), CHIP_ERROR_INVALID_ARGUMENT); + + tagNumber = static_cast(result); elementType = nameFields[1].c_str(); } else if (nameFields.size() == 3) { VerifyOrReturnError(IsUnsignedInteger(nameFields[1]), CHIP_ERROR_INVALID_ARGUMENT); - tagNumber = std::strtoull(nameFields[1].c_str(), nullptr, 10); + + char * endPtr; + errno = 0; + unsigned long result = strtoul(nameFields[1].c_str(), &endPtr, 10); + VerifyOrReturnError(nameFields[1].c_str() != endPtr, CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrReturnError((errno != ERANGE && result <= UINT32_MAX), CHIP_ERROR_INVALID_ARGUMENT); + + tagNumber = static_cast(result); elementType = nameFields[2].c_str(); } else @@ -459,10 +482,19 @@ CHIP_ERROR JsonToTlv(const std::string & jsonString, TLV::TLVWriter & writer) ElementContext elementCtx; elementCtx.type = { TLV::kTLVType_Structure, false }; + + // Use kTemporaryImplicitProfileId as the default value for cases where no explicit implicit profile ID is provided by + // the caller. This allows for the encoding of tags that are not vendor-specific or context-specific but are instead + // associated with a temporary implicit profile ID (0xFF01). + if (writer.ImplicitProfileId == TLV::kProfileIdNotSpecified) + { + writer.ImplicitProfileId = kTemporaryImplicitProfileId; + } + return EncodeTlvElement(json, writer, elementCtx); } -CHIP_ERROR ConvertTlvTag(const uint64_t tagNumber, TLV::Tag & tag) +CHIP_ERROR ConvertTlvTag(uint32_t tagNumber, TLV::Tag & tag) { return InternalConvertTlvTag(tagNumber, tag); } diff --git a/src/lib/support/jsontlv/JsonToTlv.h b/src/lib/support/jsontlv/JsonToTlv.h index 287f0d7279f645..9b0ff194fa8182 100644 --- a/src/lib/support/jsontlv/JsonToTlv.h +++ b/src/lib/support/jsontlv/JsonToTlv.h @@ -33,10 +33,14 @@ CHIP_ERROR JsonToTlv(const std::string & jsonString, MutableByteSpan & tlv); CHIP_ERROR JsonToTlv(const std::string & jsonString, TLV::TLVWriter & writer); /* - * Convert a uint64_t tagNumber to a TLV tag. When tagNumber is less than or equal to UINT8_MAX, - * the tag is encoded using ContextTag. When tagNumber is larger than UINT8_MAX and less than or equal to UINT32_MAX, - * the tag is encoded using an implicit profile tag. + * Convert a uint32_t tagNumber (from MEI) to a TLV tag. + * The upper 16 bits of tag_number represent the vendor_id. + * The lower 16 bits of tag_number represent the tag_id. + * When the MEI prefix encodes a standard/scoped source, the tag is encoded using ContextSpecific tag if tag_id is less than or + * equal to UINT8_MAX, and ImplicitProfile tag if tag_id is larger than UINT8_MAX. When the MEI prefix encodes a manufacturer code, + * the tag is encoded using FullyQualified_6Bytes tag, the Vendor ID SHALL be set to the manufacturer code, the profile number set + * to 0 and the tag number set to the MEI suffix. */ -CHIP_ERROR ConvertTlvTag(const uint64_t tagNumber, TLV::Tag & tag); +CHIP_ERROR ConvertTlvTag(uint32_t tagNumber, TLV::Tag & tag); } // namespace chip diff --git a/src/lib/support/jsontlv/TlvToJson.cpp b/src/lib/support/jsontlv/TlvToJson.cpp index 9bafeccf431b2c..3169dbb79faa27 100644 --- a/src/lib/support/jsontlv/TlvToJson.cpp +++ b/src/lib/support/jsontlv/TlvToJson.cpp @@ -108,14 +108,12 @@ struct JsonObjectElementContext { if (TLV::ProfileIdFromTag(tag) == implicitProfileId) { - // Explicit assume implicit tags are just things we want - // 32-bit numbers for str = std::to_string(TLV::TagNumFromTag(tag)); } else { - // UNEXPECTED, create a full 64-bit number here - str = std::to_string(TLV::ProfileIdFromTag(tag)) + "/" + std::to_string(TLV::TagNumFromTag(tag)); + uint32_t tagNumber = (static_cast(TLV::VendorIdFromTag(tag)) << 16) | TLV::TagNumFromTag(tag); + str = std::to_string(tagNumber); } } str = str + ":" + GetJsonElementStrFromType(type); @@ -173,11 +171,8 @@ CHIP_ERROR TlvStructToJson(TLV::TLVReader & reader, Json::Value & jsonObj) TLV::Tag tag = reader.GetTag(); VerifyOrReturnError(TLV::IsContextTag(tag) || TLV::IsProfileTag(tag), CHIP_ERROR_INVALID_TLV_TAG); - // Profile tags are expected to be implicit profile tags and they are - // used to encode > 8bit values from json - if (TLV::IsProfileTag(tag)) + if (TLV::IsProfileTag(tag) && TLV::VendorIdFromTag(tag) == 0) { - VerifyOrReturnError(TLV::ProfileIdFromTag(tag) == reader.ImplicitProfileId, CHIP_ERROR_INVALID_TLV_TAG); VerifyOrReturnError(TLV::TagNumFromTag(tag) > UINT8_MAX, CHIP_ERROR_INVALID_TLV_TAG); } diff --git a/src/lib/support/tests/TestJsonToTlv.cpp b/src/lib/support/tests/TestJsonToTlv.cpp index c6f5df36333238..539d2720caf191 100644 --- a/src/lib/support/tests/TestJsonToTlv.cpp +++ b/src/lib/support/tests/TestJsonToTlv.cpp @@ -300,7 +300,7 @@ void Test32BitConvert(nlTestSuite * inSuite, void * inContext) NL_TEST_ASSERT(inSuite, reader.Next(TLV::AnonymousTag()) == CHIP_NO_ERROR); NL_TEST_ASSERT(inSuite, reader.GetType() == TLV::kTLVType_Structure); NL_TEST_ASSERT(inSuite, reader.EnterContainer(tlvType) == CHIP_NO_ERROR); - NL_TEST_ASSERT(inSuite, reader.Next(TLV::ProfileTag(kImplicitProfileId, 0xFEDCBA98u)) == CHIP_NO_ERROR); + NL_TEST_ASSERT(inSuite, reader.Next(TLV::ProfileTag((4275878552 >> 16) & 0xFFFF, 0, 4275878552 & 0xFFFF)) == CHIP_NO_ERROR); NL_TEST_ASSERT(inSuite, reader.GetType() == TLV::kTLVType_SignedInteger); NL_TEST_ASSERT(inSuite, reader.Get(value) == CHIP_NO_ERROR); NL_TEST_ASSERT(inSuite, value == 321); @@ -312,6 +312,76 @@ void Test32BitConvert(nlTestSuite * inSuite, void * inContext) // FIXME: implement } +void TestMEIConvert(nlTestSuite * inSuite, void * inContext) +{ + TLV::TLVReader reader; + TLV::TLVType tlvType; + int32_t value = 0; + + // Vendor ID = 1, Tag ID = 0 + { + SetupWriters(); + JsonToTlv("{\"65536:INT\": 321}", gWriter1); + NL_TEST_ASSERT(inSuite, gWriter1.Finalize() == CHIP_NO_ERROR); + + reader.Init(gBuf1, gWriter1.GetLengthWritten()); + reader.ImplicitProfileId = kImplicitProfileId; + + NL_TEST_ASSERT(inSuite, reader.Next(TLV::AnonymousTag()) == CHIP_NO_ERROR); + NL_TEST_ASSERT(inSuite, reader.GetType() == TLV::kTLVType_Structure); + NL_TEST_ASSERT(inSuite, reader.EnterContainer(tlvType) == CHIP_NO_ERROR); + NL_TEST_ASSERT(inSuite, reader.Next(TLV::ProfileTag(1, 0, 0)) == CHIP_NO_ERROR); + NL_TEST_ASSERT(inSuite, reader.GetType() == TLV::kTLVType_SignedInteger); + NL_TEST_ASSERT(inSuite, reader.Get(value) == CHIP_NO_ERROR); + NL_TEST_ASSERT(inSuite, value == 321); + NL_TEST_ASSERT(inSuite, reader.Next() == CHIP_END_OF_TLV); + NL_TEST_ASSERT(inSuite, reader.ExitContainer(tlvType) == CHIP_NO_ERROR); + NL_TEST_ASSERT(inSuite, reader.Next() == CHIP_END_OF_TLV); + } + + // Vendor ID = 0xFFFF, Tag ID = 0 + { + SetupWriters(); + JsonToTlv("{\"4294901760:INT\": 123}", gWriter1); + NL_TEST_ASSERT(inSuite, gWriter1.Finalize() == CHIP_NO_ERROR); + + reader.Init(gBuf1, gWriter1.GetLengthWritten()); + reader.ImplicitProfileId = kImplicitProfileId; + + NL_TEST_ASSERT(inSuite, reader.Next(TLV::AnonymousTag()) == CHIP_NO_ERROR); + NL_TEST_ASSERT(inSuite, reader.GetType() == TLV::kTLVType_Structure); + NL_TEST_ASSERT(inSuite, reader.EnterContainer(tlvType) == CHIP_NO_ERROR); + NL_TEST_ASSERT(inSuite, reader.Next(TLV::ProfileTag(0xFFFF, 0, 0)) == CHIP_NO_ERROR); + NL_TEST_ASSERT(inSuite, reader.GetType() == TLV::kTLVType_SignedInteger); + NL_TEST_ASSERT(inSuite, reader.Get(value) == CHIP_NO_ERROR); + NL_TEST_ASSERT(inSuite, value == 123); + NL_TEST_ASSERT(inSuite, reader.Next() == CHIP_END_OF_TLV); + NL_TEST_ASSERT(inSuite, reader.ExitContainer(tlvType) == CHIP_NO_ERROR); + NL_TEST_ASSERT(inSuite, reader.Next() == CHIP_END_OF_TLV); + } + + // Vendor ID = 0xFFFF, Tag ID = 0xFFFF + { + SetupWriters(); + JsonToTlv("{\"4294967295:INT\": 123}", gWriter1); + NL_TEST_ASSERT(inSuite, gWriter1.Finalize() == CHIP_NO_ERROR); + + reader.Init(gBuf1, gWriter1.GetLengthWritten()); + reader.ImplicitProfileId = kImplicitProfileId; + + NL_TEST_ASSERT(inSuite, reader.Next(TLV::AnonymousTag()) == CHIP_NO_ERROR); + NL_TEST_ASSERT(inSuite, reader.GetType() == TLV::kTLVType_Structure); + NL_TEST_ASSERT(inSuite, reader.EnterContainer(tlvType) == CHIP_NO_ERROR); + NL_TEST_ASSERT(inSuite, reader.Next(TLV::ProfileTag(0xFFFF, 0, 0xFFFF)) == CHIP_NO_ERROR); + NL_TEST_ASSERT(inSuite, reader.GetType() == TLV::kTLVType_SignedInteger); + NL_TEST_ASSERT(inSuite, reader.Get(value) == CHIP_NO_ERROR); + NL_TEST_ASSERT(inSuite, value == 123); + NL_TEST_ASSERT(inSuite, reader.Next() == CHIP_END_OF_TLV); + NL_TEST_ASSERT(inSuite, reader.ExitContainer(tlvType) == CHIP_NO_ERROR); + NL_TEST_ASSERT(inSuite, reader.Next() == CHIP_END_OF_TLV); + } +} + int Initialize(void * apSuite) { VerifyOrReturnError(chip::Platform::MemoryInit() == CHIP_NO_ERROR, FAILURE); @@ -329,6 +399,7 @@ const nlTest sTests[] = { NL_TEST_DEF("TestConverter", TestConverter), NL_TEST_DEF("Test32BitConvert", Test32BitConvert), + NL_TEST_DEF("TestMEIConvert", TestMEIConvert), NL_TEST_SENTINEL() }; // clang-format on diff --git a/src/lib/support/tests/TestJsonToTlvToJson.cpp b/src/lib/support/tests/TestJsonToTlvToJson.cpp index b14d84ceed4e03..576203461b5384 100644 --- a/src/lib/support/tests/TestJsonToTlvToJson.cpp +++ b/src/lib/support/tests/TestJsonToTlvToJson.cpp @@ -705,7 +705,8 @@ void TestConverter_Array_Empty_ImplicitProfileTag4(nlTestSuite * inSuite, void * NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, containerType)); NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == - writer.StartContainer(TLV::ProfileTag(kImplicitProfileId, 1000000), TLV::kTLVType_Array, containerType2)); + writer.StartContainer(TLV::ProfileTag((1000000 >> 16) & 0xFFFF, 0, 1000000 & 0xFFFF), TLV::kTLVType_Array, + containerType2)); NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.EndContainer(containerType2)); NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.EndContainer(containerType)); NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Finalize()); @@ -1070,7 +1071,8 @@ void TestConverter_Array_Strings(nlTestSuite * inSuite, void * inContext) NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, containerType)); NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == - writer.StartContainer(TLV::ProfileTag(kImplicitProfileId, 100000), TLV::kTLVType_Array, containerType2)); + writer.StartContainer(TLV::ProfileTag((100000 >> 16) & 0xFFFF, 0, 100000 & 0xFFFF), TLV::kTLVType_Array, + containerType2)); NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.PutString(TLV::AnonymousTag(), "ABC")); NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.PutString(TLV::AnonymousTag(), "Options")); NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.PutString(TLV::AnonymousTag(), "more")); @@ -1202,11 +1204,10 @@ void TestConverter_Struct_MixedTags(nlTestSuite * inSuite, void * inContext) NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, containerType)); NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.StartContainer(TLV::ContextTag(0), TLV::kTLVType_Structure, containerType2)); NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Put(TLV::ContextTag(255), static_cast(42))); + NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Put(TLV::ProfileTag(0x0001u, 0, 0), static_cast(345678))); NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Put(TLV::ProfileTag(kImplicitProfileId, 256), static_cast(17000))); + NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Put(TLV::ProfileTag(0xFFFFu, 0, 0xFFFFu), static_cast(500000000000))); NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Put(TLV::ProfileTag(kImplicitProfileId, 65535), static_cast(1))); - NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Put(TLV::ProfileTag(kImplicitProfileId, 65536), static_cast(345678))); - NL_TEST_ASSERT( - gSuite, CHIP_NO_ERROR == writer.Put(TLV::ProfileTag(kImplicitProfileId, 4294967295), static_cast(500000000000))); NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.EndContainer(containerType2)); NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.EndContainer(containerType)); NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Finalize()); @@ -1706,7 +1707,7 @@ void TestConverter_TlvToJson_ErrorCases(nlTestSuite * inSuite, void * inContext) uint8_t buf9[32]; writer.Init(buf9); NL_TEST_ASSERT(inSuite, CHIP_NO_ERROR == writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, containerType)); - NL_TEST_ASSERT(inSuite, CHIP_NO_ERROR == writer.Put(TLV::ProfileTag(0xAA55FEED, 234), static_cast(42))); + NL_TEST_ASSERT(inSuite, CHIP_NO_ERROR == writer.Put(TLV::ProfileTag(0xFEED, 234), static_cast(42))); NL_TEST_ASSERT(inSuite, CHIP_NO_ERROR == writer.EndContainer(containerType)); NL_TEST_ASSERT(inSuite, CHIP_NO_ERROR == writer.Finalize()); ByteSpan useFullyQualifiedTag(buf9, writer.GetLengthWritten()); @@ -1773,10 +1774,6 @@ void TestConverter_JsonToTlv_ErrorCases(nlTestSuite * inSuite, void * inContext) " \"UINT\" : 42\n" "}\n"; - std::string invalidNameTagValueTooBig = "{\n" - " \"invalid:4294967296:UINT\" : 42\n" - "}\n"; - std::string invalidNameWithNegativeTag = "{\n" " \"-1:UINT\" : 42\n" "}\n"; @@ -1814,7 +1811,6 @@ void TestConverter_JsonToTlv_ErrorCases(nlTestSuite * inSuite, void * inContext) { arrayElementsWithName, CHIP_ERROR_INTERNAL, "Array Elements With Json Name" }, { invalidNameWithoutTagField, CHIP_ERROR_INVALID_ARGUMENT, "Invalid Name String Without Tag Field" }, { invalidNameWithoutTagField2, CHIP_ERROR_INVALID_ARGUMENT, "Invalid Name String Without Tag Field 2" }, - { invalidNameTagValueTooBig, CHIP_ERROR_INVALID_ARGUMENT, "Invalid Name String Tag Value Larger than UINT32_MAX" }, { invalidNameWithNegativeTag, CHIP_ERROR_INVALID_ARGUMENT, "Invalid Name With Negative Tag Value" }, { invalidNameWithInvalidTypeField, CHIP_ERROR_INVALID_ARGUMENT, "Invalid Name With Invalid Type Field" }, { invalidBytesBase64Value1, CHIP_ERROR_INVALID_ARGUMENT, "Invalid Base64 Encoding: Invalid Character" }, @@ -1834,6 +1830,40 @@ void TestConverter_JsonToTlv_ErrorCases(nlTestSuite * inSuite, void * inContext) } } +// Full Qualified Profile tags, Unsigned Integer structure: {65536 = 42, 4294901760 = 17000, 4294967295 = 500000000000} +void TestConverter_Struct_MEITags(nlTestSuite * inSuite, void * inContext) +{ + gSuite = inSuite; + + uint8_t buf[256]; + TLV::TLVWriter writer; + TLV::TLVType containerType; + TLV::TLVType containerType2; + + writer.Init(buf); + writer.ImplicitProfileId = kImplicitProfileId; + + NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, containerType)); + NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.StartContainer(TLV::ContextTag(0), TLV::kTLVType_Structure, containerType2)); + NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Put(TLV::ProfileTag(0xFFFFu, 0, 0), static_cast(17000))); + NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Put(TLV::ProfileTag(0x0001u, 0, 0), static_cast(42))); + NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Put(TLV::ProfileTag(0xFFFFu, 0, 0xFFFFu), static_cast(500000000000))); + NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.EndContainer(containerType2)); + NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.EndContainer(containerType)); + NL_TEST_ASSERT(gSuite, CHIP_NO_ERROR == writer.Finalize()); + + std::string jsonString = "{\n" + " \"0:STRUCT\" : {\n" + " \"65536:UINT\" : 42,\n" + " \"4294901760:UINT\" : 17000,\n" + " \"4294967295:UINT\" : \"500000000000\"\n" + " }\n" + "}\n"; + + ByteSpan tlvSpan(buf, writer.GetLengthWritten()); + CheckValidConversion(jsonString, tlvSpan, jsonString); +} + int Initialize(void * apSuite) { VerifyOrReturnError(chip::Platform::MemoryInit() == CHIP_NO_ERROR, FAILURE); @@ -1899,6 +1929,7 @@ const nlTest sTests[] = { NL_TEST_DEF("Test Json Tlv Converter - Complex Structure from the README File", TestConverter_Structure_FromReadme), NL_TEST_DEF("Test Json Tlv Converter - Tlv to Json Error Cases", TestConverter_TlvToJson_ErrorCases), NL_TEST_DEF("Test Json Tlv Converter - Json To Tlv Error Cases", TestConverter_JsonToTlv_ErrorCases), + NL_TEST_DEF("Test Json Tlv Converter - Structure with MEI Elements", TestConverter_Struct_MEITags), NL_TEST_SENTINEL() }; From 1d429eaba679f73d2ee06ea5c688344dd9048468 Mon Sep 17 00:00:00 2001 From: chrisdecenzo <61757564+chrisdecenzo@users.noreply.github.com> Date: Fri, 23 Feb 2024 13:32:42 -0800 Subject: [PATCH 079/385] TV Android Sample App: Dialogs for new commissioning feedback and message cluster (#32281) * Dialogs for new commissioning feedback and message cluster * Address comments * Restyle TV Android Sample App: Dialogs for new commissioning feedback and message cluster (#32282) * Restyled by whitespace * Restyled by google-java-format --------- Co-authored-by: Restyled.io --------- Co-authored-by: restyled-io[bot] <32688539+restyled-io[bot]@users.noreply.github.com> Co-authored-by: Restyled.io --- .../server/MatterCommissioningPrompter.java | 311 ++++++++++++++---- .../tv-app/android/java/MessagesManager.cpp | 6 +- .../android/java/MyUserPrompter-JNI.cpp | 165 ++++++++-- .../tv-app/android/java/MyUserPrompter-JNI.h | 3 + .../java/MyUserPrompterResolver-JNI.cpp | 35 ++ .../tv/server/tvapp/MessagesManagerStub.java | 19 +- .../matter/tv/server/tvapp/UserPrompter.java | 31 ++ .../tv/server/tvapp/UserPrompterResolver.java | 16 + .../linux/CastingShellCommands.cpp | 7 + .../CommissionerDiscoveryController.cpp | 4 +- 10 files changed, 507 insertions(+), 90 deletions(-) diff --git a/examples/tv-app/android/App/platform-app/src/main/java/com/matter/tv/server/MatterCommissioningPrompter.java b/examples/tv-app/android/App/platform-app/src/main/java/com/matter/tv/server/MatterCommissioningPrompter.java index 29690a408c562f..7879af41158438 100644 --- a/examples/tv-app/android/App/platform-app/src/main/java/com/matter/tv/server/MatterCommissioningPrompter.java +++ b/examples/tv-app/android/App/platform-app/src/main/java/com/matter/tv/server/MatterCommissioningPrompter.java @@ -12,6 +12,7 @@ import androidx.appcompat.app.AlertDialog; import androidx.core.app.NotificationCompat; import com.matter.tv.server.service.MatterServant; +import com.matter.tv.server.tvapp.Message; import com.matter.tv.server.tvapp.UserPrompter; import com.matter.tv.server.tvapp.UserPrompterResolver; @@ -26,6 +27,7 @@ public class MatterCommissioningPrompter extends UserPrompterResolver implements public MatterCommissioningPrompter(Context context) { this.context = context; this.createNotificationChannel(); + setUserPrompter(this); } private Activity getActivity() { @@ -34,7 +36,6 @@ private Activity getActivity() { public void promptForCommissionOkPermission( int vendorId, int productId, String commissioneeName) { - // TODO: find app by vendorId and productId Log.d( TAG, "Received prompt for OK permission vendor id:" @@ -43,28 +44,33 @@ public void promptForCommissionOkPermission( + productId + ". Commissionee: " + commissioneeName); - AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); - - builder - .setMessage(commissioneeName + " is requesting permission to cast to this device, approve?") - .setTitle("Allow access to " + commissioneeName) - .setPositiveButton( - "Ok", - (dialog, which) -> { - OnPromptAccepted(); - }) - .setNegativeButton( - "Cancel", - (dialog, which) -> { - OnPromptDeclined(); - }) - .create() - .show(); + + getActivity() + .runOnUiThread( + () -> { + AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); + builder + .setMessage( + commissioneeName + + " is requesting permission to cast to this device, approve?") + .setTitle("Allow access to " + commissioneeName) + .setPositiveButton( + "Ok", + (dialog, which) -> { + OnPromptAccepted(); + }) + .setNegativeButton( + "Cancel", + (dialog, which) -> { + OnPromptDeclined(); + }) + .create() + .show(); + }); } @Override public void promptForCommissionPinCode(int vendorId, int productId, String commissioneeName) { - // TODO: find app by vendorId and productId Log.d( TAG, "Received prompt for PIN code vendor id:" @@ -73,26 +79,143 @@ public void promptForCommissionPinCode(int vendorId, int productId, String commi + productId + ". Commissionee: " + commissioneeName); - EditText editText = new EditText(getActivity()); - AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); - - builder - .setMessage("Please enter PIN displayed in casting app.") - .setTitle("Allow access to " + commissioneeName) - .setView(editText) - .setPositiveButton( - "Ok", - (dialog, which) -> { - String pinCode = editText.getText().toString(); - OnPinCodeEntered(Integer.parseInt(pinCode)); - }) - .setNegativeButton( - "Cancel", - (dialog, which) -> { - OnPinCodeDeclined(); - }) - .create() - .show(); + + getActivity() + .runOnUiThread( + () -> { + EditText editText = new EditText(getActivity()); + AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); + + builder + .setMessage("Please enter PIN displayed in casting app.") + .setTitle("Allow access to " + commissioneeName) + .setView(editText) + .setPositiveButton( + "Ok", + (dialog, which) -> { + String pinCode = editText.getText().toString(); + OnPinCodeEntered(Integer.parseInt(pinCode)); + }) + .setNegativeButton( + "Cancel", + (dialog, which) -> { + OnPinCodeDeclined(); + }) + .create() + .show(); + }); + } + + public void hidePromptsOnCancel(int vendorId, int productId, String commissioneeName) { + Log.d( + TAG, + "Received Cancel from vendor id:" + + vendorId + + " productId:" + + productId + + ". Commissionee: " + + commissioneeName); + + getActivity() + .runOnUiThread( + () -> { + AlertDialog.Builder abuilder = new AlertDialog.Builder(getActivity()); + abuilder + .setMessage("Cancelled connection to " + commissioneeName) + .setTitle("Connection Cancelled") + .create() + .show(); + + NotificationCompat.Builder builder = + new NotificationCompat.Builder(getActivity(), CHANNEL_ID) + .setSmallIcon(R.drawable.ic_baseline_check_24) + .setContentTitle("Connection Cancelled") + .setContentText("Cancelled connection to " + commissioneeName) + .setPriority(NotificationCompat.PRIORITY_DEFAULT); + + notificationManager.notify(SUCCESS_ID, builder.build()); + }); + } + + public void promptWithCommissionerPasscode( + int vendorId, + int productId, + String commissioneeName, + long passcode, + int pairingHint, + String pairingInstruction) { + Log.d( + TAG, + "Received prompt for Commissioner Passcode:" + + passcode + + " vendor id:" + + vendorId + + " productId:" + + productId + + ". Commissionee: " + + commissioneeName); + + getActivity() + .runOnUiThread( + () -> { + EditText editText = new EditText(getActivity()); + AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); + + builder + .setMessage( + "Please enter " + + passcode + + " in " + + commissioneeName + + " app. " + + pairingInstruction + + " [" + + pairingHint + + "]") + .setTitle("Passcode" + passcode) + .setPositiveButton( + "Ok", + (dialog, which) -> { + OnCommissionerPasscodeOK(); + }) + .setNegativeButton( + "Cancel", + (dialog, which) -> { + OnCommissionerPasscodeCancel(); + }) + .create() + .show(); + }); + } + + public void promptCommissioningStarted(int vendorId, int productId, String commissioneeName) { + Log.d( + TAG, + "Received prompt for started vendor id:" + + vendorId + + " productId:" + + productId + + ". Commissionee: " + + commissioneeName); + getActivity() + .runOnUiThread( + () -> { + AlertDialog.Builder abuilder = new AlertDialog.Builder(getActivity()); + abuilder + .setMessage("Starting connection to " + commissioneeName) + .setTitle("Connection Starting") + .create() + .show(); + + NotificationCompat.Builder builder = + new NotificationCompat.Builder(getActivity(), CHANNEL_ID) + .setSmallIcon(R.drawable.ic_baseline_check_24) + .setContentTitle("Connection Starting") + .setContentText("Starting connection to " + commissioneeName) + .setPriority(NotificationCompat.PRIORITY_DEFAULT); + + notificationManager.notify(SUCCESS_ID, builder.build()); + }); } public void promptCommissioningSucceeded(int vendorId, int productId, String commissioneeName) { @@ -104,35 +227,105 @@ public void promptCommissioningSucceeded(int vendorId, int productId, String com + productId + ". Commissionee: " + commissioneeName); - NotificationCompat.Builder builder = - new NotificationCompat.Builder(getActivity(), CHANNEL_ID) - .setSmallIcon(R.drawable.ic_baseline_check_24) - .setContentTitle("Connection Complete") - .setContentText( - "Success. " - + commissioneeName - + " can now cast to this device. Visit settings to manage access control for casting.") - .setPriority(NotificationCompat.PRIORITY_DEFAULT); - - notificationManager.notify(SUCCESS_ID, builder.build()); + getActivity() + .runOnUiThread( + () -> { + AlertDialog.Builder abuilder = new AlertDialog.Builder(getActivity()); + abuilder + .setMessage( + "Success. " + + commissioneeName + + " can now cast to this device. Visit settings to manage access control for casting.") + .setTitle("Connection Complete") + .create() + .show(); + + NotificationCompat.Builder builder = + new NotificationCompat.Builder(getActivity(), CHANNEL_ID) + .setSmallIcon(R.drawable.ic_baseline_check_24) + .setContentTitle("Connection Complete") + .setContentText( + "Success. " + + commissioneeName + + " can now cast to this device. Visit settings to manage access control for casting.") + .setPriority(NotificationCompat.PRIORITY_DEFAULT); + + notificationManager.notify(SUCCESS_ID, builder.build()); + }); } public void promptCommissioningFailed(String commissioneeName, String error) { Log.d(TAG, "Received prompt for failure Commissionee: " + commissioneeName); - NotificationCompat.Builder builder = - new NotificationCompat.Builder(getActivity(), CHANNEL_ID) - .setSmallIcon(R.drawable.ic_baseline_clear_24) - .setContentTitle("Connection Failed") - .setContentText("Failed. " + commissioneeName + " experienced error: " + error + ".") - .setPriority(NotificationCompat.PRIORITY_DEFAULT); - - notificationManager.notify(FAIL_ID, builder.build()); + getActivity() + .runOnUiThread( + () -> { + AlertDialog.Builder abuilder = new AlertDialog.Builder(getActivity()); + abuilder + .setMessage("Failed. " + commissioneeName + " experienced error: " + error + ".") + .setTitle("Connection Failed") + .create() + .show(); + + NotificationCompat.Builder builder = + new NotificationCompat.Builder(getActivity(), CHANNEL_ID) + .setSmallIcon(R.drawable.ic_baseline_clear_24) + .setContentTitle("Connection Failed") + .setContentText( + "Failed. " + commissioneeName + " experienced error: " + error + ".") + .setPriority(NotificationCompat.PRIORITY_DEFAULT); + + notificationManager.notify(FAIL_ID, builder.build()); + }); + } + + public void promptWithMessage(Message message) { + Log.d(TAG, "Received message prompt for " + message.messageText); + getActivity() + .runOnUiThread( + () -> { + if (message.responseOptions.length != 2) { + AlertDialog.Builder abuilder = new AlertDialog.Builder(getActivity()); + abuilder + .setMessage("" + message.messageId + ":" + message.messageText) + .setTitle("New Message from Test") + .setPositiveButton( + "Ok", + (dialog, which) -> { + OnMessageResponse(message.messageId, 0); // ack + }) + .setNegativeButton( + "Ignore", + (dialog, which) -> { + OnMessageResponse(message.messageId, -1); // ignore + }) + .create() + .show(); + } else { + AlertDialog.Builder abuilder = new AlertDialog.Builder(getActivity()); + abuilder + .setMessage("" + message.messageId + ":" + message.messageText) + .setTitle("New Message from Test") + .setPositiveButton( + message.responseOptions[0].label, + (dialog, which) -> { + OnMessageResponse(message.messageId, message.responseOptions[0].id); + }) + .setNegativeButton( + message.responseOptions[1].label, + (dialog, which) -> { + OnMessageResponse(message.messageId, message.responseOptions[1].id); + }) + .create() + .show(); + } + }); } private void createNotificationChannel() { // Create the NotificationChannel, but only on API 26+ because // the NotificationChannel class is new and not in the support library if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + Log.d(TAG, " ------------- createNotificationChannel"); CharSequence name = "MatterPromptNotificationChannel"; String description = "Matter Channel for sending notifications"; int importance = NotificationManager.IMPORTANCE_DEFAULT; @@ -142,6 +335,8 @@ private void createNotificationChannel() { // or other notification behaviors after this this.notificationManager = getSystemService(context, NotificationManager.class); notificationManager.createNotificationChannel(channel); + } else { + Log.d(TAG, " ------------- NOT createNotificationChannel"); } } } diff --git a/examples/tv-app/android/java/MessagesManager.cpp b/examples/tv-app/android/java/MessagesManager.cpp index dbcb5c5994504b..680c96b3a34807 100644 --- a/examples/tv-app/android/java/MessagesManager.cpp +++ b/examples/tv-app/android/java/MessagesManager.cpp @@ -382,11 +382,11 @@ CHIP_ERROR MessagesManager::HandlePresentMessagesRequest( return CHIP_ERROR_INTERNAL; } - jobject jlong = env->NewObject(longClass, longCtor, response.messageResponseID.Value()); - VerifyOrReturnError(jlong != nullptr, CHIP_ERROR_INCORRECT_STATE, ChipLogError(Zcl, "Could not create Long")); + jobject jlongobj = env->NewObject(longClass, longCtor, static_cast(response.messageResponseID.Value())); + VerifyOrReturnError(jlongobj != nullptr, CHIP_ERROR_INCORRECT_STATE, ChipLogError(Zcl, "Could not create Long")); // add to HashMap - env->CallObjectMethod(joptions, hashMapPut, jlong, jlabel); + env->CallObjectMethod(joptions, hashMapPut, jlongobj, jlabel); if (env->ExceptionCheck()) { ChipLogError(DeviceLayer, "Java exception in MessagesManager::HandlePresentMessagesRequest"); diff --git a/examples/tv-app/android/java/MyUserPrompter-JNI.cpp b/examples/tv-app/android/java/MyUserPrompter-JNI.cpp index 82b06e210d7853..6d586d99c1c67f 100644 --- a/examples/tv-app/android/java/MyUserPrompter-JNI.cpp +++ b/examples/tv-app/android/java/MyUserPrompter-JNI.cpp @@ -51,6 +51,29 @@ JNIMyUserPrompter::JNIMyUserPrompter(jobject provider) env->ExceptionClear(); } + mHidePromptsOnCancelMethod = env->GetMethodID(JNIMyUserPrompterClass, "hidePromptsOnCancel", "(IILjava/lang/String;)V"); + if (mHidePromptsOnCancelMethod == nullptr) + { + ChipLogError(Zcl, "Failed to access JNIMyUserPrompter 'hidePromptsOnCancel' method"); + env->ExceptionClear(); + } + + mPromptWithCommissionerPasscodeMethod = + env->GetMethodID(JNIMyUserPrompterClass, "promptWithCommissionerPasscode", "(IILjava/lang/String;JILjava/lang/String;)V"); + if (mPromptWithCommissionerPasscodeMethod == nullptr) + { + ChipLogError(Zcl, "Failed to access JNIMyUserPrompter 'promptWithCommissionerPasscode' method"); + env->ExceptionClear(); + } + + mPromptCommissioningStartedMethod = + env->GetMethodID(JNIMyUserPrompterClass, "promptCommissioningStarted", "(IILjava/lang/String;)V"); + if (mPromptCommissioningStartedMethod == nullptr) + { + ChipLogError(Zcl, "Failed to access JNIMyUserPrompter 'promptCommissioningStarted' method"); + env->ExceptionClear(); + } + mPromptCommissioningSucceededMethod = env->GetMethodID(JNIMyUserPrompterClass, "promptCommissioningSucceeded", "(IILjava/lang/String;)V"); if (mPromptCommissioningSucceededMethod == nullptr) @@ -81,17 +104,18 @@ void JNIMyUserPrompter::PromptForCommissionOKPermission(uint16_t vendorId, uint1 DeviceLayer::StackUnlock unlock; CHIP_ERROR err = CHIP_NO_ERROR; JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread(); - std::string stringCommissioneeName(commissioneeName); VerifyOrExit(mJNIMyUserPrompterObject.HasValidObjectRef(), err = CHIP_ERROR_INCORRECT_STATE); VerifyOrExit(mPromptForCommissionOKPermissionMethod != nullptr, err = CHIP_ERROR_INCORRECT_STATE); VerifyOrExit(env != nullptr, err = CHIP_JNI_ERROR_NO_ENV); { - UtfString jniCommissioneeName(env, stringCommissioneeName.data()); + jstring jcommissioneeName = env->NewStringUTF(commissioneeName); + VerifyOrExit(jcommissioneeName != nullptr, ChipLogError(Zcl, "Could not create jstring"); err = CHIP_ERROR_INTERNAL); + env->ExceptionClear(); env->CallVoidMethod(mJNIMyUserPrompterObject.ObjectRef(), mPromptForCommissionOKPermissionMethod, - static_cast(vendorId), static_cast(productId), jniCommissioneeName.jniValue()); + static_cast(vendorId), static_cast(productId), jcommissioneeName); if (env->ExceptionCheck()) { ChipLogError(DeviceLayer, "Java exception in PromptForCommissionOKPermission"); @@ -123,17 +147,18 @@ void JNIMyUserPrompter::PromptForCommissionPasscode(uint16_t vendorId, uint16_t DeviceLayer::StackUnlock unlock; CHIP_ERROR err = CHIP_NO_ERROR; JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread(); - std::string stringCommissioneeName(commissioneeName); VerifyOrExit(mJNIMyUserPrompterObject.HasValidObjectRef(), err = CHIP_ERROR_INCORRECT_STATE); VerifyOrExit(mPromptForCommissionPincodeMethod != nullptr, err = CHIP_ERROR_INCORRECT_STATE); VerifyOrExit(env != nullptr, err = CHIP_JNI_ERROR_NO_ENV); { - UtfString jniCommissioneeName(env, stringCommissioneeName.data()); + jstring jcommissioneeName = env->NewStringUTF(commissioneeName); + VerifyOrExit(jcommissioneeName != nullptr, ChipLogError(Zcl, "Could not create jstring"); err = CHIP_ERROR_INTERNAL); + env->ExceptionClear(); env->CallVoidMethod(mJNIMyUserPrompterObject.ObjectRef(), mPromptForCommissionPincodeMethod, static_cast(vendorId), - static_cast(productId), jniCommissioneeName.jniValue()); + static_cast(productId), jcommissioneeName); if (env->ExceptionCheck()) { ChipLogError(Zcl, "Java exception in PromptForCommissionPincode"); @@ -158,8 +183,38 @@ void JNIMyUserPrompter::PromptForCommissionPasscode(uint16_t vendorId, uint16_t */ void JNIMyUserPrompter::HidePromptsOnCancel(uint16_t vendorId, uint16_t productId, const char * commissioneeName) { - // TODO - ChipLogError(Zcl, "JNIMyUserPrompter::HidePromptsOnCancel Needs Implementation"); + ChipLogError(Zcl, "JNIMyUserPrompter::HidePromptsOnCancel"); + + DeviceLayer::StackUnlock unlock; + CHIP_ERROR err = CHIP_NO_ERROR; + JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread(); + + VerifyOrExit(mJNIMyUserPrompterObject.HasValidObjectRef(), err = CHIP_ERROR_INCORRECT_STATE); + VerifyOrExit(mPromptForCommissionOKPermissionMethod != nullptr, err = CHIP_ERROR_INCORRECT_STATE); + VerifyOrExit(env != nullptr, err = CHIP_JNI_ERROR_NO_ENV); + + { + jstring jcommissioneeName = env->NewStringUTF(commissioneeName); + VerifyOrExit(jcommissioneeName != nullptr, ChipLogError(Zcl, "Could not create jstring"); err = CHIP_ERROR_INTERNAL); + + env->ExceptionClear(); + env->CallVoidMethod(mJNIMyUserPrompterObject.ObjectRef(), mHidePromptsOnCancelMethod, static_cast(vendorId), + static_cast(productId), jcommissioneeName); + if (env->ExceptionCheck()) + { + ChipLogError(DeviceLayer, "Java exception in HidePromptsOnCancel"); + env->ExceptionDescribe(); + env->ExceptionClear(); + err = CHIP_ERROR_INCORRECT_STATE; + goto exit; + } + } + +exit: + if (err != CHIP_NO_ERROR) + { + ChipLogError(Zcl, "HidePromptsOnCancel error: %s", err.AsString()); + } } /** @@ -168,7 +223,6 @@ void JNIMyUserPrompter::HidePromptsOnCancel(uint16_t vendorId, uint16_t productI */ bool JNIMyUserPrompter::DisplaysPasscodeAndQRCode() { - // TODO ChipLogError(Zcl, "JNIMyUserPrompter::DisplaysPasscodeAndQRCode Needs Implementation"); return false; } @@ -182,8 +236,42 @@ bool JNIMyUserPrompter::DisplaysPasscodeAndQRCode() void JNIMyUserPrompter::PromptWithCommissionerPasscode(uint16_t vendorId, uint16_t productId, const char * commissioneeName, uint32_t passcode, uint16_t pairingHint, const char * pairingInstruction) { - // TODO - ChipLogError(Zcl, "JNIMyUserPrompter::PromptWithCommissionerPasscode Needs Implementation"); + ChipLogError(Zcl, "JNIMyUserPrompter::PromptWithCommissionerPasscode"); + + DeviceLayer::StackUnlock unlock; + CHIP_ERROR err = CHIP_NO_ERROR; + JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread(); + + VerifyOrExit(mJNIMyUserPrompterObject.HasValidObjectRef(), err = CHIP_ERROR_INCORRECT_STATE); + VerifyOrExit(mPromptForCommissionOKPermissionMethod != nullptr, err = CHIP_ERROR_INCORRECT_STATE); + VerifyOrExit(env != nullptr, err = CHIP_JNI_ERROR_NO_ENV); + + { + jstring jcommissioneeName = env->NewStringUTF(commissioneeName); + VerifyOrExit(jcommissioneeName != nullptr, ChipLogError(Zcl, "Could not create jstring"); err = CHIP_ERROR_INTERNAL); + + jstring jpairingInstruction = env->NewStringUTF(pairingInstruction); + VerifyOrExit(jpairingInstruction != nullptr, ChipLogError(Zcl, "Could not create jstring"); err = CHIP_ERROR_INTERNAL); + + env->ExceptionClear(); + env->CallVoidMethod(mJNIMyUserPrompterObject.ObjectRef(), mPromptWithCommissionerPasscodeMethod, + static_cast(vendorId), static_cast(productId), jcommissioneeName, + static_cast(passcode), static_cast(pairingHint), jpairingInstruction); + if (env->ExceptionCheck()) + { + ChipLogError(DeviceLayer, "Java exception in PromptWithCommissionerPasscode"); + env->ExceptionDescribe(); + env->ExceptionClear(); + err = CHIP_ERROR_INCORRECT_STATE; + goto exit; + } + } + +exit: + if (err != CHIP_NO_ERROR) + { + ChipLogError(Zcl, "PromptWithCommissionerPasscode error: %s", err.AsString()); + } } /** @@ -191,8 +279,38 @@ void JNIMyUserPrompter::PromptWithCommissionerPasscode(uint16_t vendorId, uint16 */ void JNIMyUserPrompter::PromptCommissioningStarted(uint16_t vendorId, uint16_t productId, const char * commissioneeName) { - // TODO - ChipLogError(Zcl, "JNIMyUserPrompter::PromptCommissioningStarted Needs Implementation"); + ChipLogError(Zcl, "JNIMyUserPrompter::PromptCommissioningStarted"); + + DeviceLayer::StackUnlock unlock; + CHIP_ERROR err = CHIP_NO_ERROR; + JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread(); + + VerifyOrExit(mJNIMyUserPrompterObject.HasValidObjectRef(), err = CHIP_ERROR_INCORRECT_STATE); + VerifyOrExit(mPromptForCommissionOKPermissionMethod != nullptr, err = CHIP_ERROR_INCORRECT_STATE); + VerifyOrExit(env != nullptr, err = CHIP_JNI_ERROR_NO_ENV); + + { + jstring jcommissioneeName = env->NewStringUTF(commissioneeName); + VerifyOrExit(jcommissioneeName != nullptr, ChipLogError(Zcl, "Could not create jstring"); err = CHIP_ERROR_INTERNAL); + + env->ExceptionClear(); + env->CallVoidMethod(mJNIMyUserPrompterObject.ObjectRef(), mPromptCommissioningStartedMethod, static_cast(vendorId), + static_cast(productId), jcommissioneeName); + if (env->ExceptionCheck()) + { + ChipLogError(DeviceLayer, "Java exception in PromptCommissioningStarted"); + env->ExceptionDescribe(); + env->ExceptionClear(); + err = CHIP_ERROR_INCORRECT_STATE; + goto exit; + } + } + +exit: + if (err != CHIP_NO_ERROR) + { + ChipLogError(Zcl, "PromptCommissioningStarted error: %s", err.AsString()); + } } /* @@ -203,17 +321,18 @@ void JNIMyUserPrompter::PromptCommissioningSucceeded(uint16_t vendorId, uint16_t DeviceLayer::StackUnlock unlock; CHIP_ERROR err = CHIP_NO_ERROR; JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread(); - std::string stringCommissioneeName(commissioneeName); VerifyOrExit(mJNIMyUserPrompterObject.HasValidObjectRef(), err = CHIP_ERROR_INCORRECT_STATE); VerifyOrExit(mPromptCommissioningSucceededMethod != nullptr, err = CHIP_ERROR_INCORRECT_STATE); VerifyOrExit(env != nullptr, err = CHIP_JNI_ERROR_NO_ENV); { - UtfString jniCommissioneeName(env, stringCommissioneeName.data()); + jstring jcommissioneeName = env->NewStringUTF(commissioneeName); + VerifyOrExit(jcommissioneeName != nullptr, ChipLogError(Zcl, "Could not create jstring"); err = CHIP_ERROR_INTERNAL); + env->ExceptionClear(); env->CallVoidMethod(mJNIMyUserPrompterObject.ObjectRef(), mPromptCommissioningSucceededMethod, static_cast(vendorId), - static_cast(productId), jniCommissioneeName.jniValue()); + static_cast(productId), jcommissioneeName); if (env->ExceptionCheck()) { @@ -240,19 +359,21 @@ void JNIMyUserPrompter::PromptCommissioningFailed(const char * commissioneeName, DeviceLayer::StackUnlock unlock; CHIP_ERROR err = CHIP_NO_ERROR; JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread(); - std::string stringCommissioneeName(commissioneeName); VerifyOrExit(mJNIMyUserPrompterObject.HasValidObjectRef(), err = CHIP_ERROR_INCORRECT_STATE); VerifyOrExit(mPromptCommissioningFailedMethod != nullptr, err = CHIP_ERROR_INCORRECT_STATE); VerifyOrExit(env != nullptr, err = CHIP_JNI_ERROR_NO_ENV); { - std::string stringError(error.AsString()); - UtfString jniCommissioneeName(env, stringCommissioneeName.data()); - UtfString jniCommissioneeError(env, stringError.data()); + jstring jcommissioneeError = env->NewStringUTF(error.AsString()); + VerifyOrExit(jcommissioneeError != nullptr, ChipLogError(Zcl, "Could not create jstring"); err = CHIP_ERROR_INTERNAL); + + jstring jcommissioneeName = env->NewStringUTF(commissioneeName); + VerifyOrExit(jcommissioneeName != nullptr, ChipLogError(Zcl, "Could not create jstring"); err = CHIP_ERROR_INTERNAL); + env->ExceptionClear(); - env->CallVoidMethod(mJNIMyUserPrompterObject.ObjectRef(), mPromptCommissioningFailedMethod, jniCommissioneeName.jniValue(), - jniCommissioneeError.jniValue()); + env->CallVoidMethod(mJNIMyUserPrompterObject.ObjectRef(), mPromptCommissioningFailedMethod, jcommissioneeName, + jcommissioneeError); if (env->ExceptionCheck()) { diff --git a/examples/tv-app/android/java/MyUserPrompter-JNI.h b/examples/tv-app/android/java/MyUserPrompter-JNI.h index 03fb88d2fd7887..408346326a6fd6 100644 --- a/examples/tv-app/android/java/MyUserPrompter-JNI.h +++ b/examples/tv-app/android/java/MyUserPrompter-JNI.h @@ -41,6 +41,9 @@ class JNIMyUserPrompter : public UserPrompter chip::JniGlobalReference mJNIMyUserPrompterObject; jmethodID mPromptForCommissionOKPermissionMethod = nullptr; jmethodID mPromptForCommissionPincodeMethod = nullptr; + jmethodID mHidePromptsOnCancelMethod = nullptr; + jmethodID mPromptWithCommissionerPasscodeMethod = nullptr; + jmethodID mPromptCommissioningStartedMethod = nullptr; jmethodID mPromptCommissioningSucceededMethod = nullptr; jmethodID mPromptCommissioningFailedMethod = nullptr; }; diff --git a/examples/tv-app/android/java/MyUserPrompterResolver-JNI.cpp b/examples/tv-app/android/java/MyUserPrompterResolver-JNI.cpp index 2e6bd0aa1f54e3..94f56f98e49db5 100644 --- a/examples/tv-app/android/java/MyUserPrompterResolver-JNI.cpp +++ b/examples/tv-app/android/java/MyUserPrompterResolver-JNI.cpp @@ -64,3 +64,38 @@ JNI_METHOD(void, OnPromptDeclined)(JNIEnv *, jobject) GetCommissionerDiscoveryController()->Cancel(); #endif } + +JNI_METHOD(void, OnCommissionerPasscodeOK)(JNIEnv *, jobject) +{ +#if CHIP_DEVICE_CONFIG_ENABLE_BOTH_COMMISSIONER_AND_COMMISSIONEE + chip::DeviceLayer::StackLock lock; + ChipLogProgress(Zcl, "OnCommissionerPasscodeOK"); + // GetCommissionerDiscoveryController()->Ok(); +#endif +} + +JNI_METHOD(void, OnCommissionerPasscodeCancel)(JNIEnv *, jobject) +{ +#if CHIP_DEVICE_CONFIG_ENABLE_BOTH_COMMISSIONER_AND_COMMISSIONEE + chip::DeviceLayer::StackLock lock; + ChipLogProgress(Zcl, "OnCommissionerPasscodeCancel"); + GetCommissionerDiscoveryController()->Cancel(); +#endif +} + +JNI_METHOD(void, OnMessageResponse)(JNIEnv * env, jobject, jstring jMessageId, jlong jOptionId) +{ + chip::DeviceLayer::StackLock lock; + uint32_t optionid = static_cast(jOptionId); + ChipLogProgress(Zcl, "OnMessageResponse option id: %u", optionid); + + JniUtfString messageId(env, jMessageId); + if (jMessageId != nullptr) + { + ChipLogProgress(Zcl, "OnMessageResponse message id: %s", messageId.c_str()); + } + else + { + ChipLogProgress(Zcl, "OnMessageResponse message id null"); + } +} diff --git a/examples/tv-app/android/java/src/com/matter/tv/server/tvapp/MessagesManagerStub.java b/examples/tv-app/android/java/src/com/matter/tv/server/tvapp/MessagesManagerStub.java index 55d94209197559..054218a78c6a54 100644 --- a/examples/tv-app/android/java/src/com/matter/tv/server/tvapp/MessagesManagerStub.java +++ b/examples/tv-app/android/java/src/com/matter/tv/server/tvapp/MessagesManagerStub.java @@ -61,15 +61,24 @@ public boolean presentMessages( int i = 0; for (Map.Entry set : responseOptions.entrySet()) { - Log.d(TAG, "presentMessages option: key:" + set.getKey() + " value:" + set.getValue()); + Log.d( + TAG, + "presentMessages option: key:" + set.getKey().longValue() + " value:" + set.getValue()); options[i] = new MessageResponseOption(set.getKey().longValue(), set.getValue()); i++; } - messages.put( - messageId, - new Message( - messageId, priority, messageControl, startTime, duration, messageText, options)); + Message message = + new Message(messageId, priority, messageControl, startTime, duration, messageText, options); + messages.put(messageId, message); + + UserPrompter prompter = UserPrompterResolver.getUserPrompter(); + if (prompter != null) { + prompter.promptWithMessage(message); + } else { + Log.d(TAG, "presentMessages no global user prompter"); + } + return true; } diff --git a/examples/tv-app/android/java/src/com/matter/tv/server/tvapp/UserPrompter.java b/examples/tv-app/android/java/src/com/matter/tv/server/tvapp/UserPrompter.java index d0aeb5c97df412..dc6fb34ba61261 100644 --- a/examples/tv-app/android/java/src/com/matter/tv/server/tvapp/UserPrompter.java +++ b/examples/tv-app/android/java/src/com/matter/tv/server/tvapp/UserPrompter.java @@ -39,6 +39,32 @@ public interface UserPrompter { */ void promptForCommissionPinCode(int vendorId, int productId, String commissioneeName); + /** + * Called to when CancelCommissioning is received via UDC. Indicates that commissioner can stop + * showing the passcode entry or display dialog. For example, can show text such as "Commissioning + * cancelled by client" before hiding dialog. + */ + void hidePromptsOnCancel(int vendorId, int productId, String commissioneeName); + + /** + * Called to display the given setup passcode to the user, for commissioning the given + * commissioneeName with the given vendorId and productId, and provide instructions for where to + * enter it in the commissionee (when pairingHint and pairingInstruction are provided). For + * example "Casting Passcode: [passcode]. For more instructions, click here." + */ + void promptWithCommissionerPasscode( + int vendorId, + int productId, + String commissioneeName, + long passcode, + int pairingHint, + String pairingInstruction); + + /* + * Called to notify the user that commissioning succeeded. It can be in form of UI Notification. + */ + void promptCommissioningStarted(int vendorId, int productId, String commissioneeName); + /* * Called to notify the user that commissioning succeeded. It can be in form of UI Notification. */ @@ -48,4 +74,9 @@ public interface UserPrompter { * Called to notify the user that commissioning succeeded. It can be in form of UI Notification. */ void promptCommissioningFailed(String commissioneeName, String error); + + /* + * Called to display a message on the screen + */ + void promptWithMessage(Message message); } diff --git a/examples/tv-app/android/java/src/com/matter/tv/server/tvapp/UserPrompterResolver.java b/examples/tv-app/android/java/src/com/matter/tv/server/tvapp/UserPrompterResolver.java index f90c18aba1648a..4d81173aca6f9d 100644 --- a/examples/tv-app/android/java/src/com/matter/tv/server/tvapp/UserPrompterResolver.java +++ b/examples/tv-app/android/java/src/com/matter/tv/server/tvapp/UserPrompterResolver.java @@ -29,7 +29,23 @@ public class UserPrompterResolver { public native void OnPromptDeclined(); + public native void OnCommissionerPasscodeOK(); + + public native void OnCommissionerPasscodeCancel(); + + public native void OnMessageResponse(String messageId, long optionid); + static { System.loadLibrary("TvApp"); } + + static UserPrompter globalPrompter = null; + + public static void setUserPrompter(UserPrompter prompter) { + globalPrompter = prompter; + } + + public static UserPrompter getUserPrompter() { + return globalPrompter; + } } diff --git a/examples/tv-casting-app/linux/CastingShellCommands.cpp b/examples/tv-casting-app/linux/CastingShellCommands.cpp index f6b245b42dc13a..bf20ccdec73b7f 100644 --- a/examples/tv-casting-app/linux/CastingShellCommands.cpp +++ b/examples/tv-casting-app/linux/CastingShellCommands.cpp @@ -192,6 +192,13 @@ static CHIP_ERROR CastingHandler(int argc, char ** argv) { id.SetPairingInst(argv[5]); } + if (argc > 6) + { + uint16_t vid = (uint16_t) strtol(argv[6], &eptr, 10); + Protocols::UserDirectedCommissioning::TargetAppInfo info; + info.vendorId = vid; + id.AddTargetAppInfo(info); + } return Server::GetInstance().SendUserDirectedCommissioningRequest(chip::Transport::PeerAddress::UDP(commissioner, port), id); } diff --git a/src/controller/CommissionerDiscoveryController.cpp b/src/controller/CommissionerDiscoveryController.cpp index c1c6492636ecd0..86849a32f91271 100644 --- a/src/controller/CommissionerDiscoveryController.cpp +++ b/src/controller/CommissionerDiscoveryController.cpp @@ -47,7 +47,7 @@ void CommissionerDiscoveryController::OnUserDirectedCommissioningRequest(UDCClie { if (!mReady) { - ChipLogDetail(Controller, "CommissionerDiscoveryController not read. Current instance=%s", mCurrentInstance); + ChipLogDetail(Controller, "CommissionerDiscoveryController not ready. Current instance=%s", mCurrentInstance); return; } // first check if this is a cancel @@ -163,7 +163,7 @@ void CommissionerDiscoveryController::Ok() } } // handle NoAppsFound CDC case - if (!hasTargetApp) + if (!hasTargetApp && client->GetNoPasscode()) { ChipLogError(AppServer, "UX Ok: target apps specified but none found, sending CDC"); CommissionerDeclaration cd; From 22bb7373669171c47374e85729da3bda465ca0c0 Mon Sep 17 00:00:00 2001 From: Robert Szewczyk Date: Fri, 23 Feb 2024 14:15:47 -0800 Subject: [PATCH 080/385] Fix a a few gaps in jumping between Java and C++ for Messages cluster (#32295) Fix dangling problems arising from uint16 seconds for duration to uint64_t milliseconds --- examples/tv-app/android/java/MessagesManager.cpp | 4 ++-- .../src/com/matter/tv/server/tvapp/MessagesManagerStub.java | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/tv-app/android/java/MessagesManager.cpp b/examples/tv-app/android/java/MessagesManager.cpp index 680c96b3a34807..ad214e117d33d8 100644 --- a/examples/tv-app/android/java/MessagesManager.cpp +++ b/examples/tv-app/android/java/MessagesManager.cpp @@ -74,7 +74,7 @@ void MessagesManager::InitializeWithObjects(jobject managerObject) } mPresentMessagesMethod = - env->GetMethodID(managerClass, "presentMessages", "(Ljava/lang/String;IIJILjava/lang/String;Ljava/util/HashMap;)Z"); + env->GetMethodID(managerClass, "presentMessages", "(Ljava/lang/String;IIJJLjava/lang/String;Ljava/util/HashMap;)Z"); if (mPresentMessagesMethod == nullptr) { ChipLogError(Zcl, "Failed to access MessagesManager 'presentMessages' method"); @@ -182,7 +182,7 @@ CHIP_ERROR MessagesManager::HandleGetMessages(AttributeValueEncoder & aEncoder) message.startTime = DataModel::Nullable(static_cast(jstartTime)); } - jfieldID durationField = env->GetFieldID(messageClass, "duration", "I"); + jfieldID durationField = env->GetFieldID(messageClass, "duration", "J"); jlong jduration = env->GetLongField(messageObject, durationField); if (jduration >= 0) { diff --git a/examples/tv-app/android/java/src/com/matter/tv/server/tvapp/MessagesManagerStub.java b/examples/tv-app/android/java/src/com/matter/tv/server/tvapp/MessagesManagerStub.java index 054218a78c6a54..b31f14a112304b 100644 --- a/examples/tv-app/android/java/src/com/matter/tv/server/tvapp/MessagesManagerStub.java +++ b/examples/tv-app/android/java/src/com/matter/tv/server/tvapp/MessagesManagerStub.java @@ -36,7 +36,7 @@ public MessagesManagerStub(int endpoint) { responseOptions.put(new Long(1), "Yes"); responseOptions.put(new Long(2), "No"); presentMessages( - "31323334353637383930313233343536", 1, 1, 30, 60, "TestMessage", responseOptions); + "31323334353637383930313233343536", 1, 1, 30, 60000, "TestMessage", responseOptions); Log.d(TAG, "MessagesManagerStub: added dummy message"); } From c5a07207ea37df369e3685bb9c67fc5b9a87b732 Mon Sep 17 00:00:00 2001 From: C Freeman Date: Fri, 23 Feb 2024 23:25:50 -0500 Subject: [PATCH 081/385] DM XMLs: Remove some in-progress that are not going to cert. (#32294) Removing LIT-icd, aliro, per device credentials --- data_model/clusters/DoorLock.xml | 181 +----------------- data_model/clusters/ICDManagement.xml | 38 +--- .../clusters/NetworkCommissioningCluster.xml | 80 +------- 3 files changed, 13 insertions(+), 286 deletions(-) diff --git a/data_model/clusters/DoorLock.xml b/data_model/clusters/DoorLock.xml index 6284b973eb63e1..16d26420fe2009 100644 --- a/data_model/clusters/DoorLock.xml +++ b/data_model/clusters/DoorLock.xml @@ -57,7 +57,7 @@ Davis, CA 95616, USA :xrefstyle: basic --> - + @@ -66,7 +66,6 @@ Davis, CA 95616, USA - @@ -104,19 +103,14 @@ Davis, CA 95616, USA
- - - - - - - - - - - - - + + + + + + + + @@ -130,14 +124,6 @@ Davis, CA 95616, USA - - - - - - - -
@@ -220,23 +206,6 @@ Davis, CA 95616, USA - - - - - - - - - - - - - - - @@ -370,21 +339,6 @@ Davis, CA 95616, USA - - - - - - - - - - - - - - - @@ -533,11 +487,6 @@ Davis, CA 95616, USA - - - - - @@ -1109,81 +1058,6 @@ Davis, CA 95616, USA - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -2059,13 +1933,6 @@ Davis, CA 95616, USA - - - - - - - @@ -2092,36 +1959,6 @@ Davis, CA 95616, USA - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/data_model/clusters/ICDManagement.xml b/data_model/clusters/ICDManagement.xml index 2a770a4f97f2b4..2de6842d1e0dd9 100644 --- a/data_model/clusters/ICDManagement.xml +++ b/data_model/clusters/ICDManagement.xml @@ -57,10 +57,9 @@ Davis, CA 95616, USA // Update Name --> - + - @@ -69,26 +68,12 @@ Davis, CA 95616, USA - - - - - - - - - - - + - - - - @@ -153,25 +138,6 @@ Davis, CA 95616, USA - - - - - - - - - - - - - - - - - - - diff --git a/data_model/clusters/NetworkCommissioningCluster.xml b/data_model/clusters/NetworkCommissioningCluster.xml index 86c7a01ce9f951..745a659f1b900b 100644 --- a/data_model/clusters/NetworkCommissioningCluster.xml +++ b/data_model/clusters/NetworkCommissioningCluster.xml @@ -59,8 +59,7 @@ Davis, CA 95616, USA - + @@ -76,11 +75,6 @@ Added support for Wi-Fi Per-Device Credentials (PDC feature; QueryIdentity and Q - - - - - @@ -177,9 +171,6 @@ Added support for Wi-Fi Per-Device Credentials (PDC feature; QueryIdentity and Q - - - @@ -189,22 +180,6 @@ Added support for Wi-Fi Per-Device Credentials (PDC feature; QueryIdentity and Q - - - - - - - - - - - - - - - - @@ -431,18 +406,6 @@ Added support for Wi-Fi Per-Device Credentials (PDC feature; QueryIdentity and Q - - - - - - - - - - - - @@ -492,18 +455,6 @@ Added support for Wi-Fi Per-Device Credentials (PDC feature; QueryIdentity and Q - - - - - - - - - - - - @@ -559,32 +510,5 @@ Added support for Wi-Fi Per-Device Credentials (PDC feature; QueryIdentity and Q - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file From 8f2a4d227839637d7b3244c4d865542a0f443a66 Mon Sep 17 00:00:00 2001 From: Anush Nadathur Date: Mon, 26 Feb 2024 03:48:13 +0530 Subject: [PATCH 082/385] Framework for emitting metrics data (#32223) * Rerouted tracing macros to Darwin signposts * Initial framework for logging scalar data event * Handled the new metrics event changes in collector * Modified VerifyOrExit macro to accept an optional metric key as third argument * Removed direct use of chrono in metrics_event.h Switched MTRMetrics to vend dictionary for metric keys * Modified SuccessOrExit to optionally accept metric key * Moved metric keys to separate header Reworked metric_event names for more clarity * Switched MATTER_TRACE_METRIC usage to MATTER_LOG_METRIC * Restyle fixes * Fixed unit tests * Fixed build failure due to MetricEvent hidden inside tracing enabled * Fixing one source of build error * Fixing darwin build failure * Code Review: Rename LogMetric to LogMetricEvent * Code Review Suggestions: 1. Metric Macros take full string constants and no longer use preprocessor to prefix. Allows free flowing strings 2. Reworked MetricEvent class and documented 3. Handled LogEventMetric for Darwin, ESP32, Perfetto, JSON to account for all types 4. Removed timePoint from MetricEvent class. Timestamps and duration calculation is now responsibility for the handlers of the event 5. Reverted BUILD.gn in system to not break out SystemClock.h * Code Review Feedback #2: 1. Added SuccessOrExitWithMetric and VerifyOrExitWithMetric 2. Cleaned up support .gn to remove dependedency on metrics * Code Review Feedback #3: 1. Added ScopedMetricEvent to use RAII to track begin and end within a scope * Code Review #4: Reverted an accidental removal * Added MTRMetricData to description as per review comment * Restyler fixes * Sample code of how Begin and End log metrics can be used * Fixed compilation error when tracing is disabled * Fixes for build failures when tracing is disabled * Picked up code review suggestion accidently dropped * Code Review Feedback: 1. Begin metric does not take value 2. Allow undefined value for metric 3. Misc other feedback * Handle undefined value and error value * Revert a comment change * Review Feedback: Changed ScopedMetricEvent to capture error by reference * Fixed another build failure * Reverting usage of LOG_METRICS * Review feedback: Fix incorrect documentation * Code Review Feedback: Remove access to Value in MetricEvent to avoid incorrect access * Restyler fixes * Unregistering backend in Darwin shutdown * Resytler fixes... --- .../wifi-network-diagnostics-server.cpp | 3 +- .../CHIP/MTRDeviceControllerDelegateBridge.mm | 14 +- .../CHIP/MTRDeviceControllerFactory.mm | 7 + src/darwin/Framework/CHIP/MTRFramework.mm | 4 + src/darwin/Framework/CHIP/MTRMetrics.h | 16 +- src/darwin/Framework/CHIP/MTRMetrics.mm | 10 +- .../Framework/CHIP/MTRMetricsCollector.h | 59 ++++ .../Framework/CHIP/MTRMetricsCollector.mm | 256 ++++++++++++++++++ .../Framework/CHIP/MTRMetrics_Internal.h | 22 +- .../Framework/CHIPTests/MTRMetricsTests.m | 12 +- .../Matter.xcodeproj/project.pbxproj | 10 + src/lib/support/CodeUtils.h | 8 +- src/platform/Darwin/BUILD.gn | 13 + src/platform/Darwin/Tracing.h | 77 ++++++ src/platform/Darwin/Tracing.mm | 55 ++++ src/tracing/BUILD.gn | 4 + src/tracing/backend.h | 2 +- src/tracing/darwin/BUILD.gn | 25 ++ .../include/matter/tracing/macros_impl.h | 25 ++ src/tracing/esp32_trace/esp32_tracing.cpp | 33 ++- src/tracing/esp32_trace/esp32_tracing.h | 2 +- .../include/matter/tracing/macros_impl.h | 1 - src/tracing/json/json_tracing.cpp | 27 +- src/tracing/json/json_tracing.h | 2 +- src/tracing/log_declares.h | 1 + src/tracing/macros.h | 5 - src/tracing/metric_event.h | 189 +++++++++++++ src/tracing/metric_keys.h | 44 +++ src/tracing/metric_macros.h | 243 +++++++++++++++++ .../include/matter/tracing/macros_impl.h | 1 - .../none/include/matter/tracing/macros_impl.h | 1 - .../include/matter/tracing/macros_impl.h | 2 - src/tracing/perfetto/perfetto_tracing.cpp | 24 ++ src/tracing/perfetto/perfetto_tracing.h | 1 + src/tracing/registry.cpp | 16 +- src/tracing/registry.h | 2 +- src/tracing/tracing_args.gni | 5 +- 37 files changed, 1167 insertions(+), 54 deletions(-) create mode 100644 src/darwin/Framework/CHIP/MTRMetricsCollector.h create mode 100644 src/darwin/Framework/CHIP/MTRMetricsCollector.mm create mode 100644 src/platform/Darwin/Tracing.h create mode 100644 src/platform/Darwin/Tracing.mm create mode 100644 src/tracing/darwin/BUILD.gn create mode 100644 src/tracing/darwin/include/matter/tracing/macros_impl.h create mode 100644 src/tracing/metric_event.h create mode 100644 src/tracing/metric_keys.h create mode 100644 src/tracing/metric_macros.h diff --git a/src/app/clusters/wifi-network-diagnostics-server/wifi-network-diagnostics-server.cpp b/src/app/clusters/wifi-network-diagnostics-server/wifi-network-diagnostics-server.cpp index f116def50c089a..3cf9239ddff59e 100644 --- a/src/app/clusters/wifi-network-diagnostics-server/wifi-network-diagnostics-server.cpp +++ b/src/app/clusters/wifi-network-diagnostics-server/wifi-network-diagnostics-server.cpp @@ -28,6 +28,7 @@ #include #include #include +#include using namespace chip; using namespace chip::app; @@ -163,7 +164,7 @@ CHIP_ERROR WiFiDiagosticsAttrAccess::ReadWiFiRssi(AttributeValueEncoder & aEncod { rssi.SetNonNull(value); ChipLogProgress(Zcl, "The current RSSI of the Node’s Wi-Fi radio in dB: %d", value); - MATTER_TRACE_METRIC("wifi_rssi", value); + MATTER_LOG_METRIC(chip::Tracing::kMetricWiFiRSSI, value); } else { diff --git a/src/darwin/Framework/CHIP/MTRDeviceControllerDelegateBridge.mm b/src/darwin/Framework/CHIP/MTRDeviceControllerDelegateBridge.mm index e1c49031e3abb2..04ac68a6dae1fe 100644 --- a/src/darwin/Framework/CHIP/MTRDeviceControllerDelegateBridge.mm +++ b/src/darwin/Framework/CHIP/MTRDeviceControllerDelegateBridge.mm @@ -17,9 +17,10 @@ #import "MTRDeviceControllerDelegateBridge.h" #import "MTRDeviceController.h" +#import "MTRDeviceController_Internal.h" #import "MTRError_Internal.h" #import "MTRLogging_Internal.h" -#import "MTRMetrics_Internal.h" +#import "MTRMetricsCollector.h" MTRDeviceControllerDelegateBridge::MTRDeviceControllerDelegateBridge(void) : mDelegate(nil) @@ -130,15 +131,10 @@ nodeID = @(nodeId); } + // If the client implements the metrics delegate, prefer that over others if ([strongDelegate respondsToSelector:@selector(controller:commissioningComplete:nodeID:metrics:)]) { - MTRMetrics * metrics = [MTRMetrics new]; - - if (nsError) { - [metrics setValue:nsError forKey:MTRMetricCommissioningStatusKey]; - } else { - auto * error = [NSError errorWithDomain:MTRErrorDomain code:0 userInfo:nil]; - [metrics setValue:error forKey:MTRMetricCommissioningStatusKey]; - } + // Create a snapshot and clear for next operation + MTRMetrics * metrics = [[MTRMetricsCollector sharedInstance] metricSnapshot:TRUE]; [strongDelegate controller:strongController commissioningComplete:nsError nodeID:nodeID metrics:metrics]; } else { [strongDelegate controller:strongController commissioningComplete:nsError nodeID:nodeID]; diff --git a/src/darwin/Framework/CHIP/MTRDeviceControllerFactory.mm b/src/darwin/Framework/CHIP/MTRDeviceControllerFactory.mm index 0430558e8a4b32..d89df5a4b09c4d 100644 --- a/src/darwin/Framework/CHIP/MTRDeviceControllerFactory.mm +++ b/src/darwin/Framework/CHIP/MTRDeviceControllerFactory.mm @@ -39,6 +39,7 @@ #import "MTRFabricInfo_Internal.h" #import "MTRFramework.h" #import "MTRLogging_Internal.h" +#import "MTRMetricsCollector.h" #import "MTROTAProviderDelegateBridge.h" #import "MTROperationalBrowser.h" #import "MTRP256KeypairBridge.h" @@ -349,6 +350,8 @@ - (void)cleanupStartupObjects } _diagnosticLogsDownloader = nil; + + ShutdownMetricsCollection(); } - (CHIP_ERROR)_initFabricTable:(FabricTable &)fabricTable @@ -414,6 +417,10 @@ - (BOOL)startControllerFactory:(MTRDeviceControllerFactoryParams *)startupParams return YES; } + // Register any tracing backends. This has to be done before starting the event loop to run registering + // the tracing backend in the right queue context + StartupMetricsCollection(); + DeviceLayer::PlatformMgrImpl().StartEventLoopTask(); __block CHIP_ERROR errorCode = CHIP_NO_ERROR; diff --git a/src/darwin/Framework/CHIP/MTRFramework.mm b/src/darwin/Framework/CHIP/MTRFramework.mm index e6a0e672955be3..3eff8a1b8dbfc3 100644 --- a/src/darwin/Framework/CHIP/MTRFramework.mm +++ b/src/darwin/Framework/CHIP/MTRFramework.mm @@ -15,6 +15,7 @@ */ #import "MTRFramework.h" +#import "MTRMetricsCollector.h" #include #include @@ -34,5 +35,8 @@ void MTRFrameworkInit() // Suppress CHIP logging until we actually need it for redirection // (see MTRSetLogCallback()). Logging to os_log is always enabled. chip::Logging::SetLogFilter(chip::Logging::kLogCategory_None); + + // Startup metrics collection and tracing framework + StartupMetricsCollection(); }); } diff --git a/src/darwin/Framework/CHIP/MTRMetrics.h b/src/darwin/Framework/CHIP/MTRMetrics.h index 81161ee049bedd..483de01df3ebd6 100644 --- a/src/darwin/Framework/CHIP/MTRMetrics.h +++ b/src/darwin/Framework/CHIP/MTRMetrics.h @@ -21,14 +21,28 @@ NS_ASSUME_NONNULL_BEGIN /** - * A representation of metrics data for an operation. + * A representation of a collection of metrics data for an operation. */ MTR_NEWLY_AVAILABLE @interface MTRMetrics : NSObject +- (instancetype)init NS_UNAVAILABLE; ++ (instancetype)new NS_UNAVAILABLE; + +/** + * @brief Returns the names of all the metrics data items collected. + */ @property (nonatomic, readonly, copy) NSArray * allKeys; +/** + * @brief Returns metric object corresponding to the metric identified by its key + * + * @param [in] key Name of the metric + * + * @return An object containing the metric data, nil if key is invalid + */ - (nullable id)valueForKey:(NSString *)key; @end + NS_ASSUME_NONNULL_END diff --git a/src/darwin/Framework/CHIP/MTRMetrics.mm b/src/darwin/Framework/CHIP/MTRMetrics.mm index c1135c1cfbc0b6..8c338b70285e08 100644 --- a/src/darwin/Framework/CHIP/MTRMetrics.mm +++ b/src/darwin/Framework/CHIP/MTRMetrics.mm @@ -16,16 +16,24 @@ */ #import "MTRLogging_Internal.h" #import "MTRMetrics_Internal.h" +#include #import +#include @implementation MTRMetrics { NSMutableDictionary * _metricsData; } - (instancetype)init +{ + NSAssert(false, @"'init' unavailable, use initWithCapacity: instead"); + return nil; +} + +- (instancetype)initWithCapacity:(NSUInteger)numItems { if (self = [super init]) { - _metricsData = [NSMutableDictionary dictionary]; + _metricsData = [NSMutableDictionary dictionaryWithCapacity:numItems]; } return self; } diff --git a/src/darwin/Framework/CHIP/MTRMetricsCollector.h b/src/darwin/Framework/CHIP/MTRMetricsCollector.h new file mode 100644 index 00000000000000..71d0afc26c039a --- /dev/null +++ b/src/darwin/Framework/CHIP/MTRMetricsCollector.h @@ -0,0 +1,59 @@ +/** + * + * Copyright (c) 2024 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#import + +NS_ASSUME_NONNULL_BEGIN + +/** + * This function initializes any backend required to collect metrics data. + */ +void StartupMetricsCollection(); + +/** + * This function shuts down any backend created to collect metrics data. + */ +void ShutdownMetricsCollection(); + +/** + * A representation of metrics data for an operation. + */ +@interface MTRMetricsCollector : NSObject + +- (instancetype)init NS_UNAVAILABLE; ++ (instancetype)new NS_UNAVAILABLE; + +/** + * Return the singleton MTRMetricsCollector to vend MTRMetrics snapshots + */ ++ (instancetype)sharedInstance; + +/** + * @brief This method creates a snapshot of the metrics collected until the current point in time + * and returns an object with the stats. + * + * @param [in] resetCollection Boolean that specifies whether or not to clear the stats collected after + * creating the snapshot. + * + * @return MTRMetric object representing the metric data. + */ +- (MTRMetrics *)metricSnapshot:(BOOL)resetCollection; + +@end + +NS_ASSUME_NONNULL_END diff --git a/src/darwin/Framework/CHIP/MTRMetricsCollector.mm b/src/darwin/Framework/CHIP/MTRMetricsCollector.mm new file mode 100644 index 00000000000000..6387738a7c13c8 --- /dev/null +++ b/src/darwin/Framework/CHIP/MTRMetricsCollector.mm @@ -0,0 +1,256 @@ +/** + * + * Copyright (c) 2024 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "MTRMetricsCollector.h" +#import "MTRLogging_Internal.h" +#include "MTRMetrics_Internal.h" +#import +#include +#include +#include +#include + +using MetricEvent = chip::Tracing::MetricEvent; + +static NSString * kMTRMetricDataValueKey = @"value"; +static NSString * kMTRMetricDataTimepointKey = @"time_point"; +static NSString * kMTRMetricDataDurationKey = @"duration_us"; + +@implementation MTRMetricsData { + chip::System::Clock::Microseconds64 _timePoint; + chip::System::Clock::Microseconds64 _duration; +} + +- (instancetype)initWithMetricEvent:(const MetricEvent &)event +{ + if (!(self = [super init])) { + return nil; + } + + using ValueType = MetricEvent::Value::Type; + switch (event.ValueType()) { + case ValueType::kInt32: + _value = [NSNumber numberWithInteger:event.ValueInt32()]; + break; + case ValueType::kUInt32: + _value = [NSNumber numberWithInteger:event.ValueUInt32()]; + break; + case ValueType::kChipErrorCode: + _value = [NSNumber numberWithInteger:event.ValueErrorCode()]; + break; + case ValueType::kUndefined: + default: + _value = nil; + } + + _timePoint = chip::System::SystemClock().GetMonotonicMicroseconds64(); + _duration = chip::System::Clock::Microseconds64(0); + return self; +} + +- (void)setDurationFromMetricData:(MTRMetricsData *)fromData +{ + _duration = _timePoint - fromData->_timePoint; +} + +- (NSNumber *)timePointMicroseconds +{ + return [NSNumber numberWithUnsignedLongLong:_timePoint.count()]; +} + +- (NSNumber *)durationMicroseconds +{ + return [NSNumber numberWithUnsignedLongLong:_duration.count()]; +} + +- (NSString *)description +{ + return [NSString stringWithFormat:@"MTRMetricsData: Value = %@, TimePoint = %@, Duration = %@ us", self.value, self.timePointMicroseconds, self.durationMicroseconds]; +} + +- (NSDictionary *)toDictionary +{ + NSMutableDictionary * dictRepresentation = [NSMutableDictionary dictionary]; + if (self.value) { + [dictRepresentation setValue:self.value forKey:kMTRMetricDataValueKey]; + } + if (auto tmPt = self.timePointMicroseconds) { + [dictRepresentation setValue:tmPt forKey:kMTRMetricDataTimepointKey]; + } + if (auto duration = self.durationMicroseconds) { + [dictRepresentation setValue:duration forKey:kMTRMetricDataDurationKey]; + } + return dictRepresentation; +} + +@end + +@interface MTRMetricsCollector () + +- (void)registerTracingBackend; + +- (void)unregisterTracingBackend; + +@end + +void StartupMetricsCollection() +{ + if ([MTRMetricsCollector sharedInstance]) { + MTR_LOG_INFO("Initialized metrics collection backend for Darwin"); + + [[MTRMetricsCollector sharedInstance] registerTracingBackend]; + } +} + +void ShutdownMetricsCollection() +{ + [[MTRMetricsCollector sharedInstance] unregisterTracingBackend]; +} + +@implementation MTRMetricsCollector { + os_unfair_lock _lock; + NSMutableDictionary * _metricsDataCollection; + chip::Tracing::signposts::DarwinTracingBackend _tracingBackend; +} + ++ (instancetype)sharedInstance +{ + static MTRMetricsCollector * singleton = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + // Initialize the singleton and register the event handler + singleton = [[MTRMetricsCollector alloc] init]; + if (singleton) { + singleton->_tracingBackend.SetMetricEventHandler(^(MetricEvent event) { + if (singleton) { + [singleton handleMetricEvent:event]; + } + }); + } + }); + return singleton; +} + +- (instancetype)init +{ + if (!(self = [super init])) { + return nil; + } + _lock = OS_UNFAIR_LOCK_INIT; + _metricsDataCollection = [NSMutableDictionary dictionary]; + return self; +} + +- (void)registerTracingBackend +{ + std::lock_guard lock(_lock); + chip::Tracing::Register(_tracingBackend); + MTR_LOG_INFO("Registered tracing backend with the registry"); +} + +- (void)unregisterTracingBackend +{ + std::lock_guard lock(_lock); + chip::Tracing::Unregister(_tracingBackend); + MTR_LOG_INFO("Unregistered tracing backend with the registry"); +} + +static inline NSString * suffixNameForMetricType(MetricEvent::Type type) +{ + switch (type) { + case MetricEvent::Type::kBeginEvent: + return @"-begin"; + case MetricEvent::Type::kEndEvent: + return @"-end"; + case MetricEvent::Type::kInstantEvent: + return @"-instant"; + } +} + +static inline NSString * suffixNameForMetric(const MetricEvent & event) +{ + return suffixNameForMetricType(event.type()); +} + +- (void)handleMetricEvent:(MetricEvent)event +{ + std::lock_guard lock(_lock); + + using ValueType = MetricEvent::Value::Type; + switch (event.ValueType()) { + case ValueType::kInt32: + MTR_LOG_INFO("Received metric event, key: %s, type: %d, value: %d", event.key(), event.type(), event.ValueInt32()); + break; + case ValueType::kUInt32: + MTR_LOG_INFO("Received metric event, key: %s, type: %d, value: %u", event.key(), event.type(), event.ValueUInt32()); + break; + case ValueType::kChipErrorCode: + MTR_LOG_INFO("Received metric event, key: %s, type: %d, error value: %u", event.key(), event.type(), event.ValueErrorCode()); + break; + case ValueType::kUndefined: + MTR_LOG_INFO("Received metric event, key: %s, type: %d, value: nil", event.key(), event.type()); + break; + default: + MTR_LOG_INFO("Received metric event, key: %s, type: %d, unknown value", event.key(), event.type()); + return; + } + + // Create the new metric key based event type + auto metricsKey = [NSString stringWithFormat:@"%s%@", event.key(), suffixNameForMetric(event)]; + MTRMetricsData * data = [[MTRMetricsData alloc] initWithMetricEvent:event]; + + // If End event, compute its duration using the Begin event + if (event.type() == MetricEvent::Type::kEndEvent) { + auto metricsBeginKey = [NSString stringWithFormat:@"%s%@", event.key(), suffixNameForMetricType(MetricEvent::Type::kBeginEvent)]; + MTRMetricsData * beginMetric = _metricsDataCollection[metricsBeginKey]; + if (beginMetric) { + [data setDurationFromMetricData:beginMetric]; + } else { + // Unbalanced end + MTR_LOG_ERROR("Unable to find Begin event corresponding to Metric Event: %s", event.key()); + } + } + + [_metricsDataCollection setValue:data forKey:metricsKey]; + + // If the event is a begin or end event, implicitly emit a corresponding instant event + if (event.type() == MetricEvent::Type::kBeginEvent || event.type() == MetricEvent::Type::kEndEvent) { + MetricEvent instantEvent(MetricEvent::Type::kInstantEvent, event.key()); + data = [[MTRMetricsData alloc] initWithMetricEvent:instantEvent]; + metricsKey = [NSString stringWithFormat:@"%s%@", event.key(), suffixNameForMetric(instantEvent)]; + [_metricsDataCollection setValue:data forKey:metricsKey]; + } +} + +- (MTRMetrics *)metricSnapshot:(BOOL)resetCollection +{ + std::lock_guard lock(_lock); + + // Copy the MTRMetrics as NSDictionary + MTRMetrics * metrics = [[MTRMetrics alloc] initWithCapacity:[_metricsDataCollection count]]; + for (NSString * key in _metricsDataCollection) { + [metrics setValue:[_metricsDataCollection[key] toDictionary] forKey:key]; + } + + // Clear curent stats, if specified + if (resetCollection) { + [_metricsDataCollection removeAllObjects]; + } + return metrics; +} + +@end diff --git a/src/darwin/Framework/CHIP/MTRMetrics_Internal.h b/src/darwin/Framework/CHIP/MTRMetrics_Internal.h index 3e69c79dd53802..757ff0731ada0c 100644 --- a/src/darwin/Framework/CHIP/MTRMetrics_Internal.h +++ b/src/darwin/Framework/CHIP/MTRMetrics_Internal.h @@ -15,13 +15,33 @@ * limitations under the License. */ #import "MTRMetrics.h" +#include NS_ASSUME_NONNULL_BEGIN -#define MTRMetricCommissioningStatusKey @"com.matter.metric.commissioningStatus" +/** + * A representation of a metric data for an operation. + */ +@interface MTRMetricsData : NSObject + +// Value for the metric. This can be null if the metric is just a fire event with no value +@property (nonatomic, nullable, readonly, copy) NSNumber * value; + +// Relative time point at which the metric was emitted. This may be null. +@property (nonatomic, nullable, readonly, copy) NSNumber * timePointMicroseconds; + +// During for the event. This may be null. +@property (nonatomic, nullable, readonly, copy) NSNumber * durationMicroseconds; + +// Convert contents to a dictionary +- (NSDictionary *)toDictionary; + +@end @interface MTRMetrics () +- (instancetype)initWithCapacity:(NSUInteger)numItems; + - (void)setValue:(id _Nullable)value forKey:(NSString *)key; - (void)removeValueForKey:(NSString *)key; diff --git a/src/darwin/Framework/CHIPTests/MTRMetricsTests.m b/src/darwin/Framework/CHIPTests/MTRMetricsTests.m index ed5de20b5c433b..696f55bef89df4 100644 --- a/src/darwin/Framework/CHIPTests/MTRMetricsTests.m +++ b/src/darwin/Framework/CHIPTests/MTRMetricsTests.m @@ -49,7 +49,7 @@ - (void)test000_SetUp - (void)test001_TestAllKeys { - MTRMetrics * metrics = [MTRMetrics new]; + MTRMetrics * metrics = [[MTRMetrics alloc] initWithCapacity:4]; [metrics setValue:@"metricsCounter1" forKey:@"com.matter.metrics.counter1"]; [metrics setValue:@"metricsCounter2" forKey:@"com.matter.metrics.counter2"]; [metrics setValue:@"metricsCounter3" forKey:@"com.matter.metrics.counter3"]; @@ -65,7 +65,7 @@ - (void)test001_TestAllKeys } - (void)test002_TestOneKey { - MTRMetrics * metrics = [MTRMetrics new]; + MTRMetrics * metrics = [[MTRMetrics alloc] initWithCapacity:1]; [metrics setValue:@"metricsCounter1" forKey:@"com.matter.metrics.counter1"]; NSArray * keys = [metrics allKeys]; @@ -75,7 +75,7 @@ - (void)test002_TestOneKey - (void)test003_TestMultipleKeys { - MTRMetrics * metrics = [MTRMetrics new]; + MTRMetrics * metrics = [[MTRMetrics alloc] initWithCapacity:3]; [metrics setValue:@"metricsCounter1" forKey:@"com.matter.metrics.counter1"]; [metrics setValue:@"metricsCounter2" forKey:@"com.matter.metrics.counter2"]; [metrics setValue:[NSError errorWithDomain:MTRErrorDomain code:MTRErrorCodeInvalidState userInfo:nil] forKey:@"com.matter.metrics.counter3"]; @@ -90,7 +90,7 @@ - (void)test003_TestMultipleKeys - (void)test004_TestValueForKey { - MTRMetrics * metrics = [MTRMetrics new]; + MTRMetrics * metrics = [[MTRMetrics alloc] initWithCapacity:1]; [metrics setValue:@"metricsCounter1" forKey:@"com.matter.metrics.counter1"]; XCTAssertEqualObjects([metrics valueForKey:@"com.matter.metrics.counter1"], @"metricsCounter1"); @@ -98,7 +98,7 @@ - (void)test004_TestValueForKey - (void)test005_TestMultipleValueForKeys { - MTRMetrics * metrics = [MTRMetrics new]; + MTRMetrics * metrics = [[MTRMetrics alloc] initWithCapacity:3]; [metrics setValue:@"metricsCounter1" forKey:@"com.matter.metrics.counter1"]; [metrics setValue:@"metricsCounter2" forKey:@"com.matter.metrics.counter2"]; [metrics setValue:[NSError errorWithDomain:MTRErrorDomain code:MTRErrorCodeInvalidState userInfo:nil] forKey:@"com.matter.metrics.counter3"]; @@ -110,7 +110,7 @@ - (void)test005_TestMultipleValueForKeys - (void)test006_TestValueRemoval { - MTRMetrics * metrics = [MTRMetrics new]; + MTRMetrics * metrics = [[MTRMetrics alloc] initWithCapacity:2]; [metrics setValue:@"metricsCounter1" forKey:@"com.matter.metrics.counter1"]; [metrics setValue:@"metricsCounter2" forKey:@"com.matter.metrics.counter2"]; diff --git a/src/darwin/Framework/Matter.xcodeproj/project.pbxproj b/src/darwin/Framework/Matter.xcodeproj/project.pbxproj index a49b33fa3a1ea4..698fe2ad47114a 100644 --- a/src/darwin/Framework/Matter.xcodeproj/project.pbxproj +++ b/src/darwin/Framework/Matter.xcodeproj/project.pbxproj @@ -266,6 +266,9 @@ 88EBF8CE27FABDD500686BC1 /* MTRDeviceAttestationDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 88EBF8CB27FABDD500686BC1 /* MTRDeviceAttestationDelegate.h */; settings = {ATTRIBUTES = (Public, ); }; }; 88EBF8CF27FABDD500686BC1 /* MTRDeviceAttestationDelegateBridge.mm in Sources */ = {isa = PBXBuildFile; fileRef = 88EBF8CC27FABDD500686BC1 /* MTRDeviceAttestationDelegateBridge.mm */; }; 88EBF8D027FABDD500686BC1 /* MTRDeviceAttestationDelegateBridge.h in Headers */ = {isa = PBXBuildFile; fileRef = 88EBF8CD27FABDD500686BC1 /* MTRDeviceAttestationDelegateBridge.h */; }; + 88FA798D2B7B257100CD4B6F /* MTRMetricsCollector.h in Headers */ = {isa = PBXBuildFile; fileRef = 88FA798B2B7B257100CD4B6F /* MTRMetricsCollector.h */; }; + 88FA798E2B7B257100CD4B6F /* MTRMetricsCollector.mm in Sources */ = {isa = PBXBuildFile; fileRef = 88FA798C2B7B257100CD4B6F /* MTRMetricsCollector.mm */; }; + 88FA79902B7BE42500CD4B6F /* MTRMetricsCollector.mm in Sources */ = {isa = PBXBuildFile; fileRef = 88FA798C2B7B257100CD4B6F /* MTRMetricsCollector.mm */; }; 93B2CF9A2B56E45C00E4D187 /* MTRClusterNames.mm in Sources */ = {isa = PBXBuildFile; fileRef = 93B2CF992B56E45C00E4D187 /* MTRClusterNames.mm */; }; 93E610AA2B626E290077F02A /* MTRClusterNames.h in Headers */ = {isa = PBXBuildFile; fileRef = 93E610A92B626E290077F02A /* MTRClusterNames.h */; settings = {ATTRIBUTES = (Public, ); }; }; 991DC0842475F45400C13860 /* MTRDeviceController.h in Headers */ = {isa = PBXBuildFile; fileRef = 991DC0822475F45400C13860 /* MTRDeviceController.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -664,6 +667,8 @@ 88EBF8CB27FABDD500686BC1 /* MTRDeviceAttestationDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MTRDeviceAttestationDelegate.h; sourceTree = ""; }; 88EBF8CC27FABDD500686BC1 /* MTRDeviceAttestationDelegateBridge.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MTRDeviceAttestationDelegateBridge.mm; sourceTree = ""; }; 88EBF8CD27FABDD500686BC1 /* MTRDeviceAttestationDelegateBridge.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MTRDeviceAttestationDelegateBridge.h; sourceTree = ""; }; + 88FA798B2B7B257100CD4B6F /* MTRMetricsCollector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MTRMetricsCollector.h; sourceTree = ""; }; + 88FA798C2B7B257100CD4B6F /* MTRMetricsCollector.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MTRMetricsCollector.mm; sourceTree = ""; }; 93B2CF992B56E45C00E4D187 /* MTRClusterNames.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MTRClusterNames.mm; sourceTree = ""; }; 93E610A92B626E290077F02A /* MTRClusterNames.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MTRClusterNames.h; sourceTree = ""; }; 991DC0822475F45400C13860 /* MTRDeviceController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MTRDeviceController.h; sourceTree = ""; }; @@ -1160,6 +1165,8 @@ B202528F2459E34F00F97062 /* CHIP */ = { isa = PBXGroup; children = ( + 88FA798B2B7B257100CD4B6F /* MTRMetricsCollector.h */, + 88FA798C2B7B257100CD4B6F /* MTRMetricsCollector.mm */, 88E6C9442B6334ED001A1FE0 /* MTRMetrics_Internal.h */, 88E6C9432B6334ED001A1FE0 /* MTRMetrics.h */, 88E6C9452B6334ED001A1FE0 /* MTRMetrics.mm */, @@ -1518,6 +1525,7 @@ 2C222AD0255C620600E446B9 /* MTRBaseDevice.h in Headers */, 7596A84F2877E6A9004DAE0E /* MTRCluster_Internal.h in Headers */, 991DC0842475F45400C13860 /* MTRDeviceController.h in Headers */, + 88FA798D2B7B257100CD4B6F /* MTRMetricsCollector.h in Headers */, 88E6C9462B6334ED001A1FE0 /* MTRMetrics.h in Headers */, AF1CB86E2874B03B00865A96 /* MTROTAProviderDelegate.h in Headers */, 51D0B1402B61B3A4006E3511 /* MTRServerCluster.h in Headers */, @@ -1739,6 +1747,7 @@ 039546A62991E151006D42A8 /* InteractionModel.cpp in Sources */, B45373E72A9FEBA400807602 /* parsers.c in Sources */, B4FCD5722B603A6300832859 /* DownloadLogCommand.mm in Sources */, + 88FA79902B7BE42500CD4B6F /* MTRMetricsCollector.mm in Sources */, B45373BF2A9FEA9100807602 /* adopt.c in Sources */, B45373F32A9FEC1A00807602 /* server-ws.c in Sources */, 03F430AA2994113500166449 /* sysunix.c in Sources */, @@ -1893,6 +1902,7 @@ 5A6FEC9827B5C6AF00F25F42 /* MTRDeviceOverXPC.mm in Sources */, 514654492A72F9DF00904E61 /* MTRDemuxingStorage.mm in Sources */, 1E4D655229C30A8700BC3478 /* MTRCommissionableBrowser.mm in Sources */, + 88FA798E2B7B257100CD4B6F /* MTRMetricsCollector.mm in Sources */, 3DA1A3562ABAB3B4004F0BB9 /* MTRAsyncWorkQueue.mm in Sources */, 51D0B1272B617246006E3511 /* MTRServerEndpoint.mm in Sources */, 3DECCB722934AFE200585AEC /* MTRLogging.mm in Sources */, diff --git a/src/lib/support/CodeUtils.h b/src/lib/support/CodeUtils.h index 58094a01731c37..2b47538b8faebf 100644 --- a/src/lib/support/CodeUtils.h +++ b/src/lib/support/CodeUtils.h @@ -362,10 +362,10 @@ constexpr inline const _T & max(const _T & a, const _T & b) } while (false) /** - * @def SuccessOrExit(aStatus) + * @def SuccessOrExit(error) * * @brief - * This checks for the specified status, which is expected to + * This checks for the specified error, which is expected to * commonly be successful (CHIP_NO_ERROR), and branches to * the local label 'exit' if the status is unsuccessful. * @@ -387,10 +387,10 @@ constexpr inline const _T & max(const _T & a, const _T & b) * } * @endcode * - * @param[in] aStatus A scalar status to be evaluated against zero (0). + * @param[in] error A ChipError object to be evaluated against success (CHIP_NO_ERROR). * */ -#define SuccessOrExit(aStatus) nlEXPECT(::chip::ChipError::IsSuccess((aStatus)), exit) +#define SuccessOrExit(error) nlEXPECT(::chip::ChipError::IsSuccess((error)), exit) /** * @def VerifyOrExit(aCondition, anAction) diff --git a/src/platform/Darwin/BUILD.gn b/src/platform/Darwin/BUILD.gn index 11372cb5f4c627..321076da241cb5 100644 --- a/src/platform/Darwin/BUILD.gn +++ b/src/platform/Darwin/BUILD.gn @@ -97,6 +97,7 @@ static_library("Darwin") { deps = [ ":logging", + ":tracing", "${chip_root}/src/lib/dnssd:platform_header", "${chip_root}/src/platform/logging:headers", "${chip_root}/src/setup_payload", @@ -131,6 +132,18 @@ static_library("Darwin") { } } +source_set("tracing") { + sources = [ + "Tracing.h", + "Tracing.mm", + ] + + deps = [ + ":logging", + "${chip_root}/src/tracing", + ] +} + static_library("logging") { sources = [ "Logging.h", diff --git a/src/platform/Darwin/Tracing.h b/src/platform/Darwin/Tracing.h new file mode 100644 index 00000000000000..cefc5c326fc3d5 --- /dev/null +++ b/src/platform/Darwin/Tracing.h @@ -0,0 +1,77 @@ +/* + * + * Copyright (c) 2024 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 + +#define MATTER_TRACE_BEGIN(label, group) os_signpost_interval_begin(__DARWIN_MATTER_SIGNPOST_LOGGER(), OS_SIGNPOST_ID_EXCLUSIVE, group "-" label) +#define MATTER_TRACE_END(label, group) os_signpost_interval_end(__DARWIN_MATTER_SIGNPOST_LOGGER(), OS_SIGNPOST_ID_EXCLUSIVE, group "-" label) +#define MATTER_TRACE_INSTANT(label, group) os_signpost_event_emit(__DARWIN_MATTER_SIGNPOST_LOGGER(), OS_SIGNPOST_ID_EXCLUSIVE, group "-" label) + +#define MATTER_TRACE_COUNTER(label) \ + do { \ + static unsigned int count##_label = 0; \ + os_signpost_event_emit(__DARWIN_MATTER_SIGNPOST_LOGGER(), OS_SIGNPOST_ID_EXCLUSIVE, label, "%u", ++count##_label); \ + } while (0) + +#define _CONCAT_IMPL(a, b) a##b +#define _MACRO_CONCAT(a, b) _CONCAT_IMPL(a, b) + +#define MATTER_TRACE_SCOPE(label, group) ::chip::Tracing::signposts::Scoped _MACRO_CONCAT(_trace_scope, __COUNTER__)(label, group) + +#define MATTER_SDK_SIGNPOST_NAME "com.csa.matter.signpost" +#define __DARWIN_MATTER_SIGNPOST_LOGGER() chip::Tracing::signposts::GetMatterSignpostLogger() + +namespace chip { +namespace Tracing { + namespace signposts { + + os_log_t GetMatterSignpostLogger(); + + class Scoped { + public: + inline Scoped(const char * label, const char * group) + : mLabel(label) + , mGroup(group) + { + os_signpost_interval_begin(__DARWIN_MATTER_SIGNPOST_LOGGER(), OS_SIGNPOST_ID_EXCLUSIVE, MATTER_SDK_SIGNPOST_NAME, "%s-%s", group, label); + } + inline ~Scoped() { os_signpost_interval_end(__DARWIN_MATTER_SIGNPOST_LOGGER(), OS_SIGNPOST_ID_EXCLUSIVE, MATTER_SDK_SIGNPOST_NAME, "%s-%s", mGroup, mLabel); } + + private: + const char * mLabel; + const char * mGroup; + }; + + class DarwinTracingBackend : public ::chip::Tracing::Backend { + public: + DarwinTracingBackend(); + + typedef void (^MetricEventHandler)(MetricEvent event); + + void SetMetricEventHandler(MetricEventHandler callback); + void LogMetricEvent(const MetricEvent & event) override; + + private: + MetricEventHandler mClientCallback; + }; + + } // namespace signposts +} // namespace Tracing +} // namespace chip diff --git a/src/platform/Darwin/Tracing.mm b/src/platform/Darwin/Tracing.mm new file mode 100644 index 00000000000000..a729c32e8079a1 --- /dev/null +++ b/src/platform/Darwin/Tracing.mm @@ -0,0 +1,55 @@ +/* + * + * Copyright (c) 2024 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. + */ +#import +#include +#include + +namespace chip { +namespace Tracing { + namespace signposts { + os_log_t GetMatterSignpostLogger() + { + static dispatch_once_t onceToken; + static os_log_t logger; + dispatch_once(&onceToken, ^{ + logger = os_log_create("com.csa.matter.signposts", "com.csa.matter.sdk"); + }); + return logger; + } + + DarwinTracingBackend::DarwinTracingBackend() + : mClientCallback(nullptr) + { + } + + void DarwinTracingBackend::SetMetricEventHandler(MetricEventHandler callback) + { + mClientCallback = callback; + } + + void DarwinTracingBackend::LogMetricEvent(const MetricEvent & event) + { + // Pass along to the client to handle the event + if (mClientCallback) { + mClientCallback(event); + } + } + + } // namespace signposts +} // namespace Tracing +} // namespace chip diff --git a/src/tracing/BUILD.gn b/src/tracing/BUILD.gn index 84af8b09ef2449..cdb50a710c9c00 100644 --- a/src/tracing/BUILD.gn +++ b/src/tracing/BUILD.gn @@ -36,12 +36,16 @@ static_library("tracing") { sources = [ "backend.h", "log_declares.h", + "metric_event.h", + "metric_keys.h", + "metric_macros.h", "registry.cpp", "registry.h", ] public_deps = [ ":tracing_buildconfig", + "${chip_root}/src/lib/core:error", "${chip_root}/src/lib/support", ] } diff --git a/src/tracing/backend.h b/src/tracing/backend.h index c57e97ddd27638..9bc4e8bd096ebd 100644 --- a/src/tracing/backend.h +++ b/src/tracing/backend.h @@ -64,13 +64,13 @@ class Backend : public ::chip::IntrusiveListNodeBase<> virtual void TraceInstant(const char * label, const char * group) {} virtual void TraceCounter(const char * label) {} - virtual void TraceMetric(const char * label, int32_t value) {} virtual void LogMessageSend(MessageSendInfo &) { TraceInstant("MessageSent", "Messaging"); } virtual void LogMessageReceived(MessageReceivedInfo &) { TraceInstant("MessageReceived", "Messaging"); } virtual void LogNodeLookup(NodeLookupInfo &) { TraceInstant("Lookup", "DNSSD"); } virtual void LogNodeDiscovered(NodeDiscoveredInfo &) { TraceInstant("Node Discovered", "DNSSD"); } virtual void LogNodeDiscoveryFailed(NodeDiscoveryFailedInfo &) { TraceInstant("Discovery Failed", "DNSSD"); } + virtual void LogMetricEvent(const MetricEvent &) { TraceInstant("Metric Event", "Metric"); } }; } // namespace Tracing diff --git a/src/tracing/darwin/BUILD.gn b/src/tracing/darwin/BUILD.gn new file mode 100644 index 00000000000000..3bd9b7685b594e --- /dev/null +++ b/src/tracing/darwin/BUILD.gn @@ -0,0 +1,25 @@ +# Copyright (c) 2024 Project CHIP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build_overrides/build.gni") +import("//build_overrides/chip.gni") + +config("tracing") { + include_dirs = [ "include" ] +} + +source_set("darwin_tracing") { + public = [ "include/matter/tracing/macros_impl.h" ] + public_configs = [ ":tracing" ] +} diff --git a/src/tracing/darwin/include/matter/tracing/macros_impl.h b/src/tracing/darwin/include/matter/tracing/macros_impl.h new file mode 100644 index 00000000000000..536618dc2875b2 --- /dev/null +++ b/src/tracing/darwin/include/matter/tracing/macros_impl.h @@ -0,0 +1,25 @@ +/* + * + * Copyright (c) 2024 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 + +/* Ensure we do not have double tracing macros defined */ +#if defined(MATTER_TRACE_BEGIN) +#error "Tracing macros seem to be double defined" +#endif + +#include diff --git a/src/tracing/esp32_trace/esp32_tracing.cpp b/src/tracing/esp32_trace/esp32_tracing.cpp index 6193587be49c7d..db5f09ee9a751c 100644 --- a/src/tracing/esp32_trace/esp32_tracing.cpp +++ b/src/tracing/esp32_trace/esp32_tracing.cpp @@ -24,6 +24,7 @@ #include #include #include +#include namespace chip { namespace Tracing { @@ -154,16 +155,38 @@ void ESP32Backend::TraceCounter(const char * label) ::Insights::ESPInsightsCounter::GetInstance(label)->ReportMetrics(); } -void ESP32Backend::TraceMetric(const char * label, int32_t value) +void ESP32Backend::LogMetricEvent(const MetricEvent & event) { if (!mRegistered) { - esp_diag_metrics_register("SYS_MTR" /*Tag of metrics */, label /* Unique key 8 */, label /* label displayed on dashboard */, - "insights.mtr" /* hierarchical path */, ESP_DIAG_DATA_TYPE_INT /* data_type */); + esp_diag_metrics_register("SYS_MTR" /*Tag of metrics */, event.key() /* Unique key 8 */, + event.key() /* label displayed on dashboard */, "insights.mtr" /* hierarchical path */, + ESP_DIAG_DATA_TYPE_INT /* data_type */); mRegistered = true; } - ESP_LOGI("mtr", "The value of %s is %ld ", label, value); - esp_diag_metrics_add_int(label, value); + + using ValueType = MetricEvent::Value::Type; + switch (event.ValueType()) + { + case ValueType::kInt32: + ESP_LOGI("mtr", "The value of %s is %ld ", event.key(), event.ValueInt32()); + esp_diag_metrics_add_int(event.key(), event.ValueInt32()); + break; + case ValueType::kUInt32: + ESP_LOGI("mtr", "The value of %s is %lu ", event.key(), event.ValueUInt32()); + esp_diag_metrics_add_uint(event.key(), event.ValueUInt32()); + break; + case ValueType::kChipErrorCode: + ESP_LOGI("mtr", "The value of %s is error with code %lu ", event.key(), event.ValueErrorCode()); + esp_diag_metrics_add_uint(event.key(), event.ValueErrorCode()); + break; + case ValueType::kUndefined: + ESP_LOGI("mtr", "The value of %s is undefined", event.key()); + break; + default: + ESP_LOGI("mtr", "The value of %s is of an UNKNOWN TYPE", event.key()); + break; + } } void ESP32Backend::TraceBegin(const char * label, const char * group) diff --git a/src/tracing/esp32_trace/esp32_tracing.h b/src/tracing/esp32_trace/esp32_tracing.h index 3eb127c1d3367f..2e08e69d616158 100644 --- a/src/tracing/esp32_trace/esp32_tracing.h +++ b/src/tracing/esp32_trace/esp32_tracing.h @@ -29,7 +29,6 @@ class ESP32Backend : public ::chip::Tracing::Backend void TraceInstant(const char * label, const char * group) override; void TraceCounter(const char * label) override; - void TraceMetric(const char * label, int32_t value) override; void LogMessageSend(MessageSendInfo &) override; void LogMessageReceived(MessageReceivedInfo &) override; @@ -37,6 +36,7 @@ class ESP32Backend : public ::chip::Tracing::Backend void LogNodeLookup(NodeLookupInfo &) override; void LogNodeDiscovered(NodeDiscoveredInfo &) override; void LogNodeDiscoveryFailed(NodeDiscoveryFailedInfo &) override; + void LogMetricEvent(const MetricEvent &) override; private: bool mRegistered = false; diff --git a/src/tracing/esp32_trace/include/matter/tracing/macros_impl.h b/src/tracing/esp32_trace/include/matter/tracing/macros_impl.h index 8ebde173d8297b..b95c20754237a1 100644 --- a/src/tracing/esp32_trace/include/matter/tracing/macros_impl.h +++ b/src/tracing/esp32_trace/include/matter/tracing/macros_impl.h @@ -29,7 +29,6 @@ #define MATTER_TRACE_END(label, group) ::chip::Tracing::Internal::End(label, group) #define MATTER_TRACE_INSTANT(label, group) ::chip::Tracing::Internal::Instant(label, group) #define MATTER_TRACE_COUNTER(label) ::chip::Tracing::Internal::Counter(label) -#define MATTER_TRACE_METRIC(label, value) ::chip::Tracing::Internal::Metric(label, value) namespace chip { namespace Tracing { diff --git a/src/tracing/json/json_tracing.cpp b/src/tracing/json/json_tracing.cpp index 64627f079d04dd..91b4474388ecd0 100644 --- a/src/tracing/json/json_tracing.cpp +++ b/src/tracing/json/json_tracing.cpp @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -295,11 +296,31 @@ void JsonBackend::TraceCounter(const char * label) OutputValue(value); } -void JsonBackend::TraceMetric(const char * label, int32_t val) +void JsonBackend::LogMetricEvent(const MetricEvent & event) { ::Json::Value value; - value["label"] = label; - value["value"] = val; + + value["label"] = event.key(); + + using ValueType = MetricEvent::Value::Type; + switch (event.ValueType()) + { + case ValueType::kInt32: + value["value"] = event.ValueInt32(); + break; + case ValueType::kUInt32: + value["value"] = event.ValueUInt32(); + break; + case ValueType::kChipErrorCode: + value["value"] = event.ValueErrorCode(); + break; + case ValueType::kUndefined: + value["value"] = ::Json::Value(); + break; + default: + value["value"] = "UNKNOWN"; + break; + } OutputValue(value); } diff --git a/src/tracing/json/json_tracing.h b/src/tracing/json/json_tracing.h index e8ad8ee5894b03..14f3d163a04c46 100644 --- a/src/tracing/json/json_tracing.h +++ b/src/tracing/json/json_tracing.h @@ -52,12 +52,12 @@ class JsonBackend : public ::chip::Tracing::Backend void TraceEnd(const char * label, const char * group) override; void TraceInstant(const char * label, const char * group) override; void TraceCounter(const char * label) override; - void TraceMetric(const char * label, int32_t val) override; void LogMessageSend(MessageSendInfo &) override; void LogMessageReceived(MessageReceivedInfo &) override; void LogNodeLookup(NodeLookupInfo &) override; void LogNodeDiscovered(NodeDiscoveredInfo &) override; void LogNodeDiscoveryFailed(NodeDiscoveryFailedInfo &) override; + void LogMetricEvent(const MetricEvent &) override; void Close() override { CloseFile(); } private: diff --git a/src/tracing/log_declares.h b/src/tracing/log_declares.h index 5e502d0c93af6c..72ebbce7c18011 100644 --- a/src/tracing/log_declares.h +++ b/src/tracing/log_declares.h @@ -27,6 +27,7 @@ struct MessageReceivedInfo; struct NodeLookupInfo; struct NodeDiscoveredInfo; struct NodeDiscoveryFailedInfo; +class MetricEvent; } // namespace Tracing } // namespace chip diff --git a/src/tracing/macros.h b/src/tracing/macros.h index 0643a466c2a77d..1a9b4569e2a35b 100644 --- a/src/tracing/macros.h +++ b/src/tracing/macros.h @@ -30,10 +30,6 @@ // Tracing macro to trace monotonically increasing counter values. // MATTER_TRACE_COUNTER(label) -// Tracing macro to represent historical metric data i.e the data points which represent different -// values at different point of time. -// MATTER_TRACE_METRIC(label, value) - #include #include #include @@ -87,7 +83,6 @@ #define MATTER_TRACE_INSTANT(...) _MATTER_TRACE_DISABLE(__VA_ARGS__) #define MATTER_TRACE_SCOPE(...) _MATTER_TRACE_DISABLE(__VA_ARGS__) #define MATTER_TRACE_COUNTER(...) _MATTER_TRACE_DISABLE(__VA_ARGS__) -#define MATTER_TRACE_METRIC(...) _MATTER_TRACE_DISABLE(__VA_ARGS__) #define MATTER_LOG_MESSAGE_SEND(...) _MATTER_TRACE_DISABLE(__VA_ARGS__) #define MATTER_LOG_MESSAGE_RECEIVED(...) _MATTER_TRACE_DISABLE(__VA_ARGS__) diff --git a/src/tracing/metric_event.h b/src/tracing/metric_event.h new file mode 100644 index 00000000000000..7bb5d8b5b81b51 --- /dev/null +++ b/src/tracing/metric_event.h @@ -0,0 +1,189 @@ +/* + * Copyright (c) 2024 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 +#include +#include + +namespace chip { +namespace Tracing { + +/** + * Define a metric that can be logged. A metric consists of a key and an optional value pair. + * The value is currently limited to simple scalar values. + * + * Additionally a metric is tagged as either an instant event or marked with a begin/end + * for the event. When the latter is used, a duration can be associated between the two events. + */ +class MetricEvent +{ +public: + MetricEvent(const MetricEvent &) = default; + MetricEvent(MetricEvent &&) = default; + MetricEvent & operator=(const MetricEvent &) = default; + MetricEvent & operator=(MetricEvent &&) = default; + + // This specifies the different categories of metric events that can created. In addition to + // emitting an event, events paired with a kBeginEvent and kEndEvent can be used to track + // duration for the event. A kInstantEvent represents a one shot event. + enum class Type + { + // This specifies an event marked to track the Begin of an operation + kBeginEvent, + + // This specifies an event marked to track the End of an operation + kEndEvent, + + // This specifies a one shot event + kInstantEvent + }; + + // This defines the different types of values that can stored when a metric is emitted + struct Value + { + Value(const Value &) = default; + Value(Value &&) = default; + Value & operator=(const Value &) = default; + Value & operator=(Value &&) = default; + + enum class Type : uint8_t + { + kUndefined, // Value is not valid + kInt32, // int32_t + kUInt32, // uint32_t + kChipErrorCode // chip::ChipError + }; + + union Store + { + int32_t int32_value; + uint32_t uint32_value; + + Store() {} + + Store(int32_t v) : int32_value(v) {} + + Store(uint32_t v) : uint32_value(v) {} + }; + + Store store; + Type type; + + Value() : type(Type::kUndefined) {} + + Value(uint32_t value) : store(value), type(Type::kUInt32) {} + + Value(int32_t value) : store(value), type(Type::kInt32) {} + + Value(const ChipError & err) : store(err.AsInteger()), type(Type::kChipErrorCode) {} + }; + + MetricEvent(Type type, MetricKey key) : mType(type), mKey(key) {} + + MetricEvent(Type type, MetricKey key, int32_t value) : mType(type), mKey(key), mValue(value) {} + + MetricEvent(Type type, MetricKey key, uint32_t value) : mType(type), mKey(key), mValue(value) {} + + MetricEvent(Type type, MetricKey key, const ChipError & error) : mType(type), mKey(key), mValue(error) {} + + MetricEvent(Type type, MetricKey key, Value value) : mType(type), mKey(key), mValue(value) {} + + MetricEvent(Type type, MetricKey key, int8_t value) : MetricEvent(type, key, int32_t(value)) {} + + MetricEvent(Type type, MetricKey key, uint8_t value) : MetricEvent(type, key, uint32_t(value)) {} + + MetricEvent(Type type, MetricKey key, int16_t value) : MetricEvent(type, key, int32_t(value)) {} + + MetricEvent(Type type, MetricKey key, uint16_t value) : MetricEvent(type, key, uint32_t(value)) {} + + Type type() const { return mType; } + + MetricKey key() const { return mKey; } + + Value::Type ValueType() const { return mValue.type; } + + uint32_t ValueUInt32() const + { + VerifyOrDie(mValue.type == Value::Type::kUInt32); + return mValue.store.uint32_value; + } + + int32_t ValueInt32() const + { + VerifyOrDie(mValue.type == Value::Type::kInt32); + return mValue.store.int32_value; + } + + uint32_t ValueErrorCode() const + { + VerifyOrDie(mValue.type == Value::Type::kChipErrorCode); + return mValue.store.uint32_value; + } + +private: + Type mType; + MetricKey mKey; + Value mValue; +}; + +namespace ErrorHandling { + +/** + * Utility to emit an instant metric if the error is not a success. + */ +inline bool LogMetricIfError(MetricKey metricKey, const ::chip::ChipError & err) +{ + bool success = ::chip::ChipError::IsSuccess(err); + if (!success) + { + MATTER_LOG_METRIC(metricKey, err); + } + return success; +} + +} // namespace ErrorHandling + +/** + * This utility class helps generate a Begin and End metric event within the scope of a block using RAII. + */ +class ScopedMetricEvent +{ +public: + ScopedMetricEvent(const ScopedMetricEvent &) = delete; + ScopedMetricEvent(ScopedMetricEvent &&) = delete; + ScopedMetricEvent & operator=(const ScopedMetricEvent &) = delete; + ScopedMetricEvent & operator=(ScopedMetricEvent &&) = delete; + + ScopedMetricEvent(MetricKey key, ChipError & error) : mKey(key), mError(error) + { + MATTER_LOG_METRIC_BEGIN(mKey); + IgnoreUnusedVariable(mKey); + IgnoreUnusedVariable(mError); + } + + ~ScopedMetricEvent() { MATTER_LOG_METRIC_END(mKey, mError); } + +private: + MetricKey mKey; + ChipError & mError; +}; + +} // namespace Tracing +} // namespace chip diff --git a/src/tracing/metric_keys.h b/src/tracing/metric_keys.h new file mode 100644 index 00000000000000..f52b2ab3244776 --- /dev/null +++ b/src/tracing/metric_keys.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2024 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 + +namespace chip { +namespace Tracing { + +/** + * Defines the key type use to identity a specific metric + */ +typedef const char * MetricKey; + +/** + * List of supported metric keys + */ +constexpr MetricKey kMetricDiscoveryOverBLE = "disc-over-ble"; +constexpr MetricKey kMetricDiscoveryOnNetwork = "disc-on-nw"; +constexpr MetricKey kMetricPASESession = "pase-session"; +constexpr MetricKey kMetricPASESessionPair = "pase-session-pair"; +constexpr MetricKey kMetricPASESessionBLE = "pase-session-ble"; +constexpr MetricKey kMetricAttestationResult = "attestation-result"; +constexpr MetricKey kMetricAttestationOverridden = "attestation-overridden"; +constexpr MetricKey kMetricCASESession = "case-session"; +constexpr MetricKey kMetricCASESessionEstState = "case-conn-est"; +constexpr MetricKey kMetricWiFiRSSI = "wifi_rssi"; + +} // namespace Tracing +} // namespace chip diff --git a/src/tracing/metric_macros.h b/src/tracing/metric_macros.h new file mode 100644 index 00000000000000..4ff85f353701b3 --- /dev/null +++ b/src/tracing/metric_macros.h @@ -0,0 +1,243 @@ +/* + * + * Copyright (c) 2024 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 + +#define __LOG_METRIC_CONCAT_IMPL(a, b) a##b +#define __LOG_METRIC_MACRO_CONCAT(a, b) __LOG_METRIC_CONCAT_IMPL(a, b) + +#if MATTER_TRACING_ENABLED + +/** + * @def SuccessOrExitWithMetric(kMetriKey, error) + * + * @brief + * This checks for the specified error, which is expected to + * commonly be successful (CHIP_NO_ERROR), and branches to + * the local label 'exit' if the error is not success. + * If error is not a success, a metric with key kMetriKey is emitted with + * the error code as the value of the metric. + * + * Example Usage: + * + * @code + * CHIP_ERROR TryHard() + * { + * CHIP_ERROR err; + * + * err = TrySomething(); + * SuccessOrExitWithMetric(kMetricKey, err); + * + * err = TrySomethingElse(); + * SuccessOrExitWithMetric(kMetricKey, err); + * + * exit: + * return err; + * } + * @endcode + * + * @param[in] kMetricKey Metric key for the metric event to be emitted + * if the condition evaluates to false. The value + * for the metric is result of the expression aStatus. + * @param[in] error A ChipError object to be evaluated against success (CHIP_NO_ERROR). + * + */ +#define SuccessOrExitWithMetric(kMetricKey, error) \ + nlEXPECT(::chip::Tracing::ErrorHandling::LogMetricIfError((kMetricKey), (error)), exit) + +/** + * @def VerifyOrExitWithMetric(kMetricKey, aCondition, anAction) + * + * @brief + * This checks for the specified condition, which is expected to + * commonly be true, and both executes @a anAction and branches to + * the local label 'exit' if the condition is false. If the condition + * is false a metric event with the specified key is emitted with value + * set to the result of the expression anAction. + * + * Example Usage: + * + * @code + * CHIP_ERROR MakeBuffer(const uint8_t *& buf) + * { + * CHIP_ERROR err = CHIP_NO_ERROR; + * + * buf = (uint8_t *)malloc(1024); + * VerifyOrExitWithMetric(kMetricKey, buf != NULL, err = CHIP_ERROR_NO_MEMORY); + * + * memset(buf, 0, 1024); + * + * exit: + * return err; + * } + * @endcode + * + * @param[in] kMetricKey Metric key for the metric event to be emitted + * if the aCondition evaluates to false. The value + * for the metric is result of the expression anAction. + * @param[in] aCondition A Boolean expression to be evaluated. + * @param[in] anAction An expression or block to execute when the + * assertion fails. + */ +#define VerifyOrExitWithMetric(kMetricKey, aCondition, anAction) \ + nlEXPECT_ACTION(aCondition, exit, MATTER_LOG_METRIC((kMetricKey), (anAction))) + +/* + * Utility Macros to support optional arguments for MATTER_LOG_METRIC_XYZ macros + */ + +// Utility to always return the 4th argument from macro parameters +#define __GET_4TH_ARG(_a1, _a2, _a3, _a4, ...) _a4 + +// Utility macro to select the macro with the correct signature based on the invoked MATTER_LOG_METRIC_XYZ macro +#define __SELECT_MACRO_FOR_EVENT_METRIC(...) \ + __GET_4TH_ARG(__VA_ARGS__, __MATTER_LOG_METRIC_3ARGS, __MATTER_LOG_METRIC_2ARGS, __MATTER_LOG_METRIC_1ARGS, ) + +// Wrapper to capture all arguments and invoke the real wrapper for logging metrics +#define __MATTER_LOG_METRIC(...) __SELECT_MACRO_FOR_EVENT_METRIC(__VA_ARGS__)(__VA_ARGS__) + +// Wrapper macro that accepts metric key and logs and instant event +#define __MATTER_LOG_METRIC_1ARGS(key) \ + do \ + { \ + using Type = chip::Tracing::MetricEvent::Type; \ + ::chip::Tracing::MetricEvent _metric_event(Type::kInstantEvent, key); \ + ::chip::Tracing::Internal::LogMetricEvent(_metric_event); \ + } while (false) + +// Wrapper macro that accepts metric type and key and logs an event corresponding to the type +#define __MATTER_LOG_METRIC_2ARGS(type, key) \ + do \ + { \ + ::chip::Tracing::MetricEvent _metric_event(type, key); \ + ::chip::Tracing::Internal::LogMetricEvent(_metric_event); \ + } while (false) + +// Wrapper macro that accepts metric type, key and value and logs the corresponding event +#define __MATTER_LOG_METRIC_3ARGS(type, key, value) \ + do \ + { \ + ::chip::Tracing::MetricEvent _metric_event(type, key, value); \ + ::chip::Tracing::Internal::LogMetricEvent(_metric_event); \ + } while (false) + +//////////////////////// +// Metric logging macros +//////////////////////// + +/** + * @def MATTER_LOG_METRIC + * + * @brief + * When tracing is enabled, this macro generates a metric event and logs it to the tracing backend. + * + * Example usage: + * @code + * MATTER_LOG_METRIC(chip::Tracing::kMetricPASESession, err); + * @endcode + * The above example generates an instant metric event with key kMetricPASESession. + * The metric also holds the 32 bit value corresponding to the ChipError object 'err'. + * + * @param[in] key The key representing the metric name/event. + * + * @param[in] value An optional value for the metric. This value corresponds to one of the values supported + * in MetricEvent::Value + */ +#define MATTER_LOG_METRIC(key, ...) __MATTER_LOG_METRIC(chip::Tracing::MetricEvent::Type::kInstantEvent, key, ##__VA_ARGS__) + +/** + * @def MATTER_LOG_METRIC_BEGIN + * + * @brief + * Generate a metric with the Begin Type + * + * Example usage: + * @code + * MATTER_LOG_METRIC_BEGIN(chip::Tracing::kMetricPASESession); + * @endcode + * The above example generates a Begin metric event with key kMetricPASESession. + * + * @param[in] key The key representing the metric name/event. + */ +#define MATTER_LOG_METRIC_BEGIN(key) __MATTER_LOG_METRIC(chip::Tracing::MetricEvent::Type::kBeginEvent, key) + +/** + * @def MATTER_LOG_METRIC_END + * + * @brief + * Generate a metric with the End Type + * + * Example usage: + * @code + * MATTER_LOG_METRIC_END(chip::Tracing::kMetricPASESession); + * @endcode + * The above example generates an End metric event with key kMetricPASESession. + * + * @param[in] key The key representing the metric name/event. + * + * @param[in] value An optional value for the metric. This value corresponds to one of the values supported + * in MetricEvent::Value + */ +#define MATTER_LOG_METRIC_END(key, ...) __MATTER_LOG_METRIC(chip::Tracing::MetricEvent::Type::kEndEvent, key, ##__VA_ARGS__) + +/** + * @def MATTER_LOG_METRIC_SCOPE + * + * @brief + * Generate a scoped metric tracking Begin and End within a given scope. + * + * Example usage: + * @code + * MATTER_LOG_METRIC_SCOPE(chip::Tracing::kMetricPASESession); + * @endcode + * The above example generates an Begin and the End metric using RAII. + * + * @param[in] key The key representing the metric name/event. + * @param[in] error Reference to a ChipError object that is used as the value of the End event. + */ +#define MATTER_LOG_METRIC_SCOPE(key, error) \ + ::chip::Tracing::ScopedMetricEvent __LOG_METRIC_MACRO_CONCAT(_metric_scope, __COUNTER__)(key, error) + +#else // Tracing is disabled + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Remap Success, Return, and Verify macros to the ones without metrics +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +#define SuccessOrExitWithMetric(kMetricKey, aStatus) SuccessOrExit(aStatus) + +#define VerifyOrExitWithMetric(kMetricKey, aCondition, anAction) VerifyOrExit(aCondition, anAction) + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Map all MATTER_LOG_METRIC_XYZ macros to noops +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +#define __MATTER_LOG_METRIC_DISABLE(...) \ + do \ + { \ + } while (false) + +#define MATTER_LOG_METRIC(...) __MATTER_LOG_METRIC_DISABLE(__VA_ARGS__) +#define MATTER_LOG_METRIC_BEGIN(...) __MATTER_LOG_METRIC_DISABLE(__VA_ARGS__) +#define MATTER_LOG_METRIC_END(...) __MATTER_LOG_METRIC_DISABLE(__VA_ARGS__) +#define MATTER_LOG_METRIC_SCOPE(...) __MATTER_LOG_METRIC_DISABLE(__VA_ARGS__) + +#endif // MATTER_TRACING_ENABLED diff --git a/src/tracing/multiplexed/include/matter/tracing/macros_impl.h b/src/tracing/multiplexed/include/matter/tracing/macros_impl.h index eda5f2ed5142a4..8b3e728289dc1d 100644 --- a/src/tracing/multiplexed/include/matter/tracing/macros_impl.h +++ b/src/tracing/multiplexed/include/matter/tracing/macros_impl.h @@ -29,7 +29,6 @@ #define MATTER_TRACE_END(label, group) ::chip::Tracing::Internal::End(label, group) #define MATTER_TRACE_INSTANT(label, group) ::chip::Tracing::Internal::Instant(label, group) #define MATTER_TRACE_COUNTER(label) ::chip::Tracing::Internal::Counter(label) -#define MATTER_TRACE_METRIC(label, value) ::chip::Tracing::Internal::Metric(label, value) namespace chip { namespace Tracing { diff --git a/src/tracing/none/include/matter/tracing/macros_impl.h b/src/tracing/none/include/matter/tracing/macros_impl.h index 1fc940683d75e2..3119dce2a2b49f 100644 --- a/src/tracing/none/include/matter/tracing/macros_impl.h +++ b/src/tracing/none/include/matter/tracing/macros_impl.h @@ -32,4 +32,3 @@ #define MATTER_TRACE_INSTANT(...) _MATTER_TRACE_DISABLE(__VA_ARGS__) #define MATTER_TRACE_SCOPE(...) _MATTER_TRACE_DISABLE(__VA_ARGS__) #define MATTER_TRACE_COUNTER(...) _MATTER_TRACE_DISABLE(__VA_ARGS__) -#define MATTER_TRACE_METRIC(...) _MATTER_TRACE_DISABLE(__VA_ARGS__) diff --git a/src/tracing/perfetto/include/matter/tracing/macros_impl.h b/src/tracing/perfetto/include/matter/tracing/macros_impl.h index 559e877db1fe11..9b05d2f3539a45 100644 --- a/src/tracing/perfetto/include/matter/tracing/macros_impl.h +++ b/src/tracing/perfetto/include/matter/tracing/macros_impl.h @@ -37,5 +37,3 @@ PERFETTO_DEFINE_CATEGORIES(perfetto::Category("Matter").SetDescription("Matter t static int count##_label = 0; \ TRACE_COUNTER("Matter", label, ++count##_label); \ } while (0) - -#define MATTER_TRACE_METRIC(label, value) TRACE_COUNTER("Matter", label, value) diff --git a/src/tracing/perfetto/perfetto_tracing.cpp b/src/tracing/perfetto/perfetto_tracing.cpp index b68ec33d33101d..f9b00cc7ad96d3 100644 --- a/src/tracing/perfetto/perfetto_tracing.cpp +++ b/src/tracing/perfetto/perfetto_tracing.cpp @@ -16,6 +16,7 @@ * limitations under the License. */ +#include #include #include @@ -126,6 +127,29 @@ void PerfettoBackend::LogNodeDiscoveryFailed(NodeDiscoveryFailedInfo & info) ); } +void PerfettoBackend::LogMetricEvent(const MetricEvent & event) +{ + using ValueType = MetricEvent::Value::Type; + switch (event.ValueType()) + { + case ValueType::kInt32: + TRACE_EVENT_INSTANT("Matter", event.key(), "value", event.ValueInt32()); + break; + case ValueType::kUInt32: + TRACE_EVENT_INSTANT("Matter", event.key(), "value", event.ValueUInt32()); + break; + case ValueType::kChipErrorCode: + TRACE_EVENT_INSTANT("Matter", event.key(), "error", event.ValueErrorCode()); + break; + case ValueType::kUndefined: + TRACE_EVENT_INSTANT("Matter", event.key()); + break; + default: + TRACE_EVENT_INSTANT("Matter", event.key(), "type", "UNKNOWN"); + break; + } +} + } // namespace Perfetto } // namespace Tracing } // namespace chip diff --git a/src/tracing/perfetto/perfetto_tracing.h b/src/tracing/perfetto/perfetto_tracing.h index 901165e35a548d..05fee4b49934de 100644 --- a/src/tracing/perfetto/perfetto_tracing.h +++ b/src/tracing/perfetto/perfetto_tracing.h @@ -44,6 +44,7 @@ class PerfettoBackend : public ::chip::Tracing::Backend void LogNodeLookup(NodeLookupInfo &) override; void LogNodeDiscovered(NodeDiscoveredInfo &) override; void LogNodeDiscoveryFailed(NodeDiscoveryFailedInfo &) override; + void LogMetricEvent(const MetricEvent &) override; }; } // namespace Perfetto diff --git a/src/tracing/registry.cpp b/src/tracing/registry.cpp index ee46b542e7f5f2..a4fcdbe81c650f 100644 --- a/src/tracing/registry.cpp +++ b/src/tracing/registry.cpp @@ -84,14 +84,6 @@ void Counter(const char * label) } } -void Metric(const char * label, int32_t value) -{ - for (auto & backend : gTracingBackends) - { - backend.TraceMetric(label, value); - } -} - void LogMessageSend(::chip::Tracing::MessageSendInfo & info) { for (auto & backend : gTracingBackends) @@ -132,6 +124,14 @@ void LogNodeDiscoveryFailed(::chip::Tracing::NodeDiscoveryFailedInfo & info) } } +void LogMetricEvent(const ::chip::Tracing::MetricEvent & event) +{ + for (auto & backend : gTracingBackends) + { + backend.LogMetricEvent(event); + } +} + } // namespace Internal #endif // MATTTER_TRACING_ENABLED diff --git a/src/tracing/registry.h b/src/tracing/registry.h index 5f3b3c1a6cea84..7d14522c56e708 100644 --- a/src/tracing/registry.h +++ b/src/tracing/registry.h @@ -77,13 +77,13 @@ void Begin(const char * label, const char * group); void End(const char * label, const char * group); void Instant(const char * label, const char * group); void Counter(const char * label); -void Metric(const char * label, int32_t value); void LogMessageSend(::chip::Tracing::MessageSendInfo & info); void LogMessageReceived(::chip::Tracing::MessageReceivedInfo & info); void LogNodeLookup(::chip::Tracing::NodeLookupInfo & info); void LogNodeDiscovered(::chip::Tracing::NodeDiscoveredInfo & info); void LogNodeDiscoveryFailed(::chip::Tracing::NodeDiscoveryFailedInfo & info); +void LogMetricEvent(const ::chip::Tracing::MetricEvent & event); } // namespace Internal diff --git a/src/tracing/tracing_args.gni b/src/tracing/tracing_args.gni index d3741b5eba5f10..d6ddb1fd2e99b8 100644 --- a/src/tracing/tracing_args.gni +++ b/src/tracing/tracing_args.gni @@ -23,7 +23,8 @@ declare_args() { # # Additionally, if tracing is enabled, the main() function has to add # backends explicitly - matter_enable_tracing_support = current_os == "android" + matter_enable_tracing_support = + current_os == "android" || chip_device_platform == "darwin" # Defines the trace backend. Current matter tracing splits the logic # into two parts: @@ -46,6 +47,8 @@ declare_args() { # if (current_os == "linux" || current_os == "android") { matter_trace_config = "${chip_root}/src/tracing/perfetto:perfetto_tracing" + } else if (chip_device_platform == "darwin") { + matter_trace_config = "${chip_root}/src/tracing/darwin:darwin_tracing" } else { matter_trace_config = "${chip_root}/src/tracing/none" } From 6a0a0569b1d8c90e737348b6190f26764e494e9d Mon Sep 17 00:00:00 2001 From: Junior Martinez <67972863+jmartinez-silabs@users.noreply.github.com> Date: Mon, 26 Feb 2024 08:53:11 -0500 Subject: [PATCH 083/385] Adjust the default discovery timeout when BLE extend announcement is enabled. (#32300) * add build arg to enable BLE extended advertisement feature * Set a increased based value for the Discovery timeout when BLE extended advertising is set --- src/include/platform/CHIPDeviceConfig.h | 13 ++++++++++++- src/platform/silabs/CHIPDevicePlatformConfig.h | 2 ++ third_party/silabs/efr32_sdk.gni | 4 ++++ 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/include/platform/CHIPDeviceConfig.h b/src/include/platform/CHIPDeviceConfig.h index 88ef78d1005314..9d1f7804da63b4 100644 --- a/src/include/platform/CHIPDeviceConfig.h +++ b/src/include/platform/CHIPDeviceConfig.h @@ -713,8 +713,19 @@ static_assert(CHIP_DEVICE_CONFIG_BLE_EXT_ADVERTISING_INTERVAL_MIN <= CHIP_DEVICE * Time in seconds that a factory new device will advertise commissionable node discovery. */ #ifndef CHIP_DEVICE_CONFIG_DISCOVERY_TIMEOUT_SECS +#if CHIP_DEVICE_CONFIG_BLE_EXT_ADVERTISING +/** + * By default, the extended announcement, when enabled, starts its extended advertising 15 mins + * after the standard slow advertisement. Time at which the default discovery time would close the + * commissioning window and stop the BLE. + * Therefore, when CHIP_DEVICE_CONFIG_BLE_EXT_ADVERTISING is enabled bump the default Discovery timeout + * to the maximum allowed by the spec. 48h. + */ +#define CHIP_DEVICE_CONFIG_DISCOVERY_TIMEOUT_SECS (60 * 60 * 48) +#else #define CHIP_DEVICE_CONFIG_DISCOVERY_TIMEOUT_SECS (15 * 60) -#endif +#endif // CHIP_DEVICE_CONFIG_BLE_EXT_ADVERTISING +#endif // CHIP_DEVICE_CONFIG_DISCOVERY_TIMEOUT_SECS /** * CHIP_DEVICE_CONFIG_MAX_DISCOVERED_NODES diff --git a/src/platform/silabs/CHIPDevicePlatformConfig.h b/src/platform/silabs/CHIPDevicePlatformConfig.h index fa3a50974f6a50..e8601e5feedaf9 100644 --- a/src/platform/silabs/CHIPDevicePlatformConfig.h +++ b/src/platform/silabs/CHIPDevicePlatformConfig.h @@ -140,6 +140,8 @@ #define CHIP_DEVICE_CONFIG_MAX_EVENT_QUEUE_SIZE 25 +#define CHIP_DEVICE_CONFIG_BLE_EXT_ADVERTISING SL_MATTER_BLE_EXTENDED_ADV + /* ICD Configuration Defines */ diff --git a/third_party/silabs/efr32_sdk.gni b/third_party/silabs/efr32_sdk.gni index 8510295bf7c2e0..55934ae5128b0f 100644 --- a/third_party/silabs/efr32_sdk.gni +++ b/third_party/silabs/efr32_sdk.gni @@ -46,6 +46,9 @@ declare_args() { # Enable Segger System View use_system_view = false + # Enable the BLE extended advertisement + sl_matter_ble_extended_adv = false + # ICD Openthread Configuration flags sl_ot_idle_interval_ms = 15000 # 15s Idle Intervals sl_ot_active_interval_ms = 200 # 200ms Active Intervals @@ -297,6 +300,7 @@ template("efr32_sdk") { "SL_RAIL_LIB_MULTIPROTOCOL_SUPPORT=1", "SL_RAIL_UTIL_PA_CONFIG_HEADER=", "RADIO_CONFIG_DMP_SUPPORT=1", + "SL_MATTER_BLE_EXTENDED_ADV=${sl_matter_ble_extended_adv}", #"__STACK_SIZE=0", ] From 3799c4192ce20100264e399f8b64f8d58c8b3d4f Mon Sep 17 00:00:00 2001 From: lpbeliveau-silabs <112982107+lpbeliveau-silabs@users.noreply.github.com> Date: Mon, 26 Feb 2024 10:11:48 -0500 Subject: [PATCH 084/385] [ICD] StayActiveRequest (#32247) * Implementation of StayActive request with test * Regenerated zap files * Added StayActiveRequest scenarios to the yaml test * Co-authored-by: Boris Zbarsky Applied comments about #if and clarifying maximum guaranteed stay active * Added the #if back for platforms that build the icd-management-server cluster without being ICD devices * Applied suggestions --- .../nxp/zap-lit/contact-sensor-app.matter | 6 +- .../nxp/zap-sit/contact-sensor-app.matter | 6 +- .../light-switch-app.matter | 6 +- .../light-switch-app/qpg/zap/switch.matter | 6 +- .../lit-icd-common/lit-icd-server-app.matter | 6 +- examples/lock-app/lock-common/lock-app.matter | 6 +- examples/lock-app/lock-common/lock-app.zap | 9 ++- examples/lock-app/qpg/zap/lock.matter | 6 +- .../smoke-co-alarm-app.matter | 6 +- examples/window-app/common/window-app.matter | 6 +- .../icd-management-server.cpp | 20 ++--- .../icd-management-server.h | 2 - src/app/icd/server/ICDConfigurationData.h | 5 ++ src/app/icd/server/ICDManager.cpp | 46 +++++++---- src/app/icd/server/ICDManager.h | 14 ++++ src/app/icd/server/ICDNotifier.h | 3 +- src/app/tests/TestICDManager.cpp | 78 ++++++++++++++++++ .../suites/TestIcdManagementCluster.yaml | 79 +++++++++++++++++++ .../chip/icd-management-cluster.xml | 1 + .../data_model/controller-clusters.matter | 6 +- .../chip/devicecontroller/ChipClusters.java | 10 ++- .../devicecontroller/ClusterIDMapping.java | 17 ++++ .../devicecontroller/ClusterInfoMapping.java | 6 ++ .../cluster/clusters/IcdManagementCluster.kt | 8 +- .../python/chip/clusters/CHIPClusters.py | 1 + .../python/chip/clusters/Objects.py | 3 + .../CHIP/zap-generated/MTRBaseClusters.h | 4 +- .../CHIP/zap-generated/MTRBaseClusters.mm | 6 +- .../CHIP/zap-generated/MTRClusters.h | 4 +- .../CHIP/zap-generated/MTRClusters.mm | 6 +- .../zap-generated/MTRCommandPayloadsObjc.h | 2 + .../zap-generated/MTRCommandPayloadsObjc.mm | 8 +- src/system/SystemLayer.h | 14 ++++ src/system/SystemLayerImplFreeRTOS.cpp | 5 ++ src/system/SystemLayerImplFreeRTOS.h | 1 + src/system/SystemLayerImplSelect.cpp | 5 ++ src/system/SystemLayerImplSelect.h | 1 + .../zap-generated/cluster-objects.cpp | 14 ++++ .../zap-generated/cluster-objects.h | 4 + .../zap-generated/cluster/Commands.h | 1 + .../zap-generated/cluster/Commands.h | 7 ++ 41 files changed, 377 insertions(+), 67 deletions(-) diff --git a/examples/contact-sensor-app/nxp/zap-lit/contact-sensor-app.matter b/examples/contact-sensor-app/nxp/zap-lit/contact-sensor-app.matter index 9a6eeb77ef10f2..fa6101b2586a63 100644 --- a/examples/contact-sensor-app/nxp/zap-lit/contact-sensor-app.matter +++ b/examples/contact-sensor-app/nxp/zap-lit/contact-sensor-app.matter @@ -1337,6 +1337,10 @@ cluster IcdManagement = 70 { optional octet_string<16> verificationKey = 1; } + request struct StayActiveRequestRequest { + int32u stayActiveDuration = 0; + } + response struct StayActiveResponse = 4 { int32u promisedActiveDuration = 0; } @@ -1346,7 +1350,7 @@ cluster IcdManagement = 70 { /** Unregister a client from an end device */ fabric command access(invoke: manage) UnregisterClient(UnregisterClientRequest): DefaultSuccess = 2; /** Request the end device to stay in Active Mode for an additional ActiveModeThreshold */ - command access(invoke: manage) StayActiveRequest(): StayActiveResponse = 3; + command access(invoke: manage) StayActiveRequest(StayActiveRequestRequest): StayActiveResponse = 3; } endpoint 0 { diff --git a/examples/contact-sensor-app/nxp/zap-sit/contact-sensor-app.matter b/examples/contact-sensor-app/nxp/zap-sit/contact-sensor-app.matter index 479f8baa86284c..f82f6a9ea079d4 100644 --- a/examples/contact-sensor-app/nxp/zap-sit/contact-sensor-app.matter +++ b/examples/contact-sensor-app/nxp/zap-sit/contact-sensor-app.matter @@ -1337,6 +1337,10 @@ cluster IcdManagement = 70 { optional octet_string<16> verificationKey = 1; } + request struct StayActiveRequestRequest { + int32u stayActiveDuration = 0; + } + response struct StayActiveResponse = 4 { int32u promisedActiveDuration = 0; } @@ -1346,7 +1350,7 @@ cluster IcdManagement = 70 { /** Unregister a client from an end device */ fabric command access(invoke: manage) UnregisterClient(UnregisterClientRequest): DefaultSuccess = 2; /** Request the end device to stay in Active Mode for an additional ActiveModeThreshold */ - command access(invoke: manage) StayActiveRequest(): StayActiveResponse = 3; + command access(invoke: manage) StayActiveRequest(StayActiveRequestRequest): StayActiveResponse = 3; } endpoint 0 { diff --git a/examples/light-switch-app/light-switch-common/light-switch-app.matter b/examples/light-switch-app/light-switch-common/light-switch-app.matter index 90e60581be27da..b96bf908f766ab 100644 --- a/examples/light-switch-app/light-switch-common/light-switch-app.matter +++ b/examples/light-switch-app/light-switch-common/light-switch-app.matter @@ -2007,6 +2007,10 @@ cluster IcdManagement = 70 { optional octet_string<16> verificationKey = 1; } + request struct StayActiveRequestRequest { + int32u stayActiveDuration = 0; + } + response struct StayActiveResponse = 4 { int32u promisedActiveDuration = 0; } @@ -2016,7 +2020,7 @@ cluster IcdManagement = 70 { /** Unregister a client from an end device */ fabric command access(invoke: manage) UnregisterClient(UnregisterClientRequest): DefaultSuccess = 2; /** Request the end device to stay in Active Mode for an additional ActiveModeThreshold */ - command access(invoke: manage) StayActiveRequest(): StayActiveResponse = 3; + command access(invoke: manage) StayActiveRequest(StayActiveRequestRequest): StayActiveResponse = 3; } /** Attributes and commands for scene configuration and manipulation. */ diff --git a/examples/light-switch-app/qpg/zap/switch.matter b/examples/light-switch-app/qpg/zap/switch.matter index b7f217d7221b27..0475721b798fe9 100644 --- a/examples/light-switch-app/qpg/zap/switch.matter +++ b/examples/light-switch-app/qpg/zap/switch.matter @@ -1804,6 +1804,10 @@ cluster IcdManagement = 70 { optional octet_string<16> verificationKey = 1; } + request struct StayActiveRequestRequest { + int32u stayActiveDuration = 0; + } + response struct StayActiveResponse = 4 { int32u promisedActiveDuration = 0; } @@ -1813,7 +1817,7 @@ cluster IcdManagement = 70 { /** Unregister a client from an end device */ fabric command access(invoke: manage) UnregisterClient(UnregisterClientRequest): DefaultSuccess = 2; /** Request the end device to stay in Active Mode for an additional ActiveModeThreshold */ - command access(invoke: manage) StayActiveRequest(): StayActiveResponse = 3; + command access(invoke: manage) StayActiveRequest(StayActiveRequestRequest): StayActiveResponse = 3; } /** Attributes and commands for scene configuration and manipulation. */ diff --git a/examples/lit-icd-app/lit-icd-common/lit-icd-server-app.matter b/examples/lit-icd-app/lit-icd-common/lit-icd-server-app.matter index db80008fef240c..d4b7f3faa245db 100644 --- a/examples/lit-icd-app/lit-icd-common/lit-icd-server-app.matter +++ b/examples/lit-icd-app/lit-icd-common/lit-icd-server-app.matter @@ -1465,6 +1465,10 @@ cluster IcdManagement = 70 { optional octet_string<16> verificationKey = 1; } + request struct StayActiveRequestRequest { + int32u stayActiveDuration = 0; + } + response struct StayActiveResponse = 4 { int32u promisedActiveDuration = 0; } @@ -1474,7 +1478,7 @@ cluster IcdManagement = 70 { /** Unregister a client from an end device */ fabric command access(invoke: manage) UnregisterClient(UnregisterClientRequest): DefaultSuccess = 2; /** Request the end device to stay in Active Mode for an additional ActiveModeThreshold */ - command access(invoke: manage) StayActiveRequest(): StayActiveResponse = 3; + command access(invoke: manage) StayActiveRequest(StayActiveRequestRequest): StayActiveResponse = 3; } endpoint 0 { diff --git a/examples/lock-app/lock-common/lock-app.matter b/examples/lock-app/lock-common/lock-app.matter index f07b85cfe6de45..1b34782e4ea180 100644 --- a/examples/lock-app/lock-common/lock-app.matter +++ b/examples/lock-app/lock-common/lock-app.matter @@ -1825,6 +1825,10 @@ cluster IcdManagement = 70 { optional octet_string<16> verificationKey = 1; } + request struct StayActiveRequestRequest { + int32u stayActiveDuration = 0; + } + response struct StayActiveResponse = 4 { int32u promisedActiveDuration = 0; } @@ -1834,7 +1838,7 @@ cluster IcdManagement = 70 { /** Unregister a client from an end device */ fabric command access(invoke: manage) UnregisterClient(UnregisterClientRequest): DefaultSuccess = 2; /** Request the end device to stay in Active Mode for an additional ActiveModeThreshold */ - command access(invoke: manage) StayActiveRequest(): StayActiveResponse = 3; + command access(invoke: manage) StayActiveRequest(StayActiveRequestRequest): StayActiveResponse = 3; } /** An interface to a generic way to secure a door */ diff --git a/examples/lock-app/lock-common/lock-app.zap b/examples/lock-app/lock-common/lock-app.zap index c5201e7a6fbb0c..8ec233c5250e71 100644 --- a/examples/lock-app/lock-common/lock-app.zap +++ b/examples/lock-app/lock-common/lock-app.zap @@ -2412,10 +2412,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, @@ -2428,10 +2428,10 @@ "side": "server", "type": "int16u", "included": 1, - "storageOption": "RAM", + "storageOption": "External", "singleton": 0, "bounded": 0, - "defaultValue": "0x0002", + "defaultValue": null, "reportable": 1, "minInterval": 0, "maxInterval": 65344, @@ -4939,6 +4939,7 @@ "define": "ICD_MANAGEMENT_CLUSTER", "side": "server", "enabled": 1, + "commands": [], "attributes": [ { "name": "IdleModeDuration", diff --git a/examples/lock-app/qpg/zap/lock.matter b/examples/lock-app/qpg/zap/lock.matter index 91ff76970813f1..9815defa7f8cef 100644 --- a/examples/lock-app/qpg/zap/lock.matter +++ b/examples/lock-app/qpg/zap/lock.matter @@ -1481,6 +1481,10 @@ cluster IcdManagement = 70 { optional octet_string<16> verificationKey = 1; } + request struct StayActiveRequestRequest { + int32u stayActiveDuration = 0; + } + response struct StayActiveResponse = 4 { int32u promisedActiveDuration = 0; } @@ -1490,7 +1494,7 @@ cluster IcdManagement = 70 { /** Unregister a client from an end device */ fabric command access(invoke: manage) UnregisterClient(UnregisterClientRequest): DefaultSuccess = 2; /** Request the end device to stay in Active Mode for an additional ActiveModeThreshold */ - command access(invoke: manage) StayActiveRequest(): StayActiveResponse = 3; + command access(invoke: manage) StayActiveRequest(StayActiveRequestRequest): StayActiveResponse = 3; } /** An interface to a generic way to secure a door */ diff --git a/examples/smoke-co-alarm-app/smoke-co-alarm-common/smoke-co-alarm-app.matter b/examples/smoke-co-alarm-app/smoke-co-alarm-common/smoke-co-alarm-app.matter index 6c1938c578ea27..f3188350035291 100644 --- a/examples/smoke-co-alarm-app/smoke-co-alarm-common/smoke-co-alarm-app.matter +++ b/examples/smoke-co-alarm-app/smoke-co-alarm-common/smoke-co-alarm-app.matter @@ -1801,6 +1801,10 @@ cluster IcdManagement = 70 { optional octet_string<16> verificationKey = 1; } + request struct StayActiveRequestRequest { + int32u stayActiveDuration = 0; + } + response struct StayActiveResponse = 4 { int32u promisedActiveDuration = 0; } @@ -1810,7 +1814,7 @@ cluster IcdManagement = 70 { /** Unregister a client from an end device */ fabric command access(invoke: manage) UnregisterClient(UnregisterClientRequest): DefaultSuccess = 2; /** Request the end device to stay in Active Mode for an additional ActiveModeThreshold */ - command access(invoke: manage) StayActiveRequest(): StayActiveResponse = 3; + command access(invoke: manage) StayActiveRequest(StayActiveRequestRequest): StayActiveResponse = 3; } /** This cluster provides an interface for observing and managing the state of smoke and CO alarms. */ diff --git a/examples/window-app/common/window-app.matter b/examples/window-app/common/window-app.matter index 7e0053fd83ee39..7f1b3d34943911 100644 --- a/examples/window-app/common/window-app.matter +++ b/examples/window-app/common/window-app.matter @@ -1899,6 +1899,10 @@ cluster IcdManagement = 70 { optional octet_string<16> verificationKey = 1; } + request struct StayActiveRequestRequest { + int32u stayActiveDuration = 0; + } + response struct StayActiveResponse = 4 { int32u promisedActiveDuration = 0; } @@ -1908,7 +1912,7 @@ cluster IcdManagement = 70 { /** Unregister a client from an end device */ fabric command access(invoke: manage) UnregisterClient(UnregisterClientRequest): DefaultSuccess = 2; /** Request the end device to stay in Active Mode for an additional ActiveModeThreshold */ - command access(invoke: manage) StayActiveRequest(): StayActiveResponse = 3; + command access(invoke: manage) StayActiveRequest(StayActiveRequestRequest): StayActiveResponse = 3; } /** Provides an interface for controlling and adjusting automatic window coverings. */ diff --git a/src/app/clusters/icd-management-server/icd-management-server.cpp b/src/app/clusters/icd-management-server/icd-management-server.cpp index 27ecfe778a33bb..0f71345a38d0f1 100644 --- a/src/app/clusters/icd-management-server/icd-management-server.cpp +++ b/src/app/clusters/icd-management-server/icd-management-server.cpp @@ -364,14 +364,6 @@ void ICDManagementServer::TriggerICDMTableUpdatedEvent() #endif // CHIP_CONFIG_ENABLE_ICD_CIP -Status ICDManagementServer::StayActiveRequest(FabricIndex fabricIndex) -{ - // TODO: Implementent stay awake logic for end device - // https://github.com/project-chip/connectedhomeip/issues/24259 - ICDNotifier::GetInstance().NotifyICDManagementEvent(ICDListener::ICDManagementEvents::kStayActiveRequestReceived); - return InteractionModel::Status::UnsupportedCommand; -} - void ICDManagementServer::Init(PersistentStorageDelegate & storage, Crypto::SymmetricKeystore * symmetricKeystore, ICDConfigurationData & icdConfigurationData) { @@ -433,10 +425,14 @@ bool emberAfIcdManagementClusterUnregisterClientCallback(CommandHandler * comman bool emberAfIcdManagementClusterStayActiveRequestCallback(CommandHandler * commandObj, const ConcreteCommandPath & commandPath, const Commands::StayActiveRequest::DecodableType & commandData) { - ICDManagementServer server; - InteractionModel::Status status = server.StayActiveRequest(commandObj->GetAccessingFabricIndex()); - - commandObj->AddStatus(commandPath, status); +// Note: We only need this #if statement for platform examples that enable the ICD management server without building the sample +// as an ICD. Since this is not spec compliant, we should remove this #if statement once we stop compiling the ICD management +// server in those examples. +#if CHIP_CONFIG_ENABLE_ICD_SERVER + IcdManagement::Commands::StayActiveResponse::Type response; + response.promisedActiveDuration = Server::GetInstance().GetICDManager().StayActiveRequest(commandData.stayActiveDuration); + commandObj->AddResponse(commandPath, response); +#endif // CHIP_CONFIG_ENABLE_ICD_SERVER return true; } diff --git a/src/app/clusters/icd-management-server/icd-management-server.h b/src/app/clusters/icd-management-server/icd-management-server.h index 4462cb96d9c9f2..5c6b838fa9b527 100644 --- a/src/app/clusters/icd-management-server/icd-management-server.h +++ b/src/app/clusters/icd-management-server/icd-management-server.h @@ -68,8 +68,6 @@ class ICDManagementServer const chip::app::Clusters::IcdManagement::Commands::UnregisterClient::DecodableType & commandData); #endif // CHIP_CONFIG_ENABLE_ICD_CIP - chip::Protocols::InteractionModel::Status StayActiveRequest(chip::FabricIndex fabricIndex); - private: #if CHIP_CONFIG_ENABLE_ICD_CIP /** diff --git a/src/app/icd/server/ICDConfigurationData.h b/src/app/icd/server/ICDConfigurationData.h index 3fb3e9a92d2304..8b87d090f769e1 100644 --- a/src/app/icd/server/ICDConfigurationData.h +++ b/src/app/icd/server/ICDConfigurationData.h @@ -61,6 +61,8 @@ class ICDConfigurationData System::Clock::Milliseconds16 GetActiveModeThreshold() { return mActiveThreshold; } + System::Clock::Milliseconds32 GetGuaranteedStayActiveDuration() { return kGuaranteedStayActiveDuration; } + Protocols::SecureChannel::CheckInCounter & GetICDCounter() { return mICDCounter; } uint16_t GetClientsSupportedPerFabric() { return mFabricClientsSupported; } @@ -123,6 +125,9 @@ class ICDConfigurationData static constexpr System::Clock::Seconds32 kMaxIdleModeDuration = System::Clock::Seconds32(18 * kSecondsPerHour); static constexpr System::Clock::Seconds32 kMinIdleModeDuration = System::Clock::Seconds32(1); + // As defined in the spec, the maximum guaranteed duration for the StayActiveDuration is 30s "Matter Application + // Clusters: 9.17.7.5.1. PromisedActiveDuration Field" + static constexpr System::Clock::Milliseconds32 kGuaranteedStayActiveDuration = System::Clock::Milliseconds32(30000); static_assert((CHIP_CONFIG_ICD_IDLE_MODE_DURATION_SEC) <= kMaxIdleModeDuration.count(), "Spec requires the IdleModeDuration to be equal or inferior to 64800s."); diff --git a/src/app/icd/server/ICDManager.cpp b/src/app/icd/server/ICDManager.cpp index 057cc089e9624f..931737783dde9f 100644 --- a/src/app/icd/server/ICDManager.cpp +++ b/src/app/icd/server/ICDManager.cpp @@ -120,6 +120,22 @@ bool ICDManager::SupportsFeature(Feature feature) #endif // !CONFIG_BUILD_FOR_HOST_UNIT_TEST } +uint32_t ICDManager::StayActiveRequest(uint32_t stayActiveDuration) +{ + // This should only be called when the device is in ActiveMode + VerifyOrReturnValue(mOperationalState == OperationalState::ActiveMode, 0); + + uint32_t promisedActiveDuration = + std::min(ICDConfigurationData::GetInstance().GetGuaranteedStayActiveDuration().count(), stayActiveDuration); + + // If the device is already in ActiveMode, we need to extend the active mode duration + // for whichever is smallest between 30000 milliseconds and stayActiveDuration, taking in account the remaining active time. + ExtendActiveMode(System::Clock::Milliseconds16(promisedActiveDuration)); + promisedActiveDuration = DeviceLayer::SystemLayer().GetRemainingTime(OnActiveModeDone, this).count(); + + return promisedActiveDuration; +} + #if CHIP_CONFIG_ENABLE_ICD_CIP void ICDManager::SendCheckInMsgs() { @@ -366,17 +382,7 @@ void ICDManager::UpdateOperationState(OperationalState state) } else { - Milliseconds16 activeModeThreshold = ICDConfigurationData::GetInstance().GetActiveModeThreshold(); - DeviceLayer::SystemLayer().ExtendTimerTo(activeModeThreshold, OnActiveModeDone, this); - - Milliseconds32 activeModeJitterThreshold = Milliseconds32(ICD_ACTIVE_TIME_JITTER_MS); - activeModeJitterThreshold = - (activeModeThreshold >= activeModeJitterThreshold) ? activeModeThreshold - activeModeJitterThreshold : kZero; - - if (!mTransitionToIdleCalled) - { - DeviceLayer::SystemLayer().ExtendTimerTo(activeModeJitterThreshold, OnTransitionToIdle, this); - } + ExtendActiveMode(ICDConfigurationData::GetInstance().GetActiveModeThreshold()); } } } @@ -521,11 +527,6 @@ void ICDManager::OnICDManagementServerEvent(ICDManagementEvents event) case ICDManagementEvents::kTableUpdated: this->UpdateICDMode(); break; - - case ICDManagementEvents::kStayActiveRequestReceived: - // TODO : Implement the StayActiveRequest - // https://github.com/project-chip/connectedhomeip/issues/24259 - break; default: break; } @@ -540,6 +541,19 @@ void ICDManager::OnSubscriptionReport() this->UpdateOperationState(OperationalState::ActiveMode); } +void ICDManager::ExtendActiveMode(Milliseconds16 extendDuration) +{ + DeviceLayer::SystemLayer().ExtendTimerTo(extendDuration, OnActiveModeDone, this); + + Milliseconds32 activeModeJitterThreshold = Milliseconds32(ICD_ACTIVE_TIME_JITTER_MS); + activeModeJitterThreshold = (extendDuration >= activeModeJitterThreshold) ? extendDuration - activeModeJitterThreshold : kZero; + + if (!mTransitionToIdleCalled) + { + DeviceLayer::SystemLayer().ExtendTimerTo(activeModeJitterThreshold, OnTransitionToIdle, this); + } +} + ICDManager::ObserverPointer * ICDManager::RegisterObserver(ICDStateObserver * observer) { return mStateObserverPool.CreateObject(observer); diff --git a/src/app/icd/server/ICDManager.h b/src/app/icd/server/ICDManager.h index 396e6be20d0606..5e391c1469143c 100644 --- a/src/app/icd/server/ICDManager.h +++ b/src/app/icd/server/ICDManager.h @@ -109,6 +109,14 @@ class ICDManager : public ICDListener void postObserverEvent(ObserverEventType event); OperationalState GetOperationalState() { return mOperationalState; } + /** + * @brief Ensures that the remaining Active Mode duration is at least the smaller of 30000 milliseconds and stayActiveDuration. + * + * @param stayActiveDuration The duration (in milliseconds) requested by the client to stay in Active Mode + * @return The duration (in milliseconds) the device will stay in Active Mode + */ + uint32_t StayActiveRequest(uint32_t stayActiveDuration); + #if CHIP_CONFIG_ENABLE_ICD_CIP void SendCheckInMsgs(); @@ -131,6 +139,12 @@ class ICDManager : public ICDListener void OnSubscriptionReport() override; protected: + /** + * @brief Hepler function that extends the Active Mode duration as well as the Active Mode Jitter timer for the transition to + * iddle mode. + */ + void ExtendActiveMode(System::Clock::Milliseconds16 extendDuration); + friend class TestICDManager; static void OnIdleModeDone(System::Layer * aLayer, void * appState); diff --git a/src/app/icd/server/ICDNotifier.h b/src/app/icd/server/ICDNotifier.h index 1223732e3fc05f..5db14503a296d7 100644 --- a/src/app/icd/server/ICDNotifier.h +++ b/src/app/icd/server/ICDNotifier.h @@ -48,8 +48,7 @@ class ICDListener enum class ICDManagementEvents : uint8_t { - kTableUpdated = 0x01, - kStayActiveRequestReceived = 0x02, + kTableUpdated = 0x01, }; using KeepActiveFlags = BitFlags; diff --git a/src/app/tests/TestICDManager.cpp b/src/app/tests/TestICDManager.cpp index da549ff5062f34..ba311f889989f8 100644 --- a/src/app/tests/TestICDManager.cpp +++ b/src/app/tests/TestICDManager.cpp @@ -540,6 +540,83 @@ class TestICDManager // After the init we should be in Idle mode NL_TEST_ASSERT(aSuite, ctx->mICDManager.mOperationalState == ICDManager::OperationalState::IdleMode); } + + /* Test that verifies the logic of the ICDManager when it receives a StayActiveRequest*/ + static void TestICDMStayActive(nlTestSuite * aSuite, void * aContext) + { + TestContext * ctx = static_cast(aContext); + ICDNotifier notifier = ICDNotifier::GetInstance(); + ICDConfigurationData & icdConfigData = ICDConfigurationData::GetInstance(); + + // Verify That ICDManager starts in Idle + NL_TEST_ASSERT(aSuite, ctx->mICDManager.mOperationalState == ICDManager::OperationalState::IdleMode); + + // Trigger a subscription report. Put the ICD manager into active mode. + notifier.NotifySubscriptionReport(); + NL_TEST_ASSERT(aSuite, ctx->mICDManager.mOperationalState == ICDManager::OperationalState::ActiveMode); + + // Advance time by the ActiveModeDuration - 1 + AdvanceClockAndRunEventLoop(ctx, icdConfigData.GetActiveModeDuration() - 1_ms32); + // Confirm ICD manager is in active mode + NL_TEST_ASSERT(aSuite, ctx->mICDManager.mOperationalState == ICDManager::OperationalState::ActiveMode); + + uint32_t stayActiveRequestedMs = 20000; + // Send a stay active request for 20 seconds + uint32_t stayActivePromisedMs = ctx->mICDManager.StayActiveRequest(stayActiveRequestedMs); + // confirm the promised time is the same as the requested time + NL_TEST_ASSERT(aSuite, stayActivePromisedMs == stayActiveRequestedMs); + + // Advance time by the duration of the stay stayActiveRequestedMs - 1 ms + AdvanceClockAndRunEventLoop(ctx, System::Clock::Milliseconds32(stayActiveRequestedMs) - 1_ms32); + // Confirm ICD manager is in active mode + NL_TEST_ASSERT(aSuite, ctx->mICDManager.mOperationalState == ICDManager::OperationalState::ActiveMode); + + // Advance time by 1ms and Confirm ICD manager is in idle mode + AdvanceClockAndRunEventLoop(ctx, 1_ms32); + NL_TEST_ASSERT(aSuite, ctx->mICDManager.mOperationalState == ICDManager::OperationalState::IdleMode); + + // Trigger a subscription report Put the ICD manager into active mode + notifier.NotifySubscriptionReport(); + NL_TEST_ASSERT(aSuite, ctx->mICDManager.mOperationalState == ICDManager::OperationalState::ActiveMode); + + // Advance time by the duration of the stay active request - 1 ms + AdvanceClockAndRunEventLoop(ctx, icdConfigData.GetActiveModeDuration() - 1_ms32); + stayActiveRequestedMs = 35000; + // Send a stay active request for 35 seconds, which is higher than the maximum stay active duration (30 seconds) + stayActivePromisedMs = ctx->mICDManager.StayActiveRequest(stayActiveRequestedMs); + // confirm the promised time is the maximum stay active duration (30 seconds) + NL_TEST_ASSERT(aSuite, stayActivePromisedMs == 30000); + + // Advance time by the duration of the max stay active duration - 1 ms + AdvanceClockAndRunEventLoop(ctx, System::Clock::Milliseconds32(30000) - 1_ms32); + NL_TEST_ASSERT(aSuite, ctx->mICDManager.mOperationalState == ICDManager::OperationalState::ActiveMode); + + // Advance time by 1ms and Confirm ICD manager is in idle mode + AdvanceClockAndRunEventLoop(ctx, 1_ms32); + NL_TEST_ASSERT(aSuite, ctx->mICDManager.mOperationalState == ICDManager::OperationalState::IdleMode); + + // Trigger a subscription report Put the ICD manager into active mode + notifier.NotifySubscriptionReport(); + NL_TEST_ASSERT(aSuite, ctx->mICDManager.mOperationalState == ICDManager::OperationalState::ActiveMode); + + // Advance time by the duration of the stay active request - 1 ms + AdvanceClockAndRunEventLoop(ctx, icdConfigData.GetActiveModeDuration() - 1_ms32); + stayActiveRequestedMs = 30000; + // Send a stay active request for 30 seconds + stayActivePromisedMs = ctx->mICDManager.StayActiveRequest(stayActiveRequestedMs); + // confirm the promised time is the same as the requested time + NL_TEST_ASSERT(aSuite, stayActivePromisedMs == 30000); + + // Advance time by the duration of the stay active request - 20000 ms + AdvanceClockAndRunEventLoop(ctx, System::Clock::Milliseconds32(stayActiveRequestedMs) - 20000_ms32); + // Confirm ICD manager is in active mode, we should have 20000 seconds left at that point + NL_TEST_ASSERT(aSuite, ctx->mICDManager.mOperationalState == ICDManager::OperationalState::ActiveMode); + + stayActiveRequestedMs = 10000; + stayActivePromisedMs = ctx->mICDManager.StayActiveRequest(stayActiveRequestedMs); + // confirm the promised time is 20000 since the device is already planing to stay active longer than the requested time + NL_TEST_ASSERT(aSuite, stayActivePromisedMs == 20000); + } }; } // namespace app @@ -556,6 +633,7 @@ static const nlTest sTests[] = { NL_TEST_DEF("TestKeepActivemodeRequests", TestICDManager::TestKeepActivemodeRequests), NL_TEST_DEF("TestICDMRegisterUnregisterEvents", TestICDManager::TestICDMRegisterUnregisterEvents), NL_TEST_DEF("TestICDCounter", TestICDManager::TestICDCounter), + NL_TEST_DEF("TestICDStayActive", TestICDManager::TestICDMStayActive), NL_TEST_SENTINEL(), }; diff --git a/src/app/tests/suites/TestIcdManagementCluster.yaml b/src/app/tests/suites/TestIcdManagementCluster.yaml index d9d275b90faf3c..3d0081504c19bf 100644 --- a/src/app/tests/suites/TestIcdManagementCluster.yaml +++ b/src/app/tests/suites/TestIcdManagementCluster.yaml @@ -372,3 +372,82 @@ tests: value: 102 response: error: NOT_FOUND + + - label: + "Wait for a little bit less than the active mode duration (10000ms)" + cluster: "DelayCommands" + command: "WaitForMs" + arguments: + values: + - name: "ms" + value: 9000 + + - label: + "StayActive Scenario 1: Confirm the promised active duration is + increased to a specific if a value less than 30000ms is requested and + the device does not intend to stay active longer" + command: "StayActiveRequest" + arguments: + values: + - name: "StayActiveDuration" + value: 20000 + response: + values: + - name: "PromisedActiveDuration" + constraints: + type: int32u + minValue: 19500 + maxValue: 20500 + + - label: + "Wait for a little bit less than the new promied active mode duration + (20000ms)" + cluster: "DelayCommands" + command: "WaitForMs" + arguments: + values: + - name: "ms" + value: 19000 + + - label: + "StayActive Scenario 2: Confirm the promised active duration is + reduced to 30000ms if a value greater than 30000ms is requested" + command: "StayActiveRequest" + arguments: + values: + - name: "StayActiveDuration" + value: 35000 + response: + values: + - name: "PromisedActiveDuration" + constraints: + type: int32u + minValue: 29500 + maxValue: 30500 + + - label: + "Wait for a 20000 less than the new promied active mode duration + (30000ms)" + cluster: "DelayCommands" + command: "WaitForMs" + arguments: + values: + - name: "ms" + value: 10000 + + - label: + "StayActive Scenario 3: confirm that the device ignores the request if + the device intends to stay active longer than the requested duration + we should have about 20000ms left here" + command: "StayActiveRequest" + arguments: + values: + - name: "StayActiveDuration" + value: 10000 + response: + values: + - name: "PromisedActiveDuration" + constraints: + type: int32u + minValue: 19500 + maxValue: 20500 diff --git a/src/app/zap-templates/zcl/data-model/chip/icd-management-cluster.xml b/src/app/zap-templates/zcl/data-model/chip/icd-management-cluster.xml index a2665916e23204..d68cc30ea95f9c 100644 --- a/src/app/zap-templates/zcl/data-model/chip/icd-management-cluster.xml +++ b/src/app/zap-templates/zcl/data-model/chip/icd-management-cluster.xml @@ -111,6 +111,7 @@ limitations under the License. Request the end device to stay in Active Mode for an additional ActiveModeThreshold + diff --git a/src/controller/data_model/controller-clusters.matter b/src/controller/data_model/controller-clusters.matter index 8611f4bdcf62d8..5dece392f3cd97 100644 --- a/src/controller/data_model/controller-clusters.matter +++ b/src/controller/data_model/controller-clusters.matter @@ -2740,6 +2740,10 @@ cluster IcdManagement = 70 { optional octet_string<16> verificationKey = 1; } + request struct StayActiveRequestRequest { + int32u stayActiveDuration = 0; + } + response struct StayActiveResponse = 4 { int32u promisedActiveDuration = 0; } @@ -2749,7 +2753,7 @@ cluster IcdManagement = 70 { /** Unregister a client from an end device */ fabric command access(invoke: manage) UnregisterClient(UnregisterClientRequest): DefaultSuccess = 2; /** Request the end device to stay in Active Mode for an additional ActiveModeThreshold */ - command access(invoke: manage) StayActiveRequest(): StayActiveResponse = 3; + command access(invoke: manage) StayActiveRequest(StayActiveRequestRequest): StayActiveResponse = 3; } /** This cluster supports creating a simple timer functionality. */ diff --git a/src/controller/java/generated/java/chip/devicecontroller/ChipClusters.java b/src/controller/java/generated/java/chip/devicecontroller/ChipClusters.java index 7025f3cde37858..c55a45b77aaca8 100644 --- a/src/controller/java/generated/java/chip/devicecontroller/ChipClusters.java +++ b/src/controller/java/generated/java/chip/devicecontroller/ChipClusters.java @@ -18170,14 +18170,18 @@ public void onResponse(StructType invokeStructValue) { }}, commandId, commandArgs, timedInvokeTimeoutMs); } - public void stayActiveRequest(StayActiveResponseCallback callback) { - stayActiveRequest(callback, 0); + public void stayActiveRequest(StayActiveResponseCallback callback, Long stayActiveDuration) { + stayActiveRequest(callback, stayActiveDuration, 0); } - public void stayActiveRequest(StayActiveResponseCallback callback, int timedInvokeTimeoutMs) { + public void stayActiveRequest(StayActiveResponseCallback callback, Long stayActiveDuration, int timedInvokeTimeoutMs) { final long commandId = 3L; ArrayList elements = new ArrayList<>(); + final long stayActiveDurationFieldID = 0L; + BaseTLVType stayActiveDurationtlvValue = new UIntType(stayActiveDuration); + elements.add(new StructElement(stayActiveDurationFieldID, stayActiveDurationtlvValue)); + StructType commandArgs = new StructType(elements); invoke(new InvokeCallbackImpl(callback) { @Override diff --git a/src/controller/java/generated/java/chip/devicecontroller/ClusterIDMapping.java b/src/controller/java/generated/java/chip/devicecontroller/ClusterIDMapping.java index a1d43e3a7933a5..3437b8a981e476 100644 --- a/src/controller/java/generated/java/chip/devicecontroller/ClusterIDMapping.java +++ b/src/controller/java/generated/java/chip/devicecontroller/ClusterIDMapping.java @@ -5881,6 +5881,23 @@ public static UnregisterClientCommandField value(int id) throws NoSuchFieldError } throw new NoSuchFieldError(); } + }public enum StayActiveRequestCommandField {StayActiveDuration(0),; + private final int id; + StayActiveRequestCommandField(int id) { + this.id = id; + } + + public int getID() { + return id; + } + public static StayActiveRequestCommandField value(int id) throws NoSuchFieldError { + for (StayActiveRequestCommandField field : StayActiveRequestCommandField.values()) { + if (field.getID() == id) { + return field; + } + } + throw new NoSuchFieldError(); + } }@Override public String getAttributeName(long id) throws NoSuchFieldError { return Attribute.value(id).toString(); diff --git a/src/controller/java/generated/java/chip/devicecontroller/ClusterInfoMapping.java b/src/controller/java/generated/java/chip/devicecontroller/ClusterInfoMapping.java index 5162f9766a74da..4ded328fad6ed5 100644 --- a/src/controller/java/generated/java/chip/devicecontroller/ClusterInfoMapping.java +++ b/src/controller/java/generated/java/chip/devicecontroller/ClusterInfoMapping.java @@ -23352,10 +23352,16 @@ public Map> getCommandMap() { icdManagementClusterInteractionInfoMap.put("unregisterClient", icdManagementunregisterClientInteractionInfo); Map icdManagementstayActiveRequestCommandParams = new LinkedHashMap(); + + CommandParameterInfo icdManagementstayActiveRequeststayActiveDurationCommandParameterInfo = new CommandParameterInfo("stayActiveDuration", Long.class, Long.class); + icdManagementstayActiveRequestCommandParams.put("stayActiveDuration",icdManagementstayActiveRequeststayActiveDurationCommandParameterInfo); InteractionInfo icdManagementstayActiveRequestInteractionInfo = new InteractionInfo( (cluster, callback, commandArguments) -> { ((ChipClusters.IcdManagementCluster) cluster) .stayActiveRequest((ChipClusters.IcdManagementCluster.StayActiveResponseCallback) callback + , (Long) + commandArguments.get("stayActiveDuration") + ); }, () -> new DelegatedIcdManagementClusterStayActiveResponseCallback(), diff --git a/src/controller/java/generated/java/matter/controller/cluster/clusters/IcdManagementCluster.kt b/src/controller/java/generated/java/matter/controller/cluster/clusters/IcdManagementCluster.kt index 9421d92a1742f7..008aa6349da2ce 100644 --- a/src/controller/java/generated/java/matter/controller/cluster/clusters/IcdManagementCluster.kt +++ b/src/controller/java/generated/java/matter/controller/cluster/clusters/IcdManagementCluster.kt @@ -193,11 +193,17 @@ class IcdManagementCluster( logger.log(Level.FINE, "Invoke command succeeded: ${response}") } - suspend fun stayActiveRequest(timedInvokeTimeout: Duration? = null): StayActiveResponse { + suspend fun stayActiveRequest( + stayActiveDuration: UInt, + timedInvokeTimeout: Duration? = null + ): StayActiveResponse { val commandId: UInt = 3u val tlvWriter = TlvWriter() tlvWriter.startStructure(AnonymousTag) + + val TAG_STAY_ACTIVE_DURATION_REQ: Int = 0 + tlvWriter.put(ContextSpecificTag(TAG_STAY_ACTIVE_DURATION_REQ), stayActiveDuration) tlvWriter.endStructure() val request: InvokeRequest = diff --git a/src/controller/python/chip/clusters/CHIPClusters.py b/src/controller/python/chip/clusters/CHIPClusters.py index 853fd1f98c38cd..3bc715829f27db 100644 --- a/src/controller/python/chip/clusters/CHIPClusters.py +++ b/src/controller/python/chip/clusters/CHIPClusters.py @@ -4078,6 +4078,7 @@ class ChipClusters: "commandId": 0x00000003, "commandName": "StayActiveRequest", "args": { + "stayActiveDuration": "int", }, }, }, diff --git a/src/controller/python/chip/clusters/Objects.py b/src/controller/python/chip/clusters/Objects.py index 3f5c116cc5515b..cd411b93d43301 100644 --- a/src/controller/python/chip/clusters/Objects.py +++ b/src/controller/python/chip/clusters/Objects.py @@ -14304,8 +14304,11 @@ class StayActiveRequest(ClusterCommand): def descriptor(cls) -> ClusterObjectDescriptor: return ClusterObjectDescriptor( Fields=[ + ClusterObjectFieldDescriptor(Label="stayActiveDuration", Tag=0, Type=uint), ]) + stayActiveDuration: 'uint' = 0 + @dataclass class StayActiveResponse(ClusterCommand): cluster_id: typing.ClassVar[int] = 0x00000046 diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters.h b/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters.h index 9f7d6f8ffd5c64..6232b6424b8eb1 100644 --- a/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters.h +++ b/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters.h @@ -4491,9 +4491,7 @@ MTR_PROVISIONALLY_AVAILABLE * * Request the end device to stay in Active Mode for an additional ActiveModeThreshold */ -- (void)stayActiveRequestWithParams:(MTRICDManagementClusterStayActiveRequestParams * _Nullable)params completion:(void (^)(MTRICDManagementClusterStayActiveResponseParams * _Nullable data, NSError * _Nullable error))completion MTR_PROVISIONALLY_AVAILABLE; -- (void)stayActiveRequestWithCompletion:(void (^)(MTRICDManagementClusterStayActiveResponseParams * _Nullable data, NSError * _Nullable error))completion - MTR_PROVISIONALLY_AVAILABLE; +- (void)stayActiveRequestWithParams:(MTRICDManagementClusterStayActiveRequestParams *)params completion:(void (^)(MTRICDManagementClusterStayActiveResponseParams * _Nullable data, NSError * _Nullable error))completion MTR_PROVISIONALLY_AVAILABLE; - (void)readAttributeIdleModeDurationWithCompletion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion MTR_PROVISIONALLY_AVAILABLE; - (void)subscribeAttributeIdleModeDurationWithParams:(MTRSubscribeParams *)params diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters.mm b/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters.mm index 8cca4c8ed5a7d5..b375488f292fc8 100644 --- a/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters.mm +++ b/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters.mm @@ -37049,11 +37049,7 @@ - (void)unregisterClientWithParams:(MTRICDManagementClusterUnregisterClientParam queue:self.callbackQueue completion:responseHandler]; } -- (void)stayActiveRequestWithCompletion:(void (^)(MTRICDManagementClusterStayActiveResponseParams * _Nullable data, NSError * _Nullable error))completion -{ - [self stayActiveRequestWithParams:nil completion:completion]; -} -- (void)stayActiveRequestWithParams:(MTRICDManagementClusterStayActiveRequestParams * _Nullable)params completion:(void (^)(MTRICDManagementClusterStayActiveResponseParams * _Nullable data, NSError * _Nullable error))completion +- (void)stayActiveRequestWithParams:(MTRICDManagementClusterStayActiveRequestParams *)params completion:(void (^)(MTRICDManagementClusterStayActiveResponseParams * _Nullable data, NSError * _Nullable error))completion { if (params == nil) { params = [[MTRICDManagementClusterStayActiveRequestParams diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRClusters.h b/src/darwin/Framework/CHIP/zap-generated/MTRClusters.h index d8bc6458a2680d..7ce97cfe09442f 100644 --- a/src/darwin/Framework/CHIP/zap-generated/MTRClusters.h +++ b/src/darwin/Framework/CHIP/zap-generated/MTRClusters.h @@ -2090,9 +2090,7 @@ MTR_PROVISIONALLY_AVAILABLE - (void)registerClientWithParams:(MTRICDManagementClusterRegisterClientParams *)params expectedValues:(NSArray *> * _Nullable)expectedDataValueDictionaries expectedValueInterval:(NSNumber * _Nullable)expectedValueIntervalMs completion:(void (^)(MTRICDManagementClusterRegisterClientResponseParams * _Nullable data, NSError * _Nullable error))completion MTR_PROVISIONALLY_AVAILABLE; - (void)unregisterClientWithParams:(MTRICDManagementClusterUnregisterClientParams *)params expectedValues:(NSArray *> * _Nullable)expectedDataValueDictionaries expectedValueInterval:(NSNumber * _Nullable)expectedValueIntervalMs completion:(MTRStatusCompletion)completion MTR_PROVISIONALLY_AVAILABLE; -- (void)stayActiveRequestWithParams:(MTRICDManagementClusterStayActiveRequestParams * _Nullable)params expectedValues:(NSArray *> * _Nullable)expectedDataValueDictionaries expectedValueInterval:(NSNumber * _Nullable)expectedValueIntervalMs completion:(void (^)(MTRICDManagementClusterStayActiveResponseParams * _Nullable data, NSError * _Nullable error))completion MTR_PROVISIONALLY_AVAILABLE; -- (void)stayActiveRequestWithExpectedValues:(NSArray *> * _Nullable)expectedValues expectedValueInterval:(NSNumber * _Nullable)expectedValueIntervalMs completion:(void (^)(MTRICDManagementClusterStayActiveResponseParams * _Nullable data, NSError * _Nullable error))completion - MTR_PROVISIONALLY_AVAILABLE; +- (void)stayActiveRequestWithParams:(MTRICDManagementClusterStayActiveRequestParams *)params expectedValues:(NSArray *> * _Nullable)expectedDataValueDictionaries expectedValueInterval:(NSNumber * _Nullable)expectedValueIntervalMs completion:(void (^)(MTRICDManagementClusterStayActiveResponseParams * _Nullable data, NSError * _Nullable error))completion MTR_PROVISIONALLY_AVAILABLE; - (NSDictionary * _Nullable)readAttributeIdleModeDurationWithParams:(MTRReadParams * _Nullable)params MTR_PROVISIONALLY_AVAILABLE; diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRClusters.mm b/src/darwin/Framework/CHIP/zap-generated/MTRClusters.mm index 2374d7f3cf9531..db279250cac8bf 100644 --- a/src/darwin/Framework/CHIP/zap-generated/MTRClusters.mm +++ b/src/darwin/Framework/CHIP/zap-generated/MTRClusters.mm @@ -6080,11 +6080,7 @@ - (void)unregisterClientWithParams:(MTRICDManagementClusterUnregisterClientParam completion:responseHandler]; } -- (void)stayActiveRequestWithExpectedValues:(NSArray *> *)expectedValues expectedValueInterval:(NSNumber *)expectedValueIntervalMs completion:(void (^)(MTRICDManagementClusterStayActiveResponseParams * _Nullable data, NSError * _Nullable error))completion -{ - [self stayActiveRequestWithParams:nil expectedValues:expectedValues expectedValueInterval:expectedValueIntervalMs completion:completion]; -} -- (void)stayActiveRequestWithParams:(MTRICDManagementClusterStayActiveRequestParams * _Nullable)params expectedValues:(NSArray *> * _Nullable)expectedValues expectedValueInterval:(NSNumber * _Nullable)expectedValueIntervalMs completion:(void (^)(MTRICDManagementClusterStayActiveResponseParams * _Nullable data, NSError * _Nullable error))completion +- (void)stayActiveRequestWithParams:(MTRICDManagementClusterStayActiveRequestParams *)params expectedValues:(NSArray *> * _Nullable)expectedValues expectedValueInterval:(NSNumber * _Nullable)expectedValueIntervalMs completion:(void (^)(MTRICDManagementClusterStayActiveResponseParams * _Nullable data, NSError * _Nullable error))completion { if (params == nil) { params = [[MTRICDManagementClusterStayActiveRequestParams diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloadsObjc.h b/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloadsObjc.h index 8f2b0705fe3283..ccd23b30f0aceb 100644 --- a/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloadsObjc.h +++ b/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloadsObjc.h @@ -3697,6 +3697,8 @@ MTR_PROVISIONALLY_AVAILABLE MTR_PROVISIONALLY_AVAILABLE @interface MTRICDManagementClusterStayActiveRequestParams : NSObject + +@property (nonatomic, copy) NSNumber * _Nonnull stayActiveDuration MTR_PROVISIONALLY_AVAILABLE; /** * Controls whether the command is a timed command (using Timed Invoke). * diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloadsObjc.mm b/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloadsObjc.mm index 60757c92d0dfdb..3105c9a9d21f80 100644 --- a/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloadsObjc.mm +++ b/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloadsObjc.mm @@ -9783,6 +9783,8 @@ @implementation MTRICDManagementClusterStayActiveRequestParams - (instancetype)init { if (self = [super init]) { + + _stayActiveDuration = @(0); _timedInvokeTimeoutMs = nil; _serverSideProcessingTimeout = nil; } @@ -9793,6 +9795,7 @@ - (id)copyWithZone:(NSZone * _Nullable)zone; { auto other = [[MTRICDManagementClusterStayActiveRequestParams alloc] init]; + other.stayActiveDuration = self.stayActiveDuration; other.timedInvokeTimeoutMs = self.timedInvokeTimeoutMs; other.serverSideProcessingTimeout = self.serverSideProcessingTimeout; @@ -9801,7 +9804,7 @@ - (id)copyWithZone:(NSZone * _Nullable)zone; - (NSString *)description { - NSString * descriptionString = [NSString stringWithFormat:@"<%@: >", NSStringFromClass([self class])]; + NSString * descriptionString = [NSString stringWithFormat:@"<%@: stayActiveDuration:%@; >", NSStringFromClass([self class]), _stayActiveDuration]; return descriptionString; } @@ -9813,6 +9816,9 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader { chip::app::Clusters::IcdManagement::Commands::StayActiveRequest::Type encodableStruct; ListFreer listFreer; + { + encodableStruct.stayActiveDuration = self.stayActiveDuration.unsignedIntValue; + } auto buffer = chip::System::PacketBufferHandle::New(chip::System::PacketBuffer::kMaxSizeWithoutReserve, 0); if (buffer.IsNull()) { diff --git a/src/system/SystemLayer.h b/src/system/SystemLayer.h index 427bf00c99c3eb..d91a80d9be8f57 100644 --- a/src/system/SystemLayer.h +++ b/src/system/SystemLayer.h @@ -142,6 +142,9 @@ class DLL_EXPORT Layer * This method searches for the timer matching the provided parameters. * and returns whether it is still "running" and waiting to trigger or not. * + * @note This is used to verify by how long the ExtendTimer method extends the timer, as it may ignore an extension request + * if it is shorter than the current timer's remaining time. + * * @param[in] onComplete A pointer to the function called when timer expires. * @param[in] appState A pointer to the application state object used when timer expires. * @@ -150,6 +153,17 @@ class DLL_EXPORT Layer */ virtual bool IsTimerActive(TimerCompleteCallback onComplete, void * appState) = 0; + /** + * @brief + * This method searches for the timer matching the provided parameters + * and returns the remaining time left before it expires. + * @param[in] onComplete A pointer to the function called when timer expires. + * @param[in] appState A pointer to the application state object used when timer expires. + * + * @return The remaining time left before the timer expires. + */ + virtual Clock::Timeout GetRemainingTime(TimerCompleteCallback onComplete, void * appState) = 0; + /** * @brief This method cancels a one-shot timer, started earlier through @p StartTimer(). This method must * be called while in the Matter context (from the Matter event loop, or while holding the Matter diff --git a/src/system/SystemLayerImplFreeRTOS.cpp b/src/system/SystemLayerImplFreeRTOS.cpp index cfc8e091208f86..59265f61d03693 100644 --- a/src/system/SystemLayerImplFreeRTOS.cpp +++ b/src/system/SystemLayerImplFreeRTOS.cpp @@ -96,6 +96,11 @@ bool LayerImplFreeRTOS::IsTimerActive(TimerCompleteCallback onComplete, void * a return (mTimerList.GetRemainingTime(onComplete, appState) > Clock::kZero); } +Clock::Timeout LayerImplFreeRTOS::GetRemainingTime(TimerCompleteCallback onComplete, void * appState) +{ + return mTimerList.GetRemainingTime(onComplete, appState); +} + void LayerImplFreeRTOS::CancelTimer(TimerCompleteCallback onComplete, void * appState) { assertChipStackLockedByCurrentThread(); diff --git a/src/system/SystemLayerImplFreeRTOS.h b/src/system/SystemLayerImplFreeRTOS.h index 2e7401dfce03ce..fe0e9be4bc7e33 100644 --- a/src/system/SystemLayerImplFreeRTOS.h +++ b/src/system/SystemLayerImplFreeRTOS.h @@ -42,6 +42,7 @@ class LayerImplFreeRTOS : public LayerFreeRTOS CHIP_ERROR StartTimer(Clock::Timeout delay, TimerCompleteCallback onComplete, void * appState) override; CHIP_ERROR ExtendTimerTo(Clock::Timeout delay, TimerCompleteCallback onComplete, void * appState) override; bool IsTimerActive(TimerCompleteCallback onComplete, void * appState) override; + Clock::Timeout GetRemainingTime(TimerCompleteCallback onComplete, void * appState) override; void CancelTimer(TimerCompleteCallback onComplete, void * appState) override; CHIP_ERROR ScheduleWork(TimerCompleteCallback onComplete, void * appState) override; diff --git a/src/system/SystemLayerImplSelect.cpp b/src/system/SystemLayerImplSelect.cpp index 7ae25a0a59d134..86ff1cb62da42f 100644 --- a/src/system/SystemLayerImplSelect.cpp +++ b/src/system/SystemLayerImplSelect.cpp @@ -255,6 +255,11 @@ bool LayerImplSelect::IsTimerActive(TimerCompleteCallback onComplete, void * app return timerIsActive; } +Clock::Timeout LayerImplSelect::GetRemainingTime(TimerCompleteCallback onComplete, void * appState) +{ + return mTimerList.GetRemainingTime(onComplete, appState); +} + void LayerImplSelect::CancelTimer(TimerCompleteCallback onComplete, void * appState) { assertChipStackLockedByCurrentThread(); diff --git a/src/system/SystemLayerImplSelect.h b/src/system/SystemLayerImplSelect.h index 060657e77a72ef..1bab3db9b5f39c 100644 --- a/src/system/SystemLayerImplSelect.h +++ b/src/system/SystemLayerImplSelect.h @@ -65,6 +65,7 @@ class LayerImplSelect : public LayerSocketsLoop CHIP_ERROR StartTimer(Clock::Timeout delay, TimerCompleteCallback onComplete, void * appState) override; CHIP_ERROR ExtendTimerTo(Clock::Timeout delay, TimerCompleteCallback onComplete, void * appState) override; bool IsTimerActive(TimerCompleteCallback onComplete, void * appState) override; + Clock::Timeout GetRemainingTime(TimerCompleteCallback onComplete, void * appState) override; void CancelTimer(TimerCompleteCallback onComplete, void * appState) override; CHIP_ERROR ScheduleWork(TimerCompleteCallback onComplete, void * appState) override; diff --git a/zzz_generated/app-common/app-common/zap-generated/cluster-objects.cpp b/zzz_generated/app-common/app-common/zap-generated/cluster-objects.cpp index fc5a2bd789227b..32b62631ed30fd 100644 --- a/zzz_generated/app-common/app-common/zap-generated/cluster-objects.cpp +++ b/zzz_generated/app-common/app-common/zap-generated/cluster-objects.cpp @@ -9794,6 +9794,7 @@ namespace StayActiveRequest { CHIP_ERROR Type::Encode(TLV::TLVWriter & aWriter, TLV::Tag aTag) const { DataModel::WrappedStructEncoder encoder{ aWriter, aTag }; + encoder.Encode(to_underlying(Fields::kStayActiveDuration), stayActiveDuration); return encoder.Finalize(); } @@ -9807,6 +9808,19 @@ CHIP_ERROR DecodableType::Decode(TLV::TLVReader & reader) { return std::get(__element); } + + CHIP_ERROR err = CHIP_NO_ERROR; + const uint8_t __context_tag = std::get(__element); + + if (__context_tag == to_underlying(Fields::kStayActiveDuration)) + { + err = DataModel::Decode(reader, stayActiveDuration); + } + else + { + } + + ReturnErrorOnFailure(err); } } } // namespace StayActiveRequest. diff --git a/zzz_generated/app-common/app-common/zap-generated/cluster-objects.h b/zzz_generated/app-common/app-common/zap-generated/cluster-objects.h index dfdf2e691686f2..89c36f3c6f147d 100644 --- a/zzz_generated/app-common/app-common/zap-generated/cluster-objects.h +++ b/zzz_generated/app-common/app-common/zap-generated/cluster-objects.h @@ -13302,6 +13302,7 @@ struct DecodableType namespace StayActiveRequest { enum class Fields : uint8_t { + kStayActiveDuration = 0, }; struct Type @@ -13311,6 +13312,8 @@ struct Type static constexpr CommandId GetCommandId() { return Commands::StayActiveRequest::Id; } static constexpr ClusterId GetClusterId() { return Clusters::IcdManagement::Id; } + uint32_t stayActiveDuration = static_cast(0); + CHIP_ERROR Encode(TLV::TLVWriter & aWriter, TLV::Tag aTag) const; using ResponseType = Clusters::IcdManagement::Commands::StayActiveResponse::DecodableType; @@ -13324,6 +13327,7 @@ struct DecodableType static constexpr CommandId GetCommandId() { return Commands::StayActiveRequest::Id; } static constexpr ClusterId GetClusterId() { return Clusters::IcdManagement::Id; } + uint32_t stayActiveDuration = static_cast(0); CHIP_ERROR Decode(TLV::TLVReader & reader); }; }; // namespace StayActiveRequest diff --git a/zzz_generated/chip-tool/zap-generated/cluster/Commands.h b/zzz_generated/chip-tool/zap-generated/cluster/Commands.h index 6191eb2aa3ec2d..8a3081edc0dc1b 100644 --- a/zzz_generated/chip-tool/zap-generated/cluster/Commands.h +++ b/zzz_generated/chip-tool/zap-generated/cluster/Commands.h @@ -4314,6 +4314,7 @@ class IcdManagementStayActiveRequest : public ClusterCommand IcdManagementStayActiveRequest(CredentialIssuerCommands * credsIssuerConfig) : ClusterCommand("stay-active-request", credsIssuerConfig) { + AddArgument("StayActiveDuration", 0, UINT32_MAX, &mRequest.stayActiveDuration); ClusterCommand::AddArguments(); } diff --git a/zzz_generated/darwin-framework-tool/zap-generated/cluster/Commands.h b/zzz_generated/darwin-framework-tool/zap-generated/cluster/Commands.h index 60843e78e103e7..be046cb6155993 100644 --- a/zzz_generated/darwin-framework-tool/zap-generated/cluster/Commands.h +++ b/zzz_generated/darwin-framework-tool/zap-generated/cluster/Commands.h @@ -47653,6 +47653,9 @@ class IcdManagementStayActiveRequest : public ClusterCommand { IcdManagementStayActiveRequest() : ClusterCommand("stay-active-request") { +#if MTR_ENABLE_PROVISIONAL + AddArgument("StayActiveDuration", 0, UINT32_MAX, &mRequest.stayActiveDuration); +#endif // MTR_ENABLE_PROVISIONAL ClusterCommand::AddArguments(); } @@ -47667,6 +47670,9 @@ class IcdManagementStayActiveRequest : public ClusterCommand { __auto_type * cluster = [[MTRBaseClusterICDManagement alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue]; __auto_type * params = [[MTRICDManagementClusterStayActiveRequestParams alloc] init]; params.timedInvokeTimeoutMs = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil; +#if MTR_ENABLE_PROVISIONAL + params.stayActiveDuration = [NSNumber numberWithUnsignedInt:mRequest.stayActiveDuration]; +#endif // MTR_ENABLE_PROVISIONAL uint16_t repeatCount = mRepeatCount.ValueOr(1); uint16_t __block responsesNeeded = repeatCount; while (repeatCount--) { @@ -47693,6 +47699,7 @@ class IcdManagementStayActiveRequest : public ClusterCommand { } private: + chip::app::Clusters::IcdManagement::Commands::StayActiveRequest::Type mRequest; }; #endif // MTR_ENABLE_PROVISIONAL From 10ff1f6fb9949043fc955646e29878f1c4a6c816 Mon Sep 17 00:00:00 2001 From: Jean-Francois Penven <67962328+jepenven-silabs@users.noreply.github.com> Date: Mon, 26 Feb 2024 11:13:35 -0500 Subject: [PATCH 085/385] Fix header guard since 2 headers had the same (#32297) --- src/platform/silabs/rs911x/rsi_ble_config.h | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/platform/silabs/rs911x/rsi_ble_config.h b/src/platform/silabs/rs911x/rsi_ble_config.h index bf40cad514dada..72f830b423ef9d 100644 --- a/src/platform/silabs/rs911x/rsi_ble_config.h +++ b/src/platform/silabs/rs911x/rsi_ble_config.h @@ -14,9 +14,7 @@ * sections of the MSLA applicable to Source Code. * ******************************************************************************/ - -#ifndef RSI_BLE_CONFIG_H -#define RSI_BLE_CONFIG_H +#pragma once #include "rsi_ble_apis.h" #if (SIWX_917 | EXP_BOARD) @@ -315,6 +313,4 @@ typedef struct rsi_ble_s uint16_t DATA_ix; uint16_t att_rec_list_count; rsi_ble_att_list_t att_rec_list[NO_OF_VAL_ATT]; -} rsi_ble_t; - -#endif \ No newline at end of file +} rsi_ble_t; \ No newline at end of file From d812a168a3c69ceab56969e265c08d85033b1949 Mon Sep 17 00:00:00 2001 From: Vivien Nicolas Date: Mon, 26 Feb 2024 17:47:00 +0100 Subject: [PATCH 086/385] [Matter.framework] Get downloadLogOfType to work over XPC (#32319) * [Matter.framework] Move downloadLogOfType from MTRDevice to MTRBaseDevice * [Matter.framework] Get downloadLogOfType to work over XPC * Add a simple test to MTRXPCProtocolTests.m to check that the XPC protocol works * Add a simple test to MTRXPCListenerSampleTests * [Matter.framework] Do not delete the file containing the log data once the downloadLogOfType completion is done --- .github/workflows/darwin.yaml | 3 +- .../commands/bdx/DownloadLogCommand.mm | 2 +- src/darwin/Framework/CHIP/MTRBaseDevice.h | 21 ++++++++ src/darwin/Framework/CHIP/MTRBaseDevice.mm | 13 +++++ src/darwin/Framework/CHIP/MTRDevice.h | 22 -------- src/darwin/Framework/CHIP/MTRDevice.mm | 12 ----- .../Framework/CHIP/MTRDeviceController+XPC.h | 10 ++++ .../Framework/CHIP/MTRDeviceController+XPC.mm | 4 ++ src/darwin/Framework/CHIP/MTRDeviceOverXPC.mm | 32 ++++++++++++ .../CHIP/MTRDiagnosticLogsDownloader.mm | 1 - .../CHIPTests/MTRXPCListenerSampleTests.m | 46 ++++++++++++++++ .../Framework/CHIPTests/MTRXPCProtocolTests.m | 52 +++++++++++++++++++ 12 files changed, 181 insertions(+), 37 deletions(-) diff --git a/.github/workflows/darwin.yaml b/.github/workflows/darwin.yaml index a58617131a035d..2662853b1f790b 100644 --- a/.github/workflows/darwin.yaml +++ b/.github/workflows/darwin.yaml @@ -103,7 +103,8 @@ jobs: # target versions instead? run: | mkdir -p /tmp/darwin/framework-tests - ../../../out/debug/chip-all-clusters-app --interface-id -1 > >(tee /tmp/darwin/framework-tests/all-cluster-app.log) 2> >(tee /tmp/darwin/framework-tests/all-cluster-app-err.log >&2) & + echo "This is a simple log" > /tmp/darwin/framework-tests/end_user_support_log.txt + ../../../out/debug/chip-all-clusters-app --interface-id -1 --end_user_support_log /tmp/darwin/framework-tests/end_user_support_log.txt > >(tee /tmp/darwin/framework-tests/all-cluster-app.log) 2> >(tee /tmp/darwin/framework-tests/all-cluster-app-err.log >&2) & ../../../out/debug/chip-all-clusters-app --interface-id -1 --dac_provider ../../../credentials/development/commissioner_dut/struct_cd_origin_pid_vid_correct/test_case_vector.json --product-id 32768 --discriminator 3839 --secured-device-port 5539 --KVS /tmp/chip-all-clusters-app-kvs2 > >(tee /tmp/darwin/framework-tests/all-cluster-app-origin-vid.log) 2> >(tee /tmp/darwin/framework-tests/all-cluster-app-origin-vid-err.log >&2) & # Disable BLE (CHIP_IS_BLE=NO) because the app does not have the permission to use it and that may crash the CI. diff --git a/examples/darwin-framework-tool/commands/bdx/DownloadLogCommand.mm b/examples/darwin-framework-tool/commands/bdx/DownloadLogCommand.mm index b105b6cb3098c8..dd693b4358304b 100644 --- a/examples/darwin-framework-tool/commands/bdx/DownloadLogCommand.mm +++ b/examples/darwin-framework-tool/commands/bdx/DownloadLogCommand.mm @@ -28,7 +28,7 @@ ChipLogProgress(chipTool, "Downloading logs from node 0x" ChipLogFormatX64, ChipLogValueX64(mNodeId)); MTRDeviceController * commissioner = CurrentCommissioner(); - auto * device = [MTRDevice deviceWithNodeID:@(mNodeId) controller:commissioner]; + auto * device = [MTRBaseDevice deviceWithNodeID:@(mNodeId) controller:commissioner]; auto logType = static_cast(mLogType); auto queue = dispatch_queue_create("com.chip.bdx.downloader", DISPATCH_QUEUE_SERIAL); diff --git a/src/darwin/Framework/CHIP/MTRBaseDevice.h b/src/darwin/Framework/CHIP/MTRBaseDevice.h index af0a15bd1a6857..1fe9735932a6d0 100644 --- a/src/darwin/Framework/CHIP/MTRBaseDevice.h +++ b/src/darwin/Framework/CHIP/MTRBaseDevice.h @@ -19,6 +19,7 @@ #import #import +#import @class MTRSetupPayload; @class MTRDeviceController; @@ -542,6 +543,26 @@ MTR_AVAILABLE(ios(16.1), macos(13.0), watchos(9.1), tvos(16.1)) reportHandler:(MTRDeviceResponseHandler)reportHandler subscriptionEstablished:(MTRSubscriptionEstablishedHandler _Nullable)subscriptionEstablished MTR_AVAILABLE(ios(16.4), macos(13.3), watchos(9.4), tvos(16.4)); + +/** + * Download log of the desired type from the device. + * + * @param type The type of log being requested. This should correspond to a value in the enum MTRDiagnosticLogType. + * @param timeout The timeout for getting the log. If the timeout expires, completion will be called with whatever + * has been retrieved by that point (which might be none or a partial log). + * If the timeout is set to 0, the request will not expire and completion will not be called until + * the log is fully retrieved or an error occurs. + * @param queue The queue on which completion will be called. + * @param completion The completion handler that is called after attempting to retrieve the requested log. + * - In case of success, the completion handler is called with a non-nil URL and a nil error. + * - If there is an error, a non-nil error is used and the url can be non-nil too if some logs have already been downloaded. + */ +- (void)downloadLogOfType:(MTRDiagnosticLogType)type + timeout:(NSTimeInterval)timeout + queue:(dispatch_queue_t)queue + completion:(void (^)(NSURL * _Nullable url, NSError * _Nullable error))completion + MTR_NEWLY_AVAILABLE; + @end /** diff --git a/src/darwin/Framework/CHIP/MTRBaseDevice.mm b/src/darwin/Framework/CHIP/MTRBaseDevice.mm index 2a981cdd860fff..13154f8ac97aa2 100644 --- a/src/darwin/Framework/CHIP/MTRBaseDevice.mm +++ b/src/darwin/Framework/CHIP/MTRBaseDevice.mm @@ -2147,6 +2147,19 @@ + (NSDictionary *)eventReportForHeader:(const chip::app::EventHeader &)header an return buffer; } + +- (void)downloadLogOfType:(MTRDiagnosticLogType)type + timeout:(NSTimeInterval)timeout + queue:(dispatch_queue_t)queue + completion:(void (^)(NSURL * _Nullable url, NSError * _Nullable error))completion +{ + [_deviceController downloadLogFromNodeWithID:@(_nodeID) + type:type + timeout:timeout + queue:queue + completion:completion]; +} + @end @implementation MTRBaseDevice (Deprecated) diff --git a/src/darwin/Framework/CHIP/MTRDevice.h b/src/darwin/Framework/CHIP/MTRDevice.h index d4641d5dd321b3..23a1ecf51ad56c 100644 --- a/src/darwin/Framework/CHIP/MTRDevice.h +++ b/src/darwin/Framework/CHIP/MTRDevice.h @@ -18,7 +18,6 @@ #import #import #import -#import NS_ASSUME_NONNULL_BEGIN @@ -326,27 +325,6 @@ MTR_AVAILABLE(ios(16.1), macos(13.0), watchos(9.1), tvos(16.1)) */ - (void)removeClientDataForKey:(NSString *)key endpointID:(NSNumber *)endpointID MTR_UNSTABLE_API; -/** - * Download log of the desired type from the device. - * - * Note: The consumer of this API should move the file that the url points to or open it for reading before the - * completion handler returns. Otherwise, the file will be deleted, and the data will be lost. - * - * @param type The type of log being requested. This should correspond to a value in the enum MTRDiagnosticLogType. - * @param timeout The timeout for getting the log. If the timeout expires, completion will be called with whatever - * has been retrieved by that point (which might be none or a partial log). - * If the timeout is set to 0, the request will not expire and completion will not be called until - * the log is fully retrieved or an error occurs. - * @param queue The queue on which completion will be called. - * @param completion The completion handler that is called after attempting to retrieve the requested log. - * - In case of success, the completion handler is called with a non-nil URL and a nil error. - * - If there is an error, a non-nil error is used and the url can be non-nil too if some logs have already been downloaded. - */ -- (void)downloadLogOfType:(MTRDiagnosticLogType)type - timeout:(NSTimeInterval)timeout - queue:(dispatch_queue_t)queue - completion:(void (^)(NSURL * _Nullable url, NSError * _Nullable error))completion - MTR_NEWLY_AVAILABLE; @end MTR_EXTERN NSString * const MTRPreviousDataKey MTR_NEWLY_AVAILABLE; diff --git a/src/darwin/Framework/CHIP/MTRDevice.mm b/src/darwin/Framework/CHIP/MTRDevice.mm index 1b42caecf80c76..dbf1785c9bb6ba 100644 --- a/src/darwin/Framework/CHIP/MTRDevice.mm +++ b/src/darwin/Framework/CHIP/MTRDevice.mm @@ -1713,18 +1713,6 @@ - (void)openCommissioningWindowWithDiscriminator:(NSNumber *)discriminator [baseDevice openCommissioningWindowWithDiscriminator:discriminator duration:duration queue:queue completion:completion]; } -- (void)downloadLogOfType:(MTRDiagnosticLogType)type - timeout:(NSTimeInterval)timeout - queue:(dispatch_queue_t)queue - completion:(void (^)(NSURL * _Nullable url, NSError * _Nullable error))completion -{ - [_deviceController downloadLogFromNodeWithID:_nodeID - type:type - timeout:timeout - queue:queue - completion:completion]; -} - #pragma mark - Cache management // assume lock is held diff --git a/src/darwin/Framework/CHIP/MTRDeviceController+XPC.h b/src/darwin/Framework/CHIP/MTRDeviceController+XPC.h index 4316ba65f25198..2c4ec56e180113 100644 --- a/src/darwin/Framework/CHIP/MTRDeviceController+XPC.h +++ b/src/darwin/Framework/CHIP/MTRDeviceController+XPC.h @@ -20,6 +20,7 @@ #import #import #import +#import NS_ASSUME_NONNULL_BEGIN @@ -183,6 +184,15 @@ typedef void (^MTRValuesHandler)(id _Nullable values, NSError * _Nullable error) attributeId:(NSNumber * _Nullable)attributeId completion:(MTRValuesHandler)completion; +/** + * Requests downloading some logs + */ +- (void)downloadLogWithController:(id _Nullable)controller + nodeId:(uint64_t)nodeId + type:(MTRDiagnosticLogType)type + timeout:(NSTimeInterval)timeout + completion:(void (^)(NSString * _Nullable url, NSError * _Nullable error))completion; + @end /** diff --git a/src/darwin/Framework/CHIP/MTRDeviceController+XPC.mm b/src/darwin/Framework/CHIP/MTRDeviceController+XPC.mm index fa532f19aa833b..87ce5560381cca 100644 --- a/src/darwin/Framework/CHIP/MTRDeviceController+XPC.mm +++ b/src/darwin/Framework/CHIP/MTRDeviceController+XPC.mm @@ -220,6 +220,10 @@ + (NSXPCInterface *)xpcInterfaceForServerProtocol forSelector:@selector(readAttributeCacheWithController:nodeId:endpointId:clusterId:attributeId:completion:) argumentIndex:0 ofReply:YES]; + [xpcInterface setClasses:GetXPCAllowedClasses() + forSelector:@selector(downloadLogWithController:nodeId:type:timeout:completion:) + argumentIndex:0 + ofReply:YES]; return xpcInterface; } diff --git a/src/darwin/Framework/CHIP/MTRDeviceOverXPC.mm b/src/darwin/Framework/CHIP/MTRDeviceOverXPC.mm index 36dc5b27410da1..dee3ae86331812 100644 --- a/src/darwin/Framework/CHIP/MTRDeviceOverXPC.mm +++ b/src/darwin/Framework/CHIP/MTRDeviceOverXPC.mm @@ -427,6 +427,38 @@ - (void)openCommissioningWindowWithDiscriminator:(NSNumber *)discriminator }); } +- (void)downloadLogOfType:(MTRDiagnosticLogType)type + timeout:(NSTimeInterval)timeout + queue:(dispatch_queue_t)queue + completion:(void (^)(NSURL * _Nullable url, NSError * _Nullable error))completion +{ + MTR_LOG_DEBUG("Downloading log ..."); + + __auto_type workBlock = ^(MTRDeviceControllerXPCProxyHandle * _Nullable handle, NSError * _Nullable error) { + if (error != nil) { + completion(nil, error); + return; + } + + [handle.proxy downloadLogWithController:self.controllerID + nodeId:self.nodeID.unsignedLongLongValue + type:type + timeout:timeout + completion:^(NSString * _Nullable url, NSError * _Nullable error) { + dispatch_async(queue, ^{ + MTR_LOG_DEBUG("Download log"); + completion([NSURL URLWithString:url], error); + // The following captures the proxy handle in the closure so that the + // handle won't be released prior to block call. + __auto_type handleRetainer = handle; + (void) handleRetainer; + }); + }]; + }; + + [self fetchProxyHandleWithQueue:queue completion:workBlock]; +} + - (void)fetchProxyHandleWithQueue:(dispatch_queue_t)queue completion:(MTRFetchProxyHandleCompletion)completion { if (self.controllerID != nil) { diff --git a/src/darwin/Framework/CHIP/MTRDiagnosticLogsDownloader.mm b/src/darwin/Framework/CHIP/MTRDiagnosticLogsDownloader.mm index 46226d69357058..8d2832052979e7 100644 --- a/src/darwin/Framework/CHIP/MTRDiagnosticLogsDownloader.mm +++ b/src/darwin/Framework/CHIP/MTRDiagnosticLogsDownloader.mm @@ -165,7 +165,6 @@ - (instancetype)initWithType:(MTRDiagnosticLogType)type // data in the logs that the caller may find useful. For this reason, fileURL is passed in even // when there is an error but fileHandle is not nil. completion(strongSelf->_fileHandle ? fileURL : nil, bdxError); - [strongSelf deleteFile]; done(strongSelf); } diff --git a/src/darwin/Framework/CHIPTests/MTRXPCListenerSampleTests.m b/src/darwin/Framework/CHIPTests/MTRXPCListenerSampleTests.m index eabd682a5a0d59..3bf727db3dabb3 100644 --- a/src/darwin/Framework/CHIPTests/MTRXPCListenerSampleTests.m +++ b/src/darwin/Framework/CHIPTests/MTRXPCListenerSampleTests.m @@ -167,6 +167,28 @@ - (void)getAnyDeviceControllerWithCompletion:(void (^)(id _Nullable controller, completion(MTRDeviceControllerId, nil); } +- (void)downloadLogWithController:(id)controller + nodeId:(uint64_t)nodeId + type:(MTRDiagnosticLogType)type + timeout:(NSTimeInterval)timeout + completion:(void (^)(NSString * _Nullable url, NSError * _Nullable error))completion +{ + (void) controller; + __auto_type sharedController = sController; + if (sharedController) { + __auto_type device = [MTRBaseDevice deviceWithNodeID:@(nodeId) controller:sharedController]; + [device downloadLogOfType:type + timeout:timeout + queue:dispatch_get_main_queue() + completion:^(NSURL * _Nullable url, NSError * _Nullable error) { + completion([url absoluteString], error); + }]; + } else { + NSLog(@"Failed to get shared controller"); + completion(nil, [NSError errorWithDomain:MTRErrorDomain code:MTRErrorCodeGeneralError userInfo:nil]); + } +} + - (void)readAttributeWithController:(id)controller nodeId:(uint64_t)nodeId endpointId:(NSNumber * _Nullable)endpointId @@ -1865,6 +1887,30 @@ - (void)test015_MTRDeviceInteraction }, @(NO)); } +- (void)test016_DownloadLog +{ + XCTestExpectation * expectation = + [self expectationWithDescription:@"Download EndUserSupport log"]; + + MTRBaseDevice * device = GetConnectedDevice(); + dispatch_queue_t queue = dispatch_get_main_queue(); + + [device downloadLogOfType:MTRDiagnosticLogTypeEndUserSupport + timeout:10 + queue:queue + completion:^(NSURL * _Nullable url, NSError * _Nullable error) { + NSLog(@"downloadLogOfType: url: %@, error: %@", url, error); + XCTAssertNil(error); + + NSError * readError; + NSString * fileContent = [NSString stringWithContentsOfURL:url encoding:NSUTF8StringEncoding error:&readError]; + XCTAssertNil(readError); + XCTAssertTrue([fileContent isEqualToString:@"This is a simple log\n"]); + [expectation fulfill]; + }]; + [self waitForExpectationsWithTimeout:kTimeoutInSeconds handler:nil]; +} + - (void)test900_SubscribeClusterStateCache { XCTestExpectation * expectation = [self expectationWithDescription:@"subscribe attributes by cache"]; diff --git a/src/darwin/Framework/CHIPTests/MTRXPCProtocolTests.m b/src/darwin/Framework/CHIPTests/MTRXPCProtocolTests.m index d3d010ff7f0764..f626323cefb162 100644 --- a/src/darwin/Framework/CHIPTests/MTRXPCProtocolTests.m +++ b/src/darwin/Framework/CHIPTests/MTRXPCProtocolTests.m @@ -116,6 +116,8 @@ @interface MTRXPCProtocolTests @property (readwrite, strong) void (^handleReadClusterStateCache) (id controller, NSNumber * nodeId, NSNumber * _Nullable endpointId, NSNumber * _Nullable clusterId, NSNumber * _Nullable attributeId, void (^completion)(id _Nullable values, NSError * _Nullable error)); +@property (readwrite, strong) void (^handleDownloadLog)(id controller, NSNumber * nodeId, MTRDiagnosticLogType type, NSTimeInterval timeout, + void (^completion)(NSString * _Nullable url, NSError * _Nullable error)); @end @@ -274,6 +276,18 @@ - (void)readAttributeCacheWithController:(id _Nullable)controller }); } +- (void)downloadLogWithController:(id)controller + nodeId:(uint64_t)nodeId + type:(MTRDiagnosticLogType)type + timeout:(NSTimeInterval)timeout + completion:(void (^)(NSString * _Nullable url, NSError * _Nullable error))completion +{ + dispatch_async(dispatch_get_main_queue(), ^{ + XCTAssertNotNil(self.handleDownloadLog); + self.handleDownloadLog(controller, @(nodeId), type, timeout, completion); + }); +} + - (void)setUp { [self setContinueAfterFailure:NO]; @@ -300,6 +314,44 @@ - (void)tearDown _xpcDisconnectExpectation = nil; } +- (void)testDownloadLogSuccess +{ + uint64_t myNodeId = 9876543210; + NSString * myBdxURL = @"bdx://foo"; + NSTimeInterval myTimeout = 10; + + XCTestExpectation * callExpectation = [self expectationWithDescription:@"XPC call received"]; + XCTestExpectation * responseExpectation = [self expectationWithDescription:@"XPC response received"]; + + __auto_type uuid = self.controllerUUID; + _handleDownloadLog = ^(id controller, NSNumber * nodeId, MTRDiagnosticLogType type, NSTimeInterval timeout, + void (^completion)(NSString * _Nullable url, NSError * _Nullable error)) { + XCTAssertTrue([controller isEqualToString:uuid]); + XCTAssertEqual([nodeId unsignedLongLongValue], myNodeId); + [callExpectation fulfill]; + completion(myBdxURL, nil); + }; + + __auto_type * device = [MTRBaseDevice deviceWithNodeID:@(myNodeId) controller:_remoteDeviceController]; + NSLog(@"Device acquired. Downloading..."); + [device downloadLogOfType:MTRDiagnosticLogTypeEndUserSupport + timeout:myTimeout + queue:dispatch_get_main_queue() + completion:^(NSURL * _Nullable url, NSError * _Nullable error) { + NSLog(@"Read url: %@", url); + XCTAssertNotNil(url); + XCTAssertNil(error); + [responseExpectation fulfill]; + self.xpcDisconnectExpectation = [self expectationWithDescription:@"XPC Disconnected"]; + }]; + + [self waitForExpectations:[NSArray arrayWithObjects:callExpectation, responseExpectation, nil] timeout:kTimeoutInSeconds]; + + // When download is done, connection should have been released + [self waitForExpectations:[NSArray arrayWithObject:_xpcDisconnectExpectation] timeout:kTimeoutInSeconds]; + XCTAssertNil(_xpcConnection); +} + - (void)testReadAttributeSuccess { uint64_t myNodeId = 9876543210; From 116317ff924a3c36ccd5ed9d2c6e1dc709edc57a Mon Sep 17 00:00:00 2001 From: Andrei Litvin Date: Mon, 26 Feb 2024 12:01:00 -0500 Subject: [PATCH 087/385] remove the header `src/app/util/common.h` (#32320) * remove `src/app/util/common.h * Fix some typos * Remove some references of util/common.h * Fix up comment * Fix lint - a file got removed * Make the paths to the files full-paths --- .github/workflows/lint.yml | 1 - .../src/ThermostaticRadiatorValveManager.cpp | 2 +- .../identify-server/identify-server.cpp | 3 --- src/app/util/attribute-storage.cpp | 9 +++---- src/app/util/attribute-table.cpp | 6 +---- src/app/util/common.h | 24 ------------------- src/app/util/util.cpp | 4 +++- 7 files changed, 8 insertions(+), 41 deletions(-) delete mode 100644 src/app/util/common.h diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 69613217033e8b..e0255646dbc487 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -114,7 +114,6 @@ jobs: --known-failure app/util/attribute-table.h \ --known-failure app/util/binding-table.cpp \ --known-failure app/util/binding-table.h \ - --known-failure app/util/common.h \ --known-failure app/util/config.h \ --known-failure app/util/DataModelHandler.cpp \ --known-failure app/util/DataModelHandler.h \ diff --git a/examples/thermostat/qpg/src/ThermostaticRadiatorValveManager.cpp b/examples/thermostat/qpg/src/ThermostaticRadiatorValveManager.cpp index 55173272977964..a7375d54dc45ac 100644 --- a/examples/thermostat/qpg/src/ThermostaticRadiatorValveManager.cpp +++ b/examples/thermostat/qpg/src/ThermostaticRadiatorValveManager.cpp @@ -23,7 +23,7 @@ #include "AppConfig.h" #include "AppTask.h" -#include "app/util/common.h" + #include #include diff --git a/src/app/clusters/identify-server/identify-server.cpp b/src/app/clusters/identify-server/identify-server.cpp index 257adf934a5328..6ea8a34ca4db33 100644 --- a/src/app/clusters/identify-server/identify-server.cpp +++ b/src/app/clusters/identify-server/identify-server.cpp @@ -24,10 +24,7 @@ #include #include #include - #include -#include -#include #include #include #include diff --git a/src/app/util/attribute-storage.cpp b/src/app/util/attribute-storage.cpp index bd785c5b9682b1..0b94cc8f4c211c 100644 --- a/src/app/util/attribute-storage.cpp +++ b/src/app/util/attribute-storage.cpp @@ -15,12 +15,12 @@ * limitations under the License. */ -#include "app/util/common.h" +#include + #include #include #include #include -#include #include #include #include @@ -36,10 +36,7 @@ using chip::Protocols::InteractionModel::Status; // - zap-generated/callback.h is needed because endpoint_config will call the // corresponding callbacks (via GENERATED_FUNCTION_ARRAYS) and the include // for it is: -// util/common.h -// -> util/af.h -// -> util/config.h -// -> zap-generated/endpoint_config.h +// util/config.h -> zap-generated/endpoint_config.h #include using namespace chip; diff --git a/src/app/util/attribute-table.cpp b/src/app/util/attribute-table.cpp index d16942646ba929..de68b7e6a77f98 100644 --- a/src/app/util/attribute-table.cpp +++ b/src/app/util/attribute-table.cpp @@ -14,13 +14,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - -// this file contains all the common includes for clusters in the zcl-util +#include #include - -// for pulling in defines dealing with EITHER server or client -#include "app/util/common.h" #include #include #include diff --git a/src/app/util/common.h b/src/app/util/common.h deleted file mode 100644 index c2e42889313ddf..00000000000000 --- a/src/app/util/common.h +++ /dev/null @@ -1,24 +0,0 @@ -/** - * - * Copyright (c) 2020 Project CHIP Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#pragma once - -// App framework -#include -#include -#include -#include diff --git a/src/app/util/util.cpp b/src/app/util/util.cpp index e327673fc3cbf4..e8163547d94d53 100644 --- a/src/app/util/util.cpp +++ b/src/app/util/util.cpp @@ -15,12 +15,14 @@ * limitations under the License. */ -#include "app/util/common.h" +#include + #include #include #include #include #include +#include #include #include #include From 0a54586c2e73b4571c489938ad8aefe00cc511ee Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 26 Feb 2024 17:10:32 +0000 Subject: [PATCH 088/385] Bump third_party/imgui/repo from `5360903` to `277ae93` (#32317) Bumps [third_party/imgui/repo](https://github.com/ocornut/imgui) from `5360903` to `277ae93`. - [Release notes](https://github.com/ocornut/imgui/releases) - [Commits](https://github.com/ocornut/imgui/compare/536090303a8fca7d896f77d6d63dc59249bc87f4...277ae93c41314ba5f4c7444f37c4319cdf07e8cf) --- updated-dependencies: - dependency-name: third_party/imgui/repo dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- third_party/imgui/repo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/third_party/imgui/repo b/third_party/imgui/repo index 536090303a8fca..277ae93c41314b 160000 --- a/third_party/imgui/repo +++ b/third_party/imgui/repo @@ -1 +1 @@ -Subproject commit 536090303a8fca7d896f77d6d63dc59249bc87f4 +Subproject commit 277ae93c41314ba5f4c7444f37c4319cdf07e8cf From 5b1b617d62fecb655a3634fe61924b3fd4702ee7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 26 Feb 2024 17:10:45 +0000 Subject: [PATCH 089/385] Bump third_party/nanopb/repo from `1f0c2e1` to `41319af` (#32314) Bumps [third_party/nanopb/repo](https://github.com/nanopb/nanopb) from `1f0c2e1` to `41319af`. - [Commits](https://github.com/nanopb/nanopb/compare/1f0c2e19c661f18dd88428858b8e965a26589e03...41319af88e569d4af31ea28a08fd2580a1f6655c) --- updated-dependencies: - dependency-name: third_party/nanopb/repo dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- third_party/nanopb/repo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/third_party/nanopb/repo b/third_party/nanopb/repo index 1f0c2e19c661f1..41319af88e569d 160000 --- a/third_party/nanopb/repo +++ b/third_party/nanopb/repo @@ -1 +1 @@ -Subproject commit 1f0c2e19c661f18dd88428858b8e965a26589e03 +Subproject commit 41319af88e569d4af31ea28a08fd2580a1f6655c From 9c6cf9a1b2e2130bd98d522bb4076cc6152b9d73 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 26 Feb 2024 17:28:45 +0000 Subject: [PATCH 090/385] Bump third_party/mbedtls/repo from `039c903` to `36e6bd6` (#32316) Bumps [third_party/mbedtls/repo](https://github.com/ARMmbed/mbedtls) from `039c903` to `36e6bd6`. - [Release notes](https://github.com/ARMmbed/mbedtls/releases) - [Commits](https://github.com/ARMmbed/mbedtls/compare/039c903e7b2882af8e85ce5e090fd44e6a9d2289...36e6bd6926560933583dc04a7f92f69bdbafe8bd) --- updated-dependencies: - dependency-name: third_party/mbedtls/repo dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- third_party/mbedtls/repo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/third_party/mbedtls/repo b/third_party/mbedtls/repo index 039c903e7b2882..36e6bd69265609 160000 --- a/third_party/mbedtls/repo +++ b/third_party/mbedtls/repo @@ -1 +1 @@ -Subproject commit 039c903e7b2882af8e85ce5e090fd44e6a9d2289 +Subproject commit 36e6bd6926560933583dc04a7f92f69bdbafe8bd From ee133f7879c95101325156cf60e6aa6359db0faa Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 26 Feb 2024 18:27:27 +0000 Subject: [PATCH 091/385] Bump third_party/openthread/repo from `33574ad` to `f0b6fce` (#32313) Bumps [third_party/openthread/repo](https://github.com/openthread/openthread) from `33574ad` to `f0b6fce`. - [Release notes](https://github.com/openthread/openthread/releases) - [Commits](https://github.com/openthread/openthread/compare/33574ad4175ffb088bcca047f4c8d5fb240d1495...f0b6fcea6ef77c9a54ab11767593f9a8798e3662) --- updated-dependencies: - dependency-name: third_party/openthread/repo dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- third_party/openthread/repo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/third_party/openthread/repo b/third_party/openthread/repo index 33574ad4175ffb..f0b6fcea6ef77c 160000 --- a/third_party/openthread/repo +++ b/third_party/openthread/repo @@ -1 +1 @@ -Subproject commit 33574ad4175ffb088bcca047f4c8d5fb240d1495 +Subproject commit f0b6fcea6ef77c9a54ab11767593f9a8798e3662 From effff5953e51d55931399f1764c142b54569d0b5 Mon Sep 17 00:00:00 2001 From: andrei-menzopol <96489227+andrei-menzopol@users.noreply.github.com> Date: Mon, 26 Feb 2024 20:53:46 +0200 Subject: [PATCH 092/385] [Docker][NXP] Update Docker image for K32W1 SDK (#32312) Signed-off-by: Andrei Menzopol --- integrations/docker/images/base/chip-build/version | 2 +- .../docker/images/stage-2/chip-build-k32w/Dockerfile | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/integrations/docker/images/base/chip-build/version b/integrations/docker/images/base/chip-build/version index 7c7cf32a71a021..fe142046be7c1c 100644 --- a/integrations/docker/images/base/chip-build/version +++ b/integrations/docker/images/base/chip-build/version @@ -1 +1 @@ -37 : [NXP] Update Docker image for RW61X SDK +38 : [NXP] Update Docker image for K32W1 SDK diff --git a/integrations/docker/images/stage-2/chip-build-k32w/Dockerfile b/integrations/docker/images/stage-2/chip-build-k32w/Dockerfile index 309bc061d5fc20..908c882da75191 100644 --- a/integrations/docker/images/stage-2/chip-build-k32w/Dockerfile +++ b/integrations/docker/images/stage-2/chip-build-k32w/Dockerfile @@ -24,9 +24,9 @@ RUN set -x \ RUN set -x \ && mkdir -p k32w1 \ - && wget https://cache.nxp.com/lgfiles/bsps/SDK_2_12_6_K32W148-EVK.zip \ - && unzip SDK_2_12_6_K32W148-EVK.zip -d k32w1 \ - && rm -rf SDK_2_12_6_K32W148-EVK.zip + && wget https://cache.nxp.com/lgfiles/bsps/SDK_2_12_7_K32W148-EVK.zip \ + && unzip SDK_2_12_7_K32W148-EVK.zip -d k32w1 \ + && rm -rf SDK_2_12_7_K32W148-EVK.zip FROM ghcr.io/project-chip/chip-build:${VERSION} From 3b407b1209aeddfa0cd1bb9a35e31c6be87a8613 Mon Sep 17 00:00:00 2001 From: joonhaengHeo <85541460+joonhaengHeo@users.noreply.github.com> Date: Tue, 27 Feb 2024 04:07:45 +0900 Subject: [PATCH 093/385] [Android] Support General value TLV parsing (#32285) * Support General value parsing * Restyled by clang-format * Add List, Array TLV * Restyled by clang-format --------- Co-authored-by: Restyled.io --- src/controller/java/AndroidCallbacks.cpp | 126 ++++++++++++++++++++++- 1 file changed, 121 insertions(+), 5 deletions(-) diff --git a/src/controller/java/AndroidCallbacks.cpp b/src/controller/java/AndroidCallbacks.cpp index 01ef820f82c6ed..fb7975262dff57 100644 --- a/src/controller/java/AndroidCallbacks.cpp +++ b/src/controller/java/AndroidCallbacks.cpp @@ -41,6 +41,8 @@ static const int MILLIS_SINCE_EPOCH = 1; // Add the bytes for attribute tag(1:control + 8:tag + 8:length) and structure(1:struct + 1:close container) static const int EXTRA_SPACE_FOR_ATTRIBUTE_TAG = 19; +jobject DecodeGeneralTLVValue(JNIEnv * env, TLV::TLVReader & readerForGeneralValueObject, CHIP_ERROR & err); + GetConnectedDeviceCallback::GetConnectedDeviceCallback(jobject wrapperCallback, jobject javaCallback, const char * callbackClassSignature) : mOnSuccess(OnDeviceConnectedFn, this), @@ -314,20 +316,24 @@ void ReportCallback::OnAttributeData(const app::ConcreteDataAttributePath & aPat readerForJavaTLV.Init(*apData); jobject value = nullptr; -#ifdef USE_JAVA_TLV_ENCODE_DECODE TLV::TLVReader readerForJavaObject; readerForJavaObject.Init(*apData); - +#ifdef USE_JAVA_TLV_ENCODE_DECODE value = DecodeAttributeValue(aPath, readerForJavaObject, &err); // If we don't know this attribute, suppress it. if (err == CHIP_ERROR_IM_MALFORMED_ATTRIBUTE_PATH_IB) { - err = CHIP_NO_ERROR; + TLV::TLVReader readerForGeneralValueObject; + readerForGeneralValueObject.Init(*apData); + value = DecodeGeneralTLVValue(env, readerForGeneralValueObject, err); + err = CHIP_NO_ERROR; } VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Controller, "Fail to decode attribute with error %s", ErrorStr(err)); aPath.LogPath()); VerifyOrReturn(!env->ExceptionCheck(), env->ExceptionDescribe()); +#else + value = DecodeGeneralTLVValue(env, readerForJavaObject, err); #endif // Create TLV byte array to pass to Java layer size_t bufferLen = readerForJavaTLV.GetRemainingLength() + readerForJavaTLV.GetLengthRead(); @@ -468,18 +474,23 @@ void ReportCallback::OnEventData(const app::EventHeader & aEventHeader, TLV::TLV } jobject value = nullptr; -#ifdef USE_JAVA_TLV_ENCODE_DECODE TLV::TLVReader readerForJavaObject; readerForJavaObject.Init(*apData); +#ifdef USE_JAVA_TLV_ENCODE_DECODE value = DecodeEventValue(aEventHeader.mPath, readerForJavaObject, &err); // If we don't know this event, just skip it. if (err == CHIP_ERROR_IM_MALFORMED_EVENT_PATH_IB) { - err = CHIP_NO_ERROR; + TLV::TLVReader readerForGeneralValueObject; + readerForGeneralValueObject.Init(*apData); + value = DecodeGeneralTLVValue(env, readerForGeneralValueObject, err); + err = CHIP_NO_ERROR; } VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Controller, "Fail to decode event with error %s", ErrorStr(err)); aEventHeader.LogPath()); VerifyOrReturn(!env->ExceptionCheck(), env->ExceptionDescribe()); +#else + value = DecodeGeneralTLVValue(env, readerForJavaObject, err); #endif // Create TLV byte array to pass to Java layer @@ -907,6 +918,111 @@ void InvokeCallback::ReportError(const char * message, ChipError::StorageType er VerifyOrReturn(!env->ExceptionCheck(), env->ExceptionDescribe()); } +jobject DecodeGeneralTLVValue(JNIEnv * env, TLV::TLVReader & readerForGeneralValueObject, CHIP_ERROR & err) +{ + jobject retValue = nullptr; + + switch (readerForGeneralValueObject.GetType()) + { + case TLV::kTLVType_SignedInteger: { + int64_t signedValue = 0; + VerifyOrReturnValue(readerForGeneralValueObject.Get(signedValue) == CHIP_NO_ERROR, nullptr, + ChipLogProgress(Controller, "Get TLV Value fail!")); + err = JniReferences::GetInstance().CreateBoxedObject("java/lang/Long", "(J)V", static_cast(signedValue), + retValue); + VerifyOrReturnValue(err == CHIP_NO_ERROR, nullptr, ChipLogProgress(Controller, "Create Boxed Object fail!")); + return retValue; + } + case TLV::kTLVType_UnsignedInteger: { + uint64_t unsignedValue = 0; + VerifyOrReturnValue(readerForGeneralValueObject.Get(unsignedValue) == CHIP_NO_ERROR, nullptr, + ChipLogProgress(Controller, "Get TLV Value fail!")); + err = JniReferences::GetInstance().CreateBoxedObject("java/lang/Long", "(J)V", static_cast(unsignedValue), + retValue); + VerifyOrReturnValue(err == CHIP_NO_ERROR, nullptr, ChipLogProgress(Controller, "Create Boxed Object fail!")); + return retValue; + } + case TLV::kTLVType_Boolean: { + bool booleanValue = false; + VerifyOrReturnValue(readerForGeneralValueObject.Get(booleanValue) == CHIP_NO_ERROR, nullptr, + ChipLogProgress(Controller, "Get TLV Value fail!")); + err = JniReferences::GetInstance().CreateBoxedObject("java/lang/Boolean", "(Z)V", + static_cast(booleanValue), retValue); + VerifyOrReturnValue(err == CHIP_NO_ERROR, nullptr, ChipLogProgress(Controller, "Create Boxed Object fail!")); + return retValue; + } + case TLV::kTLVType_FloatingPointNumber: { + double doubleValue = 0.0; + VerifyOrReturnValue(readerForGeneralValueObject.Get(doubleValue) == CHIP_NO_ERROR, nullptr, + ChipLogProgress(Controller, "Get TLV Value fail!")); + err = JniReferences::GetInstance().CreateBoxedObject("java/lang/Double", "(D)V", static_cast(doubleValue), + retValue); + VerifyOrReturnValue(err == CHIP_NO_ERROR, nullptr, ChipLogProgress(Controller, "Create Boxed Object fail!")); + return retValue; + } + case TLV::kTLVType_UTF8String: { + uint32_t bufferLen = readerForGeneralValueObject.GetLength(); + std::unique_ptr buffer = std::unique_ptr(new char[bufferLen + 1]); + err = readerForGeneralValueObject.GetString(buffer.get(), bufferLen + 1); + VerifyOrReturnValue(err == CHIP_NO_ERROR, nullptr, ChipLogProgress(Controller, "Get TLV Value fail!")); + chip::CharSpan valueSpan(buffer.get(), bufferLen); + chip::JniReferences::GetInstance().CharToStringUTF(valueSpan, retValue); + return retValue; + } + case TLV::kTLVType_ByteString: { + uint32_t bufferLen = readerForGeneralValueObject.GetLength(); + std::unique_ptr buffer = std::unique_ptr(new uint8_t[bufferLen + 1]); + err = readerForGeneralValueObject.GetBytes(buffer.get(), bufferLen + 1); + VerifyOrReturnValue(err == CHIP_NO_ERROR, nullptr, ChipLogProgress(Controller, "Get TLV Value fail!")); + + jbyteArray valueByteArray = env->NewByteArray(static_cast(bufferLen)); + env->SetByteArrayRegion(valueByteArray, 0, static_cast(bufferLen), reinterpret_cast(buffer.get())); + + return static_cast(valueByteArray); + } + case TLV::kTLVType_Array: { + TLV::TLVType containerType; + err = readerForGeneralValueObject.EnterContainer(containerType); + VerifyOrReturnValue(err == CHIP_NO_ERROR, nullptr, + ChipLogProgress(Controller, "EnterContainer fail! : %" CHIP_ERROR_FORMAT, err.Format())); + err = chip::JniReferences::GetInstance().CreateArrayList(retValue); + VerifyOrReturnValue(err == CHIP_NO_ERROR, nullptr, + ChipLogProgress(Controller, "CreateArrayList fail! : %" CHIP_ERROR_FORMAT, err.Format())); + while (readerForGeneralValueObject.Next() == CHIP_NO_ERROR) + { + jobject inValue = DecodeGeneralTLVValue(env, readerForGeneralValueObject, err); + VerifyOrReturnValue(err == CHIP_NO_ERROR, nullptr, + ChipLogProgress(Controller, "Can't parse general value : %" CHIP_ERROR_FORMAT, err.Format())); + err = chip::JniReferences::GetInstance().AddToList(retValue, inValue); + } + return retValue; + } + case TLV::kTLVType_List: { + TLV::TLVType containerType; + err = readerForGeneralValueObject.EnterContainer(containerType); + VerifyOrReturnValue(err == CHIP_NO_ERROR, nullptr, + ChipLogProgress(Controller, "EnterContainer fail! : %" CHIP_ERROR_FORMAT, err.Format())); + err = chip::JniReferences::GetInstance().CreateArrayList(retValue); + VerifyOrReturnValue(err == CHIP_NO_ERROR, nullptr, + ChipLogProgress(Controller, "CreateArrayList fail! : %" CHIP_ERROR_FORMAT, err.Format())); + while (readerForGeneralValueObject.Next() == CHIP_NO_ERROR) + { + jobject inValue = DecodeGeneralTLVValue(env, readerForGeneralValueObject, err); + VerifyOrReturnValue(err == CHIP_NO_ERROR, nullptr, + ChipLogProgress(Controller, "Can't parse general value : %" CHIP_ERROR_FORMAT, err.Format())); + err = chip::JniReferences::GetInstance().AddToList(retValue, inValue); + } + return retValue; + } + case TLV::kTLVType_Null: { + return nullptr; + } + default: + err = CHIP_ERROR_WRONG_TLV_TYPE; + return nullptr; + } +} + jlong newConnectedDeviceCallback(JNIEnv * env, jobject self, jobject callback) { chip::DeviceLayer::StackLock lock; From 49895313241524d9a90c65aae9a195435fc5aaab Mon Sep 17 00:00:00 2001 From: Wang Qixiang <43193572+wqx6@users.noreply.github.com> Date: Tue, 27 Feb 2024 03:13:57 +0800 Subject: [PATCH 094/385] ESP32: fix conversion error for EndpointQueueFilter (#32287) --- src/platform/ESP32/ConnectivityManagerImpl_WiFi.cpp | 4 ++-- src/platform/ESP32/ESP32EndpointQueueFilter.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/platform/ESP32/ConnectivityManagerImpl_WiFi.cpp b/src/platform/ESP32/ConnectivityManagerImpl_WiFi.cpp index 8fb52e7bb71629..5fefcb5490f059 100644 --- a/src/platform/ESP32/ConnectivityManagerImpl_WiFi.cpp +++ b/src/platform/ESP32/ConnectivityManagerImpl_WiFi.cpp @@ -1119,8 +1119,8 @@ void ConnectivityManagerImpl::OnStationIPv6AddressAvailable(const ip_event_got_i { uint8_t dig1 = (station_mac[i] & 0xF0) >> 4; uint8_t dig2 = station_mac[i] & 0x0F; - station_mac_str[2 * i] = dig1 > 9 ? ('A' + dig1 - 0xA) : ('0' + dig1); - station_mac_str[2 * i + 1] = dig2 > 9 ? ('A' + dig2 - 0xA) : ('0' + dig2); + station_mac_str[2 * i] = static_cast(dig1 > 9 ? ('A' + dig1 - 0xA) : ('0' + dig1)); + station_mac_str[2 * i + 1] = static_cast(dig2 > 9 ? ('A' + dig2 - 0xA) : ('0' + dig2)); } if (sEndpointQueueFilter.SetMdnsHostName(chip::CharSpan(station_mac_str)) == CHIP_NO_ERROR) { diff --git a/src/platform/ESP32/ESP32EndpointQueueFilter.h b/src/platform/ESP32/ESP32EndpointQueueFilter.h index e7d154dcf458af..031ea29b64d798 100644 --- a/src/platform/ESP32/ESP32EndpointQueueFilter.h +++ b/src/platform/ESP32/ESP32EndpointQueueFilter.h @@ -103,7 +103,7 @@ class ESP32EndpointQueueFilter : public EndpointQueueFilter { if (hostNameLowerCase[i] <= 'F' && hostNameLowerCase[i] >= 'A') { - hostNameLowerCase[i] = 'a' + hostNameLowerCase[i] - 'A'; + hostNameLowerCase[i] = static_cast('a' + hostNameLowerCase[i] - 'A'); } } return PayloadContains(payload, ByteSpan(mHostNameBuffer)) || PayloadContains(payload, ByteSpan(hostNameLowerCase)); From 44ca3957f15ed42f2e6d72fb1a4e1e827c8ed1da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ludovic=20BOU=C3=89?= Date: Mon, 26 Feb 2024 20:14:55 +0100 Subject: [PATCH 095/385] Add particulate matter (PM) events in AirQuality sensor README.md (#32255) * Update AirQuality sensor README.md Generate Particulate matter (PM) event * Update README.md --- .../air-quality-sensor-app/linux/README.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/examples/air-quality-sensor-app/linux/README.md b/examples/air-quality-sensor-app/linux/README.md index 73139ef4aeeacb..38a0adfb2fe7bf 100644 --- a/examples/air-quality-sensor-app/linux/README.md +++ b/examples/air-quality-sensor-app/linux/README.md @@ -165,3 +165,21 @@ value. ``` $ echo '{"Name":"NitrogenDioxideConcentrationMeasurement","NewValue":1}' > /tmp/chip_air_quality_fifo_ ``` + +Generate event `Pm1ConcentrationMeasurement`, to change the PM1 value. + +``` +echo '{"Name":"Pm1ConcentrationMeasurement","NewValue":1}' > /tmp/chip_air_quality_fifo_ +``` + +Generate event `Pm25ConcentrationMeasurement`, to change the PM2.5 value. + +``` +echo '{"Name":"Pm25ConcentrationMeasurement","NewValue":2.5}' > /tmp/chip_air_quality_fifo_ +``` + +Generate event `Pm10ConcentrationMeasurement`, to change the PM10 value. + +``` +echo '{"Name":"Pm10ConcentrationMeasurement","NewValue":10}' > /tmp/chip_air_quality_fifo_ +``` From 86a0265e9d894a6c23a1c778c786b8c4614af4e6 Mon Sep 17 00:00:00 2001 From: Andrei Litvin Date: Mon, 26 Feb 2024 15:44:12 -0500 Subject: [PATCH 096/385] Add a `ObjectPoolIterator::Type` class to allow begin/end iteration on active objects in memory pools. (#32126) * Remove PoolCommon: bad name, non-member method, very very limited usage * Restyle * Have a working iterator (and unit test) for static bitmap iterator * Start unit testing for nested loops * Fix tests and implementation * Added another test * Extra unit test that we iterate correctly * Added comment about returning null on failure * Fix compile on fixed size pools * Restyle * Support iteration depth since it seems we need to delete objects during looping ... ouch! * Update to also have a post-iteration clean when using iterators * Make sure iterators on pools have a type that can be passed around * Switch to not use a cast * Fix types ... use auto because types are messy, unsure why * Rename for smaller diff * Rename for smaller diff * Correct the comment * More comments cleanup * Remove useless comment * make things compile for NRF * Restyle * Update the comment * Update allocated to active in naming * Add comment regarding iteration depth * Undo submodule update --------- Co-authored-by: Andrei Litvin --- src/lib/support/Pool.cpp | 74 ++++++++++--- src/lib/support/Pool.h | 170 ++++++++++++++++++++++++++++- src/lib/support/tests/TestPool.cpp | 157 +++++++++++++++++++++++--- 3 files changed, 369 insertions(+), 32 deletions(-) diff --git a/src/lib/support/Pool.cpp b/src/lib/support/Pool.cpp index c32b46be45e819..555127a7082d67 100644 --- a/src/lib/support/Pool.cpp +++ b/src/lib/support/Pool.cpp @@ -127,6 +127,46 @@ Loop StaticAllocatorBitmap::ForEachActiveObjectInner(void * context, Lambda lamb return Loop::Finish; } +size_t StaticAllocatorBitmap::FirstActiveIndex() +{ + size_t idx = 0; + for (size_t word = 0; word * kBitChunkSize < Capacity(); ++word) + { + auto & usage = mUsage[word]; + auto value = usage.load(std::memory_order_relaxed); + for (size_t offset = 0; offset < kBitChunkSize && offset + word * kBitChunkSize < Capacity(); ++offset) + { + if ((value & (kBit1 << offset)) != 0) + { + return idx; + } + idx++; + } + } + VerifyOrDie(idx == mCapacity); + return mCapacity; +} + +size_t StaticAllocatorBitmap::NextActiveIndexAfter(size_t start) +{ + size_t idx = 0; + for (size_t word = 0; word * kBitChunkSize < Capacity(); ++word) + { + auto & usage = mUsage[word]; + auto value = usage.load(std::memory_order_relaxed); + for (size_t offset = 0; offset < kBitChunkSize && offset + word * kBitChunkSize < Capacity(); ++offset) + { + if (((value & (kBit1 << offset)) != 0) && (start < idx)) + { + return idx; + } + idx++; + } + } + VerifyOrDie(idx == mCapacity); + return mCapacity; +} + #if CHIP_SYSTEM_CONFIG_POOL_USE_HEAP HeapObjectListNode * HeapObjectList::FindNode(void * object) const @@ -159,24 +199,30 @@ Loop HeapObjectList::ForEachNode(void * context, Lambda lambda) p = p->mNext; } --mIterationDepth; - if (mIterationDepth == 0 && mHaveDeferredNodeRemovals) + CleanupDeferredReleases(); + return result; +} + +void HeapObjectList::CleanupDeferredReleases() +{ + if (mIterationDepth != 0 || !mHaveDeferredNodeRemovals) { - // Remove nodes for released objects. - p = mNext; - while (p != this) + return; + } + // Remove nodes for released objects. + HeapObjectListNode * p = mNext; + while (p != this) + { + HeapObjectListNode * next = p->mNext; + if (p->mObject == nullptr) { - HeapObjectListNode * next = p->mNext; - if (p->mObject == nullptr) - { - p->Remove(); - Platform::Delete(p); - } - p = next; + p->Remove(); + Platform::Delete(p); } - - mHaveDeferredNodeRemovals = false; + p = next; } - return result; + + mHaveDeferredNodeRemovals = false; } #endif // CHIP_SYSTEM_CONFIG_POOL_USE_HEAP diff --git a/src/lib/support/Pool.h b/src/lib/support/Pool.h index a3959fd1e868f9..e4fb31769f4193 100644 --- a/src/lib/support/Pool.h +++ b/src/lib/support/Pool.h @@ -36,6 +36,9 @@ namespace chip { +template +class BitmapActiveObjectIterator; + namespace internal { class Statistics @@ -91,6 +94,16 @@ class StaticAllocatorBitmap : public internal::StaticAllocatorBase void * At(size_t index) { return static_cast(mElements) + mElementSize * index; } size_t IndexOf(void * element); + /// Returns the first index that is active (i.e. allocated data). + /// + /// If nothing is active, this will return mCapacity + size_t FirstActiveIndex(); + + /// Returns the next active index after `start`. + /// + /// If nothing else active/allocated, returns mCapacity + size_t NextActiveIndexAfter(size_t start); + using Lambda = Loop (*)(void * context, void * object); Loop ForEachActiveObjectInner(void * context, Lambda lambda); Loop ForEachActiveObjectInner(void * context, Loop lambda(void * context, const void * object)) const @@ -102,6 +115,10 @@ class StaticAllocatorBitmap : public internal::StaticAllocatorBase void * mElements; const size_t mElementSize; std::atomic * mUsage; + + /// allow accessing direct At() calls + template + friend class ::chip::BitmapActiveObjectIterator; }; template @@ -132,9 +149,9 @@ struct HeapObjectListNode mPrev->mNext = mNext; } - void * mObject; - HeapObjectListNode * mNext; - HeapObjectListNode * mPrev; + void * mObject = nullptr; + HeapObjectListNode * mNext = nullptr; + HeapObjectListNode * mPrev = nullptr; }; struct HeapObjectList : HeapObjectListNode @@ -158,6 +175,9 @@ struct HeapObjectList : HeapObjectListNode return const_cast(this)->ForEachNode(context, reinterpret_cast(lambda)); } + /// Cleans up any deferred releases IFF iteration depth is 0 + void CleanupDeferredReleases(); + size_t mIterationDepth = 0; bool mHaveDeferredNodeRemovals = false; }; @@ -166,6 +186,46 @@ struct HeapObjectList : HeapObjectListNode } // namespace internal +/// Provides iteration over active objects in a Bitmap pool. +/// +/// Creating and releasing items within a pool does not invalidate +/// an iterator, however there are no guarantees which objects the +/// iterator will return (i.e. newly created objects while iterating +/// may be visible or not to the iterator depending where they are +/// allocated). +/// +/// You are not prevented from releasing the object the iterator +/// currently points at. In that case, iterator should be advanced. +template +class BitmapActiveObjectIterator +{ +public: + using value_type = T; + using pointer = T *; + using reference = T &; + + explicit BitmapActiveObjectIterator(internal::StaticAllocatorBitmap * pool, size_t idx) : mPool(pool), mIndex(idx) {} + BitmapActiveObjectIterator() {} + + bool operator==(const BitmapActiveObjectIterator & other) const + { + return (AtEnd() && other.AtEnd()) || ((mPool == other.mPool) && (mIndex == other.mIndex)); + } + bool operator!=(const BitmapActiveObjectIterator & other) const { return !(*this == other); } + BitmapActiveObjectIterator & operator++() + { + mIndex = mPool->NextActiveIndexAfter(mIndex); + return *this; + } + T * operator*() const { return static_cast(mPool->At(mIndex)); } + +private: + bool AtEnd() const { return (mPool == nullptr) || (mIndex >= mPool->Capacity()); } + + internal::StaticAllocatorBitmap * mPool = nullptr; // pool that this belongs to + size_t mIndex = std::numeric_limits::max(); +}; + /** * @class ObjectPool * @@ -205,6 +265,9 @@ class BitMapObjectPool : public internal::StaticAllocatorBitmap BitMapObjectPool() : StaticAllocatorBitmap(mData.mMemory, mUsage, N, sizeof(T)) {} ~BitMapObjectPool() { VerifyOrDie(Allocated() == 0); } + BitmapActiveObjectIterator begin() { return BitmapActiveObjectIterator(this, FirstActiveIndex()); } + BitmapActiveObjectIterator end() { return BitmapActiveObjectIterator(this, N); } + template T * CreateObject(Args &&... args) { @@ -331,6 +394,91 @@ class HeapObjectPool : public internal::Statistics, public HeapObjectPoolExitHan #endif // __SANITIZE_ADDRESS__ } + /// Provides iteration over active objects in the pool. + /// + /// NOTE: There is extra logic to allow objects release WHILE the iterator is + /// active while still allowing to advance the iterator. + /// This is done by flagging an iteration depth whenever an active + /// iterator exists. This also means that while a pool iterator exists, releasing + /// of tracking memory objects may be deferred until the last active iterator is + /// released. + class ActiveObjectIterator + { + public: + using value_type = T; + using pointer = T *; + using reference = T &; + + ActiveObjectIterator() {} + ActiveObjectIterator(const ActiveObjectIterator & other) : mCurrent(other.mCurrent), mEnd(other.mEnd) + { + if (mEnd != nullptr) + { + // Iteration depth is used to support `Release` while an iterator is active. + // + // Code was historically using this functionality, so we support it here + // as well: while iteration is active, iteration depth is > 0. When it + // goes to 0, then any deferred `Release()` calls are executed. + mEnd->mIterationDepth++; + } + } + + ActiveObjectIterator & operator=(const ActiveObjectIterator & other) + { + if (mEnd != nullptr) + { + mEnd->mIterationDepth--; + mEnd->CleanupDeferredReleases(); + } + mCurrent = other.mCurrent; + mEnd = other.mEnd; + mEnd->mIterationDepth++; + } + + ~ActiveObjectIterator() + { + if (mEnd != nullptr) + { + mEnd->mIterationDepth--; + mEnd->CleanupDeferredReleases(); + } + } + + bool operator==(const ActiveObjectIterator & other) const + { + // extra current/end compare is to have all "end iterators" + // compare as equal (in particular default active object iterator is the end + // of an iterator) + return (mCurrent == other.mCurrent) || ((mCurrent == mEnd) && (other.mCurrent == other.mEnd)); + } + bool operator!=(const ActiveObjectIterator & other) const { return !(*this == other); } + ActiveObjectIterator & operator++() + { + do + { + mCurrent = mCurrent->mNext; + } while ((mCurrent != mEnd) && (mCurrent->mObject == nullptr)); + return *this; + } + T * operator*() const { return static_cast(mCurrent->mObject); } + + protected: + friend class HeapObjectPool; + + explicit ActiveObjectIterator(internal::HeapObjectListNode * current, internal::HeapObjectList * end) : + mCurrent(current), mEnd(end) + { + mEnd->mIterationDepth++; + } + + private: + internal::HeapObjectListNode * mCurrent = nullptr; + internal::HeapObjectList * mEnd = nullptr; + }; + + ActiveObjectIterator begin() { return ActiveObjectIterator(mObjects.mNext, &mObjects); } + ActiveObjectIterator end() { return ActiveObjectIterator(&mObjects, &mObjects); } + template T * CreateObject(Args &&... args) { @@ -456,6 +604,15 @@ enum class ObjectPoolMem #endif // CHIP_SYSTEM_CONFIG_POOL_USE_HEAP }; +template +struct ObjectPoolIterator; + +template +struct ObjectPoolIterator +{ + using Type = BitmapActiveObjectIterator; +}; + template class ObjectPool; @@ -465,6 +622,13 @@ class ObjectPool : public BitMapObjectPool }; #if CHIP_SYSTEM_CONFIG_POOL_USE_HEAP + +template +struct ObjectPoolIterator +{ + using Type = typename HeapObjectPool::ActiveObjectIterator; +}; + template class ObjectPool : public HeapObjectPool { diff --git a/src/lib/support/tests/TestPool.cpp b/src/lib/support/tests/TestPool.cpp index b78d2b3e281107..963a7b3c52f7ea 100644 --- a/src/lib/support/tests/TestPool.cpp +++ b/src/lib/support/tests/TestPool.cpp @@ -234,25 +234,54 @@ void TestForEachActiveObject(nlTestSuite * inSuite, void * inContext) objIds.insert(i); } + // Default constructor of an iterator should be pointing to the pool end. + { + typename ObjectPoolIterator::Type defaultIterator; + NL_TEST_ASSERT(inSuite, defaultIterator == pool.end()); + } + // Verify that iteration visits all objects. size_t count = 0; - size_t sum = 0; - pool.ForEachActiveObject([&](S * object) { - NL_TEST_ASSERT(inSuite, object != nullptr); - if (object == nullptr) - { - // NL_TEST_ASSERT doesn't stop running the test and we want to avoid nullptr dereference. + { + size_t sum = 0; + pool.ForEachActiveObject([&](S * object) { + NL_TEST_ASSERT(inSuite, object != nullptr); + if (object == nullptr) + { + // NL_TEST_ASSERT doesn't stop running the test and we want to avoid nullptr dereference. + return Loop::Continue; + } + NL_TEST_ASSERT(inSuite, objIds.count(object->mId) == 1); + objIds.erase(object->mId); + ++count; + sum += object->mId; return Loop::Continue; + }); + NL_TEST_ASSERT(inSuite, count == kSize); + NL_TEST_ASSERT(inSuite, sum == kSize * (kSize - 1) / 2); + NL_TEST_ASSERT(inSuite, objIds.size() == 0); + } + + // Test begin/end iteration + { + // re-create the above test environment, this time using iterators + for (size_t i = 0; i < kSize; ++i) + { + objIds.insert(i); } - NL_TEST_ASSERT(inSuite, objIds.count(object->mId) == 1); - objIds.erase(object->mId); - ++count; - sum += object->mId; - return Loop::Continue; - }); - NL_TEST_ASSERT(inSuite, count == kSize); - NL_TEST_ASSERT(inSuite, sum == kSize * (kSize - 1) / 2); - NL_TEST_ASSERT(inSuite, objIds.size() == 0); + count = 0; + size_t sum = 0; + for (auto v = pool.begin(); v != pool.end(); ++v) + { + NL_TEST_ASSERT(inSuite, objIds.count((*v)->mId) == 1); + objIds.erase((*v)->mId); + ++count; + sum += (*v)->mId; + } + NL_TEST_ASSERT(inSuite, count == kSize); + NL_TEST_ASSERT(inSuite, sum == kSize * (kSize - 1) / 2); + NL_TEST_ASSERT(inSuite, objIds.size() == 0); + } // Verify that returning Loop::Break stops iterating. count = 0; @@ -285,6 +314,42 @@ void TestForEachActiveObject(nlTestSuite * inSuite, void * inContext) NL_TEST_ASSERT(inSuite, count == (kSize - 1) * kSize / 2); NL_TEST_ASSERT(inSuite, objIds.size() == 0); + // Verify that iteration can be nested for iterator types + { + count = 0; + for (auto v : pool) + { + objIds.insert(v->mId); + if (++count == kSize / 2) + { + break; + } + } + + count = 0; + for (auto outer : pool) + { + if (objIds.count(outer->mId) != 1) + { + continue; + } + + for (auto inner : pool) + { + if (inner == outer) + { + objIds.erase(inner->mId); + } + else + { + ++count; + } + } + } + NL_TEST_ASSERT(inSuite, count == (kSize - 1) * kSize / 2); + NL_TEST_ASSERT(inSuite, objIds.size() == 0); + } + count = 0; pool.ForEachActiveObject([&](S * object) { ++count; @@ -334,6 +399,68 @@ void TestForEachActiveObject(nlTestSuite * inSuite, void * inContext) NL_TEST_ASSERT(inSuite, count >= kSize / 2); NL_TEST_ASSERT(inSuite, count <= kSize); + // Test begin/end iteration + { + count = 0; + for (auto object : pool) + { + ++count; + if ((object->mId % 2) == 0) + { + objArray[object->mId] = nullptr; + // NOTE: this explicitly tests if pool supports releasing while iterating + // this MUST be supported by contract of Pool iterators + pool.ReleaseObject(object); + } + else + { + objIds.insert(object->mId); + } + } + NL_TEST_ASSERT(inSuite, count == kSize); + NL_TEST_ASSERT(inSuite, objIds.size() == kSize / 2); + + // validate we iterate only over active objects + for (auto object : pool) + { + NL_TEST_ASSERT(inSuite, (object->mId % 2) == 1); + } + + for (size_t i = 0; i < kSize; ++i) + { + if ((i % 2) == 0) + { + NL_TEST_ASSERT(inSuite, objArray[i] == nullptr); + } + else + { + NL_TEST_ASSERT(inSuite, objArray[i] != nullptr); + NL_TEST_ASSERT(inSuite, objArray[i]->mId == i); + } + } + + count = 0; + for (auto object : pool) + { + ++count; + if ((object->mId % 2) != 1) + { + continue; + } + size_t id = object->mId - 1; + NL_TEST_ASSERT(inSuite, objArray[id] == nullptr); + objArray[id] = pool.CreateObject(id); + NL_TEST_ASSERT(inSuite, objArray[id] != nullptr); + } + for (size_t i = 0; i < kSize; ++i) + { + NL_TEST_ASSERT(inSuite, objArray[i] != nullptr); + NL_TEST_ASSERT(inSuite, objArray[i]->mId == i); + } + NL_TEST_ASSERT(inSuite, count >= kSize / 2); + NL_TEST_ASSERT(inSuite, count <= kSize); + } + pool.ReleaseAll(); } From dbfd4b53d64be6109cdd157bad4edc4bfe785c10 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 26 Feb 2024 21:09:53 +0000 Subject: [PATCH 097/385] Bump third_party/pigweed/repo from `5165b9c` to `544a7b5` (#32315) * Bump third_party/pigweed/repo from `5165b9c` to `544a7b5` Bumps [third_party/pigweed/repo](https://github.com/google/pigweed) from `5165b9c` to `544a7b5`. - [Commits](https://github.com/google/pigweed/compare/5165b9c17a9933b8d0714ef701421bf065d5d66a...544a7b57c35e11690c73c390625a86a9e9a3ae51) --- updated-dependencies: - dependency-name: third_party/pigweed/repo dependency-type: direct:production ... Signed-off-by: dependabot[bot] * zap regen ... again.. we seem to go back and forth on format here --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Andrei Litvin --- .../app-templates/endpoint_config.h | 34 +++++++++---------- third_party/pigweed/repo | 2 +- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/scripts/tools/zap/tests/outputs/all-clusters-app/app-templates/endpoint_config.h b/scripts/tools/zap/tests/outputs/all-clusters-app/app-templates/endpoint_config.h index 38f04fbfea5857..6985b44ac27da5 100644 --- a/scripts/tools/zap/tests/outputs/all-clusters-app/app-templates/endpoint_config.h +++ b/scripts/tools/zap/tests/outputs/all-clusters-app/app-templates/endpoint_config.h @@ -302,15 +302,15 @@ { (uint16_t) 0x0, (uint16_t) 0x0, (uint16_t) 0x7 }, /* ControlMode */ \ \ /* Endpoint: 1, Cluster: Thermostat (server) */ \ - { (uint16_t) 0xA28, (uint16_t) - 0x6AB3, (uint16_t) 0x7FFF }, /* OccupiedCoolingSetpoint */ \ - { (uint16_t) 0x7D0, (uint16_t) - 0x6AB3, (uint16_t) 0x7FFF }, /* OccupiedHeatingSetpoint */ \ - { (uint16_t) 0x2BC, (uint16_t) - 0x6AB3, (uint16_t) 0x7FFF }, /* MinHeatSetpointLimit */ \ - { (uint16_t) 0xBB8, (uint16_t) - 0x6AB3, (uint16_t) 0x7FFF }, /* MaxHeatSetpointLimit */ \ - { (uint16_t) 0x640, (uint16_t) - 0x6AB3, (uint16_t) 0x7FFF }, /* MinCoolSetpointLimit */ \ - { (uint16_t) 0xC80, (uint16_t) - 0x6AB3, (uint16_t) 0x7FFF }, /* MaxCoolSetpointLimit */ \ - { (uint16_t) 0x19, (uint16_t) 0x0, (uint16_t) 0x19 }, /* MinSetpointDeadBand */ \ - { (uint16_t) 0x4, (uint16_t) 0x0, (uint16_t) 0x5 }, /* ControlSequenceOfOperation */ \ - { (uint16_t) 0x1, (uint16_t) 0x0, (uint16_t) 0x9 }, /* SystemMode */ \ + { (uint16_t) 0xA28, (uint16_t) -0x6AB3, (uint16_t) 0x7FFF }, /* OccupiedCoolingSetpoint */ \ + { (uint16_t) 0x7D0, (uint16_t) -0x6AB3, (uint16_t) 0x7FFF }, /* OccupiedHeatingSetpoint */ \ + { (uint16_t) 0x2BC, (uint16_t) -0x6AB3, (uint16_t) 0x7FFF }, /* MinHeatSetpointLimit */ \ + { (uint16_t) 0xBB8, (uint16_t) -0x6AB3, (uint16_t) 0x7FFF }, /* MaxHeatSetpointLimit */ \ + { (uint16_t) 0x640, (uint16_t) -0x6AB3, (uint16_t) 0x7FFF }, /* MinCoolSetpointLimit */ \ + { (uint16_t) 0xC80, (uint16_t) -0x6AB3, (uint16_t) 0x7FFF }, /* MaxCoolSetpointLimit */ \ + { (uint16_t) 0x19, (uint16_t) 0x0, (uint16_t) 0x19 }, /* MinSetpointDeadBand */ \ + { (uint16_t) 0x4, (uint16_t) 0x0, (uint16_t) 0x5 }, /* ControlSequenceOfOperation */ \ + { (uint16_t) 0x1, (uint16_t) 0x0, (uint16_t) 0x9 }, /* SystemMode */ \ \ /* Endpoint: 1, Cluster: Fan Control (server) */ \ { (uint16_t) 0x0, (uint16_t) 0x0, (uint16_t) 0x6 }, /* FanMode */ \ @@ -334,14 +334,14 @@ { (uint16_t) 0x0, (uint16_t) 0x0, (uint16_t) 0xFEFF }, /* StartUpColorTemperatureMireds */ \ \ /* Endpoint: 1, Cluster: Unit Testing (server) */ \ - { (uint16_t) 0x46, (uint16_t) 0x14, (uint16_t) 0x64 }, /* range_restricted_int8u */ \ - { (uint16_t) - 0x14, (uint16_t) - 0x28, (uint16_t) 0x32 }, /* range_restricted_int8s */ \ - { (uint16_t) 0xC8, (uint16_t) 0x64, (uint16_t) 0x3E8 }, /* range_restricted_int16u */ \ - { (uint16_t) - 0x64, (uint16_t) - 0x96, (uint16_t) 0xC8 }, /* range_restricted_int16s */ \ - { (uint16_t) 0x46, (uint16_t) 0x14, (uint16_t) 0x64 }, /* nullable_range_restricted_int8u */ \ - { (uint16_t) - 0x14, (uint16_t) - 0x28, (uint16_t) 0x32 }, /* nullable_range_restricted_int8s */ \ - { (uint16_t) 0xC8, (uint16_t) 0x64, (uint16_t) 0x3E8 }, /* nullable_range_restricted_int16u */ \ - { (uint16_t) - 0x64, (uint16_t) - 0x96, (uint16_t) 0xC8 }, /* nullable_range_restricted_int16s */ \ + { (uint16_t) 0x46, (uint16_t) 0x14, (uint16_t) 0x64 }, /* range_restricted_int8u */ \ + { (uint16_t) -0x14, (uint16_t) -0x28, (uint16_t) 0x32 }, /* range_restricted_int8s */ \ + { (uint16_t) 0xC8, (uint16_t) 0x64, (uint16_t) 0x3E8 }, /* range_restricted_int16u */ \ + { (uint16_t) -0x64, (uint16_t) -0x96, (uint16_t) 0xC8 }, /* range_restricted_int16s */ \ + { (uint16_t) 0x46, (uint16_t) 0x14, (uint16_t) 0x64 }, /* nullable_range_restricted_int8u */ \ + { (uint16_t) -0x14, (uint16_t) -0x28, (uint16_t) 0x32 }, /* nullable_range_restricted_int8s */ \ + { (uint16_t) 0xC8, (uint16_t) 0x64, (uint16_t) 0x3E8 }, /* nullable_range_restricted_int16u */ \ + { (uint16_t) -0x64, (uint16_t) -0x96, (uint16_t) 0xC8 }, /* nullable_range_restricted_int16s */ \ \ /* Endpoint: 2, Cluster: On/Off (server) */ \ { \ diff --git a/third_party/pigweed/repo b/third_party/pigweed/repo index 5165b9c17a9933..544a7b57c35e11 160000 --- a/third_party/pigweed/repo +++ b/third_party/pigweed/repo @@ -1 +1 @@ -Subproject commit 5165b9c17a9933b8d0714ef701421bf065d5d66a +Subproject commit 544a7b57c35e11690c73c390625a86a9e9a3ae51 From 2e35d01d984d29df4bc6f174d58b7888c72ebfe7 Mon Sep 17 00:00:00 2001 From: Carolina Lopes <116589288+ccruzagralopes@users.noreply.github.com> Date: Mon, 26 Feb 2024 18:12:11 -0300 Subject: [PATCH 098/385] Support user input for python tests in TH (#32299) * Add supporting functions * Update TC-RVCOPSTATE-2.4 * Fix linting errors * Restyled by isort * Update src/python_testing/matter_testing_support.py --------- Co-authored-by: Restyled.io --- .../matter_yamltests/hooks.py | 11 ++++++++ src/python_testing/TC_RVCOPSTATE_2_4.py | 20 +++++++------ src/python_testing/matter_testing_support.py | 28 +++++++++++++++++++ 3 files changed, 51 insertions(+), 8 deletions(-) diff --git a/scripts/py_matter_yamltests/matter_yamltests/hooks.py b/scripts/py_matter_yamltests/matter_yamltests/hooks.py index 575a05d95871ad..9b202c7e94d122 100644 --- a/scripts/py_matter_yamltests/matter_yamltests/hooks.py +++ b/scripts/py_matter_yamltests/matter_yamltests/hooks.py @@ -13,6 +13,8 @@ # See the License for the specific language governing permissions and # limitations under the License. +from typing import Optional + from .parser import TestStep @@ -213,6 +215,15 @@ async def step_manual(self): """ pass + def show_prompt(self, + msg: str, + placeholder: Optional[str] = None, + default_value: Optional[str] = None) -> None: + """ + This method is called when the step needs to ask the user to perform some action or provide some value. + """ + pass + class WebSocketRunnerHooks(): def connecting(self, url: str): diff --git a/src/python_testing/TC_RVCOPSTATE_2_4.py b/src/python_testing/TC_RVCOPSTATE_2_4.py index 7352fbd089f172..9c07fd15de042f 100644 --- a/src/python_testing/TC_RVCOPSTATE_2_4.py +++ b/src/python_testing/TC_RVCOPSTATE_2_4.py @@ -119,47 +119,51 @@ async def test_TC_RVCOPSTATE_2_4(self): self.write_to_app_pipe('{"Name": "Reset"}') if self.check_pics("RVCOPSTATE.S.M.ST_ERROR"): - self.print_step(2, "Manually put the device in the ERROR operational state") + step_name = "Manually put the device in the ERROR operational state" + self.print_step(2, step_name) if self.is_ci: self.write_to_app_pipe('{"Name": "ErrorEvent", "Error": "UnableToStartOrResume"}') else: - input("Press Enter when done.\n") + self.wait_for_user_input(step_name) await self.read_operational_state_with_check(3, op_states.kError) await self.send_go_home_cmd_with_check(4, op_errors.kCommandInvalidInState) if self.check_pics("RVCOPSTATE.S.M.ST_CHARGING"): - self.print_step(5, "Manually put the device in the CHARGING operational state") + step_name = "Manually put the device in the CHARGING operational state" + self.print_step(5, step_name) if self.is_ci: self.write_to_app_pipe('{"Name": "Reset"}') self.write_to_app_pipe('{"Name": "Docked"}') self.write_to_app_pipe('{"Name": "Charging"}') else: - input("Press Enter when done.\n") + self.wait_for_user_input(step_name) await self.read_operational_state_with_check(6, rvc_op_states.kCharging) await self.send_go_home_cmd_with_check(7, op_errors.kCommandInvalidInState) if self.check_pics("RVCOPSTATE.S.M.ST_DOCKED"): - self.print_step(8, "Manually put the device in the DOCKED operational state") + step_name = "Manually put the device in the DOCKED operational state" + self.print_step(8, step_name) if self.is_ci: self.write_to_app_pipe('{"Name": "Charged"}') else: - input("Press Enter when done.\n") + self.wait_for_user_input(step_name) await self.read_operational_state_with_check(9, rvc_op_states.kDocked) await self.send_go_home_cmd_with_check(10, op_errors.kCommandInvalidInState) if self.check_pics("PICS_M_ST_SEEKING_CHARGER"): - self.print_step(8, "Manually put the device in the SEEKING CHARGER operational state") + step_name = "Manually put the device in the SEEKING CHARGER operational state" + self.print_step(8, step_name) if self.is_ci: await self.send_run_change_to_mode_cmd(rvc_app_run_mode_cleaning) await self.send_run_change_to_mode_cmd(rvc_app_run_mode_idle) else: - input("Press Enter when done.\n") + self.wait_for_user_input(step_name) await self.read_operational_state_with_check(9, rvc_op_states.kSeekingCharger) diff --git a/src/python_testing/matter_testing_support.py b/src/python_testing/matter_testing_support.py index 7efe5ab948966b..aee09dd1b93f09 100644 --- a/src/python_testing/matter_testing_support.py +++ b/src/python_testing/matter_testing_support.py @@ -346,6 +346,12 @@ def step_unknown(self): """ pass + def show_prompt(self, + msg: str, + placeholder: Optional[str] = None, + default_value: Optional[str] = None) -> None: + pass + @dataclass class MatterTestConfig: @@ -1091,6 +1097,28 @@ def get_setup_payload_info(self) -> SetupPayloadInfo: return info + def wait_for_user_input(self, + prompt_msg: str, + input_msg: str = "Press Enter when done.\n", + prompt_msg_placeholder: str = "Submit anything to continue", + default_value: str = "y") -> str: + """Ask for user input and wait for it. + + Args: + prompt_msg (str): Message for TH UI prompt. Indicates what is expected from the user. + input_msg (str, optional): Prompt for input function, used when running tests manually. Defaults to "Press Enter when done.\n". + prompt_msg_placeholder (str, optional): TH UI prompt input placeholder. Defaults to "Submit anything to continue". + default_value (str, optional): TH UI prompt default value. Defaults to "y". + + Returns: + str: User input + """ + if self.runner_hook: + self.runner_hook.show_prompt(msg=prompt_msg, + placeholder=prompt_msg_placeholder, + default_value=default_value) + return input(input_msg) + def generate_mobly_test_config(matter_test_config: MatterTestConfig): test_run_config = TestRunConfig() From d89901913ff288ae314377c2cbf24026d44d434d Mon Sep 17 00:00:00 2001 From: Andrei Litvin Date: Mon, 26 Feb 2024 16:19:42 -0500 Subject: [PATCH 099/385] Remove `prune_outputs` support from code generation build scripts (#32322) * Remove output prunning - files are now separated enough for this to not be needed * Restyle * Remove more references of prune outputs --- build/chip/chip_codegen.gni | 55 ++---------------------------- scripts/tools/zap/prune_outputs.py | 42 ----------------------- src/app/chip_data_model.gni | 12 ------- 3 files changed, 3 insertions(+), 106 deletions(-) delete mode 100644 scripts/tools/zap/prune_outputs.py diff --git a/build/chip/chip_codegen.gni b/build/chip/chip_codegen.gni index 02acd08150aae8..08d9f17da6c1be 100644 --- a/build/chip/chip_codegen.gni +++ b/build/chip/chip_codegen.gni @@ -152,7 +152,7 @@ template("_chip_build_time_zapgen") { _output_subdir = "zap-generated" } - pw_python_action("${_name}_zap_pregen") { + pw_python_action("${_name}_zap") { script = "${chip_root}/scripts/tools/zap/generate.py" # TODO: this seems to touch internals. Is this ok? speeds up builds! @@ -165,7 +165,7 @@ template("_chip_build_time_zapgen") { "--templates", _template_path, "--output-dir", - rebase_path(target_gen_dir) + "/zap_pregen/" + _output_subdir, + rebase_path(target_gen_dir) + "/zapgen/" + _output_subdir, # TODO: lock file support should be removed as this serializes zap # (slower), however this is currently done because on Darwin zap startup @@ -188,54 +188,10 @@ template("_chip_build_time_zapgen") { sources = [ _idl_file ] - outputs = [] - foreach(name, invoker.outputs) { - outputs += [ "${target_gen_dir}/zap_pregen/${name}" ] - } - - forward_variables_from(invoker, [ "prune_outputs" ]) - if (defined(prune_outputs)) { - foreach(name, prune_outputs) { - outputs += [ "${target_gen_dir}/zap_pregen/${name}" ] - } - } - } - - # This action ensures that any "extra" files generated by zap codegen - # are actually deleted. - # - # This is to avoid double-codegen of configurations like endpoint config - # or access credentials being generated for both "controller client" and - # application-specific - pw_python_action("${_name}_files") { - # TODO: this seems to touch internals. Is this ok? speeds up builds! - _pw_internal_run_in_venv = false - - script = "${chip_root}/scripts/tools/zap/prune_outputs.py" - - _keep_file = rebase_path("${target_gen_dir}/${_name}.keep.outputs") - write_file(_keep_file, invoker.outputs, "list lines") - - args = [ - "--keep", - _keep_file, - "--input-dir", - rebase_path("${target_gen_dir}/zap_pregen/"), - "--output-dir", - rebase_path("${target_gen_dir}/zapgen/"), - ] - - inputs = [] - foreach(name, invoker.outputs) { - inputs += [ "${target_gen_dir}/zap_pregen/${name}" ] - } - outputs = [] foreach(name, invoker.outputs) { outputs += [ "${target_gen_dir}/zapgen/${name}" ] } - - deps = [ ":${_name}_zap_pregen" ] } source_set(_name) { @@ -255,10 +211,7 @@ template("_chip_build_time_zapgen") { if (!defined(public_deps)) { public_deps = [] } - public_deps += [ - ":${_name}_files", - ":${_name}_zap_pregen", - ] + public_deps += [ ":${_name}_zap" ] } } @@ -420,7 +373,6 @@ template("chip_zapgen") { "input", "outputs", "public_configs", - "prune_outputs", ]) } } else { @@ -482,7 +434,6 @@ template("chip_zapgen") { [ "deps", "public_configs", - "prune_outputs", ]) if (!defined(public_configs)) { public_configs = [] diff --git a/scripts/tools/zap/prune_outputs.py b/scripts/tools/zap/prune_outputs.py deleted file mode 100644 index 09f92a9378ab33..00000000000000 --- a/scripts/tools/zap/prune_outputs.py +++ /dev/null @@ -1,42 +0,0 @@ -#!/usr/bin/env python -# Copyright (c) 2022 Project CHIP Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import argparse -import os -import shutil - - -def main(): - parser = argparse.ArgumentParser( - description='Delete files based on an input file listing files to be removed') - - parser.add_argument('--keep', required=True, help="File containing names to keep (copy over)") - parser.add_argument('--output-dir', required=True, help="Output directory to copy files into") - parser.add_argument('--input-dir', required=True, help="Input directory to get the files from") - - args = parser.parse_args() - - with open(args.keep, "rt") as f: - for source in f.readlines(): - source = source.strip() - if not source: - continue - target = os.path.join(args.output_dir, source) - os.makedirs(os.path.dirname(target), exist_ok=True) - shutil.copyfile(os.path.join(args.input_dir, source), target) - - -if __name__ == '__main__': - main() diff --git a/src/app/chip_data_model.gni b/src/app/chip_data_model.gni index 42bc2f9b74ad64..a065d833b43846 100644 --- a/src/app/chip_data_model.gni +++ b/src/app/chip_data_model.gni @@ -56,20 +56,8 @@ template("chip_data_model") { "zap-generated/endpoint_config.h", ] - # NOTE: these are ALSO auto-generated but handled below: - # "zap-generated/IMClusterCommandHandler.cpp" - # -> contains one large DispatchSingleClusterCommand and DispatchServerCommand - - if (chip_code_pre_generated_directory == "") { - prune_outputs = [] - } - if (!chip_build_controller_dynamic_server) { outputs += [ "zap-generated/IMClusterCommandHandler.cpp" ] - } else { - if (defined(prune_outputs)) { - prune_outputs += [ "zap-generated/IMClusterCommandHandler.cpp" ] - } } if (!defined(deps)) { From d12311a496f5dc59399792fb1638b215722f9248 Mon Sep 17 00:00:00 2001 From: yunhanw-google Date: Mon, 26 Feb 2024 16:22:38 -0800 Subject: [PATCH 100/385] call OnActiveModeNotification out from onCheckInComplete (#32159) --- examples/chip-tool/commands/common/CHIPCommand.cpp | 6 ++++-- src/app/icd/client/CheckInHandler.cpp | 9 +++++++-- src/app/icd/client/CheckInHandler.h | 6 ++++-- src/app/icd/client/DefaultCheckInDelegate.cpp | 11 ++++------- src/app/icd/client/DefaultCheckInDelegate.h | 7 +++++-- src/app/icd/client/RefreshKeySender.cpp | 13 +++++++++---- src/app/icd/client/RefreshKeySender.h | 7 ++++--- 7 files changed, 37 insertions(+), 22 deletions(-) diff --git a/examples/chip-tool/commands/common/CHIPCommand.cpp b/examples/chip-tool/commands/common/CHIPCommand.cpp index 78abff12ada208..125ab46433e0ef 100644 --- a/examples/chip-tool/commands/common/CHIPCommand.cpp +++ b/examples/chip-tool/commands/common/CHIPCommand.cpp @@ -149,9 +149,11 @@ CHIP_ERROR CHIPCommand::MaybeSetUpStack() ReturnErrorOnFailure(GetAttestationTrustStore(mPaaTrustStorePath.ValueOr(nullptr), &sTrustStore)); - ReturnLogErrorOnFailure(sCheckInDelegate.Init(&sICDClientStorage)); + auto engine = chip::app::InteractionModelEngine::GetInstance(); + VerifyOrReturnError(engine != nullptr, CHIP_ERROR_INCORRECT_STATE); + ReturnLogErrorOnFailure(sCheckInDelegate.Init(&sICDClientStorage, engine)); ReturnLogErrorOnFailure(sCheckInHandler.Init(DeviceControllerFactory::GetInstance().GetSystemState()->ExchangeMgr(), - &sICDClientStorage, &sCheckInDelegate)); + &sICDClientStorage, &sCheckInDelegate, engine)); CommissionerIdentity nullIdentity{ kIdentityNull, chip::kUndefinedNodeId }; ReturnLogErrorOnFailure(InitializeCommissioner(nullIdentity, kIdentityNullFabricId)); diff --git a/src/app/icd/client/CheckInHandler.cpp b/src/app/icd/client/CheckInHandler.cpp index 165301c45480fd..f6ef50a0019d66 100644 --- a/src/app/icd/client/CheckInHandler.cpp +++ b/src/app/icd/client/CheckInHandler.cpp @@ -22,6 +22,8 @@ * */ +#include +#include #include #include #include @@ -44,7 +46,7 @@ inline constexpr uint32_t kKeyRefreshLimit = (1U << 31); CheckInHandler::CheckInHandler() {} CHIP_ERROR CheckInHandler::Init(Messaging::ExchangeManager * exchangeManager, ICDClientStorage * clientStorage, - CheckInDelegate * delegate) + CheckInDelegate * delegate, InteractionModelEngine * engine) { VerifyOrReturnError(exchangeManager != nullptr, CHIP_ERROR_INVALID_ARGUMENT); VerifyOrReturnError(clientStorage != nullptr, CHIP_ERROR_INVALID_ARGUMENT); @@ -54,7 +56,7 @@ CHIP_ERROR CheckInHandler::Init(Messaging::ExchangeManager * exchangeManager, IC mpExchangeManager = exchangeManager; mpICDClientStorage = clientStorage; mpCheckInDelegate = delegate; - + mpImEngine = engine; return mpExchangeManager->RegisterUnsolicitedMessageHandlerForType(Protocols::SecureChannel::MsgType::ICD_CheckIn, this); } @@ -127,6 +129,9 @@ CHIP_ERROR CheckInHandler::OnMessageReceived(Messaging::ExchangeContext * ec, co else { mpCheckInDelegate->OnCheckInComplete(clientInfo); +#if CHIP_CONFIG_ENABLE_READ_CLIENT + mpImEngine->OnActiveModeNotification(clientInfo.peer_node); +#endif // CHIP_CONFIG_ENABLE_READ_CLIENT } return CHIP_NO_ERROR; diff --git a/src/app/icd/client/CheckInHandler.h b/src/app/icd/client/CheckInHandler.h index 22170a1b332694..b2489aaac34812 100644 --- a/src/app/icd/client/CheckInHandler.h +++ b/src/app/icd/client/CheckInHandler.h @@ -36,12 +36,13 @@ namespace chip { namespace app { - +class InteractionModelEngine; class CheckInHandler : public Messaging::ExchangeDelegate, public Messaging::UnsolicitedMessageHandler { public: - CHIP_ERROR Init(Messaging::ExchangeManager * exchangeManager, ICDClientStorage * clientStorage, CheckInDelegate * delegate); + CHIP_ERROR Init(Messaging::ExchangeManager * exchangeManager, ICDClientStorage * clientStorage, CheckInDelegate * delegate, + InteractionModelEngine * engine); void Shutdown(); CheckInHandler(); @@ -87,6 +88,7 @@ class CheckInHandler : public Messaging::ExchangeDelegate, public Messaging::Uns Messaging::ExchangeManager * mpExchangeManager = nullptr; CheckInDelegate * mpCheckInDelegate = nullptr; ICDClientStorage * mpICDClientStorage = nullptr; + InteractionModelEngine * mpImEngine = nullptr; }; } // namespace app diff --git a/src/app/icd/client/DefaultCheckInDelegate.cpp b/src/app/icd/client/DefaultCheckInDelegate.cpp index 8df98006f6e9e0..e967138310c0f4 100644 --- a/src/app/icd/client/DefaultCheckInDelegate.cpp +++ b/src/app/icd/client/DefaultCheckInDelegate.cpp @@ -15,7 +15,6 @@ * limitations under the License. */ -#include #include #include #include @@ -25,11 +24,12 @@ namespace chip { namespace app { -CHIP_ERROR DefaultCheckInDelegate::Init(ICDClientStorage * storage) +CHIP_ERROR DefaultCheckInDelegate::Init(ICDClientStorage * storage, InteractionModelEngine * engine) { VerifyOrReturnError(storage != nullptr, CHIP_ERROR_INVALID_ARGUMENT); VerifyOrReturnError(mpStorage == nullptr, CHIP_ERROR_INCORRECT_STATE); - mpStorage = storage; + mpStorage = storage; + mpImEngine = engine; return CHIP_NO_ERROR; } @@ -38,9 +38,6 @@ void DefaultCheckInDelegate::OnCheckInComplete(const ICDClientInfo & clientInfo) ChipLogProgress( ICD, "Check In Message processing complete: start_counter=%" PRIu32 " offset=%" PRIu32 " nodeid=" ChipLogFormatScopedNodeId, clientInfo.start_icd_counter, clientInfo.offset, ChipLogValueScopedNodeId(clientInfo.peer_node)); -#if CHIP_CONFIG_ENABLE_READ_CLIENT - InteractionModelEngine::GetInstance()->OnActiveModeNotification(clientInfo.peer_node); -#endif } RefreshKeySender * DefaultCheckInDelegate::OnKeyRefreshNeeded(ICDClientInfo & clientInfo, ICDClientStorage * clientStorage) @@ -55,7 +52,7 @@ RefreshKeySender * DefaultCheckInDelegate::OnKeyRefreshNeeded(ICDClientInfo & cl return nullptr; } - auto refreshKeySender = Platform::New(this, clientInfo, clientStorage, newKey); + auto refreshKeySender = Platform::New(this, clientInfo, clientStorage, mpImEngine, newKey); if (refreshKeySender == nullptr) { return nullptr; diff --git a/src/app/icd/client/DefaultCheckInDelegate.h b/src/app/icd/client/DefaultCheckInDelegate.h index e7b856677734bd..5465994ef1bda0 100644 --- a/src/app/icd/client/DefaultCheckInDelegate.h +++ b/src/app/icd/client/DefaultCheckInDelegate.h @@ -26,18 +26,21 @@ namespace app { using namespace std; +class InteractionModelEngine; + /// Callbacks for check in protocol class DefaultCheckInDelegate : public CheckInDelegate { public: virtual ~DefaultCheckInDelegate() {} - CHIP_ERROR Init(ICDClientStorage * storage); + CHIP_ERROR Init(ICDClientStorage * storage, InteractionModelEngine * engine); void OnCheckInComplete(const ICDClientInfo & clientInfo) override; RefreshKeySender * OnKeyRefreshNeeded(ICDClientInfo & clientInfo, ICDClientStorage * clientStorage) override; void OnKeyRefreshDone(RefreshKeySender * refreshKeySender, CHIP_ERROR error) override; private: - ICDClientStorage * mpStorage = nullptr; + ICDClientStorage * mpStorage = nullptr; + InteractionModelEngine * mpImEngine = nullptr; }; } // namespace app diff --git a/src/app/icd/client/RefreshKeySender.cpp b/src/app/icd/client/RefreshKeySender.cpp index 45cbbd9c987a68..f0fbdbae7721d8 100644 --- a/src/app/icd/client/RefreshKeySender.cpp +++ b/src/app/icd/client/RefreshKeySender.cpp @@ -19,6 +19,7 @@ #include "CheckInDelegate.h" #include "controller/InvokeInteraction.h" #include +#include #include #include #include @@ -28,10 +29,11 @@ namespace chip { namespace app { RefreshKeySender::RefreshKeySender(CheckInDelegate * checkInDelegate, const ICDClientInfo & icdClientInfo, - ICDClientStorage * icdClientStorage, const RefreshKeyBuffer & refreshKeyBuffer) : - mICDClientInfo(icdClientInfo), - mpICDClientStorage(icdClientStorage), mpCheckInDelegate(checkInDelegate), mOnConnectedCallback(HandleDeviceConnected, this), - mOnConnectionFailureCallback(HandleDeviceConnectionFailure, this) + ICDClientStorage * icdClientStorage, InteractionModelEngine * engine, + const RefreshKeyBuffer & refreshKeyBuffer) : + mpCheckInDelegate(checkInDelegate), + mICDClientInfo(icdClientInfo), mpICDClientStorage(icdClientStorage), mpImEngine(engine), + mOnConnectedCallback(HandleDeviceConnected, this), mOnConnectionFailureCallback(HandleDeviceConnectionFailure, this) { mNewKey = refreshKeyBuffer; @@ -64,6 +66,9 @@ CHIP_ERROR RefreshKeySender::RegisterClientWithNewKey(Messaging::ExchangeManager } mpCheckInDelegate->OnCheckInComplete(mICDClientInfo); +#if CHIP_CONFIG_ENABLE_READ_CLIENT + mpImEngine->OnActiveModeNotification(mICDClientInfo.peer_node); +#endif // CHIP_CONFIG_ENABLE_READ_CLIENT mpCheckInDelegate->OnKeyRefreshDone(this, CHIP_NO_ERROR); }; diff --git a/src/app/icd/client/RefreshKeySender.h b/src/app/icd/client/RefreshKeySender.h index a0cf822fa446f9..a92345fbe8ab83 100644 --- a/src/app/icd/client/RefreshKeySender.h +++ b/src/app/icd/client/RefreshKeySender.h @@ -34,7 +34,7 @@ namespace chip { namespace app { class CheckInDelegate; - +class InteractionModelEngine; /** * @brief RefreshKeySender contains all the data and methods needed for key refresh and re-registration of an ICD client. */ @@ -44,7 +44,7 @@ class RefreshKeySender typedef Crypto::SensitiveDataBuffer RefreshKeyBuffer; RefreshKeySender(CheckInDelegate * checkInDelegate, const ICDClientInfo & icdClientInfo, ICDClientStorage * icdClientStorage, - const RefreshKeyBuffer & refreshKeyBuffer); + InteractionModelEngine * engine, const RefreshKeyBuffer & refreshKeyBuffer); /** * @brief Sets up a CASE session to the peer for re-registering a client with the peer when a key refresh is required to avoid @@ -82,9 +82,10 @@ class RefreshKeySender */ CHIP_ERROR RegisterClientWithNewKey(Messaging::ExchangeManager & exchangeMgr, const SessionHandle & sessionHandle); + CheckInDelegate * mpCheckInDelegate = nullptr; ICDClientInfo mICDClientInfo; ICDClientStorage * mpICDClientStorage = nullptr; - CheckInDelegate * mpCheckInDelegate = nullptr; + InteractionModelEngine * mpImEngine = nullptr; RefreshKeyBuffer mNewKey; Callback::Callback mOnConnectedCallback; Callback::Callback mOnConnectionFailureCallback; From 28c78af5643dbca32ee99a7f464e489db26430a3 Mon Sep 17 00:00:00 2001 From: Andrei Litvin Date: Mon, 26 Feb 2024 20:01:14 -0500 Subject: [PATCH 101/385] Define dependencies for some files in zzz_generated and compatenums.h (#32327) * Add dependency on CompatEnumNames as this is a requirement and direct include of cluster-enums.h * define ids as a source set for zzz generated * Fix dependencies * CompatEnumNames is NOT in a subdirectory of app, which is wrong however for now roll with it * Move CompatEnumNames to common so linter catches it * Restyle --- .github/workflows/lint.yml | 1 - src/app/common/BUILD.gn | 15 +++++++++++++++ src/app/{ => common}/CompatEnumNames.h | 0 .../templates/app/cluster-enums.zapt | 2 +- .../app-common/zap-generated/cluster-enums.h | 2 +- 5 files changed, 17 insertions(+), 3 deletions(-) rename src/app/{ => common}/CompatEnumNames.h (100%) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index e0255646dbc487..e5afb69fabd2b1 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -96,7 +96,6 @@ jobs: --known-failure app/CommandHandler.h \ --known-failure app/CommandHandlerInterface.h \ --known-failure app/CommandSenderLegacyCallback.h \ - --known-failure app/CompatEnumNames.h \ --known-failure app/data-model/ListLargeSystemExtensions.h \ --known-failure app/EventHeader.h \ --known-failure app/EventLoggingTypes.h \ diff --git a/src/app/common/BUILD.gn b/src/app/common/BUILD.gn index 1af268a477efaf..de7eef3008588d 100644 --- a/src/app/common/BUILD.gn +++ b/src/app/common/BUILD.gn @@ -18,6 +18,19 @@ config("includes") { include_dirs = [ "${chip_root}/zzz_generated/app-common" ] } +source_set("ids") { + sources = [ + "${chip_root}/zzz_generated/app-common/app-common/zap-generated/ids/Attributes.h", + "${chip_root}/zzz_generated/app-common/app-common/zap-generated/ids/Clusters.h", + "${chip_root}/zzz_generated/app-common/app-common/zap-generated/ids/Commands.h", + "${chip_root}/zzz_generated/app-common/app-common/zap-generated/ids/Events.h", + ] + + public_deps = [ "${chip_root}/src/app/util:types" ] + + public_configs = [ ":includes" ] +} + static_library("cluster-objects") { output_name = "libClusterObjects" @@ -27,6 +40,7 @@ static_library("cluster-objects") { ] public_deps = [ + ":ids", "${chip_root}/src/app:paths", "${chip_root}/src/app/data-model", "${chip_root}/src/app/util:types", @@ -42,6 +56,7 @@ source_set("enums") { sources = [ "${chip_root}/zzz_generated/app-common/app-common/zap-generated/cluster-enums-check.h", "${chip_root}/zzz_generated/app-common/app-common/zap-generated/cluster-enums.h", + "CompatEnumNames.h", ] public_configs = [ ":includes" ] diff --git a/src/app/CompatEnumNames.h b/src/app/common/CompatEnumNames.h similarity index 100% rename from src/app/CompatEnumNames.h rename to src/app/common/CompatEnumNames.h diff --git a/src/app/zap-templates/templates/app/cluster-enums.zapt b/src/app/zap-templates/templates/app/cluster-enums.zapt index 612b3dd6a29d4b..17ce795200795f 100644 --- a/src/app/zap-templates/templates/app/cluster-enums.zapt +++ b/src/app/zap-templates/templates/app/cluster-enums.zapt @@ -70,4 +70,4 @@ k{{asUpperCamelCase label}} = {{asHex mask}}, } // namespace chip // Included at the end, so all our definitions above are available. -#include +#include diff --git a/zzz_generated/app-common/app-common/zap-generated/cluster-enums.h b/zzz_generated/app-common/app-common/zap-generated/cluster-enums.h index 1a1afc11a522d1..42a54b95ee944f 100644 --- a/zzz_generated/app-common/app-common/zap-generated/cluster-enums.h +++ b/zzz_generated/app-common/app-common/zap-generated/cluster-enums.h @@ -4893,4 +4893,4 @@ namespace SampleMei {} // namespace SampleMei } // namespace chip // Included at the end, so all our definitions above are available. -#include +#include From a2d98f869562ae1efc9a6c1c40f5049a12fa71e0 Mon Sep 17 00:00:00 2001 From: Anush Nadathur Date: Tue, 27 Feb 2024 11:28:00 +0530 Subject: [PATCH 102/385] Fix MTRMetricsCollector.mm build failure using clang (#32330) - Missing static_cast to int for enum class in a format string --- src/darwin/Framework/CHIP/MTRMetricsCollector.mm | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/darwin/Framework/CHIP/MTRMetricsCollector.mm b/src/darwin/Framework/CHIP/MTRMetricsCollector.mm index 6387738a7c13c8..e829c57f486729 100644 --- a/src/darwin/Framework/CHIP/MTRMetricsCollector.mm +++ b/src/darwin/Framework/CHIP/MTRMetricsCollector.mm @@ -193,19 +193,19 @@ - (void)handleMetricEvent:(MetricEvent)event using ValueType = MetricEvent::Value::Type; switch (event.ValueType()) { case ValueType::kInt32: - MTR_LOG_INFO("Received metric event, key: %s, type: %d, value: %d", event.key(), event.type(), event.ValueInt32()); + MTR_LOG_INFO("Received metric event, key: %s, type: %d, value: %d", event.key(), static_cast(event.type()), event.ValueInt32()); break; case ValueType::kUInt32: - MTR_LOG_INFO("Received metric event, key: %s, type: %d, value: %u", event.key(), event.type(), event.ValueUInt32()); + MTR_LOG_INFO("Received metric event, key: %s, type: %d, value: %u", event.key(), static_cast(event.type()), event.ValueUInt32()); break; case ValueType::kChipErrorCode: - MTR_LOG_INFO("Received metric event, key: %s, type: %d, error value: %u", event.key(), event.type(), event.ValueErrorCode()); + MTR_LOG_INFO("Received metric event, key: %s, type: %d, error value: %u", event.key(), static_cast(event.type()), event.ValueErrorCode()); break; case ValueType::kUndefined: - MTR_LOG_INFO("Received metric event, key: %s, type: %d, value: nil", event.key(), event.type()); + MTR_LOG_INFO("Received metric event, key: %s, type: %d, value: nil", event.key(), static_cast(event.type())); break; default: - MTR_LOG_INFO("Received metric event, key: %s, type: %d, unknown value", event.key(), event.type()); + MTR_LOG_INFO("Received metric event, key: %s, type: %d, unknown value", event.key(), static_cast(event.type())); return; } From 8428564bed7736f8572e4df3d592bba8f1687e9a Mon Sep 17 00:00:00 2001 From: weicheng Date: Tue, 27 Feb 2024 22:12:36 +0800 Subject: [PATCH 103/385] [ASR] fix double init in BLEManager and OTA (#31579) * fix BLE pairing issue because the initialization time of ble is earlier the callback registration time * fix ota fail issue * Restyled by clang-format * Update ASR582X SDK to v1.9.1 --- src/platform/ASR/ASROTAImageProcessor.cpp | 6 ++---- src/platform/ASR/BLEManagerImpl.cpp | 3 +++ third_party/asr/asr582x/asr_sdk | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/platform/ASR/ASROTAImageProcessor.cpp b/src/platform/ASR/ASROTAImageProcessor.cpp index 92a3ab08a4da7b..d83ba75362cb69 100644 --- a/src/platform/ASR/ASROTAImageProcessor.cpp +++ b/src/platform/ASR/ASROTAImageProcessor.cpp @@ -20,9 +20,6 @@ #include #include -/// No error, operation OK -#define LEGA_OTA_OK 0L - namespace chip { CHIP_ERROR ASROTAImageProcessor::PrepareDownload() @@ -121,7 +118,8 @@ void ASROTAImageProcessor::HandlePrepareDownload(intptr_t context) imageProcessor->mHeaderParser.Init(); - imageProcessor->mDownloader->OnPreparedForDownload(err == LEGA_OTA_OK ? CHIP_NO_ERROR : CHIP_ERROR_INTERNAL); + imageProcessor->mDownloader->OnPreparedForDownload( + ((err == LEGA_OTA_OK) || (err == LEGA_OTA_INIT_ALREADY)) ? CHIP_NO_ERROR : CHIP_ERROR_INTERNAL); } void ASROTAImageProcessor::HandleFinalize(intptr_t context) diff --git a/src/platform/ASR/BLEManagerImpl.cpp b/src/platform/ASR/BLEManagerImpl.cpp index 51bd920b832dc7..e960a617b4e33b 100644 --- a/src/platform/ASR/BLEManagerImpl.cpp +++ b/src/platform/ASR/BLEManagerImpl.cpp @@ -110,6 +110,9 @@ CHIP_ERROR BLEManagerImpl::_Init() } else { + matter_ble_stack_open(); + matter_ble_add_service(); + BLEMgrImpl().SetStackInit(); mFlags.Set(Flags::kFlag_StackInitialized, true); log_i("ble is alread open!\n"); } diff --git a/third_party/asr/asr582x/asr_sdk b/third_party/asr/asr582x/asr_sdk index 54644715210812..8d6fd5e9f7f04e 160000 --- a/third_party/asr/asr582x/asr_sdk +++ b/third_party/asr/asr582x/asr_sdk @@ -1 +1 @@ -Subproject commit 54644715210812fa6c1e6e9433b5b824ba735c67 +Subproject commit 8d6fd5e9f7f04efd06d12a923a94f288e9d8c24b From 6d8613dfb673d3419d9ed0802db5e7c36069b935 Mon Sep 17 00:00:00 2001 From: fesseha-eve <88329315+fessehaeve@users.noreply.github.com> Date: Tue, 27 Feb 2024 15:43:59 +0100 Subject: [PATCH 104/385] fix crash caused by lacking null pointer, which is caused by using wrong cluster id (#32339) --- src/app/clusters/on-off-server/on-off-server.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/app/clusters/on-off-server/on-off-server.cpp b/src/app/clusters/on-off-server/on-off-server.cpp index ac1c4a0c3bf3c6..e4ba82bb8bdc2f 100644 --- a/src/app/clusters/on-off-server/on-off-server.cpp +++ b/src/app/clusters/on-off-server/on-off-server.cpp @@ -214,6 +214,7 @@ class DefaultOnOffSceneHandler : public scenes::DefaultSceneHandlerImpl ScenesManagement::ScenesServer::Instance().IsHandlerRegistered(endpoint, LevelControlServer::GetSceneHandler()))) #endif { + VerifyOrReturnError(mTransitionTimeInterface.sceneEventControl(endpoint) != nullptr, CHIP_ERROR_INVALID_ARGUMENT); OnOffServer::Instance().scheduleTimerCallbackMs(mTransitionTimeInterface.sceneEventControl(endpoint), timeMs); } @@ -221,7 +222,7 @@ class DefaultOnOffSceneHandler : public scenes::DefaultSceneHandlerImpl } private: - OnOffTransitionTimeInterface mTransitionTimeInterface = OnOffTransitionTimeInterface(Attributes::OnOff::Id, sceneOnOffCallback); + OnOffTransitionTimeInterface mTransitionTimeInterface = OnOffTransitionTimeInterface(OnOff::Id, sceneOnOffCallback); }; static DefaultOnOffSceneHandler sOnOffSceneHandler; From db76ad7420a19e10a6b2f9c5e7187683f2a91b02 Mon Sep 17 00:00:00 2001 From: Karsten Sperling <113487422+ksperling-apple@users.noreply.github.com> Date: Wed, 28 Feb 2024 15:15:45 +1300 Subject: [PATCH 105/385] Improve DeviceCommissioner::StopPairing behavior (#32233) * Prefix DeviceCommissioner members with 'm' * Move OnBasic* into DeviceCommissioner as private helpers * Consistently check for presence of mDefaultCommissioner first * Darwin: Reduce boilerplate in MTRError and use switch * Darwin: Add MTRErrorCodeCancelled * Darwin: Extend MTRPairingTests to cover cancellation * Improve DeviceCommissioner::StopPairing behavior Improve StopPairing behavior by cancelling the current read or invoke interaction to avoid stray callbacks messing up a future commissioning attempt. Rename SendCommand to SendCommissioningCommand. * Make gLogFilter atomic to avoid races / TSAN failures Note that most constrained platforms build with CHIP_LOG_FILTERING=0 so will not be incurring any extra runtime cost because of this change. * Exclude Darwin code from PRI*64 lint * Document InvokeCancelFn as internal-only * Address review comments - Log VerifyOrDie failures at Error level instead of Detail - Use reset() for clearing UniquePtr * Improve logging for commissioning - Log when commissioning is complete (SendCommissioningCompleteCallbacks) - Consolidate logging in AutoCommissioner::CommissioningStepFinished - Also rely on VerifyOrDie in Variant instead of bug log message * Another logging tweak --- .github/workflows/lint.yml | 2 +- src/controller/AutoCommissioner.cpp | 27 +-- src/controller/CHIPDeviceController.cpp | 170 ++++++++++------ src/controller/CHIPDeviceController.h | 44 ++-- src/controller/InvokeInteraction.h | 20 +- src/darwin/Framework/CHIP/MTRError.h | 9 + src/darwin/Framework/CHIP/MTRError.mm | 192 +++++++++--------- .../Framework/CHIPTests/MTRPairingTests.m | 86 +++++++- src/lib/support/CodeUtils.h | 4 +- src/lib/support/logging/TextOnlyLogging.cpp | 8 +- 10 files changed, 342 insertions(+), 220 deletions(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index e5afb69fabd2b1..a5398ccb7567a2 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -203,7 +203,7 @@ jobs: # TODO: TLVDebug should ideally not be excluded here. # TODO: protocol_decoder.cpp should ideally not be excluded here. # TODO: PersistentStorageMacros.h should ideally not be excluded here. - git grep -I -n "PRI.64" -- './*' ':(exclude).github/workflows/lint.yml' ':(exclude)examples/chip-tool' ':(exclude)examples/tv-casting-app' ':(exclude)src/app/MessageDef/MessageDefHelper.cpp' ':(exclude)src/app/tests/integration/chip_im_initiator.cpp' ':(exclude)src/lib/core/TLVDebug.cpp' ':(exclude)src/lib/dnssd/tests/TestTxtFields.cpp' ':(exclude)src/lib/format/protocol_decoder.cpp' ':(exclude)src/lib/support/PersistentStorageMacros.h' ':(exclude)src/messaging/tests/echo/echo_requester.cpp' ':(exclude)src/platform/Linux' ':(exclude)src/platform/Ameba' ':(exclude)src/platform/ESP32' ':(exclude)src/platform/webos' ':(exclude)zzz_generated/chip-tool' ':(exclude)src/tools/chip-cert/Cmd_PrintCert.cpp' && exit 1 || exit 0 + git grep -I -n "PRI.64" -- './*' ':(exclude).github/workflows/lint.yml' ':(exclude)examples/chip-tool' ':(exclude)examples/tv-casting-app' ':(exclude)src/app/MessageDef/MessageDefHelper.cpp' ':(exclude)src/app/tests/integration/chip_im_initiator.cpp' ':(exclude)src/lib/core/TLVDebug.cpp' ':(exclude)src/lib/dnssd/tests/TestTxtFields.cpp' ':(exclude)src/lib/format/protocol_decoder.cpp' ':(exclude)src/lib/support/PersistentStorageMacros.h' ':(exclude)src/messaging/tests/echo/echo_requester.cpp' ':(exclude)src/platform/Linux' ':(exclude)src/platform/Ameba' ':(exclude)src/platform/ESP32' ':(exclude)src/platform/Darwin' ':(exclude)src/darwin' ':(exclude)src/platform/webos' ':(exclude)zzz_generated/chip-tool' ':(exclude)src/tools/chip-cert/Cmd_PrintCert.cpp' && exit 1 || exit 0 # git grep exits with 0 if it finds a match, but we want # to fail (exit nonzero) on match. And we want to exclude this file, diff --git a/src/controller/AutoCommissioner.cpp b/src/controller/AutoCommissioner.cpp index 69a9c9b9c6bbf3..557cdf43a6ad9c 100644 --- a/src/controller/AutoCommissioner.cpp +++ b/src/controller/AutoCommissioner.cpp @@ -673,20 +673,10 @@ CHIP_ERROR AutoCommissioner::CommissioningStepFinished(CHIP_ERROR err, Commissio { CompletionStatus completionStatus; completionStatus.err = err; - - if (err == CHIP_NO_ERROR) - { - ChipLogProgress(Controller, "Successfully finished commissioning step '%s'", StageToString(report.stageCompleted)); - } - else - { - ChipLogProgress(Controller, "Error on commissioning step '%s': '%s'", StageToString(report.stageCompleted), err.AsString()); - } - if (err != CHIP_NO_ERROR) { + ChipLogError(Controller, "Error on commissioning step '%s': '%s'", StageToString(report.stageCompleted), err.AsString()); completionStatus.failedStage = MakeOptional(report.stageCompleted); - ChipLogError(Controller, "Failed to perform commissioning step %d", static_cast(report.stageCompleted)); if (report.Is()) { completionStatus.attestationResult = MakeOptional(report.Get().attestationResult); @@ -727,19 +717,14 @@ CHIP_ERROR AutoCommissioner::CommissioningStepFinished(CHIP_ERROR err, Commissio } else { + ChipLogProgress(Controller, "Successfully finished commissioning step '%s'", StageToString(report.stageCompleted)); switch (report.stageCompleted) { case CommissioningStage::kReadCommissioningInfo: break; case CommissioningStage::kReadCommissioningInfo2: { - if (!report.Is()) - { - ChipLogError(Controller, - "[BUG] Should read commissioning info, but report is not ReadCommissioningInfo. THIS IS A BUG."); - } - ReadCommissioningInfo commissioningInfo = report.Get(); - mDeviceCommissioningInfo = report.Get(); + if (!mParams.GetFailsafeTimerSeconds().HasValue() && mDeviceCommissioningInfo.general.recommendedFailsafe > 0) { mParams.SetFailsafeTimerSeconds(mDeviceCommissioningInfo.general.recommendedFailsafe); @@ -751,11 +736,11 @@ CHIP_ERROR AutoCommissioner::CommissioningStepFinished(CHIP_ERROR err, Commissio // Don't send DST unless the device says it needs it mNeedsDST = false; - mParams.SetSupportsConcurrentConnection(commissioningInfo.supportsConcurrentConnection); + mParams.SetSupportsConcurrentConnection(mDeviceCommissioningInfo.supportsConcurrentConnection); if (mParams.GetCheckForMatchingFabric()) { - chip::NodeId nodeId = commissioningInfo.remoteNodeId; + chip::NodeId nodeId = mDeviceCommissioningInfo.remoteNodeId; if (nodeId != kUndefinedNodeId) { mParams.SetRemoteNodeId(nodeId); @@ -764,7 +749,7 @@ CHIP_ERROR AutoCommissioner::CommissioningStepFinished(CHIP_ERROR err, Commissio if (mParams.GetICDRegistrationStrategy() != ICDRegistrationStrategy::kIgnore) { - if (commissioningInfo.icd.isLIT && commissioningInfo.icd.checkInProtocolSupport) + if (mDeviceCommissioningInfo.icd.isLIT && mDeviceCommissioningInfo.icd.checkInProtocolSupport) { mNeedIcdRegistration = true; ChipLogDetail(Controller, "AutoCommissioner: ICD supports the check-in protocol."); diff --git a/src/controller/CHIPDeviceController.cpp b/src/controller/CHIPDeviceController.cpp index 69e95244dcce01..35c616ac0426db 100644 --- a/src/controller/CHIPDeviceController.cpp +++ b/src/controller/CHIPDeviceController.cpp @@ -38,11 +38,11 @@ #include #include -#include - #include #include +#include #include +#include #include #include #include @@ -400,11 +400,7 @@ DeviceCommissioner::DeviceCommissioner() : #endif // CHIP_DEVICE_CONFIG_ENABLE_AUTOMATIC_CASE_RETRIES mDeviceAttestationInformationVerificationCallback(OnDeviceAttestationInformationVerification, this), mDeviceNOCChainCallback(OnDeviceNOCChainGeneration, this), mSetUpCodePairer(this) -{ - mPairingDelegate = nullptr; - mDeviceBeingCommissioned = nullptr; - mDeviceInPASEEstablishment = nullptr; -} +{} CHIP_ERROR DeviceCommissioner::Init(CommissionerInitParams params) { @@ -483,7 +479,8 @@ void DeviceCommissioner::Shutdown() ChipLogDetail(Controller, "Setup in progress, stopping setup before shutting down"); OnSessionEstablishmentError(CHIP_ERROR_CONNECTION_ABORTED); } - // TODO: If we have a commissioning step in progress, is there a way to cancel that callback? + + CancelCommissioningInteractions(); #if CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONER_DISCOVERY // make this commissioner discoverable if (mUdcTransportMgr != nullptr) @@ -816,6 +813,13 @@ CHIP_ERROR DeviceCommissioner::Commission(NodeId remoteDeviceId, CommissioningPa CHIP_ERROR DeviceCommissioner::Commission(NodeId remoteDeviceId) { MATTER_TRACE_SCOPE("Commission", "DeviceCommissioner"); + + if (mDefaultCommissioner == nullptr) + { + ChipLogError(Controller, "No default commissioner is specified"); + return CHIP_ERROR_INCORRECT_STATE; + } + CommissioneeDeviceProxy * device = FindCommissioneeDevice(remoteDeviceId); if (device == nullptr || (!device->IsSecureConnected() && !device->IsSessionSetupInProgress())) { @@ -831,13 +835,8 @@ CHIP_ERROR DeviceCommissioner::Commission(NodeId remoteDeviceId) if (mCommissioningStage != CommissioningStage::kSecurePairing) { - ChipLogError(Controller, "Commissioning already in progress - not restarting"); - return CHIP_ERROR_INCORRECT_STATE; - } - - if (mDefaultCommissioner == nullptr) - { - ChipLogError(Controller, "No default commissioner is specified"); + ChipLogError(Controller, "Commissioning already in progress (stage '%s') - not restarting", + StageToString(mCommissioningStage)); return CHIP_ERROR_INCORRECT_STATE; } @@ -860,6 +859,13 @@ DeviceCommissioner::ContinueCommissioningAfterDeviceAttestation(DeviceProxy * de Credentials::AttestationVerificationResult attestationResult) { MATTER_TRACE_SCOPE("continueCommissioningDevice", "DeviceCommissioner"); + + if (mDefaultCommissioner == nullptr) + { + ChipLogError(Controller, "No default commissioner is specified"); + return CHIP_ERROR_INCORRECT_STATE; + } + if (device == nullptr || device != mDeviceBeingCommissioned) { ChipLogError(Controller, "Invalid device for commissioning %p", device); @@ -884,12 +890,6 @@ DeviceCommissioner::ContinueCommissioningAfterDeviceAttestation(DeviceProxy * de return CHIP_ERROR_INCORRECT_STATE; } - if (mDefaultCommissioner == nullptr) - { - ChipLogError(Controller, "No default commissioner is specified"); - return CHIP_ERROR_INCORRECT_STATE; - } - ChipLogProgress(Controller, "Continuing commissioning after attestation failure for device ID 0x" ChipLogFormatX64, ChipLogValueX64(commissioneeDevice->GetDeviceId())); @@ -920,6 +920,7 @@ CHIP_ERROR DeviceCommissioner::StopPairing(NodeId remoteDeviceId) // If we're still in the process of discovering the device, just stop the SetUpCodePairer if (mSetUpCodePairer.StopPairing(remoteDeviceId)) { + mRunCommissioningAfterConnection = false; return CHIP_NO_ERROR; } @@ -929,6 +930,7 @@ CHIP_ERROR DeviceCommissioner::StopPairing(NodeId remoteDeviceId) if (mDeviceBeingCommissioned == device) { + CancelCommissioningInteractions(); CommissioningStageComplete(CHIP_ERROR_CANCELLED); } else @@ -938,6 +940,21 @@ CHIP_ERROR DeviceCommissioner::StopPairing(NodeId remoteDeviceId) return CHIP_NO_ERROR; } +void DeviceCommissioner::CancelCommissioningInteractions() +{ + if (mReadClient) + { + ChipLogDetail(Controller, "Cancelling read request for step '%s'", StageToString(mCommissioningStage)); + mReadClient.reset(); // destructor cancels + } + if (mInvokeCancelFn) + { + ChipLogDetail(Controller, "Cancelling command invocation for step '%s'", StageToString(mCommissioningStage)); + mInvokeCancelFn(); + mInvokeCancelFn = nullptr; + } +} + CHIP_ERROR DeviceCommissioner::UnpairDevice(NodeId remoteDeviceId) { MATTER_TRACE_SCOPE("UnpairDevice", "DeviceCommissioner"); @@ -1014,7 +1031,8 @@ CHIP_ERROR DeviceCommissioner::SendCertificateChainRequestCommand(DeviceProxy * OperationalCredentials::Commands::CertificateChainRequest::Type request; request.certificateType = static_cast(certificateType); - return SendCommand(device, request, OnCertificateChainResponse, OnCertificateChainFailureResponse, timeout); + return SendCommissioningCommand(device, request, OnCertificateChainResponse, OnCertificateChainFailureResponse, kRootEndpointId, + timeout); } void DeviceCommissioner::OnCertificateChainFailureResponse(void * context, CHIP_ERROR error) @@ -1048,7 +1066,8 @@ CHIP_ERROR DeviceCommissioner::SendAttestationRequestCommand(DeviceProxy * devic OperationalCredentials::Commands::AttestationRequest::Type request; request.attestationNonce = attestationNonce; - ReturnErrorOnFailure(SendCommand(device, request, OnAttestationResponse, OnAttestationFailureResponse, timeout)); + ReturnErrorOnFailure( + SendCommissioningCommand(device, request, OnAttestationResponse, OnAttestationFailureResponse, kRootEndpointId, timeout)); ChipLogDetail(Controller, "Sent Attestation request, waiting for the Attestation Information"); return CHIP_NO_ERROR; } @@ -1218,7 +1237,7 @@ bool DeviceCommissioner::ExtendArmFailSafe(DeviceProxy * proxy, CommissioningSta request.expiryLengthSeconds = armFailSafeTimeout; request.breadcrumb = breadcrumb; ChipLogProgress(Controller, "Arming failsafe (%u seconds)", request.expiryLengthSeconds); - CHIP_ERROR err = SendCommand(proxy, request, onSuccess, onFailure, kRootEndpointId, commandTimeout); + CHIP_ERROR err = SendCommissioningCommand(proxy, request, onSuccess, onFailure, kRootEndpointId, commandTimeout); if (err != CHIP_NO_ERROR) { onFailure(this, err); @@ -1309,7 +1328,8 @@ CHIP_ERROR DeviceCommissioner::SendOperationalCertificateSigningRequestCommand(D OperationalCredentials::Commands::CSRRequest::Type request; request.CSRNonce = csrNonce; - ReturnErrorOnFailure(SendCommand(device, request, OnOperationalCertificateSigningRequest, OnCSRFailureResponse, timeout)); + ReturnErrorOnFailure(SendCommissioningCommand(device, request, OnOperationalCertificateSigningRequest, OnCSRFailureResponse, + kRootEndpointId, timeout)); ChipLogDetail(Controller, "Sent CSR request, waiting for the CSR"); return CHIP_NO_ERROR; } @@ -1431,7 +1451,8 @@ CHIP_ERROR DeviceCommissioner::SendOperationalCertificate(DeviceProxy * device, request.caseAdminSubject = adminSubject; request.adminVendorId = mVendorId; - ReturnErrorOnFailure(SendCommand(device, request, OnOperationalCertificateAddResponse, OnAddNOCFailureResponse, timeout)); + ReturnErrorOnFailure(SendCommissioningCommand(device, request, OnOperationalCertificateAddResponse, OnAddNOCFailureResponse, + kRootEndpointId, timeout)); ChipLogProgress(Controller, "Sent operational certificate to the device"); @@ -1515,7 +1536,8 @@ CHIP_ERROR DeviceCommissioner::SendTrustedRootCertificate(DeviceProxy * device, OperationalCredentials::Commands::AddTrustedRootCertificate::Type request; request.rootCACertificate = rcac; - ReturnErrorOnFailure(SendCommand(device, request, OnRootCertSuccessResponse, OnRootCertFailureResponse, timeout)); + ReturnErrorOnFailure( + SendCommissioningCommand(device, request, OnRootCertSuccessResponse, OnRootCertFailureResponse, kRootEndpointId, timeout)); ChipLogProgress(Controller, "Sent root certificate to the device"); @@ -1623,13 +1645,13 @@ void DeviceCommissioner::OnNodeDiscovered(const chip::Dnssd::DiscoveredNodeData mSetUpCodePairer.NotifyCommissionableDeviceDiscovered(nodeData); } -void OnBasicSuccess(void * context, const chip::app::DataModel::NullObjectType &) +void DeviceCommissioner::OnBasicSuccess(void * context, const chip::app::DataModel::NullObjectType &) { DeviceCommissioner * commissioner = static_cast(context); commissioner->CommissioningStageComplete(CHIP_NO_ERROR); } -void OnBasicFailure(void * context, CHIP_ERROR error) +void DeviceCommissioner::OnBasicFailure(void * context, CHIP_ERROR error) { ChipLogProgress(Controller, "Received failure response %s\n", chip::ErrorStr(error)); DeviceCommissioner * commissioner = static_cast(context); @@ -1638,7 +1660,7 @@ void OnBasicFailure(void * context, CHIP_ERROR error) void DeviceCommissioner::CleanupCommissioning(DeviceProxy * proxy, NodeId nodeId, const CompletionStatus & completionStatus) { - commissioningCompletionStatus = completionStatus; + mCommissioningCompletionStatus = completionStatus; if (completionStatus.err == CHIP_NO_ERROR) { @@ -1650,15 +1672,17 @@ void DeviceCommissioner::CleanupCommissioning(DeviceProxy * proxy, NodeId nodeId } // Send the callbacks, we're done. CommissioningStageComplete(CHIP_NO_ERROR); - SendCommissioningCompleteCallbacks(nodeId, commissioningCompletionStatus); + SendCommissioningCompleteCallbacks(nodeId, mCommissioningCompletionStatus); } - else if (completionStatus.failedStage.HasValue() && completionStatus.failedStage.Value() >= kWiFiNetworkSetup) + else if (completionStatus.failedStage.HasValue() && completionStatus.failedStage.Value() >= kWiFiNetworkSetup && + completionStatus.err != CHIP_ERROR_CANCELLED) { // If we were already doing network setup, we need to retain the pase session and start again from network setup stage. // We do not need to reset the failsafe here because we want to keep everything on the device up to this point, so just - // send the completion callbacks. + // send the completion callbacks (see "Commissioning Flows Error Handling" in the spec). This does not apply if + // we're cleaning up because cancellation has been requested via StopPairing(). CommissioningStageComplete(CHIP_NO_ERROR); - SendCommissioningCompleteCallbacks(nodeId, commissioningCompletionStatus); + SendCommissioningCompleteCallbacks(nodeId, mCommissioningCompletionStatus); } else { @@ -1671,8 +1695,8 @@ void DeviceCommissioner::CleanupCommissioning(DeviceProxy * proxy, NodeId nodeId ChipLogProgress(Controller, "Expiring failsafe on proxy %p", proxy); mDeviceBeingCommissioned = proxy; // We actually want to do the same thing on success or failure because we're already in a failure state - CHIP_ERROR err = SendCommand(proxy, request, OnDisarmFailsafe, OnDisarmFailsafeFailure, - /* timeout = */ NullOptional); + CHIP_ERROR err = SendCommissioningCommand(proxy, request, OnDisarmFailsafe, OnDisarmFailsafeFailure, kRootEndpointId, + /* timeout = */ NullOptional); if (err != CHIP_NO_ERROR) { // We won't get any async callbacks here, so just pretend like the @@ -1694,7 +1718,7 @@ void DeviceCommissioner::OnDisarmFailsafe(void * context, void DeviceCommissioner::OnDisarmFailsafeFailure(void * context, CHIP_ERROR error) { - ChipLogProgress(Controller, "Received failure response when disarming failsafe%s\n", chip::ErrorStr(error)); + ChipLogProgress(Controller, "Ignoring failure to disarm failsafe: %" CHIP_ERROR_FORMAT, error.Format()); DeviceCommissioner * commissioner = static_cast(context); commissioner->DisarmDone(); } @@ -1711,7 +1735,7 @@ void DeviceCommissioner::DisarmDone() // Signal completion - this will reset mDeviceBeingCommissioned. CommissioningStageComplete(CHIP_NO_ERROR); - SendCommissioningCompleteCallbacks(nodeId, commissioningCompletionStatus); + SendCommissioningCompleteCallbacks(nodeId, mCommissioningCompletionStatus); // If we've disarmed the failsafe, it's because we're starting again, so kill the pase connection. if (commissionee != nullptr) @@ -1722,7 +1746,10 @@ void DeviceCommissioner::DisarmDone() void DeviceCommissioner::SendCommissioningCompleteCallbacks(NodeId nodeId, const CompletionStatus & completionStatus) { + ChipLogProgress(Controller, "Commissioning complete for node ID 0x" ChipLogFormatX64 ": %s", ChipLogValueX64(nodeId), + (completionStatus.err == CHIP_NO_ERROR ? "success" : completionStatus.err.AsString())); mCommissioningStage = CommissioningStage::kSecurePairing; + if (mPairingDelegate == nullptr) { return; @@ -1746,17 +1773,12 @@ void DeviceCommissioner::CommissioningStageComplete(CHIP_ERROR err, Commissionin { // Once this stage is complete, reset mDeviceBeingCommissioned - this will be reset when the delegate calls the next step. MATTER_TRACE_SCOPE("CommissioningStageComplete", "DeviceCommissioner"); - if (mDeviceBeingCommissioned == nullptr) - { - // We are getting a stray callback (e.g. due to un-cancellable - // operations) when we are not in fact commissioning anything. Just - // ignore it. - return; - } + VerifyOrDie(mDeviceBeingCommissioned); NodeId nodeId = mDeviceBeingCommissioned->GetDeviceId(); DeviceProxy * proxy = mDeviceBeingCommissioned; mDeviceBeingCommissioned = nullptr; + mInvokeCancelFn = nullptr; if (mPairingDelegate != nullptr) { @@ -1769,7 +1791,7 @@ void DeviceCommissioner::CommissioningStageComplete(CHIP_ERROR err, Commissionin } report.stageCompleted = mCommissioningStage; CHIP_ERROR status = mCommissioningDelegate->CommissioningStepFinished(err, report); - if (status != CHIP_NO_ERROR) + if (status != CHIP_NO_ERROR && mCommissioningStage != CommissioningStage::kCleanup) { // Commissioning delegate will only return error if it failed to perform the appropriate commissioning step. // In this case, we should complete the commissioning for it. @@ -1898,9 +1920,10 @@ void DeviceCommissioner::OnDeviceConnectionRetryFn(void * context, const ScopedN #endif // CHIP_DEVICE_CONFIG_ENABLE_AUTOMATIC_CASE_RETRIES // ClusterStateCache::Callback impl -void DeviceCommissioner::OnDone(app::ReadClient *) +void DeviceCommissioner::OnDone(app::ReadClient * readClient) { - mReadClient = nullptr; + VerifyOrDie(readClient != nullptr && readClient == mReadClient.get()); + mReadClient.reset(); switch (mCommissioningStage) { case CommissioningStage::kReadCommissioningInfo: @@ -1913,6 +1936,7 @@ void DeviceCommissioner::OnDone(app::ReadClient *) ParseCommissioningInfo(); break; default: + VerifyOrDie(false); break; } } @@ -2484,9 +2508,31 @@ void DeviceCommissioner::OnCommissioningCompleteResponse( commissioner->CommissioningStageComplete(err, report); } +template +CHIP_ERROR +DeviceCommissioner::SendCommissioningCommand(DeviceProxy * device, const RequestObjectT & request, + CommandResponseSuccessCallback successCb, + CommandResponseFailureCallback failureCb, EndpointId endpoint, + Optional timeout) + +{ + VerifyOrDie(!mInvokeCancelFn); // we don't make parallel calls + + auto onSuccessCb = [context = this, successCb](const app::ConcreteCommandPath & aPath, const app::StatusIB & aStatus, + const typename RequestObjectT::ResponseType & responseData) { + successCb(context, responseData); + }; + auto onFailureCb = [context = this, failureCb](CHIP_ERROR aError) { failureCb(context, aError); }; + + return InvokeCommandRequest(device->GetExchangeManager(), device->GetSecureSession().Value(), endpoint, request, onSuccessCb, + onFailureCb, NullOptional, timeout, &mInvokeCancelFn); +} + void DeviceCommissioner::SendCommissioningReadRequest(DeviceProxy * proxy, Optional timeout, app::AttributePathParams * readPaths, size_t readPathsSize) { + VerifyOrDie(!mReadClient); // we don't perform parallel reads + app::InteractionModelEngine * engine = app::InteractionModelEngine::GetInstance(); app::ReadPrepareParams readParams(proxy->GetSecureSession().Value()); readParams.mIsFabricFiltered = false; @@ -2635,7 +2681,7 @@ void DeviceCommissioner::PerformCommissioningStep(DeviceProxy * proxy, Commissio request.UTCTime = utcTime.count() - kChipEpochUsSinceUnixEpoch; // For now, we assume a seconds granularity request.granularity = TimeSynchronization::GranularityEnum::kSecondsGranularity; - CHIP_ERROR err = SendCommand(proxy, request, OnBasicSuccess, OnSetUTCError, endpoint, timeout); + CHIP_ERROR err = SendCommissioningCommand(proxy, request, OnBasicSuccess, OnSetUTCError, endpoint, timeout); if (err != CHIP_NO_ERROR) { // We won't get any async callbacks here, so just complete our stage. @@ -2654,7 +2700,7 @@ void DeviceCommissioner::PerformCommissioningStep(DeviceProxy * proxy, Commissio } TimeSynchronization::Commands::SetTimeZone::Type request; request.timeZone = params.GetTimeZone().Value(); - CHIP_ERROR err = SendCommand(proxy, request, OnSetTimeZoneResponse, OnBasicFailure, endpoint, timeout); + CHIP_ERROR err = SendCommissioningCommand(proxy, request, OnSetTimeZoneResponse, OnBasicFailure, endpoint, timeout); if (err != CHIP_NO_ERROR) { // We won't get any async callbacks here, so just complete our stage. @@ -2673,7 +2719,7 @@ void DeviceCommissioner::PerformCommissioningStep(DeviceProxy * proxy, Commissio } TimeSynchronization::Commands::SetDSTOffset::Type request; request.DSTOffset = params.GetDSTOffsets().Value(); - CHIP_ERROR err = SendCommand(proxy, request, OnBasicSuccess, OnBasicFailure, endpoint, timeout); + CHIP_ERROR err = SendCommissioningCommand(proxy, request, OnBasicSuccess, OnBasicFailure, endpoint, timeout); if (err != CHIP_NO_ERROR) { // We won't get any async callbacks here, so just complete our stage. @@ -2692,7 +2738,7 @@ void DeviceCommissioner::PerformCommissioningStep(DeviceProxy * proxy, Commissio } TimeSynchronization::Commands::SetDefaultNTP::Type request; request.defaultNTP = params.GetDefaultNTP().Value(); - CHIP_ERROR err = SendCommand(proxy, request, OnBasicSuccess, OnBasicFailure, endpoint, timeout); + CHIP_ERROR err = SendCommissioningCommand(proxy, request, OnBasicSuccess, OnBasicFailure, endpoint, timeout); if (err != CHIP_NO_ERROR) { // We won't get any async callbacks here, so just complete our stage. @@ -2709,7 +2755,7 @@ void DeviceCommissioner::PerformCommissioningStep(DeviceProxy * proxy, Commissio request.ssid.Emplace(params.GetWiFiCredentials().Value().ssid); } request.breadcrumb.Emplace(breadcrumb); - CHIP_ERROR err = SendCommand(proxy, request, OnScanNetworksResponse, OnScanNetworksFailure, endpoint, timeout); + CHIP_ERROR err = SendCommissioningCommand(proxy, request, OnScanNetworksResponse, OnScanNetworksFailure, endpoint, timeout); if (err != CHIP_NO_ERROR) { // We won't get any async callbacks here, so just complete our stage. @@ -2776,7 +2822,7 @@ void DeviceCommissioner::PerformCommissioningStep(DeviceProxy * proxy, Commissio request.newRegulatoryConfig = regulatoryConfig; request.countryCode = countryCode; request.breadcrumb = breadcrumb; - CHIP_ERROR err = SendCommand(proxy, request, OnSetRegulatoryConfigResponse, OnBasicFailure, endpoint, timeout); + CHIP_ERROR err = SendCommissioningCommand(proxy, request, OnSetRegulatoryConfigResponse, OnBasicFailure, endpoint, timeout); if (err != CHIP_NO_ERROR) { // We won't get any async callbacks here, so just complete our stage. @@ -2968,7 +3014,7 @@ void DeviceCommissioner::PerformCommissioningStep(DeviceProxy * proxy, Commissio } TimeSynchronization::Commands::SetTrustedTimeSource::Type request; request.trustedTimeSource = params.GetTrustedTimeSource().Value(); - CHIP_ERROR err = SendCommand(proxy, request, OnBasicSuccess, OnBasicFailure, endpoint, timeout); + CHIP_ERROR err = SendCommissioningCommand(proxy, request, OnBasicSuccess, OnBasicFailure, endpoint, timeout); if (err != CHIP_NO_ERROR) { // We won't get any async callbacks here, so just complete our stage. @@ -2990,7 +3036,7 @@ void DeviceCommissioner::PerformCommissioningStep(DeviceProxy * proxy, Commissio request.ssid = params.GetWiFiCredentials().Value().ssid; request.credentials = params.GetWiFiCredentials().Value().credentials; request.breadcrumb.Emplace(breadcrumb); - CHIP_ERROR err = SendCommand(proxy, request, OnNetworkConfigResponse, OnBasicFailure, endpoint, timeout); + CHIP_ERROR err = SendCommissioningCommand(proxy, request, OnNetworkConfigResponse, OnBasicFailure, endpoint, timeout); if (err != CHIP_NO_ERROR) { // We won't get any async callbacks here, so just complete our stage. @@ -3010,7 +3056,7 @@ void DeviceCommissioner::PerformCommissioningStep(DeviceProxy * proxy, Commissio NetworkCommissioning::Commands::AddOrUpdateThreadNetwork::Type request; request.operationalDataset = params.GetThreadOperationalDataset().Value(); request.breadcrumb.Emplace(breadcrumb); - CHIP_ERROR err = SendCommand(proxy, request, OnNetworkConfigResponse, OnBasicFailure, endpoint, timeout); + CHIP_ERROR err = SendCommissioningCommand(proxy, request, OnNetworkConfigResponse, OnBasicFailure, endpoint, timeout); if (err != CHIP_NO_ERROR) { // We won't get any async callbacks here, so just complete our stage. @@ -3044,7 +3090,7 @@ void DeviceCommissioner::PerformCommissioningStep(DeviceProxy * proxy, Commissio params.GetSupportsConcurrentConnection().HasValue() ? (params.GetSupportsConcurrentConnection().Value() ? "true" : "false") : "missing"); - err = SendCommand(proxy, request, OnConnectNetworkResponse, OnBasicFailure, endpoint, timeout); + err = SendCommissioningCommand(proxy, request, OnConnectNetworkResponse, OnBasicFailure, endpoint, timeout); if (err != CHIP_NO_ERROR) { @@ -3069,7 +3115,7 @@ void DeviceCommissioner::PerformCommissioningStep(DeviceProxy * proxy, Commissio NetworkCommissioning::Commands::ConnectNetwork::Type request; request.networkID = extendedPanId; request.breadcrumb.Emplace(breadcrumb); - CHIP_ERROR err = SendCommand(proxy, request, OnConnectNetworkResponse, OnBasicFailure, endpoint, timeout); + CHIP_ERROR err = SendCommissioningCommand(proxy, request, OnConnectNetworkResponse, OnBasicFailure, endpoint, timeout); if (err != CHIP_NO_ERROR) { // We won't get any async callbacks here, so just complete our stage. @@ -3099,7 +3145,8 @@ void DeviceCommissioner::PerformCommissioningStep(DeviceProxy * proxy, Commissio request.monitoredSubject = params.GetICDMonitoredSubject().Value(); request.key = params.GetICDSymmetricKey().Value(); - CHIP_ERROR err = SendCommand(proxy, request, OnICDManagementRegisterClientResponse, OnBasicFailure, endpoint, timeout); + CHIP_ERROR err = + SendCommissioningCommand(proxy, request, OnICDManagementRegisterClientResponse, OnBasicFailure, endpoint, timeout); if (err != CHIP_NO_ERROR) { // We won't get any async callbacks here, so just complete our stage. @@ -3137,7 +3184,8 @@ void DeviceCommissioner::PerformCommissioningStep(DeviceProxy * proxy, Commissio break; case CommissioningStage::kSendComplete: { GeneralCommissioning::Commands::CommissioningComplete::Type request; - CHIP_ERROR err = SendCommand(proxy, request, OnCommissioningCompleteResponse, OnBasicFailure, endpoint, timeout); + CHIP_ERROR err = + SendCommissioningCommand(proxy, request, OnCommissioningCompleteResponse, OnBasicFailure, endpoint, timeout); if (err != CHIP_NO_ERROR) { // We won't get any async callbacks here, so just complete our stage. diff --git a/src/controller/CHIPDeviceController.h b/src/controller/CHIPDeviceController.h index a7e6f6dac4bcb9..024421dd8a1a6e 100644 --- a/src/controller/CHIPDeviceController.h +++ b/src/controller/CHIPDeviceController.h @@ -84,10 +84,6 @@ using namespace chip::Protocols::UserDirectedCommissioning; inline constexpr uint16_t kNumMaxActiveDevices = CHIP_CONFIG_CONTROLLER_MAX_ACTIVE_DEVICES; -// Raw functions for cluster callbacks -void OnBasicFailure(void * context, CHIP_ERROR err); -void OnBasicSuccess(void * context, const chip::app::DataModel::NullObjectType &); - struct ControllerInitParams { DeviceControllerSystemState * systemState = nullptr; @@ -569,8 +565,12 @@ class DLL_EXPORT DeviceCommissioner : public DeviceController, /** * @brief - * This function stops a pairing process that's in progress. It does not delete the pairing of a previously - * paired device. + * This function stops a pairing or commissioning process that is in progress. + * It does not delete the pairing of a previously paired device. + * + * Note that cancelling an ongoing commissioning process is an asynchronous operation. + * The pairing delegate (if any) will receive OnCommissioningComplete and OnCommissioningFailure + * failure callbacks with a status code of CHIP_ERROR_CANCELLED once cancellation is complete. * * @param[in] remoteDeviceId The remote device Id. * @@ -769,13 +769,14 @@ class DLL_EXPORT DeviceCommissioner : public DeviceController, OnExtendFailsafeFailure onFailure); private: - DevicePairingDelegate * mPairingDelegate; + DevicePairingDelegate * mPairingDelegate = nullptr; DeviceProxy * mDeviceBeingCommissioned = nullptr; CommissioneeDeviceProxy * mDeviceInPASEEstablishment = nullptr; CommissioningStage mCommissioningStage = CommissioningStage::kSecurePairing; bool mRunCommissioningAfterConnection = false; + Internal::InvokeCancelFn mInvokeCancelFn; ObjectPool mCommissioneeDevicePool; @@ -794,6 +795,9 @@ class DLL_EXPORT DeviceCommissioner : public DeviceController, CHIP_ERROR LoadKeyId(PersistentStorageDelegate * delegate, uint16_t & out); + static void OnBasicFailure(void * context, CHIP_ERROR err); + static void OnBasicSuccess(void * context, const chip::app::DataModel::NullObjectType &); + /* This function sends a Device Attestation Certificate chain request to the device. The function does not hold a reference to the device object. */ @@ -955,26 +959,14 @@ class DLL_EXPORT DeviceCommissioner : public DeviceController, void ReleaseCommissioneeDevice(CommissioneeDeviceProxy * device); template - CHIP_ERROR SendCommand(DeviceProxy * device, const RequestObjectT & request, - CommandResponseSuccessCallback successCb, - CommandResponseFailureCallback failureCb, Optional timeout) - { - return SendCommand(device, request, successCb, failureCb, 0, timeout); - } - - template - CHIP_ERROR SendCommand(DeviceProxy * device, const RequestObjectT & request, - CommandResponseSuccessCallback successCb, - CommandResponseFailureCallback failureCb, EndpointId endpoint, Optional timeout) - { - ClusterBase cluster(*device->GetExchangeManager(), device->GetSecureSession().Value(), endpoint); - cluster.SetCommandTimeout(timeout); - - return cluster.InvokeCommand(request, this, successCb, failureCb); - } - + CHIP_ERROR SendCommissioningCommand(DeviceProxy * device, const RequestObjectT & request, + CommandResponseSuccessCallback successCb, + CommandResponseFailureCallback failureCb, EndpointId endpoint, + Optional timeout); void SendCommissioningReadRequest(DeviceProxy * proxy, Optional timeout, app::AttributePathParams * readPaths, size_t readPathsSize); + void CancelCommissioningInteractions(); + #if CHIP_CONFIG_ENABLE_READ_CLIENT void ParseCommissioningInfo(); // Parsing attributes read in kReadCommissioningInfo stage. @@ -1024,7 +1016,7 @@ class DLL_EXPORT DeviceCommissioner : public DeviceController, nullptr; // Commissioning delegate to call when PairDevice / Commission functions are used CommissioningDelegate * mCommissioningDelegate = nullptr; // Commissioning delegate that issued the PerformCommissioningStep command - CompletionStatus commissioningCompletionStatus; + CompletionStatus mCommissioningCompletionStatus; #if CHIP_CONFIG_ENABLE_READ_CLIENT Platform::UniquePtr mAttributeCache; diff --git a/src/controller/InvokeInteraction.h b/src/controller/InvokeInteraction.h index d167cde140db23..7576f8aac2e78b 100644 --- a/src/controller/InvokeInteraction.h +++ b/src/controller/InvokeInteraction.h @@ -18,13 +18,19 @@ #pragma once -#include #include #include +#include + namespace chip { namespace Controller { +namespace Internal { +// Cancellation functions on InvokeCommandRequest() are for internal use only. +typedef std::function InvokeCancelFn; +} // namespace Internal + /* * A typed command invocation function that takes as input a cluster-object representation of a command request and * callbacks for success and failure and either returns a decoded cluster-object representation of the response through @@ -49,7 +55,8 @@ InvokeCommandRequest(Messaging::ExchangeManager * aExchangeMgr, const SessionHan typename TypedCommandCallback::OnSuccessCallbackType onSuccessCb, typename TypedCommandCallback::OnErrorCallbackType onErrorCb, const Optional & timedInvokeTimeoutMs, - const Optional & responseTimeout = NullOptional) + const Optional & responseTimeout = NullOptional, + Internal::InvokeCancelFn * outCancelFn = nullptr) { // InvokeCommandRequest expects responses, so cannot happen over a group session. VerifyOrReturnError(!sessionHandle->IsGroupSession(), CHIP_ERROR_INVALID_ARGUMENT); @@ -81,6 +88,15 @@ InvokeCommandRequest(Messaging::ExchangeManager * aExchangeMgr, const SessionHan ReturnErrorOnFailure(commandSender->AddRequestData(commandPath, requestCommandData, timedInvokeTimeoutMs)); ReturnErrorOnFailure(commandSender->SendCommandRequest(sessionHandle, responseTimeout)); + // If requested by the caller, provide a way to cancel the invoke interaction. + if (outCancelFn != nullptr) + { + *outCancelFn = [rawDecoderPtr = decoder.get(), rawCommandSender = commandSender.get()]() { + chip::Platform::Delete(rawCommandSender); + chip::Platform::Delete(rawDecoderPtr); + }; + } + // // We've effectively transferred ownership of the above allocated objects to CommandSender, and we need to wait for it to call // us back when processing is completed (through OnDone) to eventually free up resources. diff --git a/src/darwin/Framework/CHIP/MTRError.h b/src/darwin/Framework/CHIP/MTRError.h index 8eaefbd50df643..3068a1b2405779 100644 --- a/src/darwin/Framework/CHIP/MTRError.h +++ b/src/darwin/Framework/CHIP/MTRError.h @@ -56,21 +56,25 @@ typedef NS_ERROR_ENUM(MTRErrorDomain, MTRErrorCode){ MTRErrorCodeIntegrityCheckFailed = 8, MTRErrorCodeTimeout = 9, MTRErrorCodeBufferTooSmall = 10, + /** * MTRErrorCodeFabricExists is returned when trying to commission a device * into a fabric when it's already part of that fabric. */ MTRErrorCodeFabricExists = 11, + /** * MTRErrorCodeUnknownSchema means the schema for the given cluster/attribute, * cluster/event, or cluster/command combination is not known. */ MTRErrorCodeUnknownSchema MTR_AVAILABLE(ios(17.0), macos(14.0), watchos(10.0), tvos(17.0)) = 12, + /** * MTRErrorCodeSchemaMismatch means that provided data did not match the * expected schema. */ MTRErrorCodeSchemaMismatch MTR_AVAILABLE(ios(17.0), macos(14.0), watchos(10.0), tvos(17.0)) = 13, + /** * MTRErrorCodeTLVDecodeFailed means that the TLV being decoded was malformed in * some way. This can include things like lengths running past the end of @@ -87,6 +91,11 @@ typedef NS_ERROR_ENUM(MTRErrorDomain, MTRErrorCode){ * application's Info.plist. */ MTRErrorCodeDNSSDUnauthorized MTR_AVAILABLE(ios(17.2), macos(14.2), watchos(10.2), tvos(17.2)) = 15, + + /** + * The operation was cancelled. + */ + MTRErrorCodeCancelled MTR_NEWLY_AVAILABLE = 16, }; // clang-format on diff --git a/src/darwin/Framework/CHIP/MTRError.mm b/src/darwin/Framework/CHIP/MTRError.mm index 0cb40006ac3293..d607f00400d158 100644 --- a/src/darwin/Framework/CHIP/MTRError.mm +++ b/src/darwin/Framework/CHIP/MTRError.mm @@ -61,52 +61,72 @@ + (NSError *)errorForCHIPErrorCode:(CHIP_ERROR)errorCode logContext:(id)contextT return [MTRError errorForIMStatus:status]; } - NSMutableDictionary * userInfo = [[NSMutableDictionary alloc] init]; - MTRErrorCode code = MTRErrorCodeGeneralError; - - if (errorCode == CHIP_ERROR_INVALID_STRING_LENGTH) { + MTRErrorCode code; + NSString * description; + NSDictionary * additionalUserInfo; + switch (errorCode.AsInteger()) { + case CHIP_ERROR_INVALID_STRING_LENGTH.AsInteger(): code = MTRErrorCodeInvalidStringLength; - [userInfo addEntriesFromDictionary:@{ NSLocalizedDescriptionKey : NSLocalizedString(@"A list length is invalid.", nil) }]; - } else if (errorCode == CHIP_ERROR_INVALID_INTEGER_VALUE) { + description = NSLocalizedString(@"A list length is invalid.", nil); + break; + case CHIP_ERROR_INVALID_INTEGER_VALUE.AsInteger(): code = MTRErrorCodeInvalidIntegerValue; - [userInfo addEntriesFromDictionary:@{ NSLocalizedDescriptionKey : NSLocalizedString(@"Unexpected integer value.", nil) }]; - } else if (errorCode == CHIP_ERROR_INVALID_ARGUMENT) { + description = NSLocalizedString(@"Unexpected integer value.", nil); + break; + case CHIP_ERROR_INVALID_ARGUMENT.AsInteger(): code = MTRErrorCodeInvalidArgument; - [userInfo addEntriesFromDictionary:@{ NSLocalizedDescriptionKey : NSLocalizedString(@"An argument is invalid.", nil) }]; - } else if (errorCode == CHIP_ERROR_INVALID_MESSAGE_LENGTH) { + description = NSLocalizedString(@"An argument is invalid.", nil); + break; + case CHIP_ERROR_INVALID_MESSAGE_LENGTH.AsInteger(): code = MTRErrorCodeInvalidMessageLength; - [userInfo - addEntriesFromDictionary:@{ NSLocalizedDescriptionKey : NSLocalizedString(@"A message length is invalid.", nil) }]; - } else if (errorCode == CHIP_ERROR_INCORRECT_STATE) { + description = NSLocalizedString(@"A message length is invalid.", nil); + break; + case CHIP_ERROR_INCORRECT_STATE.AsInteger(): code = MTRErrorCodeInvalidState; - [userInfo addEntriesFromDictionary:@{ NSLocalizedDescriptionKey : NSLocalizedString(@"Invalid object state.", nil) }]; - } else if (errorCode == CHIP_ERROR_INTEGRITY_CHECK_FAILED) { + description = NSLocalizedString(@"Invalid object state.", nil); + break; + case CHIP_ERROR_INTEGRITY_CHECK_FAILED.AsInteger(): code = MTRErrorCodeIntegrityCheckFailed; - [userInfo addEntriesFromDictionary:@{ NSLocalizedDescriptionKey : NSLocalizedString(@"Integrity check failed.", nil) }]; - } else if (errorCode == CHIP_ERROR_TIMEOUT) { + description = NSLocalizedString(@"Integrity check failed.", nil); + break; + case CHIP_ERROR_TIMEOUT.AsInteger(): code = MTRErrorCodeTimeout; - [userInfo addEntriesFromDictionary:@{ NSLocalizedDescriptionKey : NSLocalizedString(@"Transaction timed out.", nil) }]; - } else if (errorCode == CHIP_ERROR_BUFFER_TOO_SMALL) { + description = NSLocalizedString(@"Transaction timed out.", nil); + break; + case CHIP_ERROR_BUFFER_TOO_SMALL.AsInteger(): code = MTRErrorCodeBufferTooSmall; - [userInfo addEntriesFromDictionary:@{ NSLocalizedDescriptionKey : NSLocalizedString(@"A buffer is too small.", nil) }]; - } else if (errorCode == CHIP_ERROR_FABRIC_EXISTS) { + description = NSLocalizedString(@"A buffer is too small.", nil); + break; + case CHIP_ERROR_FABRIC_EXISTS.AsInteger(): code = MTRErrorCodeFabricExists; - [userInfo addEntriesFromDictionary:@{ - NSLocalizedDescriptionKey : NSLocalizedString(@"The device is already a member of this fabric.", nil) - }]; - } else if (errorCode == CHIP_ERROR_DECODE_FAILED) { + description = NSLocalizedString(@"The device is already a member of this fabric.", nil); + break; + case CHIP_ERROR_DECODE_FAILED.AsInteger(): code = MTRErrorCodeTLVDecodeFailed; - [userInfo addEntriesFromDictionary:@{ NSLocalizedDescriptionKey : NSLocalizedString(@"TLV decoding failed.", nil) }]; - } else if (errorCode == CHIP_ERROR_DNS_SD_UNAUTHORIZED) { + description = NSLocalizedString(@"TLV decoding failed.", nil); + break; + case CHIP_ERROR_DNS_SD_UNAUTHORIZED.AsInteger(): code = MTRErrorCodeDNSSDUnauthorized; - [userInfo addEntriesFromDictionary:@{ NSLocalizedDescriptionKey : NSLocalizedString(@"Access denied to perform DNS-SD lookups. Check that \"_matter._tcp\" and/or \"_matterc._udp\" are listed under the NSBonjourServices key in Info.plist", nil) }]; - } else { + description = NSLocalizedString(@"Access denied to perform DNS-SD lookups. " + "Check that \"_matter._tcp\" and/or \"_matterc._udp\" " + "are listed under the NSBonjourServices key in Info.plist", + nil); + break; + case CHIP_ERROR_CANCELLED.AsInteger(): + code = MTRErrorCodeCancelled; + description = NSLocalizedString(@"The operation was cancelled.", nil); + break; + default: code = MTRErrorCodeGeneralError; - [userInfo addEntriesFromDictionary:@{ - NSLocalizedDescriptionKey : - [NSString stringWithFormat:NSLocalizedString(@"Undefined error:%u.", nil), errorCode.AsInteger()], - @"errorCode" : @(errorCode.AsInteger()), - }]; + description = [NSString stringWithFormat:NSLocalizedString(@"General error: %u", nil), errorCode.AsInteger()]; + additionalUserInfo = @{ @"errorCode" : @(errorCode.AsInteger()) }; + } + + NSDictionary * userInfo = @{ NSLocalizedDescriptionKey : description }; + if (additionalUserInfo) { + NSMutableDictionary * combined = [userInfo mutableCopy]; + [combined addEntriesFromDictionary:additionalUserInfo]; + userInfo = combined; } auto * error = [NSError errorWithDomain:MTRErrorDomain code:code userInfo:userInfo]; @@ -125,105 +145,87 @@ + (NSError *)errorForIMStatus:(const chip::app::StatusIB &)status using chip::Protocols::InteractionModel::Status; switch (status.mStatus) { case Status::Failure: - default: { + default: description = NSLocalizedString(@"Operation was not successful.", nil); break; - } - case Status::InvalidSubscription: { + case Status::InvalidSubscription: description = NSLocalizedString(@"Subscription ID is not active.", nil); break; - } - case Status::UnsupportedAccess: { + case Status::UnsupportedAccess: description = NSLocalizedString(@"The sender of the action or command does not have authorization or access.", nil); break; - } - case Status::UnsupportedEndpoint: { + case Status::UnsupportedEndpoint: description = NSLocalizedString(@"The endpoint indicated is unsupported on the node.", nil); break; - } - case Status::InvalidAction: { - description = NSLocalizedString( - @"The action is malformed, has missing fields, or fields with invalid values. Action not carried out.", nil); + case Status::InvalidAction: + description = NSLocalizedString(@"The action is malformed, has missing fields, or fields with invalid values. " + "Action not carried out.", + nil); break; - } - case Status::UnsupportedCommand: { - description = NSLocalizedString( - @"The specified action or command indicated is not supported on the device. Command or action not carried out.", nil); + case Status::UnsupportedCommand: + description = NSLocalizedString(@"The specified action or command indicated is not supported on the device." + "Command or action not carried out.", + nil); break; - } - case Status::InvalidCommand: { - description = NSLocalizedString( - @"The cluster command is malformed, has missing fields, or fields with invalid values. Command not carried out.", nil); + case Status::InvalidCommand: + description = NSLocalizedString(@"The cluster command is malformed, has missing fields, or fields with invalid values." + "Command not carried out.", + nil); break; - } - case Status::UnsupportedAttribute: { - description - = NSLocalizedString(@"The specified attribute or attribute data field or entry does not exist on the device.", nil); + case Status::UnsupportedAttribute: + description = NSLocalizedString(@"The specified attribute or attribute data field or entry does not exist on the device.", nil); break; - } - case Status::ConstraintError: { + case Status::ConstraintError: description = NSLocalizedString(@"Out of range error or set to a reserved value.", nil); break; - } - case Status::UnsupportedWrite: { + case Status::UnsupportedWrite: description = NSLocalizedString(@"Attempt to write a read-only attribute.", nil); break; - } - case Status::ResourceExhausted: { + case Status::ResourceExhausted: description = NSLocalizedString(@"An action or operation failed due to insufficient available resources. ", nil); break; - } - case Status::NotFound: { + case Status::NotFound: description = NSLocalizedString(@"The indicated data field or entry could not be found.", nil); break; - } - case Status::UnreportableAttribute: { + case Status::UnreportableAttribute: description = NSLocalizedString(@"Reports cannot be issued for this attribute.", nil); break; - } - case Status::InvalidDataType: { - description = NSLocalizedString( - @"The data type indicated is undefined or invalid for the indicated data field. Command or action not carried out.", + case Status::InvalidDataType: + description = NSLocalizedString(@"The data type indicated is undefined or invalid for the indicated data field. " + "Command or action not carried out.", nil); break; - } - case Status::UnsupportedRead: { + case Status::UnsupportedRead: description = NSLocalizedString(@"Attempt to read a write-only attribute.", nil); break; - } - case Status::DataVersionMismatch: { + case Status::DataVersionMismatch: description = NSLocalizedString(@"Cluster instance data version did not match request path.", nil); break; - } - case Status::Timeout: { + case Status::Timeout: description = NSLocalizedString(@"The transaction was aborted due to time being exceeded.", nil); break; - } case Status::Busy: { - description = NSLocalizedString( - @"The receiver is busy processing another action that prevents the execution of the incoming action.", nil); + description = NSLocalizedString(@"The receiver is busy processing another action " + "that prevents the execution of the incoming action.", + nil); break; - } - case Status::UnsupportedCluster: { + case Status::UnsupportedCluster: description = NSLocalizedString(@"The cluster indicated is not supported", nil); break; - } // Gap in values is intentional. - case Status::NoUpstreamSubscription: { + case Status::NoUpstreamSubscription: description = NSLocalizedString(@"Proxy does not have a subscription to the source.", nil); break; } - case Status::NeedsTimedInteraction: { - description = NSLocalizedString(@"An Untimed Write or Untimed Invoke interaction was used for an attribute or command that " - @"requires a Timed Write or Timed Invoke.", + case Status::NeedsTimedInteraction: + description = NSLocalizedString(@"An Untimed Write or Untimed Invoke interaction was used " + "for an attribute or command that requires a Timed Write or Timed Invoke.", nil); break; - } - case Status::UnsupportedEvent: { + case Status::UnsupportedEvent: description = NSLocalizedString(@"The event indicated is unsupported on the cluster.", nil); break; } - } NSMutableDictionary * userInfo = [[NSMutableDictionary alloc] init]; userInfo[NSLocalizedDescriptionKey] = description; @@ -301,17 +303,21 @@ + (CHIP_ERROR)errorToCHIPErrorCode:(NSError * _Nullable)error case MTRErrorCodeDNSSDUnauthorized: code = CHIP_ERROR_DNS_SD_UNAUTHORIZED.AsInteger(); break; + case MTRErrorCodeCancelled: + code = CHIP_ERROR_CANCELLED.AsInteger(); + break; case MTRErrorCodeGeneralError: { - if (error.userInfo != nil && error.userInfo[@"errorCode"] != nil) { - code = static_cast([error.userInfo[@"errorCode"] unsignedLongValue]); + id userInfoErrorCode = error.userInfo[@"errorCode"]; + if ([userInfoErrorCode isKindOfClass:NSNumber.class]) { + code = static_cast([userInfoErrorCode unsignedLongValue]); break; } // Weird error we did not create. Fall through. + } default: code = CHIP_ERROR_INTERNAL.AsInteger(); break; } - } return chip::ChipError(code); } diff --git a/src/darwin/Framework/CHIPTests/MTRPairingTests.m b/src/darwin/Framework/CHIPTests/MTRPairingTests.m index 6757dea7ceb541..54b8a4991325b7 100644 --- a/src/darwin/Framework/CHIPTests/MTRPairingTests.m +++ b/src/darwin/Framework/CHIPTests/MTRPairingTests.m @@ -32,7 +32,7 @@ static const uint16_t kPairingTimeoutInSeconds = 10; static const uint16_t kTimeoutInSeconds = 3; -static uint64_t sDeviceId = 0x12344321; +static uint64_t sDeviceId = 100000000; static NSString * kOnboardingPayload = @"MT:Y.K90SO527JA0648G00"; static const uint16_t kLocalPort = 5541; static const uint16_t kTestVendorId = 0xFFF1u; @@ -82,6 +82,7 @@ @interface MTRPairingTestControllerDelegate : NSObject attestationDelegate; @property (nonatomic, nullable) NSNumber * failSafeExtension; +@property (nullable) NSError * commissioningCompleteError; @end @implementation MTRPairingTestControllerDelegate @@ -100,22 +101,22 @@ - (id)initWithExpectation:(XCTestExpectation *)expectation - (void)controller:(MTRDeviceController *)controller commissioningSessionEstablishmentDone:(NSError * _Nullable)error { - XCTAssertEqual(error.code, 0); + XCTAssertNil(error); __auto_type * params = [[MTRCommissioningParameters alloc] init]; params.deviceAttestationDelegate = self.attestationDelegate; params.failSafeTimeout = self.failSafeExtension; NSError * commissionError = nil; - [controller commissionNodeWithID:@(sDeviceId) commissioningParams:params error:&commissionError]; - XCTAssertNil(commissionError); + XCTAssertTrue([controller commissionNodeWithID:@(sDeviceId) commissioningParams:params error:&commissionError], + @"Failed to start commissioning for node ID %" PRIu64 ": %@", sDeviceId, commissionError); // Keep waiting for onCommissioningComplete } - (void)controller:(MTRDeviceController *)controller commissioningComplete:(NSError * _Nullable)error { - XCTAssertEqual(error.code, 0); + self.commissioningCompleteError = error; [_expectation fulfill]; _expectation = nil; } @@ -123,6 +124,7 @@ - (void)controller:(MTRDeviceController *)controller commissioningComplete:(NSEr @end @interface MTRPairingTests : XCTestCase +@property (nullable) MTRPairingTestControllerDelegate * controllerDelegate; @end @implementation MTRPairingTests @@ -148,11 +150,9 @@ + (void)setUp + (void)tearDown { - MTRDeviceController * controller = sController; - XCTAssertNotNil(controller); - - [controller shutdown]; - XCTAssertFalse([controller isRunning]); + [sController shutdown]; + XCTAssertFalse([sController isRunning]); + sController = nil; [[MTRDeviceControllerFactory sharedInstance] stopControllerFactory]; } @@ -163,6 +163,12 @@ - (void)setUp [self setContinueAfterFailure:NO]; } +- (void)tearDown +{ + [sController setDeviceControllerDelegate:(id _Nonnull) nil queue:dispatch_get_main_queue()]; // TODO: do we need a clearDeviceControllerDelegate API? + self.controllerDelegate = nil; +} + // attestationDelegate and failSafeExtension can both be nil - (void)doPairingTestWithAttestationDelegate:(id)attestationDelegate failSafeExtension:(NSNumber *)failSafeExtension { @@ -176,6 +182,7 @@ - (void)doPairingTestWithAttestationDelegate:(id)a dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.pairing", DISPATCH_QUEUE_SERIAL_WITH_AUTORELEASE_POOL); [sController setDeviceControllerDelegate:controllerDelegate queue:callbackQueue]; + self.controllerDelegate = controllerDelegate; NSError * error; __auto_type * payload = [MTRSetupPayload setupPayloadWithOnboardingPayload:kOnboardingPayload error:&error]; @@ -186,6 +193,7 @@ - (void)doPairingTestWithAttestationDelegate:(id)a XCTAssertNil(error); [self waitForExpectations:@[ expectation ] timeout:kPairingTimeoutInSeconds]; + XCTAssertNil(controllerDelegate.commissioningCompleteError); ResetCommissionee([MTRBaseDevice deviceWithNodeID:@(sDeviceId) controller:sController], dispatch_get_main_queue(), self, kTimeoutInSeconds); @@ -232,4 +240,62 @@ - (void)test004_PairWithAttestationDelegateFailsafeExtensionLong [self waitForExpectations:@[ expectation ] timeout:kTimeoutInSeconds]; } +- (void)doPairingAndWaitForProgress:(NSString *)trigger +{ + XCTestExpectation * expectation = [self expectationWithDescription:@"Trigger message seen"]; + MTRSetLogCallback(MTRLogTypeDetail, ^(MTRLogType type, NSString * moduleName, NSString * message) { + if ([message containsString:trigger]) { + [expectation fulfill]; + } + }); + + __auto_type * controllerDelegate = [[MTRPairingTestControllerDelegate alloc] initWithExpectation:nil + attestationDelegate:nil + failSafeExtension:nil]; + [sController setDeviceControllerDelegate:controllerDelegate queue:dispatch_get_main_queue()]; + self.controllerDelegate = controllerDelegate; + + __auto_type * payload = [MTRSetupPayload setupPayloadWithOnboardingPayload:kOnboardingPayload error:NULL]; + XCTAssertNotNil(payload); + NSError * error; + XCTAssertTrue([sController setupCommissioningSessionWithPayload:payload newNodeID:@(++sDeviceId) error:&error]); + XCTAssertNil(error); + + [self waitForExpectations:@[ expectation ] timeout:kPairingTimeoutInSeconds]; + MTRSetLogCallback(0, nil); +} + +- (void)doPairingTestAfterCancellationAtProgress:(NSString *)trigger +{ + // Run pairing up and wait for the trigger + [self doPairingAndWaitForProgress:trigger]; + + // Call StopPairing and wait for the commissioningComplete callback + XCTestExpectation * expectation = [self expectationWithDescription:@"commissioningComplete delegate method called"]; + self.controllerDelegate.expectation = expectation; + + NSError * error; + XCTAssertTrue([sController stopDevicePairing:sDeviceId error:&error], @"stopDevicePairing failed: %@", error); + [self waitForExpectations:@[ expectation ] timeout:kTimeoutInSeconds]; + + // Validate that the completion correctly indicated cancellation + error = self.controllerDelegate.commissioningCompleteError; + XCTAssertEqualObjects(error.domain, MTRErrorDomain); + XCTAssertEqual(error.code, MTRErrorCodeCancelled); + + // Now pair again. If the previous attempt was cancelled correctly this should work fine. + [self doPairingTestWithAttestationDelegate:nil failSafeExtension:nil]; +} + +- (void)test005_pairingAfterCancellation_ReadCommissioningInfo +{ + // @"Sending read request for commissioning information" + [self doPairingTestAfterCancellationAtProgress:@"Performing next commissioning step 'ReadCommissioningInfo'"]; +} + +- (void)test006_pairingAfterCancellation_ConfigRegulatoryCommand +{ + [self doPairingTestAfterCancellationAtProgress:@"Performing next commissioning step 'ConfigRegulatory'"]; +} + @end diff --git a/src/lib/support/CodeUtils.h b/src/lib/support/CodeUtils.h index 2b47538b8faebf..500804bc94912d 100644 --- a/src/lib/support/CodeUtils.h +++ b/src/lib/support/CodeUtils.h @@ -529,7 +529,7 @@ inline void chipDie(void) */ #if CHIP_CONFIG_VERBOSE_VERIFY_OR_DIE #define VerifyOrDie(aCondition) \ - nlABORT_ACTION(aCondition, ChipLogDetail(Support, "VerifyOrDie failure at %s:%d: %s", __FILE__, __LINE__, #aCondition)) + nlABORT_ACTION(aCondition, ChipLogError(Support, "VerifyOrDie failure at %s:%d: %s", __FILE__, __LINE__, #aCondition)) #else // CHIP_CONFIG_VERBOSE_VERIFY_OR_DIE #define VerifyOrDie(aCondition) VerifyOrDieWithoutLogging(aCondition) #endif // CHIP_CONFIG_VERBOSE_VERIFY_OR_DIE @@ -569,7 +569,7 @@ inline void chipDie(void) * */ #define VerifyOrDieWithMsg(aCondition, aModule, aMessage, ...) \ - nlABORT_ACTION(aCondition, ChipLogDetail(aModule, aMessage, ##__VA_ARGS__)) + nlABORT_ACTION(aCondition, ChipLogError(aModule, aMessage, ##__VA_ARGS__)) /** * @def LogErrorOnFailure(expr) diff --git a/src/lib/support/logging/TextOnlyLogging.cpp b/src/lib/support/logging/TextOnlyLogging.cpp index 1e573942f85e17..eb7065f2d938d4 100644 --- a/src/lib/support/logging/TextOnlyLogging.cpp +++ b/src/lib/support/logging/TextOnlyLogging.cpp @@ -209,21 +209,21 @@ void LogV(uint8_t module, uint8_t category, const char * msg, va_list args) } #if CHIP_LOG_FILTERING -uint8_t gLogFilter = kLogCategory_Max; +std::atomic gLogFilter(kLogCategory_Max); uint8_t GetLogFilter() { - return gLogFilter; + return gLogFilter.load(); } void SetLogFilter(uint8_t category) { - gLogFilter = category; + gLogFilter.store(category); } bool IsCategoryEnabled(uint8_t category) { - return (category <= gLogFilter); + return (category <= GetLogFilter()); } #endif // CHIP_LOG_FILTERING From ed8f37dbf58e188144cdba0ba7dd7ddd1b133c2c Mon Sep 17 00:00:00 2001 From: Jeff Tung <100387939+jtung-apple@users.noreply.github.com> Date: Tue, 27 Feb 2024 18:41:18 -0800 Subject: [PATCH 106/385] [Darwin] MTRDevice delegate should be notified when cache is primed with basic info (#32251) * [Darwin] MTRDevice delegate should be notified when cache is primed with basic info * Changed logic to only report once, and also improve documentation in comments * Update src/darwin/Framework/CHIP/MTRDevice.mm Co-authored-by: Boris Zbarsky --------- Co-authored-by: Boris Zbarsky --- src/darwin/Framework/CHIP/MTRDevice.h | 9 ++ src/darwin/Framework/CHIP/MTRDevice.mm | 84 ++++++++++++++++++- .../Framework/CHIPTests/MTRDeviceTests.m | 15 +++- .../TestHelpers/MTRDeviceTestDelegate.h | 1 + .../TestHelpers/MTRDeviceTestDelegate.m | 7 ++ 5 files changed, 111 insertions(+), 5 deletions(-) diff --git a/src/darwin/Framework/CHIP/MTRDevice.h b/src/darwin/Framework/CHIP/MTRDevice.h index 23a1ecf51ad56c..ee7b1608d8246c 100644 --- a/src/darwin/Framework/CHIP/MTRDevice.h +++ b/src/darwin/Framework/CHIP/MTRDevice.h @@ -381,6 +381,15 @@ MTR_EXTERN NSString * const MTRDataVersionKey MTR_NEWLY_AVAILABLE; */ - (void)deviceBecameActive:(MTRDevice *)device MTR_AVAILABLE(ios(16.4), macos(13.3), watchos(9.4), tvos(16.4)); +/** + * Notifies delegate when the device attribute cache has been primed with initial configuration data of the device + * + * This is called when the MTRDevice object goes from not knowing the device to having cached the first attribute reports that include basic mandatory information, e.g. Descriptor clusters. + * + * The intention is that after this is called, the client should be able to call read for mandatory attributes and likely expect non-nil values. + */ +- (void)deviceCachePrimed:(MTRDevice *)device MTR_NEWLY_AVAILABLE; + @end @interface MTRDevice (Deprecated) diff --git a/src/darwin/Framework/CHIP/MTRDevice.mm b/src/darwin/Framework/CHIP/MTRDevice.mm index dbf1785c9bb6ba..0f304f42b7a741 100644 --- a/src/darwin/Framework/CHIP/MTRDevice.mm +++ b/src/darwin/Framework/CHIP/MTRDevice.mm @@ -225,6 +225,7 @@ @implementation MTRDevice { #ifdef DEBUG NSUInteger _unitTestAttributesReportedSinceLastCheck; #endif + BOOL _delegateDeviceCachePrimedCalled; } - (instancetype)initWithNodeID:(NSNumber *)nodeID controller:(MTRDeviceController *)controller @@ -502,6 +503,11 @@ - (void)setDelegate:(id)delegate queue:(dispatch_queue_t)queu _weakDelegate = [MTRWeakReference weakReferenceWithObject:delegate]; _delegateQueue = queue; + // If Check if cache is already primed and client hasn't been informed yet, call the -deviceCachePrimed: callback + if (!_delegateDeviceCachePrimedCalled && [self _isCachePrimedWithInitialConfigurationData]) { + [self _callDelegateDeviceCachePrimed]; + } + if (setUpSubscription) { [self _setupSubscription]; } @@ -574,6 +580,29 @@ - (BOOL)_subscriptionAbleToReport return (delegate != nil) && (state == MTRDeviceStateReachable); } +- (BOOL)_callDelegateWithBlock:(void (^)(id))block +{ + os_unfair_lock_assert_owner(&self->_lock); + id delegate = _weakDelegate.strongObject; + if (delegate) { + dispatch_async(_delegateQueue, ^{ + block(delegate); + }); + return YES; + } + return NO; +} + +- (void)_callDelegateDeviceCachePrimed +{ + os_unfair_lock_assert_owner(&self->_lock); + _delegateDeviceCachePrimedCalled = [self _callDelegateWithBlock:^(id delegate) { + if ([delegate respondsToSelector:@selector(deviceCachePrimed:)]) { + [delegate deviceCachePrimed:self]; + } + }]; +} + // assume lock is held - (void)_changeState:(MTRDeviceState)state { @@ -611,6 +640,11 @@ - (void)_handleSubscriptionEstablished // reset subscription attempt wait time when subscription succeeds _lastSubscriptionAttemptWait = 0; + // As subscription is established, check if the delegate needs to be informed + if (!_delegateDeviceCachePrimedCalled) { + [self _callDelegateDeviceCachePrimed]; + } + [self _changeState:MTRDeviceStateReachable]; os_unfair_lock_unlock(&self->_lock); @@ -741,6 +775,7 @@ - (void)_handleReportEnd _receivingReport = NO; _receivingPrimingReport = NO; _estimatedStartTimeFromGeneralDiagnosticsUpTime = nil; + // For unit testing only #ifdef DEBUG id delegate = _weakDelegate.strongObject; @@ -1948,17 +1983,24 @@ - (NSArray *)_getAttributesToReportWithReportedValues:(NSArray *)attributeValues reportChanges:(BOOL)reportChanges { + os_unfair_lock_lock(&self->_lock); + if (reportChanges) { - [self _handleAttributeReport:attributeValues]; + [self _reportAttributes:[self _getAttributesToReportWithReportedValues:attributeValues]]; } else { - os_unfair_lock_lock(&self->_lock); for (NSDictionary * responseValue in attributeValues) { MTRAttributePath * path = responseValue[MTRAttributePathKey]; NSDictionary * dataValue = responseValue[MTRDataKey]; _readCache[path] = dataValue; } - os_unfair_lock_unlock(&self->_lock); } + + // If cache is set from storage and is primed with initial configuration data, then assume the client had beeen informed in the past, and mark that the callback has been called + if ([self _isCachePrimedWithInitialConfigurationData]) { + _delegateDeviceCachePrimedCalled = YES; + } + + os_unfair_lock_unlock(&self->_lock); } // If value is non-nil, associate with expectedValueID @@ -2135,6 +2177,42 @@ - (void)_removeExpectedValueForAttributePath:(MTRAttributePath *)attributePath e } } +// This method checks if there is a need to inform delegate that the attribute cache has been "primed" +- (BOOL)_isCachePrimedWithInitialConfigurationData +{ + os_unfair_lock_assert_owner(&self->_lock); + + // Check if root node descriptor exists + NSDictionary * rootDescriptorPartsListDataValue = _readCache[[MTRAttributePath attributePathWithEndpointID:@(kRootEndpointId) clusterID:@(MTRClusterIDTypeDescriptorID) attributeID:@(MTRAttributeIDTypeClusterDescriptorAttributePartsListID)]]; + if (!rootDescriptorPartsListDataValue || ![MTRArrayValueType isEqualToString:rootDescriptorPartsListDataValue[MTRTypeKey]]) { + return NO; + } + NSArray * partsList = rootDescriptorPartsListDataValue[MTRValueKey]; + if (![partsList isKindOfClass:[NSArray class]] || !partsList.count) { + MTR_LOG_ERROR("%@ unexpected type %@ for parts list %@", self, [partsList class], partsList); + return NO; + } + + // Check if we have cached descriptor clusters for each listed endpoint + for (NSDictionary * endpointDataValue in partsList) { + if (![MTRUnsignedIntegerValueType isEqual:endpointDataValue[MTRTypeKey]]) { + MTR_LOG_ERROR("%@ unexpected type for parts list item %@", self, endpointDataValue); + continue; + } + NSNumber * endpoint = endpointDataValue[MTRValueKey]; + if (![endpoint isKindOfClass:[NSNumber class]]) { + MTR_LOG_ERROR("%@ unexpected type for parts list item %@", self, endpointDataValue); + continue; + } + NSDictionary * descriptorDeviceTypeListDataValue = _readCache[[MTRAttributePath attributePathWithEndpointID:endpoint clusterID:@(MTRClusterIDTypeDescriptorID) attributeID:@(MTRAttributeIDTypeClusterDescriptorAttributeDeviceTypeListID)]]; + if (![MTRArrayValueType isEqualToString:descriptorDeviceTypeListDataValue[MTRTypeKey]] || !descriptorDeviceTypeListDataValue[MTRValueKey]) { + return NO; + } + } + + return YES; +} + - (MTRBaseDevice *)newBaseDevice { return [MTRBaseDevice deviceWithNodeID:self.nodeID controller:self.deviceController]; diff --git a/src/darwin/Framework/CHIPTests/MTRDeviceTests.m b/src/darwin/Framework/CHIPTests/MTRDeviceTests.m index e4628bd475b5ae..e5539f4f75d993 100644 --- a/src/darwin/Framework/CHIPTests/MTRDeviceTests.m +++ b/src/darwin/Framework/CHIPTests/MTRDeviceTests.m @@ -2843,7 +2843,7 @@ - (void)test031_MTRDeviceAttributeCacheLocalTestStorage { dispatch_queue_t queue = dispatch_get_main_queue(); - // First start with clean slate and + // First start with clean slate by removing the MTRDevice and clearing the persisted cache __auto_type * device = [MTRDevice deviceWithNodeID:@(kDeviceId) controller:sController]; [sController removeDevice:device]; [sController.controllerDataStore clearAllStoredAttributes]; @@ -2853,6 +2853,7 @@ - (void)test031_MTRDeviceAttributeCacheLocalTestStorage // Now recreate device and get subscription primed device = [MTRDevice deviceWithNodeID:@(kDeviceId) controller:sController]; XCTestExpectation * gotReportsExpectation = [self expectationWithDescription:@"Attribute and Event reports have been received"]; + XCTestExpectation * gotDeviceCachePrimed = [self expectationWithDescription:@"Device cache primed for the first time"]; __auto_type * delegate = [[MTRDeviceTestDelegate alloc] init]; __weak __auto_type weakDelegate = delegate; delegate.onReportEnd = ^{ @@ -2860,9 +2861,12 @@ - (void)test031_MTRDeviceAttributeCacheLocalTestStorage __strong __auto_type strongDelegate = weakDelegate; strongDelegate.onReportEnd = nil; }; + delegate.onDeviceCachePrimed = ^{ + [gotDeviceCachePrimed fulfill]; + }; [device setDelegate:delegate queue:queue]; - [self waitForExpectations:@[ gotReportsExpectation ] timeout:60]; + [self waitForExpectations:@[ gotReportsExpectation, gotDeviceCachePrimed ] timeout:60]; NSUInteger attributesReportedWithFirstSubscription = [device unitTestAttributesReportedSinceLastCheck]; @@ -2879,10 +2883,17 @@ - (void)test031_MTRDeviceAttributeCacheLocalTestStorage __strong __auto_type strongDelegate = weakDelegate; strongDelegate.onReportEnd = nil; }; + __block BOOL onDeviceCachePrimedCalled = NO; + delegate.onDeviceCachePrimed = ^{ + onDeviceCachePrimedCalled = YES; + }; [device setDelegate:delegate queue:queue]; [self waitForExpectations:@[ resubGotReportsExpectation ] timeout:60]; + // Make sure that the new callback is only ever called once, the first time subscription was primed + XCTAssertFalse(onDeviceCachePrimedCalled); + NSUInteger attributesReportedWithSecondSubscription = [device unitTestAttributesReportedSinceLastCheck]; XCTAssertTrue(attributesReportedWithSecondSubscription < attributesReportedWithFirstSubscription); diff --git a/src/darwin/Framework/CHIPTests/TestHelpers/MTRDeviceTestDelegate.h b/src/darwin/Framework/CHIPTests/TestHelpers/MTRDeviceTestDelegate.h index 0f7fce14226525..e8fd8f969b2aeb 100644 --- a/src/darwin/Framework/CHIPTests/TestHelpers/MTRDeviceTestDelegate.h +++ b/src/darwin/Framework/CHIPTests/TestHelpers/MTRDeviceTestDelegate.h @@ -27,6 +27,7 @@ typedef void (^MTRDeviceTestDelegateDataHandler)(NSArray Date: Tue, 27 Feb 2024 20:10:07 -0800 Subject: [PATCH 107/385] [Android] Add initial batch command support (#32326) --- .github/workflows/java-tests.yaml | 11 + examples/java-matter-controller/BUILD.gn | 1 + .../java/src/com/matter/controller/Main.kt | 1 + ...rOnNetworkLongImExtendableInvokeCommand.kt | 183 ++++++++++++++ kotlin-detect-config.yaml | 1 + scripts/tests/java/im_test.py | 13 + src/controller/java/AndroidCallbacks-JNI.cpp | 11 + src/controller/java/AndroidCallbacks.cpp | 180 +++++++++++++- src/controller/java/AndroidCallbacks.h | 17 ++ .../java/AndroidInteractionClient.cpp | 187 ++++++++++++++- .../java/AndroidInteractionClient.h | 2 + src/controller/java/BUILD.gn | 4 + .../java/CHIPDeviceController-JNI.cpp | 12 + src/controller/java/MatterCallbacks-JNI.cpp | 11 + .../java/MatterInteractionClient-JNI.cpp | 12 + .../devicecontroller/BatchInvokeCallback.java | 54 +++++ .../BatchInvokeCallbackJni.java | 94 ++++++++ .../ChipDeviceController.java | 34 +++ .../ExtendableInvokeCallback.java | 54 +++++ .../ExtendableInvokeCallbackJni.java | 94 ++++++++ .../model/InvokeResponseData.java | 224 ++++++++++++++++++ .../model/NoInvokeResponseData.java | 38 +++ .../chip/devicecontroller/model/Status.java | 4 + src/lib/core/core.gni | 3 +- 24 files changed, 1242 insertions(+), 3 deletions(-) create mode 100644 examples/java-matter-controller/java/src/com/matter/controller/commands/pairing/PairOnNetworkLongImExtendableInvokeCommand.kt create mode 100644 src/controller/java/src/chip/devicecontroller/BatchInvokeCallback.java create mode 100644 src/controller/java/src/chip/devicecontroller/BatchInvokeCallbackJni.java create mode 100644 src/controller/java/src/chip/devicecontroller/ExtendableInvokeCallback.java create mode 100644 src/controller/java/src/chip/devicecontroller/ExtendableInvokeCallbackJni.java create mode 100644 src/controller/java/src/chip/devicecontroller/model/InvokeResponseData.java create mode 100644 src/controller/java/src/chip/devicecontroller/model/NoInvokeResponseData.java diff --git a/.github/workflows/java-tests.yaml b/.github/workflows/java-tests.yaml index f19d451fbc2df6..3aa6935d1735c4 100644 --- a/.github/workflows/java-tests.yaml +++ b/.github/workflows/java-tests.yaml @@ -132,6 +132,17 @@ jobs: --tool-cluster "im" \ --tool-args "onnetwork-long-im-invoke --nodeid 1 --setup-pin-code 20202021 --discriminator 3840 -t 1000" \ --factoryreset \ + ' + - name: Run IM Batch Invoke Test + run: | + scripts/run_in_python_env.sh out/venv \ + './scripts/tests/run_java_test.py \ + --app out/linux-x64-all-clusters-ipv6only-no-ble-no-wifi-tsan-clang-test/chip-all-clusters-app \ + --app-args "--discriminator 3840 --interface-id -1" \ + --tool-path out/linux-x64-java-matter-controller \ + --tool-cluster "im" \ + --tool-args "onnetwork-long-im-batch-invoke --nodeid 1 --setup-pin-code 20202021 --discriminator 3840 -t 1000" \ + --factoryreset \ ' - name: Run IM Read Test run: | diff --git a/examples/java-matter-controller/BUILD.gn b/examples/java-matter-controller/BUILD.gn index 34de1ed5585c12..76acd190eade16 100644 --- a/examples/java-matter-controller/BUILD.gn +++ b/examples/java-matter-controller/BUILD.gn @@ -57,6 +57,7 @@ kotlin_binary("java-matter-controller") { "java/src/com/matter/controller/commands/pairing/PairOnNetworkFabricCommand.kt", "java/src/com/matter/controller/commands/pairing/PairOnNetworkInstanceNameCommand.kt", "java/src/com/matter/controller/commands/pairing/PairOnNetworkLongCommand.kt", + "java/src/com/matter/controller/commands/pairing/PairOnNetworkLongImExtendableInvokeCommand.kt", "java/src/com/matter/controller/commands/pairing/PairOnNetworkLongImInvokeCommand.kt", "java/src/com/matter/controller/commands/pairing/PairOnNetworkLongImReadCommand.kt", "java/src/com/matter/controller/commands/pairing/PairOnNetworkLongImSubscribeCommand.kt", diff --git a/examples/java-matter-controller/java/src/com/matter/controller/Main.kt b/examples/java-matter-controller/java/src/com/matter/controller/Main.kt index d0e2ef892b0e95..a1a66a8420b196 100644 --- a/examples/java-matter-controller/java/src/com/matter/controller/Main.kt +++ b/examples/java-matter-controller/java/src/com/matter/controller/Main.kt @@ -67,6 +67,7 @@ private fun getImCommands( PairOnNetworkLongImSubscribeCommand(controller, credentialsIssuer), PairOnNetworkLongImWriteCommand(controller, credentialsIssuer), PairOnNetworkLongImInvokeCommand(controller, credentialsIssuer), + PairOnNetworkLongImExtendableInvokeCommand(controller, credentialsIssuer), ) } diff --git a/examples/java-matter-controller/java/src/com/matter/controller/commands/pairing/PairOnNetworkLongImExtendableInvokeCommand.kt b/examples/java-matter-controller/java/src/com/matter/controller/commands/pairing/PairOnNetworkLongImExtendableInvokeCommand.kt new file mode 100644 index 00000000000000..d80e71acb53d73 --- /dev/null +++ b/examples/java-matter-controller/java/src/com/matter/controller/commands/pairing/PairOnNetworkLongImExtendableInvokeCommand.kt @@ -0,0 +1,183 @@ +/* + * Copyright (c) 2024 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. + * + */ +package com.matter.controller.commands.pairing + +import chip.devicecontroller.ChipDeviceController +import chip.devicecontroller.ExtendableInvokeCallback +import chip.devicecontroller.GetConnectedDeviceCallbackJni.GetConnectedDeviceCallback +import chip.devicecontroller.model.InvokeElement +import chip.devicecontroller.model.InvokeResponseData +import chip.devicecontroller.model.NoInvokeResponseData +import chip.devicecontroller.model.Status +import com.matter.controller.commands.common.CredentialsIssuer +import java.util.logging.Level +import java.util.logging.Logger +import kotlin.UShort +import matter.tlv.AnonymousTag +import matter.tlv.ContextSpecificTag +import matter.tlv.TlvWriter + +class PairOnNetworkLongImExtendableInvokeCommand( + controller: ChipDeviceController, + credsIssue: CredentialsIssuer? +) : + PairingCommand( + controller, + "onnetwork-long-im-batch-invoke", + credsIssue, + PairingModeType.ON_NETWORK, + PairingNetworkType.NONE, + DiscoveryFilterType.LONG_DISCRIMINATOR + ) { + private var devicePointer: Long = 0 + + private fun setDevicePointer(devicePointer: Long) { + this.devicePointer = devicePointer + } + + private inner class InternalInvokeCallback : ExtendableInvokeCallback { + private var responseCount = 0 + + override fun onError(e: Exception) { + logger.log(Level.INFO, "Batch Invoke receive onError" + e.message) + setFailure("invoke failure") + } + + override fun onResponse(invokeResponseData: InvokeResponseData) { + logger.log(Level.INFO, "Batch Invoke receive OnResponse on $invokeResponseData") + val clusterId = invokeResponseData.getClusterId().getId() + val commandId = invokeResponseData.getCommandId().getId() + val tlvData = invokeResponseData.getTlvByteArray() + val jsonData = invokeResponseData.getJsonString() + val status = invokeResponseData.getStatus() + + if (clusterId == CLUSTER_ID_IDENTIFY && commandId == IDENTIFY_COMMAND) { + if (tlvData != null || jsonData != null) { + setFailure("invoke failure with problematic payload") + } + if ( + status != null && status.status != Status.Code.Success && status.clusterStatus.isPresent() + ) { + setFailure("invoke failure with incorrect status") + } + } + + if (clusterId == CLUSTER_ID_TEST && commandId == TEST_ADD_ARGUMENT_RSP_COMMAND) { + if (tlvData == null || jsonData == null) { + setFailure("invoke failure with problematic payload") + } + + if (!jsonData.equals("""{"0:UINT":2}""")) { + setFailure("invoke failure with problematic json") + } + + if (status != null) { + setFailure("invoke failure with incorrect status") + } + } + responseCount++ + } + + override fun onNoResponse(noInvokeResponseData: NoInvokeResponseData) { + logger.log(Level.INFO, "Batch Invoke receive onNoResponse on $noInvokeResponseData") + } + + override fun onDone() { + if (responseCount == TEST_COMMONDS_NUM) { + setSuccess() + } else { + setFailure("invoke failure") + } + } + } + + private inner class InternalGetConnectedDeviceCallback : GetConnectedDeviceCallback { + override fun onDeviceConnected(devicePointer: Long) { + setDevicePointer(devicePointer) + logger.log(Level.INFO, "onDeviceConnected") + } + + override fun onConnectionFailure(nodeId: Long, error: Exception) { + logger.log(Level.INFO, "onConnectionFailure") + } + } + + override fun runCommand() { + val number: UShort = 1u + val tlvWriter1 = TlvWriter() + tlvWriter1.startStructure(AnonymousTag) + tlvWriter1.put(ContextSpecificTag(0), number) + tlvWriter1.endStructure() + + val element1: InvokeElement = + InvokeElement.newInstance( + /* endpointId= */ 0, + CLUSTER_ID_IDENTIFY, + IDENTIFY_COMMAND, + tlvWriter1.getEncoded(), + null + ) + + val tlvWriter2 = TlvWriter() + tlvWriter2.startStructure(AnonymousTag) + tlvWriter2.put(ContextSpecificTag(0), number) + tlvWriter2.put(ContextSpecificTag(1), number) + tlvWriter2.endStructure() + + val element2: InvokeElement = + InvokeElement.newInstance( + /* endpointId= */ 1, + CLUSTER_ID_TEST, + TEST_ADD_ARGUMENT_COMMAND, + tlvWriter2.getEncoded(), + null + ) + + val invokeList = listOf(element1, element2) + currentCommissioner() + .pairDeviceWithAddress( + getNodeId(), + getRemoteAddr().address.hostAddress, + MATTER_PORT, + getDiscriminator(), + getSetupPINCode(), + null + ) + currentCommissioner().setCompletionListener(this) + waitCompleteMs(getTimeoutMillis()) + currentCommissioner() + .getConnectedDevicePointer(getNodeId(), InternalGetConnectedDeviceCallback()) + clear() + currentCommissioner() + .extendableInvoke(InternalInvokeCallback(), devicePointer, invokeList, 0, 0) + waitCompleteMs(getTimeoutMillis()) + } + + companion object { + private val logger = + Logger.getLogger(PairOnNetworkLongImExtendableInvokeCommand::class.java.name) + + private const val MATTER_PORT = 5540 + private const val CLUSTER_ID_IDENTIFY = 0x0003L + private const val IDENTIFY_COMMAND = 0L + private const val CLUSTER_ID_TEST = 0xFFF1FC05L + private const val TEST_ADD_ARGUMENT_COMMAND = 0X04L + private const val TEST_ADD_ARGUMENT_RSP_COMMAND = 0X01L + private const val TEST_COMMONDS_NUM = 2 + } +} diff --git a/kotlin-detect-config.yaml b/kotlin-detect-config.yaml index 2ad54a05d6c483..c8398293d93e8b 100644 --- a/kotlin-detect-config.yaml +++ b/kotlin-detect-config.yaml @@ -104,6 +104,7 @@ style: - "**/examples/java-matter-controller/java/src/com/matter/controller/commands/pairing/PairOnNetworkInstanceNameCommand.kt" - "**/examples/java-matter-controller/java/src/com/matter/controller/commands/pairing/PairOnNetworkLongCommand.kt" - "**/examples/java-matter-controller/java/src/com/matter/controller/commands/pairing/PairOnNetworkLongImInvokeCommand.kt" + - "**/examples/java-matter-controller/java/src/com/matter/controller/commands/pairing/PairOnNetworkLongImExtendableInvokeCommand.kt" - "**/examples/java-matter-controller/java/src/com/matter/controller/commands/pairing/PairOnNetworkLongImWriteCommand.kt" - "**/examples/java-matter-controller/java/src/com/matter/controller/commands/pairing/PairOnNetworkShortCommand.kt" - "**/examples/java-matter-controller/java/src/com/matter/controller/commands/pairing/PairOnNetworkVendorCommand.kt" diff --git a/scripts/tests/java/im_test.py b/scripts/tests/java/im_test.py index d8acc6362e000d..6ac393629fbee8 100755 --- a/scripts/tests/java/im_test.py +++ b/scripts/tests/java/im_test.py @@ -71,6 +71,14 @@ def TestCmdOnnetworkLongImInvoke(self, nodeid, setuppin, discriminator, timeout) DumpProgramOutputToQueue(self.thread_list, Fore.GREEN + "JAVA " + Style.RESET_ALL, java_process, self.queue) return java_process.wait() + def TestCmdOnnetworkLongImExtendableInvoke(self, nodeid, setuppin, discriminator, timeout): + java_command = self.command + ['im', 'onnetwork-long-im-batch-invoke', nodeid, setuppin, discriminator, timeout] + logging.info(f"Execute: {java_command}") + java_process = subprocess.Popen( + java_command, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + DumpProgramOutputToQueue(self.thread_list, Fore.GREEN + "JAVA " + Style.RESET_ALL, java_process, self.queue) + return java_process.wait() + def TestCmdOnnetworkLongImWrite(self, nodeid, setuppin, discriminator, timeout): java_command = self.command + ['im', 'onnetwork-long-im-write', nodeid, setuppin, discriminator, timeout] logging.info(f"Execute: {java_command}") @@ -101,6 +109,11 @@ def RunTest(self): code = self.TestCmdOnnetworkLongImInvoke(self.nodeid, self.setup_pin_code, self.discriminator, self.timeout) if code != 0: raise Exception(f"Testing pairing onnetwork-long-im-invoke failed with error {code}") + elif self.command_name == 'onnetwork-long-im-batch-invoke': + logging.info("Testing pairing onnetwork-long-im-batch-invoke") + code = self.TestCmdOnnetworkLongImExtendableInvoke(self.nodeid, self.setup_pin_code, self.discriminator, self.timeout) + if code != 0: + raise Exception(f"Testing pairing onnetwork-long-im-batch-invoke failed with error {code}") elif self.command_name == 'onnetwork-long-im-write': logging.info("Testing pairing onnetwork-long-im-write") code = self.TestCmdOnnetworkLongImWrite(self.nodeid, self.setup_pin_code, self.discriminator, self.timeout) diff --git a/src/controller/java/AndroidCallbacks-JNI.cpp b/src/controller/java/AndroidCallbacks-JNI.cpp index c87b669f9b521f..fff1226bdb37d2 100644 --- a/src/controller/java/AndroidCallbacks-JNI.cpp +++ b/src/controller/java/AndroidCallbacks-JNI.cpp @@ -69,3 +69,14 @@ JNI_METHOD(void, InvokeCallbackJni, deleteCallback)(JNIEnv * env, jobject self, { deleteInvokeCallback(env, self, callbackHandle); } + +JNI_METHOD(jlong, ExtendableInvokeCallbackJni, newCallback) +(JNIEnv * env, jobject self) +{ + return newExtendableInvokeCallback(env, self); +} + +JNI_METHOD(void, ExtendableInvokeCallbackJni, deleteCallback)(JNIEnv * env, jobject self, jlong callbackHandle) +{ + deleteExtendableInvokeCallback(env, self, callbackHandle); +} diff --git a/src/controller/java/AndroidCallbacks.cpp b/src/controller/java/AndroidCallbacks.cpp index fb7975262dff57..fc9fbe02f12292 100644 --- a/src/controller/java/AndroidCallbacks.cpp +++ b/src/controller/java/AndroidCallbacks.cpp @@ -791,6 +791,7 @@ InvokeCallback::~InvokeCallback() if (mCommandSender != nullptr) { Platform::Delete(mCommandSender); + mCommandSender = nullptr; } } @@ -802,7 +803,6 @@ void InvokeCallback::OnResponse(app::CommandSender * apCommandSender, const app: VerifyOrReturn(env != nullptr, ChipLogError(Controller, "Could not get JNIEnv for current thread")); jmethodID onResponseMethod; JniLocalReferenceScope scope(env); - VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Controller, "Unable to create Java InvokeElement: %s", ErrorStr(err))); VerifyOrReturn(mWrapperCallbackRef.HasValidObjectRef(), ChipLogError(Controller, "mWrapperCallbackRef is not valid in %s", __func__)); jobject wrapperCallbackRef = mWrapperCallbackRef.ObjectRef(); @@ -1023,6 +1023,170 @@ jobject DecodeGeneralTLVValue(JNIEnv * env, TLV::TLVReader & readerForGeneralVal } } +ExtendableInvokeCallback::ExtendableInvokeCallback(jobject wrapperCallback) +{ + VerifyOrReturn(mWrapperCallbackRef.Init(wrapperCallback) == CHIP_NO_ERROR, + ChipLogError(Controller, "Could not init mWrapperCallbackRef for ExtendableInvokeCallback")); +} + +ExtendableInvokeCallback::~ExtendableInvokeCallback() +{ + if (mCommandSender != nullptr) + { + Platform::Delete(mCommandSender); + mCommandSender = nullptr; + } +} + +void ExtendableInvokeCallback::OnResponse(app::CommandSender * apCommandSender, + const app::CommandSender::ResponseData & aResponseData) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread(); + VerifyOrReturn(env != nullptr, ChipLogError(Controller, "Could not get JNIEnv for current thread")); + jmethodID onResponseMethod; + JniLocalReferenceScope scope(env); + VerifyOrReturn(mWrapperCallbackRef.HasValidObjectRef(), + ChipLogError(Controller, "mWrapperCallbackRef is not valid in %s", __func__)); + jobject wrapperCallbackRef = mWrapperCallbackRef.ObjectRef(); + DeviceLayer::StackUnlock unlock; + + jobject jCommandRef = nullptr; + if (aResponseData.commandRef.HasValue()) + { + err = JniReferences::GetInstance().CreateBoxedObject( + "java/lang/Integer", "(I)V", static_cast(aResponseData.commandRef.Value()), jCommandRef); + VerifyOrReturn(err == CHIP_NO_ERROR, + ChipLogError(Controller, "Could not CreateBoxedObject with error %" CHIP_ERROR_FORMAT, err.Format())); + } + + if (aResponseData.data != nullptr) + { + TLV::TLVReader readerForJavaTLV; + TLV::TLVReader readerForJson; + readerForJavaTLV.Init(*(aResponseData.data)); + + // Create TLV byte array to pass to Java layer + size_t bufferLen = readerForJavaTLV.GetRemainingLength() + readerForJavaTLV.GetLengthRead(); + std::unique_ptr buffer = std::unique_ptr(new uint8_t[bufferLen]); + uint32_t size = 0; + + TLV::TLVWriter writer; + writer.Init(buffer.get(), bufferLen); + err = writer.CopyElement(TLV::AnonymousTag(), readerForJavaTLV); + VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Controller, "Failed CopyElement: %" CHIP_ERROR_FORMAT, err.Format())); + size = writer.GetLengthWritten(); + + chip::ByteArray jniByteArray(env, reinterpret_cast(buffer.get()), static_cast(size)); + + // Convert TLV to JSON + std::string json; + readerForJson.Init(buffer.get(), size); + err = readerForJson.Next(); + VerifyOrReturn(err == CHIP_NO_ERROR, + ChipLogError(Controller, "Failed readerForJson next: %" CHIP_ERROR_FORMAT, err.Format())); + err = TlvToJson(readerForJson, json); + VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Controller, "Failed TlvToJson: %" CHIP_ERROR_FORMAT, err.Format())); + UtfString jsonString(env, json.c_str()); + + err = JniReferences::GetInstance().FindMethod(env, wrapperCallbackRef, "onResponse", + "(IJJLjava/lang/Integer;[BLjava/lang/String;)V", &onResponseMethod); + VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Controller, "Unable to find onResponse method: %s", ErrorStr(err))); + + env->CallVoidMethod(wrapperCallbackRef, onResponseMethod, static_cast(aResponseData.path.mEndpointId), + static_cast(aResponseData.path.mClusterId), static_cast(aResponseData.path.mCommandId), + jCommandRef, jniByteArray.jniValue(), jsonString.jniValue()); + } + else + { + err = JniReferences::GetInstance().FindMethod(env, wrapperCallbackRef, "onResponse", + "(IJJLjava/lang/Integer;ILjava/lang/Integer;)V", &onResponseMethod); + VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Controller, "Unable to find onResponse method: %s", ErrorStr(err))); + + jobject jClusterState = nullptr; + if (aResponseData.statusIB.mClusterStatus.HasValue()) + { + err = JniReferences::GetInstance().CreateBoxedObject( + "java/lang/Integer", "(I)V", static_cast(aResponseData.statusIB.mClusterStatus.Value()), jClusterState); + VerifyOrReturn(err == CHIP_NO_ERROR, + ChipLogError(Controller, "Could not CreateBoxedObject with error %" CHIP_ERROR_FORMAT, err.Format())); + } + + env->CallVoidMethod(wrapperCallbackRef, onResponseMethod, static_cast(aResponseData.path.mEndpointId), + static_cast(aResponseData.path.mClusterId), static_cast(aResponseData.path.mCommandId), + jCommandRef, aResponseData.statusIB.mStatus, jClusterState); + } + + VerifyOrReturn(!env->ExceptionCheck(), env->ExceptionDescribe()); +} + +void ExtendableInvokeCallback::OnNoResponse(app::CommandSender * commandSender, + const app::CommandSender::NoResponseData & aNoResponseData) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread(); + VerifyOrReturn(env != nullptr, ChipLogError(Controller, "Could not get JNIEnv for current thread")); + jmethodID onNoResponseMethod; + JniLocalReferenceScope scope(env); + VerifyOrReturn(mWrapperCallbackRef.HasValidObjectRef(), + ChipLogError(Controller, "mWrapperCallbackRef is not valid in %s", __func__)); + jobject wrapperCallbackRef = mWrapperCallbackRef.ObjectRef(); + DeviceLayer::StackUnlock unlock; + + err = JniReferences::GetInstance().FindMethod(env, wrapperCallbackRef, "onNoResponse", "(I)V", &onNoResponseMethod); + VerifyOrReturn(err == CHIP_NO_ERROR, + ChipLogError(Controller, "Unable to find onNoResponse method: %" CHIP_ERROR_FORMAT, err.Format())); + env->CallVoidMethod(wrapperCallbackRef, onNoResponseMethod, static_cast(aNoResponseData.commandRef)); + VerifyOrReturn(!env->ExceptionCheck(), env->ExceptionDescribe()); +} + +void ExtendableInvokeCallback::OnError(const app::CommandSender * apCommandSender, const app::CommandSender::ErrorData & aErrorData) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread(); + VerifyOrReturn(env != nullptr, ChipLogError(Controller, "Could not get JNIEnv for current thread")); + JniLocalReferenceScope scope(env); + ChipLogError(Controller, "ExtendableInvokeCallback::OnError is called with %u", aErrorData.error.AsInteger()); + jthrowable exception; + err = AndroidControllerExceptions::GetInstance().CreateAndroidControllerException(env, ErrorStr(aErrorData.error), + aErrorData.error.AsInteger(), exception); + VerifyOrReturn( + err == CHIP_NO_ERROR, + ChipLogError(Controller, "Unable to create AndroidControllerException with error: %" CHIP_ERROR_FORMAT, err.Format())); + + jmethodID onErrorMethod; + VerifyOrReturn(mWrapperCallbackRef.HasValidObjectRef(), + ChipLogError(Controller, "mWrapperCallbackRef is not valid in %s", __func__)); + jobject wrapperCallback = mWrapperCallbackRef.ObjectRef(); + err = JniReferences::GetInstance().FindMethod(env, wrapperCallback, "onError", "(Ljava/lang/Exception;)V", &onErrorMethod); + VerifyOrReturn(err == CHIP_NO_ERROR, + ChipLogError(Controller, "Unable to find onError method: %" CHIP_ERROR_FORMAT, err.Format())); + + DeviceLayer::StackUnlock unlock; + env->CallVoidMethod(wrapperCallback, onErrorMethod, exception); + VerifyOrReturn(!env->ExceptionCheck(), env->ExceptionDescribe()); +} + +void ExtendableInvokeCallback::OnDone(app::CommandSender * apCommandSender) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread(); + VerifyOrReturn(env != nullptr, ChipLogError(Controller, "Could not get JNIEnv for current thread")); + JniLocalReferenceScope scope(env); + jmethodID onDoneMethod; + VerifyOrReturn(mWrapperCallbackRef.HasValidObjectRef(), + ChipLogError(Controller, "mWrapperCallbackRef is not valid in %s", __func__)); + jobject wrapperCallback = mWrapperCallbackRef.ObjectRef(); + JniGlobalReference globalRef(std::move(mWrapperCallbackRef)); + + err = JniReferences::GetInstance().FindMethod(env, wrapperCallback, "onDone", "()V", &onDoneMethod); + VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Controller, "Could not find onDone method")); + + DeviceLayer::StackUnlock unlock; + env->CallVoidMethod(wrapperCallback, onDoneMethod); + VerifyOrReturn(!env->ExceptionCheck(), env->ExceptionDescribe()); +} + jlong newConnectedDeviceCallback(JNIEnv * env, jobject self, jobject callback) { chip::DeviceLayer::StackLock lock; @@ -1085,5 +1249,19 @@ void deleteInvokeCallback(JNIEnv * env, jobject self, jlong callbackHandle) chip::Platform::Delete(invokeCallback); } +jlong newExtendableInvokeCallback(JNIEnv * env, jobject self) +{ + chip::DeviceLayer::StackLock lock; + ExtendableInvokeCallback * invokeCallback = chip::Platform::New(self); + return reinterpret_cast(invokeCallback); +} + +void deleteExtendableInvokeCallback(JNIEnv * env, jobject self, jlong callbackHandle) +{ + chip::DeviceLayer::StackLock lock; + ExtendableInvokeCallback * invokeCallback = reinterpret_cast(callbackHandle); + VerifyOrReturn(invokeCallback != nullptr, ChipLogError(Controller, "ExtendableInvokeCallback handle is nullptr")); + chip::Platform::Delete(invokeCallback); +} } // namespace Controller } // namespace chip diff --git a/src/controller/java/AndroidCallbacks.h b/src/controller/java/AndroidCallbacks.h index 700a1fb467f13f..0c49daf1b21a84 100644 --- a/src/controller/java/AndroidCallbacks.h +++ b/src/controller/java/AndroidCallbacks.h @@ -25,6 +25,7 @@ #include #include #include +#include #include namespace chip { @@ -138,6 +139,20 @@ struct InvokeCallback : public app::CommandSender::Callback JniGlobalReference mWrapperCallbackRef; }; +struct ExtendableInvokeCallback : public app::CommandSender::ExtendableCallback +{ + ExtendableInvokeCallback(jobject wrapperCallback); + ~ExtendableInvokeCallback(); + + void OnResponse(app::CommandSender * commandSender, const app::CommandSender::ResponseData & aResponseData) override; + void OnNoResponse(app::CommandSender * commandSender, const app::CommandSender::NoResponseData & aNoResponseData) override; + void OnError(const app::CommandSender * apCommandSender, const app::CommandSender::ErrorData & aErrorData) override; + void OnDone(app::CommandSender * apCommandSender) override; + + app::CommandSender * mCommandSender = nullptr; + JniGlobalReference mWrapperCallbackRef; +}; + jlong newConnectedDeviceCallback(JNIEnv * env, jobject self, jobject callback); void deleteConnectedDeviceCallback(JNIEnv * env, jobject self, jlong callbackHandle); jlong newReportCallback(JNIEnv * env, jobject self, jobject subscriptionEstablishedCallbackJava, @@ -147,6 +162,8 @@ jlong newWriteAttributesCallback(JNIEnv * env, jobject self); void deleteWriteAttributesCallback(JNIEnv * env, jobject self, jlong callbackHandle); jlong newInvokeCallback(JNIEnv * env, jobject self); void deleteInvokeCallback(JNIEnv * env, jobject self, jlong callbackHandle); +jlong newExtendableInvokeCallback(JNIEnv * env, jobject self); +void deleteExtendableInvokeCallback(JNIEnv * env, jobject self, jlong callbackHandle); } // namespace Controller } // namespace chip diff --git a/src/controller/java/AndroidInteractionClient.cpp b/src/controller/java/AndroidInteractionClient.cpp index a0b22bfde530af..ec809570bcb1c7 100644 --- a/src/controller/java/AndroidInteractionClient.cpp +++ b/src/controller/java/AndroidInteractionClient.cpp @@ -431,7 +431,7 @@ CHIP_ERROR write(JNIEnv * env, jlong handle, jlong callbackHandle, jlong deviceP CHIP_ERROR PutPreencodedInvokeRequest(app::CommandSender & commandSender, app::CommandPathParams & path, const ByteSpan & data) { - // PrepareCommand does nott create the struct container with kFields and copycontainer below sets the + // PrepareCommand does not create the struct container with kFields and copycontainer below sets the // kFields container already ReturnErrorOnFailure(commandSender.PrepareCommand(path, false /* aStartDataStruct */)); TLV::TLVWriter * writer = commandSender.GetCommandDataIBTLVWriter(); @@ -442,6 +442,191 @@ CHIP_ERROR PutPreencodedInvokeRequest(app::CommandSender & commandSender, app::C return writer->CopyContainer(TLV::ContextTag(app::CommandDataIB::Tag::kFields), reader); } +CHIP_ERROR PutPreencodedInvokeRequest(app::CommandSender & commandSender, app::CommandPathParams & path, const ByteSpan & data, + app::CommandSender::PrepareCommandParameters & prepareCommandParams) +{ + // PrepareCommand does not create the struct container with kFields and copycontainer below sets the + // kFields container already + ReturnErrorOnFailure(commandSender.PrepareCommand(path, prepareCommandParams)); + TLV::TLVWriter * writer = commandSender.GetCommandDataIBTLVWriter(); + VerifyOrReturnError(writer != nullptr, CHIP_ERROR_INCORRECT_STATE); + TLV::TLVReader reader; + reader.Init(data); + ReturnErrorOnFailure(reader.Next()); + return writer->CopyContainer(TLV::ContextTag(app::CommandDataIB::Tag::kFields), reader); +} + +CHIP_ERROR extendableInvoke(JNIEnv * env, jlong handle, jlong callbackHandle, jlong devicePtr, jobject invokeElementList, + jint timedRequestTimeoutMs, jint imTimeoutMs) +{ + chip::DeviceLayer::StackLock lock; + CHIP_ERROR err = CHIP_NO_ERROR; + auto callback = reinterpret_cast(callbackHandle); + app::CommandSender * commandSender = nullptr; + uint16_t groupId = 0; + bool isEndpointIdValid = false; + bool isGroupIdValid = false; + jint listSize = 0; + uint16_t convertedTimedRequestTimeoutMs = static_cast(timedRequestTimeoutMs); + app::CommandSender::ConfigParameters config; + + ChipLogDetail(Controller, "IM extendableInvoke() called"); + + DeviceProxy * device = reinterpret_cast(devicePtr); + VerifyOrExit(device != nullptr, err = CHIP_ERROR_INCORRECT_STATE); + VerifyOrExit(device->GetSecureSession().HasValue(), err = CHIP_ERROR_MISSING_SECURE_SESSION); + + VerifyOrExit(invokeElementList != nullptr, err = CHIP_ERROR_INVALID_ARGUMENT); + SuccessOrExit(err = JniReferences::GetInstance().GetListSize(invokeElementList, listSize)); + + if ((listSize > 1) && (device->GetSecureSession().Value()->IsGroupSession())) + { + ChipLogError(Controller, "Not allow group session for InvokeRequests that has more than 1 CommandDataIB)"); + err = CHIP_ERROR_INVALID_ARGUMENT; + goto exit; + } + + commandSender = Platform::New(callback, device->GetExchangeManager(), timedRequestTimeoutMs != 0); + config.SetRemoteMaxPathsPerInvoke(device->GetSecureSession().Value()->GetRemoteSessionParameters().GetMaxPathsPerInvoke()); + SuccessOrExit(err = commandSender->SetCommandSenderConfig(config)); + + for (uint8_t i = 0; i < listSize; i++) + { + jmethodID getEndpointIdMethod = nullptr; + jmethodID getClusterIdMethod = nullptr; + jmethodID getCommandIdMethod = nullptr; + jmethodID getGroupIdMethod = nullptr; + jmethodID getTlvByteArrayMethod = nullptr; + jmethodID getJsonStringMethod = nullptr; + jmethodID isEndpointIdValidMethod = nullptr; + jmethodID isGroupIdValidMethod = nullptr; + jlong endpointIdObj = 0; + jlong clusterIdObj = 0; + jlong commandIdObj = 0; + jobject groupIdObj = nullptr; + jbyteArray tlvBytesObj = nullptr; + jobject invokeElement = nullptr; + SuccessOrExit(err = JniReferences::GetInstance().GetListItem(invokeElementList, i, invokeElement)); + SuccessOrExit( + err = JniReferences::GetInstance().FindMethod(env, invokeElement, "getEndpointId", "(J)J", &getEndpointIdMethod)); + SuccessOrExit(err = + JniReferences::GetInstance().FindMethod(env, invokeElement, "getClusterId", "(J)J", &getClusterIdMethod)); + SuccessOrExit(err = + JniReferences::GetInstance().FindMethod(env, invokeElement, "getCommandId", "(J)J", &getCommandIdMethod)); + SuccessOrExit(err = JniReferences::GetInstance().FindMethod(env, invokeElement, "getGroupId", "()Ljava/util/Optional;", + &getGroupIdMethod)); + SuccessOrExit(err = JniReferences::GetInstance().FindMethod(env, invokeElement, "isEndpointIdValid", "()Z", + &isEndpointIdValidMethod)); + SuccessOrExit( + err = JniReferences::GetInstance().FindMethod(env, invokeElement, "isGroupIdValid", "()Z", &isGroupIdValidMethod)); + SuccessOrExit( + err = JniReferences::GetInstance().FindMethod(env, invokeElement, "getTlvByteArray", "()[B", &getTlvByteArrayMethod)); + + isEndpointIdValid = (env->CallBooleanMethod(invokeElement, isEndpointIdValidMethod) == JNI_TRUE); + isGroupIdValid = (env->CallBooleanMethod(invokeElement, isGroupIdValidMethod) == JNI_TRUE); + + if (isEndpointIdValid) + { + endpointIdObj = env->CallLongMethod(invokeElement, getEndpointIdMethod, static_cast(kInvalidEndpointId)); + VerifyOrExit(!env->ExceptionCheck(), err = CHIP_JNI_ERROR_EXCEPTION_THROWN); + } + + if (isGroupIdValid) + { + VerifyOrExit(device->GetSecureSession().Value()->IsGroupSession(), err = CHIP_ERROR_INVALID_ARGUMENT); + groupIdObj = env->CallObjectMethod(invokeElement, getGroupIdMethod); + VerifyOrExit(!env->ExceptionCheck(), err = CHIP_JNI_ERROR_EXCEPTION_THROWN); + VerifyOrExit(groupIdObj != nullptr, err = CHIP_ERROR_INVALID_ARGUMENT); + + jobject boxedGroupId = nullptr; + + SuccessOrExit(err = JniReferences::GetInstance().GetOptionalValue(groupIdObj, boxedGroupId)); + VerifyOrExit(boxedGroupId != nullptr, err = CHIP_ERROR_INVALID_ARGUMENT); + groupId = static_cast(JniReferences::GetInstance().IntegerToPrimitive(boxedGroupId)); + } + + clusterIdObj = env->CallLongMethod(invokeElement, getClusterIdMethod, static_cast(kInvalidClusterId)); + VerifyOrExit(!env->ExceptionCheck(), err = CHIP_JNI_ERROR_EXCEPTION_THROWN); + + commandIdObj = env->CallLongMethod(invokeElement, getCommandIdMethod, static_cast(kInvalidCommandId)); + VerifyOrExit(!env->ExceptionCheck(), err = CHIP_JNI_ERROR_EXCEPTION_THROWN); + + tlvBytesObj = static_cast(env->CallObjectMethod(invokeElement, getTlvByteArrayMethod)); + VerifyOrExit(!env->ExceptionCheck(), err = CHIP_JNI_ERROR_EXCEPTION_THROWN); + + app::CommandSender::PrepareCommandParameters prepareCommandParams; + prepareCommandParams.commandRef.SetValue(static_cast(i)); + + { + uint16_t id = isEndpointIdValid ? static_cast(endpointIdObj) : groupId; + app::CommandPathFlags flag = + isEndpointIdValid ? app::CommandPathFlags::kEndpointIdValid : app::CommandPathFlags::kGroupIdValid; + app::CommandPathParams path(id, static_cast(clusterIdObj), static_cast(commandIdObj), flag); + + if (tlvBytesObj != nullptr) + { + JniByteArray tlvBytesObjBytes(env, tlvBytesObj); + SuccessOrExit( + err = PutPreencodedInvokeRequest(*commandSender, path, tlvBytesObjBytes.byteSpan(), prepareCommandParams)); + } + else + { + SuccessOrExit(err = JniReferences::GetInstance().FindMethod(env, invokeElement, "getJsonString", + "()Ljava/lang/String;", &getJsonStringMethod)); + jstring jsonJniString = static_cast(env->CallObjectMethod(invokeElement, getJsonStringMethod)); + VerifyOrExit(!env->ExceptionCheck(), err = CHIP_JNI_ERROR_EXCEPTION_THROWN); + VerifyOrExit(jsonJniString != nullptr, err = CHIP_ERROR_INVALID_ARGUMENT); + JniUtfString jsonUtfJniString(env, jsonJniString); + // The invoke does not support chunk, kMaxSecureSduLengthBytes should be enough for command json blob + uint8_t tlvBytes[chip::app::kMaxSecureSduLengthBytes] = { 0 }; + MutableByteSpan tlvEncodingLocal{ tlvBytes }; + SuccessOrExit(err = JsonToTlv(std::string(jsonUtfJniString.c_str(), static_cast(jsonUtfJniString.size())), + tlvEncodingLocal)); + SuccessOrExit(err = PutPreencodedInvokeRequest(*commandSender, path, tlvEncodingLocal, prepareCommandParams)); + } + } + + app::CommandSender::FinishCommandParameters finishCommandParams(convertedTimedRequestTimeoutMs != 0 + ? Optional(convertedTimedRequestTimeoutMs) + : Optional::Missing()); + + finishCommandParams.commandRef = prepareCommandParams.commandRef; + SuccessOrExit(err = commandSender->FinishCommand(finishCommandParams)); + } + SuccessOrExit(err = device->GetSecureSession().Value()->IsGroupSession() + ? commandSender->SendGroupCommandRequest(device->GetSecureSession().Value()) + : commandSender->SendCommandRequest(device->GetSecureSession().Value(), + imTimeoutMs != 0 + ? MakeOptional(System::Clock::Milliseconds32(imTimeoutMs)) + : Optional::Missing())); + + callback->mCommandSender = commandSender; +exit: + if (err != CHIP_NO_ERROR) + { + ChipLogError(Controller, "JNI IM Invoke Error: %s", err.AsString()); + if (err == CHIP_JNI_ERROR_EXCEPTION_THROWN) + { + env->ExceptionDescribe(); + env->ExceptionClear(); + } + app::CommandSender::ErrorData errorData; + errorData.error = err; + callback->OnError(nullptr, errorData); + if (commandSender != nullptr) + { + Platform::Delete(commandSender); + commandSender = nullptr; + } + if (callback != nullptr) + { + Platform::Delete(callback); + callback = nullptr; + } + } + return err; +} + CHIP_ERROR invoke(JNIEnv * env, jlong handle, jlong callbackHandle, jlong devicePtr, jobject invokeElement, jint timedRequestTimeoutMs, jint imTimeoutMs) { diff --git a/src/controller/java/AndroidInteractionClient.h b/src/controller/java/AndroidInteractionClient.h index 095061f0c98172..f38af6f4eb2a96 100644 --- a/src/controller/java/AndroidInteractionClient.h +++ b/src/controller/java/AndroidInteractionClient.h @@ -29,3 +29,5 @@ CHIP_ERROR write(JNIEnv * env, jlong handle, jlong callbackHandle, jlong deviceP jint timedRequestTimeoutMs, jint imTimeoutMs); CHIP_ERROR invoke(JNIEnv * env, jlong handle, jlong callbackHandle, jlong devicePtr, jobject invokeElement, jint timedRequestTimeoutMs, jint imTimeoutMs); +CHIP_ERROR extendableInvoke(JNIEnv * env, jlong handle, jlong callbackHandle, jlong devicePtr, jobject invokeElementList, + jint timedRequestTimeoutMs, jint imTimeoutMs); diff --git a/src/controller/java/BUILD.gn b/src/controller/java/BUILD.gn index 31dbaafc9fb21f..a2f3c866bdaa76 100644 --- a/src/controller/java/BUILD.gn +++ b/src/controller/java/BUILD.gn @@ -459,6 +459,8 @@ android_library("java") { "src/chip/devicecontroller/ControllerParams.java", "src/chip/devicecontroller/DeviceAttestationDelegate.java", "src/chip/devicecontroller/DiscoveredDevice.java", + "src/chip/devicecontroller/ExtendableInvokeCallback.java", + "src/chip/devicecontroller/ExtendableInvokeCallbackJni.java", "src/chip/devicecontroller/GetConnectedDeviceCallbackJni.java", "src/chip/devicecontroller/GroupKeySecurityPolicy.java", "src/chip/devicecontroller/ICDClientInfo.java", @@ -493,6 +495,8 @@ android_library("java") { "src/chip/devicecontroller/model/EndpointState.java", "src/chip/devicecontroller/model/EventState.java", "src/chip/devicecontroller/model/InvokeElement.java", + "src/chip/devicecontroller/model/InvokeResponseData.java", + "src/chip/devicecontroller/model/NoInvokeResponseData.java", "src/chip/devicecontroller/model/NodeState.java", "src/chip/devicecontroller/model/Status.java", ] diff --git a/src/controller/java/CHIPDeviceController-JNI.cpp b/src/controller/java/CHIPDeviceController-JNI.cpp index 206103ca82a311..fc2c0694b29849 100644 --- a/src/controller/java/CHIPDeviceController-JNI.cpp +++ b/src/controller/java/CHIPDeviceController-JNI.cpp @@ -2285,6 +2285,18 @@ JNI_METHOD(void, invoke) } } +JNI_METHOD(void, extendableInvoke) +(JNIEnv * env, jclass clz, jlong handle, jlong callbackHandle, jlong devicePtr, jobject invokeElementList, + jint timedRequestTimeoutMs, jint imTimeoutMs) +{ + CHIP_ERROR err = + extendableInvoke(env, handle, callbackHandle, devicePtr, invokeElementList, timedRequestTimeoutMs, imTimeoutMs); + if (err != CHIP_NO_ERROR) + { + ChipLogError(Controller, "JNI IM Batch Invoke Error: %" CHIP_ERROR_FORMAT, err.Format()); + } +} + void * IOThreadMain(void * arg) { JNIEnv * env; diff --git a/src/controller/java/MatterCallbacks-JNI.cpp b/src/controller/java/MatterCallbacks-JNI.cpp index f20d9e47f093ff..93101df18066c4 100644 --- a/src/controller/java/MatterCallbacks-JNI.cpp +++ b/src/controller/java/MatterCallbacks-JNI.cpp @@ -69,3 +69,14 @@ JNI_METHOD(void, InvokeCallbackJni, deleteCallback)(JNIEnv * env, jobject self, { deleteInvokeCallback(env, self, callbackHandle); } + +JNI_METHOD(jlong, ExtendableInvokeCallbackJni, newCallback) +(JNIEnv * env, jobject self) +{ + return newExtendableInvokeCallback(env, self); +} + +JNI_METHOD(void, ExtendableInvokeCallbackJni, deleteCallback)(JNIEnv * env, jobject self, jlong callbackHandle) +{ + deleteExtendableInvokeCallback(env, self, callbackHandle); +} diff --git a/src/controller/java/MatterInteractionClient-JNI.cpp b/src/controller/java/MatterInteractionClient-JNI.cpp index 6a541723d041ed..152e52aedd65d7 100644 --- a/src/controller/java/MatterInteractionClient-JNI.cpp +++ b/src/controller/java/MatterInteractionClient-JNI.cpp @@ -65,3 +65,15 @@ JNI_METHOD(void, invoke) ChipLogError(Controller, "JNI IM Invoke Error: %" CHIP_ERROR_FORMAT, err.Format()); } } + +JNI_METHOD(void, extendableInvoke) +(JNIEnv * env, jobject self, jlong handle, jlong callbackHandle, jlong devicePtr, jobject invokeElementList, + jint timedRequestTimeoutMs, jint imTimeoutMs) +{ + CHIP_ERROR err = + extendableInvoke(env, handle, callbackHandle, devicePtr, invokeElementList, timedRequestTimeoutMs, imTimeoutMs); + if (err != CHIP_NO_ERROR) + { + ChipLogError(Controller, "JNI IM Batch Invoke Error: %" CHIP_ERROR_FORMAT, err.Format()); + } +} diff --git a/src/controller/java/src/chip/devicecontroller/BatchInvokeCallback.java b/src/controller/java/src/chip/devicecontroller/BatchInvokeCallback.java new file mode 100644 index 00000000000000..1b07e38de0615e --- /dev/null +++ b/src/controller/java/src/chip/devicecontroller/BatchInvokeCallback.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2024 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. + * + */ +package chip.devicecontroller; + +import chip.devicecontroller.model.InvokeResponseData; +import chip.devicecontroller.model.NoInvokeResponseData; + +/** An interface for receiving invoke response. */ +public interface ExtendableInvokeCallback { + + /** + * OnError will be called when an error occurs after failing to call + * + * @param Exception The IllegalStateException which encapsulated the error message, the possible + * chip error could be - CHIP_ERROR_TIMEOUT: A response was not received within the expected + * response timeout. - CHIP_ERROR_*TLV*: A malformed, non-compliant response was received from + * the server. - CHIP_ERROR encapsulating the converted error from the StatusIB: If we got a + * non-path-specific status response from the server. - CHIP_ERROR*: All other cases. + */ + void onError(Exception e); + + /** + * OnResponse will be called when a write response has been received and processed for the given + * path. + * + * @param invokeResponseData invoke response that has either payload or status + */ + void onResponse(InvokeResponseData invokeResponseData); + + /** + * onNoResponse will be called for each request that failed to receive a response after the server + * indicates completion of all requests. + * + * @param noInvokeResponseData failed response data + */ + void onNoResponse(NoInvokeResponseData noInvokeResponseData); + + void onDone(); +} diff --git a/src/controller/java/src/chip/devicecontroller/BatchInvokeCallbackJni.java b/src/controller/java/src/chip/devicecontroller/BatchInvokeCallbackJni.java new file mode 100644 index 00000000000000..6982f58429a353 --- /dev/null +++ b/src/controller/java/src/chip/devicecontroller/BatchInvokeCallbackJni.java @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2024 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. + * + */ +package chip.devicecontroller; + +import chip.devicecontroller.model.InvokeResponseData; +import chip.devicecontroller.model.NoInvokeResponseData; +import java.util.Optional; +import javax.annotation.Nullable; + +/** JNI wrapper callback class for {@link InvokeCallback}. */ +public final class ExtendableInvokeCallbackJni { + private final ExtendableInvokeCallback wrappedExtendableInvokeCallback; + private long callbackHandle; + + public ExtendableInvokeCallbackJni(ExtendableInvokeCallback wrappedExtendableInvokeCallback) { + this.wrappedExtendableInvokeCallback = wrappedExtendableInvokeCallback; + this.callbackHandle = newCallback(); + } + + long getCallbackHandle() { + return callbackHandle; + } + + private native long newCallback(); + + private native void deleteCallback(long callbackHandle); + + private void onError(Exception e) { + wrappedExtendableInvokeCallback.onError(e); + } + + private void onResponse( + int endpointId, + long clusterId, + long commandId, + @Nullable Integer commandRef, + byte[] tlv, + String jsonString) { + wrappedExtendableInvokeCallback.onResponse( + InvokeResponseData.newInstance( + endpointId, clusterId, commandId, Optional.ofNullable(commandRef), tlv, jsonString)); + } + + private void onResponse( + int endpointId, + long clusterId, + long commandId, + @Nullable Integer commandRef, + int status, + @Nullable Integer clusterStatus) { + wrappedExtendableInvokeCallback.onResponse( + InvokeResponseData.newInstance( + endpointId, + clusterId, + commandId, + Optional.ofNullable(commandRef), + status, + Optional.ofNullable(clusterStatus))); + } + + private void onNoResponse(int commandRef) { + wrappedExtendableInvokeCallback.onNoResponse(NoInvokeResponseData.newInstance(commandRef)); + } + + private void onDone() { + wrappedExtendableInvokeCallback.onDone(); + } + + // TODO(#8578): Replace finalizer with PhantomReference. + @SuppressWarnings("deprecation") + protected void finalize() throws Throwable { + super.finalize(); + + if (callbackHandle != 0) { + deleteCallback(callbackHandle); + callbackHandle = 0; + } + } +} diff --git a/src/controller/java/src/chip/devicecontroller/ChipDeviceController.java b/src/controller/java/src/chip/devicecontroller/ChipDeviceController.java index 9e5c6e12f42520..25d300ec1cadc1 100644 --- a/src/controller/java/src/chip/devicecontroller/ChipDeviceController.java +++ b/src/controller/java/src/chip/devicecontroller/ChipDeviceController.java @@ -1205,6 +1205,32 @@ public void invoke( imTimeoutMs); } + /** + * @brief ExtendableInvoke command to target device + * @param ExtendableInvokeCallback Callback when invoke responses have been received and processed + * for the given batched invoke commands. + * @param devicePtr connected device pointer + * @param invokeElementList invoke element list + * @param timedRequestTimeoutMs this is timed request if this value is larger than 0 + * @param imTimeoutMs im interaction time out value, it would override the default value in c++ im + * layer if this value is non-zero. + */ + public void extendableInvoke( + ExtendableInvokeCallback callback, + long devicePtr, + List invokeElementList, + int timedRequestTimeoutMs, + int imTimeoutMs) { + ExtendableInvokeCallbackJni jniCallback = new ExtendableInvokeCallbackJni(callback); + extendableInvoke( + deviceControllerPtr, + jniCallback.getCallbackHandle(), + devicePtr, + invokeElementList, + timedRequestTimeoutMs, + imTimeoutMs); + } + /** Create a root (self-signed) X.509 DER encoded certificate */ public static byte[] createRootCertificate( KeypairDelegate keypair, long issuerId, @Nullable Long fabricId) { @@ -1377,6 +1403,14 @@ static native void invoke( int timedRequestTimeoutMs, int imTimeoutMs); + static native void extendableInvoke( + long deviceControllerPtr, + long callbackHandle, + long devicePtr, + List invokeElementList, + int timedRequestTimeoutMs, + int imTimeoutMs); + private native long newDeviceController(ControllerParams params); private native void setDeviceAttestationDelegate( diff --git a/src/controller/java/src/chip/devicecontroller/ExtendableInvokeCallback.java b/src/controller/java/src/chip/devicecontroller/ExtendableInvokeCallback.java new file mode 100644 index 00000000000000..1b07e38de0615e --- /dev/null +++ b/src/controller/java/src/chip/devicecontroller/ExtendableInvokeCallback.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2024 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. + * + */ +package chip.devicecontroller; + +import chip.devicecontroller.model.InvokeResponseData; +import chip.devicecontroller.model.NoInvokeResponseData; + +/** An interface for receiving invoke response. */ +public interface ExtendableInvokeCallback { + + /** + * OnError will be called when an error occurs after failing to call + * + * @param Exception The IllegalStateException which encapsulated the error message, the possible + * chip error could be - CHIP_ERROR_TIMEOUT: A response was not received within the expected + * response timeout. - CHIP_ERROR_*TLV*: A malformed, non-compliant response was received from + * the server. - CHIP_ERROR encapsulating the converted error from the StatusIB: If we got a + * non-path-specific status response from the server. - CHIP_ERROR*: All other cases. + */ + void onError(Exception e); + + /** + * OnResponse will be called when a write response has been received and processed for the given + * path. + * + * @param invokeResponseData invoke response that has either payload or status + */ + void onResponse(InvokeResponseData invokeResponseData); + + /** + * onNoResponse will be called for each request that failed to receive a response after the server + * indicates completion of all requests. + * + * @param noInvokeResponseData failed response data + */ + void onNoResponse(NoInvokeResponseData noInvokeResponseData); + + void onDone(); +} diff --git a/src/controller/java/src/chip/devicecontroller/ExtendableInvokeCallbackJni.java b/src/controller/java/src/chip/devicecontroller/ExtendableInvokeCallbackJni.java new file mode 100644 index 00000000000000..6982f58429a353 --- /dev/null +++ b/src/controller/java/src/chip/devicecontroller/ExtendableInvokeCallbackJni.java @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2024 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. + * + */ +package chip.devicecontroller; + +import chip.devicecontroller.model.InvokeResponseData; +import chip.devicecontroller.model.NoInvokeResponseData; +import java.util.Optional; +import javax.annotation.Nullable; + +/** JNI wrapper callback class for {@link InvokeCallback}. */ +public final class ExtendableInvokeCallbackJni { + private final ExtendableInvokeCallback wrappedExtendableInvokeCallback; + private long callbackHandle; + + public ExtendableInvokeCallbackJni(ExtendableInvokeCallback wrappedExtendableInvokeCallback) { + this.wrappedExtendableInvokeCallback = wrappedExtendableInvokeCallback; + this.callbackHandle = newCallback(); + } + + long getCallbackHandle() { + return callbackHandle; + } + + private native long newCallback(); + + private native void deleteCallback(long callbackHandle); + + private void onError(Exception e) { + wrappedExtendableInvokeCallback.onError(e); + } + + private void onResponse( + int endpointId, + long clusterId, + long commandId, + @Nullable Integer commandRef, + byte[] tlv, + String jsonString) { + wrappedExtendableInvokeCallback.onResponse( + InvokeResponseData.newInstance( + endpointId, clusterId, commandId, Optional.ofNullable(commandRef), tlv, jsonString)); + } + + private void onResponse( + int endpointId, + long clusterId, + long commandId, + @Nullable Integer commandRef, + int status, + @Nullable Integer clusterStatus) { + wrappedExtendableInvokeCallback.onResponse( + InvokeResponseData.newInstance( + endpointId, + clusterId, + commandId, + Optional.ofNullable(commandRef), + status, + Optional.ofNullable(clusterStatus))); + } + + private void onNoResponse(int commandRef) { + wrappedExtendableInvokeCallback.onNoResponse(NoInvokeResponseData.newInstance(commandRef)); + } + + private void onDone() { + wrappedExtendableInvokeCallback.onDone(); + } + + // TODO(#8578): Replace finalizer with PhantomReference. + @SuppressWarnings("deprecation") + protected void finalize() throws Throwable { + super.finalize(); + + if (callbackHandle != 0) { + deleteCallback(callbackHandle); + callbackHandle = 0; + } + } +} diff --git a/src/controller/java/src/chip/devicecontroller/model/InvokeResponseData.java b/src/controller/java/src/chip/devicecontroller/model/InvokeResponseData.java new file mode 100644 index 00000000000000..263051580f09e5 --- /dev/null +++ b/src/controller/java/src/chip/devicecontroller/model/InvokeResponseData.java @@ -0,0 +1,224 @@ +/* + * 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. + * + */ +package chip.devicecontroller.model; + +import java.util.Locale; +import java.util.Objects; +import java.util.Optional; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.annotation.Nullable; +import org.json.JSONException; +import org.json.JSONObject; + +/** Class for tracking invoke response data with either data or status */ +public final class InvokeResponseData { + private static final Logger logger = Logger.getLogger(InvokeResponseData.class.getName()); + @Nullable private final ChipPathId endpointId; + private final ChipPathId clusterId, commandId; + private final Optional commandRef; + @Nullable private final byte[] tlv; + @Nullable private final JSONObject json; + @Nullable private final Status status; + + private InvokeResponseData( + ChipPathId endpointId, + ChipPathId clusterId, + ChipPathId commandId, + Optional commandRef, + @Nullable byte[] tlv, + @Nullable String jsonString) { + this.endpointId = endpointId; + this.clusterId = clusterId; + this.commandId = commandId; + this.commandRef = commandRef; + + if (tlv != null) { + this.tlv = tlv.clone(); + } else { + this.tlv = null; + } + + JSONObject jsonObject = null; + if (jsonString != null) { + try { + jsonObject = new JSONObject(jsonString); + } catch (JSONException ex) { + logger.log(Level.SEVERE, "Error parsing JSON string", ex); + } + } + + this.json = jsonObject; + this.status = null; + } + + private InvokeResponseData( + ChipPathId endpointId, + ChipPathId clusterId, + ChipPathId commandId, + Optional commandRef, + int status, + Optional clusterStatus) { + this.endpointId = endpointId; + this.clusterId = clusterId; + this.commandId = commandId; + this.commandRef = commandRef; + this.status = Status.newInstance(status, clusterStatus); + this.tlv = null; + this.json = null; + } + + public ChipPathId getEndpointId() { + return endpointId; + } + + public ChipPathId getClusterId() { + return clusterId; + } + + public ChipPathId getCommandId() { + return commandId; + } + + public Optional getCommandRef() { + return commandRef; + } + + @Nullable + public Status getStatus() { + return status; + } + + // For use in JNI. + private long getEndpointId(long wildcardValue) { + return endpointId.getId(wildcardValue); + } + + private long getClusterId(long wildcardValue) { + return clusterId.getId(wildcardValue); + } + + private long getCommandId(long wildcardValue) { + return commandId.getId(wildcardValue); + } + + public boolean isEndpointIdValid() { + return endpointId != null; + } + + @Nullable + public byte[] getTlvByteArray() { + if (tlv != null) { + return tlv.clone(); + } + return null; + } + + @Nullable + public JSONObject getJsonObject() { + return json; + } + + @Nullable + public String getJsonString() { + if (json == null) return null; + return json.toString(); + } + + // check whether the current InvokeResponseData has same path as others. + @Override + public boolean equals(Object object) { + if (object instanceof InvokeResponseData) { + InvokeResponseData that = (InvokeResponseData) object; + return Objects.equals(this.endpointId, that.endpointId) + && Objects.equals(this.clusterId, that.clusterId) + && Objects.equals(this.commandId, that.commandId); + } + return false; + } + + @Override + public int hashCode() { + return Objects.hash(endpointId, clusterId, commandId); + } + + @Override + public String toString() { + return String.format( + Locale.ENGLISH, + "Endpoint %s, cluster %s, command %s, payload: %s, status: %s", + endpointId, + clusterId, + commandId, + json == null ? "null" : getJsonString(), + status == null ? "null" : status.toString()); + } + + public static InvokeResponseData newInstance( + ChipPathId endpointId, + ChipPathId clusterId, + ChipPathId commandId, + Optional commandRef, + @Nullable byte[] tlv, + @Nullable String jsonString) { + return new InvokeResponseData(endpointId, clusterId, commandId, commandRef, tlv, jsonString); + } + + public static InvokeResponseData newInstance( + int endpointId, + long clusterId, + long commandId, + Optional commandRef, + @Nullable byte[] tlv, + @Nullable String jsonString) { + return new InvokeResponseData( + ChipPathId.forId(endpointId), + ChipPathId.forId(clusterId), + ChipPathId.forId(commandId), + commandRef, + tlv, + jsonString); + } + + public static InvokeResponseData newInstance( + ChipPathId endpointId, + ChipPathId clusterId, + ChipPathId commandId, + Optional commandRef, + int status, + Optional clusterStatus) { + return new InvokeResponseData( + endpointId, clusterId, commandId, commandRef, status, clusterStatus); + } + + public static InvokeResponseData newInstance( + int endpointId, + long clusterId, + long commandId, + Optional commandRef, + int status, + Optional clusterStatus) { + return new InvokeResponseData( + ChipPathId.forId(endpointId), + ChipPathId.forId(clusterId), + ChipPathId.forId(commandId), + commandRef, + status, + clusterStatus); + } +} diff --git a/src/controller/java/src/chip/devicecontroller/model/NoInvokeResponseData.java b/src/controller/java/src/chip/devicecontroller/model/NoInvokeResponseData.java new file mode 100644 index 00000000000000..03e930c62a978f --- /dev/null +++ b/src/controller/java/src/chip/devicecontroller/model/NoInvokeResponseData.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2024 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. + * + */ +package chip.devicecontroller.model; + +import java.util.logging.Logger; + +/** Class for tracking failed invoke response data. */ +public final class NoInvokeResponseData { + private static final Logger logger = Logger.getLogger(NoInvokeResponseData.class.getName()); + private final Integer commandRef; + + private NoInvokeResponseData(int commandRef) { + this.commandRef = commandRef; + } + + public Integer getCommandRef() { + return commandRef; + } + + public static NoInvokeResponseData newInstance(int commandRef) { + return new NoInvokeResponseData(commandRef); + } +} diff --git a/src/controller/java/src/chip/devicecontroller/model/Status.java b/src/controller/java/src/chip/devicecontroller/model/Status.java index d859fae9f189e0..28abd36465689b 100644 --- a/src/controller/java/src/chip/devicecontroller/model/Status.java +++ b/src/controller/java/src/chip/devicecontroller/model/Status.java @@ -124,4 +124,8 @@ public static Status newInstance(int status) { public static Status newInstance(int status, Integer clusterStatus) { return new Status(status, Optional.ofNullable(clusterStatus)); } + + public static Status newInstance(int status, Optional clusterStatus) { + return new Status(status, clusterStatus); + } } diff --git a/src/lib/core/core.gni b/src/lib/core/core.gni index 8c7032ebac675a..02f98e3557f948 100644 --- a/src/lib/core/core.gni +++ b/src/lib/core/core.gni @@ -100,7 +100,8 @@ declare_args() { chip_tlv_validate_char_string_on_read = false chip_enable_sending_batch_commands = - current_os == "linux" || current_os == "mac" || current_os == "ios" + current_os == "linux" || current_os == "mac" || current_os == "ios" || + current_os == "android" } if (chip_target_style == "") { From 6f621f2fc1041e4c0f8cac03fde8a4d989907f4d Mon Sep 17 00:00:00 2001 From: Karsten Sperling <113487422+ksperling-apple@users.noreply.github.com> Date: Wed, 28 Feb 2024 19:30:02 +1300 Subject: [PATCH 108/385] CI: Free up space on the github runner by deleting some tools we don't use (#32350) Currently this deletes .NET tooling and parts of the Android SDK. Note that our Android CI builds bring their own Android SDK via the chip-build-android container, and do not rely on the copy that is installed in the GitHub Ubuntu image. --- .../action.yaml | 2 + .../actions/maximize-runner-disk/action.yaml | 50 +++++++++++++++++++ .github/workflows/build.yaml | 5 ++ .github/workflows/smoketest-android.yaml | 1 + .github/workflows/unit_integration_test.yaml | 1 + 5 files changed, 59 insertions(+) create mode 100644 .github/actions/maximize-runner-disk/action.yaml diff --git a/.github/actions/checkout-submodules-and-bootstrap/action.yaml b/.github/actions/checkout-submodules-and-bootstrap/action.yaml index 8ddaec14e7bc47..b514b8dd795509 100644 --- a/.github/actions/checkout-submodules-and-bootstrap/action.yaml +++ b/.github/actions/checkout-submodules-and-bootstrap/action.yaml @@ -15,6 +15,8 @@ inputs: runs: using: "composite" steps: + - name: Maximize runner disk + uses: ./.github/actions/maximize-runner-disk - name: Dump disk info uses: ./.github/actions/dump-disk-info - name: Set git safe directory for local act runs diff --git a/.github/actions/maximize-runner-disk/action.yaml b/.github/actions/maximize-runner-disk/action.yaml new file mode 100644 index 00000000000000..fe5f95352aa53e --- /dev/null +++ b/.github/actions/maximize-runner-disk/action.yaml @@ -0,0 +1,50 @@ +name: Maximize runner disk +description: Free up disk space on the github runner +runs: + using: "composite" + steps: + - name: Free up disk space on the github runner + if: ${{ !env.ACT }} + shell: bash + run: | + # maximize-runner-disk + if [[ "$RUNNER_OS" == Linux ]]; then + # Directories to prune to free up space. Candidates: + # 1.6G /usr/share/dotnet + # 1.1G /usr/local/lib/android/sdk/platforms + # 1000M /usr/local/lib/android/sdk/build-tools + # 8.9G /usr/local/lib/android/sdk + # This list can be amended later to change the trade-off between the amount of + # disk space freed up, and how long it takes to do so (deleting many files is slow). + prune=(/usr/share/dotnet /usr/local/lib/android/sdk/platforms /usr/local/lib/android/sdk/build-tools) + + if [[ "$UID" -eq 0 && -d /__w ]]; then + root=/runner-root-volume + if [[ ! -d "$root" ]]; then + echo "Unable to maximize disk space, job is running inside a container and $root is not mounted" + exit 0 + fi + function sudo() { "$@"; } # we're already root (and sudo is probably unavailable) + elif [[ "$UID" -ne 0 && "$RUNNER_ENVIRONMENT" == github-hosted ]]; then + root= + else + echo "Unable to maximize disk space, unknown runner environment" + exit 0 + fi + + echo "Freeing up runner disk space on ${root:-/}" + function avail() { df -k --output=avail "${root:-/}" | grep '^[0-9]*$'; } + function now() { date '+%s'; } + before="$(avail)" start="$(now)" + for dir in "${prune[@]}"; do + if [[ -d "${root}${dir}" ]]; then + echo "- $dir" + # du -sh -- "${root}${dir}" + sudo rm -rf -- "${root}${dir}" + else + echo "- $dir (not found)" + fi + done + after="$(avail)" end="$(now)" + echo "Done, freed up $(( (after - before) / 1024 ))M of disk space in $(( end - start )) seconds." + fi diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 23dd3d3eb0f309..effec464b45aee 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -42,6 +42,7 @@ jobs: container: image: ghcr.io/project-chip/chip-build:35 volumes: + - "/:/runner-root-volume" - "/tmp/log_output:/tmp/test_logs" options: --privileged --sysctl "net.ipv6.conf.all.disable_ipv6=0 net.ipv4.conf.all.forwarding=1 net.ipv6.conf.all.forwarding=1" @@ -137,6 +138,7 @@ jobs: container: image: ghcr.io/project-chip/chip-build:35 volumes: + - "/:/runner-root-volume" - "/tmp/log_output:/tmp/test_logs" options: --privileged --sysctl "net.ipv6.conf.all.disable_ipv6=0 net.ipv4.conf.all.forwarding=1 net.ipv6.conf.all.forwarding=1" @@ -285,6 +287,7 @@ jobs: container: image: ghcr.io/project-chip/chip-build:35 volumes: + - "/:/runner-root-volume" - "/tmp/log_output:/tmp/test_logs" options: --sysctl "net.ipv6.conf.all.disable_ipv6=0 net.ipv4.conf.all.forwarding=1 net.ipv6.conf.all.forwarding=1" @@ -345,6 +348,7 @@ jobs: container: image: ghcr.io/project-chip/chip-build:35 volumes: + - "/:/runner-root-volume" - "/tmp/log_output:/tmp/test_logs" options: --sysctl "net.ipv6.conf.all.disable_ipv6=0 net.ipv4.conf.all.forwarding=1 net.ipv6.conf.all.forwarding=1" @@ -453,6 +457,7 @@ jobs: container: image: ghcr.io/project-chip/chip-build:35 volumes: + - "/:/runner-root-volume" - "/tmp/log_output:/tmp/test_logs" options: --privileged --sysctl "net.ipv6.conf.all.disable_ipv6=0 net.ipv4.conf.all.forwarding=1 net.ipv6.conf.all.forwarding=1" diff --git a/.github/workflows/smoketest-android.yaml b/.github/workflows/smoketest-android.yaml index 396fb3ae153a46..64efaeb82ff20f 100644 --- a/.github/workflows/smoketest-android.yaml +++ b/.github/workflows/smoketest-android.yaml @@ -39,6 +39,7 @@ jobs: container: image: ghcr.io/project-chip/chip-build-android:35 volumes: + - "/:/runner-root-volume" - "/tmp/log_output:/tmp/test_logs" steps: diff --git a/.github/workflows/unit_integration_test.yaml b/.github/workflows/unit_integration_test.yaml index 62231116bb92c1..15199d4d6532e3 100644 --- a/.github/workflows/unit_integration_test.yaml +++ b/.github/workflows/unit_integration_test.yaml @@ -39,6 +39,7 @@ jobs: container: image: ghcr.io/project-chip/chip-build:35 volumes: + - "/:/runner-root-volume" - "/tmp/log_output:/tmp/test_logs" options: --privileged --sysctl "net.ipv6.conf.all.disable_ipv6=0 net.ipv4.conf.all.forwarding=1 net.ipv6.conf.all.forwarding=1" From 355e2b478676271f72f7c1071865f16114f4a371 Mon Sep 17 00:00:00 2001 From: joonhaengHeo <85541460+joonhaengHeo@users.noreply.github.com> Date: Wed, 28 Feb 2024 19:10:30 +0900 Subject: [PATCH 109/385] [Android] Implement multiple write invoke UI (#32352) * Implement multiple write,invoke UI * fix reset btn --- .../clusterclient/WildcardFragment.kt | 240 +++++++++++------- .../app/src/main/res/layout/invoke_dialog.xml | 28 +- .../src/main/res/layout/wildcard_fragment.xml | 104 +++++++- .../app/src/main/res/layout/write_dialog.xml | 55 +--- .../app/src/main/res/values/strings.xml | 14 +- 5 files changed, 264 insertions(+), 177 deletions(-) diff --git a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/WildcardFragment.kt b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/WildcardFragment.kt index 5b49a6d9ab05ab..2ffbec50c746a2 100644 --- a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/WildcardFragment.kt +++ b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/WildcardFragment.kt @@ -16,7 +16,7 @@ import androidx.fragment.app.Fragment import androidx.lifecycle.lifecycleScope import chip.devicecontroller.ChipDeviceController import chip.devicecontroller.ChipIdLookup -import chip.devicecontroller.InvokeCallback +import chip.devicecontroller.ExtendableInvokeCallback import chip.devicecontroller.ReportCallback import chip.devicecontroller.ResubscriptionAttemptCallback import chip.devicecontroller.SubscriptionEstablishedCallback @@ -26,6 +26,8 @@ import chip.devicecontroller.model.ChipAttributePath import chip.devicecontroller.model.ChipEventPath import chip.devicecontroller.model.ChipPathId import chip.devicecontroller.model.InvokeElement +import chip.devicecontroller.model.InvokeResponseData +import chip.devicecontroller.model.NoInvokeResponseData import chip.devicecontroller.model.NodeState import chip.devicecontroller.model.Status import com.google.chip.chiptool.ChipClient @@ -57,6 +59,8 @@ class WildcardFragment : Fragment() { private val attributePath = ArrayList() private val eventPath = ArrayList() + private val writePath = ArrayList() + private val invokePath = ArrayList() private val subscribeIdList = ArrayList() private val reportCallback = @@ -89,29 +93,47 @@ class WildcardFragment : Fragment() { private val writeAttributeCallback = object : WriteAttributesCallback { + var viewText = "" + override fun onError(attributePath: ChipAttributePath?, ex: Exception?) { Log.e(TAG, "Report error for $attributePath: $ex") + viewText += "onError : $attributePath - $ex\n" } override fun onResponse(attributePath: ChipAttributePath, status: Status) { - val text = "$attributePath : Write response: $status" - requireActivity().runOnUiThread { binding.outputTv.text = text } + viewText += "$attributePath : Write response: $status\n" } override fun onDone() { - Log.i(TAG, "write attribute Done") + requireActivity().runOnUiThread { + binding.outputTv.text = viewText + viewText = "" + } } } - private val invokeCallback = - object : InvokeCallback { + private val extendableInvokeCallback = + object : ExtendableInvokeCallback { + var viewText = "" + override fun onError(e: java.lang.Exception?) { + viewText += "Invoke onError : $e\n" Log.e(TAG, "Report error", e) } - override fun onResponse(invokeElement: InvokeElement?, successCode: Long) { - val text = "Invoke Response : $invokeElement, $successCode" - requireActivity().runOnUiThread { binding.outputTv.text = text } + override fun onResponse(invokeResponseData: InvokeResponseData?) { + viewText += "Invoke Response : $invokeResponseData\n" + } + + override fun onNoResponse(noInvokeResponseData: NoInvokeResponseData?) { + viewText += "Invoke onNoResponse : $noInvokeResponseData\n" + } + + override fun onDone() { + requireActivity().runOnUiThread { + binding.outputTv.text = viewText + viewText = "" + } } } @@ -123,41 +145,27 @@ class WildcardFragment : Fragment() { _binding = WildcardFragmentBinding.inflate(inflater, container, false) scope = viewLifecycleOwner.lifecycleScope - binding.selectTypeRadioGroup.setOnCheckedChangeListener { _, i -> - val readBtnOn = (i == R.id.readRadioBtn) - val subscribeBtnOn = (i == R.id.subscribeRadioBtn) - val writeBtnOn = (i == R.id.writeRadioBtn) - val invokeBtnOn = (i == R.id.invokeRadioBtn) - - binding.addLayout.visibility = getVisibility(readBtnOn || subscribeBtnOn) - binding.attributeIdLabel.visibility = getVisibility(readBtnOn || subscribeBtnOn || writeBtnOn) - binding.attributeIdEd.visibility = getVisibility(readBtnOn || subscribeBtnOn || writeBtnOn) - binding.eventIdLabel.visibility = getVisibility(readBtnOn || subscribeBtnOn) - binding.eventIdEd.visibility = getVisibility(readBtnOn || subscribeBtnOn) - binding.commandIdLabel.visibility = getVisibility(invokeBtnOn) - binding.commandIdEd.visibility = getVisibility(invokeBtnOn) - binding.isUrgentLabel.visibility = getVisibility(subscribeBtnOn) - binding.isUrgentSp.visibility = getVisibility(subscribeBtnOn) - binding.shutdownSubscriptionBtn.visibility = getVisibility(subscribeBtnOn) - } + val writeTypeSpinnerAdapter = + ArrayAdapter( + requireActivity(), + android.R.layout.simple_spinner_dropdown_item, + TLV_MAP.keys.toList() + ) + binding.writeValueTypeSp.adapter = writeTypeSpinnerAdapter - binding.sendBtn.setOnClickListener { - if (binding.readRadioBtn.isChecked) { - showReadDialog() - } else if (binding.subscribeRadioBtn.isChecked) { - showSubscribeDialog() - } else if (binding.writeRadioBtn.isChecked) { - showWriteDialog() - } else if (binding.invokeRadioBtn.isChecked) { - showInvokeDialog() - } + binding.selectTypeRadioGroup.setOnCheckedChangeListener { _, radioBtnId -> + setVisibilityEachView(radioBtnId) } + binding.sendBtn.setOnClickListener { showDialog() } + binding.shutdownSubscriptionBtn.setOnClickListener { showShutdownSubscriptionDialog() } - binding.addAttributeBtn.setOnClickListener { addPathList(ATTRIBUTE) } - binding.addEventBtn.setOnClickListener { addPathList(EVENT) } + binding.addAttributeBtn.setOnClickListener { addPathList(SendType.ATTRIBUTE) } + binding.addEventBtn.setOnClickListener { addPathList(SendType.EVENT) } + binding.addListBtn.setOnClickListener { addRequest() } binding.resetBtn.setOnClickListener { resetPath() } + binding.writeInvokeresetBtn.setOnClickListener { resetPath() } addressUpdateFragment = childFragmentManager.findFragmentById(R.id.addressUpdateFragment) as AddressUpdateFragment @@ -165,6 +173,58 @@ class WildcardFragment : Fragment() { return binding.root } + private fun setVisibilityEachView(radioBtnId: Int) { + val readBtnOn = (radioBtnId == R.id.readRadioBtn) + val subscribeBtnOn = (radioBtnId == R.id.subscribeRadioBtn) + val writeBtnOn = (radioBtnId == R.id.writeRadioBtn) + val invokeBtnOn = (radioBtnId == R.id.invokeRadioBtn) + + binding.addAttributeBtn.visibility = getVisibility(readBtnOn || subscribeBtnOn) + binding.addEventBtn.visibility = getVisibility(readBtnOn || subscribeBtnOn) + binding.resetBtn.visibility = getVisibility(readBtnOn || subscribeBtnOn) + binding.attributeIdLabel.visibility = getVisibility(readBtnOn || subscribeBtnOn || writeBtnOn) + binding.attributeIdEd.visibility = getVisibility(readBtnOn || subscribeBtnOn || writeBtnOn) + binding.eventIdLabel.visibility = getVisibility(readBtnOn || subscribeBtnOn) + binding.eventIdEd.visibility = getVisibility(readBtnOn || subscribeBtnOn) + binding.addListBtn.visibility = getVisibility(writeBtnOn || invokeBtnOn) + binding.commandIdLabel.visibility = getVisibility(invokeBtnOn) + binding.commandIdEd.visibility = getVisibility(invokeBtnOn) + binding.isUrgentLabel.visibility = getVisibility(subscribeBtnOn) + binding.isUrgentSp.visibility = getVisibility(subscribeBtnOn) + binding.writeValueLabel.visibility = getVisibility(writeBtnOn) + binding.writeValueEd.visibility = getVisibility(writeBtnOn) + binding.writeValueTypeLabel.visibility = getVisibility(writeBtnOn) + binding.writeValueTypeSp.visibility = getVisibility(writeBtnOn) + binding.dataVersionLabel.visibility = getVisibility(writeBtnOn) + binding.dataVersionEd.visibility = getVisibility(writeBtnOn) + binding.invokeValueLabel.visibility = getVisibility(invokeBtnOn) + binding.invokeValueEd.visibility = getVisibility(invokeBtnOn) + binding.shutdownSubscriptionBtn.visibility = getVisibility(subscribeBtnOn) + binding.writeInvokeresetBtn.visibility = getVisibility(writeBtnOn || invokeBtnOn) + + resetPath() + } + + private fun showDialog() { + if (binding.readRadioBtn.isChecked) { + showReadDialog() + } else if (binding.subscribeRadioBtn.isChecked) { + showSubscribeDialog() + } else if (binding.writeRadioBtn.isChecked) { + showWriteDialog() + } else if (binding.invokeRadioBtn.isChecked) { + showInvokeDialog() + } + } + + private fun addRequest() { + if (binding.writeRadioBtn.isChecked) { + addWriteRequest() + } else { + addInvokeRequest() + } + } + private fun getVisibility(isShowing: Boolean): Int { return if (isShowing) { View.VISIBLE @@ -173,7 +233,7 @@ class WildcardFragment : Fragment() { } } - private fun addPathList(type: Int) { + private fun addPathList(type: SendType) { val endpointId = getChipPathIdForText(binding.endpointIdEd.text.toString()) val clusterId = getChipPathIdForText(binding.clusterIdEd.text.toString()) val attributeId = getChipPathIdForText(binding.attributeIdEd.text.toString()) @@ -183,9 +243,9 @@ class WildcardFragment : Fragment() { (binding.subscribeRadioBtn.isChecked) && (binding.isUrgentSp.selectedItem.toString().toBoolean()) - if (type == ATTRIBUTE) { + if (type == SendType.ATTRIBUTE) { attributePath.add(ChipAttributePath.newInstance(endpointId, clusterId, attributeId)) - } else if (type == EVENT) { + } else if (type == SendType.EVENT) { eventPath.add(ChipEventPath.newInstance(endpointId, clusterId, eventId, isUrgent)) } updateAddListView() @@ -194,6 +254,8 @@ class WildcardFragment : Fragment() { private fun resetPath() { attributePath.clear() eventPath.clear() + writePath.clear() + invokePath.clear() updateAddListView() } @@ -205,6 +267,12 @@ class WildcardFragment : Fragment() { for (event in eventPath) { builder.append("event($event)\n") } + for (write in writePath) { + builder.append("WritePath($write)\n") + } + for (invoke in invokePath) { + builder.append("InvokePath($invoke)\n") + } binding.sendListView.text = builder.toString() } @@ -312,13 +380,11 @@ class WildcardFragment : Fragment() { ) } - private suspend fun write( - writeValueType: String, - writeValue: String, - dataVersion: Int?, - timedRequestTimeoutMs: Int, - imTimeoutMs: Int - ) { + private fun addWriteRequest() { + val writeValue = binding.writeValueEd.text.toString() + val writeValueType = binding.writeValueTypeSp.selectedItem.toString() + val dataVersion = binding.dataVersionEd.text.toString() + val endpointId = if (!addressUpdateFragment.isGroupId()) { getChipPathIdForText(binding.endpointIdEd.text.toString()) @@ -329,10 +395,10 @@ class WildcardFragment : Fragment() { val attributeId = getChipPathIdForText(binding.attributeIdEd.text.toString()) val version = - if (dataVersion == null) { + if (dataVersion.isEmpty()) { Optional.empty() } else { - Optional.of(dataVersion) + Optional.of(dataVersion.toInt()) } lateinit var writeRequest: AttributeWriteRequest @@ -364,26 +430,15 @@ class WildcardFragment : Fragment() { version ) } - val devicePtr = - try { - addressUpdateFragment.getDevicePointer(requireContext()) - } catch (e: IllegalStateException) { - Log.d(TAG, "getDevicePointer exception", e) - return - } - deviceController.write( - writeAttributeCallback, - devicePtr, - listOf(writeRequest), - timedRequestTimeoutMs, - imTimeoutMs - ) + writePath.add(writeRequest) + updateAddListView() } - private suspend fun invoke(invokeJson: String, timedRequestTimeoutMs: Int, imTimeoutMs: Int) { + private fun addInvokeRequest() { val endpointId = getChipPathIdForText(binding.endpointIdEd.text.toString()) val clusterId = getChipPathIdForText(binding.clusterIdEd.text.toString()) val commandId = getChipPathIdForText(binding.commandIdEd.text.toString()) + val invokeJson = binding.invokeValueEd.text.toString() val jsonString = invokeJson.ifEmpty { "{}" } val invokeElement = @@ -398,6 +453,28 @@ class WildcardFragment : Fragment() { } else { InvokeElement.newInstance(endpointId, clusterId, commandId, null, jsonString) } + invokePath.add(invokeElement) + updateAddListView() + } + + private suspend fun write(timedRequestTimeoutMs: Int, imTimeoutMs: Int) { + val devicePtr = + try { + addressUpdateFragment.getDevicePointer(requireContext()) + } catch (e: IllegalStateException) { + Log.d(TAG, "getDevicePointer exception", e) + return + } + deviceController.write( + writeAttributeCallback, + devicePtr, + writePath, + timedRequestTimeoutMs, + imTimeoutMs + ) + } + + private suspend fun invoke(timedRequestTimeoutMs: Int, imTimeoutMs: Int) { val devicePtr = try { addressUpdateFragment.getDevicePointer(requireContext()) @@ -405,10 +482,10 @@ class WildcardFragment : Fragment() { Log.d(TAG, "getDevicePointer exception", e) return } - deviceController.invoke( - invokeCallback, + deviceController.extendableInvoke( + extendableInvokeCallback, devicePtr, - invokeElement, + invokePath, timedRequestTimeoutMs, imTimeoutMs ) @@ -453,31 +530,14 @@ class WildcardFragment : Fragment() { private fun showWriteDialog() { binding.outputTv.text = "" val dialogView = requireActivity().layoutInflater.inflate(R.layout.write_dialog, null) - val writeValueTypeSp = dialogView.findViewById(R.id.writeValueTypeSp) - val spinnerAdapter = - ArrayAdapter( - requireActivity(), - android.R.layout.simple_spinner_dropdown_item, - TLV_MAP.keys.toList() - ) - writeValueTypeSp.adapter = spinnerAdapter val dialog = AlertDialog.Builder(requireContext()).apply { setView(dialogView) }.create() dialogView.findViewById