From 6a72fd185b9c01074dfb51d3ab000f1c792fc65f Mon Sep 17 00:00:00 2001 From: Jakub Latusek Date: Thu, 27 Jun 2024 17:28:41 +0200 Subject: [PATCH 01/12] Use in k32w example dependencies from project (#34112) * Use in k32w example dependencies from project not default one from pigweed * Restyle --- examples/lighting-app/nxp/k32w/k32w0/.gn | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/examples/lighting-app/nxp/k32w/k32w0/.gn b/examples/lighting-app/nxp/k32w/k32w0/.gn index 363727423ce903..cfa8fcb8c07dc4 100644 --- a/examples/lighting-app/nxp/k32w/k32w0/.gn +++ b/examples/lighting-app/nxp/k32w/k32w0/.gn @@ -26,6 +26,10 @@ default_args = { import("//args.gni") + pw_build_PIP_CONSTRAINTS = [ "${chip_root}/scripts/setup/constraints.txt" ] + pw_build_PIP_REQUIREMENTS = + [ "${chip_root}/scripts/setup/requirements.build.txt" ] + # Import default platform configs import("${chip_root}/src/platform/nxp/k32w/k32w0/args.gni") } From 3fc8d676525d3b2855b6b3b0278673cfb92a8cdd Mon Sep 17 00:00:00 2001 From: Rohan Sahay Date: Thu, 27 Jun 2024 21:53:56 +0530 Subject: [PATCH 02/12] [Silabs] Adds support for both PSA and TinyCrypt on SiWx917 SoC (#29776) * Refactor SiWx917 for mbedtls usage * Refactor PlatformManagerImpl initialization * Remove experimental ECDSA support * Adds multithreaded safety in crypto operations * Adds changes for use of SL_MBEDTLS_USE_TINYCRYPT * Adds changes for use of SL_MBEDTLS_USE_TINYCRYPT * addressed comments * Updated as per comments --------- Co-authored-by: Rohan S <3526930+brosahay@users.noreply.github.com> --- .../silabs/SiWx917/SiWx917/sl_wifi_if.cpp | 14 +- src/platform/silabs/PlatformManagerImpl.cpp | 17 +- src/platform/silabs/PlatformManagerImpl.h | 4 +- src/platform/silabs/SiWx917/BUILD.gn | 12 +- .../SiWx917/siwx917-chip-mbedtls-config.h | 162 +++----- .../silabs/SiWx917/siwx917-chip-psa-config.h | 32 ++ third_party/silabs/SiWx917_sdk.gni | 356 ++++++++++++++---- 7 files changed, 398 insertions(+), 199 deletions(-) create mode 100644 src/platform/silabs/SiWx917/siwx917-chip-psa-config.h diff --git a/examples/platform/silabs/SiWx917/SiWx917/sl_wifi_if.cpp b/examples/platform/silabs/SiWx917/SiWx917/sl_wifi_if.cpp index c89c6768abe62c..5253b3b2ec5062 100644 --- a/examples/platform/silabs/SiWx917/SiWx917/sl_wifi_if.cpp +++ b/examples/platform/silabs/SiWx917/SiWx917/sl_wifi_if.cpp @@ -74,10 +74,10 @@ extern "C" { #include "sl_wifi.h" #include "sl_wifi_callback_framework.h" #include "wfx_host_events.h" -#if SLI_SI91X_MCU_INTERFACE +#if SL_MBEDTLS_USE_TINYCRYPT +#include "sl_si91x_constants.h" #include "sl_si91x_trng.h" -#define TRNGKEY_SIZE 4 -#endif // SLI_SI91X_MCU_INTERFACE +#endif // SL_MBEDTLS_USE_TINYCRYPT } WfxRsi_t wfx_rsi; @@ -456,8 +456,8 @@ static sl_status_t wfx_rsi_init(void) return status; } -#ifdef SLI_SI91X_MCU_INTERFACE - const uint32_t trngKey[TRNGKEY_SIZE] = { 0x16157E2B, 0xA6D2AE28, 0x8815F7AB, 0x3C4FCF09 }; +#ifdef SL_MBEDTLS_USE_TINYCRYPT + const uint32_t trngKey[TRNG_KEY_SIZE] = { 0x16157E2B, 0xA6D2AE28, 0x8815F7AB, 0x3C4FCF09 }; // To check the Entropy of TRNG and verify TRNG functioning. status = sl_si91x_trng_entropy(); @@ -468,13 +468,13 @@ static sl_status_t wfx_rsi_init(void) } // Initiate and program the key required for TRNG hardware engine - status = sl_si91x_trng_program_key((uint32_t *) trngKey, TRNGKEY_SIZE); + status = sl_si91x_trng_program_key((uint32_t *) trngKey, TRNG_KEY_SIZE); if (status != SL_STATUS_OK) { SILABS_LOG("TRNG Key Programming Failed"); return status; } -#endif // SLI_SI91X_MCU_INTERFACE +#endif // SL_MBEDTLS_USE_TINYCRYPT wfx_rsi.events = xEventGroupCreateStatic(&rsiDriverEventGroup); wfx_rsi.dev_state |= WFX_RSI_ST_DEV_READY; diff --git a/src/platform/silabs/PlatformManagerImpl.cpp b/src/platform/silabs/PlatformManagerImpl.cpp index 4e54a2a53f98a5..741a0b6b8676e1 100644 --- a/src/platform/silabs/PlatformManagerImpl.cpp +++ b/src/platform/silabs/PlatformManagerImpl.cpp @@ -31,9 +31,9 @@ #include #include -#if defined(TINYCRYPT_PRIMITIVES) +#if defined(SL_MBEDTLS_USE_TINYCRYPT) #include "tinycrypt/ecc.h" -#endif // TINYCRYPT_PRIMITIVES +#endif // SL_MBEDTLS_USE_TINYCRYPT #if CHIP_SYSTEM_CONFIG_USE_LWIP #include @@ -46,7 +46,7 @@ namespace DeviceLayer { PlatformManagerImpl PlatformManagerImpl::sInstance; -#if defined(TINYCRYPT_PRIMITIVES) +#if defined(SL_MBEDTLS_USE_TINYCRYPT) sys_mutex_t PlatformManagerImpl::rngMutexHandle = NULL; int PlatformManagerImpl::uECC_RNG_Function(uint8_t * dest, unsigned int size) @@ -76,12 +76,10 @@ static int app_entropy_source(void * data, unsigned char * output, size_t len, s return 0; } #endif // !SLI_SI91X_MCU_INTERFACE -#endif // TINYCRYPT_PRIMITIVES - +#endif // SL_MBEDTLS_USE_TINYCRYPT CHIP_ERROR PlatformManagerImpl::_InitChipStack(void) { CHIP_ERROR err; - // Initialize the configuration system. err = chip::DeviceLayer::PersistedStorage::KeyValueStoreMgrImpl().Init(); SuccessOrExit(err); @@ -93,14 +91,15 @@ CHIP_ERROR PlatformManagerImpl::_InitChipStack(void) ReturnErrorOnFailure(System::Clock::InitClock_RealTime()); -#if defined(TINYCRYPT_PRIMITIVES) +#if defined(SL_MBEDTLS_USE_TINYCRYPT) #if !(SLI_SI91X_MCU_INTERFACE) - ReturnErrorOnFailure(chip::Crypto::add_entropy_source(app_entropy_source, NULL, 16 /*Threshold value*/)); + // 16 : Threshold value + ReturnErrorOnFailure(chip::Crypto::add_entropy_source(app_entropy_source, NULL, 16)); #endif // !SLI_SI91X_MCU_INTERFACE /* Set RNG function for tinycrypt operations. */ VerifyOrExit(sys_mutex_new(&rngMutexHandle) == ERR_OK, err = CHIP_ERROR_NO_MEMORY); uECC_set_rng(PlatformManagerImpl::uECC_RNG_Function); -#endif // TINYCRYPT_PRIMITIVES +#endif // SL_MBEDTLS_USE_TINYCRYPT // Call _InitChipStack() on the generic implementation base class // to finish the initialization process. diff --git a/src/platform/silabs/PlatformManagerImpl.h b/src/platform/silabs/PlatformManagerImpl.h index 4a0bfdb52c1e81..b44fbadbfa3308 100644 --- a/src/platform/silabs/PlatformManagerImpl.h +++ b/src/platform/silabs/PlatformManagerImpl.h @@ -41,7 +41,7 @@ class PlatformManagerImpl final : public PlatformManager, public Internal::Gener // the implementation methods provided by this class. friend PlatformManager; -#if defined(TINYCRYPT_PRIMITIVES) +#if defined(SL_MBEDTLS_USE_TINYCRYPT) // Since the RNG callback will be called from multiple threads, // use this mutex to lock/unlock the call to Matter RNG API, which // uses some global variables. @@ -51,7 +51,7 @@ class PlatformManagerImpl final : public PlatformManager, public Internal::Gener // It must be set before calling any sign operations, // which are used in both Matter and OT threads. static int uECC_RNG_Function(uint8_t * dest, unsigned int size); -#endif +#endif // SL_MBEDTLS_USE_TINYCRYPT // Allow the generic implementation base class to call helper methods on // this class. diff --git a/src/platform/silabs/SiWx917/BUILD.gn b/src/platform/silabs/SiWx917/BUILD.gn index 27df228be44222..ca3c4042349113 100644 --- a/src/platform/silabs/SiWx917/BUILD.gn +++ b/src/platform/silabs/SiWx917/BUILD.gn @@ -18,11 +18,14 @@ import("${chip_root}/src/platform/device.gni") import("${chip_root}/build/chip/buildconfig_header.gni") import("${chip_root}/src/crypto/crypto.gni") +import("${chip_root}/src/platform/silabs/wifi_args.gni") +import("${chip_root}/third_party/silabs/SiWx917_sdk.gni") import("${chip_root}/third_party/silabs/silabs_board.gni") silabs_platform_dir = "${chip_root}/src/platform/silabs" assert(chip_device_platform == "SiWx917") + if (chip_crypto == "platform") { import("//build_overrides/mbedtls.gni") } @@ -80,7 +83,14 @@ static_library("SiWx917") { # Add platform crypto implementation if (chip_crypto == "platform") { - sources += [ "CHIPCryptoPALTinyCrypt.cpp" ] + if (sl_si91x_crypto_flavor == "tinycrypt") { + sources += [ "CHIPCryptoPALTinyCrypt.cpp" ] + } + + if (sl_si91x_crypto_flavor == "psa") { + sources += [ "${silabs_platform_dir}/efr32/CHIPCryptoPALPsaEfr32.cpp" ] + } + public_deps += [ "${chip_root}/src/crypto", "${mbedtls_root}:mbedtls", diff --git a/src/platform/silabs/SiWx917/siwx917-chip-mbedtls-config.h b/src/platform/silabs/SiWx917/siwx917-chip-mbedtls-config.h index 1fb5fde59341af..de0298957c4836 100644 --- a/src/platform/silabs/SiWx917/siwx917-chip-mbedtls-config.h +++ b/src/platform/silabs/SiWx917/siwx917-chip-mbedtls-config.h @@ -1,111 +1,86 @@ /* - * Copyright (c) 2021, The OpenThread Authors. - * All rights reserved. * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holder nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. + * 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 -/** - * Enable FreeRTOS threading support - */ -#define MBEDTLS_FREERTOS +#define MBEDTLS_PLATFORM_C +#define MBEDTLS_PLATFORM_MEMORY +#define MBEDTLS_VERSION_C +#define MBEDTLS_VERSION_FEATURES -/** - * Enable H Crypto and Entropy modules - */ -#define MBEDTLS_AES_C -#define MBEDTLS_ECP_C -#define MBEDTLS_ECDH_C -#define MBEDTLS_ENTROPY_C -#define MBEDTLS_SHA256_C -#define MBEDTLS_CIPHER_MODE_CTR -#define MBEDTLS_TRNG_C +#define MBEDTLS_HKDF_C +#define MBEDTLS_PKCS5_C -#define MBEDTLS_NO_PLATFORM_ENTROPY -#define MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES +// DIC Specific Configurations +#ifdef DIC_ENABLE -#if defined(MBEDTLS_ECP_ALT) && !defined(MBEDTLS_ECP_RESTARTABLE) -typedef void mbedtls_ecp_restart_ctx; -#endif +#define MBEDTLS_MPI_MAX_SIZE 512 -#ifdef DIC_ENABLE -#define MBEDTLS_PKCS1_V15 -#define MBEDTLS_RSA_NO_CRT #define MBEDTLS_CIPHER_MODE_CBC +#define MBEDTLS_CIPHER_MODE_WITH_PADDING #define MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED +#define MBEDTLS_PKCS1_V15 #define MBEDTLS_RSA_C +#define MBEDTLS_RSA_NO_CRT #define MBEDTLS_SHA1_C #define MBEDTLS_SSL_IN_CONTENT_LEN 5120 +#define MBEDTLS_SSL_MAX_CONTENT_LEN 5120 #define MBEDTLS_SSL_OUT_CONTENT_LEN 1560 -#define MBEDTLS_DEBUG_C -#define MBEDTLS_CIPHER_MODE_WITH_PADDING -#endif + +#endif // DIC_ENABLE + +#ifdef SL_MBEDTLS_USE_TINYCRYPT +#define TINYCRYPT_PRIMITIVES +#define OPTIMIZE_TINYCRYPT_ASM + +#define MBEDTLS_FREERTOS + +#if (!(DIC_ENABLE) || !defined(DIC_ENABLE)) +/**< Maximum windows size used. */ +#define MBEDTLS_MPI_WINDOW_SIZE 1 + +/**< Maximum number of bytes for usable MPIs. */ +#define MBEDTLS_MPI_MAX_SIZE 32 +/**< Maxium fragment length in bytes */ +#define MBEDTLS_SSL_MAX_CONTENT_LEN 768 +#endif // !(DIC_ENABLE) + +#define MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES #define MBEDTLS_PLATFORM_SNPRINTF_MACRO snprintf #define MBEDTLS_AES_ROM_TABLES -#define MBEDTLS_ASN1_PARSE_C -#define MBEDTLS_ASN1_WRITE_C -#define MBEDTLS_BASE64_C -#define MBEDTLS_BIGNUM_C #define MBEDTLS_CCM_C -#define MBEDTLS_CIPHER_C #define MBEDTLS_CIPHER_MODE_CBC #define MBEDTLS_CIPHER_MODE_CFB -#define MBEDTLS_CMAC_C -#define MBEDTLS_CTR_DRBG_C +#define MBEDTLS_CIPHER_MODE_CTR +#define MBEDTLS_ECDH_C #define MBEDTLS_ECDH_LEGACY_CONTEXT -#define MBEDTLS_ECDSA_C #define MBEDTLS_ECDSA_DETERMINISTIC #define MBEDTLS_ECJPAKE_C -#define MBEDTLS_ECP_DP_SECP256R1_ENABLED +#define MBEDTLS_ECP_FIXED_POINT_OPTIM 0 #define MBEDTLS_ECP_NIST_OPTIM -#define MBEDTLS_ENTROPY_FORCE_SHA256 -// TODO: 3R -// #define MBEDTLS_ENTROPY_HARDWARE_ALT - +#define MBEDTLS_ECP_WINDOW_SIZE 2 #define MBEDTLS_ERROR_STRERROR_DUMMY #define MBEDTLS_HAVE_ASM -#define MBEDTLS_HKDF_C #define MBEDTLS_HMAC_DRBG_C #define MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED #define MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED #define MBEDTLS_KEY_EXCHANGE_PSK_ENABLED -#define MBEDTLS_MD_C -#define MBEDTLS_OID_C -#define MBEDTLS_PEM_PARSE_C -#define MBEDTLS_PEM_WRITE_C -#define MBEDTLS_PK_C -#define MBEDTLS_PK_PARSE_C -#define MBEDTLS_PK_WRITE_C -#define MBEDTLS_PKCS5_C -#define MBEDTLS_PLATFORM_C -#define MBEDTLS_PLATFORM_MEMORY #define MBEDTLS_SHA256_SMALLER #define MBEDTLS_SHA512_C #define MBEDTLS_SSL_CLI_C @@ -115,38 +90,17 @@ typedef void mbedtls_ecp_restart_ctx; #define MBEDTLS_SSL_EXPORT_KEYS #define MBEDTLS_SSL_KEEP_PEER_CERTIFICATE #define MBEDTLS_SSL_MAX_FRAGMENT_LENGTH -#define MBEDTLS_SSL_PROTO_TLS1_2 #define MBEDTLS_SSL_PROTO_DTLS +#define MBEDTLS_SSL_PROTO_TLS1_2 #define MBEDTLS_SSL_SRV_C #define MBEDTLS_SSL_TLS_C -#define MBEDTLS_X509_CREATE_C -#define MBEDTLS_X509_CSR_WRITE_C -#define MBEDTLS_X509_CRL_PARSE_C -#define MBEDTLS_X509_CRT_PARSE_C -#define MBEDTLS_X509_CSR_PARSE_C -#define MBEDTLS_X509_USE_C - -#define MBEDTLS_MPI_WINDOW_SIZE 1 /**< Maximum windows size used. */ -#ifdef DIC_ENABLE -#define MBEDTLS_MPI_MAX_SIZE 512 /**< Maximum number of bytes for usable MPIs. */ -#else -#define MBEDTLS_MPI_MAX_SIZE 32 /**< Maximum number of bytes for usable MPIs. */ -#endif -#define MBEDTLS_ECP_MAX_BITS 256 /**< Maximum bit size of groups */ -#define MBEDTLS_ECP_WINDOW_SIZE 2 /**< Maximum window size used */ -#define MBEDTLS_ECP_FIXED_POINT_OPTIM 0 /**< Enable fixed-point speed-up */ -#define MBEDTLS_ENTROPY_MAX_SOURCES 2 /**< Maximum number of sources supported */ - -#if OPENTHREAD_CONFIG_COAP_SECURE_API_ENABLE -#define MBEDTLS_SSL_MAX_CONTENT_LEN 900 /**< Maxium fragment length in bytes */ -#else -#ifdef DIC_ENABLE -#define MBEDTLS_SSL_MAX_CONTENT_LEN 5120 /**< Maxium fragment length in bytes */ -#else -#define MBEDTLS_SSL_MAX_CONTENT_LEN 768 /**< Maxium fragment length in bytes */ -#endif // DIC +#define MBEDTLS_TRNG_C + +#if defined(MBEDTLS_ECP_ALT) && !defined(MBEDTLS_ECP_RESTARTABLE) +typedef void mbedtls_ecp_restart_ctx; #endif -#define MBEDTLS_SSL_CIPHERSUITES MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8 +#endif // SL_MBEDTLS_USE_TINYCRYPT -#include "mbedtls/check_config.h" +// SLC GENERATED +#include "sl_mbedtls_config.h" diff --git a/src/platform/silabs/SiWx917/siwx917-chip-psa-config.h b/src/platform/silabs/SiWx917/siwx917-chip-psa-config.h new file mode 100644 index 00000000000000..f498cccc2b2582 --- /dev/null +++ b/src/platform/silabs/SiWx917/siwx917-chip-psa-config.h @@ -0,0 +1,32 @@ +/* + * + * 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 + +// DIC Specific Configurations +#ifdef DIC_ENABLE +#define MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF + +#define PSA_WANT_ALG_CBC_NO_PADDING +#define PSA_WANT_ALG_RSA_PKCS1V15_SIGN +#define PSA_WANT_ALG_SOME_PAKE +#define PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY +#endif // DIC_ENABLE + +// SLC GENERATED +#include "psa_crypto_config.h" diff --git a/third_party/silabs/SiWx917_sdk.gni b/third_party/silabs/SiWx917_sdk.gni index ddda1e68b7f4b7..6dd4085381ad4f 100644 --- a/third_party/silabs/SiWx917_sdk.gni +++ b/third_party/silabs/SiWx917_sdk.gni @@ -16,10 +16,12 @@ import("//build_overrides/chip.gni") import("//build_overrides/efr32_sdk.gni") import("//build_overrides/jlink.gni") import("//build_overrides/mbedtls.gni") -import("${efr32_sdk_build_root}/efr32_sdk.gni") import("${chip_root}/src/app/icd/icd.gni") +import("${chip_root}/src/crypto/crypto.gni") import("${chip_root}/src/lib/lib.gni") +import("${chip_root}/src/platform/silabs/wifi_args.gni") +import("${efr32_sdk_build_root}/efr32_sdk.gni") import("silabs_board.gni") examples_plat_dir = "${chip_root}/examples/platform/silabs/SiWx917" @@ -31,6 +33,9 @@ declare_args() { # Periodic time at which the 917 SoC should wakeup si91x_alarm_periodic_time = 30 + # option to select the crypto library + sl_si91x_crypto_flavor = "tinycrypt" + # enable 917 SoC M4 sleep wakeup si917_m4_sleep_enabled = false } @@ -44,13 +49,19 @@ template("siwx917_sdk") { sdk_target_name = target_name config("${sdk_target_name}_config") { + defines = [] include_dirs = [] libs = [] - defines = [] + cflags = [] + if (defined(invoker.include_dirs)) { include_dirs += invoker.include_dirs } + if (defined(invoker.defines)) { + defines += invoker.defines + } + # Treat these includes as system includes, so warnings in them are not fatal. _include_dirs = [ "${chip_root}", @@ -58,11 +69,8 @@ template("siwx917_sdk") { "${efr32_sdk_root}/platform/emdrv/nvm3/inc", "${efr32_sdk_root}/platform/emdrv/common/inc", "${efr32_sdk_root}/platform/service/device_init/inc", - "${sdk_support_root}/matter/mbedtls/tinycrypt/inc", "${sdk_support_root}/matter/si91x/siwx917/BRD4338A/autogen", "${sdk_support_root}/matter/si91x/siwx917/BRD4338A/config", - "${chip_root}/third_party/mbedtls/repo/include", - "${chip_root}/third_party/mbedtls/repo/library", "${chip_root}/src/platform/silabs/rs911x", @@ -173,7 +181,6 @@ template("siwx917_sdk") { # To fix this, these files are also manually depended upon in the source set # declared in siwx917_mbedtls_config further down this file. defines += [ - "MBEDTLS_CONFIG_FILE=\"siwx917-chip-mbedtls-config.h\"", "__STARTUP_CLEAR_BSS", "HARD_FAULT_LOG_ENABLE", "SL_HEAP_SIZE=32768", @@ -197,8 +204,6 @@ template("siwx917_sdk") { "USE_NVM3=1", "SLI_SI91X_ENABLE_BLE=1", "SL_SI91X_ENABLE_LITTLE_ENDIAN=1", - "TINYCRYPT_PRIMITIVES", - "OPTIMIZE_TINYCRYPT_ASM", "__error_t_defined", "RSI_SAMPLE_HAL", "DEBUG_UART=1", @@ -245,7 +250,6 @@ template("siwx917_sdk") { defines += [ "ENABLE_CHIP_SHELL" ] } - import("${chip_root}/src/platform/silabs/wifi_args.gni") defines += [ "LWIP_NETIF_API=1" ] if (lwip_ipv4) { defines += [ @@ -341,11 +345,6 @@ template("siwx917_sdk") { libs += [ "${sdk_support_root}/platform/emdrv/nvm3/lib/libnvm3_CM4_gcc.a" ] - cflags = [] - foreach(include_dir, _include_dirs) { - cflags += [ "-isystem" + rebase_path(include_dir, root_build_dir) ] - } - cflags += [ "-Wno-maybe-uninitialized", "-Wno-shadow", @@ -359,23 +358,256 @@ template("siwx917_sdk") { "-Wno-unused-function", ] - if (defined(invoker.defines)) { - defines += invoker.defines + foreach(include_dir, _include_dirs) { + cflags += [ "-isystem" + rebase_path(include_dir, root_build_dir) ] } } - source_set("siwx917_mbedtls_config") { - # We're setting the mbedTLS config flags here as the siwx917_sdk target - # acts as the mbedTLS target for SiWx917 builds. We need this for the build - # system to recompile mbedTLS (= the SDK) when the mbedTLS config gets - # edited. - sources = [ - "${chip_root}/src/platform/silabs/SiWx917/siwx917-chip-mbedtls-config.h", - ] + assert(chip_crypto == "platform" && (sl_si91x_crypto_flavor == "tinycrypt" || + sl_si91x_crypto_flavor == "psa"), + "sl_si91x_crypto_flavor must be tinycrypt or psa") + + if (chip_crypto == "platform") { + if (sl_si91x_crypto_flavor == "psa") { + _mbedtls_root = "${efr32_sdk_root}/util/third_party/mbedtls" + + sl_si91x_psa_crypto_path = + "${wifi_sdk_root}/components/device/silabs/si91x/wireless/crypto/" + + config("sl_si91x_psa_crypto_config") { + defines = [ + "MBEDTLS_CONFIG_FILE=\"siwx917-chip-mbedtls-config.h\"", + "MBEDTLS_PSA_CRYPTO_CONFIG_FILE=\"siwx917-chip-psa-config.h\"", + + # WISECONNECT 3 SDK + "SLI_AEAD_DEVICE_SI91X=1", + "SLI_CIPHER_DEVICE_SI91X=1", + "SLI_ECDH_DEVICE_SI91X=1", + "SLI_MAC_DEVICE_SI91X=1", + "SLI_SHA_DEVICE_SI91X=1", + "SLI_TRNG_DEVICE_SI91X=1", + "SLI_SECURE_KEY_STORAGE_DEVICE_SI91X=1", + "SLI_MULTITHREAD_DEVICE_SI91X=1", + ] - public_deps = [ "${chip_root}/src/crypto:crypto_buildconfig" ] - } + include_dirs = [ + # WISECONNECT 3 SDK + "${sl_si91x_psa_crypto_path}/inc", + "${sl_si91x_psa_crypto_path}/aes/inc", + "${sl_si91x_psa_crypto_path}/aead/inc", + "${sl_si91x_psa_crypto_path}/ccm/inc", + "${sl_si91x_psa_crypto_path}/ecdh/inc", + "${sl_si91x_psa_crypto_path}/ecdsa/inc", + "${sl_si91x_psa_crypto_path}/hmac/inc", + "${sl_si91x_psa_crypto_path}/mac/inc", + "${sl_si91x_psa_crypto_path}/gcm/inc", + "${sl_si91x_psa_crypto_path}/sha/inc", + "${sl_si91x_psa_crypto_path}/trng/inc", + "${sl_si91x_psa_crypto_path}/wrap/inc", + "${sl_si91x_psa_crypto_path}/multithread/inc", + + # mbedTLS + "${efr32_sdk_root}/platform/security/sl_component/sl_mbedtls_support/config", + "${efr32_sdk_root}/platform/security/sl_component/sl_mbedtls_support/config/preset", + "${efr32_sdk_root}/platform/security/sl_component/sl_mbedtls_support/inc", + "${efr32_sdk_root}/platform/security/sl_component/sl_psa_driver/inc", + "${efr32_sdk_root}/util/third_party/mbedtls/include", + "${efr32_sdk_root}/util/third_party/mbedtls/library", + ] + } + source_set("sl_si91x_psa_crypto") { + # We're setting the mbedTLS config flags here as the siwx917_sdk target + # acts as the mbedTLS target for SiWx917 builds. We need this for the build + # system to recompile mbedTLS (= the SDK) when the mbedTLS config gets + # edited. + sources = [ + "${_mbedtls_root}/include/mbedtls/platform.h", + "${_mbedtls_root}/include/mbedtls/version.h", + "${chip_root}/src/platform/silabs/SiWx917/siwx917-chip-mbedtls-config.h", + "${chip_root}/src/platform/silabs/SiWx917/siwx917-chip-psa-config.h", + + # mbedtls + "${_mbedtls_root}/library/aes.c", + "${_mbedtls_root}/library/asn1parse.c", + "${_mbedtls_root}/library/asn1write.c", + "${_mbedtls_root}/library/base64.c", + "${_mbedtls_root}/library/bignum.c", + "${_mbedtls_root}/library/bignum_core.c", + "${_mbedtls_root}/library/ccm.c", + "${_mbedtls_root}/library/cipher.c", + "${_mbedtls_root}/library/cipher_wrap.c", + "${_mbedtls_root}/library/cmac.c", + "${_mbedtls_root}/library/constant_time.c", + "${_mbedtls_root}/library/ctr_drbg.c", + "${_mbedtls_root}/library/ecdh.c", + "${_mbedtls_root}/library/ecdsa.c", + "${_mbedtls_root}/library/ecjpake.c", + "${_mbedtls_root}/library/ecp.c", + "${_mbedtls_root}/library/ecp_curves.c", + "${_mbedtls_root}/library/ecp_curves_new.c", + "${_mbedtls_root}/library/entropy.c", + "${_mbedtls_root}/library/entropy_poll.c", + "${_mbedtls_root}/library/hkdf.c", + "${_mbedtls_root}/library/hmac_drbg.c", + "${_mbedtls_root}/library/md.c", + "${_mbedtls_root}/library/oid.c", + "${_mbedtls_root}/library/pem.c", + "${_mbedtls_root}/library/pk.c", + "${_mbedtls_root}/library/pk_wrap.c", + "${_mbedtls_root}/library/pkcs5.c", + "${_mbedtls_root}/library/pkparse.c", + "${_mbedtls_root}/library/pkwrite.c", + "${_mbedtls_root}/library/platform.c", + "${_mbedtls_root}/library/platform_util.c", + "${_mbedtls_root}/library/psa_crypto.c", + "${_mbedtls_root}/library/psa_crypto_aead.c", + "${_mbedtls_root}/library/psa_crypto_cipher.c", + "${_mbedtls_root}/library/psa_crypto_client.c", + "${_mbedtls_root}/library/psa_crypto_driver_wrappers_no_static.c", + "${_mbedtls_root}/library/psa_crypto_ecp.c", + "${_mbedtls_root}/library/psa_crypto_hash.c", + "${_mbedtls_root}/library/psa_crypto_mac.c", + "${_mbedtls_root}/library/psa_crypto_rsa.c", + "${_mbedtls_root}/library/psa_crypto_se.c", + "${_mbedtls_root}/library/psa_crypto_slot_management.c", + "${_mbedtls_root}/library/psa_crypto_storage.c", + "${_mbedtls_root}/library/psa_util.c", + "${_mbedtls_root}/library/sha256.c", + "${_mbedtls_root}/library/ssl_cache.c", + "${_mbedtls_root}/library/ssl_ciphersuites.c", + "${_mbedtls_root}/library/ssl_client.c", + "${_mbedtls_root}/library/ssl_cookie.c", + "${_mbedtls_root}/library/ssl_msg.c", + "${_mbedtls_root}/library/ssl_ticket.c", + "${_mbedtls_root}/library/ssl_tls.c", + "${_mbedtls_root}/library/ssl_tls12_client.c", + "${_mbedtls_root}/library/ssl_tls12_server.c", + "${_mbedtls_root}/library/threading.c", + "${_mbedtls_root}/library/version.c", + "${_mbedtls_root}/library/x509.c", + "${_mbedtls_root}/library/x509_create.c", + "${_mbedtls_root}/library/x509_crl.c", + "${_mbedtls_root}/library/x509_crt.c", + "${_mbedtls_root}/library/x509_csr.c", + "${_mbedtls_root}/library/x509write_crt.c", + "${_mbedtls_root}/library/x509write_csr.c", + + # GECKO SDK + "${efr32_sdk_root}/platform/security/sl_component/sl_mbedtls_support/src/sl_psa_crypto.c", + "${efr32_sdk_root}/platform/security/sl_component/sl_mbedtls_support/src/sli_psa_crypto.c", + "${efr32_sdk_root}/platform/security/sl_component/sl_psa_driver/src/sl_psa_its_nvm3.c", + "${efr32_sdk_root}/platform/security/sl_component/sl_psa_driver/src/sli_psa_trng.c", + + # WISECONNECT 3 SDK + "${sl_si91x_psa_crypto_path}/aead/src/sl_si91x_psa_aead.c", + "${sl_si91x_psa_crypto_path}/aes/src/sl_si91x_aes.c", + "${sl_si91x_psa_crypto_path}/aes/src/sl_si91x_psa_aes.c", + "${sl_si91x_psa_crypto_path}/ccm/src/sl_si91x_ccm.c", + "${sl_si91x_psa_crypto_path}/ecdh/src/sl_si91x_ecdh.c", + "${sl_si91x_psa_crypto_path}/ecdh/src/sl_si91x_psa_ecdh.c", + "${sl_si91x_psa_crypto_path}/ecdsa/src/sl_si91x_ecdsa.c", + "${sl_si91x_psa_crypto_path}/ecdsa/src/sl_si91x_psa_ecdsa.c", + "${sl_si91x_psa_crypto_path}/gcm/src/sl_si91x_gcm.c", + "${sl_si91x_psa_crypto_path}/hmac/src/sl_si91x_hmac.c", + "${sl_si91x_psa_crypto_path}/mac/src/sl_si91x_psa_mac.c", + "${sl_si91x_psa_crypto_path}/multithread/src/sl_si91x_crypto_thread.c", + "${sl_si91x_psa_crypto_path}/sha/src/sl_si91x_psa_sha.c", + "${sl_si91x_psa_crypto_path}/sha/src/sl_si91x_sha.c", + "${sl_si91x_psa_crypto_path}/src/sli_si91x_crypto_driver_functions.c", + "${sl_si91x_psa_crypto_path}/trng/src/sl_si91x_psa_trng.c", + "${sl_si91x_psa_crypto_path}/wrap/src/sl_si91x_psa_wrap.c", + "${sl_si91x_psa_crypto_path}/wrap/src/sl_si91x_wrap.c", + ] + + public_deps = [ "${chip_root}/src/crypto:crypto_buildconfig" ] + + public_configs = [ + ":${sdk_target_name}_config", + ":sl_si91x_psa_crypto_config", + ] + } + } + + if (sl_si91x_crypto_flavor == "tinycrypt") { + _mbedtls_root = "${mbedtls_root}/repo" + + config("siwx917_tinycrypt_config") { + defines = [ + "SL_MBEDTLS_USE_TINYCRYPT", + "MBEDTLS_CONFIG_FILE=\"siwx917-chip-mbedtls-config.h\"", + ] + + include_dirs = [ + "${sdk_support_root}/matter/mbedtls/tinycrypt/inc", + "${_mbedtls_root}/include", + "${_mbedtls_root}/library", + + # GECKO SDK configuration included to be used in autogenerated files + "${efr32_sdk_root}/platform/security/sl_component/sl_mbedtls_support/config", + "${efr32_sdk_root}/platform/security/sl_component/sl_mbedtls_support/config/preset", + "${efr32_sdk_root}/platform/security/sl_component/sl_mbedtls_support/inc", + ] + } + + source_set("siwx917_tinycrypt") { + sources = [ + # config file + "${_mbedtls_root}/include/mbedtls/platform.h", + "${_mbedtls_root}/include/mbedtls/version.h", + "${chip_root}/src/platform/silabs/SiWx917/siwx917-chip-mbedtls-config.h", + + # mbedtls + "${_mbedtls_root}/library/aes.c", + "${_mbedtls_root}/library/asn1parse.c", + "${_mbedtls_root}/library/asn1write.c", + "${_mbedtls_root}/library/base64.c", + "${_mbedtls_root}/library/bignum.c", + "${_mbedtls_root}/library/ccm.c", + "${_mbedtls_root}/library/cipher.c", + "${_mbedtls_root}/library/cipher_wrap.c", + "${_mbedtls_root}/library/constant_time.c", + "${_mbedtls_root}/library/ctr_drbg.c", + "${_mbedtls_root}/library/ecdh.c", + "${_mbedtls_root}/library/ecdsa.c", + "${_mbedtls_root}/library/ecp.c", + "${_mbedtls_root}/library/ecp_curves.c", + "${_mbedtls_root}/library/entropy.c", + "${_mbedtls_root}/library/hkdf.c", + "${_mbedtls_root}/library/hmac_drbg.c", + "${_mbedtls_root}/library/md.c", + "${_mbedtls_root}/library/pem.c", + "${_mbedtls_root}/library/pkcs5.c", + "${_mbedtls_root}/library/platform.c", + "${_mbedtls_root}/library/sha256.c", + "${_mbedtls_root}/library/sha512.c", + "${_mbedtls_root}/library/version.c", + "${_mbedtls_root}/library/x509_create.c", + + # tinycrypt + "${sdk_support_root}/matter/mbedtls/tinycrypt/src/ecc.c", + "${sdk_support_root}/matter/mbedtls/tinycrypt/src/ecc_dh.c", + "${sdk_support_root}/matter/mbedtls/tinycrypt/src/ecc_dsa.c", + "${sdk_support_root}/matter/mbedtls/tinycrypt/src/error.c", + "${sdk_support_root}/matter/mbedtls/tinycrypt/src/oid.c", + "${sdk_support_root}/matter/mbedtls/tinycrypt/src/pk.c", + "${sdk_support_root}/matter/mbedtls/tinycrypt/src/pk_wrap.c", + "${sdk_support_root}/matter/mbedtls/tinycrypt/src/pkparse.c", + "${sdk_support_root}/matter/mbedtls/tinycrypt/src/pkwrite.c", + "${sdk_support_root}/matter/mbedtls/tinycrypt/src/platform_util.c", + "${sdk_support_root}/matter/mbedtls/tinycrypt/src/x509_crt.c", + "${sdk_support_root}/matter/mbedtls/tinycrypt/src/x509write_csr.c", + ] + + public_deps = [ "${chip_root}/src/crypto:crypto_buildconfig" ] + + public_configs = [ + ":${sdk_target_name}_config", + ":siwx917_tinycrypt_config", + ] + } + } + } source_set(sdk_target_name) { sources = [ # si91x component @@ -487,46 +719,9 @@ template("siwx917_sdk") { "${efr32_sdk_root}/platform/service/memory_manager/src/sl_memory_manager_retarget.c", "${efr32_sdk_root}/platform/service/memory_manager/src/sli_memory_manager_common.c", - # mbedtls - "${chip_root}/third_party/mbedtls/repo/library/aes.c", - "${chip_root}/third_party/mbedtls/repo/library/asn1parse.c", - "${chip_root}/third_party/mbedtls/repo/library/asn1write.c", - "${chip_root}/third_party/mbedtls/repo/library/base64.c", - "${chip_root}/third_party/mbedtls/repo/library/bignum.c", - "${chip_root}/third_party/mbedtls/repo/library/ccm.c", - "${chip_root}/third_party/mbedtls/repo/library/cipher.c", - "${chip_root}/third_party/mbedtls/repo/library/cipher_wrap.c", - "${chip_root}/third_party/mbedtls/repo/library/constant_time.c", - "${chip_root}/third_party/mbedtls/repo/library/ctr_drbg.c", - "${chip_root}/third_party/mbedtls/repo/library/ecdh.c", - "${chip_root}/third_party/mbedtls/repo/library/ecdsa.c", - "${chip_root}/third_party/mbedtls/repo/library/ecp.c", - "${chip_root}/third_party/mbedtls/repo/library/ecp_curves.c", - "${chip_root}/third_party/mbedtls/repo/library/entropy.c", - "${chip_root}/third_party/mbedtls/repo/library/hkdf.c", - "${chip_root}/third_party/mbedtls/repo/library/hmac_drbg.c", - "${chip_root}/third_party/mbedtls/repo/library/md.c", - "${chip_root}/third_party/mbedtls/repo/library/pem.c", - "${chip_root}/third_party/mbedtls/repo/library/pkcs5.c", - "${chip_root}/third_party/mbedtls/repo/library/platform.c", - "${chip_root}/third_party/mbedtls/repo/library/sha256.c", - "${chip_root}/third_party/mbedtls/repo/library/sha512.c", - "${chip_root}/third_party/mbedtls/repo/library/x509.c", - "${chip_root}/third_party/mbedtls/repo/library/x509_create.c", + # STARTUP FILES "${efr32_sdk_root}/platform/service/iostream/src/sl_iostream.c", "${efr32_sdk_root}/platform/service/iostream/src/sl_iostream_rtt.c", - "${sdk_support_root}/matter/mbedtls/tinycrypt/src/ecc.c", - "${sdk_support_root}/matter/mbedtls/tinycrypt/src/ecc_dh.c", - "${sdk_support_root}/matter/mbedtls/tinycrypt/src/ecc_dsa.c", - "${sdk_support_root}/matter/mbedtls/tinycrypt/src/error.c", - "${sdk_support_root}/matter/mbedtls/tinycrypt/src/oid.c", - "${sdk_support_root}/matter/mbedtls/tinycrypt/src/pk.c", - "${sdk_support_root}/matter/mbedtls/tinycrypt/src/pk_wrap.c", - "${sdk_support_root}/matter/mbedtls/tinycrypt/src/pkparse.c", - "${sdk_support_root}/matter/mbedtls/tinycrypt/src/pkwrite.c", - "${sdk_support_root}/matter/mbedtls/tinycrypt/src/platform_util.c", - "${sdk_support_root}/matter/mbedtls/tinycrypt/src/x509_crt.c", - "${sdk_support_root}/matter/mbedtls/tinycrypt/src/x509write_csr.c", "${sdk_support_root}/matter/si91x/siwx917/BRD4338A/support/src/startup_common_RS1xxxx.c", "${wifi_sdk_root}/components/device/silabs/si91x/mcu/drivers/service/nvm3/src/sl_si91x_common_flash_intf.c", @@ -579,29 +774,38 @@ template("siwx917_sdk") { "${wifi_sdk_root}/components/device/silabs/si91x/mcu/drivers/systemlevel/src/rsi_time_period.c", ] } + public_deps = [ - ":siwx917_mbedtls_config", "${segger_rtt_root}:segger_rtt", "${segger_rtt_root}:segger_rtt_printf", "${segger_rtt_root}:segger_rtt_syscalls", ] + if (chip_crypto == "platform") { + if (sl_si91x_crypto_flavor == "tinycrypt") { + public_deps += [ ":siwx917_tinycrypt" ] + } + + if (sl_si91x_crypto_flavor == "psa") { + public_deps += [ ":sl_si91x_psa_crypto" ] + } + } if (defined(invoker.sources)) { sources += invoker.sources } if (invoker.enable_dic) { sources += [ - "${chip_root}/third_party/mbedtls/repo/library/debug.c", - "${chip_root}/third_party/mbedtls/repo/library/ecjpake.c", - "${chip_root}/third_party/mbedtls/repo/library/rsa.c", - "${chip_root}/third_party/mbedtls/repo/library/rsa_internal.c", - "${chip_root}/third_party/mbedtls/repo/library/sha1.c", - "${chip_root}/third_party/mbedtls/repo/library/ssl_ciphersuites.c", - "${chip_root}/third_party/mbedtls/repo/library/ssl_cli.c", - "${chip_root}/third_party/mbedtls/repo/library/ssl_msg.c", - "${chip_root}/third_party/mbedtls/repo/library/ssl_srv.c", - "${chip_root}/third_party/mbedtls/repo/library/ssl_tls.c", - "${chip_root}/third_party/silabs/mqtt/stack/mqtt.c", + "${_mbedtls_root}/library/ecjpake.c", + "${_mbedtls_root}/library/rsa.c", + "${_mbedtls_root}/library/rsa_internal.c", + "${_mbedtls_root}/library/sha1.c", + "${_mbedtls_root}/library/ssl_ciphersuites.c", + "${_mbedtls_root}/library/ssl_cli.c", + "${_mbedtls_root}/library/ssl_msg.c", + "${_mbedtls_root}/library/ssl_srv.c", + "${_mbedtls_root}/library/ssl_tls.c", + "${_mbedtls_root}/library/x509.c", + "${efr32_sdk_build_root}/mqtt/stack/mqtt.c", ] } From 03ae36eff60e7cd2eaf40f35a833896b84190a41 Mon Sep 17 00:00:00 2001 From: Boris Zbarsky Date: Thu, 27 Jun 2024 14:32:21 -0400 Subject: [PATCH 03/12] Fix discriminator handling in chip-tool pairing commands. (#34115) Not all commands initialize the discriminator value, and the ones that don't should not use it. Fixes https://github.com/project-chip/connectedhomeip/issues/34096 --- .../commands/pairing/PairingCommand.cpp | 17 +++++++++--- .../commands/pairing/PairingCommand.h | 26 ++++++++++++------- 2 files changed, 31 insertions(+), 12 deletions(-) diff --git a/examples/chip-tool/commands/pairing/PairingCommand.cpp b/examples/chip-tool/commands/pairing/PairingCommand.cpp index a0437c53f56a7d..7bddfa3d08039c 100644 --- a/examples/chip-tool/commands/pairing/PairingCommand.cpp +++ b/examples/chip-tool/commands/pairing/PairingCommand.cpp @@ -216,7 +216,12 @@ CHIP_ERROR PairingCommand::PairWithCode(NodeId remoteId) CHIP_ERROR PairingCommand::Pair(NodeId remoteId, PeerAddress address) { - auto params = RendezvousParameters().SetSetupPINCode(mSetupPINCode).SetDiscriminator(mDiscriminator).SetPeerAddress(address); + VerifyOrDieWithMsg(mSetupPINCode.has_value(), chipTool, "Using mSetupPINCode in a mode when we have not gotten one"); + auto params = RendezvousParameters().SetSetupPINCode(mSetupPINCode.value()).SetPeerAddress(address); + if (mDiscriminator.has_value()) + { + params.SetDiscriminator(mDiscriminator.value()); + } CHIP_ERROR err = CHIP_NO_ERROR; if (mPaseOnly.ValueOr(false)) @@ -236,9 +241,11 @@ CHIP_ERROR PairingCommand::PairWithMdnsOrBleByIndex(NodeId remoteId, uint16_t in #if CHIP_DEVICE_LAYER_TARGET_DARWIN VerifyOrReturnError(IsInteractive(), CHIP_ERROR_INCORRECT_STATE); + VerifyOrDieWithMsg(mSetupPINCode.has_value(), chipTool, "Using mSetupPINCode in a mode when we have not gotten one"); + RendezvousParameters params; ReturnErrorOnFailure(GetDeviceScanner().Get(index, params)); - params.SetSetupPINCode(mSetupPINCode); + params.SetSetupPINCode(mSetupPINCode.value()); CHIP_ERROR err = CHIP_NO_ERROR; if (mPaseOnly.ValueOr(false)) @@ -258,6 +265,10 @@ CHIP_ERROR PairingCommand::PairWithMdnsOrBleByIndex(NodeId remoteId, uint16_t in CHIP_ERROR PairingCommand::PairWithMdnsOrBleByIndexWithCode(NodeId remoteId, uint16_t index) { + // We might or might not have a setup code. We don't know yet, but if we + // do, we'll emplace it at that point. + mSetupPINCode.reset(); + #if CHIP_DEVICE_LAYER_TARGET_DARWIN VerifyOrReturnError(IsInteractive(), CHIP_ERROR_INCORRECT_STATE); @@ -281,7 +292,7 @@ CHIP_ERROR PairingCommand::PairWithMdnsOrBleByIndexWithCode(NodeId remoteId, uin VerifyOrReturnError(payload.isValidManualCode(), CHIP_ERROR_INVALID_ARGUMENT); } - mSetupPINCode = payload.setUpPINCode; + mSetupPINCode.emplace(payload.setUpPINCode); return PairWithMdnsOrBleByIndex(remoteId, index); } diff --git a/examples/chip-tool/commands/pairing/PairingCommand.h b/examples/chip-tool/commands/pairing/PairingCommand.h index 9ff63e37878576..facb0f2403536b 100644 --- a/examples/chip-tool/commands/pairing/PairingCommand.h +++ b/examples/chip-tool/commands/pairing/PairingCommand.h @@ -26,6 +26,8 @@ #include #include +#include + enum class PairingMode { None, @@ -107,32 +109,32 @@ class PairingCommand : public CHIPCommand, break; case PairingMode::Ble: AddArgument("skip-commissioning-complete", 0, 1, &mSkipCommissioningComplete); - AddArgument("setup-pin-code", 0, 134217727, &mSetupPINCode); - AddArgument("discriminator", 0, 4096, &mDiscriminator); + AddArgument("setup-pin-code", 0, 134217727, &mSetupPINCode.emplace()); + AddArgument("discriminator", 0, 4096, &mDiscriminator.emplace()); break; case PairingMode::OnNetwork: AddArgument("skip-commissioning-complete", 0, 1, &mSkipCommissioningComplete); - AddArgument("setup-pin-code", 0, 134217727, &mSetupPINCode); + AddArgument("setup-pin-code", 0, 134217727, &mSetupPINCode.emplace()); AddArgument("pase-only", 0, 1, &mPaseOnly); break; case PairingMode::SoftAP: AddArgument("skip-commissioning-complete", 0, 1, &mSkipCommissioningComplete); - AddArgument("setup-pin-code", 0, 134217727, &mSetupPINCode); - AddArgument("discriminator", 0, 4096, &mDiscriminator); + AddArgument("setup-pin-code", 0, 134217727, &mSetupPINCode.emplace()); + AddArgument("discriminator", 0, 4096, &mDiscriminator.emplace()); AddArgument("device-remote-ip", &mRemoteAddr); AddArgument("device-remote-port", 0, UINT16_MAX, &mRemotePort); AddArgument("pase-only", 0, 1, &mPaseOnly); break; case PairingMode::AlreadyDiscovered: AddArgument("skip-commissioning-complete", 0, 1, &mSkipCommissioningComplete); - AddArgument("setup-pin-code", 0, 134217727, &mSetupPINCode); + AddArgument("setup-pin-code", 0, 134217727, &mSetupPINCode.emplace()); AddArgument("device-remote-ip", &mRemoteAddr); AddArgument("device-remote-port", 0, UINT16_MAX, &mRemotePort); AddArgument("pase-only", 0, 1, &mPaseOnly); break; case PairingMode::AlreadyDiscoveredByIndex: AddArgument("skip-commissioning-complete", 0, 1, &mSkipCommissioningComplete); - AddArgument("setup-pin-code", 0, 134217727, &mSetupPINCode); + AddArgument("setup-pin-code", 0, 134217727, &mSetupPINCode.emplace()); AddArgument("index", 0, UINT16_MAX, &mIndex); AddArgument("pase-only", 0, 1, &mPaseOnly); break; @@ -252,8 +254,14 @@ class PairingCommand : public CHIPCommand, mComplex_DSTOffsets; uint16_t mRemotePort; - uint16_t mDiscriminator; - uint32_t mSetupPINCode; + // mDiscriminator is only used for some situations, but in those situations + // it's mandatory. Track whether we're actually using it; the cases that do + // will emplace this optional. + std::optional mDiscriminator; + // mSetupPINCode is only used for some situations, but in those situations + // it's mandatory. Track whether we're actually using it; the cases that do + // will emplace this optional. + std::optional mSetupPINCode; uint16_t mIndex; chip::ByteSpan mOperationalDataset; chip::ByteSpan mSSID; From 0460715589413cb32e32f1626e43ad8000b84f2d Mon Sep 17 00:00:00 2001 From: Rohit Jadhav <69809379+jadhavrohit924@users.noreply.github.com> Date: Fri, 28 Jun 2024 12:52:36 +0530 Subject: [PATCH 04/12] [ESP32]: Fix ble scanning for esp32 (#34110) * [ESP32]: Fix ble scanning for esp32 * Restyled by clang-format * Address review comment --------- Co-authored-by: Restyled.io --- src/platform/ESP32/ChipDeviceScanner.h | 2 +- src/platform/ESP32/nimble/BLEManagerImpl.cpp | 8 +++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/platform/ESP32/ChipDeviceScanner.h b/src/platform/ESP32/ChipDeviceScanner.h index d921ba08e859a2..81c23d8f921fa8 100644 --- a/src/platform/ESP32/ChipDeviceScanner.h +++ b/src/platform/ESP32/ChipDeviceScanner.h @@ -17,6 +17,7 @@ #pragma once +#include #include #include @@ -31,7 +32,6 @@ #include "esp_gattc_api.h" #include "esp_log.h" #include "freertos/FreeRTOS.h" -#include #include #include #endif diff --git a/src/platform/ESP32/nimble/BLEManagerImpl.cpp b/src/platform/ESP32/nimble/BLEManagerImpl.cpp index 189ebd9dae6775..c581d1fd6d6290 100644 --- a/src/platform/ESP32/nimble/BLEManagerImpl.cpp +++ b/src/platform/ESP32/nimble/BLEManagerImpl.cpp @@ -659,7 +659,13 @@ bool BLEManagerImpl::SendWriteRequest(BLE_CONNECTION_OBJECT conId, const ChipBle return false; } - rc = ble_gattc_write_flat(conId, chr->chr.val_handle, pBuf->Start(), pBuf->DataLength(), OnWriteComplete, this); + if (pBuf->DataLength() > UINT16_MAX) + { + ChipLogError(Ble, "Buffer data Length is too long"); + return false; + } + rc = ble_gattc_write_flat(conId, chr->chr.val_handle, pBuf->Start(), static_cast(pBuf->DataLength()), OnWriteComplete, + this); if (rc != 0) { ChipLogError(Ble, "ble_gattc_write_flat failed: %d", rc); From c99be08f1a56fba3549c2d4a0c745e2626707cee Mon Sep 17 00:00:00 2001 From: Vatsal Ghelani <152916324+vatsalghelani-csa@users.noreply.github.com> Date: Fri, 28 Jun 2024 09:44:58 -0400 Subject: [PATCH 05/12] Third set of test scripts to have automated implementation of python tests to use Metadata script as an intermediate argument holder (#34063) * Adding more python tests to use Metadata script for arguments * Adding more python tests to use Metadata script for arguments * Adding more python tests to use Metadata script for arguments * Add tracing support for microwave-oven-app * Add tracing support for rvc-app --- .github/workflows/tests.yaml | 50 +++++++++++----------- examples/microwave-oven-app/linux/args.gni | 2 + examples/rvc-app/linux/args.gni | 2 + src/python_testing/TC_MWOCTRL_2_1.py | 7 +++ src/python_testing/TC_MWOCTRL_2_2.py | 7 +++ src/python_testing/TC_MWOCTRL_2_4.py | 7 +++ src/python_testing/TC_MWOM_1_2.py | 7 +++ src/python_testing/TC_OPCREDS_3_2.py | 7 +++ src/python_testing/TC_OPSTATE_2_1.py | 6 +++ src/python_testing/TC_OPSTATE_2_2.py | 6 +++ src/python_testing/TC_OPSTATE_2_3.py | 7 +++ src/python_testing/TC_OPSTATE_2_4.py | 7 +++ src/python_testing/TC_OPSTATE_2_5.py | 7 +++ src/python_testing/TC_OVENOPSTATE_2_1.py | 7 +++ src/python_testing/TC_OVENOPSTATE_2_2.py | 6 +++ src/python_testing/TC_OVENOPSTATE_2_3.py | 6 +++ src/python_testing/TC_OVENOPSTATE_2_4.py | 6 +++ src/python_testing/TC_OVENOPSTATE_2_5.py | 7 +++ src/python_testing/TC_RVCCLEANM_1_2.py | 7 +++ src/python_testing/TC_RVCCLEANM_2_1.py | 7 +++ src/python_testing/TC_RVCCLEANM_2_2.py | 7 +++ src/python_testing/TC_RVCOPSTATE_2_1.py | 7 +++ src/python_testing/TC_RVCOPSTATE_2_3.py | 7 +++ src/python_testing/TC_RVCOPSTATE_2_4.py | 7 +++ src/python_testing/TC_RVCRUNM_1_2.py | 7 +++ src/python_testing/TC_RVCRUNM_2_1.py | 7 +++ src/python_testing/TC_RVCRUNM_2_2.py | 7 +++ 27 files changed, 193 insertions(+), 24 deletions(-) diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index 8c95d0d10c5a60..de9bd0d9f64193 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yaml @@ -484,6 +484,8 @@ jobs: echo "CHIP_LOCK_APP: out/linux-x64-lock-ipv6only-no-ble-no-wifi-tsan-clang-test/chip-lock-app" >> /tmp/test_env.yaml echo "ENERGY_MANAGEMENT_APP: out/linux-x64-energy-management-ipv6only-no-ble-no-wifi-tsan-clang-test/chip-energy-management-app" >> /tmp/test_env.yaml echo "LIT_ICD_APP: out/linux-x64-lit-icd-ipv6only-no-ble-no-wifi-tsan-clang-test/lit-icd-app" >> /tmp/test_env.yaml + echo "CHIP_MICROWAVE_OVEN_APP: out/linux-x64-microwave-oven-ipv6only-no-ble-no-wifi-tsan-clang-test/chip-microwave-oven-app" >> /tmp/test_env.yaml + echo "CHIP_RVC_APP: out/linux-x64-rvc-ipv6only-no-ble-no-wifi-tsan-clang-test/chip-rvc-app" >> /tmp/test_env.yaml echo "TRACE_APP: out/trace_data/app-{SCRIPT_BASE_NAME}" >> /tmp/test_env.yaml echo "TRACE_TEST_JSON: out/trace_data/test-{SCRIPT_BASE_NAME}" >> /tmp/test_env.yaml echo "TRACE_TEST_PERFETTO: out/trace_data/test-{SCRIPT_BASE_NAME}" >> /tmp/test_env.yaml @@ -546,30 +548,30 @@ jobs: scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --load-from-env /tmp/test_env.yaml --script src/python_testing/TC_TestEventTrigger.py' scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --load-from-env /tmp/test_env.yaml --script src/python_testing/TestBatchInvoke.py' scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --load-from-env /tmp/test_env.yaml --script src/python_testing/TestGroupTableReports.py' - 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 --quiet --app-args "--discriminator 1234 --KVS kvs1 --trace-to json:out/trace_data/app-{SCRIPT_BASE_NAME}.json" --script "src/python_testing/TC_OPCREDS_3_2.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 --quiet --app-args "--discriminator 1234 --KVS kvs1 --trace-to json:out/trace_data/app-{SCRIPT_BASE_NAME}.json" --script "src/python_testing/TC_OPSTATE_2_1.py" --script-args "--endpoint 1 --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 --quiet --app-args "--discriminator 1234 --KVS kvs1 --trace-to json:out/trace_data/app-{SCRIPT_BASE_NAME}.json" --script "src/python_testing/TC_OPSTATE_2_2.py" --script-args "--endpoint 1 --int-arg PIXIT.WAITTIME.COUNTDOWN:5 --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 --quiet --app-args "--discriminator 1234 --KVS kvs1 --trace-to json:out/trace_data/app-{SCRIPT_BASE_NAME}.json" --script "src/python_testing/TC_OPSTATE_2_3.py" --script-args "--endpoint 1 --int-arg PIXIT.WAITTIME.COUNTDOWN:5 --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 --quiet --app-args "--discriminator 1234 --KVS kvs1 --trace-to json:out/trace_data/app-{SCRIPT_BASE_NAME}.json" --script "src/python_testing/TC_OPSTATE_2_4.py" --script-args "--endpoint 1 --int-arg PIXIT.OPSTATE.ErrorEventGen:1 --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 --quiet --app-args "--discriminator 1234 --KVS kvs1 --trace-to json:out/trace_data/app-{SCRIPT_BASE_NAME}.json" --script "src/python_testing/TC_OPSTATE_2_5.py" --script-args "--endpoint 1 --int-arg PIXIT.WAITTIME.REBOOT:5 --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 --quiet --app-args "--discriminator 1234 --KVS kvs1 --trace-to json:out/trace_data/app-{SCRIPT_BASE_NAME}.json" --script "src/python_testing/TC_OVENOPSTATE_2_1.py" --script-args "--endpoint 1 --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 --quiet --app-args "--discriminator 1234 --KVS kvs1 --trace-to json:out/trace_data/app-{SCRIPT_BASE_NAME}.json" --script "src/python_testing/TC_OVENOPSTATE_2_2.py" --script-args "--endpoint 1 --int-arg PIXIT.WAITTIME.COUNTDOWN:5 --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 --quiet --app-args "--discriminator 1234 --KVS kvs1 --trace-to json:out/trace_data/app-{SCRIPT_BASE_NAME}.json" --script "src/python_testing/TC_OVENOPSTATE_2_3.py" --script-args "--endpoint 1 --int-arg PIXIT.WAITTIME.COUNTDOWN:5 --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 --quiet --app-args "--discriminator 1234 --KVS kvs1 --trace-to json:out/trace_data/app-{SCRIPT_BASE_NAME}.json" --script "src/python_testing/TC_OVENOPSTATE_2_4.py" --script-args "--endpoint 1 --int-arg PIXIT.OVENOPSTATE.ErrorEventGen:1 --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 --quiet --app-args "--discriminator 1234 --KVS kvs1 --trace-to json:out/trace_data/app-{SCRIPT_BASE_NAME}.json" --script "src/python_testing/TC_OVENOPSTATE_2_5.py" --script-args "--endpoint 1 --int-arg PIXIT.WAITTIME.REBOOT:5 --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-microwave-oven-ipv6only-no-ble-no-wifi-tsan-clang-test/chip-microwave-oven-app --factoryreset --quiet --app-args "--discriminator 1234 --KVS kvs1 --trace_file json:out/trace_data/app-{SCRIPT_BASE_NAME}.json" --script "src/python_testing/TC_MWOCTRL_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-microwave-oven-ipv6only-no-ble-no-wifi-tsan-clang-test/chip-microwave-oven-app --factoryreset --quiet --app-args "--discriminator 1234 --KVS kvs1 --trace_file json:out/trace_data/app-{SCRIPT_BASE_NAME}.json" --script "src/python_testing/TC_MWOCTRL_2_2.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-microwave-oven-ipv6only-no-ble-no-wifi-tsan-clang-test/chip-microwave-oven-app --factoryreset --quiet --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 --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-microwave-oven-ipv6only-no-ble-no-wifi-tsan-clang-test/chip-microwave-oven-app --factoryreset --quiet --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 --quiet --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 --quiet --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 --quiet --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 --quiet --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 --quiet --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 --quiet --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 --quiet --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 --quiet --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 --quiet --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"' + scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --load-from-env /tmp/test_env.yaml --script src/python_testing/TC_OPCREDS_3_2.py' + scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --load-from-env /tmp/test_env.yaml --script src/python_testing/TC_OPSTATE_2_1.py' + scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --load-from-env /tmp/test_env.yaml --script src/python_testing/TC_OPSTATE_2_2.py' + scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --load-from-env /tmp/test_env.yaml --script src/python_testing/TC_OPSTATE_2_3.py' + scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --load-from-env /tmp/test_env.yaml --script src/python_testing/TC_OPSTATE_2_4.py' + scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --load-from-env /tmp/test_env.yaml --script src/python_testing/TC_OPSTATE_2_5.py' + scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --load-from-env /tmp/test_env.yaml --script src/python_testing/TC_OVENOPSTATE_2_1.py' + scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --load-from-env /tmp/test_env.yaml --script src/python_testing/TC_OVENOPSTATE_2_2.py' + scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --load-from-env /tmp/test_env.yaml --script src/python_testing/TC_OVENOPSTATE_2_3.py' + scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --load-from-env /tmp/test_env.yaml --script src/python_testing/TC_OVENOPSTATE_2_4.py' + scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --load-from-env /tmp/test_env.yaml --script src/python_testing/TC_OVENOPSTATE_2_5.py' + scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --load-from-env /tmp/test_env.yaml --script src/python_testing/TC_MWOCTRL_2_1.py' + scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --load-from-env /tmp/test_env.yaml --script src/python_testing/TC_MWOCTRL_2_2.py' + scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --load-from-env /tmp/test_env.yaml --script src/python_testing/TC_MWOCTRL_2_4.py' + scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --load-from-env /tmp/test_env.yaml --script src/python_testing/TC_MWOM_1_2.py' + scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --load-from-env /tmp/test_env.yaml --script src/python_testing/TC_RVCRUNM_1_2.py' + scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --load-from-env /tmp/test_env.yaml --script src/python_testing/TC_RVCRUNM_2_1.py' + scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --load-from-env /tmp/test_env.yaml --script src/python_testing/TC_RVCRUNM_2_2.py' + scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --load-from-env /tmp/test_env.yaml --script src/python_testing/TC_RVCCLEANM_1_2.py' + scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --load-from-env /tmp/test_env.yaml --script src/python_testing/TC_RVCCLEANM_2_1.py' + scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --load-from-env /tmp/test_env.yaml --script src/python_testing/TC_RVCCLEANM_2_2.py' + scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --load-from-env /tmp/test_env.yaml --script src/python_testing/TC_RVCOPSTATE_2_1.py' + scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --load-from-env /tmp/test_env.yaml --script src/python_testing/TC_RVCOPSTATE_2_3.py' + scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --load-from-env /tmp/test_env.yaml --script src/python_testing/TC_RVCOPSTATE_2_4.py' scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --script "src/python_testing/TestConformanceSupport.py" --script-args "--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 --script "src/python_testing/TestMatterTestingSupport.py" --script-args "--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 --script "src/python_testing/TestSpecParsingSupport.py" --script-args "--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/examples/microwave-oven-app/linux/args.gni b/examples/microwave-oven-app/linux/args.gni index 82aa84a5c1d9d3..5db04073a5979e 100644 --- a/examples/microwave-oven-app/linux/args.gni +++ b/examples/microwave-oven-app/linux/args.gni @@ -25,3 +25,5 @@ chip_system_project_config_include = "" chip_project_config_include_dirs = [ "${chip_root}/examples/microwave-oven-app/linux/include" ] chip_project_config_include_dirs += [ "${chip_root}/config/standalone" ] + +matter_enable_tracing_support = true diff --git a/examples/rvc-app/linux/args.gni b/examples/rvc-app/linux/args.gni index a94a8482760fbc..dd83cecad49ae0 100644 --- a/examples/rvc-app/linux/args.gni +++ b/examples/rvc-app/linux/args.gni @@ -23,3 +23,5 @@ chip_system_project_config_include = "" chip_project_config_include_dirs = [ "${chip_root}/examples/rvc-app/linux/include" ] chip_project_config_include_dirs += [ "${chip_root}/config/standalone" ] + +matter_enable_tracing_support = true diff --git a/src/python_testing/TC_MWOCTRL_2_1.py b/src/python_testing/TC_MWOCTRL_2_1.py index 658bdb3ae8e431..225a4569b345f0 100644 --- a/src/python_testing/TC_MWOCTRL_2_1.py +++ b/src/python_testing/TC_MWOCTRL_2_1.py @@ -15,6 +15,13 @@ # limitations under the License. # +# test-runner-runs: run1 +# test-runner-run/run1/app: ${CHIP_MICROWAVE_OVEN_APP} +# test-runner-run/run1/factoryreset: True +# test-runner-run/run1/quiet: True +# test-runner-run/run1/app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json +# test-runner-run/run1/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:${TRACE_TEST_JSON}.json --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto + import chip.clusters as Clusters from chip.interaction_model import InteractionModelError, Status from matter_testing_support import MatterBaseTest, TestStep, async_test_body, default_matter_test_main diff --git a/src/python_testing/TC_MWOCTRL_2_2.py b/src/python_testing/TC_MWOCTRL_2_2.py index ae496f6a669387..54cf7a90463831 100644 --- a/src/python_testing/TC_MWOCTRL_2_2.py +++ b/src/python_testing/TC_MWOCTRL_2_2.py @@ -15,6 +15,13 @@ # limitations under the License. # +# test-runner-runs: run1 +# test-runner-run/run1/app: ${CHIP_MICROWAVE_OVEN_APP} +# test-runner-run/run1/factoryreset: True +# test-runner-run/run1/quiet: True +# test-runner-run/run1/app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json +# test-runner-run/run1/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:${TRACE_TEST_JSON}.json --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto + import logging import chip.clusters as Clusters diff --git a/src/python_testing/TC_MWOCTRL_2_4.py b/src/python_testing/TC_MWOCTRL_2_4.py index 8cb3885ada0613..136f9f882ab20e 100644 --- a/src/python_testing/TC_MWOCTRL_2_4.py +++ b/src/python_testing/TC_MWOCTRL_2_4.py @@ -15,6 +15,13 @@ # limitations under the License. # +# test-runner-runs: run1 +# test-runner-run/run1/app: ${CHIP_MICROWAVE_OVEN_APP} +# test-runner-run/run1/factoryreset: True +# test-runner-run/run1/quiet: True +# test-runner-run/run1/app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json +# test-runner-run/run1/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:${TRACE_TEST_JSON}.json --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto + import logging import chip.clusters as Clusters diff --git a/src/python_testing/TC_MWOM_1_2.py b/src/python_testing/TC_MWOM_1_2.py index 8dc60d9e131e68..c92f8d5c5804fc 100644 --- a/src/python_testing/TC_MWOM_1_2.py +++ b/src/python_testing/TC_MWOM_1_2.py @@ -15,6 +15,13 @@ # limitations under the License. # +# test-runner-runs: run1 +# test-runner-run/run1/app: ${CHIP_MICROWAVE_OVEN_APP} +# test-runner-run/run1/factoryreset: True +# test-runner-run/run1/quiet: True +# test-runner-run/run1/app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json +# test-runner-run/run1/script-args: --storage-path admin_storage.json --commissioning-method on-network --discriminator 1234 --passcode 20202021 --trace-to json:${TRACE_TEST_JSON}.json --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto + import logging import chip.clusters as Clusters diff --git a/src/python_testing/TC_OPCREDS_3_2.py b/src/python_testing/TC_OPCREDS_3_2.py index 5b7cd5bd59480e..384540c249e7ca 100644 --- a/src/python_testing/TC_OPCREDS_3_2.py +++ b/src/python_testing/TC_OPCREDS_3_2.py @@ -15,6 +15,13 @@ # limitations under the License. # +# test-runner-runs: run1 +# test-runner-run/run1/app: ${ALL_CLUSTERS_APP} +# test-runner-run/run1/factoryreset: True +# test-runner-run/run1/quiet: True +# test-runner-run/run1/app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json +# test-runner-run/run1/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:${TRACE_TEST_JSON}.json --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto + import chip.clusters as Clusters from chip.tlv import TLVReader from chip.utils import CommissioningBuildingBlocks diff --git a/src/python_testing/TC_OPSTATE_2_1.py b/src/python_testing/TC_OPSTATE_2_1.py index 0827202af71c29..ef9afa0a14b741 100644 --- a/src/python_testing/TC_OPSTATE_2_1.py +++ b/src/python_testing/TC_OPSTATE_2_1.py @@ -15,6 +15,12 @@ # limitations under the License. # +# test-runner-runs: run1 +# test-runner-run/run1/app: ${ALL_CLUSTERS_APP} +# test-runner-run/run1/factoryreset: True +# test-runner-run/run1/quiet: True +# test-runner-run/run1/app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json +# test-runner-run/run1/script-args: --endpoint 1 --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:${TRACE_TEST_JSON}.json --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto import chip.clusters as Clusters from matter_testing_support import MatterBaseTest, TestStep, async_test_body, default_matter_test_main diff --git a/src/python_testing/TC_OPSTATE_2_2.py b/src/python_testing/TC_OPSTATE_2_2.py index 59d36b56cfa66d..e8b5286af5ee5c 100644 --- a/src/python_testing/TC_OPSTATE_2_2.py +++ b/src/python_testing/TC_OPSTATE_2_2.py @@ -15,6 +15,12 @@ # limitations under the License. # +# test-runner-runs: run1 +# test-runner-run/run1/app: ${ALL_CLUSTERS_APP} +# test-runner-run/run1/factoryreset: True +# test-runner-run/run1/quiet: True +# test-runner-run/run1/app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json +# test-runner-run/run1/script-args: --endpoint 1 --int-arg PIXIT.WAITTIME.COUNTDOWN:5 --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:${TRACE_TEST_JSON}.json --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto import chip.clusters as Clusters from matter_testing_support import MatterBaseTest, TestStep, async_test_body, default_matter_test_main diff --git a/src/python_testing/TC_OPSTATE_2_3.py b/src/python_testing/TC_OPSTATE_2_3.py index e05aef4f607263..c8abb6bc88a38b 100644 --- a/src/python_testing/TC_OPSTATE_2_3.py +++ b/src/python_testing/TC_OPSTATE_2_3.py @@ -15,6 +15,13 @@ # limitations under the License. # +# test-runner-runs: run1 +# test-runner-run/run1/app: ${ALL_CLUSTERS_APP} +# test-runner-run/run1/factoryreset: True +# test-runner-run/run1/quiet: True +# test-runner-run/run1/app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json +# test-runner-run/run1/script-args: --endpoint 1 --int-arg PIXIT.WAITTIME.COUNTDOWN:5 --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:${TRACE_TEST_JSON}.json --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto + import chip.clusters as Clusters from matter_testing_support import MatterBaseTest, TestStep, async_test_body, default_matter_test_main diff --git a/src/python_testing/TC_OPSTATE_2_4.py b/src/python_testing/TC_OPSTATE_2_4.py index 7ad8fbccd9cd42..21e18fd10cd8a5 100644 --- a/src/python_testing/TC_OPSTATE_2_4.py +++ b/src/python_testing/TC_OPSTATE_2_4.py @@ -15,6 +15,13 @@ # limitations under the License. # +# test-runner-runs: run1 +# test-runner-run/run1/app: ${ALL_CLUSTERS_APP} +# test-runner-run/run1/factoryreset: True +# test-runner-run/run1/quiet: True +# test-runner-run/run1/app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json +# test-runner-run/run1/script-args: --endpoint 1 --int-arg PIXIT.OPSTATE.ErrorEventGen:1 --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:${TRACE_TEST_JSON}.json --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto + import chip.clusters as Clusters from matter_testing_support import MatterBaseTest, TestStep, async_test_body, default_matter_test_main diff --git a/src/python_testing/TC_OPSTATE_2_5.py b/src/python_testing/TC_OPSTATE_2_5.py index ffaceaeb2863a0..fe42a59ffb0b8f 100644 --- a/src/python_testing/TC_OPSTATE_2_5.py +++ b/src/python_testing/TC_OPSTATE_2_5.py @@ -15,6 +15,13 @@ # limitations under the License. # +# test-runner-runs: run1 +# test-runner-run/run1/app: ${ALL_CLUSTERS_APP} +# test-runner-run/run1/factoryreset: True +# test-runner-run/run1/quiet: True +# test-runner-run/run1/app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json +# test-runner-run/run1/script-args: --endpoint 1 --int-arg PIXIT.WAITTIME.REBOOT:5 --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:${TRACE_TEST_JSON}.json --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto + import chip.clusters as Clusters from matter_testing_support import MatterBaseTest, TestStep, async_test_body, default_matter_test_main diff --git a/src/python_testing/TC_OVENOPSTATE_2_1.py b/src/python_testing/TC_OVENOPSTATE_2_1.py index e6847f22e94f39..56d7fe2087818a 100644 --- a/src/python_testing/TC_OVENOPSTATE_2_1.py +++ b/src/python_testing/TC_OVENOPSTATE_2_1.py @@ -15,6 +15,13 @@ # limitations under the License. # +# test-runner-runs: run1 +# test-runner-run/run1/app: ${ALL_CLUSTERS_APP} +# test-runner-run/run1/factoryreset: True +# test-runner-run/run1/quiet: True +# test-runner-run/run1/app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json +# test-runner-run/run1/script-args: --endpoint 1 --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:${TRACE_TEST_JSON}.json --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto + import chip.clusters as Clusters from matter_testing_support import MatterBaseTest, TestStep, async_test_body, default_matter_test_main diff --git a/src/python_testing/TC_OVENOPSTATE_2_2.py b/src/python_testing/TC_OVENOPSTATE_2_2.py index 7789f5076a7d0a..158bae59260ff3 100644 --- a/src/python_testing/TC_OVENOPSTATE_2_2.py +++ b/src/python_testing/TC_OVENOPSTATE_2_2.py @@ -15,6 +15,12 @@ # limitations under the License. # +# test-runner-runs: run1 +# test-runner-run/run1/app: ${ALL_CLUSTERS_APP} +# test-runner-run/run1/factoryreset: True +# test-runner-run/run1/quiet: True +# test-runner-run/run1/app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json +# test-runner-run/run1/script-args: --endpoint 1 --int-arg PIXIT.WAITTIME.COUNTDOWN:5 --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:${TRACE_TEST_JSON}.json --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto import chip.clusters as Clusters from matter_testing_support import MatterBaseTest, TestStep, async_test_body, default_matter_test_main diff --git a/src/python_testing/TC_OVENOPSTATE_2_3.py b/src/python_testing/TC_OVENOPSTATE_2_3.py index 25434978320b46..1f882b3b4ba987 100644 --- a/src/python_testing/TC_OVENOPSTATE_2_3.py +++ b/src/python_testing/TC_OVENOPSTATE_2_3.py @@ -15,6 +15,12 @@ # limitations under the License. # +# test-runner-runs: run1 +# test-runner-run/run1/app: ${ALL_CLUSTERS_APP} +# test-runner-run/run1/factoryreset: True +# test-runner-run/run1/quiet: True +# test-runner-run/run1/app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json +# test-runner-run/run1/script-args: --endpoint 1 --int-arg PIXIT.WAITTIME.COUNTDOWN:5 --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:${TRACE_TEST_JSON}.json --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto import chip.clusters as Clusters from matter_testing_support import MatterBaseTest, TestStep, async_test_body, default_matter_test_main diff --git a/src/python_testing/TC_OVENOPSTATE_2_4.py b/src/python_testing/TC_OVENOPSTATE_2_4.py index 4bc2040638b820..7fa53e73dd8e5f 100644 --- a/src/python_testing/TC_OVENOPSTATE_2_4.py +++ b/src/python_testing/TC_OVENOPSTATE_2_4.py @@ -15,6 +15,12 @@ # limitations under the License. # +# test-runner-runs: run1 +# test-runner-run/run1/app: ${ALL_CLUSTERS_APP} +# test-runner-run/run1/factoryreset: True +# test-runner-run/run1/quiet: True +# test-runner-run/run1/app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json +# test-runner-run/run1/script-args: --endpoint 1 --int-arg PIXIT.OVENOPSTATE.ErrorEventGen:1 --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:${TRACE_TEST_JSON}.json --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto import chip.clusters as Clusters from matter_testing_support import MatterBaseTest, TestStep, async_test_body, default_matter_test_main diff --git a/src/python_testing/TC_OVENOPSTATE_2_5.py b/src/python_testing/TC_OVENOPSTATE_2_5.py index 7754f0a624ffd3..0982ec4f2ff64c 100644 --- a/src/python_testing/TC_OVENOPSTATE_2_5.py +++ b/src/python_testing/TC_OVENOPSTATE_2_5.py @@ -15,6 +15,13 @@ # limitations under the License. # +# test-runner-runs: run1 +# test-runner-run/run1/app: ${ALL_CLUSTERS_APP} +# test-runner-run/run1/factoryreset: True +# test-runner-run/run1/quiet: True +# test-runner-run/run1/app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json +# test-runner-run/run1/script-args: --endpoint 1 --int-arg PIXIT.WAITTIME.REBOOT:5 --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:${TRACE_TEST_JSON}.json --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto + import chip.clusters as Clusters from matter_testing_support import MatterBaseTest, TestStep, async_test_body, default_matter_test_main diff --git a/src/python_testing/TC_RVCCLEANM_1_2.py b/src/python_testing/TC_RVCCLEANM_1_2.py index 2f3c6f9dd0085a..a0b5fa4b6fb551 100644 --- a/src/python_testing/TC_RVCCLEANM_1_2.py +++ b/src/python_testing/TC_RVCCLEANM_1_2.py @@ -15,6 +15,13 @@ # limitations under the License. # +# test-runner-runs: run1 +# test-runner-run/run1/app: ${CHIP_RVC_APP} +# test-runner-run/run1/factoryreset: True +# test-runner-run/run1/quiet: True +# test-runner-run/run1/app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json +# test-runner-run/run1/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:${TRACE_TEST_JSON}.json --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto + import logging import chip.clusters as Clusters diff --git a/src/python_testing/TC_RVCCLEANM_2_1.py b/src/python_testing/TC_RVCCLEANM_2_1.py index 8613c123b5950c..0a6e72b30cf283 100644 --- a/src/python_testing/TC_RVCCLEANM_2_1.py +++ b/src/python_testing/TC_RVCCLEANM_2_1.py @@ -15,6 +15,13 @@ # limitations under the License. # +# test-runner-runs: run1 +# test-runner-run/run1/app: ${CHIP_RVC_APP} +# test-runner-run/run1/factoryreset: True +# test-runner-run/run1/quiet: True +# test-runner-run/run1/app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json +# test-runner-run/run1/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:${TRACE_TEST_JSON}.json --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto --int-arg PIXIT.RVCCLEANM.MODE_CHANGE_FAIL:1 PIXIT.RVCCLEANM.MODE_CHANGE_OK:2 + import logging from time import sleep diff --git a/src/python_testing/TC_RVCCLEANM_2_2.py b/src/python_testing/TC_RVCCLEANM_2_2.py index 157d31924afd4a..b5f9a108a944f4 100644 --- a/src/python_testing/TC_RVCCLEANM_2_2.py +++ b/src/python_testing/TC_RVCCLEANM_2_2.py @@ -15,6 +15,13 @@ # limitations under the License. # +# test-runner-runs: run1 +# test-runner-run/run1/app: ${CHIP_RVC_APP} +# test-runner-run/run1/factoryreset: True +# test-runner-run/run1/quiet: True +# test-runner-run/run1/app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json +# test-runner-run/run1/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:${TRACE_TEST_JSON}.json --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto + from time import sleep import chip.clusters as Clusters diff --git a/src/python_testing/TC_RVCOPSTATE_2_1.py b/src/python_testing/TC_RVCOPSTATE_2_1.py index 922ae1c9348592..01d4e0c88c4b13 100644 --- a/src/python_testing/TC_RVCOPSTATE_2_1.py +++ b/src/python_testing/TC_RVCOPSTATE_2_1.py @@ -15,6 +15,13 @@ # limitations under the License. # +# test-runner-runs: run1 +# test-runner-run/run1/app: ${CHIP_RVC_APP} +# test-runner-run/run1/factoryreset: True +# test-runner-run/run1/quiet: True +# test-runner-run/run1/app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json +# test-runner-run/run1/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:${TRACE_TEST_JSON}.json --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto + import logging from time import sleep diff --git a/src/python_testing/TC_RVCOPSTATE_2_3.py b/src/python_testing/TC_RVCOPSTATE_2_3.py index ea576bbf036263..3b75515f1a23d2 100644 --- a/src/python_testing/TC_RVCOPSTATE_2_3.py +++ b/src/python_testing/TC_RVCOPSTATE_2_3.py @@ -15,6 +15,13 @@ # limitations under the License. # +# test-runner-runs: run1 +# test-runner-run/run1/app: ${CHIP_RVC_APP} +# test-runner-run/run1/factoryreset: True +# test-runner-run/run1/quiet: True +# test-runner-run/run1/app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json +# test-runner-run/run1/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:${TRACE_TEST_JSON}.json --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto + import logging from time import sleep diff --git a/src/python_testing/TC_RVCOPSTATE_2_4.py b/src/python_testing/TC_RVCOPSTATE_2_4.py index afddeb65ea6b0c..43b64b9595a172 100644 --- a/src/python_testing/TC_RVCOPSTATE_2_4.py +++ b/src/python_testing/TC_RVCOPSTATE_2_4.py @@ -15,6 +15,13 @@ # limitations under the License. # +# test-runner-runs: run1 +# test-runner-run/run1/app: ${CHIP_RVC_APP} +# test-runner-run/run1/factoryreset: True +# test-runner-run/run1/quiet: True +# test-runner-run/run1/app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json +# test-runner-run/run1/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:${TRACE_TEST_JSON}.json --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto + import logging from time import sleep diff --git a/src/python_testing/TC_RVCRUNM_1_2.py b/src/python_testing/TC_RVCRUNM_1_2.py index 4fc9a1f5cab7d9..e3e55ddcd07fa4 100644 --- a/src/python_testing/TC_RVCRUNM_1_2.py +++ b/src/python_testing/TC_RVCRUNM_1_2.py @@ -15,6 +15,13 @@ # limitations under the License. # +# test-runner-runs: run1 +# test-runner-run/run1/app: ${CHIP_RVC_APP} +# test-runner-run/run1/factoryreset: True +# test-runner-run/run1/quiet: True +# test-runner-run/run1/app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json +# test-runner-run/run1/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:${TRACE_TEST_JSON}.json --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto + import logging import chip.clusters as Clusters diff --git a/src/python_testing/TC_RVCRUNM_2_1.py b/src/python_testing/TC_RVCRUNM_2_1.py index ce9e5bf6830625..ca6986dcbb5840 100644 --- a/src/python_testing/TC_RVCRUNM_2_1.py +++ b/src/python_testing/TC_RVCRUNM_2_1.py @@ -15,6 +15,13 @@ # limitations under the License. # +# test-runner-runs: run1 +# test-runner-run/run1/app: ${CHIP_RVC_APP} +# test-runner-run/run1/factoryreset: True +# test-runner-run/run1/quiet: True +# test-runner-run/run1/app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json +# test-runner-run/run1/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:${TRACE_TEST_JSON}.json --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto --int-arg PIXIT.RVCRUNM.MODE_CHANGE_OK:0 PIXIT.RVCRUNM.MODE_CHANGE_FAIL:2 + import logging from time import sleep diff --git a/src/python_testing/TC_RVCRUNM_2_2.py b/src/python_testing/TC_RVCRUNM_2_2.py index f4d7bc9f0eb042..5723e1ec2f6fb8 100644 --- a/src/python_testing/TC_RVCRUNM_2_2.py +++ b/src/python_testing/TC_RVCRUNM_2_2.py @@ -15,6 +15,13 @@ # limitations under the License. # +# test-runner-runs: run1 +# test-runner-run/run1/app: ${CHIP_RVC_APP} +# test-runner-run/run1/factoryreset: True +# test-runner-run/run1/quiet: True +# test-runner-run/run1/app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json +# test-runner-run/run1/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:${TRACE_TEST_JSON}.json --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto --int-arg PIXIT.RVCRUNM.MODE_A:1 PIXIT.RVCRUNM.MODE_B:2 + from time import sleep import chip.clusters as Clusters From 99e20a97ef22cf5886d7a8c3575a3453ab27ed94 Mon Sep 17 00:00:00 2001 From: Erwin Pan Date: Fri, 28 Jun 2024 21:50:49 +0800 Subject: [PATCH 06/12] [Chef] Update AirPurifier composite device (#34126) * [Chef] Update AirPurifier composite device 1. Fix conformance 2. Add necessary Attributes * Update Humidity Value --- .../rootnode_airpurifier_73a6fe2651.matter | 6 +- .../rootnode_airpurifier_73a6fe2651.zap | 36 +- ...umiditysensor_thermostat_56de3d5f45.matter | 59 ++- ...r_humiditysensor_thermostat_56de3d5f45.zap | 374 +++++++++++++++++- 4 files changed, 423 insertions(+), 52 deletions(-) diff --git a/examples/chef/devices/rootnode_airpurifier_73a6fe2651.matter b/examples/chef/devices/rootnode_airpurifier_73a6fe2651.matter index 21d3d20264049e..95a5ebba08d8e5 100644 --- a/examples/chef/devices/rootnode_airpurifier_73a6fe2651.matter +++ b/examples/chef/devices/rootnode_airpurifier_73a6fe2651.matter @@ -1681,6 +1681,8 @@ endpoint 1 { callback attribute attributeList; callback attribute featureMap; ram attribute clusterRevision default = 1; + + handle command ResetCondition; } server cluster FanControl { @@ -1688,10 +1690,10 @@ endpoint 1 { ram attribute fanModeSequence default = 2; ram attribute percentSetting default = 0; ram attribute percentCurrent default = 0; - ram attribute speedMax default = 100; + ram attribute speedMax default = 10; ram attribute speedSetting default = 0; ram attribute speedCurrent default = 0; - ram attribute rockSupport default = 0x03; + ram attribute rockSupport default = 0x07; ram attribute rockSetting default = 0x00; ram attribute windSupport default = 0x03; ram attribute windSetting default = 0x00; diff --git a/examples/chef/devices/rootnode_airpurifier_73a6fe2651.zap b/examples/chef/devices/rootnode_airpurifier_73a6fe2651.zap index f76860576fe362..d72b6d11800223 100644 --- a/examples/chef/devices/rootnode_airpurifier_73a6fe2651.zap +++ b/examples/chef/devices/rootnode_airpurifier_73a6fe2651.zap @@ -19,18 +19,18 @@ "package": [ { "pathRelativity": "relativeToZap", - "path": "../../../src/app/zap-templates/zcl/zcl.json", - "type": "zcl-properties", + "path": "../../../src/app/zap-templates/app-templates.json", + "type": "gen-templates-json", "category": "matter", - "version": 1, - "description": "Matter SDK ZCL data" + "version": "chip-v1" }, { "pathRelativity": "relativeToZap", - "path": "../../../src/app/zap-templates/app-templates.json", - "type": "gen-templates-json", + "path": "../../../src/app/zap-templates/zcl/zcl.json", + "type": "zcl-properties", "category": "matter", - "version": "chip-v1" + "version": 1, + "description": "Matter SDK ZCL data" } ], "endpointTypes": [ @@ -2529,7 +2529,7 @@ "storageOption": "External", "singleton": 0, "bounded": 0, - "defaultValue": "", + "defaultValue": null, "reportable": 1, "minInterval": 1, "maxInterval": 65534, @@ -2545,7 +2545,7 @@ "storageOption": "External", "singleton": 0, "bounded": 0, - "defaultValue": "", + "defaultValue": null, "reportable": 1, "minInterval": 1, "maxInterval": 65534, @@ -2561,7 +2561,7 @@ "storageOption": "External", "singleton": 0, "bounded": 0, - "defaultValue": "", + "defaultValue": null, "reportable": 1, "minInterval": 1, "maxInterval": 65534, @@ -2577,7 +2577,7 @@ "storageOption": "External", "singleton": 0, "bounded": 0, - "defaultValue": "", + "defaultValue": null, "reportable": 1, "minInterval": 1, "maxInterval": 65534, @@ -3006,6 +3006,16 @@ "define": "ACTIVATED_CARBON_FILTER_MONITORING_CLUSTER", "side": "server", "enabled": 1, + "commands": [ + { + "name": "ResetCondition", + "code": 0, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + } + ], "attributes": [ { "name": "Condition", @@ -3293,7 +3303,7 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "100", + "defaultValue": "10", "reportable": 1, "minInterval": 1, "maxInterval": 65534, @@ -3341,7 +3351,7 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "0x03", + "defaultValue": "0x07", "reportable": 1, "minInterval": 1, "maxInterval": 65534, diff --git a/examples/chef/devices/rootnode_airpurifier_airqualitysensor_temperaturesensor_humiditysensor_thermostat_56de3d5f45.matter b/examples/chef/devices/rootnode_airpurifier_airqualitysensor_temperaturesensor_humiditysensor_thermostat_56de3d5f45.matter index 4f6fa7b242fc48..ace9e7a92793d2 100644 --- a/examples/chef/devices/rootnode_airpurifier_airqualitysensor_temperaturesensor_humiditysensor_thermostat_56de3d5f45.matter +++ b/examples/chef/devices/rootnode_airpurifier_airqualitysensor_temperaturesensor_humiditysensor_thermostat_56de3d5f45.matter @@ -2326,7 +2326,7 @@ endpoint 0 { callback attribute windowStatus; callback attribute adminFabricIndex; callback attribute adminVendorId; - ram attribute featureMap default = 0; + ram attribute featureMap default = 0x0001; ram attribute clusterRevision default = 0x0001; handle command OpenCommissioningWindow; @@ -2386,7 +2386,7 @@ endpoint 1 { callback attribute eventList; callback attribute attributeList; ram attribute featureMap default = 0; - ram attribute clusterRevision default = 2; + ram attribute clusterRevision default = 4; handle command Identify; handle command TriggerEffect; @@ -2399,7 +2399,7 @@ endpoint 1 { callback attribute eventList; callback attribute attributeList; ram attribute featureMap default = 0; - ram attribute clusterRevision default = 3; + ram attribute clusterRevision default = 4; handle command AddGroup; handle command AddGroupResponse; @@ -2431,12 +2431,16 @@ endpoint 1 { callback attribute degradationDirection; callback attribute changeIndication; callback attribute inPlaceIndicator; + callback attribute lastChangedTime; + callback attribute replacementProductList; callback attribute generatedCommandList; callback attribute acceptedCommandList; callback attribute eventList; callback attribute attributeList; callback attribute featureMap; ram attribute clusterRevision default = 1; + + handle command ResetCondition; } server cluster ActivatedCarbonFilterMonitoring { @@ -2444,12 +2448,16 @@ endpoint 1 { callback attribute degradationDirection; callback attribute changeIndication; callback attribute inPlaceIndicator; + callback attribute lastChangedTime; + callback attribute replacementProductList; callback attribute generatedCommandList; callback attribute acceptedCommandList; callback attribute eventList; callback attribute attributeList; callback attribute featureMap; ram attribute clusterRevision default = 1; + + handle command ResetCondition; } server cluster FanControl { @@ -2460,7 +2468,7 @@ endpoint 1 { ram attribute speedMax default = 10; ram attribute speedSetting default = 0; ram attribute speedCurrent default = 0; - ram attribute rockSupport default = 0x01; + ram attribute rockSupport default = 0x07; ram attribute rockSetting default = 0x00; ram attribute windSupport default = 0x03; ram attribute windSetting default = 0x00; @@ -2469,8 +2477,10 @@ endpoint 1 { callback attribute acceptedCommandList; callback attribute eventList; callback attribute attributeList; - ram attribute featureMap default = 0; + ram attribute featureMap default = 0x3F; ram attribute clusterRevision default = 4; + + handle command Step; } } endpoint 2 { @@ -2521,6 +2531,7 @@ endpoint 2 { callback attribute peakMeasuredValueWindow; callback attribute averageMeasuredValue; callback attribute averageMeasuredValueWindow; + callback attribute uncertainty; callback attribute measurementUnit; callback attribute measurementMedium; callback attribute levelValue; @@ -2540,6 +2551,7 @@ endpoint 2 { callback attribute peakMeasuredValueWindow; callback attribute averageMeasuredValue; callback attribute averageMeasuredValueWindow; + callback attribute uncertainty; callback attribute measurementUnit; callback attribute measurementMedium; callback attribute levelValue; @@ -2548,7 +2560,7 @@ endpoint 2 { callback attribute eventList; callback attribute attributeList; callback attribute featureMap; - ram attribute clusterRevision default = 1; + ram attribute clusterRevision default = 3; } server cluster NitrogenDioxideConcentrationMeasurement { @@ -2559,6 +2571,7 @@ endpoint 2 { callback attribute peakMeasuredValueWindow; callback attribute averageMeasuredValue; callback attribute averageMeasuredValueWindow; + callback attribute uncertainty; callback attribute measurementUnit; callback attribute measurementMedium; callback attribute levelValue; @@ -2578,6 +2591,7 @@ endpoint 2 { callback attribute peakMeasuredValueWindow; callback attribute averageMeasuredValue; callback attribute averageMeasuredValueWindow; + callback attribute uncertainty; callback attribute measurementUnit; callback attribute measurementMedium; callback attribute levelValue; @@ -2597,6 +2611,7 @@ endpoint 2 { callback attribute peakMeasuredValueWindow; callback attribute averageMeasuredValue; callback attribute averageMeasuredValueWindow; + callback attribute uncertainty; callback attribute measurementUnit; callback attribute measurementMedium; callback attribute levelValue; @@ -2616,6 +2631,7 @@ endpoint 2 { callback attribute peakMeasuredValueWindow; callback attribute averageMeasuredValue; callback attribute averageMeasuredValueWindow; + callback attribute uncertainty; callback attribute measurementUnit; callback attribute measurementMedium; callback attribute levelValue; @@ -2635,6 +2651,7 @@ endpoint 2 { callback attribute peakMeasuredValueWindow; callback attribute averageMeasuredValue; callback attribute averageMeasuredValueWindow; + callback attribute uncertainty; callback attribute measurementUnit; callback attribute measurementMedium; callback attribute levelValue; @@ -2654,6 +2671,7 @@ endpoint 2 { callback attribute peakMeasuredValueWindow; callback attribute averageMeasuredValue; callback attribute averageMeasuredValueWindow; + callback attribute uncertainty; callback attribute measurementUnit; callback attribute measurementMedium; callback attribute levelValue; @@ -2673,6 +2691,7 @@ endpoint 2 { callback attribute peakMeasuredValueWindow; callback attribute averageMeasuredValue; callback attribute averageMeasuredValueWindow; + callback attribute uncertainty; callback attribute measurementUnit; callback attribute measurementMedium; callback attribute levelValue; @@ -2692,6 +2711,7 @@ endpoint 2 { callback attribute peakMeasuredValueWindow; callback attribute averageMeasuredValue; callback attribute averageMeasuredValueWindow; + callback attribute uncertainty; callback attribute measurementUnit; callback attribute measurementMedium; callback attribute levelValue; @@ -2735,15 +2755,16 @@ endpoint 3 { } server cluster TemperatureMeasurement { - ram attribute measuredValue; - ram attribute minMeasuredValue default = 0x8000; - ram attribute maxMeasuredValue default = 0x8000; + persist attribute measuredValue default = 0; + persist attribute minMeasuredValue default = -5000; + persist attribute maxMeasuredValue default = 7500; + persist attribute tolerance default = 10; callback attribute generatedCommandList; callback attribute acceptedCommandList; callback attribute eventList; callback attribute attributeList; ram attribute featureMap default = 0; - ram attribute clusterRevision default = 1; + ram attribute clusterRevision default = 4; } } endpoint 4 { @@ -2778,9 +2799,10 @@ endpoint 4 { } server cluster RelativeHumidityMeasurement { - ram attribute measuredValue; - ram attribute minMeasuredValue; - ram attribute maxMeasuredValue; + ram attribute measuredValue default = 4600; + ram attribute minMeasuredValue default = 0; + ram attribute maxMeasuredValue default = 10000; + ram attribute tolerance default = 1; callback attribute generatedCommandList; callback attribute acceptedCommandList; callback attribute eventList; @@ -2821,12 +2843,15 @@ endpoint 5 { } server cluster Thermostat { - ram attribute localTemperature; + ram attribute localTemperature default = 2000; + ram attribute absMinHeatSetpointLimit default = 700; + ram attribute absMaxHeatSetpointLimit default = 3000; + persist attribute PIHeatingDemand default = 0; ram attribute occupiedHeatingSetpoint default = 2000; - ram attribute minHeatSetpointLimit default = 1700; + ram attribute minHeatSetpointLimit default = 700; ram attribute maxHeatSetpointLimit default = 3000; - ram attribute controlSequenceOfOperation default = 0x02; - ram attribute systemMode default = 0x00; + ram attribute controlSequenceOfOperation default = 2; + ram attribute systemMode default = 4; callback attribute generatedCommandList; callback attribute acceptedCommandList; callback attribute eventList; diff --git a/examples/chef/devices/rootnode_airpurifier_airqualitysensor_temperaturesensor_humiditysensor_thermostat_56de3d5f45.zap b/examples/chef/devices/rootnode_airpurifier_airqualitysensor_temperaturesensor_humiditysensor_thermostat_56de3d5f45.zap index 6b0977ea34be34..0b88b6a936cad5 100644 --- a/examples/chef/devices/rootnode_airpurifier_airqualitysensor_temperaturesensor_humiditysensor_thermostat_56de3d5f45.zap +++ b/examples/chef/devices/rootnode_airpurifier_airqualitysensor_temperaturesensor_humiditysensor_thermostat_56de3d5f45.zap @@ -1503,7 +1503,7 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "0", + "defaultValue": "0x0001", "reportable": 1, "minInterval": 1, "maxInterval": 65534, @@ -2096,7 +2096,7 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "2", + "defaultValue": "4", "reportable": 1, "minInterval": 1, "maxInterval": 65534, @@ -2300,7 +2300,7 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "3", + "defaultValue": "4", "reportable": 1, "minInterval": 1, "maxInterval": 65534, @@ -2485,6 +2485,16 @@ "define": "HEPA_FILTER_MONITORING_CLUSTER", "side": "server", "enabled": 1, + "commands": [ + { + "name": "ResetCondition", + "code": 0, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + } + ], "attributes": [ { "name": "Condition", @@ -2550,6 +2560,38 @@ "maxInterval": 65534, "reportableChange": 0 }, + { + "name": "LastChangedTime", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "epoch_s", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ReplacementProductList", + "code": 5, + "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, @@ -2655,6 +2697,16 @@ "define": "ACTIVATED_CARBON_FILTER_MONITORING_CLUSTER", "side": "server", "enabled": 1, + "commands": [ + { + "name": "ResetCondition", + "code": 0, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + } + ], "attributes": [ { "name": "Condition", @@ -2720,6 +2772,38 @@ "maxInterval": 65534, "reportableChange": 0 }, + { + "name": "LastChangedTime", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "epoch_s", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ReplacementProductList", + "code": 5, + "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, @@ -2825,6 +2909,16 @@ "define": "FAN_CONTROL_CLUSTER", "side": "server", "enabled": 1, + "commands": [ + { + "name": "Step", + "code": 0, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + } + ], "attributes": [ { "name": "FanMode", @@ -2948,7 +3042,7 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "0x01", + "defaultValue": "0x07", "reportable": 1, "minInterval": 1, "maxInterval": 65534, @@ -3092,7 +3186,7 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "0", + "defaultValue": "0x3F", "reportable": 1, "minInterval": 1, "maxInterval": 65534, @@ -3705,6 +3799,22 @@ "maxInterval": 65534, "reportableChange": 0 }, + { + "name": "Uncertainty", + "code": 7, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, { "name": "MeasurementUnit", "code": 8, @@ -3971,6 +4081,22 @@ "maxInterval": 65534, "reportableChange": 0 }, + { + "name": "Uncertainty", + "code": 7, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, { "name": "MeasurementUnit", "code": 8, @@ -4109,7 +4235,7 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "1", + "defaultValue": "3", "reportable": 1, "minInterval": 1, "maxInterval": 65534, @@ -4237,6 +4363,22 @@ "maxInterval": 65534, "reportableChange": 0 }, + { + "name": "Uncertainty", + "code": 7, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, { "name": "MeasurementUnit", "code": 8, @@ -4503,6 +4645,22 @@ "maxInterval": 65534, "reportableChange": 0 }, + { + "name": "Uncertainty", + "code": 7, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, { "name": "MeasurementUnit", "code": 8, @@ -4769,6 +4927,22 @@ "maxInterval": 65534, "reportableChange": 0 }, + { + "name": "Uncertainty", + "code": 7, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, { "name": "MeasurementUnit", "code": 8, @@ -5035,6 +5209,22 @@ "maxInterval": 65534, "reportableChange": 0 }, + { + "name": "Uncertainty", + "code": 7, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, { "name": "MeasurementUnit", "code": 8, @@ -5301,6 +5491,22 @@ "maxInterval": 65534, "reportableChange": 0 }, + { + "name": "Uncertainty", + "code": 7, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, { "name": "MeasurementUnit", "code": 8, @@ -5567,6 +5773,22 @@ "maxInterval": 65534, "reportableChange": 0 }, + { + "name": "Uncertainty", + "code": 7, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, { "name": "MeasurementUnit", "code": 8, @@ -5833,6 +6055,22 @@ "maxInterval": 65534, "reportableChange": 0 }, + { + "name": "Uncertainty", + "code": 7, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, { "name": "MeasurementUnit", "code": 8, @@ -6099,6 +6337,22 @@ "maxInterval": 65534, "reportableChange": 0 }, + { + "name": "Uncertainty", + "code": 7, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, { "name": "MeasurementUnit", "code": 8, @@ -6615,10 +6869,10 @@ "side": "server", "type": "temperature", "included": 1, - "storageOption": "RAM", + "storageOption": "NVM", "singleton": 0, "bounded": 0, - "defaultValue": "", + "defaultValue": "0", "reportable": 1, "minInterval": 1, "maxInterval": 65534, @@ -6631,10 +6885,10 @@ "side": "server", "type": "temperature", "included": 1, - "storageOption": "RAM", + "storageOption": "NVM", "singleton": 0, "bounded": 0, - "defaultValue": "0x8000", + "defaultValue": "-5000", "reportable": 1, "minInterval": 1, "maxInterval": 65534, @@ -6647,10 +6901,26 @@ "side": "server", "type": "temperature", "included": 1, - "storageOption": "RAM", + "storageOption": "NVM", + "singleton": 0, + "bounded": 0, + "defaultValue": "7500", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "Tolerance", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "NVM", "singleton": 0, "bounded": 0, - "defaultValue": "0x8000", + "defaultValue": "10", "reportable": 1, "minInterval": 1, "maxInterval": 65534, @@ -6746,7 +7016,7 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "1", + "defaultValue": "4", "reportable": 1, "minInterval": 1, "maxInterval": 65534, @@ -7127,7 +7397,7 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "", + "defaultValue": "4600", "reportable": 1, "minInterval": 1, "maxInterval": 65534, @@ -7143,7 +7413,7 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "", + "defaultValue": "0", "reportable": 1, "minInterval": 1, "maxInterval": 65534, @@ -7159,7 +7429,23 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "", + "defaultValue": "10000", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "Tolerance", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", "reportable": 1, "minInterval": 1, "maxInterval": 65534, @@ -7646,7 +7932,55 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "", + "defaultValue": "2000", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AbsMinHeatSetpointLimit", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "temperature", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "700", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AbsMaxHeatSetpointLimit", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "temperature", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "3000", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "PIHeatingDemand", + "code": 8, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "NVM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", "reportable": 1, "minInterval": 1, "maxInterval": 65534, @@ -7678,7 +8012,7 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "1700", + "defaultValue": "700", "reportable": 1, "minInterval": 1, "maxInterval": 65534, @@ -7710,7 +8044,7 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "0x02", + "defaultValue": "2", "reportable": 1, "minInterval": 1, "maxInterval": 65534, @@ -7726,7 +8060,7 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "0x00", + "defaultValue": "4", "reportable": 1, "minInterval": 1, "maxInterval": 65534, From d7028ab376e3d706b977fe32f32749ea8af84934 Mon Sep 17 00:00:00 2001 From: Boris Zbarsky Date: Fri, 28 Jun 2024 10:06:04 -0400 Subject: [PATCH 07/12] Add ServiceArea cluster to Darwin availability annotations. (#34118) --- src/darwin/Framework/CHIP/templates/availability.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/darwin/Framework/CHIP/templates/availability.yaml b/src/darwin/Framework/CHIP/templates/availability.yaml index 4327c61ba206aa..4ca8533a55d561 100644 --- a/src/darwin/Framework/CHIP/templates/availability.yaml +++ b/src/darwin/Framework/CHIP/templates/availability.yaml @@ -9690,6 +9690,7 @@ provisional: clusters: # Targeting Fall 2024 + - ServiceArea - ThreadBorderRouterManagement - ThreadNetworkDirectory - WiFiNetworkManagement From beb2bed81bcdcd50ecb57bee0a49560f47d12536 Mon Sep 17 00:00:00 2001 From: Shubham Patil Date: Fri, 28 Jun 2024 19:37:37 +0530 Subject: [PATCH 08/12] setup_payload: remove a note as we support parsing now (#34097) --- src/setup_payload/python/README.md | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/setup_payload/python/README.md b/src/setup_payload/python/README.md index a39496104300d1..b19553be7aca1e 100644 --- a/src/setup_payload/python/README.md +++ b/src/setup_payload/python/README.md @@ -20,8 +20,3 @@ Generates and parses Manual Pairing Code and QR Code ``` For more details please refer Matter Specification - ---- - -NOTE: This tool is only capable of generating the payloads and no support to -parse the payloads. From f62d3bfd120912e01903b799f6fe4ac6b9958153 Mon Sep 17 00:00:00 2001 From: Wang Qixiang <43193572+wqx6@users.noreply.github.com> Date: Fri, 28 Jun 2024 22:55:46 +0800 Subject: [PATCH 09/12] Post SecureSessionEstablished event when secure session is established (#34051) * Post SecureSessionEstablished event when secure session is established * initialized the node id and fabric index of event data for PASE session * add local session id to the event data --- src/include/platform/CHIPDeviceEvent.h | 14 ++++++++++++++ src/protocols/secure_channel/PairingSession.cpp | 15 +++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/src/include/platform/CHIPDeviceEvent.h b/src/include/platform/CHIPDeviceEvent.h index 67809adda04c73..437b20e670284f 100644 --- a/src/include/platform/CHIPDeviceEvent.h +++ b/src/include/platform/CHIPDeviceEvent.h @@ -250,6 +250,11 @@ enum PublicEventTypes * Signals that BLE is deinitialized. */ kBLEDeinitialized, + + /** + * Signals that secure session is established. + */ + kSecureSessionEstablished, }; /** @@ -533,6 +538,15 @@ struct ChipDeviceEvent final { OtaState newState; } OtaStateChanged; + + struct + { + uint64_t PeerNodeId; + uint8_t FabricIndex; + uint8_t SecureSessionType; + uint8_t TransportType; + uint16_t LocalSessionId; + } SecureSessionEstablished; }; bool IsPublic() const { return DeviceEventType::IsPublic(Type); } diff --git a/src/protocols/secure_channel/PairingSession.cpp b/src/protocols/secure_channel/PairingSession.cpp index ae4ca272858a78..6176d097c5118a 100644 --- a/src/protocols/secure_channel/PairingSession.cpp +++ b/src/protocols/secure_channel/PairingSession.cpp @@ -22,6 +22,9 @@ #include #include #include +#include +#include +#include #include namespace chip { @@ -78,6 +81,18 @@ void PairingSession::Finish() if (err == CHIP_NO_ERROR) { VerifyOrDie(mSecureSessionHolder); + DeviceLayer::ChipDeviceEvent event; + event.Type = DeviceLayer::DeviceEventType::kSecureSessionEstablished; + event.SecureSessionEstablished.TransportType = to_underlying(address.GetTransportType()); + event.SecureSessionEstablished.SecureSessionType = + to_underlying(mSecureSessionHolder->AsSecureSession()->GetSecureSessionType()); + event.SecureSessionEstablished.LocalSessionId = mSecureSessionHolder->AsSecureSession()->GetLocalSessionId(); + event.SecureSessionEstablished.PeerNodeId = mSecureSessionHolder->GetPeer().GetNodeId(); + event.SecureSessionEstablished.FabricIndex = mSecureSessionHolder->GetPeer().GetFabricIndex(); + if (DeviceLayer::PlatformMgr().PostEvent(&event) != CHIP_NO_ERROR) + { + ChipLogError(SecureChannel, "Failed to post Secure Session established event"); + } // Make sure to null out mDelegate so we don't send it any other // notifications. auto * delegate = mDelegate; From 28430f1364f541329fc5dd4350495d5afd9b8644 Mon Sep 17 00:00:00 2001 From: Andrei Litvin Date: Fri, 28 Jun 2024 12:47:51 -0400 Subject: [PATCH 10/12] implement 'ReadAttribute' inside the `codegen-data-model` IM/DM split (#33877) * Initial copy with a clean history * make linter happy * Restyle * Fix typo * Add nolint: assert will return before we use the underlying value * 2 more fixes regarding unchecked access * Switch some asserts to expects, for better test logic * Start implementing a read ... wip while I switch to a few other tests * More implementation and we seem to need privilege check as well * More mock ember functions implemented, to make it at least link for now * A bit of work on AAI support. Still need to split out global attribute readers * Split out global AAI...for now * Add global attribute access interface as part of ember data model definitions ... they seem needed * Drop RequiredPrivilegeStubs ... those are odd and if you use mock ember you may as well mock these out as well * Restyle * Added sufficient overrides for things to compile ... this is a MESS * Some more changes to compile * Things link now ... but boy do we have many workarounds... * Remove double return * Restyle * Full ember handling * Comment updates and slight restyle * remove commented out code * Remove read-state from arguments - attributevalueencoder maintains its own state, so we should not duplicate things at this time * more comments and some logic cleanup on alternatives ... code should be less broken now * clean one more comment that seemed odd * Fix off by one bug for long strin processing * More generics * Split out io storage and type conversion as shared functions for ember-compatibility * Restyle * Added more comments * Fix lint errors ... these files are not in libraries since they depend on metadata * Restyle * Fix the access denied error logic ... the translation to UnsupportedAccess is to be done by the caller at a later time, since caller may skip * Shorter code is better * Some comments, cleaner code * Fix auto-include * add some TODO because access control is needed * Model renames * Add renamed files * Add some attribute iteration hint * Make use of the attribute cache * Restyle * Add a cluster iteration hint * Add a few more hints. Ember code still contains loops though, so this may not be ideal still * Add some TODO items for using faster iterations for data. Ember index vs value duality still needs some work * Add a cluster type cache as well. This relies on ember being reasonably static * Add global attribute handling * Fix typing u16 vs unsigned * Unit test preparation: make ACL pass and have an ACL test as well * Some progress in testability. No mock reads, however at least some progress * Make some unit tests pass with ember overrides * Restyle * Attempt to decode data. It does NOT work yet * Validation actually passes * Start splitting into unrelated files ...this is painful * Restyle * Better test namespacing - be consistent * Re-organize a bit ... boilerplate still seems A LOT * Minor comments to start organizing the code better - I NEED more readable things * Restyle and re-organize for readability * More code changes to support testing strings ... however this FAILS right now * Restyle * Fix a typo ... still broken though * one more typo fix ... test passes * Long octet string test as well * Restyle * Fix comment and change the size of the string * Add several ember-specific tests * unit tests and working with nullable values * Fix up the tests * Restyle * AAI unit test for read * Slight comment updates * Restyle * Use StringBuilderAdapters to format chip_error nicely * Format * More unit tests for lists ... test overflow as well * Add test support for partially encoded lists * add missing file * Fix name shadowing * Fix auto-added include names * Test global attribute read via AAI * More unit test coverage * Test nullable string reads * One more test for error pahs * More failure cases on failure path * Restyle * Remove back the initialization and make the comment more obvious * Undo odd include that got auto-added * Place files back past renames * A bit more renaming * Fix includes * More updates to the latest code * Fix unit test merging * Resolve data model ambiguity * Restyle * Do not try to compile ember tests on zephyr as it is not compatible with single large executable * Update placement and comment for including codegen test into one large binary * Restyle * Add static cast for ember calls for span sizes ... we know we are less than 65K * Fix clang-tidy error report * Restyle * Do not try to translate UnsupportedRead * Typo fixes * Code review feedback: correct the return code for global attribute missing the cluster * Some spelling updates and format * ChipDie if internal logic for read fails * Fix typo * Add unit test for invalid global attribute read * Code review feedback: comment about internal flags and implement path expansion logic for skipping data encoding * Restyle and unit test for expansion * Another unit test for AAI this time for unsupported read * Restyle * Update src/app/codegen-data-model/tests/TestAttributeReportIBsEncoding.cpp Co-authored-by: Boris Zbarsky * Rename files to not have a Test prefix when not containing tests * Add comment as per review comment * Use macros for error returns * Fix typo * Add a macro for dynamic global IM status codes in chip_error * Reference issue in comment * Fix comment a bit * Undo module updates ... this time for real --------- Co-authored-by: Andrei Litvin Co-authored-by: Boris Zbarsky --- examples/chef/chef.py | 2 +- src/BUILD.gn | 9 +- src/app/codegen-data-model/BUILD.gn | 1 + .../codegen-data-model/CodegenDataModel.cpp | 7 - src/app/codegen-data-model/CodegenDataModel.h | 3 +- .../CodegenDataModel_Read.cpp | 372 ++++++ src/app/codegen-data-model/model.gni | 5 +- .../tests/AttributeReportIBEncodeDecode.cpp | 130 ++ .../tests/AttributeReportIBEncodeDecode.h | 68 + src/app/codegen-data-model/tests/BUILD.gn | 32 +- .../tests/EmberReadWriteOverride.cpp | 87 ++ .../tests/EmberReadWriteOverride.h | 33 + .../InteractionModelTemporaryOverrides.cpp | 84 ++ .../tests/TestCodegenModelViaMocks.cpp | 1185 ++++++++++++++++- src/app/data-model-interface/DataModel.h | 25 +- src/app/data-model-interface/OperationTypes.h | 23 +- src/lib/core/CHIPError.h | 9 + 17 files changed, 2038 insertions(+), 37 deletions(-) create mode 100644 src/app/codegen-data-model/CodegenDataModel_Read.cpp create mode 100644 src/app/codegen-data-model/tests/AttributeReportIBEncodeDecode.cpp create mode 100644 src/app/codegen-data-model/tests/AttributeReportIBEncodeDecode.h create mode 100644 src/app/codegen-data-model/tests/EmberReadWriteOverride.cpp create mode 100644 src/app/codegen-data-model/tests/EmberReadWriteOverride.h create mode 100644 src/app/codegen-data-model/tests/InteractionModelTemporaryOverrides.cpp diff --git a/examples/chef/chef.py b/examples/chef/chef.py index 6176c6e8c280ac..f681f3a059f4fc 100755 --- a/examples/chef/chef.py +++ b/examples/chef/chef.py @@ -878,7 +878,7 @@ def main() -> int: """)) if options.do_clean: shell.run_cmd("rm -rf out") - shell.run_cmd("gn gen out") + shell.run_cmd("gn gen --export-compile-commands out") shell.run_cmd("ninja -C out") # diff --git a/src/BUILD.gn b/src/BUILD.gn index 27f449dcf8e543..e2557535d9d72d 100644 --- a/src/BUILD.gn +++ b/src/BUILD.gn @@ -50,7 +50,6 @@ if (chip_build_tests) { chip_test_group("tests") { deps = [] tests = [ - "${chip_root}/src/app/codegen-data-model/tests", "${chip_root}/src/app/data-model-interface/tests", "${chip_root}/src/access/tests", "${chip_root}/src/crypto/tests", @@ -82,7 +81,15 @@ if (chip_build_tests) { if (current_os != "zephyr" && current_os != "mbed" && chip_device_platform != "efr32") { + # Avoid these items from "one single binary" test executions. Once tests + # are split, we can re-visit this (and likely many others) + # + # In particular: + # "app/codegen-data-model/tests" contains symbols for ember mocks which + # are used by other tests + tests += [ + "${chip_root}/src/app/codegen-data-model/tests", "${chip_root}/src/setup_payload/tests", "${chip_root}/src/transport/raw/tests", ] diff --git a/src/app/codegen-data-model/BUILD.gn b/src/app/codegen-data-model/BUILD.gn index 418983a2fc8b8f..5803f01a37778e 100644 --- a/src/app/codegen-data-model/BUILD.gn +++ b/src/app/codegen-data-model/BUILD.gn @@ -20,6 +20,7 @@ import("//build_overrides/chip.gni") # # Use `model.gni` to get access to: # CodegenDataModel.cpp +# CodegenDataModel_Read.cpp # CodegenDataModel.h # # The above list of files exists to satisfy the "dependency linter" diff --git a/src/app/codegen-data-model/CodegenDataModel.cpp b/src/app/codegen-data-model/CodegenDataModel.cpp index e1597dbdc4f8b4..d46deeeddaa1e0 100644 --- a/src/app/codegen-data-model/CodegenDataModel.cpp +++ b/src/app/codegen-data-model/CodegenDataModel.cpp @@ -231,13 +231,6 @@ bool CodegenDataModel::EmberCommandListIterator::Exists(const CommandId * list, return (*mCurrentHint == toCheck); } -CHIP_ERROR CodegenDataModel::ReadAttribute(const InteractionModel::ReadAttributeRequest & request, - InteractionModel::ReadState & state, AttributeValueEncoder & encoder) -{ - // TODO: this needs an implementation - return CHIP_ERROR_NOT_IMPLEMENTED; -} - CHIP_ERROR CodegenDataModel::WriteAttribute(const InteractionModel::WriteAttributeRequest & request, AttributeValueDecoder & decoder) { diff --git a/src/app/codegen-data-model/CodegenDataModel.h b/src/app/codegen-data-model/CodegenDataModel.h index f8d997451bdace..b65f38b9155e73 100644 --- a/src/app/codegen-data-model/CodegenDataModel.h +++ b/src/app/codegen-data-model/CodegenDataModel.h @@ -68,8 +68,7 @@ class CodegenDataModel : public chip::app::InteractionModel::DataModel /// Generic model implementations CHIP_ERROR Shutdown() override { return CHIP_NO_ERROR; } - CHIP_ERROR ReadAttribute(const InteractionModel::ReadAttributeRequest & request, InteractionModel::ReadState & state, - AttributeValueEncoder & encoder) override; + CHIP_ERROR ReadAttribute(const InteractionModel::ReadAttributeRequest & request, AttributeValueEncoder & encoder) override; CHIP_ERROR WriteAttribute(const InteractionModel::WriteAttributeRequest & request, AttributeValueDecoder & decoder) override; CHIP_ERROR Invoke(const InteractionModel::InvokeRequest & request, chip::TLV::TLVReader & input_arguments, InteractionModel::InvokeReply & reply) override; diff --git a/src/app/codegen-data-model/CodegenDataModel_Read.cpp b/src/app/codegen-data-model/CodegenDataModel_Read.cpp new file mode 100644 index 00000000000000..04265d37f8623f --- /dev/null +++ b/src/app/codegen-data-model/CodegenDataModel_Read.cpp @@ -0,0 +1,372 @@ +/* + * 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 "lib/core/CHIPError.h" +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace chip { +namespace app { +namespace { +using namespace chip::app::Compatibility::Internal; + +// Fetch the source for the given attribute path: either a cluster (for global ones) or attribute +// path. +// +// if returning a CHIP_ERROR, it will NEVER be CHIP_NO_ERROR. +std::variant +FindAttributeMetadata(const ConcreteAttributePath & aPath) +{ + for (auto & attr : GlobalAttributesNotInMetadata) + { + + if (attr == aPath.mAttributeId) + { + const EmberAfCluster * cluster = emberAfFindServerCluster(aPath.mEndpointId, aPath.mClusterId); + if (cluster == nullptr) + { + return (emberAfFindEndpointType(aPath.mEndpointId) == nullptr) ? CHIP_IM_GLOBAL_STATUS(UnsupportedEndpoint) + : CHIP_IM_GLOBAL_STATUS(UnsupportedCluster); + } + + return cluster; + } + } + const EmberAfAttributeMetadata * metadata = + emberAfLocateAttributeMetadata(aPath.mEndpointId, aPath.mClusterId, aPath.mAttributeId); + + if (metadata == nullptr) + { + const EmberAfEndpointType * type = emberAfFindEndpointType(aPath.mEndpointId); + if (type == nullptr) + { + return CHIP_IM_GLOBAL_STATUS(UnsupportedEndpoint); + } + + const EmberAfCluster * cluster = emberAfFindClusterInType(type, aPath.mClusterId, CLUSTER_MASK_SERVER); + if (cluster == nullptr) + { + return CHIP_IM_GLOBAL_STATUS(UnsupportedCluster); + } + + // Since we know the attribute is unsupported and the endpoint/cluster are + // OK, this is the only option left. + return CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute); + } + + return metadata; +} + +/// Attempts to read via an attribute access interface (AAI) +/// +/// If it returns a CHIP_ERROR, then this is a FINAL result (i.e. either failure or success). +/// +/// If it returns std::nullopt, then there is no AAI to handle the given path +/// and processing should figure out the value otherwise (generally from other ember data) +std::optional TryReadViaAccessInterface(const ConcreteAttributePath & path, AttributeAccessInterface * aai, + AttributeValueEncoder & encoder) +{ + // Processing can happen only if an attribute access interface actually exists.. + if (aai == nullptr) + { + return std::nullopt; + } + + CHIP_ERROR err = aai->Read(path, encoder); + + if (err != CHIP_NO_ERROR) + { + // Implementation of 8.4.3.2 of the spec for path expansion + if (path.mExpanded && (err == CHIP_IM_GLOBAL_STATUS(UnsupportedRead))) + { + return CHIP_NO_ERROR; + } + + return err; + } + + // If the encoder tried to encode, then a value should have been written. + // - if encode, assume DONE (i.e. FINAL CHIP_NO_ERROR) + // - if no encode, say that processing must continue + return encoder.TriedEncode() ? std::make_optional(CHIP_NO_ERROR) : std::nullopt; +} + +/// Metadata of what a ember/pascal short string means (prepended by a u8 length) +struct ShortPascalString +{ + using LengthType = uint8_t; + static constexpr LengthType kNullLength = 0xFF; +}; + +/// Metadata of what a ember/pascal LONG string means (prepended by a u16 length) +struct LongPascalString +{ + using LengthType = uint16_t; + static constexpr LengthType kNullLength = 0xFFFF; +}; + +// ember assumptions ... should just work +static_assert(sizeof(ShortPascalString::LengthType) == 1); +static_assert(sizeof(LongPascalString::LengthType) == 2); + +/// Given a ByteSpan containing data from ember, interpret it +/// as a span of type OUT (i.e. ByteSpan or CharSpan) given a ENCODING +/// where ENCODING is Short or Long pascal strings. +template +std::optional ExtractEmberString(ByteSpan data) +{ + typename ENCODING::LengthType len; + + // Ember storage format for pascal-prefix data is specifically "native byte order", + // hence the use of memcpy. + VerifyOrDie(sizeof(len) <= data.size()); + memcpy(&len, data.data(), sizeof(len)); + + if (len == ENCODING::kNullLength) + { + return std::nullopt; + } + + VerifyOrDie(static_cast(len + sizeof(len)) <= data.size()); + return std::make_optional(reinterpret_cast(data.data() + sizeof(len)), len); +} + +/// Encode a value inside `encoder` +/// +/// The value encoded will be of type T (e.g. CharSpan or ByteSpan) and it will be decoded +/// via the given ENCODING (i.e. ShortPascalString or LongPascalString) +/// +/// isNullable defines if the value of NULL is allowed to be encoded. +template +CHIP_ERROR EncodeStringLike(ByteSpan data, bool isNullable, AttributeValueEncoder & encoder) +{ + std::optional value = ExtractEmberString(data); + if (!value.has_value()) + { + if (isNullable) + { + return encoder.EncodeNull(); + } + return CHIP_ERROR_INCORRECT_STATE; + } + + // encode value as-is + return encoder.Encode(*value); +} + +/// Encodes a numeric data value of type T from the given ember-encoded buffer `data`. +/// +/// isNullable defines if the value of NULL is allowed to be encoded. +template +CHIP_ERROR EncodeFromSpan(ByteSpan data, bool isNullable, AttributeValueEncoder & encoder) +{ + typename NumericAttributeTraits::StorageType value; + + VerifyOrReturnError(data.size() >= sizeof(value), CHIP_ERROR_INVALID_ARGUMENT); + memcpy(&value, data.data(), sizeof(value)); + + if (isNullable && NumericAttributeTraits::IsNullValue(value)) + { + return encoder.EncodeNull(); + } + + if (!NumericAttributeTraits::CanRepresentValue(isNullable, value)) + { + return CHIP_ERROR_INCORRECT_STATE; + } + + return encoder.Encode(NumericAttributeTraits::StorageToWorking(value)); +} + +/// Converts raw ember data from `data` into the encoder +/// +/// Uses the attribute `metadata` to determine how the data is encoded into `data` and +/// write a suitable value into `encoder`. +CHIP_ERROR EncodeEmberValue(ByteSpan data, const EmberAfAttributeMetadata * metadata, AttributeValueEncoder & encoder) +{ + VerifyOrReturnError(metadata != nullptr, CHIP_ERROR_INVALID_ARGUMENT); + + const bool isNullable = metadata->IsNullable(); + + switch (AttributeBaseType(metadata->attributeType)) + { + case ZCL_NO_DATA_ATTRIBUTE_TYPE: // No data + return encoder.EncodeNull(); + case ZCL_BOOLEAN_ATTRIBUTE_TYPE: // Boolean + return EncodeFromSpan(data, isNullable, encoder); + case ZCL_INT8U_ATTRIBUTE_TYPE: // Unsigned 8-bit integer + return EncodeFromSpan(data, isNullable, encoder); + case ZCL_INT16U_ATTRIBUTE_TYPE: // Unsigned 16-bit integer + return EncodeFromSpan(data, isNullable, encoder); + case ZCL_INT24U_ATTRIBUTE_TYPE: // Unsigned 24-bit integer + return EncodeFromSpan>(data, isNullable, encoder); + case ZCL_INT32U_ATTRIBUTE_TYPE: // Unsigned 32-bit integer + return EncodeFromSpan(data, isNullable, encoder); + case ZCL_INT40U_ATTRIBUTE_TYPE: // Unsigned 40-bit integer + return EncodeFromSpan>(data, isNullable, encoder); + case ZCL_INT48U_ATTRIBUTE_TYPE: // Unsigned 48-bit integer + return EncodeFromSpan>(data, isNullable, encoder); + case ZCL_INT56U_ATTRIBUTE_TYPE: // Unsigned 56-bit integer + return EncodeFromSpan>(data, isNullable, encoder); + case ZCL_INT64U_ATTRIBUTE_TYPE: // Unsigned 64-bit integer + return EncodeFromSpan(data, isNullable, encoder); + case ZCL_INT8S_ATTRIBUTE_TYPE: // Signed 8-bit integer + return EncodeFromSpan(data, isNullable, encoder); + case ZCL_INT16S_ATTRIBUTE_TYPE: // Signed 16-bit integer + return EncodeFromSpan(data, isNullable, encoder); + case ZCL_INT24S_ATTRIBUTE_TYPE: // Signed 24-bit integer + return EncodeFromSpan>(data, isNullable, encoder); + case ZCL_INT32S_ATTRIBUTE_TYPE: // Signed 32-bit integer + return EncodeFromSpan(data, isNullable, encoder); + case ZCL_INT40S_ATTRIBUTE_TYPE: // Signed 40-bit integer + return EncodeFromSpan>(data, isNullable, encoder); + case ZCL_INT48S_ATTRIBUTE_TYPE: // Signed 48-bit integer + return EncodeFromSpan>(data, isNullable, encoder); + case ZCL_INT56S_ATTRIBUTE_TYPE: // Signed 56-bit integer + return EncodeFromSpan>(data, isNullable, encoder); + case ZCL_INT64S_ATTRIBUTE_TYPE: // Signed 64-bit integer + return EncodeFromSpan(data, isNullable, encoder); + case ZCL_SINGLE_ATTRIBUTE_TYPE: // 32-bit float + return EncodeFromSpan(data, isNullable, encoder); + case ZCL_DOUBLE_ATTRIBUTE_TYPE: // 64-bit float + return EncodeFromSpan(data, isNullable, encoder); + case ZCL_CHAR_STRING_ATTRIBUTE_TYPE: // Char string + return EncodeStringLike(data, isNullable, encoder); + case ZCL_LONG_CHAR_STRING_ATTRIBUTE_TYPE: + return EncodeStringLike(data, isNullable, encoder); + case ZCL_OCTET_STRING_ATTRIBUTE_TYPE: // Octet string + return EncodeStringLike(data, isNullable, encoder); + case ZCL_LONG_OCTET_STRING_ATTRIBUTE_TYPE: + return EncodeStringLike(data, isNullable, encoder); + default: + ChipLogError(DataManagement, "Attribute type 0x%x not handled", static_cast(metadata->attributeType)); + return CHIP_IM_GLOBAL_STATUS(UnsupportedRead); + } +} + +} // namespace + +/// separated-out ReadAttribute implementation (given existing complexity) +/// +/// Generally will: +/// - validate ACL (only for non-internal requests) +/// - Try to read attribute via the AttributeAccessInterface +/// - Try to read the value from ember RAM storage +CHIP_ERROR CodegenDataModel::ReadAttribute(const InteractionModel::ReadAttributeRequest & request, AttributeValueEncoder & encoder) +{ + ChipLogDetail(DataManagement, + "Reading attribute: Cluster=" ChipLogFormatMEI " Endpoint=0x%x AttributeId=" ChipLogFormatMEI " (expanded=%d)", + ChipLogValueMEI(request.path.mClusterId), request.path.mEndpointId, ChipLogValueMEI(request.path.mAttributeId), + request.path.mExpanded); + + // ACL check for non-internal requests + if (!request.operationFlags.Has(InteractionModel::OperationFlags::kInternal)) + { + ReturnErrorCodeIf(!request.subjectDescriptor.has_value(), CHIP_ERROR_INVALID_ARGUMENT); + + Access::RequestPath requestPath{ .cluster = request.path.mClusterId, .endpoint = request.path.mEndpointId }; + CHIP_ERROR err = Access::GetAccessControl().Check(*request.subjectDescriptor, requestPath, + RequiredPrivilege::ForReadAttribute(request.path)); + if (err != CHIP_NO_ERROR) + { + // Implementation of 8.4.3.2 of the spec for path expansion + if (request.path.mExpanded && (err == CHIP_ERROR_ACCESS_DENIED)) + { + return CHIP_NO_ERROR; + } + return err; + } + } + + auto metadata = FindAttributeMetadata(request.path); + + // Explicit failure in finding a suitable metadata + if (const CHIP_ERROR * err = std::get_if(&metadata)) + { + VerifyOrDie(*err != CHIP_NO_ERROR); + return *err; + } + + // Read via AAI + std::optional aai_result; + if (const EmberAfCluster ** cluster = std::get_if(&metadata)) + { + Compatibility::GlobalAttributeReader aai(*cluster); + aai_result = TryReadViaAccessInterface(request.path, &aai, encoder); + } + else + { + aai_result = TryReadViaAccessInterface( + request.path, GetAttributeAccessOverride(request.path.mEndpointId, request.path.mClusterId), encoder); + } + ReturnErrorCodeIf(aai_result.has_value(), *aai_result); + + if (!std::holds_alternative(metadata)) + { + // if we only got a cluster, this was for a global attribute. We cannot read ember attributes + // at this point, so give up (although GlobalAttributeReader should have returned something here). + chipDie(); + } + const EmberAfAttributeMetadata * attributeMetadata = std::get(metadata); + + // At this point, we have to use ember directly to read the data. + EmberAfAttributeSearchRecord record; + record.endpoint = request.path.mEndpointId; + record.clusterId = request.path.mClusterId; + record.attributeId = request.path.mAttributeId; + Protocols::InteractionModel::Status status = emAfReadOrWriteAttribute( + &record, &attributeMetadata, gEmberAttributeIOBufferSpan.data(), static_cast(gEmberAttributeIOBufferSpan.size()), + /* write = */ false); + + if (status != Protocols::InteractionModel::Status::Success) + { + return CHIP_ERROR_IM_GLOBAL_STATUS_VALUE(status); + } + + return EncodeEmberValue(gEmberAttributeIOBufferSpan, attributeMetadata, encoder); +} + +} // namespace app +} // namespace chip diff --git a/src/app/codegen-data-model/model.gni b/src/app/codegen-data-model/model.gni index c8dce5617b9a7b..3be7b2d2610513 100644 --- a/src/app/codegen-data-model/model.gni +++ b/src/app/codegen-data-model/model.gni @@ -24,12 +24,13 @@ import("//build_overrides/chip.gni") # As a result, the files here are NOT a source_set or similar because they cannot # be cleanly built as a stand-alone and instead have to be imported as part of # a different data model or compilation unit. -codegen_interaction_model_SOURCES = [ +codegen_data_model_SOURCES = [ "${chip_root}/src/app/codegen-data-model/CodegenDataModel.h", "${chip_root}/src/app/codegen-data-model/CodegenDataModel.cpp", + "${chip_root}/src/app/codegen-data-model/CodegenDataModel_Read.cpp", ] -codegen_interaction_model_PUBLIC_DEPS = [ +codegen_data_model_PUBLIC_DEPS = [ "${chip_root}/src/app/common:attribute-type", "${chip_root}/src/app/data-model-interface", ] diff --git a/src/app/codegen-data-model/tests/AttributeReportIBEncodeDecode.cpp b/src/app/codegen-data-model/tests/AttributeReportIBEncodeDecode.cpp new file mode 100644 index 00000000000000..29088d0cdc55e1 --- /dev/null +++ b/src/app/codegen-data-model/tests/AttributeReportIBEncodeDecode.cpp @@ -0,0 +1,130 @@ +/* + * 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 "AttributeReportIBEncodeDecode.h" + +#include +#include + +using namespace chip::app; + +namespace chip { +namespace Test { + +CHIP_ERROR DecodedAttributeData::DecodeFrom(const AttributeDataIB::Parser & parser) +{ + ReturnErrorOnFailure(parser.GetDataVersion(&dataVersion)); + + AttributePathIB::Parser pathParser; + ReturnErrorOnFailure(parser.GetPath(&pathParser)); + ReturnErrorOnFailure(pathParser.GetConcreteAttributePath(attributePath, AttributePathIB::ValidateIdRanges::kNo)); + ReturnErrorOnFailure(parser.GetData(&dataReader)); + + return CHIP_NO_ERROR; +} + +CHIP_ERROR DecodeAttributeReportIBs(ByteSpan data, std::vector & decoded_items) +{ + // Espected data format: + // CONTAINER (anonymous) + // 0x01 => Array (i.e. report data ib) + // ReportIB* + // + // Generally this is VERY hard to process ... + // + TLV::TLVReader reportIBsReader; + reportIBsReader.Init(data); + + ReturnErrorOnFailure(reportIBsReader.Next()); + if (reportIBsReader.GetType() != TLV::TLVType::kTLVType_Structure) + { + return CHIP_ERROR_INVALID_ARGUMENT; + } + TLV::TLVType outer1; + reportIBsReader.EnterContainer(outer1); + + ReturnErrorOnFailure(reportIBsReader.Next()); + if (reportIBsReader.GetType() != TLV::TLVType::kTLVType_Array) + { + return CHIP_ERROR_INVALID_ARGUMENT; + } + + TLV::TLVType outer2; + reportIBsReader.EnterContainer(outer2); + + CHIP_ERROR err = CHIP_NO_ERROR; + while (CHIP_NO_ERROR == (err = reportIBsReader.Next())) + { + TLV::TLVReader attributeReportReader = reportIBsReader; + AttributeReportIB::Parser attributeReportParser; + ReturnErrorOnFailure(attributeReportParser.Init(attributeReportReader)); + + AttributeDataIB::Parser dataParser; + // NOTE: to also grab statuses, use GetAttributeStatus and check for CHIP_END_OF_TLV + ReturnErrorOnFailure(attributeReportParser.GetAttributeData(&dataParser)); + + DecodedAttributeData decoded; + ReturnErrorOnFailure(decoded.DecodeFrom(dataParser)); + decoded_items.push_back(decoded); + } + + if ((CHIP_END_OF_TLV != err) && (err != CHIP_NO_ERROR)) + { + return CHIP_NO_ERROR; + } + + ReturnErrorOnFailure(reportIBsReader.ExitContainer(outer2)); + ReturnErrorOnFailure(reportIBsReader.ExitContainer(outer1)); + + err = reportIBsReader.Next(); + + if (CHIP_ERROR_END_OF_TLV == err) + { + return CHIP_NO_ERROR; + } + if (CHIP_NO_ERROR == err) + { + // This is NOT ok ... we have multiple things in our buffer? + return CHIP_ERROR_INVALID_ARGUMENT; + } + + return err; +} + +CHIP_ERROR EncodedReportIBs::StartEncoding(app::AttributeReportIBs::Builder & builder) +{ + mEncodeWriter.Init(mTlvDataBuffer); + ReturnErrorOnFailure(mEncodeWriter.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, mOuterStructureType)); + return builder.Init(&mEncodeWriter, to_underlying(ReportDataMessage::Tag::kAttributeReportIBs)); +} + +CHIP_ERROR EncodedReportIBs::FinishEncoding(app::AttributeReportIBs::Builder & builder) +{ + builder.EndOfContainer(); + ReturnErrorOnFailure(mEncodeWriter.EndContainer(mOuterStructureType)); + ReturnErrorOnFailure(mEncodeWriter.Finalize()); + + mDecodeSpan = ByteSpan(mTlvDataBuffer, mEncodeWriter.GetLengthWritten()); + return CHIP_NO_ERROR; +} + +CHIP_ERROR EncodedReportIBs::Decode(std::vector & decoded_items) +{ + return DecodeAttributeReportIBs(mDecodeSpan, decoded_items); +} + +} // namespace Test +} // namespace chip diff --git a/src/app/codegen-data-model/tests/AttributeReportIBEncodeDecode.h b/src/app/codegen-data-model/tests/AttributeReportIBEncodeDecode.h new file mode 100644 index 00000000000000..83c079f810ccb8 --- /dev/null +++ b/src/app/codegen-data-model/tests/AttributeReportIBEncodeDecode.h @@ -0,0 +1,68 @@ +/* + * 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 +#include +#include + +#include + +namespace chip { +namespace Test { + +struct DecodedAttributeData +{ + chip::DataVersion dataVersion; + chip::app::ConcreteDataAttributePath attributePath; + chip::TLV::TLVReader dataReader; + + CHIP_ERROR DecodeFrom(const chip::app::AttributeDataIB::Parser & parser); +}; + +CHIP_ERROR DecodeAttributeReportIBs(ByteSpan data, std::vector & decoded_items); + +/// Maintains an internal TLV buffer for data encoding and +/// decoding for ReportIBs. +/// +/// Main use case is that explicit TLV layouts (structure and container starting) need to be +/// prepared to have a proper AttributeReportIBs::Builder/parser to exist. +class EncodedReportIBs +{ +public: + /// Initialize the report structures required to encode a + CHIP_ERROR StartEncoding(app::AttributeReportIBs::Builder & builder); + CHIP_ERROR FinishEncoding(app::AttributeReportIBs::Builder & builder); + + /// Decode the embedded attribute report IBs. + /// The TLVReaders inside data have a lifetime tied to the current object (its readers point + /// inside the current object) + CHIP_ERROR Decode(std::vector & decoded_items); + +private: + uint8_t mTlvDataBuffer[1024]; + TLV::TLVType mOuterStructureType; + TLV::TLVWriter mEncodeWriter; + ByteSpan mDecodeSpan; +}; + +} // namespace Test +} // namespace chip diff --git a/src/app/codegen-data-model/tests/BUILD.gn b/src/app/codegen-data-model/tests/BUILD.gn index a3857184c25b74..3d265a96a66b29 100644 --- a/src/app/codegen-data-model/tests/BUILD.gn +++ b/src/app/codegen-data-model/tests/BUILD.gn @@ -15,17 +15,41 @@ import("//build_overrides/chip.gni") import("${chip_root}/build/chip/chip_test_suite.gni") import("${chip_root}/src/app/codegen-data-model/model.gni") +source_set("ember_extra_files") { + sources = [ + # This IS TERRIBLE, however we want to pretend AAI exists for global + # items and we need a shared IO storage to reduce overhead between + # data-model access and ember-compatibility (we share the same buffer) + "${chip_root}/src/app/util/ember-global-attribute-access-interface.cpp", + "${chip_root}/src/app/util/ember-io-storage.cpp", + "AttributeReportIBEncodeDecode.cpp", + "AttributeReportIBEncodeDecode.h", + "EmberReadWriteOverride.cpp", + "EmberReadWriteOverride.h", + "InteractionModelTemporaryOverrides.cpp", + ] + + public_deps = [ + "${chip_root}/src/app/util/mock:mock_ember", + "${chip_root}/src/protocols", + ] +} + source_set("mock_model") { - sources = codegen_interaction_model_SOURCES + sources = codegen_data_model_SOURCES - public_deps = codegen_interaction_model_PUBLIC_DEPS + public_deps = codegen_data_model_PUBLIC_DEPS # this ties in the codegen model to an actual ember implementation - public_deps += [ "${chip_root}/src/app/util/mock:mock_ember" ] + public_deps += [ + ":ember_extra_files", + "${chip_root}/src/app/util/mock:mock_ember", + "${chip_root}/src/lib/core:string-builder-adapters", + ] } chip_test_suite("tests") { - output_name = "libCodegenInteractionModelTests" + output_name = "libCodegenDataModelTests" test_sources = [ "TestCodegenModelViaMocks.cpp" ] diff --git a/src/app/codegen-data-model/tests/EmberReadWriteOverride.cpp b/src/app/codegen-data-model/tests/EmberReadWriteOverride.cpp new file mode 100644 index 00000000000000..8c65ee29b05556 --- /dev/null +++ b/src/app/codegen-data-model/tests/EmberReadWriteOverride.cpp @@ -0,0 +1,87 @@ +/* + * 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 "EmberReadWriteOverride.h" + +#include + +using chip::Protocols::InteractionModel::Status; + +namespace { + +constexpr size_t kMaxTestIoSize = 128; + +uint8_t gEmberIoBuffer[kMaxTestIoSize]; +size_t gEmberIoBufferFill; +Status gEmberStatusCode = Status::InvalidAction; + +} // namespace + +namespace chip { +namespace Test { + +void SetEmberReadOutput(std::variant what) +{ + if (const chip::ByteSpan * span = std::get_if(&what)) + { + gEmberStatusCode = Status::Success; + + if (span->size() > sizeof(gEmberIoBuffer)) + { + ChipLogError(Test, "UNEXPECTED STATE: Too much data set for ember read output"); + gEmberStatusCode = Status::ResourceExhausted; + + return; + } + + memcpy(gEmberIoBuffer, span->data(), span->size()); + gEmberIoBufferFill = span->size(); + return; + } + + if (const Status * status = std::get_if(&what)) + { + gEmberIoBufferFill = 0; + gEmberStatusCode = *status; + return; + } + + ChipLogError(Test, "UNEXPECTED STATE: invalid ember read output setting"); + gEmberStatusCode = Status::InvalidAction; +} + +} // namespace Test +} // namespace chip + +/// TODO: this SHOULD be part of attribute-storage mocks and allow proper I/O control +/// with helpers for "ember encoding" +Status emAfReadOrWriteAttribute(const EmberAfAttributeSearchRecord * attRecord, const EmberAfAttributeMetadata ** metadata, + uint8_t * buffer, uint16_t readLength, bool write) +{ + if (gEmberStatusCode != Status::Success) + { + return gEmberStatusCode; + } + + if (gEmberIoBufferFill > readLength) + { + ChipLogError(Test, "Internal TEST error: insufficient output buffer space."); + return Status::ResourceExhausted; + } + + memcpy(buffer, gEmberIoBuffer, gEmberIoBufferFill); + return Status::Success; +} diff --git a/src/app/codegen-data-model/tests/EmberReadWriteOverride.h b/src/app/codegen-data-model/tests/EmberReadWriteOverride.h new file mode 100644 index 00000000000000..527a6cfd0d18c7 --- /dev/null +++ b/src/app/codegen-data-model/tests/EmberReadWriteOverride.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 +#include + +#include + +namespace chip { +namespace Test { + +/// specify what the next `emAfReadOrWriteAttribute` will contain +/// +/// It may return a value with success or some error. The byte span WILL BE COPIED. +void SetEmberReadOutput(std::variant what); + +} // namespace Test +} // namespace chip diff --git a/src/app/codegen-data-model/tests/InteractionModelTemporaryOverrides.cpp b/src/app/codegen-data-model/tests/InteractionModelTemporaryOverrides.cpp new file mode 100644 index 00000000000000..868a26880d3ce7 --- /dev/null +++ b/src/app/codegen-data-model/tests/InteractionModelTemporaryOverrides.cpp @@ -0,0 +1,84 @@ +/* + * 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 +#include +#include +#include +#include + +using chip::Protocols::InteractionModel::Status; + +// TODO: most of the functions here are part of EmberCompatibilityFunctions and is NOT decoupled +// from IM current, but it SHOULD be +// Open issue https://github.com/project-chip/connectedhomeip/issues/34137 for this work. +namespace chip { +namespace app { + +bool ConcreteAttributePathExists(const ConcreteAttributePath & aPath) +{ + // TODO: this is just a noop which may be potentially invalid + return true; +} + +bool IsClusterDataVersionEqual(const ConcreteClusterPath & aConcreteClusterPath, DataVersion aRequiredVersion) +{ + // TODO: this is just a noop which may be potentially invalid + return true; +} + +const EmberAfAttributeMetadata * GetAttributeMetadata(const ConcreteAttributePath & aPath) +{ + return emberAfLocateAttributeMetadata(aPath.mEndpointId, aPath.mClusterId, aPath.mAttributeId); +} + +Status ServerClusterCommandExists(const ConcreteCommandPath & aCommandPath) +{ + // TODO: this is just a noop which may be potentially invalid + return Status::Success; +} + +Status CheckEventSupportStatus(const ConcreteEventPath & aPath) +{ + // TODO: this is just a noop which may be potentially invalid + return Status::Success; +} + +CHIP_ERROR WriteSingleClusterData(const Access::SubjectDescriptor & aSubjectDescriptor, const ConcreteDataAttributePath & aPath, + TLV::TLVReader & aReader, WriteHandler * apWriteHandler) +{ + // this is just to get things to compile. eventually this method should NOT be used + return CHIP_ERROR_NOT_IMPLEMENTED; +} + +CHIP_ERROR ReadSingleClusterData(const Access::SubjectDescriptor & aSubjectDescriptor, bool aIsFabricFiltered, + const ConcreteReadAttributePath & aPath, AttributeReportIBs::Builder & aAttributeReports, + AttributeEncodeState * apEncoderState) +{ + // this is just to get things to compile. eventually this method should NOT be used + return CHIP_ERROR_NOT_IMPLEMENTED; +} + +void DispatchSingleClusterCommand(const ConcreteCommandPath & aRequestCommandPath, chip::TLV::TLVReader & aReader, + CommandHandler * apCommandObj) +{ + // TODO: total hardcoded noop +} + +} // namespace app +} // namespace chip diff --git a/src/app/codegen-data-model/tests/TestCodegenModelViaMocks.cpp b/src/app/codegen-data-model/tests/TestCodegenModelViaMocks.cpp index 4403303c70cbb3..11264bbd33a36e 100644 --- a/src/app/codegen-data-model/tests/TestCodegenModelViaMocks.cpp +++ b/src/app/codegen-data-model/tests/TestCodegenModelViaMocks.cpp @@ -1,5 +1,4 @@ /* - * * Copyright (c) 2024 Project CHIP Authors * All rights reserved. * @@ -17,12 +16,35 @@ */ #include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include #include #include +#include +#include #include +#include +#include +#include +#include #include +#include using namespace chip; using namespace chip::Test; @@ -32,6 +54,9 @@ using namespace chip::app::Clusters::Globals::Attributes; namespace { +constexpr FabricIndex kTestFabrixIndex = kMinValidFabricIndex; +constexpr NodeId kTestNodeId = 0xFFFF'1234'ABCD'4321; + constexpr EndpointId kEndpointIdThatIsMissing = kMockEndpointMin - 1; static_assert(kEndpointIdThatIsMissing != kInvalidEndpointId); @@ -39,6 +64,85 @@ static_assert(kEndpointIdThatIsMissing != kMockEndpoint1); static_assert(kEndpointIdThatIsMissing != kMockEndpoint2); static_assert(kEndpointIdThatIsMissing != kMockEndpoint3); +constexpr Access::SubjectDescriptor kAdminSubjectDescriptor{ + .fabricIndex = kTestFabrixIndex, + .authMode = Access::AuthMode::kCase, + .subject = kTestNodeId, +}; +constexpr Access::SubjectDescriptor kViewSubjectDescriptor{ + .fabricIndex = kTestFabrixIndex + 1, + .authMode = Access::AuthMode::kCase, + .subject = kTestNodeId, +}; + +constexpr Access::SubjectDescriptor kDenySubjectDescriptor{ + .fabricIndex = kTestFabrixIndex + 2, + .authMode = Access::AuthMode::kCase, + .subject = kTestNodeId, +}; + +bool operator==(const Access::SubjectDescriptor & a, const Access::SubjectDescriptor & b) +{ + if (a.fabricIndex != b.fabricIndex) + { + return false; + } + if (a.authMode != b.authMode) + { + return false; + } + if (a.subject != b.subject) + { + return false; + } + for (unsigned i = 0; i < a.cats.values.size(); i++) + { + if (a.cats.values[i] != b.cats.values[i]) + { + return false; + } + } + return true; +} + +class MockAccessControl : public Access::AccessControl::Delegate, public Access::AccessControl::DeviceTypeResolver +{ +public: + CHIP_ERROR Check(const Access::SubjectDescriptor & subjectDescriptor, const Access::RequestPath & requestPath, + Access::Privilege requestPrivilege) override + { + if (subjectDescriptor == kAdminSubjectDescriptor) + { + return CHIP_NO_ERROR; + } + if ((subjectDescriptor == kViewSubjectDescriptor) && (requestPrivilege == Access::Privilege::kView)) + { + return CHIP_NO_ERROR; + } + return CHIP_ERROR_ACCESS_DENIED; + } + + bool IsDeviceTypeOnEndpoint(DeviceTypeId deviceType, EndpointId endpoint) override { return true; } +}; + +class ScopedMockAccessControl +{ +public: + ScopedMockAccessControl() { Access::GetAccessControl().Init(&mMock, mMock); } + ~ScopedMockAccessControl() { Access::GetAccessControl().Finish(); } + +private: + MockAccessControl mMock; +}; + +#define MOCK_ATTRIBUTE_ID_FOR_NULLABLE_TYPE(zcl_type) MockAttributeId(zcl_type + 0x1000) +#define MOCK_ATTRIBUTE_CONFIG_NULLABLE(zcl_type) \ + MockAttributeConfig(MOCK_ATTRIBUTE_ID_FOR_NULLABLE_TYPE(zcl_type), zcl_type, ATTRIBUTE_MASK_WRITABLE | ATTRIBUTE_MASK_NULLABLE) + +#define MOCK_ATTRIBUTE_ID_FOR_NON_NULLABLE_TYPE(zcl_type) MockAttributeId(zcl_type + 0x2000) +#define MOCK_ATTRIBUTE_CONFIG_NON_NULLABLE(zcl_type) \ + MockAttributeConfig(MOCK_ATTRIBUTE_ID_FOR_NON_NULLABLE_TYPE(zcl_type), zcl_type, ATTRIBUTE_MASK_WRITABLE) + // clang-format off const MockNodeConfig gTestNodeConfig({ MockEndpointConfig(kMockEndpoint1, { @@ -88,7 +192,155 @@ const MockNodeConfig gTestNodeConfig({ ClusterRevision::Id, FeatureMap::Id, }), MockClusterConfig(MockClusterId(4), { - ClusterRevision::Id, FeatureMap::Id, + ClusterRevision::Id, + FeatureMap::Id, + // several attributes of varying data types for testing. + MOCK_ATTRIBUTE_CONFIG_NON_NULLABLE(ZCL_BOOLEAN_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NON_NULLABLE(ZCL_BITMAP8_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NON_NULLABLE(ZCL_BITMAP16_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NON_NULLABLE(ZCL_BITMAP32_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NON_NULLABLE(ZCL_BITMAP64_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NON_NULLABLE(ZCL_INT8U_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NON_NULLABLE(ZCL_INT16U_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NON_NULLABLE(ZCL_INT24U_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NON_NULLABLE(ZCL_INT32U_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NON_NULLABLE(ZCL_INT40U_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NON_NULLABLE(ZCL_INT48U_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NON_NULLABLE(ZCL_INT56U_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NON_NULLABLE(ZCL_INT64U_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NON_NULLABLE(ZCL_INT8S_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NON_NULLABLE(ZCL_INT16S_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NON_NULLABLE(ZCL_INT24S_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NON_NULLABLE(ZCL_INT32S_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NON_NULLABLE(ZCL_INT40S_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NON_NULLABLE(ZCL_INT48S_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NON_NULLABLE(ZCL_INT56S_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NON_NULLABLE(ZCL_INT64S_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NON_NULLABLE(ZCL_ENUM8_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NON_NULLABLE(ZCL_ENUM16_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NON_NULLABLE(ZCL_PRIORITY_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NON_NULLABLE(ZCL_STATUS_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NON_NULLABLE(ZCL_SINGLE_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NON_NULLABLE(ZCL_DOUBLE_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NON_NULLABLE(ZCL_OCTET_STRING_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NON_NULLABLE(ZCL_CHAR_STRING_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NON_NULLABLE(ZCL_LONG_OCTET_STRING_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NON_NULLABLE(ZCL_LONG_CHAR_STRING_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NON_NULLABLE(ZCL_ARRAY_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NON_NULLABLE(ZCL_STRUCT_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NON_NULLABLE(ZCL_GROUP_ID_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NON_NULLABLE(ZCL_ENDPOINT_NO_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NON_NULLABLE(ZCL_VENDOR_ID_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NON_NULLABLE(ZCL_DEVTYPE_ID_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NON_NULLABLE(ZCL_FABRIC_ID_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NON_NULLABLE(ZCL_FABRIC_IDX_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NON_NULLABLE(ZCL_ENTRY_IDX_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NON_NULLABLE(ZCL_DATA_VER_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NON_NULLABLE(ZCL_EVENT_NO_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NON_NULLABLE(ZCL_SEMTAG_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NON_NULLABLE(ZCL_NAMESPACE_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NON_NULLABLE(ZCL_TAG_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NON_NULLABLE(ZCL_SYSTIME_US_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NON_NULLABLE(ZCL_SYSTIME_MS_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NON_NULLABLE(ZCL_ELAPSED_S_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NON_NULLABLE(ZCL_TEMPERATURE_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NON_NULLABLE(ZCL_POWER_MW_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NON_NULLABLE(ZCL_AMPERAGE_MA_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NON_NULLABLE(ZCL_VOLTAGE_MV_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NON_NULLABLE(ZCL_ENERGY_MWH_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NON_NULLABLE(ZCL_TOD_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NON_NULLABLE(ZCL_DATE_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NON_NULLABLE(ZCL_EPOCH_US_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NON_NULLABLE(ZCL_EPOCH_S_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NON_NULLABLE(ZCL_POSIX_MS_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NON_NULLABLE(ZCL_PERCENT_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NON_NULLABLE(ZCL_PERCENT100THS_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NON_NULLABLE(ZCL_CLUSTER_ID_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NON_NULLABLE(ZCL_ATTRIB_ID_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NON_NULLABLE(ZCL_FIELD_ID_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NON_NULLABLE(ZCL_EVENT_ID_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NON_NULLABLE(ZCL_COMMAND_ID_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NON_NULLABLE(ZCL_ACTION_ID_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NON_NULLABLE(ZCL_TRANS_ID_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NON_NULLABLE(ZCL_NODE_ID_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NON_NULLABLE(ZCL_IPADR_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NON_NULLABLE(ZCL_IPV4ADR_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NON_NULLABLE(ZCL_IPV6ADR_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NON_NULLABLE(ZCL_IPV6PRE_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NON_NULLABLE(ZCL_HWADR_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NULLABLE(ZCL_BOOLEAN_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NULLABLE(ZCL_BITMAP8_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NULLABLE(ZCL_BITMAP16_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NULLABLE(ZCL_BITMAP32_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NULLABLE(ZCL_BITMAP64_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NULLABLE(ZCL_INT8U_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NULLABLE(ZCL_INT16U_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NULLABLE(ZCL_INT24U_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NULLABLE(ZCL_INT32U_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NULLABLE(ZCL_INT40U_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NULLABLE(ZCL_INT48U_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NULLABLE(ZCL_INT56U_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NULLABLE(ZCL_INT64U_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NULLABLE(ZCL_INT8S_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NULLABLE(ZCL_INT16S_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NULLABLE(ZCL_INT24S_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NULLABLE(ZCL_INT32S_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NULLABLE(ZCL_INT40S_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NULLABLE(ZCL_INT48S_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NULLABLE(ZCL_INT56S_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NULLABLE(ZCL_INT64S_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NULLABLE(ZCL_ENUM8_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NULLABLE(ZCL_ENUM16_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NULLABLE(ZCL_PRIORITY_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NULLABLE(ZCL_STATUS_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NULLABLE(ZCL_SINGLE_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NULLABLE(ZCL_DOUBLE_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NULLABLE(ZCL_OCTET_STRING_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NULLABLE(ZCL_CHAR_STRING_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NULLABLE(ZCL_LONG_OCTET_STRING_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NULLABLE(ZCL_LONG_CHAR_STRING_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NULLABLE(ZCL_ARRAY_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NULLABLE(ZCL_STRUCT_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NULLABLE(ZCL_GROUP_ID_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NULLABLE(ZCL_ENDPOINT_NO_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NULLABLE(ZCL_VENDOR_ID_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NULLABLE(ZCL_DEVTYPE_ID_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NULLABLE(ZCL_FABRIC_ID_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NULLABLE(ZCL_FABRIC_IDX_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NULLABLE(ZCL_ENTRY_IDX_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NULLABLE(ZCL_DATA_VER_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NULLABLE(ZCL_EVENT_NO_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NULLABLE(ZCL_SEMTAG_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NULLABLE(ZCL_NAMESPACE_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NULLABLE(ZCL_TAG_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NULLABLE(ZCL_SYSTIME_US_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NULLABLE(ZCL_SYSTIME_MS_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NULLABLE(ZCL_ELAPSED_S_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NULLABLE(ZCL_TEMPERATURE_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NULLABLE(ZCL_POWER_MW_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NULLABLE(ZCL_AMPERAGE_MA_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NULLABLE(ZCL_VOLTAGE_MV_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NULLABLE(ZCL_ENERGY_MWH_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NULLABLE(ZCL_TOD_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NULLABLE(ZCL_DATE_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NULLABLE(ZCL_EPOCH_US_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NULLABLE(ZCL_EPOCH_S_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NULLABLE(ZCL_POSIX_MS_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NULLABLE(ZCL_PERCENT_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NULLABLE(ZCL_PERCENT100THS_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NULLABLE(ZCL_CLUSTER_ID_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NULLABLE(ZCL_ATTRIB_ID_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NULLABLE(ZCL_FIELD_ID_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NULLABLE(ZCL_EVENT_ID_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NULLABLE(ZCL_COMMAND_ID_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NULLABLE(ZCL_ACTION_ID_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NULLABLE(ZCL_TRANS_ID_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NULLABLE(ZCL_NODE_ID_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NULLABLE(ZCL_IPADR_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NULLABLE(ZCL_IPV4ADR_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NULLABLE(ZCL_IPV6ADR_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NULLABLE(ZCL_IPV6PRE_ATTRIBUTE_TYPE), + MOCK_ATTRIBUTE_CONFIG_NULLABLE(ZCL_HWADR_ATTRIBUTE_TYPE), }), }), }); @@ -100,6 +352,253 @@ struct UseMockNodeConfig ~UseMockNodeConfig() { ResetMockNodeConfig(); } }; +template +CHIP_ERROR DecodeList(TLV::TLVReader & reader, std::vector & out) +{ + TLV::TLVType outer; + ReturnErrorOnFailure(reader.EnterContainer(outer)); + while (true) + { + CHIP_ERROR err = reader.Next(); + + if (err == CHIP_END_OF_TLV) + { + return CHIP_NO_ERROR; + } + ReturnErrorOnFailure(err); + + T value; + ReturnErrorOnFailure(chip::app::DataModel::Decode(reader, value)); + out.emplace_back(std::move(value)); + } +} + +class UnsupportedReadAccessInterface : public AttributeAccessInterface +{ +public: + UnsupportedReadAccessInterface(ConcreteAttributePath path) : + AttributeAccessInterface(MakeOptional(path.mEndpointId), path.mClusterId), mPath(path) + {} + ~UnsupportedReadAccessInterface() = default; + + CHIP_ERROR Read(const ConcreteReadAttributePath & path, AttributeValueEncoder & encoder) override + { + if (static_cast(path) != mPath) + { + // returning without trying to handle means "I do not handle this" + return CHIP_NO_ERROR; + } + + return CHIP_IM_GLOBAL_STATUS(UnsupportedRead); + } + +private: + ConcreteAttributePath mPath; +}; + +class StructAttributeAccessInterface : public AttributeAccessInterface +{ +public: + StructAttributeAccessInterface(ConcreteAttributePath path) : + AttributeAccessInterface(MakeOptional(path.mEndpointId), path.mClusterId), mPath(path) + {} + ~StructAttributeAccessInterface() = default; + + CHIP_ERROR Read(const ConcreteReadAttributePath & path, AttributeValueEncoder & encoder) override + { + if (static_cast(path) != mPath) + { + // returning without trying to handle means "I do not handle this" + return CHIP_NO_ERROR; + } + + return encoder.Encode(mData); + } + + void SetReturnedData(const Clusters::UnitTesting::Structs::SimpleStruct::Type & data) { mData = data; } + Clusters::UnitTesting::Structs::SimpleStruct::Type simpleStruct; + +private: + ConcreteAttributePath mPath; + Clusters::UnitTesting::Structs::SimpleStruct::Type mData; +}; + +class ListAttributeAcessInterface : public AttributeAccessInterface +{ +public: + ListAttributeAcessInterface(ConcreteAttributePath path) : + AttributeAccessInterface(MakeOptional(path.mEndpointId), path.mClusterId), mPath(path) + {} + ~ListAttributeAcessInterface() = default; + + CHIP_ERROR Read(const ConcreteReadAttributePath & path, AttributeValueEncoder & encoder) override + { + if (static_cast(path) != mPath) + { + // returning without trying to handle means "I do not handle this" + return CHIP_NO_ERROR; + } + + return encoder.EncodeList([this](const auto & listEncoder) { + for (unsigned i = 0; i < mCount; i++) + { + mData.a = static_cast(i % 0xFF); + ReturnErrorOnFailure(listEncoder.Encode(mData)); + } + return CHIP_NO_ERROR; + }); + } + + void SetReturnedData(const Clusters::UnitTesting::Structs::SimpleStruct::Type & data) { mData = data; } + void SetReturnedDataCount(unsigned count) { mCount = count; } + Clusters::UnitTesting::Structs::SimpleStruct::Type simpleStruct; + +private: + ConcreteAttributePath mPath; + Clusters::UnitTesting::Structs::SimpleStruct::Type mData; + unsigned mCount = 0; +}; + +/// RAII registration of an attribute access interface +template +class RegisteredAttributeAccessInterface +{ +public: + template + RegisteredAttributeAccessInterface(Args &&... args) : mData(std::forward(args)...) + { + VerifyOrDie(registerAttributeAccessOverride(&mData)); + } + ~RegisteredAttributeAccessInterface() { unregisterAttributeAccessOverride(&mData); } + + T * operator->() { return &mData; } + T & operator*() { return mData; } + +private: + T mData; +}; + +/// Contains a `ReadAttributeRequest` as well as classes to convert this into a AttributeReportIBs +/// and later decode it +/// +/// It wraps boilerplate code to obtain a `AttributeValueEncoder` as well as later decoding +/// the underlying encoded data for verification. +struct TestReadRequest +{ + ReadAttributeRequest request; + + // encoded-used classes + EncodedReportIBs encodedIBs; + AttributeReportIBs::Builder reportBuilder; + std::unique_ptr encoder; + + TestReadRequest(const Access::SubjectDescriptor & subject, const ConcreteAttributePath & path) + { + // operationFlags is 0 i.e. not internal + // readFlags is 0 i.e. not fabric filtered + // dataVersion is missing (no data version filtering) + request.subjectDescriptor = subject; + request.path = path; + } + + std::unique_ptr StartEncoding(chip::app::InteractionModel::DataModel * model, + AttributeEncodeState state = AttributeEncodeState()) + { + std::optional info = model->GetClusterInfo(request.path); + if (!info.has_value()) + { + ChipLogError(Test, "Missing cluster information - no data version"); + return nullptr; + } + + DataVersion dataVersion = info->dataVersion; // NOLINT(bugprone-unchecked-optional-access) + + CHIP_ERROR err = encodedIBs.StartEncoding(reportBuilder); + if (err != CHIP_NO_ERROR) + { + ChipLogError(Test, "FAILURE starting encoding %" CHIP_ERROR_FORMAT, err.Format()); + return nullptr; + } + + // TODO: could we test isFabricFiltered and EncodeState? + + // request.subjectDescriptor is known non-null because it is set in the constructor + // NOLINTNEXTLINE(bugprone-unchecked-optional-access) + return std::make_unique(reportBuilder, *request.subjectDescriptor, request.path, dataVersion, + false /* aIsFabricFiltered */, state); + } + + CHIP_ERROR FinishEncoding() { return encodedIBs.FinishEncoding(reportBuilder); } +}; + +template +void TestEmberScalarTypeRead(typename NumericAttributeTraits::WorkingType value) +{ + UseMockNodeConfig config(gTestNodeConfig); + chip::app::CodegenDataModel model; + ScopedMockAccessControl accessControl; + + TestReadRequest testRequest( + kAdminSubjectDescriptor, + ConcreteAttributePath(kMockEndpoint3, MockClusterId(4), MOCK_ATTRIBUTE_ID_FOR_NON_NULLABLE_TYPE(ZclType))); + + // Ember encoding for integers is IDENTICAL to the in-memory representation for them + typename NumericAttributeTraits::StorageType storage; + NumericAttributeTraits::WorkingToStorage(value, storage); + chip::Test::SetEmberReadOutput(ByteSpan(reinterpret_cast(&storage), sizeof(storage))); + + // Data read via the encoder + std::unique_ptr encoder = testRequest.StartEncoding(&model); + ASSERT_EQ(model.ReadAttribute(testRequest.request, *encoder), CHIP_NO_ERROR); + ASSERT_EQ(testRequest.FinishEncoding(), CHIP_NO_ERROR); + + // Validate after read + std::vector attribute_data; + ASSERT_EQ(testRequest.encodedIBs.Decode(attribute_data), CHIP_NO_ERROR); + ASSERT_EQ(attribute_data.size(), 1u); + + DecodedAttributeData & encodedData = attribute_data[0]; + ASSERT_EQ(encodedData.attributePath, testRequest.request.path); + + typename NumericAttributeTraits::WorkingType actual; + ASSERT_EQ(chip::app::DataModel::Decode::WorkingType>(encodedData.dataReader, actual), + CHIP_NO_ERROR); + ASSERT_EQ(actual, value); +} + +template +void TestEmberScalarNullRead() +{ + UseMockNodeConfig config(gTestNodeConfig); + chip::app::CodegenDataModel model; + ScopedMockAccessControl accessControl; + + TestReadRequest testRequest( + kAdminSubjectDescriptor, + ConcreteAttributePath(kMockEndpoint3, MockClusterId(4), MOCK_ATTRIBUTE_ID_FOR_NULLABLE_TYPE(ZclType))); + + // Ember encoding for integers is IDENTICAL to the in-memory representation for them + typename NumericAttributeTraits::StorageType nullValue; + NumericAttributeTraits::SetNull(nullValue); + chip::Test::SetEmberReadOutput(ByteSpan(reinterpret_cast(&nullValue), sizeof(nullValue))); + + // Data read via the encoder + std::unique_ptr encoder = testRequest.StartEncoding(&model); + ASSERT_EQ(model.ReadAttribute(testRequest.request, *encoder), CHIP_NO_ERROR); + ASSERT_EQ(testRequest.FinishEncoding(), CHIP_NO_ERROR); + + // Validate after read + std::vector attribute_data; + ASSERT_EQ(testRequest.encodedIBs.Decode(attribute_data), CHIP_NO_ERROR); + ASSERT_EQ(attribute_data.size(), 1u); + + DecodedAttributeData & encodedData = attribute_data[0]; + ASSERT_EQ(encodedData.attributePath, testRequest.request.path); + chip::app::DataModel::Nullable::WorkingType> actual; + ASSERT_EQ(chip::app::DataModel::Decode(encodedData.dataReader, actual), CHIP_NO_ERROR); + ASSERT_TRUE(actual.IsNull()); +} + } // namespace TEST(TestCodegenModelViaMocks, IterateOverEndpoints) @@ -486,3 +985,685 @@ TEST(TestCodegenModelViaMocks, IterateOverGeneratedCommands) EXPECT_FALSE(path.HasValidIds()); } } + +TEST(TestCodegenModelViaMocks, EmberAttributeReadAclDeny) +{ + UseMockNodeConfig config(gTestNodeConfig); + chip::app::CodegenDataModel model; + ScopedMockAccessControl accessControl; + + TestReadRequest testRequest(kDenySubjectDescriptor, + ConcreteAttributePath(kMockEndpoint1, MockClusterId(1), MockAttributeId(10))); + std::unique_ptr encoder = testRequest.StartEncoding(&model); + + ASSERT_EQ(model.ReadAttribute(testRequest.request, *encoder), CHIP_ERROR_ACCESS_DENIED); +} + +TEST(TestCodegenModelViaMocks, ReadForInvalidGlobalAttributePath) +{ + UseMockNodeConfig config(gTestNodeConfig); + chip::app::CodegenDataModel model; + ScopedMockAccessControl accessControl; + + { + TestReadRequest testRequest(kAdminSubjectDescriptor, + ConcreteAttributePath(kEndpointIdThatIsMissing, MockClusterId(1), AttributeList::Id)); + std::unique_ptr encoder = testRequest.StartEncoding(&model); + ASSERT_EQ(model.ReadAttribute(testRequest.request, *encoder), CHIP_IM_GLOBAL_STATUS(UnsupportedEndpoint)); + } + + { + TestReadRequest testRequest(kAdminSubjectDescriptor, + ConcreteAttributePath(kMockEndpoint1, kInvalidClusterId, AttributeList::Id)); + std::unique_ptr encoder = testRequest.StartEncoding(&model); + ASSERT_EQ(model.ReadAttribute(testRequest.request, *encoder), CHIP_IM_GLOBAL_STATUS(UnsupportedCluster)); + } +} + +TEST(TestCodegenModelViaMocks, EmberAttributeInvalidRead) +{ + UseMockNodeConfig config(gTestNodeConfig); + chip::app::CodegenDataModel model; + ScopedMockAccessControl accessControl; + + // Invalid attribute + { + TestReadRequest testRequest(kAdminSubjectDescriptor, + ConcreteAttributePath(kMockEndpoint1, MockClusterId(1), MockAttributeId(10))); + std::unique_ptr encoder = testRequest.StartEncoding(&model); + + ASSERT_EQ(model.ReadAttribute(testRequest.request, *encoder), CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute)); + } + + // Invalid cluster + { + TestReadRequest testRequest(kAdminSubjectDescriptor, + ConcreteAttributePath(kMockEndpoint1, MockClusterId(100), MockAttributeId(1))); + std::unique_ptr encoder = testRequest.StartEncoding(&model); + + ASSERT_EQ(model.ReadAttribute(testRequest.request, *encoder), CHIP_IM_GLOBAL_STATUS(UnsupportedCluster)); + } + + // Invalid endpoint + { + TestReadRequest testRequest(kAdminSubjectDescriptor, + ConcreteAttributePath(kEndpointIdThatIsMissing, MockClusterId(1), MockAttributeId(1))); + std::unique_ptr encoder = testRequest.StartEncoding(&model); + + ASSERT_EQ(model.ReadAttribute(testRequest.request, *encoder), CHIP_IM_GLOBAL_STATUS(UnsupportedEndpoint)); + } +} + +TEST(TestCodegenModelViaMocks, EmberAttributePathExpansionAccessDeniedRead) +{ + UseMockNodeConfig config(gTestNodeConfig); + chip::app::CodegenDataModel model; + ScopedMockAccessControl accessControl; + + TestReadRequest testRequest(kDenySubjectDescriptor, + ConcreteAttributePath(kMockEndpoint1, MockClusterId(1), MockAttributeId(10))); + std::unique_ptr encoder = testRequest.StartEncoding(&model); + + testRequest.request.path.mExpanded = true; + + // For expanded paths, access control failures succeed without encoding anything + // This is temporary until ACL checks are moved inside the IM/ReportEngine + ASSERT_EQ(model.ReadAttribute(testRequest.request, *encoder), CHIP_NO_ERROR); + ASSERT_FALSE(encoder->TriedEncode()); +} + +TEST(TestCodegenModelViaMocks, AccessInterfaceUnsupportedRead) +{ + UseMockNodeConfig config(gTestNodeConfig); + chip::app::CodegenDataModel model; + ScopedMockAccessControl accessControl; + + const ConcreteAttributePath kTestPath(kMockEndpoint3, MockClusterId(4), + MOCK_ATTRIBUTE_ID_FOR_NON_NULLABLE_TYPE(ZCL_STRUCT_ATTRIBUTE_TYPE)); + + TestReadRequest testRequest(kAdminSubjectDescriptor, kTestPath); + RegisteredAttributeAccessInterface aai(kTestPath); + + testRequest.request.path.mExpanded = true; + + // For expanded paths, unsupported read from AAI (i.e. reading write-only data) + // succeed without attempting to encode. + // This is temporary until ACL checks are moved inside the IM/ReportEngine + std::unique_ptr encoder = testRequest.StartEncoding(&model); + ASSERT_EQ(model.ReadAttribute(testRequest.request, *encoder), CHIP_NO_ERROR); + ASSERT_FALSE(encoder->TriedEncode()); +} + +TEST(TestCodegenModelViaMocks, EmberAttributeReadInt32S) +{ + TestEmberScalarTypeRead(-1234); +} + +TEST(TestCodegenModelViaMocks, EmberAttributeReadEnum16) +{ + TestEmberScalarTypeRead(0x1234); +} + +TEST(TestCodegenModelViaMocks, EmberAttributeReadFloat) +{ + TestEmberScalarTypeRead(0.625); +} + +TEST(TestCodegenModelViaMocks, EmberAttributeReadDouble) +{ + TestEmberScalarTypeRead(0.625); +} + +TEST(TestCodegenModelViaMocks, EmberAttributeReadInt24U) +{ + TestEmberScalarTypeRead, ZCL_INT24U_ATTRIBUTE_TYPE>(0x1234AB); +} + +TEST(TestCodegenModelViaMocks, EmberAttributeReadInt32U) +{ + TestEmberScalarTypeRead(0x1234ABCD); +} + +TEST(TestCodegenModelViaMocks, EmberAttributeReadInt40U) +{ + TestEmberScalarTypeRead, ZCL_INT40U_ATTRIBUTE_TYPE>(0x1122334455); +} + +TEST(TestCodegenModelViaMocks, EmberAttributeReadInt48U) +{ + TestEmberScalarTypeRead, ZCL_INT48U_ATTRIBUTE_TYPE>(0xAABB11223344); +} + +TEST(TestCodegenModelViaMocks, EmberAttributeReadInt56U) +{ + TestEmberScalarTypeRead, ZCL_INT56U_ATTRIBUTE_TYPE>(0xAABB11223344); +} + +TEST(TestCodegenModelViaMocks, EmberAttributeReadBool) +{ + TestEmberScalarTypeRead(true); + TestEmberScalarTypeRead(false); +} + +TEST(TestCodegenModelViaMocks, EmberAttributeReadInt8U) +{ + TestEmberScalarTypeRead(0x12); +} + +TEST(TestCodegenModelViaMocks, EmberAttributeReadNulls) +{ + TestEmberScalarNullRead(); + TestEmberScalarNullRead(); + TestEmberScalarNullRead, ZCL_INT24U_ATTRIBUTE_TYPE>(); + TestEmberScalarNullRead(); + TestEmberScalarNullRead, ZCL_INT40U_ATTRIBUTE_TYPE>(); + TestEmberScalarNullRead, ZCL_INT48U_ATTRIBUTE_TYPE>(); + TestEmberScalarNullRead, ZCL_INT56U_ATTRIBUTE_TYPE>(); + TestEmberScalarNullRead(); + + TestEmberScalarNullRead(); + TestEmberScalarNullRead(); + TestEmberScalarNullRead, ZCL_INT24S_ATTRIBUTE_TYPE>(); + TestEmberScalarNullRead(); + TestEmberScalarNullRead, ZCL_INT40S_ATTRIBUTE_TYPE>(); + TestEmberScalarNullRead, ZCL_INT48S_ATTRIBUTE_TYPE>(); + TestEmberScalarNullRead, ZCL_INT56S_ATTRIBUTE_TYPE>(); + TestEmberScalarNullRead(); + + TestEmberScalarNullRead(); + + TestEmberScalarNullRead(); + TestEmberScalarNullRead(); +} + +TEST(TestCodegenModelViaMocks, EmberAttributeReadErrorReading) +{ + UseMockNodeConfig config(gTestNodeConfig); + chip::app::CodegenDataModel model; + ScopedMockAccessControl accessControl; + + { + TestReadRequest testRequest( + kAdminSubjectDescriptor, + ConcreteAttributePath(kMockEndpoint3, MockClusterId(4), + MOCK_ATTRIBUTE_ID_FOR_NULLABLE_TYPE(ZCL_LONG_OCTET_STRING_ATTRIBUTE_TYPE))); + + chip::Test::SetEmberReadOutput(Protocols::InteractionModel::Status::Failure); + + // Actual read via an encoder + std::unique_ptr encoder = testRequest.StartEncoding(&model); + ASSERT_EQ(model.ReadAttribute(testRequest.request, *encoder), CHIP_IM_GLOBAL_STATUS(Failure)); + } + + { + TestReadRequest testRequest( + kAdminSubjectDescriptor, + ConcreteAttributePath(kMockEndpoint3, MockClusterId(4), + MOCK_ATTRIBUTE_ID_FOR_NULLABLE_TYPE(ZCL_LONG_OCTET_STRING_ATTRIBUTE_TYPE))); + + chip::Test::SetEmberReadOutput(Protocols::InteractionModel::Status::Busy); + + // Actual read via an encoder + std::unique_ptr encoder = testRequest.StartEncoding(&model); + ASSERT_EQ(model.ReadAttribute(testRequest.request, *encoder), CHIP_IM_GLOBAL_STATUS(Busy)); + } +} + +TEST(TestCodegenModelViaMocks, EmberAttributeReadNullOctetString) +{ + UseMockNodeConfig config(gTestNodeConfig); + chip::app::CodegenDataModel model; + ScopedMockAccessControl accessControl; + + TestReadRequest testRequest(kAdminSubjectDescriptor, + ConcreteAttributePath(kMockEndpoint3, MockClusterId(4), + MOCK_ATTRIBUTE_ID_FOR_NULLABLE_TYPE(ZCL_LONG_OCTET_STRING_ATTRIBUTE_TYPE))); + + // NOTE: This is a pascal string of size 0xFFFF which for null strings is a null marker + char data[] = "\xFF\xFFInvalid length string is null"; + chip::Test::SetEmberReadOutput(ByteSpan(reinterpret_cast(data), sizeof(data))); + + // Actual read via an encoder + std::unique_ptr encoder = testRequest.StartEncoding(&model); + ASSERT_EQ(model.ReadAttribute(testRequest.request, *encoder), CHIP_NO_ERROR); + ASSERT_EQ(testRequest.FinishEncoding(), CHIP_NO_ERROR); + + // Validate after read + std::vector attribute_data; + ASSERT_EQ(testRequest.encodedIBs.Decode(attribute_data), CHIP_NO_ERROR); + ASSERT_EQ(attribute_data.size(), 1u); + + DecodedAttributeData & encodedData = attribute_data[0]; + ASSERT_EQ(encodedData.attributePath, testRequest.request.path); + + // data element should be null for the given 0xFFFF length + ASSERT_EQ(encodedData.dataReader.GetType(), TLV::kTLVType_Null); + + chip::app::DataModel::Nullable actual; + ASSERT_EQ(chip::app::DataModel::Decode(encodedData.dataReader, actual), CHIP_NO_ERROR); + ASSERT_TRUE(actual.IsNull()); +} + +TEST(TestCodegenModelViaMocks, EmberAttributeReadOctetString) +{ + UseMockNodeConfig config(gTestNodeConfig); + chip::app::CodegenDataModel model; + ScopedMockAccessControl accessControl; + + TestReadRequest testRequest( + kAdminSubjectDescriptor, + ConcreteAttributePath(kMockEndpoint3, MockClusterId(4), + MOCK_ATTRIBUTE_ID_FOR_NON_NULLABLE_TYPE(ZCL_LONG_OCTET_STRING_ATTRIBUTE_TYPE))); + + // NOTE: This is a pascal string, so actual data is "test" + // the longer encoding is to make it clear we do not encode the overflow + char data[] = "\0\0testing here with overflow"; + uint16_t len = 4; + memcpy(data, &len, sizeof(uint16_t)); + chip::Test::SetEmberReadOutput(ByteSpan(reinterpret_cast(data), sizeof(data))); + + // Actual read via an encoder + std::unique_ptr encoder = testRequest.StartEncoding(&model); + ASSERT_EQ(model.ReadAttribute(testRequest.request, *encoder), CHIP_NO_ERROR); + ASSERT_EQ(testRequest.FinishEncoding(), CHIP_NO_ERROR); + + // Validate after read + std::vector attribute_data; + ASSERT_EQ(testRequest.encodedIBs.Decode(attribute_data), CHIP_NO_ERROR); + ASSERT_EQ(attribute_data.size(), 1u); + + const DecodedAttributeData & encodedData = attribute_data[0]; + ASSERT_EQ(encodedData.attributePath, testRequest.request.path); + + // data element should be a encoded byte string as this is what the attribute type is + ASSERT_EQ(encodedData.dataReader.GetType(), TLV::kTLVType_ByteString); + ByteSpan actual; + ASSERT_EQ(encodedData.dataReader.Get(actual), CHIP_NO_ERROR); + + ByteSpan expected(reinterpret_cast(data + 2), 4); + ASSERT_TRUE(actual.data_equal(expected)); +} + +TEST(TestCodegenModelViaMocks, EmberAttributeReadLongOctetString) +{ + UseMockNodeConfig config(gTestNodeConfig); + chip::app::CodegenDataModel model; + ScopedMockAccessControl accessControl; + + TestReadRequest testRequest(kAdminSubjectDescriptor, + ConcreteAttributePath(kMockEndpoint3, MockClusterId(4), + MOCK_ATTRIBUTE_ID_FOR_NON_NULLABLE_TYPE(ZCL_OCTET_STRING_ATTRIBUTE_TYPE))); + + // NOTE: This is a pascal string, so actual data is "test" + // the longer encoding is to make it clear we do not encode the overflow + const char data[] = "\x04testing here with overflow"; + chip::Test::SetEmberReadOutput(ByteSpan(reinterpret_cast(data), sizeof(data))); + + // Actual read via an encoder + std::unique_ptr encoder = testRequest.StartEncoding(&model); + ASSERT_EQ(model.ReadAttribute(testRequest.request, *encoder), CHIP_NO_ERROR); + ASSERT_EQ(testRequest.FinishEncoding(), CHIP_NO_ERROR); + + // Validate after read + std::vector attribute_data; + ASSERT_EQ(testRequest.encodedIBs.Decode(attribute_data), CHIP_NO_ERROR); + ASSERT_EQ(attribute_data.size(), 1u); + + const DecodedAttributeData & encodedData = attribute_data[0]; + ASSERT_EQ(encodedData.attributePath, testRequest.request.path); + + // data element should be a encoded byte string as this is what the attribute type is + ASSERT_EQ(encodedData.dataReader.GetType(), TLV::kTLVType_ByteString); + ByteSpan actual; + ASSERT_EQ(encodedData.dataReader.Get(actual), CHIP_NO_ERROR); + + ByteSpan expected(reinterpret_cast(data + 1), 4); + ASSERT_TRUE(actual.data_equal(expected)); +} + +TEST(TestCodegenModelViaMocks, EmberAttributeReadShortString) +{ + UseMockNodeConfig config(gTestNodeConfig); + chip::app::CodegenDataModel model; + ScopedMockAccessControl accessControl; + + TestReadRequest testRequest(kAdminSubjectDescriptor, + ConcreteAttributePath(kMockEndpoint3, MockClusterId(4), + MOCK_ATTRIBUTE_ID_FOR_NON_NULLABLE_TYPE(ZCL_CHAR_STRING_ATTRIBUTE_TYPE))); + + // NOTE: This is a pascal string, so actual data is "abcde" + // the longer encoding is to make it clear we do not encode the overflow + char data[] = "\0abcdef...this is the alphabet"; + uint16_t len = 5; + memcpy(data, &len, sizeof(uint8_t)); + chip::Test::SetEmberReadOutput(ByteSpan(reinterpret_cast(data), sizeof(data))); + + // Actual read via an encoder + std::unique_ptr encoder = testRequest.StartEncoding(&model); + ASSERT_EQ(model.ReadAttribute(testRequest.request, *encoder), CHIP_NO_ERROR); + ASSERT_EQ(testRequest.FinishEncoding(), CHIP_NO_ERROR); + + // Validate after reading + std::vector attribute_data; + ASSERT_EQ(testRequest.encodedIBs.Decode(attribute_data), CHIP_NO_ERROR); + ASSERT_EQ(attribute_data.size(), 1u); + + const DecodedAttributeData & encodedData = attribute_data[0]; + ASSERT_EQ(encodedData.attributePath, testRequest.request.path); + + // data element should be a encoded byte string as this is what the attribute type is + ASSERT_EQ(encodedData.dataReader.GetType(), TLV::kTLVType_UTF8String); + CharSpan actual; + ASSERT_EQ(encodedData.dataReader.Get(actual), CHIP_NO_ERROR); + ASSERT_TRUE(actual.data_equal("abcde"_span)); +} + +TEST(TestCodegenModelViaMocks, EmberAttributeReadLongString) +{ + UseMockNodeConfig config(gTestNodeConfig); + chip::app::CodegenDataModel model; + ScopedMockAccessControl accessControl; + + TestReadRequest testRequest( + kAdminSubjectDescriptor, + ConcreteAttributePath(kMockEndpoint3, MockClusterId(4), + MOCK_ATTRIBUTE_ID_FOR_NON_NULLABLE_TYPE(ZCL_LONG_CHAR_STRING_ATTRIBUTE_TYPE))); + + // NOTE: This is a pascal string, so actual data is "abcde" + // the longer encoding is to make it clear we do not encode the overflow + char data[] = "\0\0abcdef...this is the alphabet"; + uint16_t len = 5; + memcpy(data, &len, sizeof(uint16_t)); + chip::Test::SetEmberReadOutput(ByteSpan(reinterpret_cast(data), sizeof(data))); + + // Actual read via an encoder + std::unique_ptr encoder = testRequest.StartEncoding(&model); + ASSERT_EQ(model.ReadAttribute(testRequest.request, *encoder), CHIP_NO_ERROR); + ASSERT_EQ(testRequest.FinishEncoding(), CHIP_NO_ERROR); + + // Validate after reading + std::vector attribute_data; + ASSERT_EQ(testRequest.encodedIBs.Decode(attribute_data), CHIP_NO_ERROR); + ASSERT_EQ(attribute_data.size(), 1u); + + const DecodedAttributeData & encodedData = attribute_data[0]; + ASSERT_EQ(encodedData.attributePath, testRequest.request.path); + + // data element should be a encoded byte string as this is what the attribute type is + ASSERT_EQ(encodedData.dataReader.GetType(), TLV::kTLVType_UTF8String); + CharSpan actual; + ASSERT_EQ(encodedData.dataReader.Get(actual), CHIP_NO_ERROR); + ASSERT_TRUE(actual.data_equal("abcde"_span)); +} + +TEST(TestCodegenModelViaMocks, AttributeAccessInterfaceStructRead) +{ + UseMockNodeConfig config(gTestNodeConfig); + chip::app::CodegenDataModel model; + ScopedMockAccessControl accessControl; + + const ConcreteAttributePath kStructPath(kMockEndpoint3, MockClusterId(4), + MOCK_ATTRIBUTE_ID_FOR_NON_NULLABLE_TYPE(ZCL_STRUCT_ATTRIBUTE_TYPE)); + + TestReadRequest testRequest(kAdminSubjectDescriptor, kStructPath); + RegisteredAttributeAccessInterface aai(kStructPath); + + aai->SetReturnedData(Clusters::UnitTesting::Structs::SimpleStruct::Type{ + .a = 123, + .b = true, + .e = "foo"_span, + .g = 0.5, + .h = 0.125, + }); + + std::unique_ptr encoder = testRequest.StartEncoding(&model); + ASSERT_EQ(model.ReadAttribute(testRequest.request, *encoder), CHIP_NO_ERROR); + ASSERT_EQ(testRequest.FinishEncoding(), CHIP_NO_ERROR); + + // Validate after read + std::vector attribute_data; + ASSERT_EQ(testRequest.encodedIBs.Decode(attribute_data), CHIP_NO_ERROR); + ASSERT_EQ(attribute_data.size(), 1u); + + DecodedAttributeData & encodedData = attribute_data[0]; + ASSERT_EQ(encodedData.attributePath, testRequest.request.path); + + ASSERT_EQ(encodedData.dataReader.GetType(), TLV::kTLVType_Structure); + Clusters::UnitTesting::Structs::SimpleStruct::DecodableType actual; + ASSERT_EQ(chip::app::DataModel::Decode(encodedData.dataReader, actual), CHIP_NO_ERROR); + + ASSERT_EQ(actual.a, 123); + ASSERT_EQ(actual.b, true); + ASSERT_EQ(actual.g, 0.5); + ASSERT_EQ(actual.h, 0.125); + ASSERT_TRUE(actual.e.data_equal("foo"_span)); +} + +TEST(TestCodegenModelViaMocks, AttributeAccessInterfaceListRead) +{ + UseMockNodeConfig config(gTestNodeConfig); + chip::app::CodegenDataModel model; + ScopedMockAccessControl accessControl; + + const ConcreteAttributePath kStructPath(kMockEndpoint3, MockClusterId(4), + MOCK_ATTRIBUTE_ID_FOR_NON_NULLABLE_TYPE(ZCL_ARRAY_ATTRIBUTE_TYPE)); + + TestReadRequest testRequest(kAdminSubjectDescriptor, kStructPath); + RegisteredAttributeAccessInterface aai(kStructPath); + + constexpr unsigned kDataCount = 5; + aai->SetReturnedData(Clusters::UnitTesting::Structs::SimpleStruct::Type{ + .b = true, + .e = "xyz"_span, + .g = 0.25, + .h = 0.5, + }); + aai->SetReturnedDataCount(kDataCount); + + std::unique_ptr encoder = testRequest.StartEncoding(&model); + ASSERT_EQ(model.ReadAttribute(testRequest.request, *encoder), CHIP_NO_ERROR); + ASSERT_EQ(testRequest.FinishEncoding(), CHIP_NO_ERROR); + + // Validate after read + std::vector attribute_data; + ASSERT_EQ(testRequest.encodedIBs.Decode(attribute_data), CHIP_NO_ERROR); + ASSERT_EQ(attribute_data.size(), 1u); + + DecodedAttributeData & encodedData = attribute_data[0]; + ASSERT_EQ(encodedData.attributePath, testRequest.request.path); + + ASSERT_EQ(encodedData.dataReader.GetType(), TLV::kTLVType_Array); + + std::vector items; + ASSERT_EQ(DecodeList(encodedData.dataReader, items), CHIP_NO_ERROR); + + ASSERT_EQ(items.size(), kDataCount); + + for (unsigned i = 0; i < kDataCount; i++) + { + Clusters::UnitTesting::Structs::SimpleStruct::DecodableType & actual = items[i]; + + ASSERT_EQ(actual.a, static_cast(i & 0xFF)); + ASSERT_EQ(actual.b, true); + ASSERT_EQ(actual.g, 0.25); + ASSERT_EQ(actual.h, 0.5); + ASSERT_TRUE(actual.e.data_equal("xyz"_span)); + } +} + +TEST(TestCodegenModelViaMocks, AttributeAccessInterfaceListOverflowRead) +{ + UseMockNodeConfig config(gTestNodeConfig); + chip::app::CodegenDataModel model; + ScopedMockAccessControl accessControl; + + const ConcreteAttributePath kStructPath(kMockEndpoint3, MockClusterId(4), + MOCK_ATTRIBUTE_ID_FOR_NON_NULLABLE_TYPE(ZCL_ARRAY_ATTRIBUTE_TYPE)); + + TestReadRequest testRequest(kAdminSubjectDescriptor, kStructPath); + RegisteredAttributeAccessInterface aai(kStructPath); + + constexpr unsigned kDataCount = 1024; + aai->SetReturnedData(Clusters::UnitTesting::Structs::SimpleStruct::Type{ + .b = true, + .e = "thisislongertofillupfaster"_span, + .g = 0.25, + .h = 0.5, + }); + aai->SetReturnedDataCount(kDataCount); + + std::unique_ptr encoder = testRequest.StartEncoding(&model); + // NOTE: overflow, however data should be valid. Technically both NO_MEMORY and BUFFER_TOO_SMALL + // should be ok here, however we know buffer-too-small is the error in this case hence + // the compare (easier to write the test and read the output) + ASSERT_EQ(model.ReadAttribute(testRequest.request, *encoder), CHIP_ERROR_BUFFER_TOO_SMALL); + ASSERT_EQ(testRequest.FinishEncoding(), CHIP_NO_ERROR); + + // Validate after read + std::vector attribute_data; + ASSERT_EQ(testRequest.encodedIBs.Decode(attribute_data), CHIP_NO_ERROR); + ASSERT_EQ(attribute_data.size(), 1u); + + DecodedAttributeData & encodedData = attribute_data[0]; + ASSERT_EQ(encodedData.attributePath, testRequest.request.path); + + ASSERT_EQ(encodedData.dataReader.GetType(), TLV::kTLVType_Array); + + std::vector items; + ASSERT_EQ(DecodeList(encodedData.dataReader, items), CHIP_NO_ERROR); + + // On last check, 16 items can be encoded. Set some non-zero range to be enforced here that + // SOME list items are actually encoded. Actual lower bound here IS ARBITRARY and was picked + // to just ensure non-zero item count for checks. + ASSERT_GT(items.size(), 5u); + ASSERT_LT(items.size(), kDataCount); + + for (unsigned i = 0; i < items.size(); i++) + { + Clusters::UnitTesting::Structs::SimpleStruct::DecodableType & actual = items[i]; + + ASSERT_EQ(actual.a, static_cast(i & 0xFF)); + ASSERT_EQ(actual.b, true); + ASSERT_EQ(actual.g, 0.25); + ASSERT_EQ(actual.h, 0.5); + ASSERT_TRUE(actual.e.data_equal("thisislongertofillupfaster"_span)); + } +} + +TEST(TestCodegenModelViaMocks, AttributeAccessInterfaceListIncrementalRead) +{ + UseMockNodeConfig config(gTestNodeConfig); + chip::app::CodegenDataModel model; + ScopedMockAccessControl accessControl; + + const ConcreteAttributePath kStructPath(kMockEndpoint3, MockClusterId(4), + MOCK_ATTRIBUTE_ID_FOR_NON_NULLABLE_TYPE(ZCL_ARRAY_ATTRIBUTE_TYPE)); + + TestReadRequest testRequest(kAdminSubjectDescriptor, kStructPath); + RegisteredAttributeAccessInterface aai(kStructPath); + + constexpr unsigned kDataCount = 1024; + constexpr unsigned kEncodeIndexStart = 101; + aai->SetReturnedData(Clusters::UnitTesting::Structs::SimpleStruct::Type{ + .b = true, + .e = "thisislongertofillupfaster"_span, + .g = 0.25, + .h = 0.5, + }); + aai->SetReturnedDataCount(kDataCount); + + AttributeEncodeState encodeState; + encodeState.SetCurrentEncodingListIndex(kEncodeIndexStart); + + std::unique_ptr encoder = testRequest.StartEncoding(&model, encodeState); + // NOTE: overflow, however data should be valid. Technically both NO_MEMORY and BUFFER_TOO_SMALL + // should be ok here, however we know buffer-too-small is the error in this case hence + // the compare (easier to write the test and read the output) + ASSERT_EQ(model.ReadAttribute(testRequest.request, *encoder), CHIP_ERROR_BUFFER_TOO_SMALL); + ASSERT_EQ(testRequest.FinishEncoding(), CHIP_NO_ERROR); + + // Validate after read + std::vector attribute_data; + ASSERT_EQ(testRequest.encodedIBs.Decode(attribute_data), CHIP_NO_ERROR); + + // Incremental encodes are separate list items, repeated + // actual size IS ARBITRARY (current test sets it at 11) + ASSERT_GT(attribute_data.size(), 3u); + + for (unsigned i = 0; i < attribute_data.size(); i++) + { + DecodedAttributeData & encodedData = attribute_data[i]; + ASSERT_EQ(encodedData.attributePath.mEndpointId, testRequest.request.path.mEndpointId); + ASSERT_EQ(encodedData.attributePath.mClusterId, testRequest.request.path.mClusterId); + ASSERT_EQ(encodedData.attributePath.mAttributeId, testRequest.request.path.mAttributeId); + ASSERT_EQ(encodedData.attributePath.mListOp, ConcreteDataAttributePath::ListOperation::AppendItem); + + // individual structures encoded in each item + ASSERT_EQ(encodedData.dataReader.GetType(), TLV::kTLVType_Structure); + + Clusters::UnitTesting::Structs::SimpleStruct::DecodableType actual; + ASSERT_EQ(chip::app::DataModel::Decode(encodedData.dataReader, actual), CHIP_NO_ERROR); + + ASSERT_EQ(actual.a, static_cast((i + kEncodeIndexStart) & 0xFF)); + ASSERT_EQ(actual.b, true); + ASSERT_EQ(actual.g, 0.25); + ASSERT_EQ(actual.h, 0.5); + ASSERT_TRUE(actual.e.data_equal("thisislongertofillupfaster"_span)); + } +} + +TEST(TestCodegenModelViaMocks, ReadGlobalAttributeAttributeList) +{ + UseMockNodeConfig config(gTestNodeConfig); + chip::app::CodegenDataModel model; + ScopedMockAccessControl accessControl; + + TestReadRequest testRequest(kAdminSubjectDescriptor, + ConcreteAttributePath(kMockEndpoint2, MockClusterId(3), AttributeList::Id)); + + // Data read via the encoder + std::unique_ptr encoder = testRequest.StartEncoding(&model); + ASSERT_EQ(model.ReadAttribute(testRequest.request, *encoder), CHIP_NO_ERROR); + ASSERT_EQ(testRequest.FinishEncoding(), CHIP_NO_ERROR); + + // Validate after read + std::vector attribute_data; + ASSERT_EQ(testRequest.encodedIBs.Decode(attribute_data), CHIP_NO_ERROR); + ASSERT_EQ(attribute_data.size(), 1u); + + DecodedAttributeData & encodedData = attribute_data[0]; + ASSERT_EQ(encodedData.attributePath, testRequest.request.path); + + ASSERT_EQ(encodedData.dataReader.GetType(), TLV::kTLVType_Array); + + std::vector items; + ASSERT_EQ(DecodeList(encodedData.dataReader, items), CHIP_NO_ERROR); + + // Mock data contains ClusterRevision and FeatureMap. + // After this, Global attributes are auto-added + std::vector expected; + + // Encoding in global-attribute-access-interface has a logic of: + // - Append global attributes in front of the first specified + // large number global attribute. + // Since ClusterRevision and FeatureMap are + // global attributes, the order here is reversed for them + for (AttributeId id : GlobalAttributesNotInMetadata) + { + expected.push_back(id); + } + expected.push_back(ClusterRevision::Id); + expected.push_back(FeatureMap::Id); + expected.push_back(MockAttributeId(1)); + expected.push_back(MockAttributeId(2)); + expected.push_back(MockAttributeId(3)); + + ASSERT_EQ(items.size(), expected.size()); + + // Since we have no std::vector formatter, comparing element by element is somewhat + // more readable in case of failure. + for (unsigned i = 0; i < items.size(); i++) + { + EXPECT_EQ(items[i], expected[i]); + } +} diff --git a/src/app/data-model-interface/DataModel.h b/src/app/data-model-interface/DataModel.h index 0ecfd6fb624532..04911fd75cccc3 100644 --- a/src/app/data-model-interface/DataModel.h +++ b/src/app/data-model-interface/DataModel.h @@ -55,22 +55,29 @@ class DataModel : public DataModelMetadataTree // event emitting, path marking and other operations virtual InteractionModelContext CurrentContext() const { return mContext; } - /// List reading has specific handling logic: - /// `state` contains in/out data about the current list reading. MUST start with kInvalidListIndex on first call + /// TEMPORARY/TRANSITIONAL requirement for transitioning from ember-specific code + /// ReadAttribute is REQUIRED to perform: + /// - ACL validation (see notes on OperationFlags::kInternal) + /// - Validation of readability/writability + /// - use request.path.mExpanded to skip encoding replies for data according + /// to 8.4.3.2 of the spec: + /// > If the path indicates attribute data that is not readable, then the path SHALL + /// be discarded. + /// > Else if reading from the attribute in the path requires a privilege that is not + /// granted to access the cluster in the path, then the path SHALL be discarded. /// /// Return codes: - /// CHIP_ERROR_MORE_LIST_DATA_AVAILABLE (NOTE: new error defined for this purpose) - /// - partial data written to the destination - /// - destination will contain AT LEAST one valid list entry fully serialized - /// - destination will be fully valid (it will be rolled back on partial list writes) + /// CHIP_ERROR_NO_MEMORY or CHIP_ERROR_BUFFER_TOO_SMALL: + /// - Indicates that list encoding had insufficient buffer space to encode elements. + /// - encoder::GetState().AllowPartialData() determines if these errors are permanent (no partial + /// data allowed) or further encoding can be retried (AllowPartialData true for list encoding) /// CHIP_IM_GLOBAL_STATUS(code): /// - error codes that are translatable in IM status codes (otherwise we expect Failure to be reported) - /// - In particular, some handlers rely on special handling for: - /// - `UnsupportedAccess` - for ACL checks (e.g. wildcard expansion may choose to skip these) /// - to check for this, CHIP_ERROR provides: /// - ::IsPart(ChipError::SdkPart::kIMGlobalStatus) -> bool /// - ::GetSdkCode() -> uint8_t to translate to the actual code - virtual CHIP_ERROR ReadAttribute(const ReadAttributeRequest & request, ReadState & state, AttributeValueEncoder & encoder) = 0; + /// other internal falures + virtual CHIP_ERROR ReadAttribute(const ReadAttributeRequest & request, AttributeValueEncoder & encoder) = 0; /// Requests a write of an attribute. /// diff --git a/src/app/data-model-interface/OperationTypes.h b/src/app/data-model-interface/OperationTypes.h index feb2e173d91600..d19621db71d26a 100644 --- a/src/app/data-model-interface/OperationTypes.h +++ b/src/app/data-model-interface/OperationTypes.h @@ -31,17 +31,29 @@ namespace InteractionModel { /// Contains common flags among all interaction model operations: read/write/invoke enum class OperationFlags : uint32_t { - kInternal = 0x0001, // Internal request for data changes (can bypass checks/ACL etc.) + // NOTE: temporary flag. This flag exists to faciliate transition from ember-compatibilty-functions + // implementation to DataModel Interface functionality. Specifically currently the + // model is expected to perform ACL and readability/writability checks. + // + // In the future, this flag will be removed and InteractionModelEngine/ReportingEngine + // will perform the required validation. + // + // Currently the flag FORCES a bypass of: + // - ACL validation (will allow any read/write) + // - Access validation (will allow reading write-only data for example) + kInternal = 0x0001, }; /// This information is available for ALL interactions: read/write/invoke struct OperationRequest { - OperationFlags operationFlags; + BitFlags operationFlags; /// Current authentication data EXCEPT for internal requests. /// - Non-internal requests MUST have this set. /// - operationFlags.Has(OperationFlags::kInternal) MUST NOT have this set + /// + /// NOTE: once kInternal flag is removed, this will become non-optional std::optional subjectDescriptor; }; @@ -57,13 +69,6 @@ struct ReadAttributeRequest : OperationRequest BitFlags readFlags; }; -struct ReadState -{ - // When reading lists, reading will start at this index. - // As list data is read, this index is incremented - ListIndex listEncodeStart = kInvalidListIndex; -}; - enum class WriteFlags : uint32_t { kTimed = 0x0001, // Write is a timed write (i.e. a Timed Request Action preceeded it) diff --git a/src/lib/core/CHIPError.h b/src/lib/core/CHIPError.h index aebf7804aefb10..b49088247e126c 100644 --- a/src/lib/core/CHIPError.h +++ b/src/lib/core/CHIPError.h @@ -439,6 +439,15 @@ using CHIP_ERROR = ::chip::ChipError; CHIP_SDK_ERROR(::chip::ChipError::SdkPart::kIMGlobalStatus, \ ::chip::to_underlying(::chip::Protocols::InteractionModel::Status::type)) +// Defines a runtime-value for a chip-error that contains a global IM Status. +#if CHIP_CONFIG_ERROR_SOURCE +#define CHIP_ERROR_IM_GLOBAL_STATUS_VALUE(status_value) \ + ::chip::ChipError(::chip::ChipError::SdkPart::kIMGlobalStatus, ::chip::to_underlying(status_value), __FILE__, __LINE__) +#else +#define CHIP_ERROR_IM_GLOBAL_STATUS_VALUE(status_value) \ + ::chip::ChipError(::chip::ChipError::SdkPart::kIMGlobalStatus, ::chip::to_underlying(status_value)) +#endif // CHIP_CONFIG_ERROR_SOURCE + // // type must be a compile-time constant as mandated by CHIP_SDK_ERROR. // From cde0b92deff87a438c7ee114b438188b6950dc77 Mon Sep 17 00:00:00 2001 From: mkardous-silabs <84793247+mkardous-silabs@users.noreply.github.com> Date: Sun, 30 Jun 2024 16:12:59 -0400 Subject: [PATCH 11/12] [ICD] Add ClientType support to the ICDManager and ICD Management cluster (#33811) * update icdm xml * generated files * Add clientType to the ICDMonitoring table * Add client type buisness logic to ICDM cluster * Add client type logic to the ICDManager * finish clean up * make ClientType arg mandatory * regen --------- Co-authored-by: yunhanw --- .../commands/clusters/ClusterCommand.h | 7 +- .../chip-tool/commands/icd/ICDCommand.cpp | 24 ++++--- .../commands/pairing/PairingCommand.cpp | 7 +- .../commands/pairing/PairingCommand.h | 3 + .../nxp/zap-lit/contact-sensor-app.matter | 7 ++ .../nxp/zap-sit/contact-sensor-app.matter | 7 ++ .../commands/pairing/PairingCommand.cpp | 7 +- .../commands/pairing/PairingCommand.h | 3 + .../light-switch-app.matter | 7 ++ .../light-switch-app/qpg/zap/switch.matter | 7 ++ .../lit-icd-common/lit-icd-server-app.matter | 7 ++ examples/lock-app/lock-common/lock-app.matter | 7 ++ examples/lock-app/qpg/zap/lock.matter | 7 ++ .../smoke-co-alarm-app.matter | 7 ++ examples/window-app/common/window-app.matter | 7 ++ .../icd-management-server.cpp | 7 ++ .../icd-management-server.h | 2 - .../icd/client/DefaultICDClientStorage.cpp | 5 ++ src/app/icd/client/DefaultICDClientStorage.h | 9 +-- src/app/icd/client/ICDClientInfo.h | 13 ++-- src/app/icd/server/BUILD.gn | 1 + src/app/icd/server/ICDCheckInSender.h | 2 +- src/app/icd/server/ICDManager.cpp | 14 ++++ src/app/icd/server/ICDManager.h | 1 - src/app/icd/server/ICDMonitoringTable.cpp | 9 +++ src/app/icd/server/ICDMonitoringTable.h | 18 ++--- src/app/icd/server/tests/TestICDManager.cpp | 2 + .../server/tests/TestICDMonitoringTable.cpp | 10 +++ .../suites/TestIcdManagementCluster.yaml | 67 +++++++++++++++++-- .../certification/Test_TC_ICDM_3_4.yaml | 3 + .../chip/icd-management-cluster.xml | 14 +++- src/controller/AutoCommissioner.cpp | 6 ++ src/controller/CommissioningDelegate.h | 8 +++ .../data_model/controller-clusters.matter | 7 ++ .../java/AndroidDeviceControllerWrapper.cpp | 14 ++++ .../chip/devicecontroller/ChipClusters.java | 10 ++- .../chip/devicecontroller/ChipStructs.java | 15 +++++ .../devicecontroller/ClusterIDMapping.java | 2 +- .../devicecontroller/ClusterInfoMapping.java | 6 ++ ...mentClusterMonitoringRegistrationStruct.kt | 6 ++ .../cluster/clusters/IcdManagementCluster.kt | 4 ++ ...mentClusterMonitoringRegistrationStruct.kt | 6 ++ .../devicecontroller/ICDRegistrationInfo.java | 12 ++++ .../CHIPAttributeTLVValueDecoder.cpp | 17 +++-- ...Controller-ScriptDevicePairingDelegate.cpp | 1 + .../python/chip/clusters/CHIPClusters.py | 1 + .../python/chip/clusters/Objects.py | 13 ++++ .../MTRAttributeTLVValueDecoder.mm | 1 + .../CHIP/zap-generated/MTRBaseClusters.h | 5 ++ .../zap-generated/MTRCommandPayloadsObjc.h | 2 + .../zap-generated/MTRCommandPayloadsObjc.mm | 8 ++- .../CHIP/zap-generated/MTRStructsObjc.h | 1 + .../CHIP/zap-generated/MTRStructsObjc.mm | 5 +- src/lib/support/JniReferences.cpp | 13 ++++ src/lib/support/JniReferences.h | 5 ++ src/python_testing/TC_ICDM_3_1.py | 14 ++-- .../zap-generated/cluster-enums-check.h | 12 ++++ .../app-common/zap-generated/cluster-enums.h | 12 ++++ .../zap-generated/cluster-objects.cpp | 13 ++++ .../zap-generated/cluster-objects.h | 5 ++ .../zap-generated/cluster/Commands.h | 1 + .../cluster/ComplexArgumentParser.cpp | 7 ++ .../cluster/logging/DataModelLogger.cpp | 8 +++ .../zap-generated/cluster/Commands.h | 6 ++ 64 files changed, 478 insertions(+), 59 deletions(-) diff --git a/examples/chip-tool/commands/clusters/ClusterCommand.h b/examples/chip-tool/commands/clusters/ClusterCommand.h index ac141fb012e259..bf5c61fd02bd3f 100644 --- a/examples/chip-tool/commands/clusters/ClusterCommand.h +++ b/examples/chip-tool/commands/clusters/ClusterCommand.h @@ -21,6 +21,7 @@ #include "DataModelLogger.h" #include "ModelCommand.h" #include +#include class ClusterCommand : public InteractionModelCommands, public ModelCommand, public chip::app::CommandSender::Callback { @@ -70,6 +71,7 @@ class ClusterCommand : public InteractionModelCommands, public ModelCommand, pub ReturnErrorOnFailure(InteractionModelCommands::SendCommand(device, endpointId, clusterId, commandId, value)); mScopedNodeId = chip::ScopedNodeId(value.checkInNodeID, device->GetSecureSession().Value()->GetFabricIndex()); mMonitoredSubject = value.monitoredSubject; + mClientType = value.clientType; memcpy(mICDSymmetricKey, value.key.data(), value.key.size()); return CHIP_NO_ERROR; } @@ -148,6 +150,7 @@ class ClusterCommand : public InteractionModelCommands, public ModelCommand, pub clientInfo.peer_node = mScopedNodeId; clientInfo.monitored_subject = mMonitoredSubject; clientInfo.start_icd_counter = value.ICDCounter; + clientInfo.client_type = mClientType; StoreICDEntryWithKey(clientInfo, chip::ByteSpan(mICDSymmetricKey)); } @@ -258,8 +261,10 @@ class ClusterCommand : public InteractionModelCommands, public ModelCommand, pub chip::ClusterId mClusterId; chip::CommandId mCommandId; chip::ScopedNodeId mScopedNodeId; - uint64_t mMonitoredSubject = static_cast(0); + uint64_t mMonitoredSubject = static_cast(0); + chip::app::Clusters::IcdManagement::ClientTypeEnum mClientType = chip::app::Clusters::IcdManagement::ClientTypeEnum::kPermanent; uint8_t mICDSymmetricKey[chip::Crypto::kAES_CCM128_Key_Length]; + CHIP_ERROR mError = CHIP_NO_ERROR; CustomArgument mPayload; }; diff --git a/examples/chip-tool/commands/icd/ICDCommand.cpp b/examples/chip-tool/commands/icd/ICDCommand.cpp index 505e6adfbfea3d..3f7bfb328d5273 100644 --- a/examples/chip-tool/commands/icd/ICDCommand.cpp +++ b/examples/chip-tool/commands/icd/ICDCommand.cpp @@ -21,6 +21,7 @@ #include #include #include +#include using namespace ::chip; using namespace ::chip::app; @@ -36,31 +37,32 @@ CHIP_ERROR ICDListCommand::RunCommand() return CHIP_ERROR_NO_MEMORY; } app::DefaultICDClientStorage::ICDClientInfoIteratorWrapper clientInfoIteratorWrapper(iter); - fprintf(stderr, " +-----------------------------------------------------------------------------+\n"); - fprintf(stderr, " | %-75s |\n", "Known ICDs:"); - fprintf(stderr, " +-----------------------------------------------------------------------------+\n"); - fprintf(stderr, " | %20s | %15s | %15s | %16s |\n", "Fabric Index:Node ID", "Start Counter", "Counter Offset", - "MonitoredSubject"); + fprintf(stderr, " +------------------------------------------------------------------------------------------+\n"); + fprintf(stderr, " | %-88s |\n", "Known ICDs:"); + fprintf(stderr, " +------------------------------------------------------------------------------------------+\n"); + fprintf(stderr, " | %20s | %15s | %15s | %16s | %10s |\n", "Fabric Index:Node ID", "Start Counter", "Counter Offset", + "MonitoredSubject", "ClientType"); while (iter->Next(info)) { - fprintf(stderr, " +-----------------------------------------------------------------------------+\n"); - fprintf(stderr, " | %3" PRIu32 ":" ChipLogFormatX64 " | %15" PRIu32 " | %15" PRIu32 " | " ChipLogFormatX64 " |\n", + fprintf(stderr, " +------------------------------------------------------------------------------------------+\n"); + fprintf(stderr, " | %3" PRIu32 ":" ChipLogFormatX64 " | %15" PRIu32 " | %15" PRIu32 " | " ChipLogFormatX64 " | %10u |\n", static_cast(info.peer_node.GetFabricIndex()), ChipLogValueX64(info.peer_node.GetNodeId()), - info.start_icd_counter, info.offset, ChipLogValueX64(info.monitored_subject)); + info.start_icd_counter, info.offset, ChipLogValueX64(info.monitored_subject), + static_cast(info.client_type)); static_assert(std::is_same::value, "The following BytesToHex can copy/encode the key bytes from sharedKey to hexadecimal format, which only " "works for RawKeySessionKeystore"); Encoding::BytesToHex(info.aes_key_handle.As(), Crypto::kAES_CCM128_Key_Length, icdAesKeyHex, sizeof(icdAesKeyHex), chip::Encoding::HexFlags::kNullTerminate); - fprintf(stderr, " | aes key: %60s |\n", icdAesKeyHex); + fprintf(stderr, " | aes key: %60s |\n", icdAesKeyHex); Encoding::BytesToHex(info.hmac_key_handle.As(), Crypto::kHMAC_CCM128_Key_Length, icdHmacKeyHex, sizeof(icdHmacKeyHex), chip::Encoding::HexFlags::kNullTerminate); - fprintf(stderr, " | hmac key: %60s |\n", icdHmacKeyHex); + fprintf(stderr, " | hmac key: %60s |\n", icdHmacKeyHex); } - fprintf(stderr, " +-----------------------------------------------------------------------------+\n"); + fprintf(stderr, " +------------------------------------------------------------------------------------------+\n"); SetCommandExitStatus(CHIP_NO_ERROR); return CHIP_NO_ERROR; } diff --git a/examples/chip-tool/commands/pairing/PairingCommand.cpp b/examples/chip-tool/commands/pairing/PairingCommand.cpp index 7bddfa3d08039c..35ce2ba1cc7aaa 100644 --- a/examples/chip-tool/commands/pairing/PairingCommand.cpp +++ b/examples/chip-tool/commands/pairing/PairingCommand.cpp @@ -157,6 +157,10 @@ CommissioningParameters PairingCommand::GetCommissioningParameters() { mICDMonitoredSubject.SetValue(mICDCheckInNodeId.Value()); } + if (!mICDClientType.HasValue()) + { + mICDClientType.SetValue(app::Clusters::IcdManagement::ClientTypeEnum::kPermanent); + } // These Optionals must have values now. // The commissioner will verify these values. params.SetICDSymmetricKey(mICDSymmetricKey.Value()); @@ -166,6 +170,7 @@ CommissioningParameters PairingCommand::GetCommissioningParameters() } params.SetICDCheckInNodeId(mICDCheckInNodeId.Value()); params.SetICDMonitoredSubject(mICDMonitoredSubject.Value()); + params.SetICDClientType(mICDClientType.Value()); } return params; @@ -459,7 +464,7 @@ void PairingCommand::OnICDRegistrationComplete(ScopedNodeId nodeId, uint32_t icd sizeof(icdSymmetricKeyHex), chip::Encoding::HexFlags::kNullTerminate); app::ICDClientInfo clientInfo; - clientInfo.peer_node = nodeId; + clientInfo.peer_node = chip::ScopedNodeId(mICDCheckInNodeId.Value(), nodeId.GetFabricIndex()); clientInfo.monitored_subject = mICDMonitoredSubject.Value(); clientInfo.start_icd_counter = icdCounter; diff --git a/examples/chip-tool/commands/pairing/PairingCommand.h b/examples/chip-tool/commands/pairing/PairingCommand.h index facb0f2403536b..0cf4e1de2de713 100644 --- a/examples/chip-tool/commands/pairing/PairingCommand.h +++ b/examples/chip-tool/commands/pairing/PairingCommand.h @@ -74,6 +74,8 @@ class PairingCommand : public CHIPCommand, "The check-in node id for the ICD, default: node id of the commissioner."); AddArgument("icd-monitored-subject", 0, UINT64_MAX, &mICDMonitoredSubject, "The monitored subject of the ICD, default: The node id used for icd-check-in-nodeid."); + AddArgument("icd-client-type", 0, 1, &mICDClientType, + "The ClientType of the client registering, default: Permanent client - 0"); AddArgument("icd-symmetric-key", &mICDSymmetricKey, "The 16 bytes ICD symmetric key, default: randomly generated."); AddArgument("icd-stay-active-duration", 0, UINT32_MAX, &mICDStayActiveDurationMsec, "If set, a LIT ICD that is commissioned will be requested to stay active for this many milliseconds"); @@ -245,6 +247,7 @@ class PairingCommand : public CHIPCommand, chip::Optional mICDCheckInNodeId; chip::Optional mICDSymmetricKey; chip::Optional mICDMonitoredSubject; + chip::Optional mICDClientType; chip::Optional mICDStayActiveDurationMsec; chip::app::DataModel::List mTimeZoneList; TypedComplexArgument> 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 d64a06cf2c7b6e..9bffee1c83dce2 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 @@ -1315,6 +1315,11 @@ cluster BooleanState = 69 { cluster IcdManagement = 70 { revision 2; + enum ClientTypeEnum : enum8 { + kPermanent = 0; + kEphemeral = 1; + } + enum OperatingModeEnum : enum8 { kSIT = 0; kLIT = 1; @@ -1349,6 +1354,7 @@ cluster IcdManagement = 70 { fabric_scoped struct MonitoringRegistrationStruct { fabric_sensitive node_id checkInNodeID = 1; fabric_sensitive int64u monitoredSubject = 2; + fabric_sensitive ClientTypeEnum clientType = 4; fabric_idx fabricIndex = 254; } @@ -1373,6 +1379,7 @@ cluster IcdManagement = 70 { int64u monitoredSubject = 1; octet_string<16> key = 2; optional octet_string<16> verificationKey = 3; + ClientTypeEnum clientType = 4; } response struct RegisterClientResponse = 1 { 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 d0861d55518c69..70cae9e994c4fd 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 @@ -1315,6 +1315,11 @@ cluster BooleanState = 69 { cluster IcdManagement = 70 { revision 2; + enum ClientTypeEnum : enum8 { + kPermanent = 0; + kEphemeral = 1; + } + enum OperatingModeEnum : enum8 { kSIT = 0; kLIT = 1; @@ -1349,6 +1354,7 @@ cluster IcdManagement = 70 { fabric_scoped struct MonitoringRegistrationStruct { fabric_sensitive node_id checkInNodeID = 1; fabric_sensitive int64u monitoredSubject = 2; + fabric_sensitive ClientTypeEnum clientType = 4; fabric_idx fabricIndex = 254; } @@ -1373,6 +1379,7 @@ cluster IcdManagement = 70 { int64u monitoredSubject = 1; octet_string<16> key = 2; optional octet_string<16> verificationKey = 3; + ClientTypeEnum clientType = 4; } response struct RegisterClientResponse = 1 { diff --git a/examples/fabric-admin/commands/pairing/PairingCommand.cpp b/examples/fabric-admin/commands/pairing/PairingCommand.cpp index 8a261b01a8865b..521325a796dce0 100644 --- a/examples/fabric-admin/commands/pairing/PairingCommand.cpp +++ b/examples/fabric-admin/commands/pairing/PairingCommand.cpp @@ -157,6 +157,10 @@ CommissioningParameters PairingCommand::GetCommissioningParameters() { mICDMonitoredSubject.SetValue(mICDCheckInNodeId.Value()); } + if (!mICDClientType.HasValue()) + { + mICDClientType.SetValue(app::Clusters::IcdManagement::ClientTypeEnum::kPermanent); + } // These Optionals must have values now. // The commissioner will verify these values. params.SetICDSymmetricKey(mICDSymmetricKey.Value()); @@ -166,6 +170,7 @@ CommissioningParameters PairingCommand::GetCommissioningParameters() } params.SetICDCheckInNodeId(mICDCheckInNodeId.Value()); params.SetICDMonitoredSubject(mICDMonitoredSubject.Value()); + params.SetICDClientType(mICDClientType.Value()); } return params; @@ -459,7 +464,7 @@ void PairingCommand::OnICDRegistrationComplete(ScopedNodeId nodeId, uint32_t icd sizeof(icdSymmetricKeyHex), chip::Encoding::HexFlags::kNullTerminate); app::ICDClientInfo clientInfo; - clientInfo.peer_node = nodeId; + clientInfo.peer_node = chip::ScopedNodeId(mICDCheckInNodeId.Value(), nodeId.GetFabricIndex()); clientInfo.monitored_subject = mICDMonitoredSubject.Value(); clientInfo.start_icd_counter = icdCounter; diff --git a/examples/fabric-admin/commands/pairing/PairingCommand.h b/examples/fabric-admin/commands/pairing/PairingCommand.h index fbd33440f5bb14..647f2c37fc78b2 100644 --- a/examples/fabric-admin/commands/pairing/PairingCommand.h +++ b/examples/fabric-admin/commands/pairing/PairingCommand.h @@ -84,6 +84,8 @@ class PairingCommand : public CHIPCommand, "The check-in node id for the ICD, default: node id of the commissioner."); AddArgument("icd-monitored-subject", 0, UINT64_MAX, &mICDMonitoredSubject, "The monitored subject of the ICD, default: The node id used for icd-check-in-nodeid."); + AddArgument("icd-client-type", 0, 1, &mICDClientType, + "The ClientType of the client registering, default: Permanent client - 0"); AddArgument("icd-symmetric-key", &mICDSymmetricKey, "The 16 bytes ICD symmetric key, default: randomly generated."); AddArgument("icd-stay-active-duration", 0, UINT32_MAX, &mICDStayActiveDurationMsec, "If set, a LIT ICD that is commissioned will be requested to stay active for this many milliseconds"); @@ -258,6 +260,7 @@ class PairingCommand : public CHIPCommand, chip::Optional mCountryCode; chip::Optional mICDRegistration; chip::Optional mICDCheckInNodeId; + chip::Optional mICDClientType; chip::Optional mICDSymmetricKey; chip::Optional mICDMonitoredSubject; chip::Optional mICDStayActiveDurationMsec; 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 c4f73e4b338685..1380e672e747b2 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 @@ -1939,6 +1939,11 @@ cluster UserLabel = 65 { cluster IcdManagement = 70 { revision 2; + enum ClientTypeEnum : enum8 { + kPermanent = 0; + kEphemeral = 1; + } + enum OperatingModeEnum : enum8 { kSIT = 0; kLIT = 1; @@ -1973,6 +1978,7 @@ cluster IcdManagement = 70 { fabric_scoped struct MonitoringRegistrationStruct { fabric_sensitive node_id checkInNodeID = 1; fabric_sensitive int64u monitoredSubject = 2; + fabric_sensitive ClientTypeEnum clientType = 4; fabric_idx fabricIndex = 254; } @@ -1997,6 +2003,7 @@ cluster IcdManagement = 70 { int64u monitoredSubject = 1; octet_string<16> key = 2; optional octet_string<16> verificationKey = 3; + ClientTypeEnum clientType = 4; } response struct RegisterClientResponse = 1 { diff --git a/examples/light-switch-app/qpg/zap/switch.matter b/examples/light-switch-app/qpg/zap/switch.matter index d105fdea187f0a..f42b1f07744809 100644 --- a/examples/light-switch-app/qpg/zap/switch.matter +++ b/examples/light-switch-app/qpg/zap/switch.matter @@ -1736,6 +1736,11 @@ cluster UserLabel = 65 { cluster IcdManagement = 70 { revision 2; + enum ClientTypeEnum : enum8 { + kPermanent = 0; + kEphemeral = 1; + } + enum OperatingModeEnum : enum8 { kSIT = 0; kLIT = 1; @@ -1770,6 +1775,7 @@ cluster IcdManagement = 70 { fabric_scoped struct MonitoringRegistrationStruct { fabric_sensitive node_id checkInNodeID = 1; fabric_sensitive int64u monitoredSubject = 2; + fabric_sensitive ClientTypeEnum clientType = 4; fabric_idx fabricIndex = 254; } @@ -1794,6 +1800,7 @@ cluster IcdManagement = 70 { int64u monitoredSubject = 1; octet_string<16> key = 2; optional octet_string<16> verificationKey = 3; + ClientTypeEnum clientType = 4; } response struct RegisterClientResponse = 1 { 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 9d260248736c0c..79f26232c3a727 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 @@ -1413,6 +1413,11 @@ cluster BooleanState = 69 { cluster IcdManagement = 70 { revision 2; + enum ClientTypeEnum : enum8 { + kPermanent = 0; + kEphemeral = 1; + } + enum OperatingModeEnum : enum8 { kSIT = 0; kLIT = 1; @@ -1447,6 +1452,7 @@ cluster IcdManagement = 70 { fabric_scoped struct MonitoringRegistrationStruct { fabric_sensitive node_id checkInNodeID = 1; fabric_sensitive int64u monitoredSubject = 2; + fabric_sensitive ClientTypeEnum clientType = 4; fabric_idx fabricIndex = 254; } @@ -1471,6 +1477,7 @@ cluster IcdManagement = 70 { int64u monitoredSubject = 1; octet_string<16> key = 2; optional octet_string<16> verificationKey = 3; + ClientTypeEnum clientType = 4; } response struct RegisterClientResponse = 1 { diff --git a/examples/lock-app/lock-common/lock-app.matter b/examples/lock-app/lock-common/lock-app.matter index 5c21291397494c..a484b095516dc6 100644 --- a/examples/lock-app/lock-common/lock-app.matter +++ b/examples/lock-app/lock-common/lock-app.matter @@ -1756,6 +1756,11 @@ cluster UserLabel = 65 { cluster IcdManagement = 70 { revision 2; + enum ClientTypeEnum : enum8 { + kPermanent = 0; + kEphemeral = 1; + } + enum OperatingModeEnum : enum8 { kSIT = 0; kLIT = 1; @@ -1790,6 +1795,7 @@ cluster IcdManagement = 70 { fabric_scoped struct MonitoringRegistrationStruct { fabric_sensitive node_id checkInNodeID = 1; fabric_sensitive int64u monitoredSubject = 2; + fabric_sensitive ClientTypeEnum clientType = 4; fabric_idx fabricIndex = 254; } @@ -1814,6 +1820,7 @@ cluster IcdManagement = 70 { int64u monitoredSubject = 1; octet_string<16> key = 2; optional octet_string<16> verificationKey = 3; + ClientTypeEnum clientType = 4; } response struct RegisterClientResponse = 1 { diff --git a/examples/lock-app/qpg/zap/lock.matter b/examples/lock-app/qpg/zap/lock.matter index 589eb097561c77..a8628316139252 100644 --- a/examples/lock-app/qpg/zap/lock.matter +++ b/examples/lock-app/qpg/zap/lock.matter @@ -1412,6 +1412,11 @@ cluster UserLabel = 65 { cluster IcdManagement = 70 { revision 2; + enum ClientTypeEnum : enum8 { + kPermanent = 0; + kEphemeral = 1; + } + enum OperatingModeEnum : enum8 { kSIT = 0; kLIT = 1; @@ -1446,6 +1451,7 @@ cluster IcdManagement = 70 { fabric_scoped struct MonitoringRegistrationStruct { fabric_sensitive node_id checkInNodeID = 1; fabric_sensitive int64u monitoredSubject = 2; + fabric_sensitive ClientTypeEnum clientType = 4; fabric_idx fabricIndex = 254; } @@ -1470,6 +1476,7 @@ cluster IcdManagement = 70 { int64u monitoredSubject = 1; octet_string<16> key = 2; optional octet_string<16> verificationKey = 3; + ClientTypeEnum clientType = 4; } response struct RegisterClientResponse = 1 { 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 ea86a446d156eb..9ed425b817255d 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 @@ -1732,6 +1732,11 @@ cluster UserLabel = 65 { cluster IcdManagement = 70 { revision 2; + enum ClientTypeEnum : enum8 { + kPermanent = 0; + kEphemeral = 1; + } + enum OperatingModeEnum : enum8 { kSIT = 0; kLIT = 1; @@ -1766,6 +1771,7 @@ cluster IcdManagement = 70 { fabric_scoped struct MonitoringRegistrationStruct { fabric_sensitive node_id checkInNodeID = 1; fabric_sensitive int64u monitoredSubject = 2; + fabric_sensitive ClientTypeEnum clientType = 4; fabric_idx fabricIndex = 254; } @@ -1790,6 +1796,7 @@ cluster IcdManagement = 70 { int64u monitoredSubject = 1; octet_string<16> key = 2; optional octet_string<16> verificationKey = 3; + ClientTypeEnum clientType = 4; } response struct RegisterClientResponse = 1 { diff --git a/examples/window-app/common/window-app.matter b/examples/window-app/common/window-app.matter index 1a5a56ca4e3aba..f39cb7187446bc 100644 --- a/examples/window-app/common/window-app.matter +++ b/examples/window-app/common/window-app.matter @@ -1830,6 +1830,11 @@ cluster UserLabel = 65 { cluster IcdManagement = 70 { revision 2; + enum ClientTypeEnum : enum8 { + kPermanent = 0; + kEphemeral = 1; + } + enum OperatingModeEnum : enum8 { kSIT = 0; kLIT = 1; @@ -1864,6 +1869,7 @@ cluster IcdManagement = 70 { fabric_scoped struct MonitoringRegistrationStruct { fabric_sensitive node_id checkInNodeID = 1; fabric_sensitive int64u monitoredSubject = 2; + fabric_sensitive ClientTypeEnum clientType = 4; fabric_idx fabricIndex = 254; } @@ -1888,6 +1894,7 @@ cluster IcdManagement = 70 { int64u monitoredSubject = 1; octet_string<16> key = 2; optional octet_string<16> verificationKey = 3; + ClientTypeEnum clientType = 4; } response struct RegisterClientResponse = 1 { 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 f6ab59d9f2efb0..e4ead150a1fd79 100644 --- a/src/app/clusters/icd-management-server/icd-management-server.cpp +++ b/src/app/clusters/icd-management-server/icd-management-server.cpp @@ -202,6 +202,7 @@ CHIP_ERROR IcdManagementAttributeAccess::ReadRegisteredClients(EndpointId endpoi Structs::MonitoringRegistrationStruct::Type s{ .checkInNodeID = e.checkInNodeID, .monitoredSubject = e.monitoredSubject, + .clientType = e.clientType, .fabricIndex = e.fabricIndex }; ReturnErrorOnFailure(subEncoder.Encode(s)); } @@ -252,10 +253,14 @@ Status ICDManagementServer::RegisterClient(CommandHandler * commandObj, const Co FabricIndex fabricIndex = commandObj->GetAccessingFabricIndex(); NodeId nodeId = commandData.checkInNodeID; uint64_t monitoredSubject = commandData.monitoredSubject; + ClientTypeEnum clientType = commandData.clientType; ByteSpan key = commandData.key; Optional verificationKey = commandData.verificationKey; bool isClientAdmin = false; + // Check if ClientType is valid + VerifyOrReturnError(clientType != ClientTypeEnum::kUnknownEnumValue, InteractionModel::Status::ConstraintError); + // Check if client is admin VerifyOrReturnError(CHIP_NO_ERROR == CheckAdmin(commandObj, commandPath, isClientAdmin), InteractionModel::Status::Failure); @@ -291,6 +296,8 @@ Status ICDManagementServer::RegisterClient(CommandHandler * commandObj, const Co // Save entry.checkInNodeID = nodeId; entry.monitoredSubject = monitoredSubject; + entry.clientType = clientType; + if (entry.keyHandleValid) { entry.DeleteKey(); 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 5c6b838fa9b527..38fc1b7ee6d7d0 100644 --- a/src/app/clusters/icd-management-server/icd-management-server.h +++ b/src/app/clusters/icd-management-server/icd-management-server.h @@ -34,8 +34,6 @@ #include #endif // CHIP_CONFIG_ENABLE_ICD_CIP -using chip::Protocols::InteractionModel::Status; - namespace chip { namespace Crypto { using SymmetricKeystore = SessionKeystore; diff --git a/src/app/icd/client/DefaultICDClientStorage.cpp b/src/app/icd/client/DefaultICDClientStorage.cpp index 73e7b5f5c1fdf9..7582e8fd580c40 100644 --- a/src/app/icd/client/DefaultICDClientStorage.cpp +++ b/src/app/icd/client/DefaultICDClientStorage.cpp @@ -274,6 +274,10 @@ CHIP_ERROR DefaultICDClientStorage::Load(FabricIndex fabricIndex, std::vector(), hmacBuf.data(), sizeof(Crypto::Symmetric128BitsKeyByteArray)); + // ClientType + ReturnErrorOnFailure(reader.Next(TLV::ContextTag(ClientInfoTag::kClientType))); + ReturnErrorOnFailure(reader.Get(clientInfo.client_type)); + ReturnErrorOnFailure(reader.ExitContainer(ICDClientInfoType)); clientInfoVector.push_back(clientInfo); } @@ -327,6 +331,7 @@ CHIP_ERROR DefaultICDClientStorage::SerializeToTlv(TLV::TLVWriter & writer, cons ReturnErrorOnFailure(writer.Put(TLV::ContextTag(ClientInfoTag::kAesKeyHandle), aesBuf)); ByteSpan hmacBuf(clientInfo.hmac_key_handle.As()); ReturnErrorOnFailure(writer.Put(TLV::ContextTag(ClientInfoTag::kHmacKeyHandle), hmacBuf)); + ReturnErrorOnFailure(writer.Put(TLV::ContextTag(ClientInfoTag::kClientType), clientInfo.client_type)); ReturnErrorOnFailure(writer.EndContainer(ICDClientInfoContainerType)); } return writer.EndContainer(arrayType); diff --git a/src/app/icd/client/DefaultICDClientStorage.h b/src/app/icd/client/DefaultICDClientStorage.h index c2a95fd2a1064b..c3c4560e1d04ce 100644 --- a/src/app/icd/client/DefaultICDClientStorage.h +++ b/src/app/icd/client/DefaultICDClientStorage.h @@ -130,6 +130,7 @@ class DefaultICDClientStorage : public ICDClientStorage kMonitoredSubject = 5, kAesKeyHandle = 6, kHmacKeyHandle = 7, + kClientType = 8, }; enum class CounterTag : uint8_t @@ -156,10 +157,10 @@ class DefaultICDClientStorage : public ICDClientStorage static constexpr size_t MaxICDClientInfoSize() { // All the fields added together - return TLV::EstimateStructOverhead(sizeof(NodeId), sizeof(FabricIndex), sizeof(uint32_t) /*start_icd_counter*/, - sizeof(uint32_t) /*offset*/, sizeof(uint64_t) /*monitored_subject*/, - sizeof(Crypto::Symmetric128BitsKeyByteArray) /*aes_key_handle*/, - sizeof(Crypto::Symmetric128BitsKeyByteArray) /*hmac_key_handle*/); + return TLV::EstimateStructOverhead( + sizeof(NodeId), sizeof(FabricIndex), sizeof(uint32_t) /*start_icd_counter*/, sizeof(uint32_t) /*offset*/, + sizeof(uint64_t) /*monitored_subject*/, sizeof(Crypto::Symmetric128BitsKeyByteArray) /*aes_key_handle*/, + sizeof(Crypto::Symmetric128BitsKeyByteArray) /*hmac_key_handle*/, sizeof(uint8_t) /*client_type*/); } static constexpr size_t MaxICDCounterSize() diff --git a/src/app/icd/client/ICDClientInfo.h b/src/app/icd/client/ICDClientInfo.h index 5a20b1990744bd..45aabf2f977866 100644 --- a/src/app/icd/client/ICDClientInfo.h +++ b/src/app/icd/client/ICDClientInfo.h @@ -19,6 +19,7 @@ #include #include +#include #include #include #include @@ -30,11 +31,12 @@ namespace app { struct ICDClientInfo { ScopedNodeId peer_node; - uint32_t start_icd_counter = 0; - uint32_t offset = 0; - uint64_t monitored_subject = static_cast(0); - Crypto::Aes128KeyHandle aes_key_handle = Crypto::Aes128KeyHandle(); - Crypto::Hmac128KeyHandle hmac_key_handle = Crypto::Hmac128KeyHandle(); + uint32_t start_icd_counter = 0; + uint32_t offset = 0; + Clusters::IcdManagement::ClientTypeEnum client_type = Clusters::IcdManagement::ClientTypeEnum::kPermanent; + uint64_t monitored_subject = static_cast(0); + Crypto::Aes128KeyHandle aes_key_handle = Crypto::Aes128KeyHandle(); + Crypto::Hmac128KeyHandle hmac_key_handle = Crypto::Hmac128KeyHandle(); ICDClientInfo() {} ICDClientInfo(const ICDClientInfo & other) { *this = other; } @@ -44,6 +46,7 @@ struct ICDClientInfo peer_node = other.peer_node; start_icd_counter = other.start_icd_counter; offset = other.offset; + client_type = other.client_type; monitored_subject = other.monitored_subject; ByteSpan aes_buf(other.aes_key_handle.As()); memcpy(aes_key_handle.AsMutable(), aes_buf.data(), diff --git a/src/app/icd/server/BUILD.gn b/src/app/icd/server/BUILD.gn index c100cc7d041e84..89c39c203a7c16 100644 --- a/src/app/icd/server/BUILD.gn +++ b/src/app/icd/server/BUILD.gn @@ -83,6 +83,7 @@ source_set("manager") { "${chip_root}/src/app:subscription-info-provider", "${chip_root}/src/app:test-event-trigger", "${chip_root}/src/credentials:credentials", + "${chip_root}/src/lib/address_resolve:address_resolve", "${chip_root}/src/messaging", ] diff --git a/src/app/icd/server/ICDCheckInSender.h b/src/app/icd/server/ICDCheckInSender.h index b681bec149f667..ea562666acfc4d 100644 --- a/src/app/icd/server/ICDCheckInSender.h +++ b/src/app/icd/server/ICDCheckInSender.h @@ -32,7 +32,7 @@ class ICDCheckInSender : public AddressResolve::NodeListener { public: ICDCheckInSender(Messaging::ExchangeManager * exchangeManager); - ~ICDCheckInSender(){}; + ~ICDCheckInSender() = default; CHIP_ERROR RequestResolve(ICDMonitoringEntry & entry, FabricTable * fabricTable, uint32_t counter); diff --git a/src/app/icd/server/ICDManager.cpp b/src/app/icd/server/ICDManager.cpp index 2b4ccb2be8af4e..ee55b0b0f9b23b 100644 --- a/src/app/icd/server/ICDManager.cpp +++ b/src/app/icd/server/ICDManager.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -187,6 +188,13 @@ void ICDManager::SendCheckInMsgs() continue; } + if (entry.clientType == ClientTypeEnum::kEphemeral) + { + // If the registered client is ephemeral, do not send a Check-In message + // continue to next entry + continue; + } + if (!ShouldCheckInMsgsBeSentAtActiveModeFunction(entry.fabricIndex, entry.monitoredSubject)) { continue; @@ -248,6 +256,12 @@ bool ICDManager::CheckInMessagesWouldBeSent(const std::function -#include #include #include #include diff --git a/src/app/icd/server/ICDMonitoringTable.cpp b/src/app/icd/server/ICDMonitoringTable.cpp index 57e6fa265821f1..8148a7fe33b237 100644 --- a/src/app/icd/server/ICDMonitoringTable.cpp +++ b/src/app/icd/server/ICDMonitoringTable.cpp @@ -27,6 +27,7 @@ enum class Fields : uint8_t kMonitoredSubject = 2, kAesKeyHandle = 3, kHmacKeyHandle = 4, + kClientType = 5, }; CHIP_ERROR ICDMonitoringEntry::UpdateKey(StorageKeyName & skey) @@ -49,6 +50,8 @@ CHIP_ERROR ICDMonitoringEntry::Serialize(TLV::TLVWriter & writer) const ByteSpan hmacKeybuf(hmacKeyHandle.As()); ReturnErrorOnFailure(writer.Put(TLV::ContextTag(Fields::kHmacKeyHandle), hmacKeybuf)); + ReturnErrorOnFailure(writer.Put(TLV::ContextTag(Fields::kClientType), clientType)); + ReturnErrorOnFailure(writer.EndContainer(outer)); return CHIP_NO_ERROR; } @@ -106,6 +109,9 @@ CHIP_ERROR ICDMonitoringEntry::Deserialize(TLV::TLVReader & reader) sizeof(Crypto::Symmetric128BitsKeyByteArray)); } break; + case to_underlying(Fields::kClientType): + ReturnErrorOnFailure(reader.Get(clientType)); + break; default: break; } @@ -122,6 +128,7 @@ void ICDMonitoringEntry::Clear() this->checkInNodeID = kUndefinedNodeId; this->monitoredSubject = kUndefinedNodeId; this->keyHandleValid = false; + this->clientType = app::Clusters::IcdManagement::ClientTypeEnum::kPermanent; } CHIP_ERROR ICDMonitoringEntry::SetKey(ByteSpan keyData) @@ -210,6 +217,7 @@ ICDMonitoringEntry & ICDMonitoringEntry::operator=(const ICDMonitoringEntry & ic fabricIndex = icdMonitoringEntry.fabricIndex; checkInNodeID = icdMonitoringEntry.checkInNodeID; monitoredSubject = icdMonitoringEntry.monitoredSubject; + clientType = icdMonitoringEntry.clientType; index = icdMonitoringEntry.index; keyHandleValid = icdMonitoringEntry.keyHandleValid; symmetricKeystore = icdMonitoringEntry.symmetricKeystore; @@ -257,6 +265,7 @@ CHIP_ERROR ICDMonitoringTable::Set(uint16_t index, const ICDMonitoringEntry & en ICDMonitoringEntry e(this->mFabric, index); e.checkInNodeID = entry.checkInNodeID; e.monitoredSubject = entry.monitoredSubject; + e.clientType = entry.clientType; e.index = index; memcpy(e.aesKeyHandle.AsMutable(), diff --git a/src/app/icd/server/ICDMonitoringTable.h b/src/app/icd/server/ICDMonitoringTable.h index e996d0c757cc23..942c56fda45e71 100644 --- a/src/app/icd/server/ICDMonitoringTable.h +++ b/src/app/icd/server/ICDMonitoringTable.h @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -101,14 +102,15 @@ struct ICDMonitoringEntry : public PersistentData */ bool IsKeyEquivalent(ByteSpan keyData); - chip::FabricIndex fabricIndex = kUndefinedFabricIndex; - chip::NodeId checkInNodeID = kUndefinedNodeId; - uint64_t monitoredSubject = static_cast(0); - Crypto::Aes128KeyHandle aesKeyHandle = Crypto::Aes128KeyHandle(); - Crypto::Hmac128KeyHandle hmacKeyHandle = Crypto::Hmac128KeyHandle(); - bool keyHandleValid = false; - uint16_t index = 0; - Crypto::SymmetricKeystore * symmetricKeystore = nullptr; + chip::FabricIndex fabricIndex = kUndefinedFabricIndex; + chip::NodeId checkInNodeID = kUndefinedNodeId; + uint64_t monitoredSubject = static_cast(0); + app::Clusters::IcdManagement::ClientTypeEnum clientType = app::Clusters::IcdManagement::ClientTypeEnum::kPermanent; + Crypto::Aes128KeyHandle aesKeyHandle = Crypto::Aes128KeyHandle(); + Crypto::Hmac128KeyHandle hmacKeyHandle = Crypto::Hmac128KeyHandle(); + bool keyHandleValid = false; + uint16_t index = 0; + Crypto::SymmetricKeystore * symmetricKeystore = nullptr; }; /** diff --git a/src/app/icd/server/tests/TestICDManager.cpp b/src/app/icd/server/tests/TestICDManager.cpp index 45e781685e6d31..0b3c1a459441dd 100644 --- a/src/app/icd/server/tests/TestICDManager.cpp +++ b/src/app/icd/server/tests/TestICDManager.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -35,6 +36,7 @@ using namespace chip; using namespace chip::Test; using namespace chip::app; +using namespace chip::AddressResolve; using namespace chip::System; using namespace chip::System::Clock; using namespace chip::System::Clock::Literals; diff --git a/src/app/icd/server/tests/TestICDMonitoringTable.cpp b/src/app/icd/server/tests/TestICDMonitoringTable.cpp index ef1e5b32468b7a..423bc1506b36fb 100644 --- a/src/app/icd/server/tests/TestICDMonitoringTable.cpp +++ b/src/app/icd/server/tests/TestICDMonitoringTable.cpp @@ -20,10 +20,12 @@ #include #include #include +#include #include #include using namespace chip; +using namespace chip::app::Clusters::IcdManagement; using TestSessionKeystoreImpl = Crypto::DefaultSessionKeystore; @@ -73,6 +75,7 @@ TEST(TestICDMonitoringTable, TestEntryAssignationOverload) entry.checkInNodeID = 34; entry.monitoredSubject = 32; + entry.clientType = ClientTypeEnum::kEphemeral; // Entry should be valid now EXPECT_TRUE(entry.IsValid()); @@ -88,6 +91,7 @@ TEST(TestICDMonitoringTable, TestEntryAssignationOverload) EXPECT_EQ(entry.fabricIndex, entry2.fabricIndex); EXPECT_EQ(entry.checkInNodeID, entry2.checkInNodeID); EXPECT_EQ(entry.monitoredSubject, entry2.monitoredSubject); + EXPECT_EQ(entry.clientType, entry2.clientType); EXPECT_TRUE(entry2.IsKeyEquivalent(ByteSpan(kKeyBuffer1a))); } @@ -130,6 +134,7 @@ TEST(TestICDMonitoringTable, TestSaveAndLoadRegistrationValue) ICDMonitoringEntry entry1(&keystore); entry1.checkInNodeID = kClientNodeId11; entry1.monitoredSubject = kClientNodeId12; + entry1.clientType = ClientTypeEnum::kPermanent; EXPECT_EQ(CHIP_NO_ERROR, entry1.SetKey(ByteSpan(kKeyBuffer1a))); EXPECT_EQ(CHIP_NO_ERROR, saving.Set(0, entry1)); @@ -137,6 +142,7 @@ TEST(TestICDMonitoringTable, TestSaveAndLoadRegistrationValue) ICDMonitoringEntry entry2(&keystore); entry2.checkInNodeID = kClientNodeId12; entry2.monitoredSubject = kClientNodeId11; + entry2.clientType = ClientTypeEnum::kEphemeral; EXPECT_EQ(CHIP_NO_ERROR, entry2.SetKey(ByteSpan(kKeyBuffer2a))); EXPECT_EQ(CHIP_NO_ERROR, saving.Set(1, entry2)); @@ -152,6 +158,7 @@ TEST(TestICDMonitoringTable, TestSaveAndLoadRegistrationValue) EXPECT_EQ(kTestFabricIndex1, entry.fabricIndex); EXPECT_EQ(kClientNodeId11, entry.checkInNodeID); EXPECT_EQ(kClientNodeId12, entry.monitoredSubject); + EXPECT_EQ(ClientTypeEnum::kPermanent, entry.clientType); EXPECT_TRUE(entry.IsKeyEquivalent(ByteSpan(kKeyBuffer1a))); EXPECT_EQ(memcmp(entry1.hmacKeyHandle.As(), entry.hmacKeyHandle.As(), sizeof(Crypto::Symmetric128BitsKeyByteArray)), @@ -162,6 +169,7 @@ TEST(TestICDMonitoringTable, TestSaveAndLoadRegistrationValue) EXPECT_EQ(kTestFabricIndex1, entry.fabricIndex); EXPECT_EQ(kClientNodeId12, entry.checkInNodeID); EXPECT_EQ(kClientNodeId11, entry.monitoredSubject); + EXPECT_EQ(ClientTypeEnum::kEphemeral, entry.clientType); EXPECT_TRUE(entry.IsKeyEquivalent(ByteSpan(kKeyBuffer2a))); EXPECT_EQ(memcmp(entry2.hmacKeyHandle.As(), entry.hmacKeyHandle.As(), sizeof(Crypto::Symmetric128BitsKeyByteArray)), @@ -185,6 +193,7 @@ TEST(TestICDMonitoringTable, TestSaveAndLoadRegistrationValue) EXPECT_EQ(kTestFabricIndex1, entry.fabricIndex); EXPECT_EQ(kClientNodeId12, entry.checkInNodeID); EXPECT_EQ(kClientNodeId11, entry.monitoredSubject); + EXPECT_EQ(ClientTypeEnum::kEphemeral, entry.clientType); EXPECT_TRUE(entry.IsKeyEquivalent(ByteSpan(kKeyBuffer2a))); EXPECT_EQ(memcmp(entry2.hmacKeyHandle.As(), entry.hmacKeyHandle.As(), sizeof(Crypto::Symmetric128BitsKeyByteArray)), @@ -195,6 +204,7 @@ TEST(TestICDMonitoringTable, TestSaveAndLoadRegistrationValue) EXPECT_EQ(kTestFabricIndex1, entry.fabricIndex); EXPECT_EQ(kClientNodeId13, entry.checkInNodeID); EXPECT_EQ(kClientNodeId11, entry.monitoredSubject); + EXPECT_EQ(ClientTypeEnum::kPermanent, entry.clientType); EXPECT_TRUE(entry.IsKeyEquivalent(ByteSpan(kKeyBuffer1b))); EXPECT_EQ(memcmp(entry4.hmacKeyHandle.As(), entry.hmacKeyHandle.As(), sizeof(Crypto::Symmetric128BitsKeyByteArray)), diff --git a/src/app/tests/suites/TestIcdManagementCluster.yaml b/src/app/tests/suites/TestIcdManagementCluster.yaml index a3196835915b52..68e358385b8e21 100644 --- a/src/app/tests/suites/TestIcdManagementCluster.yaml +++ b/src/app/tests/suites/TestIcdManagementCluster.yaml @@ -195,6 +195,8 @@ tests: value: 1001 - name: "Key" value: "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e" + - name: "ClientType" + value: ClientTypeEnum.Permanent response: error: CONSTRAINT_ERROR @@ -208,10 +210,12 @@ tests: value: 1001 - name: "Key" value: "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\xff" + - name: "ClientType" + value: ClientTypeEnum.Permanent response: error: CONSTRAINT_ERROR - - label: "Register 1.1" + - label: "Register 1.1 - Invalid ClientType" command: "RegisterClient" arguments: values: @@ -221,6 +225,23 @@ tests: value: 1001 - name: "Key" value: "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" + - name: "ClientType" + value: ClientTypeEnum.UnknownEnumValue + response: + error: CONSTRAINT_ERROR + + - label: "Register 1.2" + command: "RegisterClient" + arguments: + values: + - name: "CheckInNodeID" + value: 101 + - name: "MonitoredSubject" + value: 1001 + - name: "Key" + value: "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" + - name: "ClientType" + value: ClientTypeEnum.Permanent response: values: - name: "ICDCounter" @@ -240,6 +261,8 @@ tests: - name: "Key" value: "\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f" + - name: "ClientType" + value: ClientTypeEnum.Ephemeral response: values: - name: "ICDCounter" @@ -258,6 +281,8 @@ tests: value: 3001 - name: "Key" value: "\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f" + - name: "ClientType" + value: ClientTypeEnum.Permanent response: error: RESOURCE_EXHAUSTED @@ -267,8 +292,16 @@ tests: response: value: [ - { CheckInNodeID: 101, MonitoredSubject: 1001 }, - { CheckInNodeID: 201, MonitoredSubject: 2001 }, + { + CheckInNodeID: 101, + MonitoredSubject: 1001, + ClientType: ClientTypeEnum.Permanent, + }, + { + CheckInNodeID: 201, + MonitoredSubject: 2001, + ClientType: ClientTypeEnum.Ephemeral, + }, ] - label: "Register 1.1 (update)" @@ -281,6 +314,8 @@ tests: value: 1002 - name: "Key" value: "\x01\x11\x21\x31\x41\x51\x61\x71\x81\x91\xa1\xb1\xc1\xd1\xe1\xf1" + - name: "ClientType" + value: ClientTypeEnum.Ephemeral response: values: - name: "ICDCounter" @@ -295,8 +330,16 @@ tests: response: value: [ - { CheckInNodeID: 101, MonitoredSubject: 1002 }, - { CheckInNodeID: 201, MonitoredSubject: 2001 }, + { + CheckInNodeID: 101, + MonitoredSubject: 1002, + ClientType: ClientTypeEnum.Ephemeral, + }, + { + CheckInNodeID: 201, + MonitoredSubject: 2001, + ClientType: ClientTypeEnum.Ephemeral, + }, ] - label: "Register 2.2 (wrong verification key)" @@ -312,6 +355,8 @@ tests: - name: "VerificationKey" value: "\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2f\x2f" + - name: "ClientType" + value: ClientTypeEnum.Permanent response: values: - name: "ICDCounter" @@ -326,8 +371,16 @@ tests: response: value: [ - { CheckInNodeID: 101, MonitoredSubject: 1002 }, - { CheckInNodeID: 201, MonitoredSubject: 2002 }, + { + CheckInNodeID: 101, + MonitoredSubject: 1002, + ClientType: ClientTypeEnum.Ephemeral, + }, + { + CheckInNodeID: 201, + MonitoredSubject: 2002, + ClientType: ClientTypeEnum.Permanent, + }, ] - label: "Unregister 1.1 (wrong key)" diff --git a/src/app/tests/suites/certification/Test_TC_ICDM_3_4.yaml b/src/app/tests/suites/certification/Test_TC_ICDM_3_4.yaml index 7bbcb729489eef..a4eb232b98e157 100644 --- a/src/app/tests/suites/certification/Test_TC_ICDM_3_4.yaml +++ b/src/app/tests/suites/certification/Test_TC_ICDM_3_4.yaml @@ -128,6 +128,9 @@ tests: value: MonitorSubID1 - name: "Key" value: Key1 + # Adding input for the test to pass for now - Full test script needs to be updated + - name: "ClientType" + value: ClientTypeEnum.Permanent response: values: - name: "ICDCounter" 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 0269b8f0f3dcad..c1e2805de8bf15 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 @@ -39,17 +39,24 @@ limitations under the License. + + + + + + + - - - + + + @@ -113,6 +120,7 @@ limitations under the License. + diff --git a/src/controller/AutoCommissioner.cpp b/src/controller/AutoCommissioner.cpp index d6bc9f5c79fcac..8232292479ff3f 100644 --- a/src/controller/AutoCommissioner.cpp +++ b/src/controller/AutoCommissioner.cpp @@ -91,6 +91,11 @@ CHIP_ERROR AutoCommissioner::VerifyICDRegistrationInfo(const CommissioningParame ChipLogError(Controller, "Missing ICD monitored subject!"); return CHIP_ERROR_INVALID_ARGUMENT; } + if (!params.GetICDClientType().HasValue()) + { + ChipLogError(Controller, "Missing ICD Client Type!"); + return CHIP_ERROR_INVALID_ARGUMENT; + } return CHIP_NO_ERROR; } @@ -270,6 +275,7 @@ CHIP_ERROR AutoCommissioner::SetCommissioningParameters(const CommissioningParam mParams.SetICDSymmetricKey(ByteSpan(mICDSymmetricKey)); mParams.SetICDCheckInNodeId(params.GetICDCheckInNodeId().Value()); mParams.SetICDMonitoredSubject(params.GetICDMonitoredSubject().Value()); + mParams.SetICDClientType(params.GetICDClientType().Value()); } return CHIP_NO_ERROR; diff --git a/src/controller/CommissioningDelegate.h b/src/controller/CommissioningDelegate.h index 99f00f109d4ff0..7a96939cf49434 100644 --- a/src/controller/CommissioningDelegate.h +++ b/src/controller/CommissioningDelegate.h @@ -558,6 +558,13 @@ class CommissioningParameters return *this; } + Optional GetICDClientType() const { return mICDClientType; } + CommissioningParameters & SetICDClientType(app::Clusters::IcdManagement::ClientTypeEnum icdClientType) + { + mICDClientType = MakeOptional(icdClientType); + return *this; + } + Optional GetICDStayActiveDurationMsec() const { return mICDStayActiveDurationMsec; } CommissioningParameters & SetICDStayActiveDurationMsec(uint32_t stayActiveDurationMsec) { @@ -632,6 +639,7 @@ class CommissioningParameters Optional mICDCheckInNodeId; Optional mICDMonitoredSubject; Optional mICDSymmetricKey; + Optional mICDClientType; Optional mICDStayActiveDurationMsec; ICDRegistrationStrategy mICDRegistrationStrategy = ICDRegistrationStrategy::kIgnore; bool mCheckForMatchingFabric = false; diff --git a/src/controller/data_model/controller-clusters.matter b/src/controller/data_model/controller-clusters.matter index cb858ffdcd8802..a8567d591b1f7a 100644 --- a/src/controller/data_model/controller-clusters.matter +++ b/src/controller/data_model/controller-clusters.matter @@ -2672,6 +2672,11 @@ cluster BooleanState = 69 { cluster IcdManagement = 70 { revision 2; + enum ClientTypeEnum : enum8 { + kPermanent = 0; + kEphemeral = 1; + } + enum OperatingModeEnum : enum8 { kSIT = 0; kLIT = 1; @@ -2706,6 +2711,7 @@ cluster IcdManagement = 70 { fabric_scoped struct MonitoringRegistrationStruct { fabric_sensitive node_id checkInNodeID = 1; fabric_sensitive int64u monitoredSubject = 2; + fabric_sensitive ClientTypeEnum clientType = 4; fabric_idx fabricIndex = 254; } @@ -2730,6 +2736,7 @@ cluster IcdManagement = 70 { int64u monitoredSubject = 1; octet_string<16> key = 2; optional octet_string<16> verificationKey = 3; + ClientTypeEnum clientType = 4; } response struct RegisterClientResponse = 1 { diff --git a/src/controller/java/AndroidDeviceControllerWrapper.cpp b/src/controller/java/AndroidDeviceControllerWrapper.cpp index 87f53735bcf617..af5d220295a983 100644 --- a/src/controller/java/AndroidDeviceControllerWrapper.cpp +++ b/src/controller/java/AndroidDeviceControllerWrapper.cpp @@ -526,6 +526,12 @@ CHIP_ERROR AndroidDeviceControllerWrapper::ApplyICDRegistrationInfo(chip::Contro VerifyOrReturnError(err == CHIP_NO_ERROR, err); jbyteArray jSymmetricKey = static_cast(env->CallObjectMethod(icdRegistrationInfo, getSymmetricKeyMethod)); + jmethodID getClientTypeMethod; + err = chip::JniReferences::GetInstance().FindMethod(env, icdRegistrationInfo, "getClientType", "()Ljava/lang/Integer;", + &getClientTypeMethod); + VerifyOrReturnError(err == CHIP_NO_ERROR, err); + jobject jClientType = env->CallObjectMethod(icdRegistrationInfo, getClientTypeMethod); + chip::NodeId checkInNodeId = chip::kUndefinedNodeId; if (jCheckInNodeId != nullptr) { @@ -556,6 +562,14 @@ CHIP_ERROR AndroidDeviceControllerWrapper::ApplyICDRegistrationInfo(chip::Contro } params.SetICDSymmetricKey(chip::ByteSpan(mICDSymmetricKey)); + chip::app::Clusters::IcdManagement::ClientTypeEnum clientType = chip::app::Clusters::IcdManagement::ClientTypeEnum::kPermanent; + if (jClientType != nullptr) + { + clientType = static_cast( + chip::JniReferences::GetInstance().IntegerToPrimitive(jClientType)); + } + params.SetICDClientType(clientType); + return err; } diff --git a/src/controller/java/generated/java/chip/devicecontroller/ChipClusters.java b/src/controller/java/generated/java/chip/devicecontroller/ChipClusters.java index 80491515bc57d3..4b762e1ef39f37 100644 --- a/src/controller/java/generated/java/chip/devicecontroller/ChipClusters.java +++ b/src/controller/java/generated/java/chip/devicecontroller/ChipClusters.java @@ -18618,11 +18618,11 @@ public long initWithDevice(long devicePtr, int endpointId) { return 0L; } - public void registerClient(RegisterClientResponseCallback callback, Long checkInNodeID, Long monitoredSubject, byte[] key, Optional verificationKey) { - registerClient(callback, checkInNodeID, monitoredSubject, key, verificationKey, 0); + public void registerClient(RegisterClientResponseCallback callback, Long checkInNodeID, Long monitoredSubject, byte[] key, Optional verificationKey, Integer clientType) { + registerClient(callback, checkInNodeID, monitoredSubject, key, verificationKey, clientType, 0); } - public void registerClient(RegisterClientResponseCallback callback, Long checkInNodeID, Long monitoredSubject, byte[] key, Optional verificationKey, int timedInvokeTimeoutMs) { + public void registerClient(RegisterClientResponseCallback callback, Long checkInNodeID, Long monitoredSubject, byte[] key, Optional verificationKey, Integer clientType, int timedInvokeTimeoutMs) { final long commandId = 0L; ArrayList elements = new ArrayList<>(); @@ -18642,6 +18642,10 @@ public void registerClient(RegisterClientResponseCallback callback, Long checkIn BaseTLVType verificationKeytlvValue = verificationKey.map((nonOptionalverificationKey) -> new ByteArrayType(nonOptionalverificationKey)).orElse(new EmptyType()); elements.add(new StructElement(verificationKeyFieldID, verificationKeytlvValue)); + final long clientTypeFieldID = 4L; + BaseTLVType clientTypetlvValue = new UIntType(clientType); + elements.add(new StructElement(clientTypeFieldID, clientTypetlvValue)); + StructType commandArgs = new StructType(elements); invoke(new InvokeCallbackImpl(callback) { @Override diff --git a/src/controller/java/generated/java/chip/devicecontroller/ChipStructs.java b/src/controller/java/generated/java/chip/devicecontroller/ChipStructs.java index c22d3593b9e87e..f78eaf9c83cd10 100644 --- a/src/controller/java/generated/java/chip/devicecontroller/ChipStructs.java +++ b/src/controller/java/generated/java/chip/devicecontroller/ChipStructs.java @@ -3483,18 +3483,22 @@ public String toString() { public static class IcdManagementClusterMonitoringRegistrationStruct { public Long checkInNodeID; public Long monitoredSubject; + public Integer clientType; public Integer fabricIndex; private static final long CHECK_IN_NODE_I_D_ID = 1L; private static final long MONITORED_SUBJECT_ID = 2L; + private static final long CLIENT_TYPE_ID = 4L; private static final long FABRIC_INDEX_ID = 254L; public IcdManagementClusterMonitoringRegistrationStruct( Long checkInNodeID, Long monitoredSubject, + Integer clientType, Integer fabricIndex ) { this.checkInNodeID = checkInNodeID; this.monitoredSubject = monitoredSubject; + this.clientType = clientType; this.fabricIndex = fabricIndex; } @@ -3502,6 +3506,7 @@ public StructType encodeTlv() { ArrayList values = new ArrayList<>(); values.add(new StructElement(CHECK_IN_NODE_I_D_ID, new UIntType(checkInNodeID))); values.add(new StructElement(MONITORED_SUBJECT_ID, new UIntType(monitoredSubject))); + values.add(new StructElement(CLIENT_TYPE_ID, new UIntType(clientType))); values.add(new StructElement(FABRIC_INDEX_ID, new UIntType(fabricIndex))); return new StructType(values); @@ -3513,6 +3518,7 @@ public static IcdManagementClusterMonitoringRegistrationStruct decodeTlv(BaseTLV } Long checkInNodeID = null; Long monitoredSubject = null; + Integer clientType = null; Integer fabricIndex = null; for (StructElement element: ((StructType)tlvValue).value()) { if (element.contextTagNum() == CHECK_IN_NODE_I_D_ID) { @@ -3525,6 +3531,11 @@ public static IcdManagementClusterMonitoringRegistrationStruct decodeTlv(BaseTLV UIntType castingValue = element.value(UIntType.class); monitoredSubject = castingValue.value(Long.class); } + } else if (element.contextTagNum() == CLIENT_TYPE_ID) { + if (element.value(BaseTLVType.class).type() == TLVType.UInt) { + UIntType castingValue = element.value(UIntType.class); + clientType = castingValue.value(Integer.class); + } } else if (element.contextTagNum() == FABRIC_INDEX_ID) { if (element.value(BaseTLVType.class).type() == TLVType.UInt) { UIntType castingValue = element.value(UIntType.class); @@ -3535,6 +3546,7 @@ public static IcdManagementClusterMonitoringRegistrationStruct decodeTlv(BaseTLV return new IcdManagementClusterMonitoringRegistrationStruct( checkInNodeID, monitoredSubject, + clientType, fabricIndex ); } @@ -3549,6 +3561,9 @@ public String toString() { output.append("\tmonitoredSubject: "); output.append(monitoredSubject); output.append("\n"); + output.append("\tclientType: "); + output.append(clientType); + output.append("\n"); output.append("\tfabricIndex: "); output.append(fabricIndex); output.append("\n"); diff --git a/src/controller/java/generated/java/chip/devicecontroller/ClusterIDMapping.java b/src/controller/java/generated/java/chip/devicecontroller/ClusterIDMapping.java index 06f9941b772c21..cc2cb937c66cad 100644 --- a/src/controller/java/generated/java/chip/devicecontroller/ClusterIDMapping.java +++ b/src/controller/java/generated/java/chip/devicecontroller/ClusterIDMapping.java @@ -5859,7 +5859,7 @@ public static Command value(long id) throws NoSuchFieldError { } throw new NoSuchFieldError(); } - }public enum RegisterClientCommandField {CheckInNodeID(0),MonitoredSubject(1),Key(2),VerificationKey(3),; + }public enum RegisterClientCommandField {CheckInNodeID(0),MonitoredSubject(1),Key(2),VerificationKey(3),ClientType(4),; private final int id; RegisterClientCommandField(int id) { this.id = id; diff --git a/src/controller/java/generated/java/chip/devicecontroller/ClusterInfoMapping.java b/src/controller/java/generated/java/chip/devicecontroller/ClusterInfoMapping.java index f4830c334b842f..2573b42c0184f7 100644 --- a/src/controller/java/generated/java/chip/devicecontroller/ClusterInfoMapping.java +++ b/src/controller/java/generated/java/chip/devicecontroller/ClusterInfoMapping.java @@ -23986,6 +23986,9 @@ public Map> getCommandMap() { CommandParameterInfo icdManagementregisterClientverificationKeyCommandParameterInfo = new CommandParameterInfo("verificationKey", Optional.class, byte[].class); icdManagementregisterClientCommandParams.put("verificationKey",icdManagementregisterClientverificationKeyCommandParameterInfo); + + CommandParameterInfo icdManagementregisterClientclientTypeCommandParameterInfo = new CommandParameterInfo("clientType", Integer.class, Integer.class); + icdManagementregisterClientCommandParams.put("clientType",icdManagementregisterClientclientTypeCommandParameterInfo); InteractionInfo icdManagementregisterClientInteractionInfo = new InteractionInfo( (cluster, callback, commandArguments) -> { ((ChipClusters.IcdManagementCluster) cluster) @@ -24002,6 +24005,9 @@ public Map> getCommandMap() { , (Optional) commandArguments.get("verificationKey") + , (Integer) + commandArguments.get("clientType") + ); }, () -> new DelegatedIcdManagementClusterRegisterClientResponseCallback(), diff --git a/src/controller/java/generated/java/chip/devicecontroller/cluster/structs/IcdManagementClusterMonitoringRegistrationStruct.kt b/src/controller/java/generated/java/chip/devicecontroller/cluster/structs/IcdManagementClusterMonitoringRegistrationStruct.kt index 8c8a7dcc410261..fd60e6d6da4328 100644 --- a/src/controller/java/generated/java/chip/devicecontroller/cluster/structs/IcdManagementClusterMonitoringRegistrationStruct.kt +++ b/src/controller/java/generated/java/chip/devicecontroller/cluster/structs/IcdManagementClusterMonitoringRegistrationStruct.kt @@ -25,12 +25,14 @@ import matter.tlv.TlvWriter class IcdManagementClusterMonitoringRegistrationStruct( val checkInNodeID: ULong, val monitoredSubject: ULong, + val clientType: UInt, val fabricIndex: UInt, ) { override fun toString(): String = buildString { append("IcdManagementClusterMonitoringRegistrationStruct {\n") append("\tcheckInNodeID : $checkInNodeID\n") append("\tmonitoredSubject : $monitoredSubject\n") + append("\tclientType : $clientType\n") append("\tfabricIndex : $fabricIndex\n") append("}\n") } @@ -40,6 +42,7 @@ class IcdManagementClusterMonitoringRegistrationStruct( startStructure(tlvTag) put(ContextSpecificTag(TAG_CHECK_IN_NODE_I_D), checkInNodeID) put(ContextSpecificTag(TAG_MONITORED_SUBJECT), monitoredSubject) + put(ContextSpecificTag(TAG_CLIENT_TYPE), clientType) put(ContextSpecificTag(TAG_FABRIC_INDEX), fabricIndex) endStructure() } @@ -48,6 +51,7 @@ class IcdManagementClusterMonitoringRegistrationStruct( companion object { private const val TAG_CHECK_IN_NODE_I_D = 1 private const val TAG_MONITORED_SUBJECT = 2 + private const val TAG_CLIENT_TYPE = 4 private const val TAG_FABRIC_INDEX = 254 fun fromTlv( @@ -57,6 +61,7 @@ class IcdManagementClusterMonitoringRegistrationStruct( tlvReader.enterStructure(tlvTag) val checkInNodeID = tlvReader.getULong(ContextSpecificTag(TAG_CHECK_IN_NODE_I_D)) val monitoredSubject = tlvReader.getULong(ContextSpecificTag(TAG_MONITORED_SUBJECT)) + val clientType = tlvReader.getUInt(ContextSpecificTag(TAG_CLIENT_TYPE)) val fabricIndex = tlvReader.getUInt(ContextSpecificTag(TAG_FABRIC_INDEX)) tlvReader.exitContainer() @@ -64,6 +69,7 @@ class IcdManagementClusterMonitoringRegistrationStruct( return IcdManagementClusterMonitoringRegistrationStruct( checkInNodeID, monitoredSubject, + clientType, fabricIndex, ) } 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 fd77e38a6f48fa..ddc206eeb28aad 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 @@ -107,6 +107,7 @@ class IcdManagementCluster( monitoredSubject: ULong, key: ByteArray, verificationKey: ByteArray?, + clientType: UByte, timedInvokeTimeout: Duration? = null, ): RegisterClientResponse { val commandId: UInt = 0u @@ -127,6 +128,9 @@ class IcdManagementCluster( verificationKey?.let { tlvWriter.put(ContextSpecificTag(TAG_VERIFICATION_KEY_REQ), verificationKey) } + + val TAG_CLIENT_TYPE_REQ: Int = 4 + tlvWriter.put(ContextSpecificTag(TAG_CLIENT_TYPE_REQ), clientType) tlvWriter.endStructure() val request: InvokeRequest = diff --git a/src/controller/java/generated/java/matter/controller/cluster/structs/IcdManagementClusterMonitoringRegistrationStruct.kt b/src/controller/java/generated/java/matter/controller/cluster/structs/IcdManagementClusterMonitoringRegistrationStruct.kt index f9866aa93f9ce5..fbf95fd9f40918 100644 --- a/src/controller/java/generated/java/matter/controller/cluster/structs/IcdManagementClusterMonitoringRegistrationStruct.kt +++ b/src/controller/java/generated/java/matter/controller/cluster/structs/IcdManagementClusterMonitoringRegistrationStruct.kt @@ -25,12 +25,14 @@ import matter.tlv.TlvWriter class IcdManagementClusterMonitoringRegistrationStruct( val checkInNodeID: ULong, val monitoredSubject: ULong, + val clientType: UByte, val fabricIndex: UByte, ) { override fun toString(): String = buildString { append("IcdManagementClusterMonitoringRegistrationStruct {\n") append("\tcheckInNodeID : $checkInNodeID\n") append("\tmonitoredSubject : $monitoredSubject\n") + append("\tclientType : $clientType\n") append("\tfabricIndex : $fabricIndex\n") append("}\n") } @@ -40,6 +42,7 @@ class IcdManagementClusterMonitoringRegistrationStruct( startStructure(tlvTag) put(ContextSpecificTag(TAG_CHECK_IN_NODE_I_D), checkInNodeID) put(ContextSpecificTag(TAG_MONITORED_SUBJECT), monitoredSubject) + put(ContextSpecificTag(TAG_CLIENT_TYPE), clientType) put(ContextSpecificTag(TAG_FABRIC_INDEX), fabricIndex) endStructure() } @@ -48,6 +51,7 @@ class IcdManagementClusterMonitoringRegistrationStruct( companion object { private const val TAG_CHECK_IN_NODE_I_D = 1 private const val TAG_MONITORED_SUBJECT = 2 + private const val TAG_CLIENT_TYPE = 4 private const val TAG_FABRIC_INDEX = 254 fun fromTlv( @@ -57,6 +61,7 @@ class IcdManagementClusterMonitoringRegistrationStruct( tlvReader.enterStructure(tlvTag) val checkInNodeID = tlvReader.getULong(ContextSpecificTag(TAG_CHECK_IN_NODE_I_D)) val monitoredSubject = tlvReader.getULong(ContextSpecificTag(TAG_MONITORED_SUBJECT)) + val clientType = tlvReader.getUByte(ContextSpecificTag(TAG_CLIENT_TYPE)) val fabricIndex = tlvReader.getUByte(ContextSpecificTag(TAG_FABRIC_INDEX)) tlvReader.exitContainer() @@ -64,6 +69,7 @@ class IcdManagementClusterMonitoringRegistrationStruct( return IcdManagementClusterMonitoringRegistrationStruct( checkInNodeID, monitoredSubject, + clientType, fabricIndex, ) } diff --git a/src/controller/java/src/chip/devicecontroller/ICDRegistrationInfo.java b/src/controller/java/src/chip/devicecontroller/ICDRegistrationInfo.java index be978fae28fee6..417d147238c526 100644 --- a/src/controller/java/src/chip/devicecontroller/ICDRegistrationInfo.java +++ b/src/controller/java/src/chip/devicecontroller/ICDRegistrationInfo.java @@ -24,11 +24,13 @@ public class ICDRegistrationInfo { @Nullable private final Long checkInNodeId; @Nullable private final Long monitoredSubject; @Nullable private final byte[] symmetricKey; + @Nullable private final Integer clientType; private ICDRegistrationInfo(Builder builder) { this.checkInNodeId = builder.checkInNodeId; this.monitoredSubject = builder.monitoredSubject; this.symmetricKey = builder.symmetricKey; + this.clientType = builder.clientType; } /** Returns the check in node ID. */ @@ -46,6 +48,10 @@ public byte[] getSymmetricKey() { return symmetricKey; } + public Integer getClientType() { + return clientType; + } + public static Builder newBuilder() { return new Builder(); } @@ -55,6 +61,7 @@ public static class Builder { @Nullable private Long checkInNodeId = null; @Nullable private Long monitoredSubject = null; @Nullable private byte[] symmetricKey = null; + @Nullable private Integer clientType = null; private Builder() {} @@ -81,6 +88,11 @@ public Builder setSymmetricKey(byte[] symmetricKey) { return this; } + public Builder setClientType(Integer clientType) { + this.clientType = clientType; + return this; + } + public ICDRegistrationInfo build() { return new ICDRegistrationInfo(this); } diff --git a/src/controller/java/zap-generated/CHIPAttributeTLVValueDecoder.cpp b/src/controller/java/zap-generated/CHIPAttributeTLVValueDecoder.cpp index 7cdabec93f43ca..4cebe9ea5a1829 100644 --- a/src/controller/java/zap-generated/CHIPAttributeTLVValueDecoder.cpp +++ b/src/controller/java/zap-generated/CHIPAttributeTLVValueDecoder.cpp @@ -12306,6 +12306,13 @@ jobject DecodeAttributeValue(const app::ConcreteAttributePath & aPath, TLV::TLVR chip::JniReferences::GetInstance().CreateBoxedObject( newElement_0_monitoredSubjectClassName.c_str(), newElement_0_monitoredSubjectCtorSignature.c_str(), jninewElement_0_monitoredSubject, newElement_0_monitoredSubject); + jobject newElement_0_clientType; + std::string newElement_0_clientTypeClassName = "java/lang/Integer"; + std::string newElement_0_clientTypeCtorSignature = "(I)V"; + jint jninewElement_0_clientType = static_cast(entry_0.clientType); + chip::JniReferences::GetInstance().CreateBoxedObject(newElement_0_clientTypeClassName.c_str(), + newElement_0_clientTypeCtorSignature.c_str(), + jninewElement_0_clientType, newElement_0_clientType); jobject newElement_0_fabricIndex; std::string newElement_0_fabricIndexClassName = "java/lang/Integer"; std::string newElement_0_fabricIndexCtorSignature = "(I)V"; @@ -12325,9 +12332,10 @@ jobject DecodeAttributeValue(const app::ConcreteAttributePath & aPath, TLV::TLVR } jmethodID monitoringRegistrationStructStructCtor_1; - err = chip::JniReferences::GetInstance().FindMethod(env, monitoringRegistrationStructStructClass_1, "", - "(Ljava/lang/Long;Ljava/lang/Long;Ljava/lang/Integer;)V", - &monitoringRegistrationStructStructCtor_1); + err = chip::JniReferences::GetInstance().FindMethod( + env, monitoringRegistrationStructStructClass_1, "", + "(Ljava/lang/Long;Ljava/lang/Long;Ljava/lang/Integer;Ljava/lang/Integer;)V", + &monitoringRegistrationStructStructCtor_1); if (err != CHIP_NO_ERROR || monitoringRegistrationStructStructCtor_1 == nullptr) { ChipLogError(Zcl, "Could not find ChipStructs$IcdManagementClusterMonitoringRegistrationStruct constructor"); @@ -12335,7 +12343,8 @@ jobject DecodeAttributeValue(const app::ConcreteAttributePath & aPath, TLV::TLVR } newElement_0 = env->NewObject(monitoringRegistrationStructStructClass_1, monitoringRegistrationStructStructCtor_1, - newElement_0_checkInNodeID, newElement_0_monitoredSubject, newElement_0_fabricIndex); + newElement_0_checkInNodeID, newElement_0_monitoredSubject, newElement_0_clientType, + newElement_0_fabricIndex); chip::JniReferences::GetInstance().AddToList(value, newElement_0); } return value; diff --git a/src/controller/python/ChipDeviceController-ScriptDevicePairingDelegate.cpp b/src/controller/python/ChipDeviceController-ScriptDevicePairingDelegate.cpp index c979e0d9cd77a3..c04481a45a11ea 100644 --- a/src/controller/python/ChipDeviceController-ScriptDevicePairingDelegate.cpp +++ b/src/controller/python/ChipDeviceController-ScriptDevicePairingDelegate.cpp @@ -191,6 +191,7 @@ void ScriptDevicePairingDelegate::OnICDRegistrationComplete(ScopedNodeId nodeId, clientInfo.peer_node = nodeId; clientInfo.monitored_subject = sCommissioningParameters.GetICDMonitoredSubject().Value(); clientInfo.start_icd_counter = icdCounter; + clientInfo.client_type = sCommissioningParameters.GetICDClientType().Value(); CHIP_ERROR err = sICDClientStorage.SetKey(clientInfo, ByteSpan(sICDSymmetricKey)); if (err == CHIP_NO_ERROR) diff --git a/src/controller/python/chip/clusters/CHIPClusters.py b/src/controller/python/chip/clusters/CHIPClusters.py index 773fe342105443..37ead8e634611a 100644 --- a/src/controller/python/chip/clusters/CHIPClusters.py +++ b/src/controller/python/chip/clusters/CHIPClusters.py @@ -4064,6 +4064,7 @@ class ChipClusters: "monitoredSubject": "int", "key": "bytes", "verificationKey": "bytes", + "clientType": "int", }, }, 0x00000002: { diff --git a/src/controller/python/chip/clusters/Objects.py b/src/controller/python/chip/clusters/Objects.py index 43917192955506..4c17fd99af2d21 100644 --- a/src/controller/python/chip/clusters/Objects.py +++ b/src/controller/python/chip/clusters/Objects.py @@ -14187,6 +14187,15 @@ def descriptor(cls) -> ClusterObjectDescriptor: clusterRevision: 'uint' = None class Enums: + class ClientTypeEnum(MatterIntEnum): + kPermanent = 0x00 + kEphemeral = 0x01 + # All received enum values that are not listed above will be mapped + # to kUnknownEnumValue. This is a helper enum value that should only + # be used by code to process how it handles receiving and unknown + # enum value. This specific should never be transmitted. + kUnknownEnumValue = 2, + class OperatingModeEnum(MatterIntEnum): kSit = 0x00 kLit = 0x01 @@ -14230,11 +14239,13 @@ def descriptor(cls) -> ClusterObjectDescriptor: Fields=[ ClusterObjectFieldDescriptor(Label="checkInNodeID", Tag=1, Type=uint), ClusterObjectFieldDescriptor(Label="monitoredSubject", Tag=2, Type=uint), + ClusterObjectFieldDescriptor(Label="clientType", Tag=4, Type=IcdManagement.Enums.ClientTypeEnum), ClusterObjectFieldDescriptor(Label="fabricIndex", Tag=254, Type=uint), ]) checkInNodeID: 'uint' = 0 monitoredSubject: 'uint' = 0 + clientType: 'IcdManagement.Enums.ClientTypeEnum' = 0 fabricIndex: 'uint' = 0 class Commands: @@ -14253,12 +14264,14 @@ def descriptor(cls) -> ClusterObjectDescriptor: ClusterObjectFieldDescriptor(Label="monitoredSubject", Tag=1, Type=uint), ClusterObjectFieldDescriptor(Label="key", Tag=2, Type=bytes), ClusterObjectFieldDescriptor(Label="verificationKey", Tag=3, Type=typing.Optional[bytes]), + ClusterObjectFieldDescriptor(Label="clientType", Tag=4, Type=IcdManagement.Enums.ClientTypeEnum), ]) checkInNodeID: 'uint' = 0 monitoredSubject: 'uint' = 0 key: 'bytes' = b"" verificationKey: 'typing.Optional[bytes]' = None + clientType: 'IcdManagement.Enums.ClientTypeEnum' = 0 @dataclass class RegisterClientResponse(ClusterCommand): diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRAttributeTLVValueDecoder.mm b/src/darwin/Framework/CHIP/zap-generated/MTRAttributeTLVValueDecoder.mm index 02ce62e1c2f0dc..1feae62ea18928 100644 --- a/src/darwin/Framework/CHIP/zap-generated/MTRAttributeTLVValueDecoder.mm +++ b/src/darwin/Framework/CHIP/zap-generated/MTRAttributeTLVValueDecoder.mm @@ -5040,6 +5040,7 @@ static id _Nullable DecodeAttributeValueForICDManagementCluster(AttributeId aAtt newElement_0 = [MTRICDManagementClusterMonitoringRegistrationStruct new]; newElement_0.checkInNodeID = [NSNumber numberWithUnsignedLongLong:entry_0.checkInNodeID]; newElement_0.monitoredSubject = [NSNumber numberWithUnsignedLongLong:entry_0.monitoredSubject]; + newElement_0.clientType = [NSNumber numberWithUnsignedChar:chip::to_underlying(entry_0.clientType)]; newElement_0.fabricIndex = [NSNumber numberWithUnsignedChar:entry_0.fabricIndex]; [array_0 addObject:newElement_0]; } diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters.h b/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters.h index a481ad0f37f8a4..1513b8c0f54540 100644 --- a/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters.h +++ b/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters.h @@ -17756,6 +17756,11 @@ typedef NS_OPTIONS(uint32_t, MTRGroupKeyManagementFeature) { MTRGroupKeyManagementFeatureCacheAndSync MTR_PROVISIONALLY_AVAILABLE = 0x1, } MTR_PROVISIONALLY_AVAILABLE; +typedef NS_ENUM(uint8_t, MTRICDManagementClientType) { + MTRICDManagementClientTypePermanent MTR_PROVISIONALLY_AVAILABLE = 0x00, + MTRICDManagementClientTypeEphemeral MTR_PROVISIONALLY_AVAILABLE = 0x01, +} MTR_PROVISIONALLY_AVAILABLE; + typedef NS_ENUM(uint8_t, MTRICDManagementOperatingMode) { MTRICDManagementOperatingModeSIT MTR_PROVISIONALLY_AVAILABLE = 0x00, MTRICDManagementOperatingModeLIT MTR_PROVISIONALLY_AVAILABLE = 0x01, diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloadsObjc.h b/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloadsObjc.h index 4e74aa8828a718..d95ac77034ce61 100644 --- a/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloadsObjc.h +++ b/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloadsObjc.h @@ -3618,6 +3618,8 @@ MTR_PROVISIONALLY_AVAILABLE @property (nonatomic, copy) NSData * _Nonnull key MTR_PROVISIONALLY_AVAILABLE; @property (nonatomic, copy) NSData * _Nullable verificationKey MTR_PROVISIONALLY_AVAILABLE; + +@property (nonatomic, copy) NSNumber * _Nonnull clientType 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 1dd6753fa889ed..08b00b6e4555f0 100644 --- a/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloadsObjc.mm +++ b/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloadsObjc.mm @@ -9524,6 +9524,8 @@ - (instancetype)init _key = [NSData data]; _verificationKey = nil; + + _clientType = @(0); _timedInvokeTimeoutMs = nil; _serverSideProcessingTimeout = nil; } @@ -9538,6 +9540,7 @@ - (id)copyWithZone:(NSZone * _Nullable)zone; other.monitoredSubject = self.monitoredSubject; other.key = self.key; other.verificationKey = self.verificationKey; + other.clientType = self.clientType; other.timedInvokeTimeoutMs = self.timedInvokeTimeoutMs; other.serverSideProcessingTimeout = self.serverSideProcessingTimeout; @@ -9546,7 +9549,7 @@ - (id)copyWithZone:(NSZone * _Nullable)zone; - (NSString *)description { - NSString * descriptionString = [NSString stringWithFormat:@"<%@: checkInNodeID:%@; monitoredSubject:%@; key:%@; verificationKey:%@; >", NSStringFromClass([self class]), _checkInNodeID, _monitoredSubject, [_key base64EncodedStringWithOptions:0], [_verificationKey base64EncodedStringWithOptions:0]]; + NSString * descriptionString = [NSString stringWithFormat:@"<%@: checkInNodeID:%@; monitoredSubject:%@; key:%@; verificationKey:%@; clientType:%@; >", NSStringFromClass([self class]), _checkInNodeID, _monitoredSubject, [_key base64EncodedStringWithOptions:0], [_verificationKey base64EncodedStringWithOptions:0], _clientType]; return descriptionString; } @@ -9573,6 +9576,9 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader definedValue_0 = AsByteSpan(self.verificationKey); } } + { + encodableStruct.clientType = static_cast>(self.clientType.unsignedCharValue); + } auto buffer = chip::System::PacketBufferHandle::New(chip::System::PacketBuffer::kMaxSizeWithoutReserve, 0); if (buffer.IsNull()) { diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRStructsObjc.h b/src/darwin/Framework/CHIP/zap-generated/MTRStructsObjc.h index 2d5da93d9df2f5..8ea03ce1fd2a9d 100644 --- a/src/darwin/Framework/CHIP/zap-generated/MTRStructsObjc.h +++ b/src/darwin/Framework/CHIP/zap-generated/MTRStructsObjc.h @@ -762,6 +762,7 @@ MTR_PROVISIONALLY_AVAILABLE @interface MTRICDManagementClusterMonitoringRegistrationStruct : NSObject @property (nonatomic, copy) NSNumber * _Nonnull checkInNodeID MTR_PROVISIONALLY_AVAILABLE; @property (nonatomic, copy) NSNumber * _Nonnull monitoredSubject MTR_PROVISIONALLY_AVAILABLE; +@property (nonatomic, copy) NSNumber * _Nonnull clientType MTR_PROVISIONALLY_AVAILABLE; @property (nonatomic, copy) NSNumber * _Nonnull fabricIndex MTR_PROVISIONALLY_AVAILABLE; @end diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRStructsObjc.mm b/src/darwin/Framework/CHIP/zap-generated/MTRStructsObjc.mm index 559789940c7fb9..1ff604e5469e36 100644 --- a/src/darwin/Framework/CHIP/zap-generated/MTRStructsObjc.mm +++ b/src/darwin/Framework/CHIP/zap-generated/MTRStructsObjc.mm @@ -2774,6 +2774,8 @@ - (instancetype)init _monitoredSubject = @(0); + _clientType = @(0); + _fabricIndex = @(0); } return self; @@ -2785,6 +2787,7 @@ - (id)copyWithZone:(NSZone * _Nullable)zone other.checkInNodeID = self.checkInNodeID; other.monitoredSubject = self.monitoredSubject; + other.clientType = self.clientType; other.fabricIndex = self.fabricIndex; return other; @@ -2792,7 +2795,7 @@ - (id)copyWithZone:(NSZone * _Nullable)zone - (NSString *)description { - NSString * descriptionString = [NSString stringWithFormat:@"<%@: checkInNodeID:%@; monitoredSubject:%@; fabricIndex:%@; >", NSStringFromClass([self class]), _checkInNodeID, _monitoredSubject, _fabricIndex]; + NSString * descriptionString = [NSString stringWithFormat:@"<%@: checkInNodeID:%@; monitoredSubject:%@; clientType:%@; fabricIndex:%@; >", NSStringFromClass([self class]), _checkInNodeID, _monitoredSubject, _clientType, _fabricIndex]; return descriptionString; } diff --git a/src/lib/support/JniReferences.cpp b/src/lib/support/JniReferences.cpp index 6b8bb005305417..021f13c2fb0fb2 100644 --- a/src/lib/support/JniReferences.cpp +++ b/src/lib/support/JniReferences.cpp @@ -392,6 +392,19 @@ jdouble JniReferences::DoubleToPrimitive(jobject boxedDouble) return env->CallDoubleMethod(boxedDouble, valueMethod); } +jshort JniReferences::ShortToPrimitive(jobject boxedShort) +{ + JNIEnv * env = GetEnvForCurrentThread(); + VerifyOrReturnValue(env != nullptr, 0, ChipLogError(Support, "env cannot be nullptr")); + jclass boxedTypeCls = nullptr; + CHIP_ERROR err = chip::JniReferences::GetInstance().GetLocalClassRef(env, "java/lang/Short", boxedTypeCls); + VerifyOrReturnValue(err == CHIP_NO_ERROR, 0, + ChipLogError(Support, "ShortToPrimitive failed due to %" CHIP_ERROR_FORMAT, err.Format())); + + jmethodID valueMethod = env->GetMethodID(boxedTypeCls, "shortValue", "()S"); + return env->CallShortMethod(boxedShort, valueMethod); +} + CHIP_ERROR JniReferences::CallSubscriptionEstablished(jobject javaCallback, long subscriptionId) { CHIP_ERROR err = CHIP_NO_ERROR; diff --git a/src/lib/support/JniReferences.h b/src/lib/support/JniReferences.h index 5cea905dc00776..a9a3e29ebcb845 100644 --- a/src/lib/support/JniReferences.h +++ b/src/lib/support/JniReferences.h @@ -177,6 +177,11 @@ class JniReferences */ jdouble DoubleToPrimitive(jobject boxedObject); + /** + * Get a primitive jshort from the Java boxed type Short, using shortValue(). + */ + jshort ShortToPrimitive(jobject boxedShort); + CHIP_ERROR CreateArrayList(jobject & outList); CHIP_ERROR AddToList(jobject list, jobject objectToAdd); diff --git a/src/python_testing/TC_ICDM_3_1.py b/src/python_testing/TC_ICDM_3_1.py index b504035f52d86f..f5a37cd763c7af 100644 --- a/src/python_testing/TC_ICDM_3_1.py +++ b/src/python_testing/TC_ICDM_3_1.py @@ -38,6 +38,7 @@ cluster = Clusters.Objects.IcdManagement commands = cluster.Commands monitoredRegistration = cluster.Structs.MonitoringRegistrationStruct +clientTypeEnum = cluster.Enums.ClientTypeEnum # Step 2 Registration entry @@ -141,7 +142,7 @@ async def test_TC_ICDM_3_1(self): self.step(2) if self.pics_guard(self.check_pics("ICDM.S.C00.Rsp")): try: - response = await self._send_single_icdm_command(commands.RegisterClient(checkInNodeID=kStep2CheckInNodeId, monitoredSubject=kStep2MonitoredSubjectStep2, key=kStep2Key)) + response = await self._send_single_icdm_command(commands.RegisterClient(checkInNodeID=kStep2CheckInNodeId, monitoredSubject=kStep2MonitoredSubjectStep2, key=kStep2Key, clientType=clientTypeEnum.kEphemeral)) except InteractionModelError as e: asserts.assert_equal( e.status, Status.Success, "Unexpected error returned") @@ -164,6 +165,8 @@ async def test_TC_ICDM_3_1(self): registeredClients[0].checkInNodeID, kStep2CheckInNodeId, "The read attribute does not match the registered value.") asserts.assert_equal( registeredClients[0].monitoredSubject, kStep2MonitoredSubjectStep2, "The read attribute does not match the registered value.") + asserts.assert_equal( + registeredClients[0].clientType, clientTypeEnum.kEphemeral, "The read attribute does not match the registered value.") self.step(4) if self.pics_guard(self.check_pics("ICDM.S.C00.Rsp")): @@ -174,12 +177,13 @@ async def test_TC_ICDM_3_1(self): newClients.append({ "checkInNodeID": i + 1, "monitoredSubject": i + 1, - "key": os.urandom(16) + "key": os.urandom(16), + "clientType": clientTypeEnum.kPermanent }) for client in newClients: try: - response = await self._send_single_icdm_command(commands.RegisterClient(checkInNodeID=client["checkInNodeID"], monitoredSubject=client["monitoredSubject"], key=client["key"])) + response = await self._send_single_icdm_command(commands.RegisterClient(checkInNodeID=client["checkInNodeID"], monitoredSubject=client["monitoredSubject"], key=client["key"], clientType=client["clientType"])) except InteractionModelError as e: asserts.assert_equal( e.status, Status.Success, "Unexpected error returned") @@ -203,11 +207,13 @@ async def test_TC_ICDM_3_1(self): client.checkInNodeID, expectedClient["checkInNodeID"], "The read attribute does not match the registered value.") asserts.assert_equal( client.monitoredSubject, expectedClient["monitoredSubject"], "The read attribute does not match the registered value.") + asserts.assert_equal( + client.clientType, expectedClient["clientType"], "The read attribute does not match the registered value.") self.step(6) if self.pics_guard(self.check_pics("ICDM.S.C00.Rsp")): try: - response = await self._send_single_icdm_command(commands.RegisterClient(checkInNodeID=0xFFFF, monitoredSubject=0xFFFF, key=os.urandom(16))) + response = await self._send_single_icdm_command(commands.RegisterClient(checkInNodeID=0xFFFF, monitoredSubject=0xFFFF, key=os.urandom(16), clientType=clientTypeEnum.kPermanent)) except InteractionModelError as e: asserts.assert_equal( e.status, Status.ResourceExhausted, "Unexpected error returned") diff --git a/zzz_generated/app-common/app-common/zap-generated/cluster-enums-check.h b/zzz_generated/app-common/app-common/zap-generated/cluster-enums-check.h index e53404d7b32737..7e52fd09a2c13c 100644 --- a/zzz_generated/app-common/app-common/zap-generated/cluster-enums-check.h +++ b/zzz_generated/app-common/app-common/zap-generated/cluster-enums-check.h @@ -1328,6 +1328,18 @@ static auto __attribute__((unused)) EnsureKnownEnumValue(GroupKeyManagement::Gro } } +static auto __attribute__((unused)) EnsureKnownEnumValue(IcdManagement::ClientTypeEnum val) +{ + using EnumType = IcdManagement::ClientTypeEnum; + switch (val) + { + case EnumType::kPermanent: + case EnumType::kEphemeral: + return val; + default: + return EnumType::kUnknownEnumValue; + } +} static auto __attribute__((unused)) EnsureKnownEnumValue(IcdManagement::OperatingModeEnum val) { using EnumType = IcdManagement::OperatingModeEnum; 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 27601f4e651c63..a7c433848df662 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 @@ -1601,6 +1601,18 @@ namespace BooleanState {} // namespace BooleanState namespace IcdManagement { +// Enum for ClientTypeEnum +enum class ClientTypeEnum : uint8_t +{ + kPermanent = 0x00, + kEphemeral = 0x01, + // All received enum values that are not listed above will be mapped + // to kUnknownEnumValue. This is a helper enum value that should only + // be used by code to process how it handles receiving and unknown + // enum value. This specific should never be transmitted. + kUnknownEnumValue = 2, +}; + // Enum for OperatingModeEnum enum class OperatingModeEnum : uint8_t { 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 289909746b0640..54bcec37353ef1 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 @@ -9622,6 +9622,10 @@ CHIP_ERROR Type::DoEncode(TLV::TLVWriter & aWriter, TLV::Tag aTag, const Optiona { encoder.Encode(to_underlying(Fields::kMonitoredSubject), monitoredSubject); } + if (includeSensitive) + { + encoder.Encode(to_underlying(Fields::kClientType), clientType); + } if (aAccessingFabricIndex.HasValue()) { encoder.Encode(to_underlying(Fields::kFabricIndex), fabricIndex); @@ -9652,6 +9656,10 @@ CHIP_ERROR DecodableType::Decode(TLV::TLVReader & reader) { err = DataModel::Decode(reader, monitoredSubject); } + else if (__context_tag == to_underlying(Fields::kClientType)) + { + err = DataModel::Decode(reader, clientType); + } else if (__context_tag == to_underlying(Fields::kFabricIndex)) { err = DataModel::Decode(reader, fabricIndex); @@ -9676,6 +9684,7 @@ CHIP_ERROR Type::Encode(TLV::TLVWriter & aWriter, TLV::Tag aTag) const encoder.Encode(to_underlying(Fields::kMonitoredSubject), monitoredSubject); encoder.Encode(to_underlying(Fields::kKey), key); encoder.Encode(to_underlying(Fields::kVerificationKey), verificationKey); + encoder.Encode(to_underlying(Fields::kClientType), clientType); return encoder.Finalize(); } @@ -9709,6 +9718,10 @@ CHIP_ERROR DecodableType::Decode(TLV::TLVReader & reader) { err = DataModel::Decode(reader, verificationKey); } + else if (__context_tag == to_underlying(Fields::kClientType)) + { + err = DataModel::Decode(reader, clientType); + } else { } 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 d396989d0a6edf..84f19b11e4f105 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 @@ -13130,6 +13130,7 @@ enum class Fields : uint8_t { kCheckInNodeID = 1, kMonitoredSubject = 2, + kClientType = 4, kFabricIndex = 254, }; @@ -13138,6 +13139,7 @@ struct Type public: chip::NodeId checkInNodeID = static_cast(0); uint64_t monitoredSubject = static_cast(0); + ClientTypeEnum clientType = static_cast(0); chip::FabricIndex fabricIndex = static_cast(0); CHIP_ERROR Decode(TLV::TLVReader & reader); @@ -13198,6 +13200,7 @@ enum class Fields : uint8_t kMonitoredSubject = 1, kKey = 2, kVerificationKey = 3, + kClientType = 4, }; struct Type @@ -13211,6 +13214,7 @@ struct Type uint64_t monitoredSubject = static_cast(0); chip::ByteSpan key; Optional verificationKey; + ClientTypeEnum clientType = static_cast(0); CHIP_ERROR Encode(TLV::TLVWriter & aWriter, TLV::Tag aTag) const; @@ -13229,6 +13233,7 @@ struct DecodableType uint64_t monitoredSubject = static_cast(0); chip::ByteSpan key; Optional verificationKey; + ClientTypeEnum clientType = static_cast(0); CHIP_ERROR Decode(TLV::TLVReader & reader); }; }; // namespace RegisterClient diff --git a/zzz_generated/chip-tool/zap-generated/cluster/Commands.h b/zzz_generated/chip-tool/zap-generated/cluster/Commands.h index a9658c4a1ace4f..2cdd59a303bb63 100644 --- a/zzz_generated/chip-tool/zap-generated/cluster/Commands.h +++ b/zzz_generated/chip-tool/zap-generated/cluster/Commands.h @@ -4242,6 +4242,7 @@ class IcdManagementRegisterClient : public ClusterCommand AddArgument("MonitoredSubject", 0, UINT64_MAX, &mRequest.monitoredSubject); AddArgument("Key", &mRequest.key); AddArgument("VerificationKey", &mRequest.verificationKey); + AddArgument("ClientType", 0, UINT8_MAX, &mRequest.clientType); ClusterCommand::AddArguments(); } diff --git a/zzz_generated/chip-tool/zap-generated/cluster/ComplexArgumentParser.cpp b/zzz_generated/chip-tool/zap-generated/cluster/ComplexArgumentParser.cpp index 6c7da78177ff10..6a73b61ce13720 100644 --- a/zzz_generated/chip-tool/zap-generated/cluster/ComplexArgumentParser.cpp +++ b/zzz_generated/chip-tool/zap-generated/cluster/ComplexArgumentParser.cpp @@ -2066,6 +2066,8 @@ CHIP_ERROR ComplexArgumentParser::Setup(const char * label, value.isMember("checkInNodeID"))); ReturnErrorOnFailure(ComplexArgumentParser::EnsureMemberExist("MonitoringRegistrationStruct.monitoredSubject", "monitoredSubject", value.isMember("monitoredSubject"))); + ReturnErrorOnFailure(ComplexArgumentParser::EnsureMemberExist("MonitoringRegistrationStruct.clientType", "clientType", + value.isMember("clientType"))); char labelWithMember[kMaxLabelLength]; snprintf(labelWithMember, sizeof(labelWithMember), "%s.%s", label, "checkInNodeID"); @@ -2076,6 +2078,10 @@ CHIP_ERROR ComplexArgumentParser::Setup(const char * label, ReturnErrorOnFailure(ComplexArgumentParser::Setup(labelWithMember, request.monitoredSubject, value["monitoredSubject"])); valueCopy.removeMember("monitoredSubject"); + snprintf(labelWithMember, sizeof(labelWithMember), "%s.%s", label, "clientType"); + ReturnErrorOnFailure(ComplexArgumentParser::Setup(labelWithMember, request.clientType, value["clientType"])); + valueCopy.removeMember("clientType"); + if (value.isMember("fabricIndex")) { snprintf(labelWithMember, sizeof(labelWithMember), "%s.%s", label, "fabricIndex"); @@ -2090,6 +2096,7 @@ void ComplexArgumentParser::Finalize(chip::app::Clusters::IcdManagement::Structs { ComplexArgumentParser::Finalize(request.checkInNodeID); ComplexArgumentParser::Finalize(request.monitoredSubject); + ComplexArgumentParser::Finalize(request.clientType); ComplexArgumentParser::Finalize(request.fabricIndex); } 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 1f8be3d7029a79..a9d3f942abcd7c 100644 --- a/zzz_generated/chip-tool/zap-generated/cluster/logging/DataModelLogger.cpp +++ b/zzz_generated/chip-tool/zap-generated/cluster/logging/DataModelLogger.cpp @@ -1878,6 +1878,14 @@ DataModelLogger::LogValue(const char * label, size_t indent, return err; } } + { + CHIP_ERROR err = LogValue("ClientType", indent + 1, value.clientType); + if (err != CHIP_NO_ERROR) + { + DataModelLogger::LogString(indent + 1, "Struct truncated due to invalid value for 'ClientType'"); + return err; + } + } { CHIP_ERROR err = LogValue("FabricIndex", indent + 1, value.fabricIndex); if (err != CHIP_NO_ERROR) 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 2bea6e6b3fff8a..dfac8e499e1449 100644 --- a/zzz_generated/darwin-framework-tool/zap-generated/cluster/Commands.h +++ b/zzz_generated/darwin-framework-tool/zap-generated/cluster/Commands.h @@ -47524,6 +47524,9 @@ class IcdManagementRegisterClient : public ClusterCommand { #endif // MTR_ENABLE_PROVISIONAL #if MTR_ENABLE_PROVISIONAL AddArgument("VerificationKey", &mRequest.verificationKey); +#endif // MTR_ENABLE_PROVISIONAL +#if MTR_ENABLE_PROVISIONAL + AddArgument("ClientType", 0, UINT8_MAX, &mRequest.clientType); #endif // MTR_ENABLE_PROVISIONAL ClusterCommand::AddArguments(); } @@ -47554,6 +47557,9 @@ class IcdManagementRegisterClient : public ClusterCommand { } else { params.verificationKey = nil; } +#endif // MTR_ENABLE_PROVISIONAL +#if MTR_ENABLE_PROVISIONAL + params.clientType = [NSNumber numberWithUnsignedChar:chip::to_underlying(mRequest.clientType)]; #endif // MTR_ENABLE_PROVISIONAL uint16_t repeatCount = mRepeatCount.ValueOr(1); uint16_t __block responsesNeeded = repeatCount; From d033f8b917faa17b82a432e0c895f96199217dcb Mon Sep 17 00:00:00 2001 From: Rohit Jadhav <69809379+jadhavrohit924@users.noreply.github.com> Date: Mon, 1 Jul 2024 10:17:34 +0530 Subject: [PATCH 12/12] [ESP32] Remove SupportedModes implementation of ModeSelect from nvs and use all-clusters-apps common implementation (#34044) --- docs/guides/esp32/providers.md | 2 - .../esp32/main/CMakeLists.txt | 3 - examples/all-clusters-app/esp32/main/main.cpp | 8 - .../static-supported-modes-manager.cpp | 223 ------------------ .../static-supported-modes-manager.h | 80 ------- .../tools/generate_esp32_chip_factory_bin.py | 93 +------- 6 files changed, 2 insertions(+), 407 deletions(-) delete mode 100644 examples/platform/esp32/mode-support/static-supported-modes-manager.cpp delete mode 100644 examples/platform/esp32/mode-support/static-supported-modes-manager.h diff --git a/docs/guides/esp32/providers.md b/docs/guides/esp32/providers.md index 59b91b624a49fc..5174e1ccaceb11 100644 --- a/docs/guides/esp32/providers.md +++ b/docs/guides/esp32/providers.md @@ -15,8 +15,6 @@ Below are the providers that have been implemented: - [Device Info Provider](https://github.com/project-chip/connectedhomeip/blob/master/src/platform/ESP32/ESP32DeviceInfoProvider.h#L31) This provider provides fixed labels, supported calendar types, and supported locales from the factory partition. -- [Supported Modes](https://github.com/project-chip/connectedhomeip/blob/master/examples/platform/esp32/mode-support/static-supported-modes-manager.h#L28) - This provider offers the supported modes for the mode-select cluster. More information can be found in the [factory data guide](factory_data.md). diff --git a/examples/all-clusters-app/esp32/main/CMakeLists.txt b/examples/all-clusters-app/esp32/main/CMakeLists.txt index 7fd1d548609257..dc41290765313a 100644 --- a/examples/all-clusters-app/esp32/main/CMakeLists.txt +++ b/examples/all-clusters-app/esp32/main/CMakeLists.txt @@ -34,7 +34,6 @@ set(SRC_DIRS_LIST "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32/ota" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32/common" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32/shell_extension" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32/mode-support" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/server" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/icd/server" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/util" @@ -106,8 +105,6 @@ set(SRC_DIRS_LIST ) -set(EXCLUDE_SRCS "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/all-clusters-app/all-clusters-common/src/static-supported-modes-manager.cpp") - if (CONFIG_ENABLE_PW_RPC) # Append additional directories for RPC build set(PRIV_INCLUDE_DIRS_LIST "${PRIV_INCLUDE_DIRS_LIST}" diff --git a/examples/all-clusters-app/esp32/main/main.cpp b/examples/all-clusters-app/esp32/main/main.cpp index af94d2b2d36afe..b85f47d883c620 100644 --- a/examples/all-clusters-app/esp32/main/main.cpp +++ b/examples/all-clusters-app/esp32/main/main.cpp @@ -41,7 +41,6 @@ #include #include #include -#include #include #include @@ -122,13 +121,6 @@ static void InitServer(intptr_t context) #if CONFIG_DEVICE_TYPE_M5STACK SetupPretendDevices(); #endif - CHIP_ERROR err = - app::Clusters::ModeSelect::StaticSupportedModesManager::getStaticSupportedModesManagerInstance().InitEndpointArray( - FIXED_ENDPOINT_COUNT); - if (err != CHIP_NO_ERROR) - { - ESP_LOGE(TAG, "Failed to initialize endpoint array for supported-modes, err:%" CHIP_ERROR_FORMAT, err.Format()); - } app::Clusters::TemperatureControl::SetInstance(&sAppSupportedTemperatureLevelsDelegate); } diff --git a/examples/platform/esp32/mode-support/static-supported-modes-manager.cpp b/examples/platform/esp32/mode-support/static-supported-modes-manager.cpp deleted file mode 100644 index d06a8b8b7dc809..00000000000000 --- a/examples/platform/esp32/mode-support/static-supported-modes-manager.cpp +++ /dev/null @@ -1,223 +0,0 @@ -/* - * - * Copyright (c) 2023 Project CHIP Authors - * All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "static-supported-modes-manager.h" -#include - -using namespace chip; -using namespace chip::app::Clusters; -using namespace chip::DeviceLayer::Internal; -using namespace chip::app::Clusters::ModeSelect; -using chip::Protocols::InteractionModel::Status; - -using ModeOptionStructType = Structs::ModeOptionStruct::Type; -using SemanticTag = Structs::SemanticTagStruct::Type; - -template -using List = app::DataModel::List; - -SupportedModesManager::ModeOptionsProvider * StaticSupportedModesManager::epModeOptionsProviderList = nullptr; - -const StaticSupportedModesManager StaticSupportedModesManager::instance = StaticSupportedModesManager(); - -int StaticSupportedModesManager::mSize = 0; - -CHIP_ERROR StaticSupportedModesManager::InitEndpointArray(int size) -{ - if (epModeOptionsProviderList != nullptr) - { - ChipLogError(Zcl, "Cannot allocate epModeOptionsProviderList"); - return CHIP_ERROR_INCORRECT_STATE; - } - mSize = size; - epModeOptionsProviderList = new SupportedModesManager::ModeOptionsProvider[mSize]; - if (epModeOptionsProviderList == nullptr) - { - ChipLogError(Zcl, "Failed to allocate memory to epModeOptionsProviderList"); - return CHIP_ERROR_NO_MEMORY; - } - for (int i = 0; i < mSize; i++) - { - epModeOptionsProviderList[i] = ModeOptionsProvider(); - } - return CHIP_NO_ERROR; -} - -SupportedModesManager::ModeOptionsProvider StaticSupportedModesManager::getModeOptionsProvider(EndpointId endpointId) const -{ - if (epModeOptionsProviderList[endpointId].begin() != nullptr && epModeOptionsProviderList[endpointId].end() != nullptr) - { - return ModeOptionsProvider(epModeOptionsProviderList[endpointId].begin(), epModeOptionsProviderList[endpointId].end()); - } - - ModeOptionStructType * modeOptionStructList = nullptr; - SemanticTag * semanticTags = nullptr; - - char keyBuf[ESP32Config::kMaxConfigKeyNameLength]; - uint32_t supportedModeCount = 0; - - VerifyOrReturnValue(ESP32Config::KeyAllocator::SupportedModesCount(keyBuf, sizeof(keyBuf), endpointId) == CHIP_NO_ERROR, - ModeOptionsProvider(nullptr, nullptr)); - ESP32Config::Key countKey(ESP32Config::kConfigNamespace_ChipFactory, keyBuf); - VerifyOrReturnValue(ESP32Config::ReadConfigValue(countKey, supportedModeCount) == CHIP_NO_ERROR, - ModeOptionsProvider(nullptr, nullptr)); - - modeOptionStructList = new ModeOptionStructType[supportedModeCount]; - if (modeOptionStructList == nullptr) - { - return ModeOptionsProvider(nullptr, nullptr); - } - - epModeOptionsProviderList[endpointId] = ModeOptionsProvider(modeOptionStructList, modeOptionStructList + supportedModeCount); - - for (int index = 0; index < supportedModeCount; index++) - { - Structs::ModeOptionStruct::Type option; - uint32_t supportedModeMode = 0; - uint32_t semanticTagCount = 0; - size_t outLen = 0; - - memset(keyBuf, 0, sizeof(char) * ESP32Config::kMaxConfigKeyNameLength); - VerifyOrReturnValue(ESP32Config::KeyAllocator::SupportedModesLabel(keyBuf, sizeof(keyBuf), endpointId, index) == - CHIP_NO_ERROR, - ModeOptionsProvider(nullptr, nullptr), CleanUp(endpointId)); - ESP32Config::Key labelKey(ESP32Config::kConfigNamespace_ChipFactory, keyBuf); - VerifyOrReturnValue(ESP32Config::ReadConfigValueStr(labelKey, nullptr, 0, outLen) == CHIP_NO_ERROR, - ModeOptionsProvider(nullptr, nullptr), CleanUp(endpointId)); - - char * modeLabel = new char[outLen + 1]; - if (modeLabel == nullptr) - { - CleanUp(endpointId); - return ModeOptionsProvider(nullptr, nullptr); - } - - VerifyOrReturnValue(ESP32Config::ReadConfigValueStr(labelKey, modeLabel, outLen + 1, outLen) == CHIP_NO_ERROR, - ModeOptionsProvider(nullptr, nullptr), CleanUp(endpointId)); - - memset(keyBuf, 0, sizeof(char) * ESP32Config::kMaxConfigKeyNameLength); - VerifyOrReturnValue(ESP32Config::KeyAllocator::SupportedModesValue(keyBuf, sizeof(keyBuf), endpointId, index) == - CHIP_NO_ERROR, - ModeOptionsProvider(nullptr, nullptr), CleanUp(endpointId)); - ESP32Config::Key modeKey(ESP32Config::kConfigNamespace_ChipFactory, keyBuf); - VerifyOrReturnValue(ESP32Config::ReadConfigValue(labelKey, supportedModeMode) == CHIP_NO_ERROR, - ModeOptionsProvider(nullptr, nullptr), CleanUp(endpointId)); - - memset(keyBuf, 0, sizeof(char) * ESP32Config::kMaxConfigKeyNameLength); - VerifyOrReturnValue(ESP32Config::KeyAllocator::SemanticTagsCount(keyBuf, sizeof(keyBuf), endpointId, index) == - CHIP_NO_ERROR, - ModeOptionsProvider(nullptr, nullptr), CleanUp(endpointId)); - ESP32Config::Key stCountKey(ESP32Config::kConfigNamespace_ChipFactory, keyBuf); - VerifyOrReturnValue(ESP32Config::ReadConfigValue(stCountKey, semanticTagCount) == CHIP_NO_ERROR, - ModeOptionsProvider(nullptr, nullptr), CleanUp(endpointId)); - - semanticTags = new SemanticTag[semanticTagCount]; - if (semanticTags == nullptr) - { - CleanUp(endpointId); - return ModeOptionsProvider(nullptr, nullptr); - } - for (auto stIndex = 0; stIndex < semanticTagCount; stIndex++) - { - - uint32_t semanticTagValue = 0; - uint32_t semanticTagMfgCode = 0; - SemanticTag tag; - - memset(keyBuf, 0, sizeof(char) * ESP32Config::kMaxConfigKeyNameLength); - VerifyOrReturnValue(ESP32Config::KeyAllocator::SemanticTagValue(keyBuf, sizeof(keyBuf), endpointId, index, stIndex) == - CHIP_NO_ERROR, - ModeOptionsProvider(nullptr, nullptr), CleanUp(endpointId)); - ESP32Config::Key stValueKey(ESP32Config::kConfigNamespace_ChipFactory, keyBuf); - VerifyOrReturnValue(ESP32Config::ReadConfigValue(stValueKey, semanticTagValue) == CHIP_NO_ERROR, - ModeOptionsProvider(nullptr, nullptr), CleanUp(endpointId)); - - memset(keyBuf, 0, sizeof(char) * ESP32Config::kMaxConfigKeyNameLength); - VerifyOrReturnValue(ESP32Config::KeyAllocator::SemanticTagMfgCode(keyBuf, sizeof(keyBuf), endpointId, index, stIndex) == - CHIP_NO_ERROR, - ModeOptionsProvider(nullptr, nullptr), CleanUp(endpointId)); - ESP32Config::Key stMfgCodeKey(ESP32Config::kConfigNamespace_ChipFactory, keyBuf); - VerifyOrReturnValue(ESP32Config::ReadConfigValue(stMfgCodeKey, semanticTagMfgCode) == CHIP_NO_ERROR, - ModeOptionsProvider(nullptr, nullptr), CleanUp(endpointId)); - - tag.value = static_cast(semanticTagValue); - tag.mfgCode = static_cast(semanticTagMfgCode); - semanticTags[stIndex] = tag; - } - - option.label = chip::CharSpan::fromCharString(modeLabel); - option.mode = static_cast(supportedModeMode); - option.semanticTags = DataModel::List(semanticTags, semanticTagCount); - - modeOptionStructList[index] = option; - } - - return ModeOptionsProvider(modeOptionStructList, modeOptionStructList + supportedModeCount); -} - -Status StaticSupportedModesManager::getModeOptionByMode(unsigned short endpointId, unsigned char mode, - const ModeOptionStructType ** dataPtr) const -{ - auto modeOptionsProvider = this->getModeOptionsProvider(endpointId); - if (modeOptionsProvider.begin() == nullptr) - { - return Status::UnsupportedCluster; - } - auto * begin = modeOptionsProvider.begin(); - auto * end = modeOptionsProvider.end(); - - for (auto * it = begin; it != end; ++it) - { - auto & modeOption = *it; - if (modeOption.mode == mode) - { - *dataPtr = &modeOption; - return Status::Success; - } - } - ChipLogProgress(Zcl, "Cannot find the mode %u", mode); - return Status::InvalidCommand; -} - -const ModeSelect::SupportedModesManager * ModeSelect::getSupportedModesManager() -{ - return &StaticSupportedModesManager::getStaticSupportedModesManagerInstance(); -} - -void StaticSupportedModesManager::FreeSupportedModes(EndpointId endpointId) const -{ - if (epModeOptionsProviderList[endpointId].begin() != nullptr) - { - auto * begin = epModeOptionsProviderList[endpointId].begin(); - auto * end = epModeOptionsProviderList[endpointId].end(); - for (auto * it = begin; it != end; ++it) - { - auto & modeOption = *it; - delete[] modeOption.label.data(); - delete[] modeOption.semanticTags.data(); - } - delete[] begin; - } - epModeOptionsProviderList[endpointId] = ModeOptionsProvider(); -} - -void StaticSupportedModesManager::CleanUp(EndpointId endpointId) const -{ - ChipLogError(Zcl, "Supported mode data is in incorrect format"); - FreeSupportedModes(endpointId); -} diff --git a/examples/platform/esp32/mode-support/static-supported-modes-manager.h b/examples/platform/esp32/mode-support/static-supported-modes-manager.h deleted file mode 100644 index 8d6bb3c665ff0c..00000000000000 --- a/examples/platform/esp32/mode-support/static-supported-modes-manager.h +++ /dev/null @@ -1,80 +0,0 @@ -/* - * - * Copyright (c) 2023 Project CHIP Authors - * All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#pragma once - -#include - -namespace chip { -namespace app { -namespace Clusters { -namespace ModeSelect { - -class StaticSupportedModesManager : public chip::app::Clusters::ModeSelect::SupportedModesManager -{ -private: - using ModeOptionStructType = Structs::ModeOptionStruct::Type; - using SemanticTag = Structs::SemanticTagStruct::Type; - static int mSize; - - static ModeOptionsProvider * epModeOptionsProviderList; - - void FreeSupportedModes(EndpointId endpointId) const; - - static const StaticSupportedModesManager instance; - -public: - // InitEndpointArray should be called only once in the application. Memory allocated to the - // epModeOptionsProviderList will be needed for the lifetime of the program, so it's never deallocated. - static CHIP_ERROR InitEndpointArray(int size); - - // DeInitEndpointArray should be called only when application need to reallocate memory of - // epModeOptionsProviderList ( Eg. Bridges ). - static void DeInitEndpointArray() - { - delete[] epModeOptionsProviderList; - epModeOptionsProviderList = nullptr; - mSize = 0; - } - - SupportedModesManager::ModeOptionsProvider getModeOptionsProvider(EndpointId endpointId) const override; - - Protocols::InteractionModel::Status getModeOptionByMode(EndpointId endpointId, uint8_t mode, - const ModeOptionStructType ** dataPtr) const override; - - void CleanUp(EndpointId endpointId) const; - - StaticSupportedModesManager() {} - - ~StaticSupportedModesManager() - { - for (int i = 0; i < mSize; i++) - { - FreeSupportedModes(i); - } - } - - static inline const StaticSupportedModesManager & getStaticSupportedModesManagerInstance() { return instance; } -}; - -const SupportedModesManager * getSupportedModesManager(); - -} // namespace ModeSelect -} // namespace Clusters -} // namespace app -} // namespace chip diff --git a/scripts/tools/generate_esp32_chip_factory_bin.py b/scripts/tools/generate_esp32_chip_factory_bin.py index eab2ec6b43c229..b641ef05b6cd88 100755 --- a/scripts/tools/generate_esp32_chip_factory_bin.py +++ b/scripts/tools/generate_esp32_chip_factory_bin.py @@ -159,39 +159,6 @@ def ishex(s): except ValueError: return False -# get_supported_modes_dict() converts the list of strings to per endpoint dictionaries. -# example with semantic tags -# input : ['0/label1/1/"1\0x8000, 2\0x8000" 1/label2/1/"1\0x8000, 2\0x8000"'] -# output : {'1': [{'Label': 'label1', 'Mode': 0, 'Semantic_Tag': [{'value': 1, 'mfgCode': 32768}, {'value': 2, 'mfgCode': 32768}]}, {'Label': 'label2', 'Mode': 1, 'Semantic_Tag': [{'value': 1, 'mfgCode': 32768}, {'value': 2, 'mfgCode': 32768}]}]} - -# example without semantic tags -# input : ['0/label1/1 1/label2/1'] -# output : {'1': [{'Label': 'label1', 'Mode': 0, 'Semantic_Tag': []}, {'Label': 'label2', 'Mode': 1, 'Semantic_Tag': []}]} - - -def get_supported_modes_dict(supported_modes): - output_dict = {} - - for mode_str in supported_modes: - mode_label_strs = mode_str.split('/') - mode = mode_label_strs[0] - label = mode_label_strs[1] - ep = mode_label_strs[2] - - semantic_tags = '' - if (len(mode_label_strs) == 4): - semantic_tag_strs = mode_label_strs[3].split(', ') - semantic_tags = [{"value": int(v.split('\\')[0]), "mfgCode": int(v.split('\\')[1], 16)} for v in semantic_tag_strs] - - mode_dict = {"Label": label, "Mode": int(mode), "Semantic_Tag": semantic_tags} - - if ep in output_dict: - output_dict[ep].append(mode_dict) - else: - output_dict[ep] = [mode_dict] - - return output_dict - def check_str_range(s, min_len, max_len, name): if s and ((len(s) < min_len) or (len(s) > max_len)): @@ -302,60 +269,6 @@ def populate_factory_data(args, spake2p_params): if args.hw_ver_str: FACTORY_DATA['hw-ver-str']['value'] = args.hw_ver_str - # SupportedModes are stored as multiple entries - # - sm-sz/ : number of supported modes for the endpoint - # - sm-label// : supported modes label key for the endpoint and index - # - sm-mode// : supported modes mode key for the endpoint and index - # - sm-st-sz// : supported modes SemanticTag key for the endpoint and index - # - st-v/// : semantic tag value key for the endpoint and index and ind - # - st-mfg/// : semantic tag mfg code key for the endpoint and index and ind - if (args.supported_modes is not None): - dictionary = get_supported_modes_dict(args.supported_modes) - for ep in dictionary.keys(): - _sz = { - 'type': 'data', - 'encoding': 'u32', - 'value': len(dictionary[ep]) - } - FACTORY_DATA.update({'sm-sz/{:x}'.format(int(ep)): _sz}) - for i in range(len(dictionary[ep])): - item = dictionary[ep][i] - _label = { - 'type': 'data', - 'encoding': 'string', - 'value': item["Label"] - } - _mode = { - 'type': 'data', - 'encoding': 'u32', - 'value': item["Mode"] - } - _st_sz = { - 'type': 'data', - 'encoding': 'u32', - 'value': len(item["Semantic_Tag"]) - } - FACTORY_DATA.update({'sm-label/{:x}/{:x}'.format(int(ep), i): _label}) - FACTORY_DATA.update({'sm-mode/{:x}/{:x}'.format(int(ep), i): _mode}) - FACTORY_DATA.update({'sm-st-sz/{:x}/{:x}'.format(int(ep), i): _st_sz}) - - for j in range(len(item["Semantic_Tag"])): - entry = item["Semantic_Tag"][j] - - _value = { - 'type': 'data', - 'encoding': 'u32', - 'value': entry["value"] - } - _mfg_code = { - 'type': 'data', - 'encoding': 'u32', - 'value': entry["mfgCode"] - } - - FACTORY_DATA.update({'st-v/{:x}/{:x}/{:x}'.format(int(ep), i, j): _value}) - FACTORY_DATA.update({'st-mfg/{:x}/{:x}/{:x}'.format(int(ep), i, j): _mfg_code}) - def gen_raw_ec_keypair_from_der(key_file, pubkey_raw_file, privkey_raw_file): with open(key_file, 'rb') as f: @@ -468,9 +381,6 @@ def any_base_int(s): return int(s, 0) help=('128-bit unique identifier for generating rotating device identifier, ' 'provide 32-byte hex string, e.g. "1234567890abcdef1234567890abcdef"')) - parser.add_argument('--supported-modes', type=str, nargs='+', required=False, - help='List of supported modes, eg: mode1/label1/ep/"tagValue1\\mfgCode, tagValue2\\mfgCode" mode2/label2/ep/"tagValue1\\mfgCode, tagValue2\\mfgCode" mode3/label3/ep/"tagValue1\\mfgCode, tagValue2\\mfgCode"') - parser.add_argument('-s', '--size', type=any_base_int, default=0x6000, help='The size of the partition.bin, default: 0x6000') parser.add_argument('--target', default='esp32', @@ -509,7 +419,8 @@ def set_up_factory_data(args): def generate_factory_partiton_binary(args): generate_nvs_csv(args.output_dir, FACTORY_PARTITION_CSV) if args.generate_bin: - generate_nvs_bin(args.encrypt, args.size, FACTORY_PARTITION_CSV, FACTORY_PARTITION_BIN, args.output_dir) + csv_file = os.path.join(args.output_dir, FACTORY_PARTITION_CSV) + generate_nvs_bin(args.encrypt, args.size, csv_file, FACTORY_PARTITION_BIN, args.output_dir) print_flashing_help(args.encrypt, args.output_dir, FACTORY_PARTITION_BIN) clean_up()