diff --git a/.github/workflows/darwin-tests.yaml b/.github/workflows/darwin-tests.yaml index a916250572bb6e..815293204b09de 100644 --- a/.github/workflows/darwin-tests.yaml +++ b/.github/workflows/darwin-tests.yaml @@ -95,6 +95,7 @@ jobs: --target darwin-x64-lit-icd-${BUILD_VARIANT} \ --target darwin-x64-microwave-oven-${BUILD_VARIANT} \ --target darwin-x64-rvc-${BUILD_VARIANT} \ + --target darwin-x64-network-manager-${BUILD_VARIANT} \ build \ --copy-artifacts-to objdir-clone \ " @@ -116,6 +117,7 @@ jobs: --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 \ + --network-manager-app ./out/darwin-x64-network-manager-${BUILD_VARIANT}/matter-network-manager-app \ " - name: Run OTA Test run: | diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index d6ff5d341cd070..03a364cc17df38 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yaml @@ -186,6 +186,7 @@ jobs: src/app/zap-templates/zcl/data-model/chip/thermostat-cluster.xml \ src/app/zap-templates/zcl/data-model/chip/thread-border-router-management-cluster.xml \ src/app/zap-templates/zcl/data-model/chip/thread-network-diagnostics-cluster.xml \ + src/app/zap-templates/zcl/data-model/chip/thread-network-directory-cluster.xml \ src/app/zap-templates/zcl/data-model/chip/time-format-localization-cluster.xml \ src/app/zap-templates/zcl/data-model/chip/time-synchronization-cluster.xml \ src/app/zap-templates/zcl/data-model/chip/timer-cluster.xml \ @@ -223,6 +224,7 @@ jobs: --target linux-x64-lit-icd-${BUILD_VARIANT} \ --target linux-x64-microwave-oven-${BUILD_VARIANT} \ --target linux-x64-rvc-${BUILD_VARIANT} \ + --target linux-x64-network-manager-${BUILD_VARIANT} \ build \ --copy-artifacts-to objdir-clone \ " @@ -245,6 +247,7 @@ jobs: --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 \ + --network-manager-app ./out/linux-x64-network-manager-${BUILD_VARIANT}/matter-network-manager-app \ " - name: Run purposeful failure tests using the python parser sending commands to chip-tool @@ -286,6 +289,7 @@ jobs: --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 \ + --network-manager-app ./out/linux-x64-network-manager-${BUILD_VARIANT}/matter-network-manager-app \ " - name: Run Tests using chip-repl (including slow) if: github.event_name == 'push' @@ -305,6 +309,7 @@ jobs: --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 \ + --network-manager-app ./out/linux-x64-network-manager-${BUILD_VARIANT}/matter-network-manager-app \ " - name: Uploading core files uses: actions/upload-artifact@v4 @@ -373,6 +378,7 @@ jobs: --target darwin-x64-lit-icd-${BUILD_VARIANT} \ --target darwin-x64-microwave-oven-${BUILD_VARIANT} \ --target darwin-x64-rvc-${BUILD_VARIANT} \ + --target darwin-x64-network-manager-${BUILD_VARIANT} \ build \ --copy-artifacts-to objdir-clone \ " @@ -396,6 +402,7 @@ jobs: --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 \ + --network-manager-app ./out/darwin-x64-network-manager-${BUILD_VARIANT}/matter-network-manager-app \ " - name: Run purposeful failure tests using the python parser sending commands to chip-tool diff --git a/build/config/compiler/BUILD.gn b/build/config/compiler/BUILD.gn index 1e634152a61d49..93333078f6f477 100644 --- a/build/config/compiler/BUILD.gn +++ b/build/config/compiler/BUILD.gn @@ -14,6 +14,7 @@ import("//build_overrides/build.gni") import("//build_overrides/pigweed.gni") +import("//build_overrides/pigweed_environment.gni") import("${build_root}/chip/java/config.gni") import("${build_root}/config/compiler/compiler.gni") import("${build_root}/config/sysroot.gni") @@ -348,7 +349,14 @@ config("cosmetic_default") { } config("runtime_default") { - if (is_clang) { # Using Pigweed clang instead of Darwin host clang + if (is_clang && + current_os == "mac") { # Using Pigweed clang instead of Darwin host clang + # Without pw_env_setup_CIPD_PIGWEED defined the hostclang:no_system_libcpp + # config silently uses the system libc++, usually resulting in linker errors. + assert( + defined(pw_env_setup_CIPD_PIGWEED), + "//build_overrides/pigweed_environment.gni must define pw_env_setup_CIPD_PIGWEED when using pigweed clang") + configs = [ "$dir_pw_toolchain/host_clang:no_system_libcpp", "$dir_pw_toolchain/host_clang:xcode_sysroot", diff --git a/examples/network-manager-app/linux/BUILD.gn b/examples/network-manager-app/linux/BUILD.gn index 1dee694c38616e..ea973edfbfd15c 100644 --- a/examples/network-manager-app/linux/BUILD.gn +++ b/examples/network-manager-app/linux/BUILD.gn @@ -15,7 +15,7 @@ import("//build_overrides/build.gni") import("//build_overrides/chip.gni") -executable("network-manager-app") { +executable("matter-network-manager-app") { sources = [ "include/CHIPProjectAppConfig.h", "main.cpp", @@ -32,7 +32,7 @@ executable("network-manager-app") { } group("linux") { - deps = [ ":network-manager-app" ] + deps = [ ":matter-network-manager-app" ] } group("default") { diff --git a/examples/network-manager-app/network-manager-common/network-manager-app.matter b/examples/network-manager-app/network-manager-common/network-manager-app.matter index dd37ffc02a635c..039b20292786b7 100644 --- a/examples/network-manager-app/network-manager-common/network-manager-app.matter +++ b/examples/network-manager-app/network-manager-common/network-manager-app.matter @@ -1193,10 +1193,11 @@ cluster GroupKeyManagement = 63 { } /** Functionality to retrieve operational information about a managed Wi-Fi network. */ -cluster WiFiNetworkManagement = 1105 { +provisional cluster WiFiNetworkManagement = 1105 { revision 1; - readonly attribute nullable octet_string<32> ssid = 1; + readonly attribute nullable octet_string<32> ssid = 0; + readonly attribute access(read: manage) nullable int64u passphraseSurrogate = 1; readonly attribute command_id generatedCommandList[] = 65528; readonly attribute command_id acceptedCommandList[] = 65529; readonly attribute event_id eventList[] = 65530; @@ -1209,11 +1210,11 @@ cluster WiFiNetworkManagement = 1105 { } /** Request the current WPA-Personal passphrase or PSK associated with the managed Wi-Fi network. */ - command access(invoke: administer) NetworkPassphraseRequest(): NetworkPassphraseResponse = 0; + command access(invoke: manage) NetworkPassphraseRequest(): NetworkPassphraseResponse = 0; } /** Manages the names and credentials of Thread networks visible to the user. */ -cluster ThreadNetworkDirectory = 1107 { +provisional cluster ThreadNetworkDirectory = 1107 { revision 1; struct ThreadNetworkStruct { @@ -1254,7 +1255,7 @@ cluster ThreadNetworkDirectory = 1107 { /** Removes an entry from the ThreadNetworks list. */ timed command access(invoke: manage) RemoveNetwork(RemoveNetworkRequest): DefaultSuccess = 1; /** Retrieves a Thread Operational Dataset from the ThreadNetworks list. */ - timed command GetOperationalDataset(GetOperationalDatasetRequest): OperationalDatasetResponse = 2; + command GetOperationalDataset(GetOperationalDatasetRequest): OperationalDatasetResponse = 2; } endpoint 0 { @@ -1525,6 +1526,7 @@ endpoint 1 { server cluster WiFiNetworkManagement { callback attribute ssid; + callback attribute passphraseSurrogate; callback attribute generatedCommandList; callback attribute acceptedCommandList; callback attribute eventList; diff --git a/examples/network-manager-app/network-manager-common/network-manager-app.zap b/examples/network-manager-app/network-manager-common/network-manager-app.zap index ec8316ce2ad3c0..64113c969dd774 100644 --- a/examples/network-manager-app/network-manager-common/network-manager-app.zap +++ b/examples/network-manager-app/network-manager-common/network-manager-app.zap @@ -3238,7 +3238,7 @@ "attributes": [ { "name": "SSID", - "code": 1, + "code": 0, "mfgCode": null, "side": "server", "type": "octet_string", @@ -3252,6 +3252,22 @@ "maxInterval": 65534, "reportableChange": 0 }, + { + "name": "PassphraseSurrogate", + "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": "GeneratedCommandList", "code": 65528, diff --git a/scripts/build/builders/host.py b/scripts/build/builders/host.py index 50695772fff354..4ea5a9aae0f836 100644 --- a/scripts/build/builders/host.py +++ b/scripts/build/builders/host.py @@ -256,6 +256,9 @@ def OutputNames(self): elif self == HostApp.LIT_ICD: yield 'lit-icd-app' yield 'lit-icd-app.map' + elif self == HostApp.NETWORK_MANAGER: + yield 'matter-network-manager-app' + yield 'matter-network-manager-app.map' elif self == HostApp.ENERGY_MANAGEMENT: yield 'chip-energy-management-app' yield 'chip-energy-management-app.map' diff --git a/scripts/tests/chiptest/__init__.py b/scripts/tests/chiptest/__init__.py index a250bab52e9de4..8d0950f379bae1 100644 --- a/scripts/tests/chiptest/__init__.py +++ b/scripts/tests/chiptest/__init__.py @@ -286,6 +286,8 @@ def target_for_name(name: str): return TestTarget.MWO if name.startswith("Test_TC_RVCRUNM_") or name.startswith("Test_TC_RVCCLEANM_") or name.startswith("Test_TC_RVCOPSTATE_"): return TestTarget.RVC + if name.startswith("Test_TC_THNETDIR_") or name.startswith("Test_TC_WIFINM_"): + return TestTarget.NETWORK_MANAGER return TestTarget.ALL_CLUSTERS diff --git a/scripts/tests/chiptest/linux.py b/scripts/tests/chiptest/linux.py index 3dbd851be26b47..0a6df4cd671671 100644 --- a/scripts/tests/chiptest/linux.py +++ b/scripts/tests/chiptest/linux.py @@ -184,6 +184,7 @@ def PathsWithNetworkNamespaces(paths: ApplicationPaths) -> ApplicationPaths: 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, + network_manager_app='ip netns exec app'.split() + paths.network_manager_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 970c098f1354bb..57c43c27a1cbca 100644 --- a/scripts/tests/chiptest/test_definition.py +++ b/scripts/tests/chiptest/test_definition.py @@ -177,6 +177,7 @@ class TestTarget(Enum): LIT_ICD = auto() MWO = auto() RVC = auto() + NETWORK_MANAGER = auto() @dataclass @@ -193,10 +194,11 @@ class ApplicationPaths: chip_repl_yaml_tester_cmd: typing.List[str] chip_tool_with_python_cmd: typing.List[str] rvc_app: typing.List[str] + network_manager_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.rvc_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.rvc_app, self.network_manager_app] @dataclass @@ -309,6 +311,8 @@ def Run(self, runner, apps_register, paths: ApplicationPaths, pics_file: str, target_app = paths.microwave_oven_app elif self.target == TestTarget.RVC: target_app = paths.rvc_app + elif self.target == TestTarget.NETWORK_MANAGER: + target_app = paths.network_manager_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 c22b4abff92f09..d546bb0803b6b9 100755 --- a/scripts/tests/run_test_suite.py +++ b/scripts/tests/run_test_suite.py @@ -260,6 +260,9 @@ def cmd_list(context): @click.option( '--rvc-app', help='what rvc app to use') +@click.option( + '--network-manager-app', + help='what network-manager app to use') @click.option( '--chip-repl-yaml-tester', help='what python script to use for running yaml tests using chip-repl as controller') @@ -291,7 +294,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, rvc_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, network_manager_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) @@ -327,6 +330,9 @@ def cmd_run(context, iterations, all_clusters_app, lock_app, ota_provider_app, o if rvc_app is None: rvc_app = paths_finder.get('chip-rvc-app') + if network_manager_app is None: + network_manager_app = paths_finder.get('matter-network-manager-app') + if chip_repl_yaml_tester is None: chip_repl_yaml_tester = paths_finder.get('yamltest_with_chip_repl_tester.py') @@ -348,6 +354,7 @@ def cmd_run(context, iterations, all_clusters_app, lock_app, ota_provider_app, o lit_icd_app=[lit_icd_app], microwave_oven_app=[microwave_oven_app], rvc_app=[rvc_app], + network_manager_app=[network_manager_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/clusters/thread-network-directory-server/thread-network-directory-server.cpp b/src/app/clusters/thread-network-directory-server/thread-network-directory-server.cpp index d1f3de7c58bbc8..384686693b0a69 100644 --- a/src/app/clusters/thread-network-directory-server/thread-network-directory-server.cpp +++ b/src/app/clusters/thread-network-directory-server/thread-network-directory-server.cpp @@ -274,8 +274,10 @@ void ThreadNetworkDirectoryServer::HandleOperationalDatasetRequest( uint8_t datasetBuffer[kSizeOperationalDataset]; MutableByteSpan datasetSpan(datasetBuffer); + OperationalDatasetResponse::Type response; SuccessOrExit(err = mStorage.GetNetworkDataset(ExtendedPanId(req.extendedPanID), datasetSpan)); - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, IMStatus::Success); + response.operationalDataset = datasetSpan; + ctx.mCommandHandler.AddResponse(ctx.mRequestPath, response); return; exit: ChipLogError(Zcl, "GetOperationalDataset: %" CHIP_ERROR_FORMAT, err.Format()); diff --git a/src/app/clusters/wifi-network-management-server/wifi-network-management-server.cpp b/src/app/clusters/wifi-network-management-server/wifi-network-management-server.cpp index f99ccdf5aafad3..43048498602ff8 100644 --- a/src/app/clusters/wifi-network-management-server/wifi-network-management-server.cpp +++ b/src/app/clusters/wifi-network-management-server/wifi-network-management-server.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -99,11 +100,20 @@ CHIP_ERROR WiFiNetworkManagementServer::SetNetworkCredentials(ByteSpan ssid, Byt VerifyOrDie(mPassphrase.SetLength(passphrase.size()) == CHIP_NO_ERROR); memcpy(mPassphrase.Bytes(), passphrase.data(), passphrase.size()); - // Note: The spec currently defines no way to signal a passphrase change if (ssidChanged) { MatterReportingAttributeChangeCallback(GetEndpointId(), WiFiNetworkManagement::Id, Ssid::Id); } + if (passphraseChanged) + { + mPassphraseSurrogate++; + System::Clock::Milliseconds64 realtime; + if (System::SystemClock().GetClock_RealTimeMS(realtime) == CHIP_NO_ERROR) + { + mPassphraseSurrogate = std::max(mPassphraseSurrogate, realtime.count()); + } + MatterReportingAttributeChangeCallback(GetEndpointId(), WiFiNetworkManagement::Id, PassphraseSurrogate::Id); + } return CHIP_NO_ERROR; } @@ -113,6 +123,8 @@ CHIP_ERROR WiFiNetworkManagementServer::Read(const ConcreteReadAttributePath & a { case Ssid::Id: return HaveNetworkCredentials() ? aEncoder.Encode(SsidSpan()) : aEncoder.EncodeNull(); + case PassphraseSurrogate::Id: + return HaveNetworkCredentials() ? aEncoder.Encode(mPassphraseSurrogate) : aEncoder.EncodeNull(); } return CHIP_NO_ERROR; } diff --git a/src/app/clusters/wifi-network-management-server/wifi-network-management-server.h b/src/app/clusters/wifi-network-management-server/wifi-network-management-server.h index ce438edf79ff73..c538c585e74899 100644 --- a/src/app/clusters/wifi-network-management-server/wifi-network-management-server.h +++ b/src/app/clusters/wifi-network-management-server/wifi-network-management-server.h @@ -57,6 +57,7 @@ class WiFiNetworkManagementServer : private AttributeAccessInterface, private Co static_assert(std::numeric_limits::max() >= sizeof(mSsid)); ByteSpan SsidSpan() const { return ByteSpan(mSsid, mSsidLen); } + uint64_t mPassphraseSurrogate = 0; Crypto::SensitiveDataBuffer<64> mPassphrase; ByteSpan PassphraseSpan() const { return mPassphrase.Span(); } diff --git a/src/app/tests/suites/certification/PICS.yaml b/src/app/tests/suites/certification/PICS.yaml index cf0159804aeee3..3edf69e6a3b739 100644 --- a/src/app/tests/suites/certification/PICS.yaml +++ b/src/app/tests/suites/certification/PICS.yaml @@ -10199,3 +10199,19 @@ PICS: - label: "Does the device implement the ActiveEndpoints attribute?" id: PWRTL.S.A0001 + + # + # Thread Network Directory Cluster + # + - label: + "Does the device implement the Thread Network Directory cluster as a + server" + id: THNETDIR.S + + # + # Wi-Fi Network Management Cluster + # + - label: + "Does the device implement the Wi-Fi Network Management cluster as a + server" + id: WIFINM.S diff --git a/src/app/tests/suites/certification/Test_TC_THNETDIR_2_1.yaml b/src/app/tests/suites/certification/Test_TC_THNETDIR_2_1.yaml new file mode 100644 index 00000000000000..3a2925dc424175 --- /dev/null +++ b/src/app/tests/suites/certification/Test_TC_THNETDIR_2_1.yaml @@ -0,0 +1,51 @@ +# 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. + +name: "[TC-THNETDIR-2.1] Simple Attributes check with DUT as Server" + +PICS: + - THNETDIR.S + +config: + nodeId: 0x12344321 + cluster: Thread Network Directory + endpoint: 1 + +tests: + - label: "Wait for the commissioned device to be retrieved" + cluster: DelayCommands + command: WaitForCommissionee + arguments: + values: + - name: nodeId + value: nodeId + + - label: "TH reads SupportedFabrics attribute from DUT" + command: readAttribute + endpoint: 0 + cluster: Operational Credentials + attribute: SupportedFabrics + response: + saveAs: supportedFabrics + constraints: + type: int8u + + - label: "TH reads ThreadNetworkTableSize attribute from DUT" + command: readAttribute + attribute: ThreadNetworkTableSize + response: + constraints: + type: int8u + minValue: 10 # assume 5 supported fabrics + # python: value >= 2 * supportedFabrics diff --git a/src/app/tests/suites/certification/Test_TC_THNETDIR_2_2.yaml b/src/app/tests/suites/certification/Test_TC_THNETDIR_2_2.yaml new file mode 100644 index 00000000000000..be0ec89952d25e --- /dev/null +++ b/src/app/tests/suites/certification/Test_TC_THNETDIR_2_2.yaml @@ -0,0 +1,225 @@ +# 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. + +name: "[TC-THNETDIR-2.2] Verification for Add/Remove/Get commands" + +PICS: + - THNETDIR.S + +config: + nodeId: 0x12344321 + cluster: Thread Network Directory + endpoint: 1 + + # Note: TestNetwork* values need to match what's encoded in TestNetworkDataset + TestNetworkDataset: + type: octet_string + defaultValue: "hex:0e080000000000000001000300000f350407fff800020839758ec8144b07fb0708fdf1f1add0797dc00510f366cec7a446bab978d90d27abe38f23030f4f70656e5468726561642d353933380102593804103ca67c969efb0d0c74a4d8ee923b576c0c0402a0f7f8" + TestNetworkExtendedPanId: + type: octet_string + defaultValue: "hex:39758ec8144b07fb" + TestNetworkName: "OpenThread-5938" + TestNetworkChannel: 15 + TestNetworkActiveTimestamp: 1 + +tests: + - label: "Wait for the commissioned device to be retrieved" + cluster: DelayCommands + command: WaitForCommissionee + arguments: + values: + - name: nodeId + value: nodeId + + - label: "TH reads ThreadNetworks attribute from DUT" + command: readAttribute + attribute: ThreadNetworks + response: + saveAs: initialNetworks + constraints: + type: list + + - label: "TH reads PreferredExtendedPanID attribute from DUT" + command: readAttribute + attribute: PreferredExtendedPanID + response: + saveAs: initialPreferredExtendedPanID + constraints: + type: octet_string + minLength: 8 + maxLength: 8 + notValue: TestNetworkExtendedPanId + + - label: + "TH writes ExtendedPanID from TestNetwork to PreferredExtendedPanID on + DUT" + command: writeAttribute + attribute: PreferredExtendedPanID + arguments: + value: TestNetworkExtendedPanId + response: + error: CONSTRAINT_ERROR # TestNetwork is not in ThreadNetworks + + - label: + "TH reads PreferredExtendedPanID attribute from DUT, verifying that + the value did not change" + command: readAttribute + attribute: PreferredExtendedPanID + response: + value: initialPreferredExtendedPanID + + - label: + "TH sends GetOperationalDataset command to DUT with ExtendedPanID of + TestNetwork" + command: GetOperationalDataset + arguments: + values: + - name: ExtendedPanID + value: TestNetworkExtendedPanId + response: + error: NOT_FOUND + + # TODO: Currently fails with darwin-framework-tool because it automatically performs a timed invoke + # - label: "TH sends AddNetwork command to DUT without a timed interaction" + # command: AddNetwork + # arguments: + # values: + # - name: OperationalDataset + # value: TestNetworkDataset + # response: + # error: NEEDS_TIMED_INTERACTION + + - label: "TH sends AddNetwork command to DUT with TestNetwork dataset" + command: AddNetwork + timedInteractionTimeoutMs: 2000 + arguments: + values: + - name: OperationalDataset + value: TestNetworkDataset + + - label: + "TH reads ThreadNetworks attribute from DUT, verifying that the + network has been added" + command: readAttribute + attribute: ThreadNetworks + response: + constraints: + type: list + # python: | + # # Split the list into test (our TestNetwork) and rest (everything else) + # test = next((n for n in value if n['ExtendedPanID'] == TestNetworkExtendedPanId), None) + # rest = [n for n in value if n != test] + # # Check test has the expected values and rest == initialNetworks (ignoring order) + # return (test is not None and + # test['NetworkName'] == TestNetworkName and + # test['Channel'] == TestNetworkChannel and + # test['ActiveTimestamp'] == TestNetworkActiveTimestamp and + # len(value) == len(initialNetworks) + 1 and + # len(rest) == len(initialNetworks) and + # all(n in initialNetworks for n in rest)) + + - label: + "TH sends GetOperationalDataset command to DUT with ExtendedPanID from + TestNetwork" + command: GetOperationalDataset + arguments: + values: + - name: ExtendedPanID + value: TestNetworkExtendedPanId + response: + values: + - name: OperationalDataset + value: TestNetworkDataset + + - label: + "TH writes ExtendedPanID from TestNetwork to PreferredExtendedPanID on + DUT" + command: writeAttribute + attribute: PreferredExtendedPanID + arguments: + value: TestNetworkExtendedPanId + + - label: + "TH reads PreferredExtendedPanID attribute from DUT, verifying that + the value was written" + command: readAttribute + attribute: PreferredExtendedPanID + response: + value: TestNetworkExtendedPanId + + # TODO: Currently fails with darwin-framework-tool because it automatically performs a timed invoke + # - label: "TH sends RemoveNetwork command to DUT without a timed interaction" + # command: RemoveNetwork + # arguments: + # values: + # - name: ExtendedPanID + # value: TestNetworkExtendedPanId + # response: + # error: NEEDS_TIMED_INTERACTION + + - label: + "TH sends RemoveNetwork command to DUT with ExtendedPanID of + TestNetwork while it is the preferred network" + command: RemoveNetwork + timedInteractionTimeoutMs: 2000 + arguments: + values: + - name: ExtendedPanID + value: TestNetworkExtendedPanId + response: + error: CONSTRAINT_ERROR # Preferred network cannot be removed + + - label: "TH writes null to PreferredExtendedPanID on DUT" + command: writeAttribute + attribute: PreferredExtendedPanID + arguments: + value: null + + - label: + "TH reads PreferredExtendedPanID attribute from DUT, verifying that + the value was cleared" + command: readAttribute + attribute: PreferredExtendedPanID + response: + value: null + + - label: + "TH sends RemoveNetwork command to DUT with ExtendedPanID of + TestNetwork" + command: RemoveNetwork + timedInteractionTimeoutMs: 2000 + arguments: + values: + - name: ExtendedPanID + value: TestNetworkExtendedPanId + + - label: + "TH reads ThreadNetworks attribute from DUT, verifying that the + network was removed" + command: readAttribute + attribute: ThreadNetworks + response: + constraints: + type: list + # python: | + # # value == initialNetworks (ignoring order) + # return (len(value) == len(initialNetworks) and + # all(n in initialNetworks for n in value)) + + - label: + "TH writes PreferredExtendedPanID to DUT, restoring the initial value" + command: writeAttribute + attribute: PreferredExtendedPanID + arguments: + value: initialPreferredExtendedPanID diff --git a/src/app/tests/suites/certification/Test_TC_WIFINM_2_1.yaml b/src/app/tests/suites/certification/Test_TC_WIFINM_2_1.yaml new file mode 100644 index 00000000000000..0f9f71157de0ea --- /dev/null +++ b/src/app/tests/suites/certification/Test_TC_WIFINM_2_1.yaml @@ -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. + +name: "[TC-WIFINM-2.1] Attributes and commands with DUT as Server" + +PICS: + - WIFINM.S + +config: + nodeId: 0x12344321 + cluster: WiFi Network Management + endpoint: 1 + +# Note: This test assumes the DUT has an active Wi-Fi network, i.e. +# SSID is not null and NetworkPassphraseRequest returns a passphrase. +tests: + - label: "Wait for the commissioned device to be retrieved" + cluster: DelayCommands + command: WaitForCommissionee + arguments: + values: + - name: nodeId + value: nodeId + + - label: "TH reads the SSID attribute from the DUT" + command: readAttribute + attribute: SSID + response: + constraints: + type: octet_string + hasValue: true + minLength: 1 + maxLength: 32 + + - label: "TH reads the PassphraseSurrogate attribute from the DUT" + command: readAttribute + attribute: PassphraseSurrogate + response: + constraints: + type: int64u + hasValue: true + + - label: "TH sends the NetworkPassphraseRequest command to the DUT" + command: NetworkPassphraseRequest + response: + values: + - name: Passphrase + constraints: + type: octet_string + hasValue: true + minLength: 8 + maxLength: 64 diff --git a/src/app/tests/suites/certification/ci-pics-values b/src/app/tests/suites/certification/ci-pics-values index 207999a74778b1..9ea99c627f16f4 100644 --- a/src/app/tests/suites/certification/ci-pics-values +++ b/src/app/tests/suites/certification/ci-pics-values @@ -2987,4 +2987,10 @@ PWRTL.S.A0001=1 PWRTL.S.F00=0 PWRTL.S.F01=0 PWRTL.S.F02=1 -PWRTL.S.F03=1 \ No newline at end of file +PWRTL.S.F03=1 + +# Thread Network Directory Cluster +THNETDIR.S=1 + +# Wi-Fi Network Management Cluster +WIFINM.S=1 diff --git a/src/app/zap-templates/zcl/data-model/chip/thread-network-directory-cluster.xml b/src/app/zap-templates/zcl/data-model/chip/thread-network-directory-cluster.xml index e97cbc931e6b0e..3a6445b15bbad3 100644 --- a/src/app/zap-templates/zcl/data-model/chip/thread-network-directory-cluster.xml +++ b/src/app/zap-templates/zcl/data-model/chip/thread-network-directory-cluster.xml @@ -17,7 +17,7 @@ limitations under the License. - + @@ -25,7 +25,7 @@ limitations under the License. - + Network Infrastructure Thread Network Directory 0x0453 @@ -59,7 +59,7 @@ limitations under the License. - + Retrieves a Thread Operational Dataset from the ThreadNetworks list. diff --git a/src/app/zap-templates/zcl/data-model/chip/wifi-network-management-cluster.xml b/src/app/zap-templates/zcl/data-model/chip/wifi-network-management-cluster.xml index f05faad4dae4d2..8c8b4d40c3abdd 100644 --- a/src/app/zap-templates/zcl/data-model/chip/wifi-network-management-cluster.xml +++ b/src/app/zap-templates/zcl/data-model/chip/wifi-network-management-cluster.xml @@ -17,7 +17,7 @@ limitations under the License. - + Network Infrastructure Wi-Fi Network Management 0x0451 @@ -30,11 +30,15 @@ limitations under the License. - SSID + SSID + + PassphraseSurrogate + + Request the current WPA-Personal passphrase or PSK associated with the managed Wi-Fi network. - + This is the response to a NetworkPassphraseRequest. diff --git a/src/app/zap-templates/zcl/zcl-with-test-extensions.json b/src/app/zap-templates/zcl/zcl-with-test-extensions.json index 2207303e1ab7b7..6769a64824f046 100644 --- a/src/app/zap-templates/zcl/zcl-with-test-extensions.json +++ b/src/app/zap-templates/zcl/zcl-with-test-extensions.json @@ -656,7 +656,7 @@ "ClusterRevision" ], "Water Heater Mode": ["SupportedModes", "CurrentMode", "FeatureMap"], - "Wi-Fi Network Management": ["SSID"], + "Wi-Fi Network Management": ["SSID", "PassphraseSurrogate"], "Thread Network Directory": [ "PreferredExtendedPanID", "ThreadNetworks", diff --git a/src/app/zap-templates/zcl/zcl.json b/src/app/zap-templates/zcl/zcl.json index c2bcc194e8611f..887707ee86b37a 100644 --- a/src/app/zap-templates/zcl/zcl.json +++ b/src/app/zap-templates/zcl/zcl.json @@ -654,7 +654,7 @@ "ClusterRevision" ], "Water Heater Mode": ["SupportedModes", "CurrentMode", "FeatureMap"], - "Wi-Fi Network Management": ["SSID"], + "Wi-Fi Network Management": ["SSID", "PassphraseSurrogate"], "Thread Network Directory": [ "PreferredExtendedPanID", "ThreadNetworks", diff --git a/src/controller/data_model/controller-clusters.matter b/src/controller/data_model/controller-clusters.matter index dd93ed7fe2cc9b..9e841b2376ea93 100644 --- a/src/controller/data_model/controller-clusters.matter +++ b/src/controller/data_model/controller-clusters.matter @@ -8121,10 +8121,11 @@ cluster RadonConcentrationMeasurement = 1071 { } /** Functionality to retrieve operational information about a managed Wi-Fi network. */ -cluster WiFiNetworkManagement = 1105 { +provisional cluster WiFiNetworkManagement = 1105 { revision 1; - readonly attribute nullable octet_string<32> ssid = 1; + readonly attribute nullable octet_string<32> ssid = 0; + readonly attribute access(read: manage) nullable int64u passphraseSurrogate = 1; readonly attribute command_id generatedCommandList[] = 65528; readonly attribute command_id acceptedCommandList[] = 65529; readonly attribute event_id eventList[] = 65530; @@ -8137,7 +8138,7 @@ cluster WiFiNetworkManagement = 1105 { } /** Request the current WPA-Personal passphrase or PSK associated with the managed Wi-Fi network. */ - command access(invoke: administer) NetworkPassphraseRequest(): NetworkPassphraseResponse = 0; + command access(invoke: manage) NetworkPassphraseRequest(): NetworkPassphraseResponse = 0; } /** Manage the Thread network of Thread Border Router */ @@ -8184,7 +8185,7 @@ provisional cluster ThreadBorderRouterManagement = 1106 { } /** Manages the names and credentials of Thread networks visible to the user. */ -cluster ThreadNetworkDirectory = 1107 { +provisional cluster ThreadNetworkDirectory = 1107 { revision 1; struct ThreadNetworkStruct { @@ -8225,7 +8226,7 @@ cluster ThreadNetworkDirectory = 1107 { /** Removes an entry from the ThreadNetworks list. */ timed command access(invoke: manage) RemoveNetwork(RemoveNetworkRequest): DefaultSuccess = 1; /** Retrieves a Thread Operational Dataset from the ThreadNetworks list. */ - timed command GetOperationalDataset(GetOperationalDatasetRequest): OperationalDatasetResponse = 2; + command GetOperationalDataset(GetOperationalDatasetRequest): OperationalDatasetResponse = 2; } /** This cluster provides an interface for managing low power mode on a device that supports the Wake On LAN protocol. */ diff --git a/src/controller/java/generated/java/chip/devicecontroller/ChipClusters.java b/src/controller/java/generated/java/chip/devicecontroller/ChipClusters.java index e11a47a23a8c7c..cbc1b912736048 100644 --- a/src/controller/java/generated/java/chip/devicecontroller/ChipClusters.java +++ b/src/controller/java/generated/java/chip/devicecontroller/ChipClusters.java @@ -54135,7 +54135,8 @@ public void onSuccess(byte[] tlv) { public static class WiFiNetworkManagementCluster extends BaseChipCluster { public static final long CLUSTER_ID = 1105L; - private static final long SSID_ATTRIBUTE_ID = 1L; + private static final long SSID_ATTRIBUTE_ID = 0L; + private static final long PASSPHRASE_SURROGATE_ATTRIBUTE_ID = 1L; private static final long GENERATED_COMMAND_LIST_ATTRIBUTE_ID = 65528L; private static final long ACCEPTED_COMMAND_LIST_ATTRIBUTE_ID = 65529L; private static final long EVENT_LIST_ATTRIBUTE_ID = 65530L; @@ -54187,6 +54188,10 @@ public interface SsidAttributeCallback extends BaseAttributeCallback { void onSuccess(@Nullable byte[] value); } + public interface PassphraseSurrogateAttributeCallback extends BaseAttributeCallback { + void onSuccess(@Nullable Long value); + } + public interface GeneratedCommandListAttributeCallback extends BaseAttributeCallback { void onSuccess(List value); } @@ -54229,6 +54234,32 @@ public void onSuccess(byte[] tlv) { }, SSID_ATTRIBUTE_ID, minInterval, maxInterval); } + public void readPassphraseSurrogateAttribute( + PassphraseSurrogateAttributeCallback callback) { + ChipAttributePath path = ChipAttributePath.newInstance(endpointId, clusterId, PASSPHRASE_SURROGATE_ATTRIBUTE_ID); + + readAttribute(new ReportCallbackImpl(callback, path) { + @Override + public void onSuccess(byte[] tlv) { + @Nullable Long value = ChipTLVValueDecoder.decodeAttributeValue(path, tlv); + callback.onSuccess(value); + } + }, PASSPHRASE_SURROGATE_ATTRIBUTE_ID, true); + } + + public void subscribePassphraseSurrogateAttribute( + PassphraseSurrogateAttributeCallback callback, int minInterval, int maxInterval) { + ChipAttributePath path = ChipAttributePath.newInstance(endpointId, clusterId, PASSPHRASE_SURROGATE_ATTRIBUTE_ID); + + subscribeAttribute(new ReportCallbackImpl(callback, path) { + @Override + public void onSuccess(byte[] tlv) { + @Nullable Long value = ChipTLVValueDecoder.decodeAttributeValue(path, tlv); + callback.onSuccess(value); + } + }, PASSPHRASE_SURROGATE_ATTRIBUTE_ID, minInterval, maxInterval); + } + public void readGeneratedCommandListAttribute( GeneratedCommandListAttributeCallback callback) { ChipAttributePath path = ChipAttributePath.newInstance(endpointId, clusterId, GENERATED_COMMAND_LIST_ATTRIBUTE_ID); @@ -54875,6 +54906,9 @@ public void onResponse(StructType invokeStructValue) { }}, commandId, commandArgs, timedInvokeTimeoutMs); } + public void getOperationalDataset(OperationalDatasetResponseCallback callback, byte[] extendedPanID) { + getOperationalDataset(callback, extendedPanID, 0); + } public void getOperationalDataset(OperationalDatasetResponseCallback callback, byte[] extendedPanID, int timedInvokeTimeoutMs) { final long commandId = 2L; diff --git a/src/controller/java/generated/java/chip/devicecontroller/ClusterIDMapping.java b/src/controller/java/generated/java/chip/devicecontroller/ClusterIDMapping.java index ab20bdcaa301e9..499617e5cf027e 100644 --- a/src/controller/java/generated/java/chip/devicecontroller/ClusterIDMapping.java +++ b/src/controller/java/generated/java/chip/devicecontroller/ClusterIDMapping.java @@ -14719,7 +14719,8 @@ public long getID() { } public enum Attribute { - Ssid(1L), + Ssid(0L), + PassphraseSurrogate(1L), GeneratedCommandList(65528L), AcceptedCommandList(65529L), EventList(65530L), diff --git a/src/controller/java/generated/java/chip/devicecontroller/ClusterInfoMapping.java b/src/controller/java/generated/java/chip/devicecontroller/ClusterInfoMapping.java index ca3d74f1ac3797..17d394d71f5d35 100644 --- a/src/controller/java/generated/java/chip/devicecontroller/ClusterInfoMapping.java +++ b/src/controller/java/generated/java/chip/devicecontroller/ClusterInfoMapping.java @@ -17855,6 +17855,27 @@ public void onError(Exception ex) { } } + public static class DelegatedWiFiNetworkManagementClusterPassphraseSurrogateAttributeCallback implements ChipClusters.WiFiNetworkManagementCluster.PassphraseSurrogateAttributeCallback, DelegatedClusterCallback { + private ClusterCommandCallback callback; + @Override + public void setCallbackDelegate(ClusterCommandCallback callback) { + this.callback = callback; + } + + @Override + public void onSuccess(@Nullable Long value) { + Map responseValues = new LinkedHashMap<>(); + CommandResponseInfo commandResponseInfo = new CommandResponseInfo("value", "Long"); + responseValues.put(commandResponseInfo, value); + callback.onSuccess(responseValues); + } + + @Override + public void onError(Exception ex) { + callback.onFailure(ex); + } + } + public static class DelegatedWiFiNetworkManagementClusterGeneratedCommandListAttributeCallback implements ChipClusters.WiFiNetworkManagementCluster.GeneratedCommandListAttributeCallback, DelegatedClusterCallback { private ClusterCommandCallback callback; @Override @@ -27842,7 +27863,7 @@ public Map> getCommandMap() { , (byte[]) commandArguments.get("extendedPanID") - , 10000); + ); }, () -> new DelegatedThreadNetworkDirectoryClusterOperationalDatasetResponseCallback(), threadNetworkDirectorygetOperationalDatasetCommandParams diff --git a/src/controller/java/generated/java/chip/devicecontroller/ClusterReadMapping.java b/src/controller/java/generated/java/chip/devicecontroller/ClusterReadMapping.java index 45d0e3037631fb..0ae1a3394ee03f 100644 --- a/src/controller/java/generated/java/chip/devicecontroller/ClusterReadMapping.java +++ b/src/controller/java/generated/java/chip/devicecontroller/ClusterReadMapping.java @@ -16938,6 +16938,17 @@ private static Map readWiFiNetworkManagementInteraction readWiFiNetworkManagementSsidCommandParams ); result.put("readSsidAttribute", readWiFiNetworkManagementSsidAttributeInteractionInfo); + Map readWiFiNetworkManagementPassphraseSurrogateCommandParams = new LinkedHashMap(); + InteractionInfo readWiFiNetworkManagementPassphraseSurrogateAttributeInteractionInfo = new InteractionInfo( + (cluster, callback, commandArguments) -> { + ((ChipClusters.WiFiNetworkManagementCluster) cluster).readPassphraseSurrogateAttribute( + (ChipClusters.WiFiNetworkManagementCluster.PassphraseSurrogateAttributeCallback) callback + ); + }, + () -> new ClusterInfoMapping.DelegatedWiFiNetworkManagementClusterPassphraseSurrogateAttributeCallback(), + readWiFiNetworkManagementPassphraseSurrogateCommandParams + ); + result.put("readPassphraseSurrogateAttribute", readWiFiNetworkManagementPassphraseSurrogateAttributeInteractionInfo); Map readWiFiNetworkManagementGeneratedCommandListCommandParams = new LinkedHashMap(); InteractionInfo readWiFiNetworkManagementGeneratedCommandListAttributeInteractionInfo = new InteractionInfo( (cluster, callback, commandArguments) -> { diff --git a/src/controller/java/generated/java/matter/controller/cluster/clusters/ThreadNetworkDirectoryCluster.kt b/src/controller/java/generated/java/matter/controller/cluster/clusters/ThreadNetworkDirectoryCluster.kt index e479f0c79ef0f2..b5af2b1db2895a 100644 --- a/src/controller/java/generated/java/matter/controller/cluster/clusters/ThreadNetworkDirectoryCluster.kt +++ b/src/controller/java/generated/java/matter/controller/cluster/clusters/ThreadNetworkDirectoryCluster.kt @@ -154,7 +154,7 @@ class ThreadNetworkDirectoryCluster( suspend fun getOperationalDataset( extendedPanID: ByteArray, - timedInvokeTimeout: Duration, + timedInvokeTimeout: Duration? = null, ): OperationalDatasetResponse { val commandId: UInt = 2u diff --git a/src/controller/java/generated/java/matter/controller/cluster/clusters/WiFiNetworkManagementCluster.kt b/src/controller/java/generated/java/matter/controller/cluster/clusters/WiFiNetworkManagementCluster.kt index 32f8edab8d7b69..48efb1cea1f4b2 100644 --- a/src/controller/java/generated/java/matter/controller/cluster/clusters/WiFiNetworkManagementCluster.kt +++ b/src/controller/java/generated/java/matter/controller/cluster/clusters/WiFiNetworkManagementCluster.kt @@ -55,6 +55,16 @@ class WiFiNetworkManagementCluster( object SubscriptionEstablished : SsidAttributeSubscriptionState() } + class PassphraseSurrogateAttribute(val value: ULong?) + + sealed class PassphraseSurrogateAttributeSubscriptionState { + data class Success(val value: ULong?) : PassphraseSurrogateAttributeSubscriptionState() + + data class Error(val exception: Exception) : PassphraseSurrogateAttributeSubscriptionState() + + object SubscriptionEstablished : PassphraseSurrogateAttributeSubscriptionState() + } + class GeneratedCommandListAttribute(val value: List) sealed class GeneratedCommandListAttributeSubscriptionState { @@ -139,7 +149,7 @@ class WiFiNetworkManagementCluster( } suspend fun readSsidAttribute(): SsidAttribute { - val ATTRIBUTE_ID: UInt = 1u + val ATTRIBUTE_ID: UInt = 0u val attributePath = AttributePath(endpointId = endpointId, clusterId = CLUSTER_ID, attributeId = ATTRIBUTE_ID) @@ -179,7 +189,7 @@ class WiFiNetworkManagementCluster( minInterval: Int, maxInterval: Int, ): Flow { - val ATTRIBUTE_ID: UInt = 1u + val ATTRIBUTE_ID: UInt = 0u val attributePaths = listOf( AttributePath(endpointId = endpointId, clusterId = CLUSTER_ID, attributeId = ATTRIBUTE_ID) @@ -231,6 +241,101 @@ class WiFiNetworkManagementCluster( } } + suspend fun readPassphraseSurrogateAttribute(): PassphraseSurrogateAttribute { + val ATTRIBUTE_ID: UInt = 1u + + val attributePath = + AttributePath(endpointId = endpointId, clusterId = CLUSTER_ID, attributeId = ATTRIBUTE_ID) + + val readRequest = ReadRequest(eventPaths = emptyList(), attributePaths = listOf(attributePath)) + + val response = controller.read(readRequest) + + if (response.successes.isEmpty()) { + logger.log(Level.WARNING, "Read command failed") + throw IllegalStateException("Read command failed with failures: ${response.failures}") + } + + logger.log(Level.FINE, "Read command succeeded") + + val attributeData = + response.successes.filterIsInstance().firstOrNull { + it.path.attributeId == ATTRIBUTE_ID + } + + requireNotNull(attributeData) { "Passphrasesurrogate attribute not found in response" } + + // Decode the TLV data into the appropriate type + val tlvReader = TlvReader(attributeData.data) + val decodedValue: ULong? = + if (!tlvReader.isNull()) { + tlvReader.getULong(AnonymousTag) + } else { + tlvReader.getNull(AnonymousTag) + null + } + + return PassphraseSurrogateAttribute(decodedValue) + } + + suspend fun subscribePassphraseSurrogateAttribute( + minInterval: Int, + maxInterval: Int, + ): Flow { + val ATTRIBUTE_ID: UInt = 1u + val attributePaths = + listOf( + AttributePath(endpointId = endpointId, clusterId = CLUSTER_ID, attributeId = ATTRIBUTE_ID) + ) + + val subscribeRequest: SubscribeRequest = + SubscribeRequest( + eventPaths = emptyList(), + attributePaths = attributePaths, + minInterval = Duration.ofSeconds(minInterval.toLong()), + maxInterval = Duration.ofSeconds(maxInterval.toLong()), + ) + + return controller.subscribe(subscribeRequest).transform { subscriptionState -> + when (subscriptionState) { + is SubscriptionState.SubscriptionErrorNotification -> { + emit( + PassphraseSurrogateAttributeSubscriptionState.Error( + Exception( + "Subscription terminated with error code: ${subscriptionState.terminationCause}" + ) + ) + ) + } + is SubscriptionState.NodeStateUpdate -> { + val attributeData = + subscriptionState.updateState.successes + .filterIsInstance() + .firstOrNull { it.path.attributeId == ATTRIBUTE_ID } + + requireNotNull(attributeData) { + "Passphrasesurrogate attribute not found in Node State update" + } + + // Decode the TLV data into the appropriate type + val tlvReader = TlvReader(attributeData.data) + val decodedValue: ULong? = + if (!tlvReader.isNull()) { + tlvReader.getULong(AnonymousTag) + } else { + tlvReader.getNull(AnonymousTag) + null + } + + decodedValue?.let { emit(PassphraseSurrogateAttributeSubscriptionState.Success(it)) } + } + SubscriptionState.SubscriptionEstablished -> { + emit(PassphraseSurrogateAttributeSubscriptionState.SubscriptionEstablished) + } + } + } + } + suspend fun readGeneratedCommandListAttribute(): GeneratedCommandListAttribute { val ATTRIBUTE_ID: UInt = 65528u diff --git a/src/controller/java/zap-generated/CHIPAttributeTLVValueDecoder.cpp b/src/controller/java/zap-generated/CHIPAttributeTLVValueDecoder.cpp index b6702569d994d9..aecebd1bd64991 100644 --- a/src/controller/java/zap-generated/CHIPAttributeTLVValueDecoder.cpp +++ b/src/controller/java/zap-generated/CHIPAttributeTLVValueDecoder.cpp @@ -38400,6 +38400,29 @@ jobject DecodeAttributeValue(const app::ConcreteAttributePath & aPath, TLV::TLVR } return value; } + case Attributes::PassphraseSurrogate::Id: { + using TypeInfo = Attributes::PassphraseSurrogate::TypeInfo; + TypeInfo::DecodableType cppValue; + *aError = app::DataModel::Decode(aReader, cppValue); + if (*aError != CHIP_NO_ERROR) + { + return nullptr; + } + jobject value; + if (cppValue.IsNull()) + { + value = nullptr; + } + else + { + std::string valueClassName = "java/lang/Long"; + std::string valueCtorSignature = "(J)V"; + jlong jnivalue = static_cast(cppValue.Value()); + chip::JniReferences::GetInstance().CreateBoxedObject(valueClassName.c_str(), valueCtorSignature.c_str(), + jnivalue, value); + } + return value; + } case Attributes::GeneratedCommandList::Id: { using TypeInfo = Attributes::GeneratedCommandList::TypeInfo; TypeInfo::DecodableType cppValue; diff --git a/src/controller/python/chip/clusters/CHIPClusters.py b/src/controller/python/chip/clusters/CHIPClusters.py index 6621bbc4bea2a6..8d40c59ba69a82 100644 --- a/src/controller/python/chip/clusters/CHIPClusters.py +++ b/src/controller/python/chip/clusters/CHIPClusters.py @@ -11828,12 +11828,18 @@ class ChipClusters: }, }, "attributes": { - 0x00000001: { + 0x00000000: { "attributeName": "Ssid", - "attributeId": 0x00000001, + "attributeId": 0x00000000, "type": "bytes", "reportable": True, }, + 0x00000001: { + "attributeName": "PassphraseSurrogate", + "attributeId": 0x00000001, + "type": "int", + "reportable": True, + }, 0x0000FFF8: { "attributeName": "GeneratedCommandList", "attributeId": 0x0000FFF8, diff --git a/src/controller/python/chip/clusters/Objects.py b/src/controller/python/chip/clusters/Objects.py index fe9a008e11066e..ed97e35be54283 100644 --- a/src/controller/python/chip/clusters/Objects.py +++ b/src/controller/python/chip/clusters/Objects.py @@ -41593,7 +41593,8 @@ class WiFiNetworkManagement(Cluster): def descriptor(cls) -> ClusterObjectDescriptor: return ClusterObjectDescriptor( Fields=[ - ClusterObjectFieldDescriptor(Label="ssid", Tag=0x00000001, Type=typing.Union[Nullable, bytes]), + ClusterObjectFieldDescriptor(Label="ssid", Tag=0x00000000, Type=typing.Union[Nullable, bytes]), + ClusterObjectFieldDescriptor(Label="passphraseSurrogate", Tag=0x00000001, Type=typing.Union[Nullable, uint]), ClusterObjectFieldDescriptor(Label="generatedCommandList", Tag=0x0000FFF8, Type=typing.List[uint]), ClusterObjectFieldDescriptor(Label="acceptedCommandList", Tag=0x0000FFF9, Type=typing.List[uint]), ClusterObjectFieldDescriptor(Label="eventList", Tag=0x0000FFFA, Type=typing.List[uint]), @@ -41603,6 +41604,7 @@ def descriptor(cls) -> ClusterObjectDescriptor: ]) ssid: 'typing.Union[Nullable, bytes]' = None + passphraseSurrogate: 'typing.Union[Nullable, uint]' = None generatedCommandList: 'typing.List[uint]' = None acceptedCommandList: 'typing.List[uint]' = None eventList: 'typing.List[uint]' = None @@ -41649,7 +41651,7 @@ def cluster_id(cls) -> int: @ChipUtility.classproperty def attribute_id(cls) -> int: - return 0x00000001 + return 0x00000000 @ChipUtility.classproperty def attribute_type(cls) -> ClusterObjectFieldDescriptor: @@ -41657,6 +41659,22 @@ def attribute_type(cls) -> ClusterObjectFieldDescriptor: value: 'typing.Union[Nullable, bytes]' = NullValue + @dataclass + class PassphraseSurrogate(ClusterAttributeDescriptor): + @ChipUtility.classproperty + def cluster_id(cls) -> int: + return 0x00000451 + + @ChipUtility.classproperty + def attribute_id(cls) -> int: + return 0x00000001 + + @ChipUtility.classproperty + def attribute_type(cls) -> ClusterObjectFieldDescriptor: + return ClusterObjectFieldDescriptor(Type=typing.Union[Nullable, uint]) + + value: 'typing.Union[Nullable, uint]' = NullValue + @dataclass class GeneratedCommandList(ClusterAttributeDescriptor): @ChipUtility.classproperty @@ -42148,10 +42166,6 @@ def descriptor(cls) -> ClusterObjectDescriptor: ClusterObjectFieldDescriptor(Label="extendedPanID", Tag=0, Type=bytes), ]) - @ChipUtility.classproperty - def must_use_timed_invoke(cls) -> bool: - return True - extendedPanID: 'bytes' = b"" @dataclass diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRAttributeSpecifiedCheck.mm b/src/darwin/Framework/CHIP/zap-generated/MTRAttributeSpecifiedCheck.mm index 204d15937b23ca..bcd496f629f2a6 100644 --- a/src/darwin/Framework/CHIP/zap-generated/MTRAttributeSpecifiedCheck.mm +++ b/src/darwin/Framework/CHIP/zap-generated/MTRAttributeSpecifiedCheck.mm @@ -5430,6 +5430,9 @@ static BOOL AttributeIsSpecifiedInWiFiNetworkManagementCluster(AttributeId aAttr case Attributes::Ssid::Id: { return YES; } + case Attributes::PassphraseSurrogate::Id: { + return YES; + } case Attributes::GeneratedCommandList::Id: { return YES; } diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRAttributeTLVValueDecoder.mm b/src/darwin/Framework/CHIP/zap-generated/MTRAttributeTLVValueDecoder.mm index ca3cc6c5e620eb..c63a8ffbfd4aaa 100644 --- a/src/darwin/Framework/CHIP/zap-generated/MTRAttributeTLVValueDecoder.mm +++ b/src/darwin/Framework/CHIP/zap-generated/MTRAttributeTLVValueDecoder.mm @@ -15670,6 +15670,21 @@ static id _Nullable DecodeAttributeValueForWiFiNetworkManagementCluster(Attribut } return value; } + case Attributes::PassphraseSurrogate::Id: { + using TypeInfo = Attributes::PassphraseSurrogate::TypeInfo; + TypeInfo::DecodableType cppValue; + *aError = DataModel::Decode(aReader, cppValue); + if (*aError != CHIP_NO_ERROR) { + return nil; + } + NSNumber * _Nullable value; + if (cppValue.IsNull()) { + value = nil; + } else { + value = [NSNumber numberWithUnsignedLongLong:cppValue.Value()]; + } + return value; + } default: { break; } diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters.h b/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters.h index 2bcdb3fbc3919e..c38d458c5f379d 100644 --- a/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters.h +++ b/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters.h @@ -13348,6 +13348,12 @@ MTR_PROVISIONALLY_AVAILABLE reportHandler:(void (^)(NSData * _Nullable value, NSError * _Nullable error))reportHandler MTR_PROVISIONALLY_AVAILABLE; + (void)readAttributeSSIDWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer endpoint:(NSNumber *)endpoint queue:(dispatch_queue_t)queue completion:(void (^)(NSData * _Nullable value, NSError * _Nullable error))completion MTR_PROVISIONALLY_AVAILABLE; +- (void)readAttributePassphraseSurrogateWithCompletion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion MTR_PROVISIONALLY_AVAILABLE; +- (void)subscribeAttributePassphraseSurrogateWithParams:(MTRSubscribeParams *)params + subscriptionEstablished:(MTRSubscriptionEstablishedHandler _Nullable)subscriptionEstablished + reportHandler:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))reportHandler MTR_PROVISIONALLY_AVAILABLE; ++ (void)readAttributePassphraseSurrogateWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer endpoint:(NSNumber *)endpoint queue:(dispatch_queue_t)queue completion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion MTR_PROVISIONALLY_AVAILABLE; + - (void)readAttributeGeneratedCommandListWithCompletion:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))completion MTR_PROVISIONALLY_AVAILABLE; - (void)subscribeAttributeGeneratedCommandListWithParams:(MTRSubscribeParams *)params subscriptionEstablished:(MTRSubscriptionEstablishedHandler _Nullable)subscriptionEstablished diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters.mm b/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters.mm index 641fea65515da4..703edcf09bf740 100644 --- a/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters.mm +++ b/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters.mm @@ -94495,6 +94495,42 @@ + (void)readAttributeSSIDWithClusterStateCache:(MTRClusterStateCacheContainer *) completion:completion]; } +- (void)readAttributePassphraseSurrogateWithCompletion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion +{ + using TypeInfo = WiFiNetworkManagement::Attributes::PassphraseSurrogate::TypeInfo; + [self.device _readKnownAttributeWithEndpointID:self.endpointID + clusterID:@(TypeInfo::GetClusterId()) + attributeID:@(TypeInfo::GetAttributeId()) + params:nil + queue:self.callbackQueue + completion:completion]; +} + +- (void)subscribeAttributePassphraseSurrogateWithParams:(MTRSubscribeParams * _Nonnull)params + subscriptionEstablished:(MTRSubscriptionEstablishedHandler _Nullable)subscriptionEstablished + reportHandler:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))reportHandler +{ + using TypeInfo = WiFiNetworkManagement::Attributes::PassphraseSurrogate::TypeInfo; + [self.device _subscribeToKnownAttributeWithEndpointID:self.endpointID + clusterID:@(TypeInfo::GetClusterId()) + attributeID:@(TypeInfo::GetAttributeId()) + params:params + queue:self.callbackQueue + reportHandler:reportHandler + subscriptionEstablished:subscriptionEstablished]; +} + ++ (void)readAttributePassphraseSurrogateWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer endpoint:(NSNumber *)endpoint queue:(dispatch_queue_t)queue completion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion +{ + using TypeInfo = WiFiNetworkManagement::Attributes::PassphraseSurrogate::TypeInfo; + [clusterStateCacheContainer + _readKnownCachedAttributeWithEndpointID:static_cast([endpoint unsignedShortValue]) + clusterID:TypeInfo::GetClusterId() + attributeID:TypeInfo::GetAttributeId() + queue:queue + completion:completion]; +} + - (void)readAttributeGeneratedCommandListWithCompletion:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))completion { using TypeInfo = WiFiNetworkManagement::Attributes::GeneratedCommandList::TypeInfo; @@ -95286,9 +95322,6 @@ - (void)getOperationalDatasetWithParams:(MTRThreadNetworkDirectoryClusterGetOper }; auto * timedInvokeTimeoutMs = params.timedInvokeTimeoutMs; - if (timedInvokeTimeoutMs == nil) { - timedInvokeTimeoutMs = @(MTR_DEFAULT_TIMED_INTERACTION_TIMEOUT_MS); - } using RequestType = ThreadNetworkDirectory::Commands::GetOperationalDataset::Type; [self.device _invokeKnownCommandWithEndpointID:self.endpointID diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRClusterConstants.h b/src/darwin/Framework/CHIP/zap-generated/MTRClusterConstants.h index 2178edd403cfe4..3dace9cd879a48 100644 --- a/src/darwin/Framework/CHIP/zap-generated/MTRClusterConstants.h +++ b/src/darwin/Framework/CHIP/zap-generated/MTRClusterConstants.h @@ -4412,7 +4412,8 @@ typedef NS_ENUM(uint32_t, MTRAttributeIDType) { MTRAttributeIDTypeClusterRadonConcentrationMeasurementAttributeClusterRevisionID MTR_AVAILABLE(ios(17.6), macos(14.6), watchos(10.6), tvos(17.6)) = MTRAttributeIDTypeGlobalAttributeClusterRevisionID, // Cluster WiFiNetworkManagement attributes - MTRAttributeIDTypeClusterWiFiNetworkManagementAttributeSSIDID MTR_PROVISIONALLY_AVAILABLE = 0x00000001, + MTRAttributeIDTypeClusterWiFiNetworkManagementAttributeSSIDID MTR_PROVISIONALLY_AVAILABLE = 0x00000000, + MTRAttributeIDTypeClusterWiFiNetworkManagementAttributePassphraseSurrogateID MTR_PROVISIONALLY_AVAILABLE = 0x00000001, MTRAttributeIDTypeClusterWiFiNetworkManagementAttributeGeneratedCommandListID MTR_PROVISIONALLY_AVAILABLE = MTRAttributeIDTypeGlobalAttributeGeneratedCommandListID, MTRAttributeIDTypeClusterWiFiNetworkManagementAttributeAcceptedCommandListID MTR_PROVISIONALLY_AVAILABLE = MTRAttributeIDTypeGlobalAttributeAcceptedCommandListID, MTRAttributeIDTypeClusterWiFiNetworkManagementAttributeEventListID MTR_PROVISIONALLY_AVAILABLE = MTRAttributeIDTypeGlobalAttributeEventListID, diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRClusterNames.mm b/src/darwin/Framework/CHIP/zap-generated/MTRClusterNames.mm index 575661bfa078bd..f8f8c8e58ad42e 100644 --- a/src/darwin/Framework/CHIP/zap-generated/MTRClusterNames.mm +++ b/src/darwin/Framework/CHIP/zap-generated/MTRClusterNames.mm @@ -7419,6 +7419,10 @@ result = @"SSID"; break; + case MTRAttributeIDTypeClusterWiFiNetworkManagementAttributePassphraseSurrogateID: + result = @"PassphraseSurrogate"; + break; + case MTRAttributeIDTypeClusterWiFiNetworkManagementAttributeGeneratedCommandListID: result = @"GeneratedCommandList"; break; diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRClusters.h b/src/darwin/Framework/CHIP/zap-generated/MTRClusters.h index cefb92935beab4..3b729d448f8012 100644 --- a/src/darwin/Framework/CHIP/zap-generated/MTRClusters.h +++ b/src/darwin/Framework/CHIP/zap-generated/MTRClusters.h @@ -6169,6 +6169,8 @@ MTR_PROVISIONALLY_AVAILABLE - (NSDictionary * _Nullable)readAttributeSSIDWithParams:(MTRReadParams * _Nullable)params MTR_PROVISIONALLY_AVAILABLE; +- (NSDictionary * _Nullable)readAttributePassphraseSurrogateWithParams:(MTRReadParams * _Nullable)params MTR_PROVISIONALLY_AVAILABLE; + - (NSDictionary * _Nullable)readAttributeGeneratedCommandListWithParams:(MTRReadParams * _Nullable)params MTR_PROVISIONALLY_AVAILABLE; - (NSDictionary * _Nullable)readAttributeAcceptedCommandListWithParams:(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 8c38a6c584b79e..810a57bc5727b8 100644 --- a/src/darwin/Framework/CHIP/zap-generated/MTRClusters.mm +++ b/src/darwin/Framework/CHIP/zap-generated/MTRClusters.mm @@ -17174,6 +17174,11 @@ - (void)networkPassphraseRequestWithParams:(MTRWiFiNetworkManagementClusterNetwo return [self.device readAttributeWithEndpointID:self.endpointID clusterID:@(MTRClusterIDTypeWiFiNetworkManagementID) attributeID:@(MTRAttributeIDTypeClusterWiFiNetworkManagementAttributeSSIDID) params:params]; } +- (NSDictionary * _Nullable)readAttributePassphraseSurrogateWithParams:(MTRReadParams * _Nullable)params +{ + return [self.device readAttributeWithEndpointID:self.endpointID clusterID:@(MTRClusterIDTypeWiFiNetworkManagementID) attributeID:@(MTRAttributeIDTypeClusterWiFiNetworkManagementAttributePassphraseSurrogateID) params:params]; +} + - (NSDictionary * _Nullable)readAttributeGeneratedCommandListWithParams:(MTRReadParams * _Nullable)params { return [self.device readAttributeWithEndpointID:self.endpointID clusterID:@(MTRClusterIDTypeWiFiNetworkManagementID) attributeID:@(MTRAttributeIDTypeClusterWiFiNetworkManagementAttributeGeneratedCommandListID) params:params]; @@ -17455,9 +17460,6 @@ - (void)getOperationalDatasetWithParams:(MTRThreadNetworkDirectoryClusterGetOper }; auto * timedInvokeTimeoutMs = params.timedInvokeTimeoutMs; - if (timedInvokeTimeoutMs == nil) { - timedInvokeTimeoutMs = @(MTR_DEFAULT_TIMED_INTERACTION_TIMEOUT_MS); - } using RequestType = ThreadNetworkDirectory::Commands::GetOperationalDataset::Type; [self.device _invokeKnownCommandWithEndpointID:self.endpointID diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRCommandTimedCheck.mm b/src/darwin/Framework/CHIP/zap-generated/MTRCommandTimedCheck.mm index 6fdc015ad0aac3..6dc2c38f8447ef 100644 --- a/src/darwin/Framework/CHIP/zap-generated/MTRCommandTimedCheck.mm +++ b/src/darwin/Framework/CHIP/zap-generated/MTRCommandTimedCheck.mm @@ -1011,9 +1011,6 @@ static BOOL CommandNeedsTimedInvokeInThreadNetworkDirectoryCluster(AttributeId a case Commands::RemoveNetwork::Id: { return YES; } - case Commands::GetOperationalDataset::Id: { - return YES; - } default: { return NO; } 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 2a3e9856803f68..977fa7f5d01db1 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 @@ -23772,6 +23772,8 @@ CHIP_ERROR TypeInfo::DecodableType::Decode(TLV::TLVReader & reader, const Concre { case Attributes::Ssid::TypeInfo::GetAttributeId(): return DataModel::Decode(reader, ssid); + case Attributes::PassphraseSurrogate::TypeInfo::GetAttributeId(): + return DataModel::Decode(reader, passphraseSurrogate); case Attributes::GeneratedCommandList::TypeInfo::GetAttributeId(): return DataModel::Decode(reader, generatedCommandList); case Attributes::AcceptedCommandList::TypeInfo::GetAttributeId(): @@ -31764,7 +31766,6 @@ bool CommandNeedsTimedInvoke(ClusterId aCluster, CommandId aCommand) { case Clusters::ThreadNetworkDirectory::Commands::AddNetwork::Id: case Clusters::ThreadNetworkDirectory::Commands::RemoveNetwork::Id: - case Clusters::ThreadNetworkDirectory::Commands::GetOperationalDataset::Id: return true; default: return false; 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 81be5e1224e81d..51054ceeef544a 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 @@ -35963,6 +35963,18 @@ struct TypeInfo static constexpr size_t MaxLength() { return 32; } }; } // namespace Ssid +namespace PassphraseSurrogate { +struct TypeInfo +{ + using Type = chip::app::DataModel::Nullable; + using DecodableType = chip::app::DataModel::Nullable; + using DecodableArgType = const chip::app::DataModel::Nullable &; + + static constexpr ClusterId GetClusterId() { return Clusters::WiFiNetworkManagement::Id; } + static constexpr AttributeId GetAttributeId() { return Attributes::PassphraseSurrogate::Id; } + static constexpr bool MustUseTimedWrite() { return false; } +}; +} // namespace PassphraseSurrogate namespace GeneratedCommandList { struct TypeInfo : public Clusters::Globals::Attributes::GeneratedCommandList::TypeInfo { @@ -36009,6 +36021,7 @@ struct TypeInfo CHIP_ERROR Decode(TLV::TLVReader & reader, const ConcreteAttributePath & path); Attributes::Ssid::TypeInfo::DecodableType ssid; + Attributes::PassphraseSurrogate::TypeInfo::DecodableType passphraseSurrogate; Attributes::GeneratedCommandList::TypeInfo::DecodableType generatedCommandList; Attributes::AcceptedCommandList::TypeInfo::DecodableType acceptedCommandList; Attributes::EventList::TypeInfo::DecodableType eventList; @@ -36473,7 +36486,7 @@ struct Type using ResponseType = Clusters::ThreadNetworkDirectory::Commands::OperationalDatasetResponse::DecodableType; - static constexpr bool MustUseTimedInvoke() { return true; } + static constexpr bool MustUseTimedInvoke() { return false; } }; struct DecodableType diff --git a/zzz_generated/app-common/app-common/zap-generated/ids/Attributes.h b/zzz_generated/app-common/app-common/zap-generated/ids/Attributes.h index c1d26d64c5d27b..90233fd66df274 100644 --- a/zzz_generated/app-common/app-common/zap-generated/ids/Attributes.h +++ b/zzz_generated/app-common/app-common/zap-generated/ids/Attributes.h @@ -6749,9 +6749,13 @@ namespace WiFiNetworkManagement { namespace Attributes { namespace Ssid { -static constexpr AttributeId Id = 0x00000001; +static constexpr AttributeId Id = 0x00000000; } // namespace Ssid +namespace PassphraseSurrogate { +static constexpr AttributeId Id = 0x00000001; +} // namespace PassphraseSurrogate + namespace GeneratedCommandList { static constexpr AttributeId Id = Globals::Attributes::GeneratedCommandList::Id; } // namespace GeneratedCommandList diff --git a/zzz_generated/chip-tool/zap-generated/cluster/Commands.h b/zzz_generated/chip-tool/zap-generated/cluster/Commands.h index 273f743a19cf00..7400b6c692ead3 100644 --- a/zzz_generated/chip-tool/zap-generated/cluster/Commands.h +++ b/zzz_generated/chip-tool/zap-generated/cluster/Commands.h @@ -11296,7 +11296,8 @@ class ColorControlStepColorTemperature : public ClusterCommand | * NetworkPassphraseRequest | 0x00 | |------------------------------------------------------------------------------| | Attributes: | | -| * Ssid | 0x0001 | +| * Ssid | 0x0000 | +| * PassphraseSurrogate | 0x0001 | | * GeneratedCommandList | 0xFFF8 | | * AcceptedCommandList | 0xFFF9 | | * EventList | 0xFFFA | @@ -25570,6 +25571,7 @@ void registerClusterWiFiNetworkManagement(Commands & commands, CredentialIssuerC // make_unique(Id, credsIssuerConfig), // make_unique(Id, "ssid", Attributes::Ssid::Id, credsIssuerConfig), // + make_unique(Id, "passphrase-surrogate", Attributes::PassphraseSurrogate::Id, credsIssuerConfig), // make_unique(Id, "generated-command-list", Attributes::GeneratedCommandList::Id, credsIssuerConfig), // make_unique(Id, "accepted-command-list", Attributes::AcceptedCommandList::Id, credsIssuerConfig), // make_unique(Id, "event-list", Attributes::EventList::Id, credsIssuerConfig), // @@ -25579,6 +25581,9 @@ void registerClusterWiFiNetworkManagement(Commands & commands, CredentialIssuerC make_unique>(Id, credsIssuerConfig), // make_unique>>( Id, "ssid", Attributes::Ssid::Id, WriteCommandType::kForceWrite, credsIssuerConfig), // + make_unique>>(Id, "passphrase-surrogate", 0, UINT64_MAX, + Attributes::PassphraseSurrogate::Id, + WriteCommandType::kForceWrite, credsIssuerConfig), // make_unique>>( Id, "generated-command-list", Attributes::GeneratedCommandList::Id, WriteCommandType::kForceWrite, credsIssuerConfig), // @@ -25594,6 +25599,7 @@ void registerClusterWiFiNetworkManagement(Commands & commands, CredentialIssuerC WriteCommandType::kForceWrite, credsIssuerConfig), // make_unique(Id, credsIssuerConfig), // make_unique(Id, "ssid", Attributes::Ssid::Id, credsIssuerConfig), // + make_unique(Id, "passphrase-surrogate", Attributes::PassphraseSurrogate::Id, credsIssuerConfig), // make_unique(Id, "generated-command-list", Attributes::GeneratedCommandList::Id, credsIssuerConfig), // make_unique(Id, "accepted-command-list", Attributes::AcceptedCommandList::Id, credsIssuerConfig), // make_unique(Id, "event-list", Attributes::EventList::Id, credsIssuerConfig), // diff --git a/zzz_generated/chip-tool/zap-generated/cluster/logging/DataModelLogger.cpp b/zzz_generated/chip-tool/zap-generated/cluster/logging/DataModelLogger.cpp index c6c1231bab95d1..ed11ca21acae81 100644 --- a/zzz_generated/chip-tool/zap-generated/cluster/logging/DataModelLogger.cpp +++ b/zzz_generated/chip-tool/zap-generated/cluster/logging/DataModelLogger.cpp @@ -16906,6 +16906,11 @@ CHIP_ERROR DataModelLogger::LogAttribute(const chip::app::ConcreteDataAttributeP ReturnErrorOnFailure(chip::app::DataModel::Decode(*data, value)); return DataModelLogger::LogValue("SSID", 1, value); } + case WiFiNetworkManagement::Attributes::PassphraseSurrogate::Id: { + chip::app::DataModel::Nullable value; + ReturnErrorOnFailure(chip::app::DataModel::Decode(*data, value)); + return DataModelLogger::LogValue("PassphraseSurrogate", 1, value); + } case WiFiNetworkManagement::Attributes::GeneratedCommandList::Id: { chip::app::DataModel::DecodableList value; ReturnErrorOnFailure(chip::app::DataModel::Decode(*data, value)); 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 8ebe6735d29dd0..21921e859e6c17 100644 --- a/zzz_generated/darwin-framework-tool/zap-generated/cluster/Commands.h +++ b/zzz_generated/darwin-framework-tool/zap-generated/cluster/Commands.h @@ -146700,7 +146700,8 @@ class SubscribeAttributeRadonConcentrationMeasurementClusterRevision : public Su | * NetworkPassphraseRequest | 0x00 | |------------------------------------------------------------------------------| | Attributes: | | -| * Ssid | 0x0001 | +| * Ssid | 0x0000 | +| * PassphraseSurrogate | 0x0001 | | * GeneratedCommandList | 0xFFF8 | | * AcceptedCommandList | 0xFFF9 | | * EventList | 0xFFFA | @@ -146851,6 +146852,91 @@ class SubscribeAttributeWiFiNetworkManagementSsid : public SubscribeAttribute { #endif // MTR_ENABLE_PROVISIONAL #if MTR_ENABLE_PROVISIONAL +/* + * Attribute PassphraseSurrogate + */ +class ReadWiFiNetworkManagementPassphraseSurrogate : public ReadAttribute { +public: + ReadWiFiNetworkManagementPassphraseSurrogate() + : ReadAttribute("passphrase-surrogate") + { + } + + ~ReadWiFiNetworkManagementPassphraseSurrogate() + { + } + + CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override + { + constexpr chip::ClusterId clusterId = chip::app::Clusters::WiFiNetworkManagement::Id; + constexpr chip::AttributeId attributeId = chip::app::Clusters::WiFiNetworkManagement::Attributes::PassphraseSurrogate::Id; + + ChipLogProgress(chipTool, "Sending cluster (0x%08" PRIX32 ") ReadAttribute (0x%08" PRIX32 ") on endpoint %u", endpointId, clusterId, attributeId); + + dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL); + __auto_type * cluster = [[MTRBaseClusterWiFiNetworkManagement alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue]; + [cluster readAttributePassphraseSurrogateWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) { + NSLog(@"WiFiNetworkManagement.PassphraseSurrogate response %@", [value description]); + if (error == nil) { + RemoteDataModelLogger::LogAttributeAsJSON(@(endpointId), @(clusterId), @(attributeId), value); + } else { + LogNSError("WiFiNetworkManagement PassphraseSurrogate read Error", error); + RemoteDataModelLogger::LogAttributeErrorAsJSON(@(endpointId), @(clusterId), @(attributeId), error); + } + SetCommandExitStatus(error); + }]; + return CHIP_NO_ERROR; + } +}; + +class SubscribeAttributeWiFiNetworkManagementPassphraseSurrogate : public SubscribeAttribute { +public: + SubscribeAttributeWiFiNetworkManagementPassphraseSurrogate() + : SubscribeAttribute("passphrase-surrogate") + { + } + + ~SubscribeAttributeWiFiNetworkManagementPassphraseSurrogate() + { + } + + CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override + { + constexpr chip::ClusterId clusterId = chip::app::Clusters::WiFiNetworkManagement::Id; + constexpr chip::CommandId attributeId = chip::app::Clusters::WiFiNetworkManagement::Attributes::PassphraseSurrogate::Id; + + ChipLogProgress(chipTool, "Sending cluster (0x%08" PRIX32 ") ReportAttribute (0x%08" PRIX32 ") on endpoint %u", clusterId, attributeId, endpointId); + dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL); + __auto_type * cluster = [[MTRBaseClusterWiFiNetworkManagement alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue]; + __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)]; + if (mKeepSubscriptions.HasValue()) { + params.replaceExistingSubscriptions = !mKeepSubscriptions.Value(); + } + if (mFabricFiltered.HasValue()) { + params.filterByFabric = mFabricFiltered.Value(); + } + if (mAutoResubscribe.HasValue()) { + params.resubscribeAutomatically = mAutoResubscribe.Value(); + } + [cluster subscribeAttributePassphraseSurrogateWithParams:params + subscriptionEstablished:^() { mSubscriptionEstablished = YES; } + reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) { + NSLog(@"WiFiNetworkManagement.PassphraseSurrogate response %@", [value description]); + if (error == nil) { + RemoteDataModelLogger::LogAttributeAsJSON(@(endpointId), @(clusterId), @(attributeId), value); + } else { + RemoteDataModelLogger::LogAttributeErrorAsJSON(@(endpointId), @(clusterId), @(attributeId), error); + } + SetCommandExitStatus(error); + }]; + + return CHIP_NO_ERROR; + } +}; + +#endif // MTR_ENABLE_PROVISIONAL +#if MTR_ENABLE_PROVISIONAL + /* * Attribute GeneratedCommandList */ @@ -196257,6 +196343,10 @@ void registerClusterWiFiNetworkManagement(Commands & commands) make_unique(), // make_unique(), // #endif // MTR_ENABLE_PROVISIONAL +#if MTR_ENABLE_PROVISIONAL + make_unique(), // + make_unique(), // +#endif // MTR_ENABLE_PROVISIONAL #if MTR_ENABLE_PROVISIONAL make_unique(), // make_unique(), //